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:
Greg Landrum
2020-07-03 18:51:19 +02:00
committed by GitHub
parent f4a85cf9cb
commit 1630540ef0
26 changed files with 415 additions and 227 deletions

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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";

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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");

View File

@@ -137,6 +137,7 @@ class RDKIT_GRAPHMOL_EXPORT MolPickler {
BEGINSTEREOGROUP,
BEGINCONFPROPS,
BEGINCONFS_DOUBLE,
QUERY_TYPELABEL,
} Tags;
static unsigned int getDefaultPickleProperties();

View File

@@ -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);

View File

@@ -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;
};
};

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -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);
}
}

View File

@@ -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;
};
};

View File

@@ -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);

View File

@@ -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;
};

View File

@@ -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;
};

View File

@@ -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;
};
};

View File

@@ -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;
}

View File

@@ -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";

View File

@@ -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

View File

@@ -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