mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-04 21:54:27 +08:00
* Add molecules names into ScaffoldNetwork - added parameter to ScaffoldNetwork Params to include molecule names in the ScaffoldNetwork nodes corresponding to input molecules * Document _Name assumption - fixed a binary and instead of a boolean and * Forgot has prop check before access * Misunderstood semantics of CHECK vs. REQUIRE
499 lines
19 KiB
C++
499 lines
19 KiB
C++
//
|
|
// Copyright (C) 2019 Greg Landrum and T5 Informatics GmbH
|
|
//
|
|
// @@ All Rights Reserved @@
|
|
// This file is part of the RDKit.
|
|
// The contents are covered by the terms of the BSD license
|
|
// which is included in the file license.txt, found at the root
|
|
// of the RDKit source tree.
|
|
//
|
|
#include "ScaffoldNetwork.h"
|
|
#include "detail.h"
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <RDGeneral/types.h>
|
|
#include <RDGeneral/Invariant.h>
|
|
#include <GraphMol/RDKitBase.h>
|
|
#include <GraphMol/ROMol.h>
|
|
#include <GraphMol/MolOps.h>
|
|
#include <GraphMol/ChemReactions/Reaction.h>
|
|
#include <GraphMol/ChemReactions/ReactionParser.h>
|
|
#include <GraphMol/SmilesParse/SmilesWrite.h>
|
|
#include <GraphMol/MolStandardize/Fragment.h>
|
|
#include <GraphMol/ChemTransforms/ChemTransforms.h>
|
|
#include <RDGeneral/Exceptions.h>
|
|
|
|
namespace RDKit {
|
|
namespace ScaffoldNetwork {
|
|
|
|
ScaffoldNetworkParams::ScaffoldNetworkParams(
|
|
const std::vector<std::string> &bondBreakersSmarts) {
|
|
bondBreakersRxns.clear();
|
|
bondBreakersRxns.reserve(bondBreakersSmarts.size());
|
|
for (auto sma : bondBreakersSmarts) {
|
|
std::shared_ptr<ChemicalReaction> rxn(RxnSmartsToChemicalReaction(sma));
|
|
if (rxn.get() == nullptr) {
|
|
throw ValueErrorException("could not parse reaction smarts: " + sma);
|
|
}
|
|
if (rxn->getNumReactantTemplates() != 1) {
|
|
throw ValueErrorException(
|
|
"bond breaker reactions must have exactly one reactant");
|
|
}
|
|
if (rxn->getNumProductTemplates() != 2) {
|
|
throw ValueErrorException(
|
|
"bond breaker reactions must have exactly two products");
|
|
}
|
|
rxn->initReactantMatchers();
|
|
bondBreakersRxns.emplace_back(rxn);
|
|
}
|
|
};
|
|
|
|
namespace detail {
|
|
|
|
void updateMolProps(RWMol &mol) { MolOps::sanitizeMol(mol); }
|
|
|
|
ROMol *makeScaffoldGeneric(const ROMol &mol, bool doAtoms, bool doBonds) {
|
|
RWMol *res = new RWMol(mol);
|
|
if (doAtoms) {
|
|
for (auto atom : res->atoms()) {
|
|
atom->setAtomicNum(0);
|
|
atom->setNumExplicitHs(0);
|
|
atom->setNoImplicit(false);
|
|
atom->setIsotope(0);
|
|
}
|
|
}
|
|
if (doBonds) {
|
|
for (auto bond : res->bonds()) {
|
|
bond->setBondType(Bond::SINGLE);
|
|
bond->getBeginAtom()->setIsAromatic(false);
|
|
bond->getEndAtom()->setIsAromatic(false);
|
|
}
|
|
}
|
|
return static_cast<ROMol *>(res);
|
|
}
|
|
ROMol *removeAttachmentPoints(const ROMol &mol, const ScaffoldNetworkParams &) {
|
|
RWMol *res = new RWMol(mol);
|
|
res->beginBatchEdit();
|
|
for (const auto atom : res->atoms()) {
|
|
if (!atom->getAtomicNum() && atom->getDegree() == 1) {
|
|
// if we're removing a neighbor from an aromatic heteroatom,
|
|
// don't forget to set the H count on that atom:
|
|
auto nbri = res->getAtomNeighbors(atom);
|
|
auto nbr = (*res)[*nbri.first];
|
|
if (nbr->getIsAromatic() && nbr->getAtomicNum() > 0 &&
|
|
nbr->getAtomicNum() != 6) {
|
|
nbr->setNoImplicit(true);
|
|
nbr->setNumExplicitHs(1);
|
|
}
|
|
res->removeAtom(atom);
|
|
}
|
|
}
|
|
res->commitBatchEdit();
|
|
return static_cast<ROMol *>(res);
|
|
}
|
|
ROMol *pruneMol(const ROMol &mol, const ScaffoldNetworkParams &) {
|
|
ROMol *res = MurckoDecompose(mol);
|
|
res->updatePropertyCache();
|
|
MolOps::fastFindRings(*res);
|
|
return res;
|
|
}
|
|
|
|
ROMol *flattenMol(const ROMol &mol, const ScaffoldNetworkParams ¶ms) {
|
|
RWMol *res;
|
|
if (params.flattenKeepLargest) {
|
|
MolStandardize::LargestFragmentChooser fragmenter;
|
|
res = static_cast<RWMol *>(fragmenter.choose(mol));
|
|
} else {
|
|
res = new RWMol(mol);
|
|
}
|
|
for (auto atom : res->atoms()) {
|
|
if (params.flattenIsotopes) {
|
|
atom->setIsotope(0);
|
|
}
|
|
if (params.flattenChirality) {
|
|
if (atom->getChiralTag() != Atom::CHI_UNSPECIFIED) {
|
|
atom->setChiralTag(Atom::CHI_UNSPECIFIED);
|
|
if (atom->getNoImplicit() &&
|
|
(atom->getAtomicNum() == 6 || atom->getAtomicNum() == 7 ||
|
|
atom->getAtomicNum() == 15 || atom->getAtomicNum() == 16)) {
|
|
atom->setNoImplicit(false);
|
|
atom->setNumExplicitHs(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (params.flattenChirality) {
|
|
for (auto bond : res->bonds()) {
|
|
bond->setBondDir(Bond::NONE);
|
|
bond->setStereo(Bond::STEREONONE);
|
|
}
|
|
}
|
|
return static_cast<ROMol *>(res);
|
|
}
|
|
std::vector<std::pair<std::string, ROMOL_SPTR>> getMolFragments(
|
|
const ROMol &mol, const ScaffoldNetworkParams ¶ms) {
|
|
std::vector<std::pair<std::string, ROMOL_SPTR>> res;
|
|
std::deque<ROMOL_SPTR> stack;
|
|
stack.push_back(ROMOL_SPTR(new ROMol(mol)));
|
|
std::vector<std::string> seen;
|
|
while (!stack.empty()) {
|
|
auto wmol = stack.front();
|
|
stack.pop_front();
|
|
auto parentSmi = MolToSmiles(*wmol);
|
|
for (auto rxn : params.bondBreakersRxns) {
|
|
auto ps = rxn->runReactant(wmol, 0);
|
|
for (auto p : ps) {
|
|
if (!params.includeScaffoldsWithAttachments) {
|
|
// we're only including scaffolds without attachments, so
|
|
// go ahead and remove attachment points here
|
|
p[0].reset(removeAttachmentPoints(*p[0], params));
|
|
}
|
|
|
|
updateMolProps(*static_cast<RWMol *>(p[0].get()));
|
|
auto tsmi0 = MolToSmiles(*p[0]);
|
|
if (std::find(seen.begin(), seen.end(), tsmi0) == seen.end()) {
|
|
stack.push_back(p[0]);
|
|
seen.push_back(tsmi0);
|
|
}
|
|
res.push_back(std::make_pair(parentSmi, p[0]));
|
|
if (!params.keepOnlyFirstFragment) {
|
|
if (!params.includeScaffoldsWithAttachments) {
|
|
// we're only including scaffolds without attachments, so
|
|
// go ahead and remove attachment points here
|
|
p[1].reset(removeAttachmentPoints(*p[1], params));
|
|
}
|
|
updateMolProps(*static_cast<RWMol *>(p[1].get()));
|
|
auto tsmi1 = MolToSmiles(*p[1]);
|
|
if (std::find(seen.begin(), seen.end(), tsmi1) == seen.end()) {
|
|
stack.push_back(p[1]);
|
|
seen.push_back(tsmi1);
|
|
}
|
|
res.push_back(std::make_pair(parentSmi, p[1]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
namespace {
|
|
template <typename T, typename V>
|
|
size_t addEntryIfMissing(T &vect, const V &e,
|
|
std::vector<unsigned> *counts = nullptr) {
|
|
auto viter = std::find(vect.begin(), vect.end(), e);
|
|
size_t res;
|
|
if (viter == vect.end()) {
|
|
vect.push_back(e);
|
|
res = vect.size() - 1;
|
|
if (counts) {
|
|
counts->push_back(0);
|
|
}
|
|
} else {
|
|
res = viter - vect.begin();
|
|
}
|
|
if (counts) {
|
|
(*counts)[res] += 1;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
} // namespace
|
|
void addMolToNetwork(const ROMol &mol, ScaffoldNetwork &network,
|
|
const ScaffoldNetworkParams ¶ms) {
|
|
auto ismi = MolToSmiles(mol);
|
|
if (params.includeNames && mol.hasProp("_Name")) {
|
|
ismi += ' ' + mol.getProp<std::string>("_Name");
|
|
}
|
|
boost::shared_ptr<ROMol> fmol(flattenMol(mol, params));
|
|
if (params.pruneBeforeFragmenting) {
|
|
boost::shared_ptr<ROMol> pmol(pruneMol(*fmol, params));
|
|
fmol.swap(pmol);
|
|
}
|
|
std::set<size_t> entriesFromMol;
|
|
auto fsmi = MolToSmiles(*fmol);
|
|
if (ismi != fsmi) {
|
|
auto iidx = addEntryIfMissing(network.nodes, ismi, &network.counts);
|
|
auto fidx = addEntryIfMissing(network.nodes, fsmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(iidx);
|
|
entriesFromMol.insert(fidx);
|
|
}
|
|
|
|
addEntryIfMissing(network.edges,
|
|
NetworkEdge({iidx, fidx, EdgeType::Initialize}));
|
|
|
|
if (params.includeGenericScaffolds) {
|
|
bool doAtoms = true;
|
|
bool doBonds = false;
|
|
std::unique_ptr<ROMol> gmol(makeScaffoldGeneric(*fmol, doAtoms, doBonds));
|
|
auto gsmi = MolToSmiles(*gmol);
|
|
auto gidx = addEntryIfMissing(network.nodes, gsmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(gidx);
|
|
}
|
|
addEntryIfMissing(network.edges,
|
|
NetworkEdge({fidx, gidx, EdgeType::Generic}));
|
|
if (params.includeGenericBondScaffolds) {
|
|
bool doAtoms = true;
|
|
bool doBonds = true;
|
|
std::unique_ptr<ROMol> gbmol(
|
|
makeScaffoldGeneric(*fmol, doAtoms, doBonds));
|
|
auto gbsmi = MolToSmiles(*gbmol);
|
|
auto gbidx = addEntryIfMissing(network.nodes, gbsmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(gbidx);
|
|
}
|
|
if (gidx != gbidx) {
|
|
addEntryIfMissing(network.edges,
|
|
NetworkEdge({gidx, gbidx, EdgeType::GenericBond}));
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// add the base molecule to the network
|
|
auto midx = addEntryIfMissing(network.nodes, fsmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(midx);
|
|
}
|
|
}
|
|
|
|
auto frags = getMolFragments(*fmol, params);
|
|
for (auto frag : frags) {
|
|
auto smi = frag.first;
|
|
ROMOL_SPTR fragMol = frag.second;
|
|
|
|
// the first node is certain to already be in the network, so don't
|
|
// update counts for it
|
|
auto iidx = addEntryIfMissing(network.nodes, smi);
|
|
auto lsmi = MolToSmiles(*fragMol);
|
|
auto lidx = addEntryIfMissing(network.nodes, lsmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(lidx);
|
|
}
|
|
|
|
addEntryIfMissing(network.edges,
|
|
NetworkEdge({iidx, lidx, EdgeType::Fragment}));
|
|
|
|
if (params.includeGenericScaffolds) {
|
|
bool doAtoms = true;
|
|
bool doBonds = false;
|
|
std::unique_ptr<ROMol> gmol(
|
|
makeScaffoldGeneric(*fragMol, doAtoms, doBonds));
|
|
auto gsmi = MolToSmiles(*gmol);
|
|
auto gidx = addEntryIfMissing(network.nodes, gsmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(gidx);
|
|
}
|
|
|
|
addEntryIfMissing(network.edges,
|
|
NetworkEdge({lidx, gidx, EdgeType::Generic}));
|
|
if (params.includeGenericBondScaffolds) {
|
|
bool doAtoms = true;
|
|
bool doBonds = true;
|
|
std::unique_ptr<ROMol> gbmol(
|
|
makeScaffoldGeneric(*fragMol, doAtoms, doBonds));
|
|
auto gbsmi = MolToSmiles(*gbmol);
|
|
auto gbidx = addEntryIfMissing(network.nodes, gbsmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(gbidx);
|
|
}
|
|
|
|
if (gidx != gbidx) {
|
|
addEntryIfMissing(network.edges,
|
|
NetworkEdge({gidx, gbidx, EdgeType::GenericBond}));
|
|
}
|
|
}
|
|
}
|
|
if (params.includeScaffoldsWithAttachments &&
|
|
params.includeScaffoldsWithoutAttachments) {
|
|
// we're including both scaffolds without attachments and those with.
|
|
// do the one without now.
|
|
std::unique_ptr<ROMol> amol(removeAttachmentPoints(*fragMol, params));
|
|
auto asmi = MolToSmiles(*amol);
|
|
auto aidx = addEntryIfMissing(network.nodes, asmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(aidx);
|
|
}
|
|
|
|
addEntryIfMissing(network.edges,
|
|
NetworkEdge({lidx, aidx, EdgeType::RemoveAttachment}));
|
|
if (params.includeGenericScaffolds) {
|
|
bool doAtoms = true;
|
|
bool doBonds = false;
|
|
std::unique_ptr<ROMol> gmol(
|
|
makeScaffoldGeneric(*amol, doAtoms, doBonds));
|
|
auto gsmi = MolToSmiles(*gmol);
|
|
auto gidx = addEntryIfMissing(network.nodes, gsmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(gidx);
|
|
}
|
|
|
|
addEntryIfMissing(network.edges,
|
|
NetworkEdge({aidx, gidx, EdgeType::Generic}));
|
|
if (params.includeGenericBondScaffolds) {
|
|
bool doAtoms = true;
|
|
bool doBonds = true;
|
|
std::unique_ptr<ROMol> gbmol(
|
|
makeScaffoldGeneric(*amol, doAtoms, doBonds));
|
|
auto gbsmi = MolToSmiles(*gbmol);
|
|
auto gbidx = addEntryIfMissing(network.nodes, gbsmi, &network.counts);
|
|
if (params.collectMolCounts) {
|
|
entriesFromMol.insert(gbidx);
|
|
}
|
|
|
|
if (gidx != gbidx) {
|
|
addEntryIfMissing(
|
|
network.edges,
|
|
NetworkEdge({gidx, gbidx, EdgeType::GenericBond}));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (params.collectMolCounts) { // update the molCounts, entriesPerMol has
|
|
// all the entries we just touched
|
|
auto maxVal = *entriesFromMol.rbegin();
|
|
if (network.molCounts.size() <= maxVal) {
|
|
network.molCounts.resize(maxVal + 1, 0u);
|
|
}
|
|
for (auto idx : entriesFromMol) {
|
|
network.molCounts[idx]++;
|
|
}
|
|
}
|
|
}
|
|
} // namespace detail
|
|
|
|
template <typename T>
|
|
void updateScaffoldNetwork(const T &mols, ScaffoldNetwork &network,
|
|
const ScaffoldNetworkParams ¶ms) {
|
|
if (!params.includeScaffoldsWithAttachments &&
|
|
!params.includeScaffoldsWithoutAttachments) {
|
|
throw ValueErrorException(
|
|
"must include at least one of scaffolds with attachments or scaffolds "
|
|
"without attachments");
|
|
}
|
|
for (const auto &mol : mols) {
|
|
if (!mol) {
|
|
throw ValueErrorException(
|
|
"updateScaffoldNetwork called with null molecule");
|
|
}
|
|
detail::addMolToNetwork(*mol, network, params);
|
|
}
|
|
}
|
|
|
|
template RDKIT_SCAFFOLDNETWORK_EXPORT void updateScaffoldNetwork(
|
|
const std::vector<ROMOL_SPTR> &ms, ScaffoldNetwork &network,
|
|
const ScaffoldNetworkParams ¶ms);
|
|
template RDKIT_SCAFFOLDNETWORK_EXPORT ScaffoldNetwork createScaffoldNetwork(
|
|
const std::vector<ROMOL_SPTR> &ms, const ScaffoldNetworkParams ¶ms);
|
|
template RDKIT_SCAFFOLDNETWORK_EXPORT void updateScaffoldNetwork(
|
|
const std::vector<std::shared_ptr<ROMol>> &ms, ScaffoldNetwork &network,
|
|
const ScaffoldNetworkParams ¶ms);
|
|
template RDKIT_SCAFFOLDNETWORK_EXPORT ScaffoldNetwork
|
|
createScaffoldNetwork(const std::vector<std::shared_ptr<ROMol>> &ms,
|
|
const ScaffoldNetworkParams ¶ms);
|
|
|
|
const std::vector<std::string> BRICSDefinitions = {
|
|
"[$([C;D3]([#0,#6,#7,#8])(=O)):1]-;!@[$([O;D2]-;!@[#0,#6,#1]):2]>>[1*]-[*"
|
|
":1].[3*]-[*:2]",
|
|
"[$([C;D3]([#0,#6,#7,#8])(=O)):1]-;!@[$([N;!D1;!$(N=*);!$(N-[!#6;!#16;!#"
|
|
"0;!#1]);!$([N;R]@[C;R]=O)]):2]>>[1*]-[*:1].[5*]-[*:2]",
|
|
"[$([C;D3]([#0,#6,#7,#8])(=O)):1]-;!@[$([N;R;$(N(@C(=O))@[C,N,O,S])]):2]>"
|
|
">[1*]-[*:1].[10*]-[*:2]",
|
|
"[$([O;D2]-;!@[#0,#6,#1]):1]-;!@[$([C;!D1;!$(C=*)]-;!@[#6]):2]>>[3*]-[*:"
|
|
"1].[4*]-[*:2]",
|
|
"[$([O;D2]-;!@[#0,#6,#1]):1]-;!@[$([C;$(C(-;@[C,N,O,S])-;@[N,O,S])]):2]>>"
|
|
"[3*]-[*:1].[13*]-[*:2]",
|
|
"[$([O;D2]-;!@[#0,#6,#1]):1]-;!@[$([c;$(c(:[c,n,o,s]):[n,o,s])]):2]>>[3*]"
|
|
"-[*:1].[14*]-[*:2]",
|
|
"[$([O;D2]-;!@[#0,#6,#1]):1]-;!@[$([C;$(C(-;@C)-;@C)]):2]>>[3*]-[*:1].["
|
|
"15*]-[*:2]",
|
|
"[$([O;D2]-;!@[#0,#6,#1]):1]-;!@[$([c;$(c(:c):c)]):2]>>[3*]-[*:1].[16*]-["
|
|
"*:2]",
|
|
"[$([C;!D1;!$(C=*)]-;!@[#6]):1]-;!@[$([N;!D1;!$(N=*);!$(N-[!#6;!#16;!#0;!"
|
|
"#1]);!$([N;R]@[C;R]=O)]):2]>>[4*]-[*:1].[5*]-[*:2]",
|
|
"[$([C;!D1;!$(C=*)]-;!@[#6]):1]-;!@[$([S;D2](-;!@[#0,#6])):2]>>[4*]-[*:1]"
|
|
".[11*]-[*:2]",
|
|
"[$([N;!D1;!$(N=*);!$(N-[!#6;!#16;!#0;!#1]);!$([N;R]@[C;R]=O)]):1]-;!@[$("
|
|
"[S;D4]([#6,#0])(=O)(=O)):2]>>[5*]-[*:1].[12*]-[*:2]",
|
|
"[$([N;!D1;!$(N=*);!$(N-[!#6;!#16;!#0;!#1]);!$([N;R]@[C;R]=O)]):1]-;!@[$("
|
|
"[c;$(c(:[c,n,o,s]):[n,o,s])]):2]>>[5*]-[*:1].[14*]-[*:2]",
|
|
"[$([N;!D1;!$(N=*);!$(N-[!#6;!#16;!#0;!#1]);!$([N;R]@[C;R]=O)]):1]-;!@[$("
|
|
"[c;$(c(:c):c)]):2]>>[5*]-[*:1].[16*]-[*:2]",
|
|
"[$([N;!D1;!$(N=*);!$(N-[!#6;!#16;!#0;!#1]);!$([N;R]@[C;R]=O)]):1]-;!@[$("
|
|
"[C;$(C(-;@[C,N,O,S])-;@[N,O,S])]):2]>>[5*]-[*:1].[13*]-[*:2]",
|
|
"[$([N;!D1;!$(N=*);!$(N-[!#6;!#16;!#0;!#1]);!$([N;R]@[C;R]=O)]):1]-;!@[$("
|
|
"[C;$(C(-;@C)-;@C)]):2]>>[5*]-[*:1].[15*]-[*:2]",
|
|
"[$([C;D3;!R](=O)-;!@[#0,#6,#7,#8]):1]-;!@[$([C;$(C(-;@[C,N,O,S])-;@[N,O,"
|
|
"S])]):2]>>[6*]-[*:1].[13*]-[*:2]",
|
|
"[$([C;D3;!R](=O)-;!@[#0,#6,#7,#8]):1]-;!@[$([c;$(c(:[c,n,o,s]):[n,o,s])]"
|
|
"):2]>>[6*]-[*:1].[14*]-[*:2]",
|
|
"[$([C;D3;!R](=O)-;!@[#0,#6,#7,#8]):1]-;!@[$([C;$(C(-;@C)-;@C)]):2]>>[6*]"
|
|
"-[*:1].[15*]-[*:2]",
|
|
"[$([C;D3;!R](=O)-;!@[#0,#6,#7,#8]):1]-;!@[$([c;$(c(:c):c)]):2]>>[6*]-[*:"
|
|
"1].[16*]-[*:2]",
|
|
"[$([C;D2,D3]-[#6]):1]=;!@[$([C;D2,D3]-[#6]):2]>>[7*]-[*:1].[7*]-[*:2]",
|
|
"[$([C;!R;!D1;!$(C!-*)]):1]-;!@[$([n;+0;$(n(:[c,n,o,s]):[c,n,o,s])]):2]>>"
|
|
"[8*]-[*:1].[9*]-[*:2]",
|
|
"[$([C;!R;!D1;!$(C!-*)]):1]-;!@[$([N;R;$(N(@C(=O))@[C,N,O,S])]):2]>>[8*]-"
|
|
"[*:1].[10*]-[*:2]",
|
|
"[$([C;!R;!D1;!$(C!-*)]):1]-;!@[$([C;$(C(-;@[C,N,O,S])-;@[N,O,S])]):2]>>["
|
|
"8*]-[*:1].[13*]-[*:2]",
|
|
"[$([C;!R;!D1;!$(C!-*)]):1]-;!@[$([c;$(c(:[c,n,o,s]):[n,o,s])]):2]>>[8*]-"
|
|
"[*:1].[14*]-[*:2]",
|
|
"[$([C;!R;!D1;!$(C!-*)]):1]-;!@[$([C;$(C(-;@C)-;@C)]):2]>>[8*]-[*:1].[15*"
|
|
"]-[*:2]",
|
|
"[$([C;!R;!D1;!$(C!-*)]):1]-;!@[$([c;$(c(:c):c)]):2]>>[8*]-[*:1].[16*]-[*"
|
|
":2]",
|
|
"[$([n;+0;$(n(:[c,n,o,s]):[c,n,o,s])]):1]-;!@[$([C;$(C(-;@[C,N,O,S])-;@["
|
|
"N,O,S])]):2]>>[9*]-[*:1].[13*]-[*:2]",
|
|
"[$([n;+0;$(n(:[c,n,o,s]):[c,n,o,s])]):1]-;!@[$([c;$(c(:[c,n,o,s]):[n,o,"
|
|
"s])]):2]>>[9*]-[*:1].[14*]-[*:2]",
|
|
"[$([n;+0;$(n(:[c,n,o,s]):[c,n,o,s])]):1]-;!@[$([C;$(C(-;@C)-;@C)]):2]>>["
|
|
"9*]-[*:1].[15*]-[*:2]",
|
|
"[$([n;+0;$(n(:[c,n,o,s]):[c,n,o,s])]):1]-;!@[$([c;$(c(:c):c)]):2]>>[9*]-"
|
|
"[*:1].[16*]-[*:2]",
|
|
"[$([N;R;$(N(@C(=O))@[C,N,O,S])]):1]-;!@[$([C;$(C(-;@[C,N,O,S])-;@[N,O,S]"
|
|
")]):2]>>[10*]-[*:1].[13*]-[*:2]",
|
|
"[$([N;R;$(N(@C(=O))@[C,N,O,S])]):1]-;!@[$([c;$(c(:[c,n,o,s]):[n,o,s])]):"
|
|
"2]>>[10*]-[*:1].[14*]-[*:2]",
|
|
"[$([N;R;$(N(@C(=O))@[C,N,O,S])]):1]-;!@[$([C;$(C(-;@C)-;@C)]):2]>>[10*]-"
|
|
"[*:1].[15*]-[*:2]",
|
|
"[$([N;R;$(N(@C(=O))@[C,N,O,S])]):1]-;!@[$([c;$(c(:c):c)]):2]>>[10*]-[*:"
|
|
"1].[16*]-[*:2]",
|
|
"[$([S;D2](-;!@[#0,#6])):1]-;!@[$([C;$(C(-;@[C,N,O,S])-;@[N,O,S])]):2]>>["
|
|
"11*]-[*:1].[13*]-[*:2]",
|
|
"[$([S;D2](-;!@[#0,#6])):1]-;!@[$([c;$(c(:[c,n,o,s]):[n,o,s])]):2]>>[11*]"
|
|
"-[*:1].[14*]-[*:2]",
|
|
"[$([S;D2](-;!@[#0,#6])):1]-;!@[$([C;$(C(-;@C)-;@C)]):2]>>[11*]-[*:1].["
|
|
"15*]-[*:2]",
|
|
"[$([S;D2](-;!@[#0,#6])):1]-;!@[$([c;$(c(:c):c)]):2]>>[11*]-[*:1].[16*]-["
|
|
"*:2]",
|
|
"[$([C;$(C(-;@[C,N,O,S])-;@[N,O,S])]):1]-;!@[$([c;$(c(:[c,n,o,s]):[n,o,s]"
|
|
")]):2]>>[13*]-[*:1].[14*]-[*:2]",
|
|
"[$([C;$(C(-;@[C,N,O,S])-;@[N,O,S])]):1]-;!@[$([C;$(C(-;@C)-;@C)]):2]>>["
|
|
"13*]-[*:1].[15*]-[*:2]",
|
|
"[$([C;$(C(-;@[C,N,O,S])-;@[N,O,S])]):1]-;!@[$([c;$(c(:c):c)]):2]>>[13*]-"
|
|
"[*:1].[16*]-[*:2]",
|
|
"[$([c;$(c(:[c,n,o,s]):[n,o,s])]):1]-;!@[$([c;$(c(:[c,n,o,s]):[n,o,s])]):"
|
|
"2]>>[14*]-[*:1].[14*]-[*:2]",
|
|
"[$([c;$(c(:[c,n,o,s]):[n,o,s])]):1]-;!@[$([C;$(C(-;@C)-;@C)]):2]>>[14*]-"
|
|
"[*:1].[15*]-[*:2]",
|
|
"[$([c;$(c(:[c,n,o,s]):[n,o,s])]):1]-;!@[$([c;$(c(:c):c)]):2]>>[14*]-[*:"
|
|
"1].[16*]-[*:2]",
|
|
"[$([C;$(C(-;@C)-;@C)]):1]-;!@[$([c;$(c(:c):c)]):2]>>[15*]-[*:1].[16*]-[*"
|
|
":2]",
|
|
"[$([c;$(c(:c):c)]):1]-;!@[$([c;$(c(:c):c)]):2]>>[16*]-[*:1].[16*]-[*:"
|
|
"2]"};
|
|
|
|
ScaffoldNetworkParams getBRICSNetworkParams() {
|
|
ScaffoldNetworkParams res{BRICSDefinitions};
|
|
res.keepOnlyFirstFragment = false;
|
|
return res;
|
|
};
|
|
|
|
// const ScaffoldNetworkParams BRICSNetworkParams;
|
|
|
|
} // namespace ScaffoldNetwork
|
|
} // namespace RDKit
|