mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-03 21:44:30 +08:00
Add cxsmiles query atoms to CTAB parsers and writers (#3261)
* allow CXSMILES generic query atoms to be parsed from mol; need more tests here * remove vestigial directory * Add d_queryType to Query This opens up additional flexibility with customizing the way queries are handled Also includes some assorted cleanups in the Query directory * remove the MolFileSymbol hack added in #3235 We don't need it anymore * Add support for additional ChemAxon extensions and document them Signed-off-by: greg landrum <greg.landrum@gmail.com> * bump pickle version * add an additional test
This commit is contained in:
@@ -186,15 +186,12 @@ void setMDLAromaticity(RWMol &mol) {
|
||||
for (size_t i = 0; i < ring.size(); ++i) {
|
||||
auto ai = ring[i];
|
||||
const auto atom = mol.getAtomWithIdx(ai);
|
||||
std::string molfileSymbol;
|
||||
if (!atom->getIsAromatic()) {
|
||||
// we only do fully aromatic rings:
|
||||
keepIt = false;
|
||||
break;
|
||||
} else if (atom->getAtomicNum() == 0 &&
|
||||
atom->getPropIfPresent(common_properties::_MolFileSymbol,
|
||||
molfileSymbol) &&
|
||||
molfileSymbol == "A") {
|
||||
} else if (atom->getAtomicNum() == 0 && atom->hasQuery() &&
|
||||
atom->getQuery()->getTypeLabel() == "A") {
|
||||
if (dummy >= ring.size()) {
|
||||
dummy = i;
|
||||
} else {
|
||||
|
||||
@@ -693,7 +693,7 @@ void addRecursiveQueries(
|
||||
break;
|
||||
}
|
||||
auto *tqp = new RecursiveStructureQuery(new ROMol(*(iter->second)));
|
||||
boost::shared_ptr<RecursiveStructureQuery> nq(tqp);
|
||||
std::shared_ptr<RecursiveStructureQuery> nq(tqp);
|
||||
qToAdd->addChild(nq);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1260,6 +1260,34 @@ void ParseAtomValue(RWMol *mol, std::string text, unsigned int line) {
|
||||
text.substr(7, text.length() - 7));
|
||||
}
|
||||
|
||||
// We support the same special atom queries that we can read from
|
||||
// CXSMILES
|
||||
const std::vector<std::string> complexQueries = {"A", "AH", "Q", "QH",
|
||||
"X", "XH", "M", "MH"};
|
||||
void convertComplexNameToQuery(Atom *query, const std::string &symb) {
|
||||
if (symb == "Q") {
|
||||
query->setQuery(makeQAtomQuery());
|
||||
} else if (symb == "QH") {
|
||||
query->setQuery(makeQHAtomQuery());
|
||||
} else if (symb == "A") {
|
||||
query->setQuery(makeAAtomQuery());
|
||||
} else if (symb == "AH") {
|
||||
query->setQuery(makeAHAtomQuery());
|
||||
} else if (symb == "X") {
|
||||
query->setQuery(makeXAtomQuery());
|
||||
} else if (symb == "XH") {
|
||||
query->setQuery(makeXHAtomQuery());
|
||||
} else if (symb == "M") {
|
||||
query->setQuery(makeMAtomQuery());
|
||||
} else if (symb == "MH") {
|
||||
query->setQuery(makeMHAtomQuery());
|
||||
} else {
|
||||
// we control what this function gets called with, so we should never land
|
||||
// here
|
||||
ASSERT_INVARIANT(0, "bad complex query symbol");
|
||||
}
|
||||
}
|
||||
|
||||
Atom *ParseMolFileAtomLine(const std::string text, RDGeom::Point3D &pos,
|
||||
unsigned int line) {
|
||||
std::string symb;
|
||||
@@ -1318,18 +1346,19 @@ Atom *ParseMolFileAtomLine(const std::string text, RDGeom::Point3D &pos,
|
||||
}
|
||||
}
|
||||
auto *res = new Atom;
|
||||
if (symb == "L" || symb == "A" || symb == "Q" || symb == "*" ||
|
||||
symb == "LP" || symb == "R" || symb == "R#" ||
|
||||
bool isComplexQueryName =
|
||||
std::find(complexQueries.begin(), complexQueries.end(), symb) !=
|
||||
complexQueries.end();
|
||||
if (isComplexQueryName || symb == "L" || symb == "*" || symb == "LP" ||
|
||||
symb == "R" || symb == "R#" ||
|
||||
(symb[0] == 'R' && symb >= "R0" && symb <= "R99")) {
|
||||
if (symb == "A" || symb == "Q" || symb == "*" || symb == "R") {
|
||||
if (isComplexQueryName || symb == "*" || symb == "R") {
|
||||
auto *query = new QueryAtom(0);
|
||||
if (symb == "*" || symb == "R") {
|
||||
// according to the MDL spec, these match anything
|
||||
query->setQuery(makeAtomNullQuery());
|
||||
} else if (symb == "Q") {
|
||||
query->setQuery(makeQAtomQuery());
|
||||
} else if (symb == "A") {
|
||||
query->setQuery(makeAAtomQuery());
|
||||
} else if (isComplexQueryName) {
|
||||
convertComplexNameToQuery(query, symb);
|
||||
}
|
||||
delete res;
|
||||
res = query;
|
||||
@@ -1338,8 +1367,6 @@ Atom *ParseMolFileAtomLine(const std::string text, RDGeom::Point3D &pos,
|
||||
} else {
|
||||
res->setAtomicNum(0);
|
||||
}
|
||||
// save the symbol:
|
||||
res->setProp(common_properties::_MolFileSymbol, symb);
|
||||
if (massDiff == 0 && symb[0] == 'R') {
|
||||
if (symb.length() > 1) {
|
||||
std::string rlabel = "";
|
||||
@@ -1951,17 +1978,19 @@ Atom *ParseV3000AtomSymbol(std::string token, unsigned int &line) {
|
||||
// it's a normal CTAB atom symbol:
|
||||
// NOTE: "R" and "R0"-"R99" are not in the v3K CTAB spec, but we're going to
|
||||
// support them anyway
|
||||
if (token == "R" || (token[0] == 'R' && token >= "R0" && token <= "R99") ||
|
||||
token == "R#" || token == "A" || token == "Q" || token == "*") {
|
||||
if (token == "A" || token == "Q" || token == "*") {
|
||||
bool isComplexQueryName =
|
||||
std::find(complexQueries.begin(), complexQueries.end(), token) !=
|
||||
complexQueries.end();
|
||||
if (isComplexQueryName || token == "R" ||
|
||||
(token[0] == 'R' && token >= "R0" && token <= "R99") || token == "R#" ||
|
||||
token == "*") {
|
||||
if (isComplexQueryName || token == "*") {
|
||||
res = new QueryAtom(0);
|
||||
if (token == "*") {
|
||||
// according to the MDL spec, these match anything
|
||||
res->setQuery(makeAtomNullQuery());
|
||||
} else if (token == "Q") {
|
||||
res->setQuery(makeQAtomQuery());
|
||||
} else if (token == "A") {
|
||||
res->setQuery(makeAAtomQuery());
|
||||
} else if (isComplexQueryName) {
|
||||
convertComplexNameToQuery(res, token);
|
||||
}
|
||||
// queries have no implicit Hs:
|
||||
res->setNoImplicit(true);
|
||||
@@ -1982,8 +2011,6 @@ Atom *ParseV3000AtomSymbol(std::string token, unsigned int &line) {
|
||||
res->setIsotope(rnumber);
|
||||
}
|
||||
}
|
||||
res->setProp(common_properties::_MolFileSymbol, token);
|
||||
|
||||
} else if (token == "D") { // mol blocks support "D" and "T" as
|
||||
// shorthand... handle that.
|
||||
res = new Atom(1);
|
||||
|
||||
@@ -286,7 +286,8 @@ const std::string GetMolFileQueryInfo(
|
||||
}
|
||||
for (const auto atom : mol.atoms()) {
|
||||
bool wrote_query = false;
|
||||
if (!listQs[atom->getIdx()] && hasComplexQuery(atom)) {
|
||||
if (!listQs[atom->getIdx()] && !queryListAtoms[atom->getIdx()] &&
|
||||
hasComplexQuery(atom)) {
|
||||
std::string sma =
|
||||
SmartsWrite::GetAtomSmarts(static_cast<const QueryAtom *>(atom));
|
||||
ss << "V " << std::setw(3) << atom->getIdx() + 1 << " " << sma
|
||||
@@ -441,27 +442,50 @@ const std::string AtomGetMolFileSymbol(
|
||||
res = atom->getSymbol();
|
||||
} else {
|
||||
if (!atom->hasProp(common_properties::dummyLabel)) {
|
||||
if (atom->hasQuery() && atom->getQuery()->getNegation() &&
|
||||
atom->getQuery()->getDescription() == "AtomAtomicNum" &&
|
||||
static_cast<ATOM_EQUALS_QUERY *>(atom->getQuery())->getVal() == 1) {
|
||||
if (atom->hasQuery() &&
|
||||
(atom->getQuery()->getTypeLabel() == "A" ||
|
||||
(atom->getQuery()->getNegation() &&
|
||||
atom->getQuery()->getDescription() == "AtomAtomicNum" &&
|
||||
static_cast<ATOM_EQUALS_QUERY *>(atom->getQuery())->getVal() ==
|
||||
1))) {
|
||||
res = "A";
|
||||
} else if (atom->hasQuery() && atom->getQuery()->getNegation() &&
|
||||
atom->getQuery()->getDescription() == "AtomOr" &&
|
||||
atom->getQuery()->endChildren() -
|
||||
atom->getQuery()->beginChildren() ==
|
||||
2 &&
|
||||
(*atom->getQuery()->beginChildren())->getDescription() ==
|
||||
"AtomAtomicNum" &&
|
||||
static_cast<ATOM_EQUALS_QUERY *>(
|
||||
(*atom->getQuery()->beginChildren()).get())
|
||||
->getVal() == 6 &&
|
||||
(*++(atom->getQuery()->beginChildren()))->getDescription() ==
|
||||
"AtomAtomicNum" &&
|
||||
static_cast<ATOM_EQUALS_QUERY *>(
|
||||
(*++(atom->getQuery()->beginChildren())).get())
|
||||
->getVal() == 1) {
|
||||
} else if (atom->hasQuery() &&
|
||||
(atom->getQuery()->getTypeLabel() == "Q" ||
|
||||
(atom->getQuery()->getNegation() &&
|
||||
atom->getQuery()->getDescription() == "AtomOr" &&
|
||||
atom->getQuery()->endChildren() -
|
||||
atom->getQuery()->beginChildren() ==
|
||||
2 &&
|
||||
(*atom->getQuery()->beginChildren())->getDescription() ==
|
||||
"AtomAtomicNum" &&
|
||||
static_cast<ATOM_EQUALS_QUERY *>(
|
||||
(*atom->getQuery()->beginChildren()).get())
|
||||
->getVal() == 6 &&
|
||||
(*++(atom->getQuery()->beginChildren()))->getDescription() ==
|
||||
"AtomAtomicNum" &&
|
||||
static_cast<ATOM_EQUALS_QUERY *>(
|
||||
(*++(atom->getQuery()->beginChildren())).get())
|
||||
->getVal() == 1))) {
|
||||
res = "Q";
|
||||
queryListAtoms.set(atom->getIdx());
|
||||
} else if (atom->hasQuery() && atom->getQuery()->getTypeLabel() == "X") {
|
||||
res = "X";
|
||||
queryListAtoms.set(atom->getIdx());
|
||||
} else if (atom->hasQuery() && atom->getQuery()->getTypeLabel() == "M") {
|
||||
res = "M";
|
||||
queryListAtoms.set(atom->getIdx());
|
||||
} else if (atom->hasQuery() && atom->getQuery()->getTypeLabel() == "AH") {
|
||||
res = "AH";
|
||||
queryListAtoms.set(atom->getIdx());
|
||||
} else if (atom->hasQuery() && atom->getQuery()->getTypeLabel() == "QH") {
|
||||
res = "QH";
|
||||
queryListAtoms.set(atom->getIdx());
|
||||
} else if (atom->hasQuery() && atom->getQuery()->getTypeLabel() == "XH") {
|
||||
res = "XH";
|
||||
queryListAtoms.set(atom->getIdx());
|
||||
} else if (atom->hasQuery() && atom->getQuery()->getTypeLabel() == "MH") {
|
||||
res = "MH";
|
||||
queryListAtoms.set(atom->getIdx());
|
||||
} else if (hasComplexQuery(atom)) {
|
||||
if (hasListQuery(atom)) {
|
||||
res = "L";
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <GraphMol/RDKitBase.h>
|
||||
#include <GraphMol/QueryAtom.h>
|
||||
#include <GraphMol/MolPickler.h>
|
||||
#include <GraphMol/FileParsers/FileParsers.h>
|
||||
#include <GraphMol/SmilesParse/SmilesWrite.h>
|
||||
#include <GraphMol/SmilesParse/SmilesParse.h>
|
||||
@@ -1588,4 +1589,91 @@ M END
|
||||
CHECK(molb.find("LINKNODE 1 3 2 1 2 1 5") != std::string::npos);
|
||||
CHECK(molb.find("LINKNODE 1 4 2 4 3 4 5") != std::string::npos);
|
||||
}
|
||||
}
|
||||
TEST_CASE("more complex queries in CTAB parsers", "[ctab]") {
|
||||
SECTION("v3000") {
|
||||
auto mol = R"CTAB(*.*.*.*.*.*.*.* |$;Q_e;M_p;X_p;AH_p;QH_p;MH_p;XH_p$|
|
||||
manual 06272007272D
|
||||
|
||||
0 0 0 0 0 999 V3000
|
||||
M V30 BEGIN CTAB
|
||||
M V30 COUNTS 8 0 0 0 0
|
||||
M V30 BEGIN ATOM
|
||||
M V30 1 A -3.2083 5.25 0 0
|
||||
M V30 2 Q -0.25 6 0 0
|
||||
M V30 3 M 4.5417 6.0417 0 0
|
||||
M V30 4 X 1.2917 4.2083 0 0
|
||||
M V30 5 AH -4.2083 5.25 0 0
|
||||
M V30 6 QH -1.25 6 0 0
|
||||
M V30 7 MH 3.5417 6.0417 0 0
|
||||
M V30 8 XH 0.2917 4.2083 0 0
|
||||
M V30 END ATOM
|
||||
M V30 END CTAB
|
||||
M END
|
||||
)CTAB"_ctab;
|
||||
REQUIRE(mol);
|
||||
for (const auto atom : mol->atoms()) {
|
||||
REQUIRE(atom->hasQuery());
|
||||
CHECK(!atom->getQuery()->getTypeLabel().empty());
|
||||
}
|
||||
std::string pkl;
|
||||
MolPickler::pickleMol(*mol, pkl);
|
||||
ROMol cp(pkl);
|
||||
for (const auto atom : cp.atoms()) {
|
||||
REQUIRE(atom->hasQuery());
|
||||
CHECK(!atom->getQuery()->getTypeLabel().empty());
|
||||
CHECK(atom->getQuery()->getTypeLabel() ==
|
||||
mol->getAtomWithIdx(atom->getIdx())->getQuery()->getTypeLabel());
|
||||
}
|
||||
auto molb = MolToV3KMolBlock(*mol);
|
||||
CHECK(molb.find(" A ") != std::string::npos);
|
||||
CHECK(molb.find(" AH ") != std::string::npos);
|
||||
CHECK(molb.find(" Q ") != std::string::npos);
|
||||
CHECK(molb.find(" QH ") != std::string::npos);
|
||||
CHECK(molb.find(" M ") != std::string::npos);
|
||||
CHECK(molb.find(" MH ") != std::string::npos);
|
||||
CHECK(molb.find(" X ") != std::string::npos);
|
||||
CHECK(molb.find(" XH ") != std::string::npos);
|
||||
}
|
||||
SECTION("v2000") {
|
||||
auto mol = R"CTAB(*.*.*.*.*.*.*.* |$;Q_e;M_p;X_p;AH_p;QH_p;MH_p;XH_p$|
|
||||
manual 06272007272D
|
||||
|
||||
8 0 0 0 0 0 999 V2000
|
||||
-3.2083 5.2500 0.0000 A 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
-0.2500 6.0000 0.0000 Q 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
4.5417 6.0417 0.0000 M 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1.2917 4.2083 0.0000 X 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
-4.2083 5.2500 0.0000 AH 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
-1.2500 6.0000 0.0000 QH 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
3.5417 6.0417 0.0000 MH 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0.2917 4.2083 0.0000 XH 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
M END
|
||||
)CTAB"_ctab;
|
||||
REQUIRE(mol);
|
||||
for (const auto atom : mol->atoms()) {
|
||||
REQUIRE(atom->hasQuery());
|
||||
CHECK(!atom->getQuery()->getTypeLabel().empty());
|
||||
}
|
||||
std::string pkl;
|
||||
MolPickler::pickleMol(*mol, pkl);
|
||||
ROMol cp(pkl);
|
||||
for (const auto atom : cp.atoms()) {
|
||||
REQUIRE(atom->hasQuery());
|
||||
CHECK(!atom->getQuery()->getTypeLabel().empty());
|
||||
CHECK(atom->getQuery()->getTypeLabel() ==
|
||||
mol->getAtomWithIdx(atom->getIdx())->getQuery()->getTypeLabel());
|
||||
}
|
||||
auto molb = MolToMolBlock(*mol);
|
||||
CHECK(molb.find(" A ") != std::string::npos);
|
||||
CHECK(molb.find(" AH ") != std::string::npos);
|
||||
CHECK(molb.find(" Q ") != std::string::npos);
|
||||
CHECK(molb.find(" QH ") != std::string::npos);
|
||||
CHECK(molb.find(" M ") != std::string::npos);
|
||||
CHECK(molb.find(" MH ") != std::string::npos);
|
||||
CHECK(molb.find(" X ") != std::string::npos);
|
||||
CHECK(molb.find(" XH ") != std::string::npos);
|
||||
/// SMARTS-based queries are not written for these:
|
||||
CHECK(molb.find("V ") == std::string::npos);
|
||||
}
|
||||
}
|
||||
@@ -2067,10 +2067,8 @@ void testMolFileAtomQueries() {
|
||||
for (const auto fName : fNames) {
|
||||
std::unique_ptr<RWMol> m(MolFileToMol(fName));
|
||||
TEST_ASSERT(m);
|
||||
TEST_ASSERT(
|
||||
m->getAtomWithIdx(6)->hasProp(common_properties::_MolFileSymbol));
|
||||
TEST_ASSERT(m->getAtomWithIdx(6)->getProp<std::string>(
|
||||
common_properties::_MolFileSymbol) == "A");
|
||||
TEST_ASSERT(m->getAtomWithIdx(6)->hasQuery());
|
||||
TEST_ASSERT(m->getAtomWithIdx(6)->getQuery()->getTypeLabel() == "A");
|
||||
|
||||
RWMol *m2;
|
||||
MatchVectType mv;
|
||||
@@ -2104,10 +2102,8 @@ void testMolFileAtomQueries() {
|
||||
std::unique_ptr<RWMol> m(MolFileToMol(fName));
|
||||
TEST_ASSERT(m);
|
||||
|
||||
TEST_ASSERT(
|
||||
m->getAtomWithIdx(6)->hasProp(common_properties::_MolFileSymbol));
|
||||
TEST_ASSERT(m->getAtomWithIdx(6)->getProp<std::string>(
|
||||
common_properties::_MolFileSymbol) == "Q");
|
||||
TEST_ASSERT(m->getAtomWithIdx(6)->hasQuery());
|
||||
TEST_ASSERT(m->getAtomWithIdx(6)->getQuery()->getTypeLabel() == "Q");
|
||||
RWMol *m2;
|
||||
MatchVectType mv;
|
||||
std::string smi;
|
||||
|
||||
@@ -32,7 +32,7 @@ using std::int32_t;
|
||||
using std::uint32_t;
|
||||
namespace RDKit {
|
||||
|
||||
const int32_t MolPickler::versionMajor = 11;
|
||||
const int32_t MolPickler::versionMajor = 12;
|
||||
const int32_t MolPickler::versionMinor = 0;
|
||||
const int32_t MolPickler::versionPatch = 0;
|
||||
const int32_t MolPickler::endianId = 0xDEADBEEF;
|
||||
@@ -129,6 +129,10 @@ template <class T>
|
||||
void pickleQuery(std::ostream &ss, const Query<int, T const *, true> *query) {
|
||||
PRECONDITION(query, "no query");
|
||||
streamWrite(ss, query->getDescription());
|
||||
if (!query->getTypeLabel().empty()) {
|
||||
streamWrite(ss, MolPickler::QUERY_TYPELABEL);
|
||||
streamWrite(ss, query->getTypeLabel());
|
||||
}
|
||||
if (query->getNegation()) {
|
||||
streamWrite(ss, MolPickler::QUERY_ISNEGATED);
|
||||
}
|
||||
@@ -503,11 +507,16 @@ Query<int, Atom const *, true> *unpickleQuery(std::istream &ss,
|
||||
Atom const *owner, int version) {
|
||||
PRECONDITION(owner, "no query");
|
||||
std::string descr;
|
||||
std::string typeLabel = "";
|
||||
bool isNegated = false;
|
||||
Query<int, Atom const *, true> *res;
|
||||
streamRead(ss, descr, version);
|
||||
MolPickler::Tags tag;
|
||||
streamRead(ss, tag, version);
|
||||
if (tag == MolPickler::QUERY_TYPELABEL) {
|
||||
streamRead(ss, typeLabel, version);
|
||||
streamRead(ss, tag, version);
|
||||
}
|
||||
if (tag == MolPickler::QUERY_ISNEGATED) {
|
||||
isNegated = true;
|
||||
streamRead(ss, tag, version);
|
||||
@@ -545,6 +554,7 @@ Query<int, Atom const *, true> *unpickleQuery(std::istream &ss,
|
||||
|
||||
res->setNegation(isNegated);
|
||||
res->setDescription(descr);
|
||||
if (!typeLabel.empty()) res->setTypeLabel(typeLabel);
|
||||
|
||||
finalizeQueryFromDescription(res, owner);
|
||||
|
||||
@@ -760,13 +770,14 @@ AtomMonomerInfo *unpickleAtomMonomerInfo(std::istream &ss, int version) {
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
// Resets the `exceptionState` of the passed stream `ss` in the destructor to the
|
||||
// `exceptionState` the stream ss was in, before setting `newExceptionState`.
|
||||
// Resets the `exceptionState` of the passed stream `ss` in the destructor to
|
||||
// the `exceptionState` the stream ss was in, before setting
|
||||
// `newExceptionState`.
|
||||
struct IOStreamExceptionStateResetter {
|
||||
std::ios &originalStream;
|
||||
std::ios_base::iostate originalExceptionState;
|
||||
IOStreamExceptionStateResetter(std::ios &ss,
|
||||
std::ios_base::iostate newExceptionState)
|
||||
std::ios_base::iostate newExceptionState)
|
||||
: originalStream(ss), originalExceptionState(ss.exceptions()) {
|
||||
ss.exceptions(newExceptionState);
|
||||
}
|
||||
@@ -800,15 +811,15 @@ void MolPickler::pickleMol(const ROMol *mol, std::ostream &ss,
|
||||
streamWrite(ss, versionMajor);
|
||||
streamWrite(ss, versionMinor);
|
||||
streamWrite(ss, versionPatch);
|
||||
#ifndef OLD_PICKLE
|
||||
#ifndef OLD_PICKLE
|
||||
if (mol->getNumAtoms() > 255) {
|
||||
_pickle<int32_t>(mol, ss, propertyFlags);
|
||||
} else {
|
||||
_pickle<unsigned char>(mol, ss, propertyFlags);
|
||||
}
|
||||
#else
|
||||
#else
|
||||
_pickleV1(mol, ss);
|
||||
#endif
|
||||
#endif
|
||||
} catch (const std::ios_base::failure &e) {
|
||||
if (ss.eof()) {
|
||||
throw MolPicklerException(
|
||||
@@ -865,13 +876,13 @@ void MolPickler::molFromPickle(std::istream &ss, ROMol *mol) {
|
||||
|
||||
mol->clearAllAtomBookmarks();
|
||||
mol->clearAllBondBookmarks();
|
||||
|
||||
|
||||
streamRead(ss, tmpInt);
|
||||
if (tmpInt != endianId) {
|
||||
throw MolPicklerException(
|
||||
"Bad pickle format: bad endian ID or invalid file format");
|
||||
}
|
||||
|
||||
|
||||
streamRead(ss, tmpInt);
|
||||
if (static_cast<Tags>(tmpInt) != VERSION) {
|
||||
throw MolPicklerException("Bad pickle format: no version tag");
|
||||
|
||||
@@ -137,6 +137,7 @@ class RDKIT_GRAPHMOL_EXPORT MolPickler {
|
||||
BEGINSTEREOGROUP,
|
||||
BEGINCONFPROPS,
|
||||
BEGINCONFS_DOUBLE,
|
||||
QUERY_TYPELABEL,
|
||||
} Tags;
|
||||
|
||||
static unsigned int getDefaultPickleProperties();
|
||||
|
||||
@@ -344,9 +344,8 @@ ATOM_EQUALS_QUERY *makeAtomInRingQuery() {
|
||||
|
||||
ATOM_OR_QUERY *makeQAtomQuery() {
|
||||
auto *res = new ATOM_OR_QUERY;
|
||||
res->setDescription("AtomOr"); // FIX: we really should label this more
|
||||
// descriptively so that it can be output more
|
||||
// cleanly
|
||||
res->setDescription("AtomOr");
|
||||
res->setTypeLabel("Q");
|
||||
res->setNegation(true);
|
||||
res->addChild(
|
||||
Queries::Query<int, Atom const *, true>::CHILD_TYPE(makeAtomNumQuery(6)));
|
||||
@@ -357,15 +356,18 @@ ATOM_OR_QUERY *makeQAtomQuery() {
|
||||
ATOM_EQUALS_QUERY *makeQHAtomQuery() {
|
||||
ATOM_EQUALS_QUERY *res = makeAtomNumQuery(6);
|
||||
res->setNegation(true);
|
||||
res->setTypeLabel("QH");
|
||||
return res;
|
||||
}
|
||||
ATOM_EQUALS_QUERY *makeAAtomQuery() {
|
||||
ATOM_EQUALS_QUERY *res = makeAtomNumQuery(1);
|
||||
res->setNegation(true);
|
||||
res->setTypeLabel("A");
|
||||
return res;
|
||||
}
|
||||
ATOM_EQUALS_QUERY *makeAHAtomQuery() {
|
||||
auto *res = rdcast<ATOM_EQUALS_QUERY *>(makeAtomNullQuery());
|
||||
res->setTypeLabel("AH");
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -382,12 +384,15 @@ ATOM_OR_QUERY *makeXAtomQuery() {
|
||||
makeAtomNumQuery(53)));
|
||||
res->addChild(Queries::Query<int, Atom const *, true>::CHILD_TYPE(
|
||||
makeAtomNumQuery(85)));
|
||||
res->setTypeLabel("X");
|
||||
|
||||
return res;
|
||||
}
|
||||
ATOM_OR_QUERY *makeXHAtomQuery() {
|
||||
ATOM_OR_QUERY *res = makeXAtomQuery();
|
||||
res->addChild(
|
||||
Queries::Query<int, Atom const *, true>::CHILD_TYPE(makeAtomNumQuery(1)));
|
||||
res->setTypeLabel("XH");
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -399,6 +404,8 @@ ATOM_OR_QUERY *makeMAtomQuery() {
|
||||
ATOM_OR_QUERY *res = makeMHAtomQuery();
|
||||
res->addChild(
|
||||
Queries::Query<int, Atom const *, true>::CHILD_TYPE(makeAtomNumQuery(1)));
|
||||
res->setTypeLabel("M");
|
||||
|
||||
return res;
|
||||
}
|
||||
ATOM_OR_QUERY *makeMHAtomQuery() {
|
||||
@@ -451,6 +458,7 @@ ATOM_OR_QUERY *makeMHAtomQuery() {
|
||||
makeAtomNumQuery(85)));
|
||||
res->addChild(Queries::Query<int, Atom const *, true>::CHILD_TYPE(
|
||||
makeAtomNumQuery(86)));
|
||||
res->setTypeLabel("MH");
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -511,7 +519,8 @@ RDKIT_GRAPHMOL_EXPORT BOND_EQUALS_QUERY *makeSingleOrAromaticBondQuery() {
|
||||
return res;
|
||||
};
|
||||
|
||||
RDKIT_GRAPHMOL_EXPORT BOND_EQUALS_QUERY *makeSingleOrDoubleOrAromaticBondQuery() {
|
||||
RDKIT_GRAPHMOL_EXPORT BOND_EQUALS_QUERY *
|
||||
makeSingleOrDoubleOrAromaticBondQuery() {
|
||||
auto *res = new BOND_EQUALS_QUERY;
|
||||
res->setVal(true);
|
||||
res->setDataFunc(queryBondIsSingleOrDoubleOrAromatic);
|
||||
@@ -519,7 +528,6 @@ RDKIT_GRAPHMOL_EXPORT BOND_EQUALS_QUERY *makeSingleOrDoubleOrAromaticBondQuery()
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
BOND_EQUALS_QUERY *makeBondDirEqualsQuery(Bond::BondDir what) {
|
||||
auto *res = new BOND_EQUALS_QUERY;
|
||||
res->setVal(what);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_ANDQUERY_H__
|
||||
#define __RD_ANDQUERY_H__
|
||||
#ifndef RD_ANDQUERY_H
|
||||
#define RD_ANDQUERY_H
|
||||
|
||||
#include "Query.h"
|
||||
|
||||
@@ -46,6 +46,7 @@ class AndQuery
|
||||
}
|
||||
res->setNegation(this->getNegation());
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_EQUALITYQUERY_H__
|
||||
#define __RD_EQUALITYQUERY_H__
|
||||
#ifndef RD_EQUALITYQUERY_H
|
||||
#define RD_EQUALITYQUERY_H
|
||||
#include "Query.h"
|
||||
#include <sstream>
|
||||
|
||||
@@ -75,6 +75,7 @@ class EqualityQuery
|
||||
res->setTol(this->d_tol);
|
||||
res->setDataFunc(this->d_dataFunc);
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_GREATEREQUALQUERY_H__
|
||||
#define __RD_GREATEREQUALQUERY_H__
|
||||
#ifndef RD_GREATEREQUALQUERY_H
|
||||
#define RD_GREATEREQUALQUERY_H
|
||||
#include "Query.h"
|
||||
#include "EqualityQuery.h"
|
||||
|
||||
@@ -59,6 +59,7 @@ class GreaterEqualQuery
|
||||
res->setNegation(this->getNegation());
|
||||
res->setDataFunc(this->d_dataFunc);
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_GREATERQUERY_H__
|
||||
#define __RD_GREATERQUERY_H__
|
||||
#ifndef RD_GREATERQUERY_H
|
||||
#define RD_GREATERQUERY_H
|
||||
#include "Query.h"
|
||||
#include "EqualityQuery.h"
|
||||
|
||||
@@ -59,6 +59,7 @@ class GreaterQuery
|
||||
res->setNegation(this->getNegation());
|
||||
res->setDataFunc(this->d_dataFunc);
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_LESSEQUALQUERY_H__
|
||||
#define __RD_LESSEQUALQUERY_H__
|
||||
#ifndef RD_LESSEQUALQUERY_H
|
||||
#define RD_LESSEQUALQUERY_H
|
||||
#include "Query.h"
|
||||
#include "EqualityQuery.h"
|
||||
|
||||
@@ -60,6 +60,7 @@ class LessEqualQuery
|
||||
res->setTol(this->d_tol);
|
||||
res->setDataFunc(this->d_dataFunc);
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_LESSQUERY_H__
|
||||
#define __RD_LESSQUERY_H__
|
||||
#ifndef RD_LESSQUERY_H
|
||||
#define RD_LESSQUERY_H
|
||||
#include "Query.h"
|
||||
#include "EqualityQuery.h"
|
||||
|
||||
@@ -59,6 +59,7 @@ class LessQuery
|
||||
res->setTol(this->d_tol);
|
||||
res->setDataFunc(this->d_dataFunc);
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
// which is included in the file license.txt, found at the root
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#ifndef _RD_NULLQUERYALGEBRA_H
|
||||
#define _RD_NULLQUERYALGEBRA_H
|
||||
#ifndef RD_NULLQUERYALGEBRA_H
|
||||
#define RD_NULLQUERYALGEBRA_H
|
||||
|
||||
#include <GraphMol/QueryOps.h>
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace RDKit {
|
||||
namespace {
|
||||
template <class T>
|
||||
void mergeBothNullQ(T *&returnQuery, T *&otherNullQ,
|
||||
Queries::CompositeQueryType how) {
|
||||
Queries::CompositeQueryType how) {
|
||||
bool negatedQ = returnQuery->getNegation();
|
||||
bool negatedOtherQ = otherNullQ->getNegation();
|
||||
|
||||
@@ -42,7 +42,7 @@ void mergeBothNullQ(T *&returnQuery, T *&otherNullQ,
|
||||
|
||||
template <class T>
|
||||
void mergeNullQFirst(T *&returnQuery, T *&otherQ,
|
||||
Queries::CompositeQueryType how) {
|
||||
Queries::CompositeQueryType how) {
|
||||
bool negatedQ = returnQuery->getNegation();
|
||||
|
||||
if (how == Queries::COMPOSITE_AND) {
|
||||
@@ -77,7 +77,7 @@ void mergeNullQueries(T *&returnQuery, bool isQueryNull, T *&otherQuery,
|
||||
} else if (isQueryNull) {
|
||||
mergeNullQFirst(returnQuery, otherQuery, how);
|
||||
} else if (isOtherQNull) {
|
||||
std::swap(returnQuery,otherQuery);
|
||||
std::swap(returnQuery, otherQuery);
|
||||
mergeNullQFirst(returnQuery, otherQuery, how);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_ORQUERY_H__
|
||||
#define __RD_ORQUERY_H__
|
||||
#ifndef RD_ORQUERY_H
|
||||
#define RD_ORQUERY_H
|
||||
|
||||
#include "Query.h"
|
||||
|
||||
@@ -47,6 +47,7 @@ class OrQuery
|
||||
}
|
||||
res->setNegation(this->getNegation());
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_QUERY_H__
|
||||
#define __RD_QUERY_H__
|
||||
#ifndef RD_QUERY_H
|
||||
#define RD_QUERY_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4800) // warning: converting things to bool
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <RDGeneral/Invariant.h>
|
||||
|
||||
namespace Queries {
|
||||
@@ -45,18 +44,14 @@ template <class MatchFuncArgType, class DataFuncArgType = MatchFuncArgType,
|
||||
bool needsConversion = false>
|
||||
class Query {
|
||||
public:
|
||||
typedef boost::shared_ptr<
|
||||
typedef std::shared_ptr<
|
||||
Query<MatchFuncArgType, DataFuncArgType, needsConversion>>
|
||||
CHILD_TYPE;
|
||||
typedef std::vector<CHILD_TYPE> CHILD_VECT;
|
||||
typedef typename CHILD_VECT::iterator CHILD_VECT_I;
|
||||
typedef typename CHILD_VECT::const_iterator CHILD_VECT_CI;
|
||||
|
||||
Query()
|
||||
: d_description(""),
|
||||
|
||||
d_matchFunc(nullptr),
|
||||
d_dataFunc(nullptr){};
|
||||
Query() : d_matchFunc(nullptr), d_dataFunc(nullptr){};
|
||||
virtual ~Query() { this->d_children.clear(); };
|
||||
|
||||
//! sets whether or not we are negated
|
||||
@@ -82,6 +77,13 @@ class Query {
|
||||
return "not " + getDescription();
|
||||
}
|
||||
|
||||
//! sets our type label
|
||||
void setTypeLabel(const std::string &typ) { this->d_queryType = typ; };
|
||||
//! \overload
|
||||
void setTypeLabel(const char *typ) { this->d_queryType = std::string(typ); };
|
||||
//! returns our text label.
|
||||
const std::string &getTypeLabel() const { return this->d_queryType; };
|
||||
|
||||
//! sets our match function
|
||||
void setMatchFunc(bool (*what)(MatchFuncArgType)) {
|
||||
this->d_matchFunc = what;
|
||||
@@ -138,13 +140,15 @@ class Query {
|
||||
res->d_matchFunc = this->d_matchFunc;
|
||||
res->d_dataFunc = this->d_dataFunc;
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
|
||||
protected:
|
||||
MatchFuncArgType d_val = 0;
|
||||
MatchFuncArgType d_tol = 0;
|
||||
std::string d_description;
|
||||
std::string d_description = "";
|
||||
std::string d_queryType = "";
|
||||
CHILD_VECT d_children;
|
||||
bool df_negate{false};
|
||||
bool (*d_matchFunc)(MatchFuncArgType);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_RANGEQUERY_H__
|
||||
#define __RD_RANGEQUERY_H__
|
||||
#ifndef RD_RANGEQUERY_H
|
||||
#define RD_RANGEQUERY_H
|
||||
#include "Query.h"
|
||||
#include <utility>
|
||||
|
||||
@@ -27,10 +27,7 @@ template <class MatchFuncArgType, class DataFuncArgType = MatchFuncArgType,
|
||||
class RangeQuery
|
||||
: public Query<MatchFuncArgType, DataFuncArgType, needsConversion> {
|
||||
public:
|
||||
RangeQuery()
|
||||
: d_upper(0), d_lower(0) {
|
||||
this->df_negate = false;
|
||||
};
|
||||
RangeQuery() : d_upper(0), d_lower(0) { this->df_negate = false; };
|
||||
//! construct and set the lower and upper bounds
|
||||
RangeQuery(MatchFuncArgType lower, MatchFuncArgType upper)
|
||||
: d_upper(upper), d_lower(lower), df_upperOpen(true), df_lowerOpen(true) {
|
||||
@@ -93,6 +90,7 @@ class RangeQuery
|
||||
res->setEndsOpen(this->df_lowerOpen, this->df_upperOpen);
|
||||
res->setDataFunc(this->d_dataFunc);
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2008 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_SETQUERY_H__
|
||||
#define __RD_SETQUERY_H__
|
||||
#ifndef RD_SETQUERY_H
|
||||
#define RD_SETQUERY_H
|
||||
#include <set>
|
||||
#include "Query.h"
|
||||
#include <sstream>
|
||||
@@ -53,6 +53,7 @@ class SetQuery
|
||||
}
|
||||
res->setNegation(this->getNegation());
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -8,8 +8,8 @@
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <RDGeneral/export.h>
|
||||
#ifndef __RD_XORQUERY_H__
|
||||
#define __RD_XORQUERY_H__
|
||||
#ifndef RD_XORQUERY_H
|
||||
#define RD_XORQUERY_H
|
||||
|
||||
#include "Query.h"
|
||||
|
||||
@@ -52,6 +52,7 @@ class XOrQuery
|
||||
}
|
||||
res->setNegation(this->getNegation());
|
||||
res->d_description = this->d_description;
|
||||
res->d_queryType = this->d_queryType;
|
||||
return res;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// $Id$
|
||||
//
|
||||
// Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
|
||||
// Copyright (c) 2003-2020 Greg Landrum and Rational Discovery LLC
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
@@ -22,31 +21,33 @@ void test1() {
|
||||
cout << "Float" << endl;
|
||||
EqualityQuery<double> q(1.0);
|
||||
|
||||
CHECK_INVARIANT(!q.Match(0.0), "");
|
||||
CHECK_INVARIANT(q.Match(1.0), "");
|
||||
CHECK_INVARIANT(!q.Match(1.001), "");
|
||||
CHECK_INVARIANT(!q.Match(1.1), "");
|
||||
CHECK_INVARIANT(!q.Match(-2), "");
|
||||
TEST_ASSERT(!q.Match(0.0));
|
||||
TEST_ASSERT(q.Match(1.0));
|
||||
TEST_ASSERT(!q.Match(1.001));
|
||||
TEST_ASSERT(!q.Match(1.1));
|
||||
TEST_ASSERT(!q.Match(-2));
|
||||
|
||||
cout << "With Tolerance" << endl;
|
||||
q.setTol(0.002);
|
||||
CHECK_INVARIANT(!q.Match(0.0), "");
|
||||
CHECK_INVARIANT(q.Match(1.0), "");
|
||||
CHECK_INVARIANT(q.Match(1.001), "");
|
||||
CHECK_INVARIANT(!q.Match(1.1), "");
|
||||
CHECK_INVARIANT(!q.Match(-2), "");
|
||||
TEST_ASSERT(!q.Match(0.0));
|
||||
TEST_ASSERT(q.Match(1.0));
|
||||
TEST_ASSERT(q.Match(1.001));
|
||||
TEST_ASSERT(!q.Match(1.1));
|
||||
TEST_ASSERT(!q.Match(-2));
|
||||
TEST_ASSERT(q.getTypeLabel().empty());
|
||||
q.setTypeLabel("FloatEquality");
|
||||
|
||||
Query<double> *newQ;
|
||||
newQ = q.copy();
|
||||
CHECK_INVARIANT(!newQ->Match(0.0), "");
|
||||
CHECK_INVARIANT(newQ->Match(1.0), "");
|
||||
CHECK_INVARIANT(newQ->Match(1.001), "");
|
||||
CHECK_INVARIANT(!newQ->Match(1.1), "");
|
||||
CHECK_INVARIANT(!newQ->Match(-2), "");
|
||||
TEST_ASSERT(!newQ->Match(0.0));
|
||||
TEST_ASSERT(newQ->Match(1.0));
|
||||
TEST_ASSERT(newQ->Match(1.001));
|
||||
TEST_ASSERT(!newQ->Match(1.1));
|
||||
TEST_ASSERT(!newQ->Match(-2));
|
||||
TEST_ASSERT(newQ->getTypeLabel() == "FloatEquality");
|
||||
delete newQ;
|
||||
}
|
||||
|
||||
|
||||
void test2() {
|
||||
cout << "Set" << endl;
|
||||
SetQuery<int> q;
|
||||
@@ -54,17 +55,17 @@ void test2() {
|
||||
q.insert(3);
|
||||
q.insert(5);
|
||||
|
||||
CHECK_INVARIANT(!q.Match(0), "");
|
||||
CHECK_INVARIANT(q.Match(1), "");
|
||||
CHECK_INVARIANT(q.Match(3), "");
|
||||
CHECK_INVARIANT(!q.Match(-3), "");
|
||||
TEST_ASSERT(!q.Match(0));
|
||||
TEST_ASSERT(q.Match(1));
|
||||
TEST_ASSERT(q.Match(3));
|
||||
TEST_ASSERT(!q.Match(-3));
|
||||
|
||||
Query<int> *newQ;
|
||||
newQ = q.copy();
|
||||
CHECK_INVARIANT(!newQ->Match(0), "");
|
||||
CHECK_INVARIANT(newQ->Match(1), "");
|
||||
CHECK_INVARIANT(newQ->Match(3), "");
|
||||
CHECK_INVARIANT(!newQ->Match(-3), "");
|
||||
TEST_ASSERT(!newQ->Match(0));
|
||||
TEST_ASSERT(newQ->Match(1));
|
||||
TEST_ASSERT(newQ->Match(3));
|
||||
TEST_ASSERT(!newQ->Match(-3));
|
||||
delete newQ;
|
||||
}
|
||||
|
||||
@@ -79,17 +80,17 @@ void test3() {
|
||||
q->addChild(Query<int>::CHILD_TYPE(l));
|
||||
q->addChild(Query<int>::CHILD_TYPE(g));
|
||||
|
||||
CHECK_INVARIANT(!q->Match(0), "");
|
||||
CHECK_INVARIANT(q->Match(1), "");
|
||||
CHECK_INVARIANT(q->Match(3), "");
|
||||
CHECK_INVARIANT(!q->Match(-3), "");
|
||||
TEST_ASSERT(!q->Match(0));
|
||||
TEST_ASSERT(q->Match(1));
|
||||
TEST_ASSERT(q->Match(3));
|
||||
TEST_ASSERT(!q->Match(-3));
|
||||
|
||||
Query<int> *newQ;
|
||||
newQ = q->copy();
|
||||
CHECK_INVARIANT(!newQ->Match(0), "");
|
||||
CHECK_INVARIANT(newQ->Match(1), "");
|
||||
CHECK_INVARIANT(newQ->Match(3), "");
|
||||
CHECK_INVARIANT(!newQ->Match(-3), "");
|
||||
TEST_ASSERT(!newQ->Match(0));
|
||||
TEST_ASSERT(newQ->Match(1));
|
||||
TEST_ASSERT(newQ->Match(3));
|
||||
TEST_ASSERT(!newQ->Match(-3));
|
||||
|
||||
delete newQ;
|
||||
delete q;
|
||||
@@ -106,17 +107,17 @@ void test4() {
|
||||
q->addChild(Query<int>::CHILD_TYPE(l));
|
||||
q->addChild(Query<int>::CHILD_TYPE(g));
|
||||
|
||||
CHECK_INVARIANT(q->Match(0), "");
|
||||
CHECK_INVARIANT(q->Match(1), "");
|
||||
CHECK_INVARIANT(q->Match(3), "");
|
||||
CHECK_INVARIANT(q->Match(-3), "");
|
||||
TEST_ASSERT(q->Match(0));
|
||||
TEST_ASSERT(q->Match(1));
|
||||
TEST_ASSERT(q->Match(3));
|
||||
TEST_ASSERT(q->Match(-3));
|
||||
|
||||
Query<int> *newQ;
|
||||
newQ = q->copy();
|
||||
CHECK_INVARIANT(newQ->Match(0), "");
|
||||
CHECK_INVARIANT(newQ->Match(1), "");
|
||||
CHECK_INVARIANT(newQ->Match(3), "");
|
||||
CHECK_INVARIANT(newQ->Match(-3), "");
|
||||
TEST_ASSERT(newQ->Match(0));
|
||||
TEST_ASSERT(newQ->Match(1));
|
||||
TEST_ASSERT(newQ->Match(3));
|
||||
TEST_ASSERT(newQ->Match(-3));
|
||||
|
||||
delete newQ;
|
||||
delete q;
|
||||
@@ -133,19 +134,19 @@ void test5() {
|
||||
q->addChild(Query<int>::CHILD_TYPE(l));
|
||||
q->addChild(Query<int>::CHILD_TYPE(g));
|
||||
|
||||
CHECK_INVARIANT(q->Match(-1), "");
|
||||
CHECK_INVARIANT(q->Match(0), "");
|
||||
CHECK_INVARIANT(!q->Match(1), "");
|
||||
CHECK_INVARIANT(!q->Match(3), "");
|
||||
CHECK_INVARIANT(q->Match(-3), "");
|
||||
TEST_ASSERT(q->Match(-1));
|
||||
TEST_ASSERT(q->Match(0));
|
||||
TEST_ASSERT(!q->Match(1));
|
||||
TEST_ASSERT(!q->Match(3));
|
||||
TEST_ASSERT(q->Match(-3));
|
||||
|
||||
Query<int> *newQ;
|
||||
newQ = q->copy();
|
||||
CHECK_INVARIANT(newQ->Match(-1), "");
|
||||
CHECK_INVARIANT(newQ->Match(0), "");
|
||||
CHECK_INVARIANT(!newQ->Match(1), "");
|
||||
CHECK_INVARIANT(!newQ->Match(3), "");
|
||||
CHECK_INVARIANT(newQ->Match(-3), "");
|
||||
TEST_ASSERT(newQ->Match(-1));
|
||||
TEST_ASSERT(newQ->Match(0));
|
||||
TEST_ASSERT(!newQ->Match(1));
|
||||
TEST_ASSERT(!newQ->Match(3));
|
||||
TEST_ASSERT(newQ->Match(-3));
|
||||
|
||||
delete newQ;
|
||||
delete q;
|
||||
@@ -158,26 +159,26 @@ void test6() {
|
||||
EqualityQuery<int, double, true> q;
|
||||
q.setDataFunc(foofun);
|
||||
q.setVal(6);
|
||||
CHECK_INVARIANT(q.Match(6.0), "");
|
||||
CHECK_INVARIANT(q.Match(6.1), "");
|
||||
CHECK_INVARIANT(!q.Match(5.0), "");
|
||||
TEST_ASSERT(q.Match(6.0));
|
||||
TEST_ASSERT(q.Match(6.1));
|
||||
TEST_ASSERT(!q.Match(5.0));
|
||||
|
||||
Query<int, double, true> *newQ;
|
||||
newQ = q.copy();
|
||||
CHECK_INVARIANT(newQ->Match(6.0), "");
|
||||
CHECK_INVARIANT(newQ->Match(6.1), "");
|
||||
CHECK_INVARIANT(!newQ->Match(5.0), "");
|
||||
TEST_ASSERT(newQ->Match(6.0));
|
||||
TEST_ASSERT(newQ->Match(6.1));
|
||||
TEST_ASSERT(!newQ->Match(5.0));
|
||||
|
||||
Query<int, double, true> *newQ2 = &q;
|
||||
CHECK_INVARIANT(newQ2->Match(6.0), "");
|
||||
CHECK_INVARIANT(newQ2->Match(6.1), "");
|
||||
CHECK_INVARIANT(!newQ2->Match(5.0), "");
|
||||
TEST_ASSERT(newQ2->Match(6.0));
|
||||
TEST_ASSERT(newQ2->Match(6.1));
|
||||
TEST_ASSERT(!newQ2->Match(5.0));
|
||||
|
||||
Query<int, double, true> *newQ3;
|
||||
newQ3 = newQ2->copy();
|
||||
CHECK_INVARIANT(newQ3->Match(6.0), "");
|
||||
CHECK_INVARIANT(newQ3->Match(6.1), "");
|
||||
CHECK_INVARIANT(!newQ3->Match(5.0), "");
|
||||
TEST_ASSERT(newQ3->Match(6.0));
|
||||
TEST_ASSERT(newQ3->Match(6.1));
|
||||
TEST_ASSERT(!newQ3->Match(5.0));
|
||||
|
||||
delete newQ;
|
||||
delete newQ3;
|
||||
@@ -195,10 +196,10 @@ void basics1() {
|
||||
q.setMatchFunc(matchF);
|
||||
q.setDataFunc(dataF);
|
||||
|
||||
CHECK_INVARIANT(!q.Match(0.0), "");
|
||||
CHECK_INVARIANT(q.Match(1.0), "");
|
||||
CHECK_INVARIANT(q.Match(1.1), "");
|
||||
CHECK_INVARIANT(!q.Match(-2.0), "");
|
||||
TEST_ASSERT(!q.Match(0.0));
|
||||
TEST_ASSERT(q.Match(1.0));
|
||||
TEST_ASSERT(q.Match(1.1));
|
||||
TEST_ASSERT(!q.Match(-2.0));
|
||||
|
||||
TEST_ASSERT(!q.getMatchFunc()(0));
|
||||
TEST_ASSERT(q.getMatchFunc()(3));
|
||||
@@ -207,66 +208,66 @@ void basics1() {
|
||||
cout << "Query2" << endl;
|
||||
Query<bool, int, true> q2;
|
||||
q2.setDataFunc(cmp);
|
||||
CHECK_INVARIANT(q2.Match(0), "");
|
||||
CHECK_INVARIANT(q2.Match(1), "");
|
||||
CHECK_INVARIANT(!q2.Match(3), "");
|
||||
CHECK_INVARIANT(!q2.Match(4), "");
|
||||
CHECK_INVARIANT(!q2.Match(4.0), "");
|
||||
TEST_ASSERT(q2.Match(0));
|
||||
TEST_ASSERT(q2.Match(1));
|
||||
TEST_ASSERT(!q2.Match(3));
|
||||
TEST_ASSERT(!q2.Match(4));
|
||||
TEST_ASSERT(!q2.Match(4.0));
|
||||
}
|
||||
|
||||
void basics2() {
|
||||
cout << "Equality" << endl;
|
||||
EqualityQuery<int> q2;
|
||||
q2.setVal(3);
|
||||
CHECK_INVARIANT(!q2.Match(0), "");
|
||||
CHECK_INVARIANT(!q2.Match(1), "");
|
||||
CHECK_INVARIANT(q2.Match(3), "");
|
||||
CHECK_INVARIANT(!q2.Match(-3), "");
|
||||
TEST_ASSERT(!q2.Match(0));
|
||||
TEST_ASSERT(!q2.Match(1));
|
||||
TEST_ASSERT(q2.Match(3));
|
||||
TEST_ASSERT(!q2.Match(-3));
|
||||
|
||||
cout << "Greater" << endl;
|
||||
GreaterQuery<int> q3;
|
||||
q3.setVal(3);
|
||||
CHECK_INVARIANT(q3.Match(0), "");
|
||||
CHECK_INVARIANT(q3.Match(1), "");
|
||||
CHECK_INVARIANT(!q3.Match(3), "");
|
||||
CHECK_INVARIANT(!q3.Match(5), "");
|
||||
TEST_ASSERT(q3.Match(0));
|
||||
TEST_ASSERT(q3.Match(1));
|
||||
TEST_ASSERT(!q3.Match(3));
|
||||
TEST_ASSERT(!q3.Match(5));
|
||||
|
||||
cout << "GreaterEqual" << endl;
|
||||
GreaterEqualQuery<int> q4(3);
|
||||
CHECK_INVARIANT(q4.Match(0), "");
|
||||
CHECK_INVARIANT(q4.Match(1), "");
|
||||
CHECK_INVARIANT(q4.Match(3), "");
|
||||
CHECK_INVARIANT(!q4.Match(5), "");
|
||||
TEST_ASSERT(q4.Match(0));
|
||||
TEST_ASSERT(q4.Match(1));
|
||||
TEST_ASSERT(q4.Match(3));
|
||||
TEST_ASSERT(!q4.Match(5));
|
||||
|
||||
cout << "Less" << endl;
|
||||
LessQuery<int> q5;
|
||||
q5.setVal(3);
|
||||
CHECK_INVARIANT(!q5.Match(0), "");
|
||||
CHECK_INVARIANT(!q5.Match(1), "");
|
||||
CHECK_INVARIANT(!q5.Match(3), "");
|
||||
CHECK_INVARIANT(q5.Match(5), "");
|
||||
TEST_ASSERT(!q5.Match(0));
|
||||
TEST_ASSERT(!q5.Match(1));
|
||||
TEST_ASSERT(!q5.Match(3));
|
||||
TEST_ASSERT(q5.Match(5));
|
||||
|
||||
cout << "LessEqual" << endl;
|
||||
LessEqualQuery<int> q6(3);
|
||||
|
||||
CHECK_INVARIANT(!q6.Match(0), "");
|
||||
CHECK_INVARIANT(!q6.Match(1), "");
|
||||
CHECK_INVARIANT(q6.Match(3), "");
|
||||
CHECK_INVARIANT(q6.Match(5), "");
|
||||
TEST_ASSERT(!q6.Match(0));
|
||||
TEST_ASSERT(!q6.Match(1));
|
||||
TEST_ASSERT(q6.Match(3));
|
||||
TEST_ASSERT(q6.Match(5));
|
||||
|
||||
cout << "Open Range" << endl;
|
||||
RangeQuery<int> q7(0, 3);
|
||||
CHECK_INVARIANT(!q7.Match(0), "");
|
||||
CHECK_INVARIANT(q7.Match(1), "");
|
||||
CHECK_INVARIANT(!q7.Match(3), "");
|
||||
CHECK_INVARIANT(!q7.Match(5), "");
|
||||
TEST_ASSERT(!q7.Match(0));
|
||||
TEST_ASSERT(q7.Match(1));
|
||||
TEST_ASSERT(!q7.Match(3));
|
||||
TEST_ASSERT(!q7.Match(5));
|
||||
|
||||
cout << "Closed Range" << endl;
|
||||
q7.setEndsOpen(false, false);
|
||||
CHECK_INVARIANT(q7.Match(0), "");
|
||||
CHECK_INVARIANT(q7.Match(1), "");
|
||||
CHECK_INVARIANT(q7.Match(3), "");
|
||||
CHECK_INVARIANT(!q7.Match(5), "");
|
||||
TEST_ASSERT(q7.Match(0));
|
||||
TEST_ASSERT(q7.Match(1));
|
||||
TEST_ASSERT(q7.Match(3));
|
||||
TEST_ASSERT(!q7.Match(5));
|
||||
}
|
||||
|
||||
int convFunc(const char *arg) { return boost::lexical_cast<int>(arg); };
|
||||
@@ -279,17 +280,17 @@ void test7() {
|
||||
q.insert(3);
|
||||
q.insert(5);
|
||||
|
||||
CHECK_INVARIANT(!q.Match("0"), "");
|
||||
CHECK_INVARIANT(q.Match("1"), "");
|
||||
CHECK_INVARIANT(q.Match("3"), "");
|
||||
CHECK_INVARIANT(!q.Match("-3"), "");
|
||||
TEST_ASSERT(!q.Match("0"));
|
||||
TEST_ASSERT(q.Match("1"));
|
||||
TEST_ASSERT(q.Match("3"));
|
||||
TEST_ASSERT(!q.Match("-3"));
|
||||
|
||||
Query<int, const char *, true> *newQ;
|
||||
newQ = q.copy();
|
||||
CHECK_INVARIANT(!newQ->Match("0"), "");
|
||||
CHECK_INVARIANT(newQ->Match("1"), "");
|
||||
CHECK_INVARIANT(newQ->Match("3"), "");
|
||||
CHECK_INVARIANT(!newQ->Match("-3"), "");
|
||||
TEST_ASSERT(!newQ->Match("0"));
|
||||
TEST_ASSERT(newQ->Match("1"));
|
||||
TEST_ASSERT(newQ->Match("3"));
|
||||
TEST_ASSERT(!newQ->Match("-3"));
|
||||
|
||||
delete newQ;
|
||||
}
|
||||
@@ -305,5 +306,4 @@ int main() {
|
||||
test5();
|
||||
test6();
|
||||
test7();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ const std::string _MolFileBondAttach = "_MolFileBondAttach";
|
||||
const std::string _MolFileBondType = "_MolFileBondType";
|
||||
const std::string _MolFileBondStereo = "_MolFileBondStereo";
|
||||
const std::string _MolFileBondCfg = "_MolFileBondCfg";
|
||||
const std::string _MolFileSymbol = "_MolFileSymbol";
|
||||
|
||||
const std::string _Name = "_Name";
|
||||
const std::string _NeedsQueryScan = "_NeedsQueryScan";
|
||||
|
||||
@@ -177,7 +177,6 @@ RDKIT_RDGENERAL_EXPORT extern const std::string _MolFileAtomQuery; // int
|
||||
RDKIT_RDGENERAL_EXPORT extern const std::string _MolFileBondQuery; // int
|
||||
RDKIT_RDGENERAL_EXPORT extern const std::string _MolFileBondEndPts; // string
|
||||
RDKIT_RDGENERAL_EXPORT extern const std::string _MolFileBondAttach; // string
|
||||
RDKIT_RDGENERAL_EXPORT extern const std::string _MolFileSymbol; // string
|
||||
RDKIT_RDGENERAL_EXPORT extern const std::string
|
||||
_MolFileBondType; // unsigned int
|
||||
RDKIT_RDGENERAL_EXPORT extern const std::string
|
||||
|
||||
@@ -400,6 +400,33 @@ Primitive Property Notes
|
||||
========= ==================== ===================
|
||||
|
||||
|
||||
Mol/SDF Support and Extensions
|
||||
==============================
|
||||
|
||||
The RDKit covers an extensive subset of the features in the V2000 and V3000 CTAB specfication.
|
||||
This subset should be better documented.
|
||||
|
||||
Here are the non-element atom queries that are supported:
|
||||
- A: any heavy atom
|
||||
- Q: any non-carbon heavy atom
|
||||
- *: unspecfied (interpreted as any atom)
|
||||
- L: (v2000): atom list
|
||||
- AH: (ChemAxon Extension) any atom
|
||||
- QH: (ChemAxon Extension) any non-carbon atom
|
||||
- X: (ChemAxon Extension) halogen
|
||||
- XH: (ChemAxon Extension) halogen or hydrogen
|
||||
- M: (ChemAxon Extension) metal ("contains alkali metals, alkaline earth metals, transition
|
||||
metals, actinides, lanthanides, poor(basic) metals, Ge, Sb, and Po")
|
||||
- MH: (ChemAxon Extension) metal or hydrogen
|
||||
|
||||
|
||||
Here's a partial list of the features that are supported:
|
||||
- enhanced stereochemistry (V3000 only)
|
||||
- Sgroups: Sgroups are read and written, but interpretation of their contents is still very much
|
||||
a work in progress
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Ring Finding and SSSR
|
||||
|
||||
Reference in New Issue
Block a user