mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-04 21:54:27 +08:00
* backup * update .gitignore * passes tests * all tests now pass * update release notes * cleanup * changes in response to review
8544 lines
279 KiB
C++
8544 lines
279 KiB
C++
//
|
|
// Copyright (C) 2002-2021 Greg Landrum and other RDKit contributors
|
|
//
|
|
// @@ 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 <algorithm>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <math.h>
|
|
#include <random>
|
|
|
|
#include <RDGeneral/test.h>
|
|
#include <RDGeneral/utils.h>
|
|
#include <RDGeneral/Invariant.h>
|
|
#include <RDGeneral/RDLog.h>
|
|
#include <GraphMol/RDKitBase.h>
|
|
#include <GraphMol/RDKitQueries.h>
|
|
#include <GraphMol/Chirality.h>
|
|
#include <GraphMol/SmilesParse/SmilesParse.h>
|
|
#include <GraphMol/SmilesParse/SmilesWrite.h>
|
|
#include <GraphMol/SmilesParse/SmartsWrite.h>
|
|
#include <GraphMol/FileParsers/FileParsers.h>
|
|
#include <GraphMol/FileParsers/MolSupplier.h>
|
|
#include <GraphMol/FileParsers/MolWriters.h>
|
|
#include <GraphMol/Substruct/SubstructMatch.h>
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846
|
|
#endif
|
|
|
|
using namespace RDKit;
|
|
using namespace std;
|
|
RWMol _t;
|
|
typedef class ROMol Mol;
|
|
|
|
void test1() {
|
|
string smi;
|
|
Mol *m;
|
|
INT_VECT iv;
|
|
unsigned int count;
|
|
std::vector<ROMOL_SPTR> frags;
|
|
|
|
smi = "CCCC(=O)O";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "smiles parse failed");
|
|
count = MolOps::getMolFrags(*m, iv);
|
|
CHECK_INVARIANT(count == 1, "bad frag count");
|
|
frags = MolOps::getMolFrags(*m);
|
|
CHECK_INVARIANT(frags.size() == 1, "bad frag count");
|
|
TEST_ASSERT(frags[0]->getNumAtoms() == 6);
|
|
delete m;
|
|
|
|
smi = "CCCC(=O)[O-].[Na+]";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "smiles parse failed");
|
|
count = MolOps::getMolFrags(*m, iv);
|
|
CHECK_INVARIANT(count == 2, "bad frag count");
|
|
frags = MolOps::getMolFrags(*m);
|
|
CHECK_INVARIANT(frags.size() == 2, "bad frag count");
|
|
TEST_ASSERT(frags[0]->getNumAtoms() == 6);
|
|
TEST_ASSERT(frags[1]->getNumAtoms() == 1);
|
|
frags = MolOps::getMolFrags(*m, true, &iv);
|
|
CHECK_INVARIANT(frags.size() == 2, "bad frag count");
|
|
TEST_ASSERT(frags[0]->getNumAtoms() == 6);
|
|
TEST_ASSERT(frags[1]->getNumAtoms() == 1);
|
|
TEST_ASSERT(iv.size() == 7);
|
|
TEST_ASSERT(iv[0] == 0)
|
|
TEST_ASSERT(iv[6] == 1)
|
|
delete m;
|
|
|
|
smi = "CCCC(=O)[O-].[Na+].[NH4+].[Cl-]";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "smiles parse failed");
|
|
count = MolOps::getMolFrags(*m, iv);
|
|
CHECK_INVARIANT(count == 4, "bad frag count");
|
|
frags = MolOps::getMolFrags(*m);
|
|
CHECK_INVARIANT(frags.size() == 4, "bad frag count");
|
|
TEST_ASSERT(frags[0]->getNumAtoms() == 6);
|
|
TEST_ASSERT(frags[1]->getNumAtoms() == 1);
|
|
TEST_ASSERT(frags[2]->getNumAtoms() == 1);
|
|
TEST_ASSERT(frags[3]->getNumAtoms() == 1);
|
|
delete m;
|
|
};
|
|
|
|
void test2() {
|
|
string smi;
|
|
Mol *m;
|
|
INT_VECT iv;
|
|
int count;
|
|
smi = "CCCC(=O)O";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "smiles parse failed");
|
|
count = MolOps::getMolFrags(*m, iv);
|
|
CHECK_INVARIANT(count == 1, "bad frag count");
|
|
CHECK_INVARIANT(iv[0] == 0, "bad frag membership");
|
|
CHECK_INVARIANT(iv[1] == 0, "bad frag membership");
|
|
CHECK_INVARIANT(iv[4] == 0, "bad frag membership");
|
|
CHECK_INVARIANT(iv[5] == 0, "bad frag membership");
|
|
delete m;
|
|
|
|
smi = "CCCC(=O)[O-].[Na+]";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "smiles parse failed");
|
|
count = MolOps::getMolFrags(*m, iv);
|
|
CHECK_INVARIANT(count == 2, "bad frag count");
|
|
CHECK_INVARIANT(iv[0] == 0, "bad frag membership");
|
|
CHECK_INVARIANT(iv[1] == 0, "bad frag membership");
|
|
CHECK_INVARIANT(iv[4] == 0, "bad frag membership");
|
|
CHECK_INVARIANT(iv[5] == 0, "bad frag membership");
|
|
CHECK_INVARIANT(iv[6] == 1, "bad frag membership");
|
|
delete m;
|
|
};
|
|
|
|
void test3() {
|
|
string smi;
|
|
Mol *m;
|
|
VECT_INT_VECT sssr;
|
|
INT_VECT rings;
|
|
int count;
|
|
|
|
smi = "C1CC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 1);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 1);
|
|
TEST_ASSERT(sssr[0].size() == 3);
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 1);
|
|
|
|
for (unsigned int i = 0; i < m->getNumAtoms(); i++) {
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(i, 3));
|
|
TEST_ASSERT(!m->getRingInfo()->isAtomInRingOfSize(i, 4));
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(i) == 1);
|
|
TEST_ASSERT(m->getRingInfo()->atomRingSizes(i) == (INT_VECT{3}));
|
|
TEST_ASSERT(m->getRingInfo()->atomMembers(i).size() == 1 &&
|
|
m->getRingInfo()->atomMembers(i).at(0) == 0);
|
|
}
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
TEST_ASSERT(m->getRingInfo()->isBondInRingOfSize(i, 3));
|
|
TEST_ASSERT(!m->getRingInfo()->isBondInRingOfSize(i, 4));
|
|
TEST_ASSERT(m->getRingInfo()->numBondRings(i) == 1);
|
|
TEST_ASSERT(m->getRingInfo()->bondRingSizes(i) == (INT_VECT{3}));
|
|
TEST_ASSERT(m->getRingInfo()->bondMembers(i).size() == 1 &&
|
|
m->getRingInfo()->bondMembers(i).at(0) == 0);
|
|
}
|
|
TEST_ASSERT(m->getRingInfo()->areAtomsInSameRing(0, 1));
|
|
TEST_ASSERT(m->getRingInfo()->areAtomsInSameRingOfSize(0, 1, 3));
|
|
TEST_ASSERT(!m->getRingInfo()->areAtomsInSameRingOfSize(0, 1, 4));
|
|
TEST_ASSERT(m->getRingInfo()->areBondsInSameRing(0, 1));
|
|
TEST_ASSERT(m->getRingInfo()->areBondsInSameRingOfSize(0, 1, 3));
|
|
TEST_ASSERT(!m->getRingInfo()->areBondsInSameRingOfSize(0, 1, 4));
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
delete m;
|
|
|
|
smi = "C1CCC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 1);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 1);
|
|
TEST_ASSERT(sssr[0].size() == 4);
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 1);
|
|
for (unsigned int i = 0; i < m->getNumAtoms(); i++) {
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(i, 4));
|
|
TEST_ASSERT(!m->getRingInfo()->isAtomInRingOfSize(i, 3));
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(i) == 1);
|
|
TEST_ASSERT(m->getRingInfo()->atomRingSizes(i) == (INT_VECT{4}));
|
|
TEST_ASSERT(m->getRingInfo()->atomMembers(i).size() == 1 &&
|
|
m->getRingInfo()->atomMembers(i).at(0) == 0);
|
|
}
|
|
TEST_ASSERT(m->getRingInfo()->isBondInRingOfSize(0, 4));
|
|
TEST_ASSERT(m->getRingInfo()->numBondRings(0) == 1);
|
|
TEST_ASSERT(m->getRingInfo()->bondRingSizes(0) == (INT_VECT{4}));
|
|
TEST_ASSERT(m->getRingInfo()->areBondsInSameRing(0, 1));
|
|
TEST_ASSERT(m->getRingInfo()->areBondsInSameRingOfSize(0, 1, 4));
|
|
TEST_ASSERT(!m->getRingInfo()->areBondsInSameRingOfSize(0, 1, 5));
|
|
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
delete m;
|
|
|
|
smi = "C1CCCCCC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 1);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 1);
|
|
TEST_ASSERT(sssr[0].size() == 7);
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 1);
|
|
for (unsigned int i = 0; i < m->getNumAtoms(); i++) {
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(i, 7));
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(i) == 1);
|
|
}
|
|
TEST_ASSERT(m->getRingInfo()->isBondInRingOfSize(0, 7));
|
|
TEST_ASSERT(m->getRingInfo()->numBondRings(0) == 1);
|
|
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
delete m;
|
|
|
|
smi = "C1C(CCC)CC(C(C)CCC(CC))CCC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 1);
|
|
TEST_ASSERT(sssr[0].size() == 7);
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(0) == 1);
|
|
TEST_ASSERT(
|
|
m->getRingInfo()->numBondRings(m->getBondBetweenAtoms(0, 1)->getIdx()));
|
|
TEST_ASSERT(m->getRingInfo()->atomMembers(0).size() == 1);
|
|
TEST_ASSERT(m->getRingInfo()->atomMembers(2).empty());
|
|
TEST_ASSERT(m->getRingInfo()->atomRingSizes(2).empty());
|
|
TEST_ASSERT(m->getRingInfo()->atomRingSizes(5) == (INT_VECT{7}));
|
|
TEST_ASSERT(m->getRingInfo()->atomRingSizes(1) == (INT_VECT{7}));
|
|
TEST_ASSERT(m->getRingInfo()->atomRingSizes(99).empty());
|
|
TEST_ASSERT(m->getRingInfo()->areAtomsInSameRing(0, 1));
|
|
TEST_ASSERT(m->getRingInfo()->areAtomsInSameRingOfSize(0, 1, 7));
|
|
TEST_ASSERT(!m->getRingInfo()->areAtomsInSameRingOfSize(0, 1, 5));
|
|
TEST_ASSERT(!m->getRingInfo()->areAtomsInSameRing(1, 2));
|
|
TEST_ASSERT(!m->getRingInfo()->areAtomsInSameRingOfSize(1, 2, 4));
|
|
TEST_ASSERT(m->getRingInfo()->bondRingSizes(1).empty());
|
|
TEST_ASSERT(m->getRingInfo()->bondRingSizes(4) == (INT_VECT{7}));
|
|
TEST_ASSERT(m->getRingInfo()->bondRingSizes(5) == (INT_VECT{7}));
|
|
TEST_ASSERT(m->getRingInfo()->bondRingSizes(99).empty());
|
|
TEST_ASSERT(m->getRingInfo()->bondMembers(0).size() == 1);
|
|
TEST_ASSERT(m->getRingInfo()->bondMembers(1).empty());
|
|
TEST_ASSERT(
|
|
!m->getRingInfo()->numBondRings(m->getBondBetweenAtoms(1, 2)->getIdx()));
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
delete m;
|
|
|
|
smi = "CC1CCC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 1);
|
|
TEST_ASSERT(sssr[0].size() == 4);
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(0, 1)->hasProp(
|
|
common_properties::ringMembership));
|
|
TEST_ASSERT(
|
|
!m->getRingInfo()->numBondRings(m->getBondBetweenAtoms(0, 1)->getIdx()));
|
|
TEST_ASSERT(
|
|
m->getRingInfo()->numBondRings(m->getBondBetweenAtoms(1, 2)->getIdx()));
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
delete m;
|
|
|
|
smi = "CC1C(C2)CCC2C1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 2)
|
|
TEST_ASSERT(sssr[0].size() == 5);
|
|
TEST_ASSERT(sssr[1].size() == 5);
|
|
TEST_ASSERT(!m->getRingInfo()->isAtomInRingOfSize(0, 5));
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(0) == 0);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(1, 5));
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(1) == 1);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(2, 5));
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(2) == 2);
|
|
TEST_ASSERT(m->getRingInfo()->atomRingSizes(0).empty());
|
|
TEST_ASSERT(m->getRingInfo()->atomRingSizes(1) == (INT_VECT{5}));
|
|
TEST_ASSERT(m->getRingInfo()->atomRingSizes(2) == (INT_VECT{5, 5}));
|
|
TEST_ASSERT(m->getRingInfo()->atomMembers(2).size() == 2);
|
|
TEST_ASSERT(m->getRingInfo()->atomMembers(2).at(0) == 0);
|
|
TEST_ASSERT(m->getRingInfo()->atomMembers(2).at(1) == 1);
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
delete m;
|
|
|
|
smi = "C(C1C2C3C41)(C2C35)C45"; // cubane
|
|
// smi = "C1(C2C3C4C5C6C72)C3C4C5C6C71"; // from Figureras paper
|
|
// smi = "C17C5C4C3C2C1C6C2C3C4C5C67";
|
|
// we cannot use the sanitization code, because that finds *symmetric*
|
|
// rings, which will break this case:
|
|
m = SmilesToMol(smi, 0, 0);
|
|
int bfs = MolOps::findSSSR(*m);
|
|
TEST_ASSERT(bfs == 5);
|
|
BOOST_LOG(rdInfoLog) << "BFSR: " << bfs << "\n";
|
|
VECT_INT_VECT bfrs;
|
|
bfrs.resize(0);
|
|
bfs = MolOps::symmetrizeSSSR(*m, bfrs);
|
|
TEST_ASSERT(bfs == 6);
|
|
BOOST_LOG(rdInfoLog) << "BFSR: " << bfs << "\n";
|
|
// VECT_INT_VECT_I ri;
|
|
// for (ri == bfrs.begin(); ri != bfrs.end(); ri++) {
|
|
for (auto bring : bfrs) {
|
|
INT_VECT_I mi;
|
|
BOOST_LOG(rdInfoLog) << "( ";
|
|
// for (mi = (*ri).begin(); mi != (*ri).end(); mi++) {
|
|
for (mi = bring.begin(); mi != bring.end(); mi++) {
|
|
BOOST_LOG(rdInfoLog) << " " << (*mi);
|
|
}
|
|
BOOST_LOG(rdInfoLog) << ")\n";
|
|
}
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
|
|
delete m;
|
|
|
|
// Figueras figure 4:
|
|
// * The third ring is bigger, and shouldn't be accessed in symmetrizeSSSR
|
|
smi = "C12CC(CC2)CC1";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
bfs = MolOps::findSSSR(*m);
|
|
TEST_ASSERT(bfs == 2);
|
|
bfrs.resize(0);
|
|
bfs = MolOps::symmetrizeSSSR(*m, bfrs);
|
|
TEST_ASSERT(bfs == 2);
|
|
delete m;
|
|
|
|
// Counterexamples in ring perception figure 4:
|
|
// * The native Figueras algorithm cannot work on this molecule, it will
|
|
// fail after finding one ring. Naive modified Figueras finds a 6 membered
|
|
// ring, which is wrong.
|
|
smi = "C123C4C5C6(C3)C7C1C8C2C4C5C6C78";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
bfs = MolOps::findSSSR(*m);
|
|
TEST_ASSERT(bfs == 7);
|
|
bfrs.resize(0);
|
|
bfs = MolOps::symmetrizeSSSR(*m, bfrs);
|
|
TEST_ASSERT(bfs == 8);
|
|
for (auto bring : bfrs) {
|
|
TEST_ASSERT(bring.size() < 6);
|
|
}
|
|
delete m;
|
|
|
|
smi = "C1CC2C1CCC2";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 2);
|
|
TEST_ASSERT(sssr[0].size() == 4);
|
|
TEST_ASSERT(sssr[1].size() == 5);
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
delete m;
|
|
|
|
smi = "C12=C3C=CC=C1C=CC2=CC=C3";
|
|
BOOST_LOG(rdInfoLog) << "\n" << smi << "\n";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 3);
|
|
TEST_ASSERT(sssr[0].size() == 6);
|
|
TEST_ASSERT(sssr[1].size() == 5);
|
|
TEST_ASSERT(sssr[2].size() == 6);
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
delete m;
|
|
|
|
smi = "C1(O)C(O)C(O)C1O";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 1);
|
|
TEST_ASSERT(sssr[0].size() == 4);
|
|
for (unsigned i = 0; i < m->getNumAtoms(); i++) {
|
|
if (!(i % 2)) {
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(i) == 1);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(i, 4));
|
|
} else {
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(i) == 0);
|
|
}
|
|
}
|
|
BOOST_LOG(rdInfoLog) << smi << "\n";
|
|
delete m;
|
|
|
|
// this molecule is from issue 134
|
|
// it should come up with three rings
|
|
smi = "SC(C3C1CC(C3)CC(C2S)(O)C1)2S";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 3);
|
|
TEST_ASSERT(sssr[0].size() == 5);
|
|
TEST_ASSERT(sssr[1].size() == 6);
|
|
TEST_ASSERT(sssr[2].size() == 6);
|
|
delete m;
|
|
|
|
// this yet another painful case
|
|
smi = "CC1=CC=C(C=C1)S(=O)(=O)O[CH]2[CH]3CO[CH](O3)[CH]4OC(C)(C)O[CH]24";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 4);
|
|
TEST_ASSERT(sssr[0].size() == 6);
|
|
TEST_ASSERT(sssr[1].size() == 5);
|
|
TEST_ASSERT(sssr[2].size() == 5);
|
|
TEST_ASSERT(sssr[3].size() == 6);
|
|
delete m;
|
|
|
|
smi = "C1CC2C1C2";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 2);
|
|
TEST_ASSERT(sssr[0].size() == 4);
|
|
TEST_ASSERT(sssr[1].size() == 3);
|
|
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(0) == 1);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(0, 4));
|
|
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(1) == 1);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(1, 4));
|
|
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(2) == 2);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(2, 3));
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(2, 4));
|
|
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(3) == 2);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(3, 4));
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(3, 3));
|
|
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(4) == 1);
|
|
TEST_ASSERT(!m->getRingInfo()->isAtomInRingOfSize(4, 4));
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(4, 3));
|
|
|
|
TEST_ASSERT(m->getRingInfo()->atomMembers(2).size() == 2);
|
|
TEST_ASSERT(m->getRingInfo()->areAtomsInSameRing(2, 3));
|
|
TEST_ASSERT(!m->getRingInfo()->areAtomsInSameRing(1, 4));
|
|
TEST_ASSERT(m->getRingInfo()->areAtomsInSameRingOfSize(2, 3, 3));
|
|
TEST_ASSERT(m->getRingInfo()->areAtomsInSameRingOfSize(2, 3, 4));
|
|
TEST_ASSERT(!m->getRingInfo()->areAtomsInSameRingOfSize(2, 3, 5));
|
|
TEST_ASSERT(m->getRingInfo()->bondMembers(2).size() == 2);
|
|
TEST_ASSERT(m->getRingInfo()->bondMembers(0).size() == 1);
|
|
TEST_ASSERT(m->getRingInfo()->areBondsInSameRing(1, 2));
|
|
TEST_ASSERT(m->getRingInfo()->areBondsInSameRing(2, 5));
|
|
TEST_ASSERT(!m->getRingInfo()->areBondsInSameRing(1, 3));
|
|
TEST_ASSERT(m->getRingInfo()->areBondsInSameRingOfSize(1, 2, 4));
|
|
TEST_ASSERT(m->getRingInfo()->areBondsInSameRingOfSize(2, 5, 3));
|
|
TEST_ASSERT(!m->getRingInfo()->areBondsInSameRingOfSize(1, 2, 3));
|
|
TEST_ASSERT(!m->getRingInfo()->areBondsInSameRingOfSize(1, 3, 4));
|
|
delete m;
|
|
|
|
// This is a test of Issue 217
|
|
smi = "C=C1C2CC1C2";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 2);
|
|
TEST_ASSERT(sssr[0].size() == 4);
|
|
TEST_ASSERT(sssr[1].size() == 4);
|
|
count = MolOps::symmetrizeSSSR(*m, sssr);
|
|
TEST_ASSERT(count == 3);
|
|
TEST_ASSERT(sssr[0].size() == 4);
|
|
TEST_ASSERT(sssr[1].size() == 4);
|
|
TEST_ASSERT(sssr[2].size() == 4);
|
|
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(0) == 0);
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(1) == 2);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(1, 4));
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(2) == 3);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(2, 4));
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(3) == 2);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(3, 4));
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(4) == 3);
|
|
TEST_ASSERT(m->getRingInfo()->isAtomInRingOfSize(4, 4));
|
|
delete m;
|
|
}
|
|
|
|
void test4() {
|
|
auto m = "C=C"_smiles;
|
|
TEST_ASSERT(m);
|
|
double *adjMat = MolOps::getAdjacencyMatrix(*m);
|
|
TEST_ASSERT(adjMat);
|
|
TEST_ASSERT(adjMat[0] == 0);
|
|
TEST_ASSERT(adjMat[1] == 1);
|
|
TEST_ASSERT(adjMat[2] == 1);
|
|
TEST_ASSERT(adjMat[3] == 0);
|
|
adjMat = MolOps::getAdjacencyMatrix(*m);
|
|
TEST_ASSERT(adjMat);
|
|
TEST_ASSERT(adjMat[0] == 0);
|
|
TEST_ASSERT(adjMat[1] == 1);
|
|
TEST_ASSERT(adjMat[2] == 1);
|
|
TEST_ASSERT(adjMat[3] == 0);
|
|
bool useBO = true;
|
|
adjMat = MolOps::getAdjacencyMatrix(*m, useBO);
|
|
TEST_ASSERT(adjMat);
|
|
TEST_ASSERT(adjMat[0] == 0);
|
|
TEST_ASSERT(adjMat[1] == 2.0);
|
|
TEST_ASSERT(adjMat[2] == 2.0);
|
|
TEST_ASSERT(adjMat[3] == 0);
|
|
}
|
|
|
|
void test5() {
|
|
string smi;
|
|
Mol *m;
|
|
VECT_INT_VECT sssr;
|
|
|
|
int count;
|
|
smi = "C1C4C5C3C(=O)C2C5C1C2C34";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
BOOST_LOG(rdInfoLog) << "Count: " << count << "\n";
|
|
CHECK_INVARIANT(count == 5, "");
|
|
delete m;
|
|
|
|
smi = "C1C(C2)CCC2C1";
|
|
m = SmilesToMol(smi);
|
|
count = MolOps::findSSSR(*m, sssr);
|
|
CHECK_INVARIANT(count == 2, "");
|
|
delete m;
|
|
}
|
|
|
|
/*
|
|
void test6(){
|
|
string smi;
|
|
Mol *m;
|
|
VECT_INT_VECT sssr;
|
|
|
|
int c1,c2;
|
|
smi = "C1(Cl)C(Cl)C1Cl";
|
|
m = SmilesToMol(smi);
|
|
INT_SET ringAtoms,ringBonds;
|
|
//boost::tie(c1,c2) = MolOps::findRingAtomsAndBonds(*m,ringAtoms,ringBonds);
|
|
|
|
CHECK_INVARIANT(c1==3,"bad nRingAtoms");
|
|
CHECK_INVARIANT(ringAtoms.count(0)==1,"bad RingAtoms");
|
|
CHECK_INVARIANT(ringAtoms.count(1)==0,"bad RingAtoms");
|
|
CHECK_INVARIANT(ringAtoms.count(2)==1,"bad RingAtoms");
|
|
CHECK_INVARIANT(ringAtoms.count(3)==0,"bad RingAtoms");
|
|
CHECK_INVARIANT(ringAtoms.count(4)==1,"bad RingAtoms");
|
|
CHECK_INVARIANT(ringAtoms.count(5)==0,"bad RingAtoms");
|
|
|
|
CHECK_INVARIANT(c2==3,"bad nRingBonds");
|
|
CHECK_INVARIANT(ringBonds.count(0)==0,"");
|
|
CHECK_INVARIANT(ringBonds.count(1)==1,"");
|
|
CHECK_INVARIANT(ringBonds.count(2)==0,"");
|
|
CHECK_INVARIANT(ringBonds.count(3)==1,"");
|
|
CHECK_INVARIANT(ringBonds.count(4)==0,"");
|
|
CHECK_INVARIANT(ringBonds.count(5)==1,"");
|
|
|
|
|
|
}
|
|
*/
|
|
|
|
void test7() {
|
|
#if 0
|
|
string smi;
|
|
Mol *m;
|
|
INT_VECT tree;
|
|
#if 1
|
|
smi = "C(CO)OCC";
|
|
m = SmilesToMol(smi);
|
|
MolOps::findSpanningTree(*m,tree);
|
|
CHECK_INVARIANT(tree.size()==5,"bad mst");
|
|
delete m;
|
|
|
|
smi = "C1CC1";
|
|
m = SmilesToMol(smi);
|
|
MolOps::findSpanningTree(*m,tree);
|
|
CHECK_INVARIANT(tree.size()==2,"bad mst");
|
|
delete m;
|
|
|
|
smi = "C1C=C1";
|
|
m = SmilesToMol(smi);
|
|
MolOps::findSpanningTree(*m,tree);
|
|
CHECK_INVARIANT(tree.size()==2,"bad mst");
|
|
CHECK_INVARIANT(std::find(tree.begin(),tree.end(),1)==tree.end(),"bogus idx in mst");
|
|
delete m;
|
|
#endif
|
|
|
|
smi = "C1C=CC=CC=1";
|
|
m = SmilesToMol(smi);
|
|
MolOps::findSpanningTree(*m,tree);
|
|
CHECK_INVARIANT(tree.size()==5,"bad mst");
|
|
delete m;
|
|
|
|
|
|
smi = "C1C(=CC1)";
|
|
m = SmilesToMol(smi);
|
|
MolOps::findSpanningTree(*m,tree);
|
|
CHECK_INVARIANT(tree.size()==3,"bad mst");
|
|
delete m;
|
|
|
|
|
|
smi = "C1C(C=C1)";
|
|
m = SmilesToMol(smi);
|
|
MolOps::findSpanningTree(*m,tree);
|
|
CHECK_INVARIANT(tree.size()==3,"bad mst");
|
|
delete m;
|
|
|
|
smi = "C1C(C2)CCC2C1";
|
|
m = SmilesToMol(smi);
|
|
MolOps::findSpanningTree(*m,tree);
|
|
CHECK_INVARIANT(tree.size()==6,"bad mst");
|
|
delete m;
|
|
|
|
smi = "C1C2CC3CCCCC3CC2CCC1";
|
|
m = SmilesToMol(smi);
|
|
MolOps::findSpanningTree(*m,tree);
|
|
CHECK_INVARIANT(tree.size()==13,"bad mst");
|
|
delete m;
|
|
#endif
|
|
}
|
|
|
|
void test8() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Hydrogen Ops"
|
|
<< std::endl;
|
|
ROMol *m, *m2, *m3;
|
|
INT_VECT tree;
|
|
|
|
std::string smi = "CCC";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 3, "");
|
|
|
|
// BOOST_LOG(rdInfoLog) << "1" << std::endl;
|
|
m2 = MolOps::addHs(*m);
|
|
CHECK_INVARIANT(m2->getNumAtoms() == 11, "");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "CC(=O)[OH]";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 4, "");
|
|
// BOOST_LOG(rdInfoLog) << "2" << std::endl;
|
|
|
|
m2 = MolOps::addHs(*m, true);
|
|
CHECK_INVARIANT(m2->getNumAtoms() == 5, "");
|
|
// BOOST_LOG(rdInfoLog) << "3" << std::endl;
|
|
m3 = MolOps::addHs(*m2, false);
|
|
CHECK_INVARIANT(m3->getNumAtoms() == 8, "");
|
|
delete m2;
|
|
delete m3;
|
|
// BOOST_LOG(rdInfoLog) << "4" << std::endl;
|
|
|
|
m2 = MolOps::addHs(*m, false);
|
|
CHECK_INVARIANT(m2->getNumAtoms() == 8, "");
|
|
delete m;
|
|
// remove all
|
|
// BOOST_LOG(rdInfoLog) << "5" << std::endl;
|
|
m3 = MolOps::removeHs(*m2, false);
|
|
CHECK_INVARIANT(m3->getNumAtoms() == 4, "");
|
|
delete m3;
|
|
|
|
// remove only implicit
|
|
// BOOST_LOG(rdInfoLog) << "6" << std::endl;
|
|
m3 = MolOps::removeHs(*m2, true);
|
|
CHECK_INVARIANT(m3->getNumAtoms() == 5, "");
|
|
// BOOST_LOG(rdInfoLog) << "7" << std::endl;
|
|
// remove all after removing only implicit
|
|
MolOps::removeHs(static_cast<RWMol &>(*m3), false);
|
|
CHECK_INVARIANT(m3->getNumAtoms() == 4, "");
|
|
delete m2;
|
|
delete m3;
|
|
|
|
// this test is also done in the same order in the python tests:
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 4, "");
|
|
m2 = MolOps::addHs(*m, true);
|
|
CHECK_INVARIANT(m2->getNumAtoms() == 5, "");
|
|
// BOOST_LOG(rdInfoLog) << "8" << std::endl;
|
|
m3 = MolOps::removeHs(*m2, true);
|
|
CHECK_INVARIANT(m3->getNumAtoms() == 5, "");
|
|
delete m3;
|
|
|
|
// BOOST_LOG(rdInfoLog) << "9" << std::endl;
|
|
m3 = MolOps::removeHs(*m2, false);
|
|
CHECK_INVARIANT(m3->getNumAtoms() == 4, "");
|
|
delete m2;
|
|
delete m3;
|
|
|
|
// BOOST_LOG(rdInfoLog) << "10" << std::endl;
|
|
m2 = MolOps::addHs(*m, false);
|
|
CHECK_INVARIANT(m2->getNumAtoms() == 8, "");
|
|
// BOOST_LOG(rdInfoLog) << "11" << std::endl;
|
|
m3 = MolOps::removeHs(*m2, true);
|
|
CHECK_INVARIANT(m3->getNumAtoms() == 5, "");
|
|
delete m3;
|
|
|
|
// BOOST_LOG(rdInfoLog) << "12" << std::endl;
|
|
m3 = MolOps::removeHs(*m2, false);
|
|
CHECK_INVARIANT(m3->getNumAtoms() == 4, "");
|
|
delete m3;
|
|
delete m2;
|
|
delete m;
|
|
|
|
// related to RDTrack Issues 109 and 110:
|
|
smi =
|
|
"C1C=C([C@H](N)C(=O)N[C@@]2([H])[C@]3([H])SC(C)(C)[C@@H](C(=O)O)N3C(=O)2)"
|
|
"C=CC=1";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 24, "");
|
|
// BOOST_LOG(rdInfoLog) << "13" << std::endl;
|
|
m3 = MolOps::removeHs(*m, false);
|
|
CHECK_INVARIANT(m3->getNumAtoms() == 24, "");
|
|
delete m;
|
|
delete m3;
|
|
|
|
// RDTrack Issue 130:
|
|
smi = "[H][N+]([H])([H])[H]";
|
|
m = SmilesToMol(smi, false, false);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 5, "");
|
|
// BOOST_LOG(rdInfoLog) << "14" << std::endl;
|
|
m2 = MolOps::removeHs(*m, 0, false);
|
|
CHECK_INVARIANT(m2->getNumAtoms() == 1, "");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "[H][N+]([H])([H])[H]";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 1, "");
|
|
|
|
delete m;
|
|
smi = "[H][H]";
|
|
m = SmilesToMol(smi, false, false);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 2, "");
|
|
// BOOST_LOG(rdInfoLog) << "15" << std::endl;
|
|
m2 = MolOps::removeHs(*m, 0, false);
|
|
CHECK_INVARIANT(m2->getNumAtoms() == 2, "");
|
|
delete m;
|
|
delete m2;
|
|
|
|
std::string sma;
|
|
smi = "C-C";
|
|
m = SmartsToMol(smi);
|
|
MolOps::sanitizeMol(*((RWMol *)m));
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
sma = SmartsWrite::GetAtomSmarts(
|
|
static_cast<const QueryAtom *>(m->getAtomWithIdx(0)));
|
|
TEST_ASSERT(sma == "C");
|
|
|
|
// BOOST_LOG(rdInfoLog) << "16" << std::endl;
|
|
m2 = MolOps::addHs(*m);
|
|
TEST_ASSERT(m2->getNumAtoms() == 8);
|
|
sma = SmartsWrite::GetAtomSmarts(
|
|
static_cast<const QueryAtom *>(m2->getAtomWithIdx(0)));
|
|
TEST_ASSERT(sma == "C");
|
|
delete m;
|
|
|
|
// BOOST_LOG(rdInfoLog) << "17" << std::endl;
|
|
m = MolOps::mergeQueryHs(*m2);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
sma = SmartsWrite::GetAtomSmarts(
|
|
static_cast<const QueryAtom *>(m->getAtomWithIdx(0)));
|
|
// BOOST_LOG(rdInfoLog) << "sma: " << sma<<std::endl;
|
|
// this was sf.net issue 3415204:
|
|
TEST_ASSERT(sma == "[C&!H0&!H1&!H2]");
|
|
delete m;
|
|
delete m2;
|
|
|
|
// RDTrack Issue 1228:
|
|
smi = "c1c[nH]cc1";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 5, "");
|
|
// BOOST_LOG(rdInfoLog) << "18" << std::endl;
|
|
m2 = MolOps::addHs(*m, false, false);
|
|
CHECK_INVARIANT(m2->getNumAtoms() == 10, "");
|
|
// BOOST_LOG(rdInfoLog) << "19" << std::endl;
|
|
delete m;
|
|
m = MolOps::removeHs(*m2);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 5, "");
|
|
delete m;
|
|
delete m2;
|
|
|
|
// labelling:
|
|
smi = "c1cn([H])cc1";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 5, "");
|
|
// BOOST_LOG(rdInfoLog) << "19" << std::endl;
|
|
m2 = MolOps::removeHs(*m);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 5, "");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "c1cn([2H])cc1";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 6, "");
|
|
// BOOST_LOG(rdInfoLog) << "19" << std::endl;
|
|
m2 = MolOps::removeHs(*m);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 6, "");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "CC[H]";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
m2 = MolOps::mergeQueryHs(*m);
|
|
TEST_ASSERT(m2->getNumAtoms() == 2);
|
|
TEST_ASSERT(!m->getAtomWithIdx(1)->hasQuery());
|
|
TEST_ASSERT(m2->getAtomWithIdx(1)->hasQuery());
|
|
delete m;
|
|
delete m2;
|
|
|
|
// sf.net issue 3415206
|
|
smi = "CO[H]";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
m2 = MolOps::mergeQueryHs(*m);
|
|
TEST_ASSERT(m2->getNumAtoms() == 2);
|
|
sma = SmartsWrite::GetAtomSmarts(
|
|
static_cast<const QueryAtom *>(m2->getAtomWithIdx(1)));
|
|
// BOOST_LOG(rdInfoLog) << "sma: " << sma<<std::endl;
|
|
TEST_ASSERT(sma == "[#8&!H0]");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "CN([H])[H]";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
m2 = MolOps::mergeQueryHs(*m);
|
|
TEST_ASSERT(m2->getNumAtoms() == 2);
|
|
sma = SmartsWrite::GetAtomSmarts(
|
|
static_cast<const QueryAtom *>(m2->getAtomWithIdx(1)));
|
|
// BOOST_LOG(rdInfoLog) << "sma: " << sma<<std::endl;
|
|
TEST_ASSERT(sma == "[#7&!H0&!H1]");
|
|
delete m;
|
|
delete m2;
|
|
|
|
{
|
|
// test the onlyOnAtoms option (github #758)
|
|
std::string smi = "CCC";
|
|
m = SmilesToMol(smi);
|
|
CHECK_INVARIANT(m, "");
|
|
CHECK_INVARIANT(m->getNumAtoms() == 3, "");
|
|
|
|
// BOOST_LOG(rdInfoLog) << "1" << std::endl;
|
|
UINT_VECT onlyOn;
|
|
onlyOn.push_back(0);
|
|
onlyOn.push_back(2);
|
|
m2 = MolOps::addHs(*m, false, false, &onlyOn);
|
|
CHECK_INVARIANT(m2->getNumAtoms() == 9, "");
|
|
CHECK_INVARIANT(m2->getAtomWithIdx(0)->getDegree() == 4, "");
|
|
CHECK_INVARIANT(m2->getAtomWithIdx(1)->getDegree() == 2, "");
|
|
CHECK_INVARIANT(m2->getAtomWithIdx(2)->getDegree() == 4, "");
|
|
delete m;
|
|
delete m2;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void test9() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing Distance Matrix Operations"
|
|
<< std::endl;
|
|
auto m = "CC=O"_smiles;
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
|
|
bool useBO = false;
|
|
bool useAtomWts = false;
|
|
double *dMat;
|
|
dMat = MolOps::getDistanceMat(*m, useBO, useAtomWts);
|
|
TEST_ASSERT(dMat);
|
|
TEST_ASSERT(dMat[0] == 0.0);
|
|
TEST_ASSERT(dMat[1] == 1.0);
|
|
TEST_ASSERT(dMat[2] == 2.0);
|
|
TEST_ASSERT(dMat[3] == 1.0);
|
|
TEST_ASSERT(dMat[4] == 0.0);
|
|
TEST_ASSERT(dMat[5] == 1.0);
|
|
TEST_ASSERT(dMat[6] == 2.0);
|
|
TEST_ASSERT(dMat[7] == 1.0);
|
|
TEST_ASSERT(dMat[8] == 0.0);
|
|
|
|
dMat = MolOps::getDistanceMat(*m, useBO, useAtomWts);
|
|
TEST_ASSERT(dMat);
|
|
TEST_ASSERT(dMat[0] == 0.0);
|
|
TEST_ASSERT(dMat[1] == 1.0);
|
|
TEST_ASSERT(dMat[2] == 2.0);
|
|
TEST_ASSERT(dMat[3] == 1.0);
|
|
TEST_ASSERT(dMat[4] == 0.0);
|
|
TEST_ASSERT(dMat[5] == 1.0);
|
|
TEST_ASSERT(dMat[6] == 2.0);
|
|
TEST_ASSERT(dMat[7] == 1.0);
|
|
TEST_ASSERT(dMat[8] == 0.0);
|
|
|
|
// test Issue328:
|
|
useBO = true;
|
|
dMat = MolOps::getDistanceMat(*m, useBO, useAtomWts);
|
|
TEST_ASSERT(dMat);
|
|
TEST_ASSERT(dMat[0] == 0.0);
|
|
TEST_ASSERT(dMat[1] == 1.0);
|
|
TEST_ASSERT(dMat[2] == 1.5);
|
|
TEST_ASSERT(dMat[3] == 1.0);
|
|
TEST_ASSERT(dMat[4] == 0.0);
|
|
TEST_ASSERT(dMat[5] == 0.5);
|
|
TEST_ASSERT(dMat[6] == 1.5);
|
|
TEST_ASSERT(dMat[7] == 0.5);
|
|
TEST_ASSERT(dMat[8] == 0.0);
|
|
|
|
useBO = false;
|
|
dMat = MolOps::getDistanceMat(*m, useBO, useAtomWts);
|
|
TEST_ASSERT(dMat);
|
|
TEST_ASSERT(dMat[0] == 0.0);
|
|
TEST_ASSERT(dMat[1] == 1.0);
|
|
TEST_ASSERT(dMat[2] == 2.0);
|
|
TEST_ASSERT(dMat[3] == 1.0);
|
|
TEST_ASSERT(dMat[4] == 0.0);
|
|
TEST_ASSERT(dMat[5] == 1.0);
|
|
TEST_ASSERT(dMat[6] == 2.0);
|
|
TEST_ASSERT(dMat[7] == 1.0);
|
|
TEST_ASSERT(dMat[8] == 0.0);
|
|
|
|
useBO = false;
|
|
useAtomWts = true;
|
|
dMat = MolOps::getDistanceMat(*m, useBO, useAtomWts);
|
|
TEST_ASSERT(dMat);
|
|
for (unsigned int i = 0; i < m->getNumAtoms(); ++i) {
|
|
for (unsigned int j = 0; j < m->getNumAtoms(); ++j) {
|
|
std::cerr << dMat[i * m->getNumAtoms() + j] << " ";
|
|
}
|
|
std::cerr << std::endl;
|
|
}
|
|
TEST_ASSERT(dMat[0] == 1.0);
|
|
TEST_ASSERT(dMat[1] == 1.0);
|
|
TEST_ASSERT(dMat[2] == 2.0);
|
|
TEST_ASSERT(dMat[3] == 1.0);
|
|
TEST_ASSERT(dMat[4] == 1.0);
|
|
TEST_ASSERT(dMat[5] == 1.0);
|
|
TEST_ASSERT(dMat[6] == 2.0);
|
|
TEST_ASSERT(dMat[7] == 1.0);
|
|
TEST_ASSERT(dMat[8] == 6. / 8.);
|
|
|
|
useBO = true;
|
|
useAtomWts = true;
|
|
dMat = MolOps::getDistanceMat(*m, useBO, useAtomWts);
|
|
TEST_ASSERT(dMat);
|
|
TEST_ASSERT(dMat[0] == 1.0);
|
|
TEST_ASSERT(dMat[1] == 1.0);
|
|
TEST_ASSERT(dMat[2] == 1.5);
|
|
TEST_ASSERT(dMat[3] == 1.0);
|
|
TEST_ASSERT(dMat[4] == 1.0);
|
|
TEST_ASSERT(dMat[5] == 0.5);
|
|
TEST_ASSERT(dMat[6] == 1.5);
|
|
TEST_ASSERT(dMat[7] == 0.5);
|
|
TEST_ASSERT(dMat[8] == 6. / 8.);
|
|
|
|
useBO = false;
|
|
useAtomWts = false;
|
|
dMat = MolOps::getDistanceMat(*m, useBO, useAtomWts);
|
|
TEST_ASSERT(dMat);
|
|
TEST_ASSERT(dMat[0] == 0.0);
|
|
TEST_ASSERT(dMat[1] == 1.0);
|
|
TEST_ASSERT(dMat[2] == 2.0);
|
|
TEST_ASSERT(dMat[3] == 1.0);
|
|
TEST_ASSERT(dMat[4] == 0.0);
|
|
TEST_ASSERT(dMat[5] == 1.0);
|
|
TEST_ASSERT(dMat[6] == 2.0);
|
|
TEST_ASSERT(dMat[7] == 1.0);
|
|
TEST_ASSERT(dMat[8] == 0.0);
|
|
|
|
// limit participating atoms and bonds
|
|
std::vector<int> activeAtoms = {1, 2};
|
|
std::vector<const Bond *> activeBonds = {m->getBondWithIdx(1)};
|
|
useBO = false;
|
|
useAtomWts = false;
|
|
std::unique_ptr<double[]> dMat2{
|
|
MolOps::getDistanceMat(*m, activeAtoms, activeBonds, useBO, useAtomWts)};
|
|
TEST_ASSERT(dMat2);
|
|
TEST_ASSERT(dMat2[0] == 0.0);
|
|
TEST_ASSERT(dMat2[1] == 1.0);
|
|
TEST_ASSERT(dMat2[2] == 1.0);
|
|
TEST_ASSERT(dMat2[3] == 0.0);
|
|
|
|
useBO = true;
|
|
useAtomWts = true;
|
|
dMat2.reset(
|
|
MolOps::getDistanceMat(*m, activeAtoms, activeBonds, useBO, useAtomWts));
|
|
TEST_ASSERT(dMat2);
|
|
TEST_ASSERT(dMat2[0] == 1.0);
|
|
TEST_ASSERT(dMat2[1] == 0.5);
|
|
TEST_ASSERT(dMat2[2] == 0.5);
|
|
TEST_ASSERT(dMat2[3] == 6.0 / 8.0);
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void test10() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Atom Ranking"
|
|
<< std::endl;
|
|
ROMol *m;
|
|
std::string smi = "FC(Cl)(Br)C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
|
|
UINT_VECT ranks;
|
|
ranks.resize(m->getNumAtoms());
|
|
Chirality::assignAtomCIPRanks(*m, ranks);
|
|
|
|
unsigned int cip1, cip2;
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPRank, cip1);
|
|
TEST_ASSERT(cip1 == ranks[0]);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPRank, cip2);
|
|
TEST_ASSERT(cip2 == ranks[2]);
|
|
TEST_ASSERT(cip1 < cip2);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(4)->getProp(common_properties::_CIPRank, cip2);
|
|
TEST_ASSERT(cip1 > cip2);
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPRank, cip1);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(3)->getProp(common_properties::_CIPRank, cip2);
|
|
TEST_ASSERT(cip1 < cip2);
|
|
|
|
delete m;
|
|
smi = "FC(Cl)(Br)C(F)(F)F";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
ranks.resize(m->getNumAtoms());
|
|
Chirality::assignAtomCIPRanks(*m, ranks);
|
|
for (unsigned int i = 0; i < m->getNumAtoms(); i++) {
|
|
unsigned int cip;
|
|
TEST_ASSERT(m->getAtomWithIdx(i)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(i)->getProp(common_properties::_CIPRank, cip);
|
|
}
|
|
delete m;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void test11() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing CIP chirality"
|
|
<< std::endl;
|
|
ROMol *m;
|
|
std::string cip;
|
|
std::string smi = "F[C@]([C@])(Cl)Br";
|
|
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
// make sure the cleanup worked:
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
|
|
TEST_ASSERT(!(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode)));
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
TEST_ASSERT(!(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode)));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "F[C@H](C)C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(!(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode)));
|
|
TEST_ASSERT(!(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode)));
|
|
TEST_ASSERT(!(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode)));
|
|
// test Issue 194:
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNumExplicitHs() == 0);
|
|
|
|
delete m;
|
|
smi = "F[C@]1CC(Cl)C1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(!(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode)));
|
|
|
|
delete m;
|
|
smi = "F[C@H]1C(Cl)CC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
|
|
delete m;
|
|
smi = "F[C@@](C)(Cl)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(!(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode)));
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
TEST_ASSERT(!(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode)));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
delete m;
|
|
smi = "F[C@](Br)(C)Cl";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
delete m;
|
|
smi = "F[C@](Cl)(Br)C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "FC(F)(F)[C@](Br)(F)C(Cl)(Cl)Cl";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(4)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "C[C@](C=C)(F)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
delete m;
|
|
smi = "CC[C@](C=C)(F)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
delete m;
|
|
std::cerr << "-------------------------------" << std::endl;
|
|
smi = "[CH2-][C@](C)(F)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
delete m;
|
|
smi = "F[C@]([H])(Cl)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "[C@H](Cl)(F)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "[C@]([H])(Cl)(F)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "F[C@H](Cl)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "CC[C@H](C=C)C";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "OC[C@H](C=C)C";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
delete m;
|
|
smi = "CC[C@H](C=C)O";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "OC[C@H](C=C)O";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
delete m;
|
|
smi = "C[C@H]1C[C@H](C=C1)N";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(3)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
// a couple random molecules from the BBB data set
|
|
delete m;
|
|
smi = "OC[C@H]1C[C@@H](N2C=NC3=C2N=C(N)N=C3NC4CC4)C=C1";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(4)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
delete m;
|
|
smi = "N[C@H]1O[C@@H](SC1)CO";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(3)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
delete m;
|
|
smi = "C1(N([C@H]2O[C@H](CO)SC2)C=CC(N)=N1)=O";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(4)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
// this is Issue 152:
|
|
smi = "C1[C@H](N)C[C@H](C)C=1";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(4)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
// -----------------------------------------------
|
|
// these are related to Issue 397:
|
|
smi = "C(=O)[C@@H](C)N";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
smi = "C(=O)[C@@H](CO)N";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
smi = "C(O)[C@@H](C)N";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
// -----------------------------------------------
|
|
|
|
// NOTE: This test gives correct results according to the current
|
|
// CIP ranking procedure, but the results are actually incorrect.
|
|
// This arises because of the inclusion of hybridization in the
|
|
// chiral atom invariants
|
|
// (see the note in Chirality.cpp:buildCIPInvariants())
|
|
smi = "[H][C@@](O)(C=C)C(C)CC";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
smi = "[H][C@@](O)(C=C)C(C)CO";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
|
|
smi = "[H][C@@]12C[C@@](NC1)(OC2)[H]";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
smi = "[H][C@@]12C[C@@](C=C1)(CC2)[H]";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
smi = "[H][C@@]12O[C@@](CC1)(C3C2C(NC3=O)=O)[H]";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
|
|
smi = "[H][C@@]12O[C@@](C=C1)(C3C2C(NC3=O)=O)[H]";
|
|
#ifdef VERBOSE_CANON
|
|
BOOST_LOG(rdDebugLog) << " ----------------- ------------- ----------------"
|
|
<< std::endl;
|
|
BOOST_LOG(rdDebugLog) << "\t>" << smi << std::endl;
|
|
#endif
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
delete m;
|
|
// -----------------------------------------------
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void test12() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing double bond stereochemistry"
|
|
<< std::endl;
|
|
ROMol *m;
|
|
RWMol *m2;
|
|
std::string smi = "F\\C=C/Cl";
|
|
std::string refSmi;
|
|
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getStereo() == Bond::STEREONONE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereo() == Bond::STEREONONE);
|
|
|
|
delete m;
|
|
smi = "F/C=CCl";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREONONE);
|
|
|
|
delete m;
|
|
smi = "F/C=C/Cl";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREOE);
|
|
|
|
delete m;
|
|
smi = "F/C=C(/Br)Cl";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREOE);
|
|
|
|
delete m;
|
|
smi = "F/C=C(/Cl)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREOZ);
|
|
|
|
delete m;
|
|
smi = "F/C(Br)=C/Cl";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereo() == Bond::STEREOZ);
|
|
|
|
delete m;
|
|
smi = "F/C=C(/Cl)Cl";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREONONE);
|
|
|
|
// build a molecule from scratch to test problems
|
|
// around Issue 180. The molecule corresponds to SMILES
|
|
// F/C=C(/Br)C
|
|
delete m;
|
|
m2 = new RWMol();
|
|
m2->addAtom(new Atom(9), true, true);
|
|
m2->addAtom(new Atom(6), true, true);
|
|
m2->addAtom(new Atom(6), true, true);
|
|
m2->addAtom(new Atom(35), true, true);
|
|
m2->addAtom(new Atom(6), true, true);
|
|
m2->addBond(0, 1, Bond::SINGLE);
|
|
m2->addBond(1, 2, Bond::DOUBLE);
|
|
m2->addBond(2, 3, Bond::SINGLE);
|
|
m2->addBond(2, 4, Bond::SINGLE);
|
|
m2->getBondWithIdx(0)->setBondDir(Bond::ENDUPRIGHT);
|
|
m2->getBondWithIdx(2)->setBondDir(Bond::ENDUPRIGHT);
|
|
m2->getBondWithIdx(3)->setBondDir(Bond::ENDDOWNRIGHT);
|
|
MolOps::sanitizeMol(*m2);
|
|
MolOps::assignStereochemistry(*m2);
|
|
TEST_ASSERT(m2->getBondWithIdx(1)->getStereo() == Bond::STEREOE);
|
|
|
|
m2->getBondWithIdx(0)->setBondDir(Bond::ENDDOWNRIGHT);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getBondWithIdx(1)->getStereo() == Bond::STEREOZ);
|
|
|
|
delete m2;
|
|
m2 = new RWMol();
|
|
m2->addAtom(new Atom(9), true, true);
|
|
m2->addAtom(new Atom(6), true, true);
|
|
m2->addAtom(new Atom(6), true, true);
|
|
m2->addAtom(new Atom(35), true, true);
|
|
m2->addAtom(new Atom(6), true, true);
|
|
m2->addBond(1, 0, Bond::SINGLE);
|
|
m2->addBond(1, 2, Bond::DOUBLE);
|
|
m2->addBond(2, 3, Bond::SINGLE);
|
|
m2->addBond(2, 4, Bond::SINGLE);
|
|
m2->getBondWithIdx(0)->setBondDir(Bond::ENDUPRIGHT);
|
|
m2->getBondWithIdx(2)->setBondDir(Bond::ENDUPRIGHT);
|
|
m2->getBondWithIdx(3)->setBondDir(Bond::ENDDOWNRIGHT);
|
|
MolOps::sanitizeMol(*m2);
|
|
MolOps::assignStereochemistry(*m2);
|
|
TEST_ASSERT(m2->getBondWithIdx(1)->getStereo() == Bond::STEREOZ);
|
|
|
|
m2->getBondWithIdx(0)->setBondDir(Bond::ENDDOWNRIGHT);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getBondWithIdx(1)->getStereo() == Bond::STEREOE);
|
|
|
|
// ----------------------
|
|
// test Issue 174:
|
|
delete m2;
|
|
smi = "O\\N=C\\C=N/O";
|
|
m2 = SmilesToMol(smi);
|
|
TEST_ASSERT(m2);
|
|
TEST_ASSERT(m2->getBondWithIdx(1)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m2->getBondWithIdx(3)->getStereo() == Bond::STEREOZ);
|
|
refSmi = MolToSmiles(*m2, 1);
|
|
m = SmilesToMol(refSmi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m, 1);
|
|
TEST_ASSERT(refSmi == smi);
|
|
|
|
delete m;
|
|
delete m2;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testIssue183() {
|
|
// ----------------------
|
|
// test "unsetting" of redundant bond directions:
|
|
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Issue 183\n"
|
|
<< std::endl;
|
|
RWMol *m, *m2;
|
|
std::string smi;
|
|
std::string refSmi;
|
|
|
|
smi = "Cl\\C(C)=C(\\C(F)=C(/F)C)/C(C)=C(\\F)C";
|
|
m2 = SmilesToMol(smi);
|
|
TEST_ASSERT(m2);
|
|
TEST_ASSERT(m2->getBondWithIdx(2)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m2->getBondWithIdx(5)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m2->getBondWithIdx(10)->getStereo() == Bond::STEREOZ);
|
|
|
|
// m2->debugMol(std::cerr);
|
|
refSmi = MolToSmiles(*m2, 1);
|
|
BOOST_LOG(rdInfoLog) << "ref: " << refSmi << std::endl;
|
|
m = SmilesToMol(refSmi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m, 1);
|
|
BOOST_LOG(rdInfoLog) << "smi: " << smi << std::endl;
|
|
TEST_ASSERT(refSmi == smi);
|
|
|
|
int nEs = 0, nZs = 0, nDbl = 0;
|
|
for (RWMol::BondIterator bondIt = m->beginBonds(); bondIt != m->endBonds();
|
|
bondIt++) {
|
|
if ((*bondIt)->getBondType() == Bond::DOUBLE) {
|
|
nDbl++;
|
|
if ((*bondIt)->getStereo() == Bond::STEREOE) {
|
|
nEs++;
|
|
} else if ((*bondIt)->getStereo() == Bond::STEREOZ) {
|
|
nZs++;
|
|
}
|
|
}
|
|
}
|
|
// BOOST_LOG(rdInfoLog) << ">> " << nDbl << " " << nEs << " " << nZs <<
|
|
// std::endl;
|
|
TEST_ASSERT(nDbl == 3);
|
|
TEST_ASSERT(nEs == 2);
|
|
TEST_ASSERT(nZs == 1);
|
|
delete m;
|
|
delete m2;
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testIssue188() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing Issue 188: bad CIP rankings"
|
|
<< std::endl;
|
|
ROMol *m;
|
|
std::string smi;
|
|
unsigned int cip1, cip2, cip3;
|
|
|
|
smi = "OC[C@H](C=C)C";
|
|
m = SmilesToMol(smi);
|
|
UINT_VECT ranks;
|
|
ranks.resize(m->getNumAtoms());
|
|
Chirality::assignAtomCIPRanks(*m, ranks);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPRank, cip1);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(3)->getProp(common_properties::_CIPRank, cip2);
|
|
TEST_ASSERT(cip1 > cip2);
|
|
TEST_ASSERT(m->getAtomWithIdx(5)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(5)->getProp(common_properties::_CIPRank, cip3);
|
|
TEST_ASSERT(cip1 > cip3);
|
|
TEST_ASSERT(cip2 > cip3);
|
|
|
|
delete m;
|
|
smi = "CC(=N\\N)/C=N/N";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
ranks.resize(m->getNumAtoms());
|
|
Chirality::assignAtomCIPRanks(*m, ranks);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPRank, cip1);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPRank, cip2);
|
|
TEST_ASSERT(cip2 > cip1);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->hasProp(common_properties::_CIPRank));
|
|
m->getAtomWithIdx(4)->getProp(common_properties::_CIPRank, cip3);
|
|
TEST_ASSERT(cip3 > cip1);
|
|
TEST_ASSERT(cip2 > cip3);
|
|
delete m;
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testIssue189() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Issue 189: "
|
|
"BondDirs not getting properly cleared."
|
|
<< std::endl;
|
|
ROMol *m;
|
|
std::string smi, refSmi;
|
|
int count;
|
|
|
|
smi = "C(=S)/N=c(/n1C)scc1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereo() == Bond::STEREOZ);
|
|
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 2);
|
|
|
|
refSmi = MolToSmiles(*m, 1);
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 2);
|
|
|
|
delete m;
|
|
m = SmilesToMol(refSmi);
|
|
TEST_ASSERT(m);
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 2);
|
|
smi = MolToSmiles(*m, 1);
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 2);
|
|
TEST_ASSERT(smi == refSmi);
|
|
|
|
delete m;
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testIssue190() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Issue 190: "
|
|
"BondDirs incorrectly cleared."
|
|
<< std::endl;
|
|
ROMol *m;
|
|
std::string smi, refSmi;
|
|
int count;
|
|
|
|
smi = "O\\N=C\\NC(\\C)=N/OC";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getStereo() == Bond::STEREOZ);
|
|
refSmi = MolToSmiles(*m, 1);
|
|
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 4);
|
|
|
|
delete m;
|
|
m = SmilesToMol(refSmi);
|
|
TEST_ASSERT(m);
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 4);
|
|
smi = MolToSmiles(*m, 1);
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 4);
|
|
TEST_ASSERT(smi == refSmi);
|
|
|
|
delete m;
|
|
smi = "O\\N=C\\CC(\\C)=N/OC";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getStereo() == Bond::STEREOZ);
|
|
refSmi = MolToSmiles(*m, 1);
|
|
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 4);
|
|
delete m;
|
|
m = SmilesToMol(refSmi);
|
|
TEST_ASSERT(m);
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 4);
|
|
smi = MolToSmiles(*m, 1);
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 4);
|
|
TEST_ASSERT(smi == refSmi);
|
|
|
|
delete m;
|
|
smi = "O\\N=C\\C(=O)C(\\C)=N/OC";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondWithIdx(6)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(6)->getStereo() == Bond::STEREOZ);
|
|
refSmi = MolToSmiles(*m, 1);
|
|
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 4);
|
|
delete m;
|
|
m = SmilesToMol(refSmi);
|
|
TEST_ASSERT(m);
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 4);
|
|
smi = MolToSmiles(*m, 1);
|
|
count = 0;
|
|
for (unsigned int i = 0; i < m->getNumBonds(); i++) {
|
|
if (m->getBondWithIdx(i)->getBondDir() != Bond::NONE) {
|
|
count++;
|
|
}
|
|
}
|
|
TEST_ASSERT(count == 4);
|
|
TEST_ASSERT(smi == refSmi);
|
|
|
|
delete m;
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testShortestPath() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing shortest path "
|
|
"code. This should finish very quickly."
|
|
<< std::endl;
|
|
{
|
|
std::string smi = "CC(OC1C(CCCC3)C3C(CCCC2)C2C1OC(C)=O)=O";
|
|
ROMol *m = SmilesToMol(smi);
|
|
|
|
INT_LIST path = MolOps::getShortestPath(*m, 1, 20);
|
|
CHECK_INVARIANT(path.size() == 7, "");
|
|
INT_LIST_CI pi = path.begin();
|
|
CHECK_INVARIANT((*pi) == 1, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 2, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 3, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 16, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 17, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 18, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 20, "");
|
|
pi++;
|
|
delete m;
|
|
}
|
|
{
|
|
// issue 2219400
|
|
std::string smi = "CC.C";
|
|
ROMol *m = SmilesToMol(smi);
|
|
|
|
INT_LIST path = MolOps::getShortestPath(*m, 0, 1);
|
|
std::cerr << "path: " << path.size() << std::endl;
|
|
CHECK_INVARIANT(path.size() == 2, "");
|
|
INT_LIST_CI pi = path.begin();
|
|
CHECK_INVARIANT((*pi) == 0, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 1, "");
|
|
|
|
path = MolOps::getShortestPath(*m, 1, 2);
|
|
CHECK_INVARIANT(path.size() == 0, "");
|
|
|
|
path = MolOps::getShortestPath(*m, 0, 2);
|
|
CHECK_INVARIANT(path.size() == 0, "");
|
|
delete m;
|
|
}
|
|
// fused ring test
|
|
{
|
|
std::string smi = "[H]c1nc2c(C(=O)N([H])C2([H])Cl)c([H])c1Cl";
|
|
ROMol *m = SmilesToMol(smi);
|
|
|
|
INT_LIST path = MolOps::getShortestPath(*m, 8, 11);
|
|
CHECK_INVARIANT(path.size() == 7, "");
|
|
INT_LIST_CI pi = path.begin();
|
|
CHECK_INVARIANT((*pi) == 8, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 7, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 2, "");
|
|
pi++;
|
|
pi++; // two equally long routes here
|
|
pi++; // two equally long routes here
|
|
CHECK_INVARIANT((*pi) == 10, "");
|
|
pi++;
|
|
CHECK_INVARIANT((*pi) == 11, "");
|
|
pi++;
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testIssue210() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Issue 210"
|
|
<< std::endl;
|
|
ROMol *m, *m2;
|
|
|
|
std::string smi = "C1CC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
TEST_ASSERT(m->getRingInfo()->isInitialized());
|
|
|
|
m2 = MolOps::addHs(*m);
|
|
TEST_ASSERT(m2->getNumAtoms() == 9);
|
|
TEST_ASSERT(m2->getRingInfo()->isInitialized());
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
delete m;
|
|
delete m2;
|
|
}
|
|
|
|
void testIssue211() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Issue 211"
|
|
<< std::endl;
|
|
ROMol *m;
|
|
|
|
std::string smi = "P(c1ccccc1)(c1ccccc1)c1ccccc1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 19);
|
|
|
|
const Atom *at = m->getAtomWithIdx(0);
|
|
TEST_ASSERT(at->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testIssue212() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Issue 212"
|
|
<< std::endl;
|
|
ROMol *m, *m2;
|
|
std::string smi, mb;
|
|
smi = "C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 1);
|
|
auto *conf = new Conformer(1);
|
|
m->addConformer(conf);
|
|
conf->setAtomPos(0, RDGeom::Point3D(0, 0, 0));
|
|
m2 = MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m2->getNumAtoms() == 5);
|
|
|
|
try {
|
|
mb = MolToMolBlock(*m2);
|
|
} catch (...) {
|
|
TEST_ASSERT(0); //,"MolToMolBlock() failed");
|
|
}
|
|
|
|
delete m;
|
|
delete m2;
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testAddHsCoords() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing AddHs with coordinates"
|
|
<< std::endl;
|
|
ROMol *m, *m2;
|
|
RDGeom::Point3D v;
|
|
double bondLength = PeriodicTable::getTable()->getRb0(1) +
|
|
PeriodicTable::getTable()->getRb0(6);
|
|
double tetDist = 2. * sin((109.471 / 2.) * M_PI / 180) * bondLength;
|
|
double sp2Dist = 2. * sin(60. * M_PI / 180) * bondLength;
|
|
|
|
std::string smi;
|
|
|
|
smi = "C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 1);
|
|
auto *conf = new Conformer(1);
|
|
m->addConformer(conf);
|
|
conf->setAtomPos(0, RDGeom::Point3D(0, 0, 0));
|
|
|
|
m2 = MolOps::addHs(*m, false, true);
|
|
const Conformer *conf2 = &(m2->getConformer());
|
|
TEST_ASSERT(m2->getNumAtoms() == 5);
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(1)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(2)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(3)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(4)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(1) - conf2->getAtomPos(2)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(1) - conf2->getAtomPos(3)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(1) - conf2->getAtomPos(4)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(2) - conf2->getAtomPos(3)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(2) - conf2->getAtomPos(4)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(3) - conf2->getAtomPos(4)).length(), tetDist));
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "CC";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
conf = new Conformer(2);
|
|
m->addConformer(conf);
|
|
conf->setAtomPos(0, RDGeom::Point3D(0, 0, 0));
|
|
conf->setAtomPos(1, RDGeom::Point3D(1.54, 0, 0));
|
|
|
|
m2 = MolOps::addHs(*m, false, true);
|
|
conf2 = &(m2->getConformer());
|
|
TEST_ASSERT(m2->getNumAtoms() == 8);
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(2)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(3)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(4)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(2) - conf2->getAtomPos(3)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(2) - conf2->getAtomPos(4)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(3) - conf2->getAtomPos(4)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(1) - conf2->getAtomPos(5)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(1) - conf2->getAtomPos(6)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(1) - conf2->getAtomPos(7)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(5) - conf2->getAtomPos(6)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(5) - conf2->getAtomPos(7)).length(), tetDist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(6) - conf2->getAtomPos(7)).length(), tetDist));
|
|
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "C=C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
conf = new Conformer(2);
|
|
m->addConformer(conf);
|
|
conf->setAtomPos(0, RDGeom::Point3D(0, 0, 0));
|
|
conf->setAtomPos(1, RDGeom::Point3D(1.3, 0, 0));
|
|
|
|
m2 = MolOps::addHs(*m, false, true);
|
|
|
|
conf2 = &(m2->getConformer());
|
|
|
|
TEST_ASSERT(m2->getNumAtoms() == 6);
|
|
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(2)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(3)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(1) - conf2->getAtomPos(4)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(1) - conf2->getAtomPos(5)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(2) - conf2->getAtomPos(3)).length(), sp2Dist));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(4) - conf2->getAtomPos(5)).length(), sp2Dist));
|
|
delete m;
|
|
delete m2;
|
|
|
|
{
|
|
// make sure Hs are on the xy plane if conformer is 2D
|
|
auto m = "C=C"_smiles;
|
|
TEST_ASSERT(m.get());
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
conf = new Conformer(2);
|
|
m->addConformer(conf);
|
|
conf->setAtomPos(0, RDGeom::Point3D(0, 0, 0));
|
|
conf->setAtomPos(1, RDGeom::Point3D(1.3, 0, 0));
|
|
conf->set3D(false);
|
|
|
|
MolOps::addHs(*m, false, true);
|
|
|
|
conf = &(m->getConformer());
|
|
|
|
TEST_ASSERT(m->getNumAtoms() == 6);
|
|
|
|
TEST_ASSERT(feq(conf->getAtomPos(2).z, 0.0));
|
|
TEST_ASSERT(feq(conf->getAtomPos(3).z, 0.0));
|
|
TEST_ASSERT(feq(conf->getAtomPos(4).z, 0.0));
|
|
TEST_ASSERT(feq(conf->getAtomPos(5).z, 0.0));
|
|
}
|
|
|
|
{
|
|
// make sure NHs are on the same plane as the double bond
|
|
auto m = "NC=C"_smiles;
|
|
TEST_ASSERT(m.get());
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
unsigned int nh2Idx = 0;
|
|
unsigned int chIdx = 1;
|
|
unsigned int ch2Idx = 2;
|
|
conf = new Conformer(3);
|
|
m->addConformer(conf);
|
|
conf->setAtomPos(nh2Idx, RDGeom::Point3D(1.759236, 0.825542, 1.347849));
|
|
conf->setAtomPos(chIdx, RDGeom::Point3D(0.817392, 0.181048, 2.180373));
|
|
conf->setAtomPos(ch2Idx, RDGeom::Point3D(-0.070943, 0.888262, 2.875625));
|
|
|
|
MolOps::addHs(*m, false, true);
|
|
|
|
conf = &(m->getConformer());
|
|
|
|
TEST_ASSERT(m->getNumAtoms() == 8);
|
|
|
|
std::vector<unsigned int> nh2HIdxs{3, 4};
|
|
unsigned int chHIdx = 5;
|
|
std::vector<unsigned int> ch2HIdxs{6, 7};
|
|
RDGeom::Point3D nccNormal =
|
|
(conf->getAtomPos(nh2Idx) - conf->getAtomPos(chIdx))
|
|
.crossProduct((conf->getAtomPos(ch2Idx) - conf->getAtomPos(chIdx)));
|
|
nccNormal.normalize();
|
|
RDGeom::Point3D hnhNormal =
|
|
(conf->getAtomPos(nh2HIdxs[0]) - conf->getAtomPos(nh2Idx))
|
|
.crossProduct(conf->getAtomPos(nh2HIdxs[1]) -
|
|
conf->getAtomPos(nh2Idx));
|
|
hnhNormal.normalize();
|
|
RDGeom::Point3D hchNormal =
|
|
(conf->getAtomPos(ch2HIdxs[0]) - conf->getAtomPos(ch2Idx))
|
|
.crossProduct(conf->getAtomPos(nh2HIdxs[1]) -
|
|
conf->getAtomPos(ch2Idx));
|
|
hchNormal.normalize();
|
|
RDGeom::Point3D hcnNormal =
|
|
(conf->getAtomPos(chHIdx) - conf->getAtomPos(chIdx))
|
|
.crossProduct((conf->getAtomPos(nh2Idx) - conf->getAtomPos(chIdx)));
|
|
hcnNormal.normalize();
|
|
TEST_ASSERT(feq(fabs(nccNormal.dotProduct(hnhNormal)), 1.0));
|
|
TEST_ASSERT(feq(fabs(nccNormal.dotProduct(hchNormal)), 1.0));
|
|
TEST_ASSERT(feq(fabs(nccNormal.dotProduct(hcnNormal)), 1.0));
|
|
}
|
|
|
|
smi = "C#C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
conf = new Conformer(2);
|
|
m->addConformer(conf);
|
|
conf->setAtomPos(0, RDGeom::Point3D(0, 0, 0));
|
|
conf->setAtomPos(1, RDGeom::Point3D(1.2, 0, 0));
|
|
|
|
m2 = MolOps::addHs(*m, false, true);
|
|
conf2 = &(m2->getConformer());
|
|
TEST_ASSERT(m2->getNumAtoms() == 4);
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(0) - conf2->getAtomPos(2)).length(), bondLength));
|
|
TEST_ASSERT(
|
|
feq((conf2->getAtomPos(1) - conf2->getAtomPos(3)).length(), bondLength));
|
|
TEST_ASSERT(feq((conf2->getAtomPos(0) - conf2->getAtomPos(3)).length(),
|
|
bondLength + 1.2));
|
|
TEST_ASSERT(feq((conf2->getAtomPos(1) - conf2->getAtomPos(2)).length(),
|
|
bondLength + 1.2));
|
|
|
|
delete m;
|
|
delete m2;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSanitOps() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Sanitization special cases"
|
|
<< std::endl;
|
|
ROMol *m;
|
|
std::string smi, pathName;
|
|
|
|
smi = "CN(=O)=O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getFormalCharge() == 1);
|
|
delete m;
|
|
|
|
smi = "C[N+](=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getFormalCharge() == 1);
|
|
delete m;
|
|
|
|
smi = "Cl(=O)(=O)(=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 3);
|
|
delete m;
|
|
|
|
smi = "Cl(=O)(=O)(=O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 3);
|
|
delete m;
|
|
|
|
smi = "Br(=O)(=O)(=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 3);
|
|
delete m;
|
|
|
|
smi = "Br(=O)(=O)(=O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 3);
|
|
delete m;
|
|
|
|
smi = "I(=O)(=O)(=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 3);
|
|
delete m;
|
|
|
|
smi = "I(=O)(=O)(=O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 3);
|
|
delete m;
|
|
|
|
pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
m = MolFileToMol(pathName + "perchlorate1.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 51);
|
|
TEST_ASSERT(m->getAtomWithIdx(7)->getFormalCharge() == 3);
|
|
delete m;
|
|
|
|
smi = "CN=N#N";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getFormalCharge() == 0);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getFormalCharge() == 1);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->getFormalCharge() == -1);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(2, 3)->getBondType() == Bond::DOUBLE);
|
|
delete m;
|
|
|
|
smi = "N#N=NC";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getFormalCharge() == 0);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getFormalCharge() == 1);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == -1);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::DOUBLE);
|
|
delete m;
|
|
|
|
smi = "N#N";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getFormalCharge() == 0);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 0);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::TRIPLE);
|
|
delete m;
|
|
|
|
smi = "Cl(=O)(=O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 2);
|
|
delete m;
|
|
|
|
smi = "Cl(=O)(=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 2);
|
|
delete m;
|
|
|
|
smi = "Br(=O)(=O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 2);
|
|
delete m;
|
|
|
|
smi = "Br(=O)(=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 2);
|
|
delete m;
|
|
|
|
smi = "I(=O)(=O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 2);
|
|
delete m;
|
|
|
|
smi = "I(=O)(=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 2);
|
|
delete m;
|
|
|
|
smi = "Cl(=O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 1);
|
|
delete m;
|
|
|
|
smi = "Cl(=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 1);
|
|
delete m;
|
|
|
|
smi = "Br(=O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 1);
|
|
delete m;
|
|
|
|
smi = "Br(=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 1);
|
|
delete m;
|
|
|
|
smi = "I(=O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 1);
|
|
delete m;
|
|
|
|
smi = "I(=O)[O-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 1);
|
|
delete m;
|
|
|
|
smi = "I(O)(O)(O)(O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 6);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 0);
|
|
delete m;
|
|
|
|
smi = "I(O)(O)O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 0);
|
|
delete m;
|
|
|
|
smi = "I(=O)(O)(O)(O)";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 1);
|
|
delete m;
|
|
|
|
smi = "CC(=O)O[IH2](O)OC(C)=O";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 10);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->getFormalCharge() == 0);
|
|
delete m;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testAddConformers() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Add Confomers"
|
|
<< std::endl;
|
|
|
|
std::string smi = "CC";
|
|
ROMol *m = SmilesToMol(smi);
|
|
unsigned int i;
|
|
for (i = 0; i < 5; i++) {
|
|
auto *conf = new Conformer(2);
|
|
conf->setAtomPos(0, RDGeom::Point3D(0.0, 0.0, 0.0));
|
|
conf->setAtomPos(1, RDGeom::Point3D(1.5, 0.0, 0.0));
|
|
m->addConformer(conf, true);
|
|
}
|
|
CHECK_INVARIANT(m->getNumConformers() == 5, "");
|
|
|
|
ROMol *m2 = MolOps::addHs(*m, false, true);
|
|
CHECK_INVARIANT(m2->getNumConformers() == 5, "");
|
|
// const ROMol::CONF_SPTR_LIST &confs = m2->getConformers();
|
|
ROMol::ConstConformerIterator ci;
|
|
i = 0;
|
|
for (ci = m2->beginConformers(); ci != m2->endConformers(); ci++) {
|
|
CHECK_INVARIANT((*ci)->getNumAtoms() == 8, "");
|
|
CHECK_INVARIANT((*ci)->getId() == i, "");
|
|
const ROMol *mn = &((*ci)->getOwningMol());
|
|
CHECK_INVARIANT(mn->getNumAtoms() == 8, "");
|
|
i++;
|
|
}
|
|
// std::cout << m2->getNumAtoms() << " " << m2->getNumConformers() << "\n";
|
|
delete m;
|
|
delete m2;
|
|
BOOST_LOG(rdInfoLog) << "Finished \n ";
|
|
}
|
|
|
|
void testIssue252() {
|
|
// lets check if we can sanitize C60
|
|
std::string smi =
|
|
"C12=C3C4=C5C6=C1C7=C8C9=C1C%10=C%11C(=C29)C3=C2C3=C4C4=C5C5=C9C6=C7C6="
|
|
"C7C8=C1C1=C8C%10=C%10C%11=C2C2=C3C3=C4C4=C5C5=C%11C%12=C(C6=C95)C7=C1C1="
|
|
"C%12C5=C%11C4=C3C3=C5C(=C81)C%10=C23";
|
|
ROMol *mol = SmilesToMol(smi);
|
|
for (ROMol::BondIterator it = mol->beginBonds(); it != mol->endBonds();
|
|
it++) {
|
|
TEST_ASSERT((*it)->getIsAromatic());
|
|
TEST_ASSERT((*it)->getBondType() == Bond::AROMATIC);
|
|
}
|
|
std::string asmi = MolToSmiles(*mol);
|
|
// check if we can do it in the aromatic form
|
|
ROMol *nmol = SmilesToMol(asmi);
|
|
for (ROMol::BondIterator it = nmol->beginBonds(); it != nmol->endBonds();
|
|
it++) {
|
|
TEST_ASSERT((*it)->getIsAromatic());
|
|
TEST_ASSERT((*it)->getBondType() == Bond::AROMATIC);
|
|
}
|
|
|
|
std::string nsmi = MolToSmiles(*nmol);
|
|
delete mol;
|
|
delete nmol;
|
|
|
|
// This is a check for Issue253
|
|
CHECK_INVARIANT(asmi == nsmi, "");
|
|
}
|
|
|
|
void testIssue276() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Issue 276" << std::endl;
|
|
std::string smi = "CP1(C)=CC=CN=C1C";
|
|
ROMol *mol = SmilesToMol(smi);
|
|
TEST_ASSERT(mol);
|
|
// as of this writing, I'm not 100% sure what the right answer is here,
|
|
// but the hybridization definitely should *not* be SP2:
|
|
TEST_ASSERT(mol->getAtomWithIdx(1)->getHybridization() > Atom::SP2);
|
|
delete mol;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished \n ";
|
|
}
|
|
|
|
void testHsAndAromaticity() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Additional Aromaticity Cases" << std::endl;
|
|
std::string smi;
|
|
ROMol *mol;
|
|
|
|
smi = "[CH]1-[CH]-[CH]-[CH]-[CH]-[CH]-1";
|
|
mol = SmilesToMol(smi);
|
|
TEST_ASSERT(mol);
|
|
// std::cerr << mol->getAtomWithIdx(0)->getHybridization() << std::endl;
|
|
TEST_ASSERT(mol->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(mol->getAtomWithIdx(0)->getImplicitValence() == 0);
|
|
TEST_ASSERT(mol->getAtomWithIdx(0)->getNumImplicitHs() == 0);
|
|
TEST_ASSERT(mol->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
TEST_ASSERT(!mol->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(!mol->getBondBetweenAtoms(0, 1)->getIsAromatic());
|
|
delete mol;
|
|
|
|
smi = "C1=CC(=C)C(=C)C=C1";
|
|
mol = SmilesToMol(smi);
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getAtomWithIdx(0)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(mol->getAtomWithIdx(2)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(mol->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(0, 1)->getIsAromatic());
|
|
|
|
delete mol;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished \n ";
|
|
}
|
|
|
|
void testSFIssue1694023() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"1694023 (bad chiral smiles after removing Hs) "
|
|
<< std::endl;
|
|
ROMol *m;
|
|
|
|
std::string smi;
|
|
|
|
smi = "[C@@]([H])(F)(Cl)Br";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getChiralTag() ==
|
|
Atom::CHI_TETRAHEDRAL_CCW);
|
|
|
|
smi = "[C@@](F)([H])(Cl)Br";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW);
|
|
|
|
smi = "[C@@](F)(Cl)([H])Br";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getChiralTag() ==
|
|
Atom::CHI_TETRAHEDRAL_CCW);
|
|
|
|
smi = "[C@@](F)(Cl)(Br)[H]";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW);
|
|
|
|
smi = "[H][C@@](F)(Cl)Br";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getChiralTag() ==
|
|
Atom::CHI_TETRAHEDRAL_CCW);
|
|
|
|
smi = "F[C@@]([H])(Cl)Br";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW);
|
|
|
|
smi = "F[C@@](Cl)([H])Br";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() ==
|
|
Atom::CHI_TETRAHEDRAL_CCW);
|
|
|
|
smi = "F[C@@](Cl)(Br)[H]";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW);
|
|
|
|
smi = "C1CO[C@@H]1Cl";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->getChiralTag() ==
|
|
Atom::CHI_TETRAHEDRAL_CCW);
|
|
|
|
smi = "C1CO[C@]1([H])Cl";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->getChiralTag() ==
|
|
Atom::CHI_TETRAHEDRAL_CCW);
|
|
|
|
smi = "C1CO[C@@]1(Cl)[H]";
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->getChiralTag() ==
|
|
Atom::CHI_TETRAHEDRAL_CCW);
|
|
|
|
delete m;
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFIssue1719053() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"1719053 (Ring stereochemistry incorrectly removed) "
|
|
<< std::endl;
|
|
ROMol *m;
|
|
|
|
std::string smi;
|
|
|
|
smi = "C[C@@H]1CCCCC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
smi = "C[C@@H]1CC[C@@H](C)CC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
smi = "C[C@@H]1C(C)CCCC1C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
smi = "C[C@@H]1[C@H](C)CCC[C@H]1C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
// this is a truly symmetric case, so the stereochem should be removed:
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(7)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
smi = "C[C@@H]1C=C[C@@H](C)C=C1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
smi = "C[N@@]1C=C[C@@H](C)C=C1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
|
|
// N in rings that aren't 3 rings is not chiral
|
|
delete m;
|
|
smi = "C[N@@]1CC[C@@H](C)CC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->getChiralTag() == Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFIssue1811276() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"1811276 (kekulization failing) "
|
|
<< std::endl;
|
|
ROMol *m;
|
|
|
|
std::string smi;
|
|
|
|
smi = "[O-]N1C=C[N+](=O)C=C1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m);
|
|
TEST_ASSERT(smi == "O=[n+]1ccn([O-])cc1");
|
|
delete m;
|
|
|
|
smi = "o1ccc(=O)cc1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m);
|
|
TEST_ASSERT(smi == "O=c1ccocc1");
|
|
delete m;
|
|
|
|
smi = "O=[n+]1ccocc1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m);
|
|
TEST_ASSERT(smi == "O=[n+]1ccocc1");
|
|
delete m;
|
|
|
|
smi = "O=[n+]1ccn([O-])cc1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m);
|
|
TEST_ASSERT(smi == "O=[n+]1ccn([O-])cc1");
|
|
delete m;
|
|
|
|
smi = "O=n1ccccc1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m);
|
|
TEST_ASSERT(smi == "[O-][n+]1ccccc1");
|
|
|
|
delete m;
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFIssue1836576() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"1836576 (sanitization crash) "
|
|
<< std::endl;
|
|
RWMol *m;
|
|
|
|
std::string smi;
|
|
bool ok;
|
|
|
|
// the original form of the test runs foul of the rules for explicit
|
|
// valence on B:
|
|
smi =
|
|
"[BH]123[BH]45[BH]167[BH]289[BH]312[BH]838[BH]966[Co]74479%10%11%12[CH]"
|
|
"633[BH]811[CH]345[BH]21[BH]1234[BH]75[BH]911[BH]226[BH]%1011[BH]227[BH]"
|
|
"633[BH]44[BH]322[CH]%1145[CH]%12271";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
|
|
unsigned int opThatFailed;
|
|
ok = false;
|
|
try {
|
|
MolOps::sanitizeMol(*m, opThatFailed);
|
|
} catch (MolSanitizeException &) {
|
|
ok = true;
|
|
}
|
|
TEST_ASSERT(ok);
|
|
TEST_ASSERT(opThatFailed == MolOps::SANITIZE_PROPERTIES);
|
|
delete m;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testChiralityAndRemoveHs() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing impact of removeHs on chirality"
|
|
<< std::endl;
|
|
ROMol *m, *m2;
|
|
|
|
std::string smi, code;
|
|
|
|
smi = "F[C@]([H])(Cl)Br";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
m2 = MolOps::removeHs(*m);
|
|
TEST_ASSERT(m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m2->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "F[C@H](Cl)Br";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
m2 = MolOps::removeHs(*m);
|
|
TEST_ASSERT(m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m2->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "[C@]([H])(Cl)(F)Br";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
m2 = MolOps::removeHs(*m);
|
|
TEST_ASSERT(m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m2->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "[C@H](Cl)(F)Br";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
m2 = MolOps::removeHs(*m);
|
|
TEST_ASSERT(m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m2->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "[H]1.F[C@]1(Cl)Br";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(2)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
m2 = MolOps::removeHs(*m);
|
|
TEST_ASSERT(m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m2->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "F[C@]1(Cl)Br.[H]1";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
m2 = MolOps::removeHs(*m);
|
|
TEST_ASSERT(m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m2->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "[H]1.[C@]1(Cl)(F)Br";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
m2 = MolOps::removeHs(*m);
|
|
TEST_ASSERT(m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m2->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "[C@]1(Cl)(F)Br.[H]1";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
m2 = MolOps::removeHs(*m);
|
|
TEST_ASSERT(m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m2->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "Cl1.F2.Br3.[C@H]123";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(3)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
|
|
smi = "[C@H]123.Cl1.F2.Br3";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(0)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
|
|
smi = "F2.Cl1.Br3.[C@H]123";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(3)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
|
|
smi = "Cl2.F1.Br3.[C@H]213";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->hasProp(common_properties::_CIPCode));
|
|
m->getAtomWithIdx(3)->getProp(common_properties::_CIPCode, code);
|
|
TEST_ASSERT(code == "R");
|
|
delete m;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFIssue1894348() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing SFIssue1894348 "
|
|
"(impact of removeHs on bond stereo atoms)"
|
|
<< std::endl;
|
|
RWMol *m, *m2;
|
|
|
|
std::string smi;
|
|
|
|
smi = "Cl/C([H])=C/Cl";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::sanitizeMol(*m);
|
|
MolOps::assignStereochemistry(*m);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereoAtoms().size() == 2);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereoAtoms()[0] == 0);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereoAtoms()[1] == 4);
|
|
// we remove an H attached to a stereo bond
|
|
m2 = static_cast<RWMol *>(MolOps::removeHs(static_cast<const ROMol &>(*m)));
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereoAtoms().size() == 2);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereoAtoms()[0] == 0);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereoAtoms()[1] == 4);
|
|
// at first the stereoatoms are gone:
|
|
TEST_ASSERT(m2->getBondWithIdx(2)->getStereoAtoms().size() == 0);
|
|
// but they can be re-perceived:
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
TEST_ASSERT(m2->getBondWithIdx(1)->getStereoAtoms()[0] == 0);
|
|
TEST_ASSERT(m2->getBondWithIdx(1)->getStereoAtoms()[1] == 3);
|
|
|
|
delete m;
|
|
delete m2;
|
|
|
|
smi = "Cl/C([H])=C/Cl";
|
|
m = SmilesToMol(smi, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::sanitizeMol(*m);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereoAtoms().size() == 0);
|
|
m2 = static_cast<RWMol *>(MolOps::removeHs(static_cast<const ROMol &>(*m)));
|
|
// if we don't assign stereocodes in the original we shouldn't have them here:
|
|
TEST_ASSERT(m2->getBondWithIdx(1)->getStereoAtoms().size() == 0);
|
|
delete m;
|
|
delete m2;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testAromaticityEdges() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing some aromaticity edge cases "
|
|
<< std::endl;
|
|
RWMol *m;
|
|
|
|
std::string smi;
|
|
|
|
// ------
|
|
// this was sf.net bug 1934360
|
|
smi = "C1=C=NC=N1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
|
|
smi = "C1=CNC=N1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
|
|
smi = "C=[C+]1=CNC=N1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!m->getAtomWithIdx(1)->getIsAromatic());
|
|
TEST_ASSERT(!m->getBondWithIdx(1)->getIsAromatic());
|
|
delete m;
|
|
|
|
// ------
|
|
// this was sf.net bug 1940646
|
|
smi = "C1#CC=C1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
smi = "C1#CC=CC=C1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
|
|
// ------
|
|
// this was sf.net bug 2091839
|
|
|
|
smi = "c1cccc[c]1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
|
|
smi = "C1=CC=CC=[C]1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
|
|
smi = "c1cccc[n+]1"; // disqualified because N has a radical
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
|
|
smi = "[N]1C=CC=C1"; // disqualified because N has a radical
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
|
|
smi = "[n]1ccccc1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
|
|
smi = "[H]n1cccc1";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
MolOps::sanitizeMol(*m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getIsAromatic());
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNumRadicalElectrons() == 0);
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
|
|
smi = "[H]";
|
|
m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
MolOps::sanitizeMol(*m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
|
|
// ------
|
|
// this was sf.net bug 2787221.
|
|
smi = "O=C1C(=O)C=C1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getIsAromatic());
|
|
delete m;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFIssue1942657() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing sf.net issue 1942657 " << std::endl;
|
|
RWMol *m;
|
|
|
|
std::string smi;
|
|
|
|
smi = "C[C](C)(C)(C)C";
|
|
try {
|
|
m = SmilesToMol(smi);
|
|
} catch (MolSanitizeException &) {
|
|
m = nullptr;
|
|
}
|
|
TEST_ASSERT(!m);
|
|
|
|
smi = "C[CH](C)(C)C";
|
|
try {
|
|
m = SmilesToMol(smi);
|
|
} catch (MolSanitizeException &) {
|
|
m = nullptr;
|
|
}
|
|
TEST_ASSERT(!m);
|
|
|
|
smi = "C[C](=C)(C)C";
|
|
try {
|
|
m = SmilesToMol(smi);
|
|
} catch (MolSanitizeException &) {
|
|
m = nullptr;
|
|
}
|
|
TEST_ASSERT(!m);
|
|
|
|
smi = "C[Si](=C)(=C)=C";
|
|
try {
|
|
m = SmilesToMol(smi);
|
|
} catch (MolSanitizeException &) {
|
|
m = nullptr;
|
|
}
|
|
TEST_ASSERT(!m);
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFIssue1968608() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing sf.net issue 198608 " << std::endl;
|
|
RWMol *m;
|
|
|
|
std::string smi;
|
|
|
|
smi = "C1CC1CC1CC1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m->getRingInfo()->minAtomRingSize(0) == 3);
|
|
TEST_ASSERT(m->getRingInfo()->minAtomRingSize(3) == 0);
|
|
TEST_ASSERT(m->getRingInfo()->minBondRingSize(0) == 3);
|
|
TEST_ASSERT(m->getRingInfo()->minBondRingSize(3) == 0);
|
|
delete m;
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testHybridization() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing hybridization assignment "
|
|
<< std::endl;
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "CCC";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "CNC";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "COC";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[C-2]C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[CH-]C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[CH]C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[C]C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[C-]C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[CH+]C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "CC=C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "CN=C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[C-]=C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[C]=C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[N+]=C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C#C";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C#[C-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C#[C]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[O]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
RWMol *m;
|
|
std::string smi = "C[N-]";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP3);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue2196817() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"2196817: handling of aromatic dummies"
|
|
<< std::endl;
|
|
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "dummyArom.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getAtomicNum() == 0);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
|
|
MolOps::Kekulize(*m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 4)->getBondType() == Bond::SINGLE);
|
|
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "*1cncc1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getAtomicNum() == 0);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "*1C=NC=C1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getAtomicNum() == 0);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
// case where all must be ignored:
|
|
std::string smi = "c1*ccc1-c1*ccc1-c1*ccc1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "c1*[nH]*c1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m);
|
|
TEST_ASSERT(smi == "*1cc*[nH]1");
|
|
delete m;
|
|
smi = "c1***c1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m);
|
|
TEST_ASSERT(smi == "*1:*cc*:1");
|
|
delete m;
|
|
smi = "c:1:*:*:*:*1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m);
|
|
TEST_ASSERT(smi == "*1:*:*c*:1");
|
|
|
|
delete m;
|
|
// we don't kekulize rings that are all dummies, this was github #1478
|
|
smi = "*:1:*:*:*:*:1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m);
|
|
TEST_ASSERT(smi == "*1:*:*:*:*:1");
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "c1*[nH]cc1-c1*[nH]cc1-c1*ccc1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
smi = "c1*[nH]cc1-c1*ccc1-c1*[nH]cc1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
smi = "c1*ccc1-c1*[nH]cc1-c1*[nH1]cc1";
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "c1*[nH]cc1-c1*[nH]cc1-c1*[nH]cc1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "c1ccc(C2CC(n4cc*c4=C2))cc1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 14)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::AROMATIC);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 14)->getBondType() == Bond::AROMATIC);
|
|
MolOps::Kekulize(*m);
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(0, 1)->getIsAromatic());
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(0, 14)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::DOUBLE ||
|
|
m->getBondBetweenAtoms(0, 14)->getBondType() == Bond::DOUBLE);
|
|
MolOps::setAromaticity(*m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 14)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::AROMATIC);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 14)->getBondType() == Bond::AROMATIC);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
for (auto smi : {"c12ccccc1**CC2", "c12ccccc1C**C2", "*12ccccc1CCCC2",
|
|
"*12ccccc1***C2"}) {
|
|
std::unique_ptr<RWMol> m(SmilesToMol(smi));
|
|
TEST_ASSERT(m);
|
|
for (size_t i = 0; i < 6; ++i) {
|
|
size_t j = i < 5 ? i + 1 : 0;
|
|
TEST_ASSERT(m->getBondBetweenAtoms(i, j)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(i, j)->getBondType() ==
|
|
Bond::AROMATIC);
|
|
}
|
|
for (size_t i = 5; i < 10; ++i) {
|
|
size_t j = i < 9 ? i + 1 : 0;
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(i, j)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(i, j)->getBondType() ==
|
|
Bond::SINGLE);
|
|
}
|
|
MolOps::Kekulize(*m);
|
|
for (size_t i = 0; i < 6; ++i) {
|
|
size_t j = i < 5 ? i + 1 : 0;
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(i, j)->getIsAromatic());
|
|
TEST_ASSERT(
|
|
m->getBondBetweenAtoms(i, j)->getBondType() == Bond::SINGLE ||
|
|
m->getBondBetweenAtoms(i, j)->getBondType() == Bond::DOUBLE);
|
|
}
|
|
for (size_t i = 5; i < 10; ++i) {
|
|
size_t j = i < 9 ? i + 1 : 0;
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(i, j)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(i, j)->getBondType() ==
|
|
Bond::SINGLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
for (auto smi : {"c12ccccc1****2", "c12ccccc1***2", "C12=CC=CC=C1****2",
|
|
"c1ccccc1N1****1", "c1ccccc1C1****1", "c1ccccc1*1****1",
|
|
"c1ccccc1*1*=**=*1"}) {
|
|
std::unique_ptr<RWMol> m(SmilesToMol(smi));
|
|
TEST_ASSERT(m);
|
|
for (unsigned int i = 6; i < m->getNumAtoms(); ++i) {
|
|
TEST_ASSERT(!m->getAtomWithIdx(i)->getIsAromatic());
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
for (auto smi : {"C1CC*2ccccc21", "C1C**2ccccc21"}) {
|
|
std::unique_ptr<RWMol> m(SmilesToMol(smi));
|
|
TEST_ASSERT(m);
|
|
for (unsigned int i = 0; i < 3; ++i) {
|
|
TEST_ASSERT(!m->getAtomWithIdx(i)->getIsAromatic());
|
|
}
|
|
for (unsigned int i = 3; i < m->getNumAtoms(); ++i) {
|
|
TEST_ASSERT(m->getAtomWithIdx(i)->getIsAromatic());
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
auto m = "*12ccccc1CCC2"_smiles;
|
|
for (unsigned int i = 0; i < 6; ++i) {
|
|
TEST_ASSERT(m->getAtomWithIdx(i)->getIsAromatic());
|
|
}
|
|
for (unsigned int i = 6; i < m->getNumAtoms(); ++i) {
|
|
TEST_ASSERT(!m->getAtomWithIdx(i)->getIsAromatic());
|
|
}
|
|
}
|
|
|
|
{
|
|
for (auto smi : {"N1****1", "C1=C*2C=CC=C*2C=C1", "N1*C=CC=C1",
|
|
"C1=CC2=CC=C3C=CC4=CC=C5C=CN1*1*2*3*4*51"}) {
|
|
std::unique_ptr<RWMol> m(SmilesToMol(smi));
|
|
TEST_ASSERT(m);
|
|
for (const auto b : m->bonds()) {
|
|
TEST_ASSERT(!b->getIsAromatic());
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
ROMOL_SPTR m = "C1=CC2=CC=C3C=CC4=CC=C5C=CN1*1*2*3*4N51"_smiles;
|
|
for (const auto a : m->atoms()) {
|
|
TEST_ASSERT(a->getIsAromatic());
|
|
}
|
|
unsigned int nNonAromaticBonds = 0;
|
|
for (const auto b : m->bonds()) {
|
|
if (!b->getIsAromatic()) {
|
|
++nNonAromaticBonds;
|
|
}
|
|
}
|
|
TEST_ASSERT(nNonAromaticBonds == 5);
|
|
}
|
|
|
|
{
|
|
for (auto smi :
|
|
{"*1C=CC=C1", "N1*=**=*1", "C1=CC2=CC=C3C=CC4=CC=C5C=CN1N1N2N3N4N51",
|
|
"C1=CC2=CC=C3C=CC4=CC=C5C=CN1*1N2*3N4N51"}) {
|
|
std::unique_ptr<RWMol> m(SmilesToMol(smi));
|
|
TEST_ASSERT(m);
|
|
for (const auto b : m->bonds()) {
|
|
TEST_ASSERT(b->getIsAromatic());
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue2208994() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"2208994 : kekulization error"
|
|
<< std::endl;
|
|
|
|
{
|
|
std::string smi = "Cn1ccc(=O)n1C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getIsAromatic() == true);
|
|
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "c:1:c:c:c:c:c1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getIsAromatic() == true);
|
|
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "c1:c:c:c:c:c:1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getIsAromatic() == true);
|
|
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue2313979() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"2313979: aromaticity assignment hangs "
|
|
<< std::endl;
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
SDMolSupplier suppl(pathName + "Issue2313979.sdf", false);
|
|
|
|
while (!suppl.atEnd()) {
|
|
ROMol *m = suppl.next();
|
|
TEST_ASSERT(m);
|
|
std::string nm;
|
|
m->getProp(common_properties::_Name, nm);
|
|
BOOST_LOG(rdInfoLog) << " Doing molecule: " << nm << std::endl;
|
|
|
|
BOOST_LOG(rdInfoLog) << " This should finish in a few seconds. >>>"
|
|
<< std::endl;
|
|
MolOps::sanitizeMol(*(RWMol *)m);
|
|
delete m;
|
|
BOOST_LOG(rdInfoLog) << " <<< Done." << std::endl;
|
|
}
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue2316677() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"2316677 : canonicalization error"
|
|
<< std::endl;
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "Issue2316677.mol");
|
|
TEST_ASSERT(m);
|
|
std::string smi = MolToSmiles(*m, true);
|
|
std::cerr << "smi: " << smi << std::endl;
|
|
TEST_ASSERT(smi ==
|
|
"Cc1ccc(S(=O)(=O)/N=C2\\CC(=N\\C(C)(C)C)/C2=N\\C(C)(C)C)cc1");
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSanitizeNonringAromatics() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"2830244: make sure that non-ring aromatic atoms "
|
|
"generate errors:"
|
|
<< std::endl;
|
|
{
|
|
std::string smi = "c-C";
|
|
|
|
RWMol *m = SmilesToMol(smi, 0, false);
|
|
bool ok = false;
|
|
try {
|
|
MolOps::Kekulize(*m);
|
|
} catch (MolSanitizeException &) {
|
|
ok = true;
|
|
}
|
|
TEST_ASSERT(ok);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "c-C";
|
|
|
|
RWMol *m = SmilesToMol(smi, 0, false);
|
|
bool ok = false;
|
|
unsigned int opThatFailed;
|
|
try {
|
|
MolOps::sanitizeMol(*m, opThatFailed);
|
|
} catch (MolSanitizeException &) {
|
|
ok = true;
|
|
}
|
|
TEST_ASSERT(ok);
|
|
TEST_ASSERT(opThatFailed == MolOps::SANITIZE_KEKULIZE);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue2951221() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"2951221 : hydrogens added with bad coordinates"
|
|
<< std::endl;
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
ROMol *m = MolFileToMol(pathName + "Issue2951221.1.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getConformer().is3D());
|
|
ROMol *m2 = MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m2);
|
|
delete m;
|
|
TEST_ASSERT(m2->getNumAtoms(false) == 12);
|
|
RDGeom::Point3D coords[4];
|
|
coords[0] = m2->getConformer().getAtomPos(2);
|
|
coords[1] = m2->getConformer().getAtomPos(0);
|
|
coords[2] = m2->getConformer().getAtomPos(1);
|
|
coords[3] = m2->getConformer().getAtomPos(9);
|
|
double dot =
|
|
(coords[3] - coords[0])
|
|
.dotProduct(
|
|
(coords[1] - coords[0]).crossProduct(coords[2] - coords[0]));
|
|
TEST_ASSERT(dot > 1.0);
|
|
delete m2;
|
|
}
|
|
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
ROMol *m = MolFileToMol(pathName + "Issue2951221.2.mol");
|
|
TEST_ASSERT(m);
|
|
ROMol *m2 = MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m2);
|
|
delete m;
|
|
TEST_ASSERT(m2->getNumAtoms(false) == 5);
|
|
MolOps::assignChiralTypesFrom3D(*m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
std::string cip;
|
|
m2->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "S");
|
|
delete m2;
|
|
}
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
ROMol *m = MolFileToMol(pathName + "Issue2951221.3.mol");
|
|
TEST_ASSERT(m);
|
|
ROMol *m2 = MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m2);
|
|
delete m;
|
|
TEST_ASSERT(m2->getNumAtoms(false) == 5);
|
|
MolOps::assignChiralTypesFrom3D(*m2);
|
|
MolOps::assignStereochemistry(*m2, true, true);
|
|
TEST_ASSERT(m2->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode));
|
|
std::string cip;
|
|
m2->getAtomWithIdx(1)->getProp(common_properties::_CIPCode, cip);
|
|
TEST_ASSERT(cip == "R");
|
|
delete m2;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue2952255() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"2952255 : bad assignment of radicals to early "
|
|
"elements"
|
|
<< std::endl;
|
|
{
|
|
std::string smi = "[C](C)(C)C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[C](C)C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[CH](C)C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[CH+](C)C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[C-](C)C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[C+](C)(C)(C)C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "C(C)(C)(C)C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[N](C)C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[N+](C)(C)C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Cl]";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Cl-]";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Cl]C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Na]";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Na+]";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Na]C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Mg+]C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Mg]C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Mg+]";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "[Mg+2]";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue3185548() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"3185548 : problems with SSSR code"
|
|
<< std::endl;
|
|
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
BOOST_LOG(rdInfoLog) << " Starting file read 1" << std::endl;
|
|
RWMol *m = MolFileToMol(pathName + "Issue3185548.mol");
|
|
BOOST_LOG(rdInfoLog) << " finished" << std::endl;
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
BOOST_LOG(rdInfoLog) << " Starting file read 2" << std::endl;
|
|
RWMol *m = MolFileToMol(pathName + "Issue3185548.2.mol");
|
|
BOOST_LOG(rdInfoLog) << " finished" << std::endl;
|
|
TEST_ASSERT(m);
|
|
|
|
m->getRingInfo()->reset();
|
|
unsigned int nsssr;
|
|
VECT_INT_VECT sssrs;
|
|
nsssr = MolOps::findSSSR(*m, sssrs);
|
|
TEST_ASSERT(nsssr = 48);
|
|
nsssr = MolOps::symmetrizeSSSR(*m, sssrs);
|
|
TEST_ASSERT(nsssr = 56);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue3349243() {
|
|
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
|
|
BOOST_LOG(rdInfoLog) << "Testing Issue 3349243" << std::endl;
|
|
{
|
|
std::string smi = "c1cccc[n+]1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::Kekulize(*m);
|
|
// just finishing is good
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getBondType() != Bond::AROMATIC);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testFastFindRings() {
|
|
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
|
|
BOOST_LOG(rdInfoLog) << "Testing fast find rings" << std::endl;
|
|
{
|
|
std::string smi = "CCC";
|
|
RWMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
MolOps::fastFindRings(*m);
|
|
TEST_ASSERT(m->getRingInfo());
|
|
TEST_ASSERT(m->getRingInfo()->isInitialized());
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "C1CC1";
|
|
RWMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
MolOps::fastFindRings(*m);
|
|
TEST_ASSERT(m->getRingInfo());
|
|
TEST_ASSERT(m->getRingInfo()->isInitialized());
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 1);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "CC1CC1";
|
|
RWMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
MolOps::fastFindRings(*m);
|
|
TEST_ASSERT(m->getRingInfo());
|
|
TEST_ASSERT(m->getRingInfo()->isInitialized());
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 1);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "C1CC1.C1CC1";
|
|
RWMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
MolOps::fastFindRings(*m);
|
|
TEST_ASSERT(m->getRingInfo());
|
|
TEST_ASSERT(m->getRingInfo()->isInitialized());
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "C1C(C)C1";
|
|
RWMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
MolOps::fastFindRings(*m);
|
|
TEST_ASSERT(m->getRingInfo());
|
|
TEST_ASSERT(m->getRingInfo()->isInitialized());
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "c1c(=O)nc2[nH]cnn2c1O";
|
|
RWMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
MolOps::fastFindRings(*m);
|
|
TEST_ASSERT(m->getRingInfo());
|
|
TEST_ASSERT(m->getRingInfo()->isInitialized());
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 2);
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue3487473() {
|
|
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
|
|
BOOST_LOG(rdInfoLog) << "Testing Issue 3487473" << std::endl;
|
|
{
|
|
std::string smi = "C*C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::UNSPECIFIED);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi = "C*C";
|
|
RWMol *m = SmartsToMol(smi);
|
|
TEST_ASSERT(m);
|
|
m->updatePropertyCache(false);
|
|
MolOps::setConjugation(*m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::UNSPECIFIED);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue3480481() {
|
|
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
|
|
BOOST_LOG(rdInfoLog) << "Testing Issue 3480481" << std::endl;
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "Issue3480481.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getExplicitValence() == 4);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getImplicitValence() == 0);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == -1);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void aamatchtest(std::string smi1, std::string smi2, bool shouldMatch, int idx1,
|
|
int idx2) {
|
|
RWMol *m1 = SmilesToMol(smi1);
|
|
RWMol *m2 = SmilesToMol(smi2);
|
|
TEST_ASSERT(m1);
|
|
TEST_ASSERT(m2);
|
|
// std::cerr<<" "<<smi1<<" "<<smi2<<std::endl;
|
|
TEST_ASSERT(m2->getAtomWithIdx(idx2)->Match(m1->getAtomWithIdx(idx1)) ==
|
|
shouldMatch);
|
|
delete m1;
|
|
delete m2;
|
|
}
|
|
|
|
void testAtomAtomMatch() {
|
|
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
|
|
BOOST_LOG(rdInfoLog) << "Testing Atom-Atom matching behavior" << std::endl;
|
|
/* Here's what we're testing:
|
|
|
|
| Molecule | Query | Match |
|
|
| CCO | CCO | Yes |
|
|
| CC[O-] | CCO | Yes |
|
|
| CCO | CC[O-] | No |
|
|
| CC[O-] | CC[O-] | Yes |
|
|
| CC[O-] | CC[OH] | Yes |
|
|
| CCOC | CC[OH] | Yes |
|
|
| CCOC | CCO | Yes |
|
|
| CCC | CCC | Yes |
|
|
| CC[14C] | CCC | Yes |
|
|
| CCC | CC[14C] | No |
|
|
| CC[14C] | CC[14C] | Yes |
|
|
| OCO | C | Yes |
|
|
| OCO | [CH2] | Yes |
|
|
| OCO | [CH3] | Yes |
|
|
| O[CH2]O | C | Yes |
|
|
| O[CH2]O | [CH2] | Yes |
|
|
| OCO | [CH] | Yes |
|
|
|
|
This is a large superset of issue 3495370
|
|
|
|
*/
|
|
|
|
// note that in some cases here we have to be fairly careful about Hs on
|
|
// the query to make sure that it doesn't have radicals (radical handling
|
|
// added to fix github #165
|
|
aamatchtest("CCO", "O", true, 2, 0);
|
|
aamatchtest("CC[O-]", "O", true, 2, 0);
|
|
aamatchtest("CCO", "[OH-]", false, 2, 0);
|
|
aamatchtest("CC[O-]", "[OH-]", true, 2, 0);
|
|
aamatchtest("CC[O-]", "[OH2]", true, 2, 0);
|
|
aamatchtest("CCOC", "[OH2]", true, 2, 0);
|
|
aamatchtest("CCOC", "O", true, 2, 0);
|
|
aamatchtest("CCC", "C", true, 2, 0);
|
|
aamatchtest("CC[14C]", "C", true, 2, 0);
|
|
aamatchtest("CCC", "[14CH4]", false, 2, 0);
|
|
aamatchtest("CC[14C]", "[14CH4]", true, 2, 0);
|
|
aamatchtest("CC[13C]", "[14CH4]", false, 2, 0);
|
|
aamatchtest("OCO", "C", true, 1, 0);
|
|
aamatchtest("OCO", "[CH4]", true, 1, 0);
|
|
aamatchtest("O[CH2]O", "C", true, 1, 0);
|
|
aamatchtest("O[CH2]O", "[CH4]", true, 1, 0);
|
|
aamatchtest("OCO", "[CH2]", false, 1,
|
|
0); // doesn't match due to radical count
|
|
aamatchtest("O[CH2]O", "[CH2]", false, 1,
|
|
0); // doesn't match due to radical count
|
|
aamatchtest("O[CH]O", "[CH3]", true, 1, 0);
|
|
aamatchtest("O[CH]O", "[CH2]", false, 1,
|
|
0); // doesn't match due to radical count
|
|
aamatchtest("CC", "*", false, 1, 0);
|
|
aamatchtest("C*", "*", true, 1, 0);
|
|
aamatchtest("C[1*]", "*", true, 1, 0);
|
|
aamatchtest("C[1*]", "[1*]", true, 1, 0);
|
|
aamatchtest("C*", "[1*]", true, 1, 0);
|
|
aamatchtest("C[2*]", "[1*]", false, 1, 0);
|
|
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue3525076() {
|
|
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
|
|
BOOST_LOG(rdInfoLog) << "Testing Issue 3525076" << std::endl;
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "Issue3525076.sdf");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(18)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getBondWithIdx(18)->getBondType() == Bond::SINGLE);
|
|
MolOps::Kekulize(*m);
|
|
TEST_ASSERT(m->getBondWithIdx(18)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getBondWithIdx(18)->getBondType() == Bond::SINGLE);
|
|
MolOps::sanitizeMol(*m);
|
|
TEST_ASSERT(m->getBondWithIdx(18)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getBondWithIdx(18)->getBondType() == Bond::SINGLE);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testBasicCanon() {
|
|
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
|
|
BOOST_LOG(rdInfoLog) << "Testing canonicalization basics" << std::endl;
|
|
// these are all cases that were problematic at one time or another during
|
|
// the canonicalization rewrite.
|
|
#if 1
|
|
{
|
|
std::string smi = "FC1C(=C/Cl)\\C1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(2, 3)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(2, 3)->getStereo() == Bond::STEREOZ);
|
|
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<std::endl;
|
|
RWMol *m2 = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m2);
|
|
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*m, *m2, mv));
|
|
std::map<int, int> mmap;
|
|
for (MatchVectType::const_iterator mvit = mv.begin(); mvit != mv.end();
|
|
++mvit) {
|
|
mmap[mvit->second] = mvit->first;
|
|
}
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[2], mmap[3])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[2], mmap[3])->getStereo() ==
|
|
Bond::STEREOZ);
|
|
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m2, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
delete m2;
|
|
}
|
|
|
|
{
|
|
std::string smi = "CC1(C)C2CCC1(C)C(=O)/C2=C\\C(N=N/c1ccccc1)=N/Nc1ccccc1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(10, 11)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(10, 11)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(12, 21)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(12, 21)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(13, 14)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(13, 14)->getStereo() ==
|
|
Bond::STEREONONE);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
|
|
RWMol *m2 = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m2);
|
|
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*m, *m2, mv));
|
|
std::map<int, int> mmap;
|
|
for (MatchVectType::const_iterator mvit = mv.begin(); mvit != mv.end();
|
|
++mvit) {
|
|
mmap[mvit->second] = mvit->first;
|
|
}
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[10], mmap[11])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[10], mmap[11])->getStereo() ==
|
|
Bond::STEREOZ);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[12], mmap[21])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[12], mmap[21])->getStereo() ==
|
|
Bond::STEREOE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[13], mmap[14])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[13], mmap[14])->getStereo() ==
|
|
Bond::STEREONONE);
|
|
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m2, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
delete m2;
|
|
}
|
|
|
|
{
|
|
std::string smi = "COc1ccc(OC)c2[nH]c(=O)cc(C)c21";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "COc1cc(C)c(C(=O)[O-])cc1OC";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "COc1ccc(C(=O)OC(c2ccc(OC)cc2)C(C)O)cc1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "CC(C)C1CCC(C)=CC1=NNC(N)=O";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "COCCNC(=O)c1ccccc1N1C(=O)C2(C)c3[nH]c4ccccc4c3CCN2C1=O";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "Cc1c(Br)cc(Br)cc1C(F)(F)F";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "zinc4235774a.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(7, 8)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(7, 8)->getStereo() == Bond::STEREOZ);
|
|
std::string smi = MolToSmiles(*m, true);
|
|
// std::cerr<<"SMILES: "<<smi<<std::endl;
|
|
RWMol *m2 = SmilesToMol(smi);
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*m, *m2, mv));
|
|
std::map<int, int> mmap;
|
|
for (MatchVectType::const_iterator mvit = mv.begin(); mvit != mv.end();
|
|
++mvit) {
|
|
mmap[mvit->second] = mvit->first;
|
|
}
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[1], mmap[2])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[7], mmap[8])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[1], mmap[2])->getStereo() ==
|
|
Bond::STEREOZ);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[7], mmap[8])->getStereo() ==
|
|
Bond::STEREOZ);
|
|
delete m;
|
|
delete m2;
|
|
}
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "zinc4235774.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(4, 5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(4, 5)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(14, 15)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(14, 15)->getStereo() == Bond::STEREOZ);
|
|
std::string smi = MolToSmiles(*m, true);
|
|
RWMol *m2 = SmilesToMol(smi);
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*m, *m2, mv));
|
|
std::map<int, int> mmap;
|
|
for (MatchVectType::const_iterator mvit = mv.begin(); mvit != mv.end();
|
|
++mvit) {
|
|
mmap[mvit->second] = mvit->first;
|
|
}
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[4], mmap[5])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[14], mmap[15])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[4], mmap[5])->getStereo() ==
|
|
Bond::STEREOZ);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[14], mmap[15])->getStereo() ==
|
|
Bond::STEREOZ);
|
|
delete m;
|
|
delete m2;
|
|
}
|
|
#endif
|
|
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "zinc3850436piece.mol");
|
|
TEST_ASSERT(m);
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi1);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "zinc13403961piece.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(3, 7)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(3, 7)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(4, 5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(4, 5)->getStereo() == Bond::STEREOE);
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
// std::cerr<<"SMI1: "<<csmi1<<std::endl;
|
|
RWMol *m2 = SmilesToMol(csmi1);
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*m, *m2, mv));
|
|
std::map<int, int> mmap;
|
|
for (MatchVectType::const_iterator mvit = mv.begin(); mvit != mv.end();
|
|
++mvit) {
|
|
mmap[mvit->second] = mvit->first;
|
|
}
|
|
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[1], mmap[2])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[1], mmap[2])->getStereo() ==
|
|
Bond::STEREOZ);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[3], mmap[7])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[3], mmap[7])->getStereo() ==
|
|
Bond::STEREOE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[4], mmap[5])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[4], mmap[5])->getStereo() ==
|
|
Bond::STEREOE);
|
|
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m2, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
delete m2;
|
|
}
|
|
{
|
|
std::string smi = "C\\N=c1/s/c(=N\\Cl)/c/1=N/F";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi =
|
|
"Cc1ccc(S(=O)(=O)/N=c2sc(=N\\C(C)(C)C)/c\\2=N/C(C)(C)C)cc1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi1);
|
|
TEST_ASSERT(m);
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "zinc6624278.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(21, 13)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(21, 13)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(5, 12)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(5, 12)->getStereo() == Bond::STEREOZ);
|
|
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
// std::cerr<<"SMI1: "<<csmi1<<std::endl;
|
|
RWMol *m2 = SmilesToMol(csmi1);
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*m, *m2, mv));
|
|
std::map<int, int> mmap;
|
|
for (MatchVectType::const_iterator mvit = mv.begin(); mvit != mv.end();
|
|
++mvit) {
|
|
mmap[mvit->second] = mvit->first;
|
|
}
|
|
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[21], mmap[13])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[21], mmap[13])->getStereo() ==
|
|
Bond::STEREOE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[5], mmap[12])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[5], mmap[12])->getStereo() ==
|
|
Bond::STEREOZ);
|
|
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m2, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m2;
|
|
|
|
std::string tsmi = MolToSmiles(*m, true, false, 7, false);
|
|
// std::cerr<<"-------------\n";
|
|
// std::cerr<<"T:\n"<<tsmi<<"\n-------------\n"<<std::endl;
|
|
m2 = SmilesToMol(tsmi);
|
|
TEST_ASSERT(SubstructMatch(*m, *m2, mv));
|
|
mmap.clear();
|
|
for (MatchVectType::const_iterator mvit = mv.begin(); mvit != mv.end();
|
|
++mvit) {
|
|
mmap[mvit->second] = mvit->first;
|
|
}
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[21], mmap[13])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[21], mmap[13])->getStereo() ==
|
|
Bond::STEREOE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[5], mmap[12])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[5], mmap[12])->getStereo() ==
|
|
Bond::STEREOZ);
|
|
|
|
// std::cerr<<"-------------\n";
|
|
csmi2 = MolToSmiles(*m2, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
delete m2;
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "F/C=C/C=C(C)/C=C/Cl";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(3, 4)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(3, 4)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(6, 7)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(6, 7)->getStereo() == Bond::STEREOE);
|
|
|
|
std::string tsmi = MolToSmiles(*m, true, false, 3, false);
|
|
// std::cerr<<"-------------\n";
|
|
// std::cerr<<"T:\n"<<tsmi<<"\n-------------\n"<<std::endl;
|
|
RWMol *m2 = SmilesToMol(tsmi);
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*m, *m2, mv));
|
|
std::map<int, int> mmap;
|
|
mmap.clear();
|
|
for (MatchVectType::const_iterator mvit = mv.begin(); mvit != mv.end();
|
|
++mvit) {
|
|
mmap[mvit->second] = mvit->first;
|
|
}
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[1], mmap[2])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[1], mmap[2])->getStereo() ==
|
|
Bond::STEREOE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[3], mmap[4])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[3], mmap[4])->getStereo() ==
|
|
Bond::STEREOE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[6], mmap[7])->getBondType() ==
|
|
Bond::DOUBLE);
|
|
TEST_ASSERT(m2->getBondBetweenAtoms(mmap[6], mmap[7])->getStereo() ==
|
|
Bond::STEREOE);
|
|
|
|
std::string csmi1 = MolToSmiles(*m, true);
|
|
// std::cerr<<"SMI1: "<<csmi1<<std::endl;
|
|
// std::cerr<<"-------------\n";
|
|
std::string csmi2 = MolToSmiles(*m2, true);
|
|
// std::cerr<<csmi1<<"\n"<<csmi2<<"\n-------------\n"<<std::endl;
|
|
TEST_ASSERT(csmi1 == csmi2);
|
|
|
|
delete m2;
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
// this was issue 3528556
|
|
std::string smi = "N12.N13.C24.C35.C46.C56";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
std::string csmi = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m, true);
|
|
TEST_ASSERT(csmi == smi);
|
|
delete m;
|
|
}
|
|
{
|
|
// this was issue 3526831
|
|
std::string smi = "CO/N=C/C(=C(\\O)/c1ccc(Cl)cc1)/C=N\\OC";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
std::string csmi = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(csmi);
|
|
TEST_ASSERT(m);
|
|
smi = MolToSmiles(*m, true);
|
|
TEST_ASSERT(csmi == smi);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue3549146() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue "
|
|
"3549146: problems after mergeQueryHs"
|
|
<< std::endl;
|
|
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
ROMol *m = MolFileToMol(pathName + "Issue3549146.mol", true, false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 16);
|
|
ROMol *m2 = MolOps::mergeQueryHs(*m);
|
|
TEST_ASSERT(m2);
|
|
TEST_ASSERT(m2->getNumAtoms() == 13);
|
|
TEST_ASSERT(!(m2->getRingInfo()->isInitialized()));
|
|
delete m;
|
|
delete m2;
|
|
}
|
|
{
|
|
std::string smi = "CCC.C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT((m->getRingInfo()->isInitialized()));
|
|
m->addBond(1, 3, Bond::SINGLE);
|
|
TEST_ASSERT((m->getRingInfo()->isInitialized()));
|
|
m->addBond(0, 2, Bond::SINGLE);
|
|
TEST_ASSERT(!(m->getRingInfo()->isInitialized()));
|
|
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "C1CC1C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT((m->getRingInfo()->isInitialized()));
|
|
m->removeBond(2, 3);
|
|
TEST_ASSERT(!(m->getRingInfo()->isInitialized()));
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "C1CC1C";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT((m->getRingInfo()->isInitialized()));
|
|
m->removeAtom(3);
|
|
TEST_ASSERT(!(m->getRingInfo()->isInitialized()));
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue249() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue 249: "
|
|
"finding rings consumes all memory"
|
|
<< std::endl;
|
|
|
|
{
|
|
std::string smi =
|
|
"Cc1cc2cc(c1)C(=O)NCc1cc-3cc(CNC(=O)c4cc(C)cc(c4)C(=O)NCc4cc(cc(CNC2=O)"
|
|
"c4O)-c2cc4CNC(=O)c5cc(C)cc(c5)C(=O)NCc5cc-3cc(CNC(=O)c3cc(C)cc(c3)C(="
|
|
"O)NCc(c2)c4O)c5O)c1O";
|
|
ROMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 88);
|
|
m->updatePropertyCache(false);
|
|
std::cerr << "starting ring finding" << std::endl;
|
|
MolOps::findSSSR(*m);
|
|
std::cerr << "done" << std::endl;
|
|
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi =
|
|
"CCCOc1c2CNC(=O)c3cc(cc(c3)C(=O)NCc3cc4cc(CNC(=O)c5cc(C(=O)NCc1cc(c2)"
|
|
"c1cc2CNC(=O)c6cc(cc(c6)C(=O)NCc6cc4cc(CNC(=O)c4cc(C(=O)NCc(c1)c2OCCC)"
|
|
"cc(c4)C(=O)NC(COCCC(=O)O)(COCCC(=O)O)COCCC(=O)O)c6OCCC)C(=O)NC(COCCC(="
|
|
"O)O)(COCCC(=O)O)COCCC(=O)O)cc(c5)C(=O)NC(COCCC(=O)O)(COCCC(=O)O)COCCC("
|
|
"=O)O)c3OCCC)C(=O)NC(COCCC(=O)O)(COCCC(=O)O)COCCC(=O)O";
|
|
ROMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 196);
|
|
m->updatePropertyCache(false);
|
|
std::cerr << "starting ring finding" << std::endl;
|
|
MolOps::findSSSR(*m);
|
|
std::cerr << "done" << std::endl;
|
|
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi =
|
|
"CCn1nnc(c1)CN=C(C1CC2C3CCC4C5C3C3C6C2C2C1C1CCC7C(C1)C1C8C9C7C(C(=O)O)"
|
|
"C(C(=O)O)C7C9C(C9C8C8C%10C1C1C(C2C2C6C6C%11C3C(C5)C3C(C(=O)O)C5C%"
|
|
"12CC9C9C8C8C(C%10)C%10C%13C(C%14C(C2C1C(=O)O)C6C1C2C%11C3C3C5C(C5C%"
|
|
"12C9C(C8CC%10)CC5)C(CC3C2C(C(C1C%14CC%13C(=NCc1nnn(c1)CC)O)C(=O)O)C(="
|
|
"O)O)C(=NCc1nnn(c1)CC)O)C(=O)O)C(=O)O)CC1C(C4C(CC71)C(=NCc1nnn(c1)CC)O)"
|
|
"C(=O)O)O";
|
|
ROMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 167);
|
|
m->updatePropertyCache(false);
|
|
std::cerr << "starting ring finding" << std::endl;
|
|
MolOps::findSSSR(*m);
|
|
std::cerr << "done" << std::endl;
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi =
|
|
"C/C=N/"
|
|
"c1ccc(cc1)c1cc2cc(c1)c1ccc(cc1)N=Cc1ccc(cc1)c1cc(cc(c1)c1ccc(cc1)C)"
|
|
"c1ccc(cc1)C=Nc1ccc(cc1)c1cc(cc(c1)c1ccc(cc1)/N=C/"
|
|
"C)c1ccc(cc1)N=Cc1ccc(cc1)c1cc(c3ccc(C=Nc4ccc(c5cc6c7ccc(N=Cc8ccc(c9cc("
|
|
"c%10ccc(C=Nc%11ccc2cc%11)cc%10)cc(c9)c2ccc(cc2)C=Nc2ccc(cc2)c2cc(cc("
|
|
"c2)c2ccc(cc2)N=Cc2ccc(cc2)c2cc(cc(c2)c2ccc(cc2)C)c2ccc(cc2)C=Nc2ccc("
|
|
"cc2)c2cc(c9ccc(N=Cc%10ccc(c%11cc(c%12ccc(C=Nc%13ccc(c(c6)c5)cc%13)cc%"
|
|
"12)cc(c%11)c5ccc(cc5)C)cc%10)cc9)cc(c2)c2ccc(cc2)/N=C/C)c2ccc(cc2)/"
|
|
"N=C/C)cc8)cc7)cc4)cc3)cc(c1)c1ccc(cc1)C";
|
|
RWMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 278);
|
|
std::cerr << smi << std::endl;
|
|
std::cerr << "starting sanitization" << std::endl;
|
|
MolOps::sanitizeMol(*m);
|
|
std::cerr << "done" << std::endl;
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smi =
|
|
"COc1cc2ccc1n1c(=O)n(c3ccc(cc3OC)c3ccc(c(c3)OC)n3c(=O)n(c4ccc(cc4OC)"
|
|
"c4ccc(c(c4)OC)n4c(=O)n(c5ccc(cc5OC)c5ccc(n6c(=O)n(c7ccc(c8ccc(n9c(=O)"
|
|
"n(c%10ccc(c%11ccc(n%12c(=O)n(c%13ccc2cc%13OC)c(=O)n(c%12=O)c2ccc("
|
|
"cc2OC)C)c(OC)c%11)cc%10OC)c(=O)n(c9=O)c2ccc(cc2OC)C)c(OC)c8)cc7OC)c(="
|
|
"O)n(c6=O)c2ccc(cc2OC)C)c(c5)OC)c(=O)n(c4=O)c2ccc(cc2OC)C)c(=O)n(c3=O)"
|
|
"c2ccc(cc2OC)C)c(=O)n(c1=O)c1ccc(cc1OC)C";
|
|
RWMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 204);
|
|
std::cerr << "starting sanitization" << std::endl;
|
|
MolOps::sanitizeMol(*m);
|
|
std::cerr << "done" << std::endl;
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue256() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing sf.net issue 256: bad atom counts"
|
|
<< std::endl;
|
|
|
|
{
|
|
std::string smi = "*CC[H]";
|
|
ROMol *m = SmilesToMol(smi, 0, 0);
|
|
TEST_ASSERT(m);
|
|
m->updatePropertyCache(false);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getNumAtoms(false) == 8);
|
|
TEST_ASSERT(m->getNumHeavyAtoms() == 2);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "*CC[2H]";
|
|
ROMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getNumAtoms(false) == 8);
|
|
TEST_ASSERT(m->getNumHeavyAtoms() == 2);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue266() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue 266: "
|
|
"ring finding error"
|
|
<< std::endl;
|
|
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "Issue266.mol", false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 19);
|
|
TEST_ASSERT(m->getNumBonds() == 25);
|
|
std::cerr << "starting ring finding" << std::endl;
|
|
MolOps::findSSSR(*m);
|
|
std::cerr << "done" << std::endl;
|
|
TEST_ASSERT(m->getRingInfo()->numRings() ==
|
|
(m->getNumBonds() - m->getNumAtoms() + 1));
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSFNetIssue272() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing sf.net issue 272: "
|
|
"removing two-coordinate Hs"
|
|
<< std::endl;
|
|
|
|
{
|
|
std::string smi = "C[H-]C";
|
|
ROMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "C[H].C";
|
|
ROMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGitHubIssue8() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue 8 "
|
|
"(impact of removeAtom on bond stereo atoms)"
|
|
<< std::endl;
|
|
{
|
|
std::string smi = "Cl/C=C/Cl";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
m->removeAtom((unsigned int)0);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereoAtoms().size() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "CC/C=C/Cl";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m);
|
|
INT_VECT &sas = m->getBondWithIdx(2)->getStereoAtoms();
|
|
TEST_ASSERT(sas.size() == 2);
|
|
TEST_ASSERT(std::find(sas.begin(), sas.end(), 1) != sas.end());
|
|
m->removeAtom((unsigned int)0);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
TEST_ASSERT(std::find(sas.begin(), sas.end(), 0) != sas.end());
|
|
TEST_ASSERT(std::find(sas.begin(), sas.end(), 1) == sas.end());
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "C/C=C/CC";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignStereochemistry(*m);
|
|
INT_VECT &sas = m->getBondWithIdx(1)->getStereoAtoms();
|
|
TEST_ASSERT(sas.size() == 2);
|
|
TEST_ASSERT(std::find(sas.begin(), sas.end(), 0) != sas.end());
|
|
TEST_ASSERT(std::find(sas.begin(), sas.end(), 3) != sas.end());
|
|
m->removeAtom((unsigned int)4);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
TEST_ASSERT(std::find(sas.begin(), sas.end(), 0) != sas.end());
|
|
TEST_ASSERT(std::find(sas.begin(), sas.end(), 3) != sas.end());
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGitHubIssue42() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue 42 "
|
|
"(impact of removeAtom on atom stereochem)"
|
|
<< std::endl;
|
|
{
|
|
std::string smi =
|
|
"CCN1CCN(c2cc3[nH]c(C(=O)[C@@]4(CC)CC[C@](C)(O)CC4)nc3cc2Cl)CC1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
int indices[] = {29, 28, 27, 26, 25, 24, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1};
|
|
for (unsigned int i = 0; indices[i] > -1; ++i) {
|
|
m->removeAtom((unsigned int)indices[i]);
|
|
}
|
|
smi = MolToSmiles(*m, true);
|
|
std::cerr << "smiles: " << smi << std::endl;
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGitHubIssue65() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue 65 "
|
|
"(kekulization of boron-containing aromatic rings)"
|
|
<< std::endl;
|
|
{
|
|
std::string smi = "C[B-]1=CC=CC=C1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getIsAromatic());
|
|
|
|
MolOps::Kekulize(*m);
|
|
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGitHubIssue72() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue 72 "
|
|
"(problems with bad benzothiazolium structure)"
|
|
<< std::endl;
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "github72.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(0, 8)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 6)->getIsAromatic());
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "github72.2.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 8)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 6)->getIsAromatic());
|
|
delete m;
|
|
}
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "github72.3.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(0, 8)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 6)->getIsAromatic());
|
|
|
|
std::string smi = MolToSmiles(*m, true);
|
|
delete m;
|
|
m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
namespace {
|
|
void _renumberTest(const ROMol *m) {
|
|
PRECONDITION(m, "no molecule");
|
|
std::vector<unsigned int> idxV(m->getNumAtoms());
|
|
for (unsigned int i = 0; i < m->getNumAtoms(); ++i) {
|
|
idxV[i] = i;
|
|
}
|
|
|
|
std::string refSmi = MolToSmiles(*m, true);
|
|
for (unsigned int i = 0; i < m->getNumAtoms(); ++i) {
|
|
std::vector<unsigned int> nVect(idxV);
|
|
std::shuffle(nVect.begin(), nVect.end(), std::mt19937(0xf00d));
|
|
// std::copy(nVect.begin(),nVect.end(),std::ostream_iterator<int>(std::cerr,",
|
|
// "));
|
|
// std::cerr<<std::endl;
|
|
|
|
ROMol *nm = MolOps::renumberAtoms(*m, nVect);
|
|
TEST_ASSERT(nm);
|
|
TEST_ASSERT(nm->getNumAtoms() == m->getNumAtoms());
|
|
TEST_ASSERT(nm->getNumBonds() == m->getNumBonds());
|
|
|
|
// checking the SSS is a test for Github #317
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*m, *nm, mv));
|
|
TEST_ASSERT(mv.size() == nm->getNumAtoms());
|
|
|
|
for (unsigned int j = 0; j < m->getNumAtoms(); ++j) {
|
|
TEST_ASSERT(m->getAtomWithIdx(nVect[j])->getAtomicNum() ==
|
|
nm->getAtomWithIdx(j)->getAtomicNum());
|
|
}
|
|
|
|
// checking the conformation is a test for Github #441
|
|
TEST_ASSERT(m->getNumConformers() == nm->getNumConformers());
|
|
if (m->getNumConformers()) {
|
|
for (unsigned int j = 0; j < m->getNumAtoms(); ++j) {
|
|
RDGeom::Point3D po = m->getConformer().getAtomPos(nVect[j]);
|
|
RDGeom::Point3D pn = nm->getConformer().getAtomPos(j);
|
|
TEST_ASSERT(po.x == pn.x);
|
|
TEST_ASSERT(po.y == pn.y);
|
|
TEST_ASSERT(po.z == pn.z);
|
|
}
|
|
// checking conformer dimensionality is a test for Github #584
|
|
TEST_ASSERT(m->getConformer().is3D() == nm->getConformer().is3D());
|
|
}
|
|
|
|
std::string nSmi = MolToSmiles(*nm, true);
|
|
if (nSmi != refSmi) {
|
|
std::cerr << refSmi << std::endl << nSmi << std::endl;
|
|
}
|
|
TEST_ASSERT(nSmi == refSmi);
|
|
delete nm;
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
void testRenumberAtoms() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing renumbering atoms"
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "CC1CCCC(C)C1C";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
_renumberTest(m);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C[C@H]1C[C@H](F)C1";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
_renumberTest(m);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C[C@H]1CC[C@H](C/C=C/[C@H](F)Cl)CC1";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
_renumberTest(m);
|
|
delete m;
|
|
}
|
|
{ // github issue #441 and #584
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "Issue266.mol"); // no significance to
|
|
// choice of files, we
|
|
// just need something
|
|
// with 2D coords
|
|
TEST_ASSERT(m);
|
|
_renumberTest(m);
|
|
delete m;
|
|
}
|
|
|
|
{ // github issue 1735 renumber empty molecules
|
|
auto *m = new ROMol;
|
|
TEST_ASSERT(m);
|
|
std::vector<unsigned int> nVect;
|
|
auto *m1 = MolOps::renumberAtoms(*m, nVect);
|
|
delete m;
|
|
delete m1;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
void testGithubIssue141() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 141: "
|
|
"Kekulization of molecule with aromatic N leaves the "
|
|
"explicit H there."
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "N1C=CC=C1";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MolOps::Kekulize(*m, true);
|
|
m->updatePropertyCache(true);
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic())
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumImplicitHs() == 1)
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumExplicitHs() == 0)
|
|
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testZBO() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n";
|
|
BOOST_LOG(rdInfoLog) << "Testing ZBO basics" << std::endl;
|
|
{
|
|
auto *m = new RWMol();
|
|
|
|
m->addAtom(new Atom(26), true, true);
|
|
m->addAtom(new Atom(6), true, true);
|
|
m->addAtom(new Atom(6), true, true);
|
|
m->addAtom(new Atom(6), true, true);
|
|
m->addAtom(new Atom(6), true, true);
|
|
m->addAtom(new Atom(6), true, true);
|
|
m->addAtom(new Atom(6), true, true);
|
|
m->addBond(1, 2, Bond::AROMATIC);
|
|
m->addBond(2, 3, Bond::AROMATIC);
|
|
m->addBond(3, 4, Bond::AROMATIC);
|
|
m->addBond(4, 5, Bond::AROMATIC);
|
|
m->addBond(5, 6, Bond::AROMATIC);
|
|
m->addBond(1, 6, Bond::AROMATIC);
|
|
|
|
m->addBond(1, 0, Bond::ZERO);
|
|
m->addBond(2, 0, Bond::ZERO);
|
|
m->addBond(3, 0, Bond::ZERO);
|
|
m->addBond(4, 0, Bond::ZERO);
|
|
m->addBond(5, 0, Bond::ZERO);
|
|
m->addBond(6, 0, Bond::ZERO);
|
|
|
|
MolOps::sanitizeMol(*m);
|
|
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(0) == 0);
|
|
TEST_ASSERT(m->getRingInfo()->numAtomRings(1) == 1);
|
|
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(3)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(5)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getAtomWithIdx(6)->getHybridization() == Atom::SP2);
|
|
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(3)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(4)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getIsAromatic());
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testMolAssignment() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing operator= on molecules"
|
|
<< std::endl;
|
|
{
|
|
std::string smi =
|
|
"CCN1CCN(c2cc3[nH]c(C(=O)[C@@]4(CC)CC[C@](C)(O)CC4)nc3cc2Cl)CC1";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
std::string csmi = MolToSmiles(*m, true);
|
|
|
|
RWMol m2 = *m;
|
|
std::string nsmi = MolToSmiles(m2, true);
|
|
TEST_ASSERT(nsmi == csmi);
|
|
|
|
RWMol *m3 = SmilesToMol("C2CC2[C@H](F)Cl");
|
|
TEST_ASSERT(m3);
|
|
*m3 = *m;
|
|
nsmi = MolToSmiles(*m3, true);
|
|
TEST_ASSERT(nsmi == csmi);
|
|
delete m3;
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue190() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 190: "
|
|
"Don't merge Hs onto dummy atoms."
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "*[H]";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
namespace {
|
|
int getAtNum(const ROMol &, const Atom *at) { return at->getAtomicNum(); }
|
|
} // namespace
|
|
void testMolFragsWithQuery() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing getMolFragsWithQuery()."
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "C1CCC1ONNC";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 8);
|
|
std::map<int, boost::shared_ptr<ROMol>> res =
|
|
MolOps::getMolFragsWithQuery(*m, getAtNum);
|
|
TEST_ASSERT(res.size() == 3);
|
|
TEST_ASSERT(res.find(6) != res.end());
|
|
TEST_ASSERT(res.find(7) != res.end());
|
|
TEST_ASSERT(res.find(8) != res.end());
|
|
TEST_ASSERT(res.find(5) == res.end());
|
|
TEST_ASSERT(res[6]->getNumAtoms() == 5);
|
|
TEST_ASSERT(res[6]->getNumBonds() == 4);
|
|
TEST_ASSERT(res[7]->getNumAtoms() == 2);
|
|
TEST_ASSERT(res[7]->getNumBonds() == 1);
|
|
TEST_ASSERT(res[8]->getNumAtoms() == 1);
|
|
TEST_ASSERT(res[8]->getNumBonds() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C1CCC1ONNC";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 8);
|
|
std::vector<int> keep;
|
|
keep.push_back(6);
|
|
keep.push_back(8);
|
|
std::map<int, boost::shared_ptr<ROMol>> res =
|
|
MolOps::getMolFragsWithQuery(*m, getAtNum, true, &keep);
|
|
TEST_ASSERT(res.size() == 2);
|
|
TEST_ASSERT(res.find(6) != res.end());
|
|
TEST_ASSERT(res.find(7) == res.end());
|
|
TEST_ASSERT(res.find(8) != res.end());
|
|
TEST_ASSERT(res[6]->getNumAtoms() == 5);
|
|
TEST_ASSERT(res[6]->getNumBonds() == 4);
|
|
TEST_ASSERT(res[8]->getNumAtoms() == 1);
|
|
TEST_ASSERT(res[8]->getNumBonds() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C1CCC1ONNC";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 8);
|
|
std::vector<int> keep;
|
|
keep.push_back(6);
|
|
keep.push_back(8);
|
|
std::map<int, boost::shared_ptr<ROMol>> res =
|
|
MolOps::getMolFragsWithQuery(*m, getAtNum, true, &keep, true);
|
|
TEST_ASSERT(res.size() == 1);
|
|
TEST_ASSERT(res.find(6) == res.end());
|
|
TEST_ASSERT(res.find(7) != res.end());
|
|
TEST_ASSERT(res.find(8) == res.end());
|
|
TEST_ASSERT(res[7]->getNumAtoms() == 2);
|
|
TEST_ASSERT(res[7]->getNumBonds() == 1);
|
|
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue418() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 418: "
|
|
"removeHs not updating H count."
|
|
<< std::endl;
|
|
{
|
|
auto *m2 = new RWMol();
|
|
m2->addAtom(new Atom(7), true, true);
|
|
m2->addAtom(new Atom(1), true, true);
|
|
m2->addAtom(new Atom(1), true, true);
|
|
m2->addAtom(new Atom(1), true, true);
|
|
m2->addAtom(new Atom(1), true, true);
|
|
m2->addBond(0, 1, Bond::SINGLE);
|
|
m2->addBond(0, 2, Bond::SINGLE);
|
|
m2->addBond(0, 3, Bond::SINGLE);
|
|
m2->addBond(0, 4, Bond::SINGLE);
|
|
MolOps::removeHs(*m2, false, true, false);
|
|
TEST_ASSERT(m2->getAtomWithIdx(0)->getNumExplicitHs() == 4);
|
|
delete m2;
|
|
}
|
|
{
|
|
std::string smiles = "[H][N+]([H])([H])[H]";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 1);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getNumExplicitHs() == 4);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "[H]N([H])([H])[H]";
|
|
bool ok = false;
|
|
try {
|
|
SmilesToMol(smiles);
|
|
} catch (MolSanitizeException &) {
|
|
ok = true;
|
|
}
|
|
TEST_ASSERT(ok);
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue432() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 432: "
|
|
"problems caused by aromatic Ns with radical "
|
|
"electrons."
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "C1=NN=N[N]1";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(4)->getNumRadicalElectrons() == 1);
|
|
TEST_ASSERT(!m->getAtomWithIdx(4)->getIsAromatic());
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
}
|
|
{ // test round-tripping:
|
|
std::string smiles = "C1=NN=N[N]1";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
smiles = MolToSmiles(*m);
|
|
delete m;
|
|
m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
}
|
|
{ // test round-tripping:
|
|
std::string smiles = "OC(=O)C(=O)Nc1cccc(c1)C2=NN=N[N]2";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
smiles = MolToSmiles(*m);
|
|
delete m;
|
|
m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C1=C[N]C=C1";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getNumRadicalElectrons() == 1);
|
|
TEST_ASSERT(!m->getAtomWithIdx(2)->getIsAromatic());
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue443() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 443: "
|
|
"kekulization problems caused by any bonds."
|
|
<< std::endl;
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "github443.min.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 3));
|
|
MolOps::Kekulize(*m);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "github443.mol");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(19)->getIsAromatic());
|
|
TEST_ASSERT(m->getAtomWithIdx(12)->getIsAromatic());
|
|
// we might normally expect these to be aromatic because the outer porphyrin
|
|
// ring
|
|
// is 4n+2 aromatic. However, the current fused ring aromaticity perception
|
|
// uses
|
|
// the symmetrized SSSR rings and only works if all atoms are aromatic. This
|
|
// cannot
|
|
// happen when the Mg is involved
|
|
// TEST_ASSERT(m->getAtomWithIdx(13)->getIsAromatic());
|
|
// TEST_ASSERT(m->getAtomWithIdx(11)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(13, 20));
|
|
TEST_ASSERT(m->getBondBetweenAtoms(19, 20));
|
|
TEST_ASSERT(m->getBondBetweenAtoms(11, 20));
|
|
TEST_ASSERT(m->getBondBetweenAtoms(12, 20));
|
|
MolOps::Kekulize(*m);
|
|
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue447() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 447: "
|
|
"Radicals are not correctly assigned when reading "
|
|
"from SMILES."
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "C[S]";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNoImplicit());
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C[SH]C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNoImplicit());
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C[SH3]C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNoImplicit());
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C[SH4]C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNoImplicit());
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNumRadicalElectrons() == 0);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C[SH4+]C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNoImplicit());
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smiles = "C[P]C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNoImplicit());
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C[PH2]C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNoImplicit());
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getNumRadicalElectrons() == 1);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGetMolFrags() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing generation of new "
|
|
"molecules from molecule fragments"
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "c1ccccc1.O.CCC(=O)O";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
|
|
INT_VECT fragsMapping;
|
|
VECT_INT_VECT fragsMolAtomMapping;
|
|
std::vector<ROMOL_SPTR> frags =
|
|
MolOps::getMolFrags(*m, false, &fragsMapping, &fragsMolAtomMapping);
|
|
|
|
TEST_ASSERT(frags.size() == 3)
|
|
TEST_ASSERT(fragsMapping.size() == m->getNumAtoms());
|
|
|
|
TEST_ASSERT(fragsMapping[2] == 0);
|
|
TEST_ASSERT(fragsMapping[6] == 1);
|
|
TEST_ASSERT(fragsMapping[8] == 2);
|
|
TEST_ASSERT(fragsMolAtomMapping[0].size() == frags[0]->getNumAtoms());
|
|
TEST_ASSERT(fragsMolAtomMapping[1].size() == frags[1]->getNumAtoms());
|
|
TEST_ASSERT(fragsMolAtomMapping[2].size() == frags[2]->getNumAtoms());
|
|
TEST_ASSERT(fragsMolAtomMapping[0][1] == 1);
|
|
TEST_ASSERT(fragsMolAtomMapping[1][0] == 6);
|
|
TEST_ASSERT(fragsMolAtomMapping[2][1] == 8);
|
|
|
|
TEST_ASSERT(MolToSmiles(*frags[0], true) == "c1ccccc1");
|
|
TEST_ASSERT(MolToSmiles(*frags[1], true) == "O");
|
|
TEST_ASSERT(MolToSmiles(*frags[2], true) == "CCC(=O)O");
|
|
delete m;
|
|
}
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
RWMol *m = MolFileToMol(pathName + "chembl1203199.mol");
|
|
TEST_ASSERT(m);
|
|
std::string smi = "C[C@H](NC(=O)[C@H]1Cc2c(sc3ccccc23)CN1)c1ccccc1.Cl";
|
|
TEST_ASSERT(MolToSmiles(*m, true) == smi);
|
|
|
|
INT_VECT fragsMapping;
|
|
VECT_INT_VECT fragsMolAtomMapping;
|
|
std::vector<ROMOL_SPTR> frags = MolOps::getMolFrags(
|
|
*m, false, &fragsMapping, &fragsMolAtomMapping, true);
|
|
|
|
TEST_ASSERT(frags.size() == 2)
|
|
TEST_ASSERT(fragsMapping.size() == m->getNumAtoms());
|
|
TEST_ASSERT(fragsMapping[2] == 0);
|
|
TEST_ASSERT(fragsMapping[24] == 1);
|
|
TEST_ASSERT(fragsMolAtomMapping[0].size() == frags[0]->getNumAtoms());
|
|
TEST_ASSERT(fragsMolAtomMapping[1].size() == frags[1]->getNumAtoms());
|
|
TEST_ASSERT(fragsMolAtomMapping[0][1] == 1);
|
|
TEST_ASSERT(fragsMolAtomMapping[1][0] == 24);
|
|
|
|
TEST_ASSERT(frags[0]->getNumConformers() == 1);
|
|
TEST_ASSERT(frags[1]->getNumConformers() == 1);
|
|
|
|
TEST_ASSERT(frags[0]->getConformer(0).getAtomPos(0).x ==
|
|
m->getConformer(0).getAtomPos(0).x);
|
|
TEST_ASSERT(frags[0]->getConformer(0).getAtomPos(0).y ==
|
|
m->getConformer(0).getAtomPos(0).y);
|
|
TEST_ASSERT(frags[0]->getConformer(0).getAtomPos(0).z ==
|
|
m->getConformer(0).getAtomPos(0).z);
|
|
|
|
TEST_ASSERT(frags[0]->getConformer(0).getAtomPos(3).x ==
|
|
m->getConformer(0).getAtomPos(3).x);
|
|
TEST_ASSERT(frags[0]->getConformer(0).getAtomPos(3).y ==
|
|
m->getConformer(0).getAtomPos(3).y);
|
|
TEST_ASSERT(frags[0]->getConformer(0).getAtomPos(3).z ==
|
|
m->getConformer(0).getAtomPos(3).z);
|
|
|
|
TEST_ASSERT(frags[1]->getConformer(0).getAtomPos(0).x ==
|
|
m->getConformer(0).getAtomPos(24).x);
|
|
TEST_ASSERT(frags[1]->getConformer(0).getAtomPos(0).y ==
|
|
m->getConformer(0).getAtomPos(24).y);
|
|
TEST_ASSERT(frags[1]->getConformer(0).getAtomPos(0).z ==
|
|
m->getConformer(0).getAtomPos(24).z);
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
namespace {
|
|
void hypervalent_check(const char *smiles) {
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getFormalCharge() == -1);
|
|
delete m;
|
|
}
|
|
} // namespace
|
|
void testGithubIssue510() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 510: "
|
|
"Hexafluorophosphate cannot be handled"
|
|
<< std::endl;
|
|
hypervalent_check("F[P-](F)(F)(F)(F)F");
|
|
// test #1668 too, it's the same thing but with As, Sb, and Bi
|
|
hypervalent_check("F[As-](F)(F)(F)(F)F");
|
|
hypervalent_check("F[Sb-](F)(F)(F)(F)F");
|
|
hypervalent_check("F[Bi-](F)(F)(F)(F)F");
|
|
|
|
hypervalent_check("F[Sb-](F)(F)(F)(F)F");
|
|
hypervalent_check("F[Bi-](F)(F)(F)(F)F");
|
|
|
|
// we also added a valence of 5 for Bi:
|
|
hypervalent_check("F[Bi-](F)(F)F");
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue526() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 526: "
|
|
"Bad ring finding in a complex fused ring"
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "N1C2[C@@H]3N[C@H]4[C@@H]5N[C@@H]([C@@H]1C35)C24";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 6);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles =
|
|
"NN1C2C3[C@@H]4[C@@H]1C1[C@H]2N([C@H]3[C@@H]1N4N1C(=O)C2=C(C=CC=C2)C1="
|
|
"O)N1C(=O)C2=C(C=CC=C2)C1=O";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getRingInfo()->numRings() == 10);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue539() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 539: "
|
|
"Lack of conjugation in allyl cations, "
|
|
"lack of aromaticity perception/ability to kekulize "
|
|
"aromatic carbocations such as cyclopropenyl and "
|
|
"tropylium"
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "C=C-[CH2+]";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
bool allConjugated = true;
|
|
for (unsigned int i = 0; allConjugated && i < m->getNumBonds(); ++i) {
|
|
allConjugated = m->getBondWithIdx(i)->getIsConjugated();
|
|
}
|
|
TEST_ASSERT(allConjugated);
|
|
delete m;
|
|
}
|
|
{
|
|
std::vector<std::string> smilesVec;
|
|
smilesVec.emplace_back("C1=C[CH+]1");
|
|
smilesVec.emplace_back("C1=CC=C[CH+]C=C1");
|
|
smilesVec.emplace_back("c1c[cH+]1");
|
|
smilesVec.emplace_back("c1ccc[cH+]cc1");
|
|
for (std::vector<std::string>::const_iterator smiles = smilesVec.begin();
|
|
smiles != smilesVec.end(); ++smiles) {
|
|
RWMol *m = SmilesToMol(*smiles);
|
|
TEST_ASSERT(m);
|
|
bool allConjugated = true;
|
|
for (unsigned int i = 0; allConjugated && i < m->getNumBonds(); ++i) {
|
|
allConjugated = m->getBondWithIdx(i)->getIsConjugated();
|
|
}
|
|
TEST_ASSERT(allConjugated);
|
|
bool allAromatic = true;
|
|
for (unsigned int i = 0; allAromatic && i < m->getNumBonds(); ++i) {
|
|
allAromatic = m->getBondWithIdx(i)->getIsAromatic();
|
|
}
|
|
TEST_ASSERT(allAromatic);
|
|
delete m;
|
|
}
|
|
}
|
|
|
|
{
|
|
std::string smiles = "C=C-C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(!m->getBondWithIdx(1)->getIsConjugated());
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smiles = "C=C-O";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getIsConjugated());
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smiles = "C=C-N";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getHybridization() == Atom::SP2);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getIsConjugated());
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
std::string smiles = "C=C-[NH3+]";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getHybridization() == Atom::SP3);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(!m->getBondWithIdx(1)->getIsConjugated());
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "Cc1ccccc1";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getBondType() == Bond::SINGLE);
|
|
// the bond to the CH3 should not be conjugated, but the others are
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsConjugated());
|
|
for (unsigned int i = 1; i < m->getNumBonds(); ++i) {
|
|
TEST_ASSERT(m->getBondWithIdx(i)->getIsConjugated());
|
|
}
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "Fc1c[nH]c(=O)[nH]c1=O";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getBondType() == Bond::SINGLE);
|
|
// the bond to the F should not be conjugated, but the others are
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsConjugated());
|
|
for (unsigned int i = 1; i < m->getNumBonds(); ++i) {
|
|
TEST_ASSERT(m->getBondWithIdx(i)->getIsConjugated());
|
|
}
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testAdjustQueryProperties() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing adjustQueryProperties()"
|
|
<< std::endl;
|
|
#if 1
|
|
{ // basics from SMILES
|
|
std::string smiles = "C1CCC1C";
|
|
ROMol *qm = SmilesToMol(smiles);
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 5);
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 5);
|
|
{
|
|
smiles = "C1CCC1CC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
{
|
|
smiles = "C1C(C)CC1CC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
|
|
delete qm;
|
|
delete aqm;
|
|
}
|
|
{ // basics from SMARTS
|
|
std::string smiles = "C1CCC1*";
|
|
ROMol *qm = SmartsToMol(smiles);
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 5);
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 5);
|
|
{
|
|
smiles = "C1CCC1CC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
{
|
|
smiles = "C1C(C)CC1CC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
|
|
delete qm;
|
|
delete aqm;
|
|
}
|
|
|
|
{
|
|
std::string smiles = "C1CC(*)C1*";
|
|
ROMol *qm = SmartsToMol(smiles);
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 6);
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 6);
|
|
{
|
|
smiles = "C1CC2C1CC2";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
|
|
MolOps::AdjustQueryParameters aqp;
|
|
|
|
delete aqm;
|
|
aqp.adjustDegree = false;
|
|
aqp.adjustRingCount = false;
|
|
aqm = MolOps::adjustQueryProperties(*qm, &aqp);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 6);
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
|
|
delete aqm;
|
|
aqp.adjustDegree = false;
|
|
aqp.adjustRingCount = true;
|
|
aqm = MolOps::adjustQueryProperties(*qm, &aqp);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 6);
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
|
|
delete aqm;
|
|
aqp.adjustDegree = true;
|
|
aqp.adjustRingCount = false;
|
|
aqp.adjustDegreeFlags = MolOps::ADJUST_IGNORENONE;
|
|
aqm = MolOps::adjustQueryProperties(*qm, &aqp);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 6);
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
|
|
delete m;
|
|
}
|
|
|
|
{
|
|
smiles = "C1CC(C2CC2)C1C2CC2";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
delete aqm;
|
|
aqm = MolOps::adjustQueryProperties(*qm);
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
|
|
MolOps::AdjustQueryParameters aqp;
|
|
|
|
delete aqm;
|
|
aqp.adjustRingCount = true;
|
|
aqm = MolOps::adjustQueryProperties(*qm, &aqp);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 6);
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
|
|
delete aqm;
|
|
aqp.adjustRingCountFlags =
|
|
MolOps::ADJUST_IGNORENONE; // neither "not dummy"
|
|
// nor "in ring"
|
|
// restrictions
|
|
aqm = MolOps::adjustQueryProperties(*qm, &aqp);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 6);
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
|
|
delete aqm;
|
|
aqp.adjustRingCountFlags =
|
|
MolOps::ADJUST_IGNOREDUMMIES; // no "in ring" restrictions
|
|
aqm = MolOps::adjustQueryProperties(*qm, &aqp);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 6);
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
|
|
delete m;
|
|
}
|
|
|
|
delete qm;
|
|
delete aqm;
|
|
}
|
|
|
|
{ // dummies from SMILES
|
|
std::string smiles = "C1CCC1*";
|
|
ROMol *qm = SmilesToMol(smiles);
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 5);
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 5);
|
|
|
|
smiles = "C1CCC1CC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
|
|
delete aqm;
|
|
MolOps::AdjustQueryParameters aqp;
|
|
aqp.makeDummiesQueries = false;
|
|
aqm = MolOps::adjustQueryProperties(*qm, &aqp);
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
|
|
delete m;
|
|
delete qm;
|
|
delete aqm;
|
|
}
|
|
{ // dummies from SMILES 2
|
|
std::string smiles = "C1CCC1[1*]";
|
|
ROMol *qm = SmilesToMol(smiles);
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 5);
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 5);
|
|
{
|
|
smiles = "C1CCC1CC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete qm;
|
|
delete aqm;
|
|
}
|
|
{ // dummies from SMILES 2
|
|
std::string smiles = "C1CCC1[*:1]";
|
|
ROMol *qm = SmilesToMol(smiles);
|
|
qm->getAtomWithIdx(4)->setProp<int>("foo", 2);
|
|
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 5);
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 5);
|
|
TEST_ASSERT(aqm->getAtomWithIdx(4)->getProp<int>("foo") == 2);
|
|
TEST_ASSERT(aqm->getAtomWithIdx(4)->getAtomMapNum() == 1);
|
|
{
|
|
smiles = "C1CCC1CC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete qm;
|
|
delete aqm;
|
|
}
|
|
{ // CTAB
|
|
// -- only match rgroups
|
|
std::string mb =
|
|
"adjust.mol\n"
|
|
" ChemDraw06271617272D\n"
|
|
"\n"
|
|
" 7 7 0 0 0 0 0 0 0 0999 V2000\n"
|
|
" -1.0717 0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.0717 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -0.3572 -0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 0.3572 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 0.3572 0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -0.3572 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 1.0717 0.8250 0.0000 R 0 0 0 0 0 0 0 0 0 1 0 "
|
|
"0\n"
|
|
" 1 2 1 0 \n"
|
|
" 2 3 2 0 \n"
|
|
" 3 4 1 0 \n"
|
|
" 4 5 2 0 \n"
|
|
" 5 6 1 0 \n"
|
|
" 6 1 2 0 \n"
|
|
" 5 7 1 0 \n"
|
|
"M END\n";
|
|
MolOps::AdjustQueryParameters params;
|
|
params.aromatizeIfPossible = false;
|
|
params.makeDummiesQueries = true;
|
|
params.adjustDegreeFlags =
|
|
(MolOps::ADJUST_IGNOREDUMMIES | MolOps::ADJUST_IGNORECHAINS |
|
|
MolOps::ADJUST_IGNOREMAPPED);
|
|
|
|
RWMol *m = MolBlockToMol(mb, false, false);
|
|
MolOps::adjustQueryProperties(*m, ¶ms);
|
|
MatchVectType match;
|
|
ROMol *t = SmilesToMol("c1ccccc1Cl");
|
|
// shouldn't match (aromaticity):
|
|
TEST_ASSERT(!SubstructMatch(*t, *m, match));
|
|
// adjust aromaticity and then it should match:
|
|
params.aromatizeIfPossible = true;
|
|
MolOps::adjustQueryProperties(*m, ¶ms);
|
|
TEST_ASSERT(SubstructMatch(*t, *m, match));
|
|
|
|
delete t;
|
|
// shouldn't match (explicit degree)
|
|
t = SmilesToMol("c1ccc(Cl)cc1Cl");
|
|
TEST_ASSERT(!SubstructMatch(*t, *m, match));
|
|
delete m;
|
|
delete t;
|
|
}
|
|
|
|
{ // CTAB
|
|
// -- match non rgroups if mapped
|
|
std::string mb =
|
|
"adjust.mol\n"
|
|
" ChemDraw06271617272D\n"
|
|
"\n"
|
|
" 7 7 0 0 0 0 0 0 0 0999 V2000\n"
|
|
" -1.0717 0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 2 0 "
|
|
"0\n"
|
|
" -1.0717 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 3 0 "
|
|
"0\n"
|
|
" -0.3572 -0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 4 0 "
|
|
"0\n"
|
|
" 0.3572 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 5 0 "
|
|
"0\n"
|
|
" 0.3572 0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 6 0 "
|
|
"0\n"
|
|
" -0.3572 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 7 0 "
|
|
"0\n"
|
|
" 1.0717 0.8250 0.0000 R 0 0 0 0 0 0 0 0 0 1 0 "
|
|
"0\n"
|
|
" 1 2 1 0 \n"
|
|
" 2 3 2 0 \n"
|
|
" 3 4 1 0 \n"
|
|
" 4 5 2 0 \n"
|
|
" 5 6 1 0 \n"
|
|
" 6 1 2 0 \n"
|
|
" 5 7 1 0 \n"
|
|
"M END\n";
|
|
MolOps::AdjustQueryParameters params;
|
|
params.aromatizeIfPossible = true;
|
|
params.makeDummiesQueries = true;
|
|
params.adjustDegreeFlags =
|
|
(MolOps::ADJUST_IGNOREDUMMIES | MolOps::ADJUST_IGNORECHAINS |
|
|
MolOps::ADJUST_IGNOREMAPPED);
|
|
|
|
RWMol *m = MolBlockToMol(mb);
|
|
MolOps::adjustQueryProperties(*m, ¶ms);
|
|
MatchVectType match;
|
|
ROMol *t = SmilesToMol("c1ccccc1Cl");
|
|
TEST_ASSERT(SubstructMatch(*t, *m, match));
|
|
delete t;
|
|
// should match (mapped!)
|
|
t = SmilesToMol("c1c(Cl)cc(Cl)cc1Cl");
|
|
TEST_ASSERT(SubstructMatch(*t, *m, match));
|
|
delete m;
|
|
delete t;
|
|
}
|
|
#endif
|
|
{ // make atoms generic
|
|
std::string smiles = "C1CC1CC";
|
|
ROMol *qm = SmilesToMol(smiles);
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 5);
|
|
|
|
{
|
|
MolOps::AdjustQueryParameters params;
|
|
params.makeAtomsGeneric = true;
|
|
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm, ¶ms);
|
|
// std::cerr << MolToSmarts(*aqm) << std::endl;
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == qm->getNumAtoms());
|
|
{
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*qm, *aqm, match));
|
|
std::string smiles = "O1CN1NN";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
// std::cerr << MolToSmiles(*m) << std::endl;
|
|
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete aqm;
|
|
}
|
|
{
|
|
MolOps::AdjustQueryParameters params;
|
|
params.makeAtomsGeneric = true;
|
|
params.makeAtomsGenericFlags = MolOps::ADJUST_IGNORECHAINS;
|
|
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm, ¶ms);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == qm->getNumAtoms());
|
|
{
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*qm, *aqm, match));
|
|
std::string smiles = "O1CN1NN";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
smiles = "O1CN1CC";
|
|
m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete aqm;
|
|
}
|
|
{
|
|
MolOps::AdjustQueryParameters params;
|
|
params.makeAtomsGeneric = true;
|
|
params.makeAtomsGenericFlags = MolOps::ADJUST_IGNORERINGS;
|
|
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm, ¶ms);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == qm->getNumAtoms());
|
|
{
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*qm, *aqm, match));
|
|
std::string smiles = "O1CN1NN";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
smiles = "C1CC1NN";
|
|
m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete aqm;
|
|
}
|
|
|
|
delete qm;
|
|
}
|
|
|
|
{ // make bonds generic
|
|
std::string smiles = "N1C=C1C=C";
|
|
ROMol *qm = SmilesToMol(smiles);
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 5);
|
|
|
|
{
|
|
MolOps::AdjustQueryParameters params;
|
|
params.makeBondsGeneric = true;
|
|
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm, ¶ms);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == qm->getNumAtoms());
|
|
{
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*qm, *aqm, match));
|
|
std::string smiles = "N1=CC1=CC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete aqm;
|
|
}
|
|
{
|
|
MolOps::AdjustQueryParameters params;
|
|
params.makeBondsGeneric = true;
|
|
params.makeBondsGenericFlags = MolOps::ADJUST_IGNORECHAINS;
|
|
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm, ¶ms);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == qm->getNumAtoms());
|
|
{
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*qm, *aqm, match));
|
|
std::string smiles = "N1=CC1=C=C";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
smiles = "N1=CC1C=C";
|
|
m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete aqm;
|
|
}
|
|
{
|
|
MolOps::AdjustQueryParameters params;
|
|
params.makeBondsGeneric = true;
|
|
params.makeBondsGenericFlags = MolOps::ADJUST_IGNORERINGS;
|
|
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm, ¶ms);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == qm->getNumAtoms());
|
|
{
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*qm, *aqm, match));
|
|
std::string smiles = "N1=CC1=C=C";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
smiles = "N1C=C1CC#C";
|
|
m = SmilesToMol(smiles);
|
|
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(!SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete aqm;
|
|
}
|
|
|
|
delete qm;
|
|
}
|
|
|
|
{ // heavy atom degree
|
|
std::string smiles = "C1CC(*)C1*";
|
|
ROMol *qm = SmartsToMol(smiles);
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 6);
|
|
MolOps::AdjustQueryParameters params;
|
|
params.adjustDegree = false;
|
|
params.adjustHeavyDegree = true;
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm, ¶ms);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 6);
|
|
{
|
|
smiles = "C1CC(C)C1(C)";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
{
|
|
smiles = "C1CC([2H])C1(C)";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete qm;
|
|
delete aqm;
|
|
}
|
|
|
|
{ // ring-chain membership
|
|
std::string smiles = "CC1CCC1";
|
|
ROMol *qm = SmartsToMol(smiles);
|
|
TEST_ASSERT(qm);
|
|
TEST_ASSERT(qm->getNumAtoms() == 5);
|
|
MolOps::AdjustQueryParameters params;
|
|
params.adjustRingChain = true;
|
|
params.adjustDegree = false;
|
|
ROMol *aqm = MolOps::adjustQueryProperties(*qm, ¶ms);
|
|
TEST_ASSERT(aqm);
|
|
TEST_ASSERT(aqm->getNumAtoms() == 5);
|
|
{
|
|
smiles = "C1CCC12CCC2";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(!SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
{
|
|
smiles = "C1CCC1CCC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*m, *qm, match));
|
|
TEST_ASSERT(SubstructMatch(*m, *aqm, match));
|
|
delete m;
|
|
}
|
|
delete qm;
|
|
delete aqm;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue678() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 678: "
|
|
"failure in AddHs when addCoords is true and coords are all zero"
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "CC";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
auto *conf = new Conformer(2);
|
|
m->addConformer(conf);
|
|
MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m->getNumAtoms() == 8);
|
|
delete m;
|
|
}
|
|
|
|
{ // single connected atom with degenerate coords
|
|
std::string mb =
|
|
"example\n"
|
|
" Mrv0541 12171503572D \n"
|
|
"\n"
|
|
" 7 8 0 0 0 0 999 V2000\n"
|
|
" -3.5063 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -3.5063 1.7089 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -2.6813 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -2.6813 1.7089 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.8563 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.8563 1.7089 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.8563 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 1 2 1 0 0 0 0\n"
|
|
" 1 3 1 0 0 0 0\n"
|
|
" 3 4 1 0 0 0 0\n"
|
|
" 2 4 1 0 0 0 0\n"
|
|
" 3 5 1 0 0 0 0\n"
|
|
" 5 6 1 0 0 0 0\n"
|
|
" 4 6 1 0 0 0 0\n"
|
|
" 5 7 1 0 0 0 0\n"
|
|
"M END\n";
|
|
RWMol *m = MolBlockToMol(mb);
|
|
TEST_ASSERT(m);
|
|
MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m->getNumAtoms() == 19);
|
|
delete m;
|
|
}
|
|
{ // doubly connected atom(s) with degenerate coords
|
|
std::string mb =
|
|
"example\n"
|
|
" Mrv0541 12171503572D \n"
|
|
"\n"
|
|
" 7 8 0 0 0 0 999 V2000\n"
|
|
" -3.5063 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -3.5063 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -2.6813 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -2.6813 1.7089 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.8563 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.8563 1.7089 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.2729 3.1173 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 1 2 1 0 0 0 0\n"
|
|
" 1 3 1 0 0 0 0\n"
|
|
" 3 4 1 0 0 0 0\n"
|
|
" 2 4 1 0 0 0 0\n"
|
|
" 3 5 1 0 0 0 0\n"
|
|
" 5 6 1 0 0 0 0\n"
|
|
" 4 6 1 0 0 0 0\n"
|
|
" 5 7 1 0 0 0 0\n"
|
|
"M END\n";
|
|
RWMol *m = MolBlockToMol(mb);
|
|
TEST_ASSERT(m);
|
|
MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m->getNumAtoms() == 19);
|
|
delete m;
|
|
}
|
|
|
|
{ // triply connected atom(s) with degenerate coords
|
|
std::string mb =
|
|
"example\n"
|
|
" Mrv0541 12171503572D \n"
|
|
"\n"
|
|
" 7 8 0 0 0 0 999 V2000\n"
|
|
" -3.5063 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -3.5063 1.7089 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -3.5063 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -3.5063 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.8563 2.5339 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.8563 1.7089 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" -1.2729 3.1173 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 1 2 1 0 0 0 0\n"
|
|
" 1 3 1 0 0 0 0\n"
|
|
" 3 4 1 0 0 0 0\n"
|
|
" 2 4 1 0 0 0 0\n"
|
|
" 3 5 1 0 0 0 0\n"
|
|
" 5 6 1 0 0 0 0\n"
|
|
" 4 6 1 0 0 0 0\n"
|
|
" 5 7 1 0 0 0 0\n"
|
|
"M END\n";
|
|
RWMol *m = MolBlockToMol(mb);
|
|
TEST_ASSERT(m);
|
|
MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m->getNumAtoms() == 19);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue717() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 717: "
|
|
"AddHs cip rank is declared <int> should be unsigned int"
|
|
<< std::endl;
|
|
|
|
{ // single connected atom with degenerate coords
|
|
std::string mb =
|
|
"mol\n"
|
|
" Mrv1561 01051606293D\n"
|
|
"\n"
|
|
" 4 3 0 0 0 0 999 V2000\n"
|
|
" -0.0080 -0.0000 -0.0004 C 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 1.5343 -0.0050 0.0032 C 0 0 1 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 2.1517 -0.8276 1.4332 Cl 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 2.0123 -0.6447 -1.1142 F 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n"
|
|
" 2 3 1 0 0 0 0\n"
|
|
" 2 4 1 0 0 0 0\n"
|
|
" 2 1 1 0 0 0 0\n"
|
|
"M END\n";
|
|
RWMol *m = MolBlockToMol(mb);
|
|
TEST_ASSERT(m);
|
|
MolOps::assignChiralTypesFrom3D(*m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m->getNumAtoms() == 8);
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testPotentialStereoBonds() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing findPotentialStereoBonds"
|
|
<< std::endl;
|
|
|
|
{ // starting point: full sanitization
|
|
auto m1 = "BrC(=NN=c1nn[nH][nH]1)c1ccncc1"_smiles;
|
|
TEST_ASSERT(m1);
|
|
std::string smiles =
|
|
"Br/C(=N\\N=c1/nn[nH][nH]1)c1ccncc1"; // possible problem reported by
|
|
// Steve Roughley
|
|
ROMol *m = SmilesToMol(smiles);
|
|
// m->updatePropertyCache(false);
|
|
// m->debugMol(std::cerr);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 15);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
TEST_ASSERT(m->getBondWithIdx(3)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(3)->getStereoAtoms().size() == 2);
|
|
delete m;
|
|
|
|
// partial sanitization:
|
|
m = SmilesToMol(smiles, false, false);
|
|
TEST_ASSERT(m);
|
|
m->updatePropertyCache(true);
|
|
MolOps::findSSSR(*m);
|
|
MolOps::findPotentialStereoBonds(*m, false);
|
|
TEST_ASSERT(m->getNumAtoms() == 15);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
TEST_ASSERT(m->getBondWithIdx(3)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(3)->getStereoAtoms().size() == 2);
|
|
delete m;
|
|
}
|
|
|
|
// this next block is for github1230: FindPotentialStereoBonds() failure
|
|
{ // simple
|
|
std::string smiles = "CC=CC";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREONONE);
|
|
|
|
MolOps::findPotentialStereoBonds(*m, true);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREOANY);
|
|
|
|
delete m;
|
|
}
|
|
{ // simple2
|
|
std::string smiles = "CC=C(C)C";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREONONE);
|
|
|
|
MolOps::findPotentialStereoBonds(*m, true);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREONONE);
|
|
|
|
delete m;
|
|
}
|
|
{ // the real problem
|
|
std::string smiles = "CC/C=C/C(\\C=C/CC)=C(CC)CO";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 14);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getStereo() == Bond::STEREONONE);
|
|
MolOps::findPotentialStereoBonds(*m, true);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereo() == Bond::STEREOANY);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getStereo() == Bond::STEREOANY);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getStereo() == Bond::STEREOANY);
|
|
|
|
delete m;
|
|
}
|
|
{ // repeat the real problem, but set the cleanIt argument to false
|
|
std::string smiles = "CC/C=C/C(\\C=C/CC)=C(CC)CO";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 14);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getStereo() == Bond::STEREONONE);
|
|
MolOps::findPotentialStereoBonds(*m, false);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getStereo() == Bond::STEREOANY);
|
|
|
|
delete m;
|
|
}
|
|
|
|
{ // just do document that we still don't do this one, which is much harder
|
|
std::string smiles = "CC/C=C/C(/C=C/CC)=C(CC)CO";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 14);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getStereo() == Bond::STEREONONE);
|
|
MolOps::findPotentialStereoBonds(*m, true);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getStereo() == Bond::STEREOANY);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getStereo() == Bond::STEREOANY);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(8)->getStereo() == Bond::STEREONONE);
|
|
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSetBondStereo() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing "
|
|
"Bond::setStereo(Bond::STEREOCIS / Bond::STEREOTRANS)"
|
|
<< std::endl;
|
|
|
|
// tests to make sure neighboring bond stereo is handled properly
|
|
{
|
|
const char *smiles[] = {"CC=CC", "CC=C/C=C/C", "CC=C/C=C\\C",
|
|
"CC=C\\C=C/C", "CC=C\\C=C\\C", "C(C)=CC",
|
|
"C(C)=C/C=C/C", "C(C)=C/C=C\\C", "C(C)=C\\C=C/C",
|
|
"C(C)=C\\C=C\\C"};
|
|
const Bond::BondStereo stereos[] = {Bond::STEREOCIS, Bond::STEREOTRANS};
|
|
const Bond::BondStereo ezstros[] = {Bond::STEREOZ, Bond::STEREOE};
|
|
|
|
for (auto &smile : smiles) {
|
|
ROMol *m = SmilesToMol(smile);
|
|
MolOps::findPotentialStereoBonds(*m);
|
|
Bond *bond = m->getBondWithIdx(1);
|
|
|
|
for (size_t j = 0; j < 2; ++j) {
|
|
Bond::BondStereo desired_stereo = stereos[j];
|
|
bond->setStereo(desired_stereo);
|
|
|
|
bool doIsomericSmiles = true;
|
|
bool doKekule = false;
|
|
int rootedAtAtom = -1;
|
|
bool canonical = false;
|
|
std::string isosmi = MolToSmiles(*m, doIsomericSmiles, doKekule,
|
|
rootedAtAtom, canonical);
|
|
|
|
ROMol *isomol = SmilesToMol(isosmi);
|
|
Bond *isobond = isomol->getBondWithIdx(1);
|
|
const Bond::BondStereo expected_ez_stereo = ezstros[j];
|
|
TEST_ASSERT(isobond->getStereo() == expected_ez_stereo);
|
|
|
|
std::string round_trip_isosmi = MolToSmiles(
|
|
*m, doIsomericSmiles, doKekule, rootedAtAtom, canonical);
|
|
TEST_ASSERT(isosmi == round_trip_isosmi);
|
|
|
|
BOOST_LOG(rdInfoLog) << isosmi << " == " << round_trip_isosmi << " "
|
|
<< desired_stereo << std::endl;
|
|
|
|
delete isomol;
|
|
}
|
|
delete m;
|
|
}
|
|
}
|
|
|
|
// tests enumerating all possible smiles with halogens still yield
|
|
// the same isomeric canonical smiles strings.
|
|
{
|
|
const char *smiles[] = {"ClC=CF", "FC=CCl", "C(Cl)=CF", "C(F)=CCl"};
|
|
const Bond::BondStereo stereos[] = {Bond::STEREOCIS, Bond::STEREOTRANS};
|
|
|
|
for (auto desired_stereo : stereos) {
|
|
std::string refSmiles;
|
|
for (auto &smile : smiles) {
|
|
ROMol *m = SmilesToMol(smile);
|
|
MolOps::findPotentialStereoBonds(*m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
|
|
Bond *doubleBond = m->getBondWithIdx(1);
|
|
doubleBond->setStereo(desired_stereo);
|
|
|
|
bool doIsomericSmiles = true;
|
|
std::string isocansmi = MolToSmiles(*m, doIsomericSmiles);
|
|
|
|
if (refSmiles.empty()) {
|
|
refSmiles = isocansmi;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << refSmiles << " == " << isocansmi << " "
|
|
<< desired_stereo << std::endl;
|
|
TEST_ASSERT(refSmiles == isocansmi);
|
|
|
|
delete m;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void testBondSetStereoAtoms() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing Bond::setStereoAtoms(...)"
|
|
<< std::endl;
|
|
|
|
// tests to make sure setStereoAtoms works as expected
|
|
{
|
|
bool doIsomericSmiles = true;
|
|
std::string unspec_smiles = "FC(Cl)=C(Br)I";
|
|
|
|
ROMol *m = SmilesToMol(unspec_smiles);
|
|
|
|
Bond *doubleBond = m->getBondWithIdx(2);
|
|
TEST_ASSERT(doubleBond->getBondType() == 2);
|
|
|
|
doubleBond->setStereoAtoms(0, 4);
|
|
doubleBond->setStereo(Bond::STEREOCIS);
|
|
BOOST_LOG(rdInfoLog) << MolToSmiles(*m, doIsomericSmiles) << std::endl;
|
|
TEST_ASSERT(MolToSmiles(*m, doIsomericSmiles) == "F/C(Cl)=C(\\Br)I");
|
|
// this should be the same as the previous
|
|
doubleBond->setStereoAtoms(0, 5);
|
|
doubleBond->setStereo(Bond::STEREOTRANS);
|
|
BOOST_LOG(rdInfoLog) << MolToSmiles(*m, doIsomericSmiles) << std::endl;
|
|
TEST_ASSERT(MolToSmiles(*m, doIsomericSmiles) == "F/C(Cl)=C(\\Br)I");
|
|
|
|
doubleBond->setStereoAtoms(0, 4);
|
|
doubleBond->setStereo(Bond::STEREOTRANS);
|
|
BOOST_LOG(rdInfoLog) << MolToSmiles(*m, doIsomericSmiles) << std::endl;
|
|
TEST_ASSERT(MolToSmiles(*m, doIsomericSmiles) == "F/C(Cl)=C(/Br)I");
|
|
// this should be the same as the previous
|
|
doubleBond->setStereoAtoms(0, 5);
|
|
doubleBond->setStereo(Bond::STEREOCIS);
|
|
BOOST_LOG(rdInfoLog) << MolToSmiles(*m, doIsomericSmiles) << std::endl;
|
|
TEST_ASSERT(MolToSmiles(*m, doIsomericSmiles) == "F/C(Cl)=C(/Br)I");
|
|
|
|
doubleBond->setStereoAtoms(3, 4);
|
|
doubleBond->setStereo(Bond::STEREOTRANS);
|
|
BOOST_LOG(rdInfoLog) << MolToSmiles(*m, doIsomericSmiles) << std::endl;
|
|
TEST_ASSERT(MolToSmiles(*m, doIsomericSmiles) == "F/C(Cl)=C(\\Br)I");
|
|
// this should be the same as the previous
|
|
doubleBond->setStereoAtoms(3, 5);
|
|
doubleBond->setStereo(Bond::STEREOCIS);
|
|
BOOST_LOG(rdInfoLog) << MolToSmiles(*m, doIsomericSmiles) << std::endl;
|
|
TEST_ASSERT(MolToSmiles(*m, doIsomericSmiles) == "F/C(Cl)=C(\\Br)I");
|
|
|
|
doubleBond->setStereoAtoms(3, 4);
|
|
doubleBond->setStereo(Bond::STEREOCIS);
|
|
BOOST_LOG(rdInfoLog) << MolToSmiles(*m, doIsomericSmiles) << std::endl;
|
|
TEST_ASSERT(MolToSmiles(*m, doIsomericSmiles) == "F/C(Cl)=C(/Br)I");
|
|
// this should be the same as the previous
|
|
doubleBond->setStereoAtoms(3, 5);
|
|
doubleBond->setStereo(Bond::STEREOTRANS);
|
|
BOOST_LOG(rdInfoLog) << MolToSmiles(*m, doIsomericSmiles) << std::endl;
|
|
TEST_ASSERT(MolToSmiles(*m, doIsomericSmiles) == "F/C(Cl)=C(/Br)I");
|
|
delete m;
|
|
;
|
|
}
|
|
}
|
|
|
|
void testGithubIssue754() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github #754 : "
|
|
"loss of double bond geometry with removeHs"
|
|
<< std::endl;
|
|
{ // starting point: full sanitization
|
|
std::string smiles =
|
|
"[H]C([H])([H])/C([H])=C(/[H])C([H])([H])[H]"; // possible problem
|
|
// reported by
|
|
// Steve Roughley
|
|
RWMol *m = SmilesToMol(smiles, false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::sanitizeMol(*m);
|
|
MolOps::assignStereochemistry(*m, true, true);
|
|
TEST_ASSERT(m->getNumAtoms() == 12);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(5)->getStereo() == Bond::STEREOZ);
|
|
delete m;
|
|
|
|
m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondWithIdx(1)->getStereo() == Bond::STEREOZ);
|
|
delete m;
|
|
}
|
|
{ // another basic test
|
|
std::string smiles = "[H]/C(C)=C/C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 2)->getStereo() == Bond::STEREOZ);
|
|
delete m;
|
|
}
|
|
{ // H following the C:
|
|
std::string smiles = "CC(\\[H])=C/C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOZ);
|
|
delete m;
|
|
}
|
|
{ // bond dir already set :
|
|
std::string smiles = "[H]/C(/C)=C\\C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 2)->getStereo() == Bond::STEREOE);
|
|
delete m;
|
|
}
|
|
|
|
{ // chained bonds :
|
|
std::string smiles = "[H]/C(C=C/C)=C\\C";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 6);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 4)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 4)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOE);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
void testGithubIssue805() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github #805 : "
|
|
"Pre-condition Violation: bad bond type"
|
|
<< std::endl;
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
ROMol *m = MolFileToMol(pathName + "pubchem_87396055.sdf");
|
|
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 20);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(2, 6)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getFormalCharge() == 1);
|
|
TEST_ASSERT(m->getAtomWithIdx(6)->getFormalCharge() == -1);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(2, 9)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(2, 9)->getStereo() != Bond::STEREONONE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(3, 10)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(3, 10)->getStereo() != Bond::STEREONONE);
|
|
std::string smi = MolToSmiles(*m, true);
|
|
TEST_ASSERT(smi == "CCO/[P+]([O-])=C1\\CSC(c2cccs2)\\C1=[P+](\\[O-])OCC");
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "O=P(/O)=C/C";
|
|
ROMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getFormalCharge() == 1);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == -1);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 3)->getBondType() == Bond::DOUBLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 3)->getStereo() != Bond::STEREONONE);
|
|
smi = MolToSmiles(*m, true);
|
|
TEST_ASSERT(smi == "C/C=[P+](/[O-])O");
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue518() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github #518 : "
|
|
"Rings containing all dummy atoms with single bonds "
|
|
"are flagged as aromatic"
|
|
<< std::endl;
|
|
{
|
|
std::string smi = "*-1-*-*-*-1";
|
|
ROMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getBondType() == Bond::SINGLE);
|
|
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
}
|
|
{ // in this case we leave it aromatic since it's all dummies
|
|
std::string smi = "*:1:*:*:*:1";
|
|
ROMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getBondType() == Bond::AROMATIC);
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "*-1-*-C-*-*-*-1";
|
|
ROMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 6);
|
|
TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getBondType() == Bond::SINGLE);
|
|
|
|
TEST_ASSERT(!m->getAtomWithIdx(0)->getIsAromatic());
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smi = "C1=CC=*2*(=C1)*1=CC=CC=*1*1=CC=CC=*21";
|
|
ROMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 18);
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(4, 6)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(4, 6)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(11, 12)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(11, 12)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(!m->getBondBetweenAtoms(3, 17)->getIsAromatic());
|
|
TEST_ASSERT(m->getBondBetweenAtoms(3, 17)->getBondType() == Bond::SINGLE);
|
|
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testSimpleAromaticity() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing simple aromaticity"
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "c1ccccc1";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
MolOps::Kekulize(*m, true);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
MolOps::setAromaticity(*m, MolOps::AROMATICITY_SIMPLE);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "c1[nH]ccc1";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
MolOps::Kekulize(*m, true);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
MolOps::setAromaticity(*m, MolOps::AROMATICITY_SIMPLE);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
delete m;
|
|
}
|
|
{ // ring size constraints
|
|
std::string smiles = "c1cccoocc1";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
MolOps::Kekulize(*m, true);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
MolOps::setAromaticity(*m, MolOps::AROMATICITY_SIMPLE);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
delete m;
|
|
}
|
|
{ // ring size constraints
|
|
std::string smiles = "c1coo1";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
MolOps::Kekulize(*m, true);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
MolOps::setAromaticity(*m, MolOps::AROMATICITY_SIMPLE);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
delete m;
|
|
}
|
|
{ // fused rings are not considered
|
|
std::string smiles = "C1=CC2=CC=CC=CC2=C1"; // azulene
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
MolOps::Kekulize(*m, true);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
MolOps::setAromaticity(*m, MolOps::AROMATICITY_SIMPLE);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
//! really dumb aromaticity: any conjugated ring bond is aromatic
|
|
int customAromaticity(RWMol &m) {
|
|
m.updatePropertyCache();
|
|
MolOps::setConjugation(m);
|
|
MolOps::fastFindRings(m);
|
|
int res = 0;
|
|
for (ROMol::BondIterator bIt = m.beginBonds(); bIt != m.endBonds(); ++bIt) {
|
|
if ((*bIt)->getIsConjugated() && queryIsBondInRing(*bIt)) {
|
|
(*bIt)->setIsAromatic(true);
|
|
(*bIt)->getBeginAtom()->setIsAromatic(true);
|
|
(*bIt)->getEndAtom()->setIsAromatic(true);
|
|
++res;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void testCustomAromaticity() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing custom aromaticity"
|
|
<< std::endl;
|
|
|
|
{
|
|
std::string smiles = "C1=CC=CC=C1";
|
|
RWMol *m = SmilesToMol(smiles, 0, false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
MolOps::setAromaticity(*m, MolOps::AROMATICITY_CUSTOM, customAromaticity);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C1CC=CC=C1";
|
|
RWMol *m = SmilesToMol(smiles, 0, false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
MolOps::setAromaticity(*m, MolOps::AROMATICITY_CUSTOM, customAromaticity);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getBondWithIdx(2)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(2)->getIsAromatic() == true);
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue1730() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue "
|
|
"#1730: setAromaticity() should work even if "
|
|
"there are aromatic atoms present"
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "C1=CC=CC=C1-c2ccccc2";
|
|
RWMol *m = SmilesToMol(smiles, 0, false);
|
|
m->updatePropertyCache();
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == false);
|
|
TEST_ASSERT(m->getBondWithIdx(6)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(6)->getIsAromatic() == true);
|
|
MolOps::setAromaticity(*m);
|
|
TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic() == true);
|
|
TEST_ASSERT(m->getAtomWithIdx(0)->getIsAromatic() == true);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testKekulizeErrorReporting() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing error reporting for kekulization"
|
|
<< std::endl;
|
|
std::stringstream sstrm;
|
|
rdErrorLog->SetTee(sstrm);
|
|
{
|
|
sstrm.str("");
|
|
std::string smi = "c1ccccc1";
|
|
ROMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(sstrm.str() == "");
|
|
delete m;
|
|
}
|
|
{
|
|
sstrm.str("");
|
|
std::string smi = "c1cccc1";
|
|
ROMol *m;
|
|
try {
|
|
m = SmilesToMol(smi);
|
|
} catch (MolSanitizeException &) {
|
|
m = nullptr;
|
|
}
|
|
TEST_ASSERT(m == nullptr);
|
|
TEST_ASSERT(sstrm.str().find("0 1 2 3 4") != std::string::npos);
|
|
delete m;
|
|
}
|
|
{
|
|
sstrm.str("");
|
|
std::string smi = "c1ccccc1.c1cccc1";
|
|
ROMol *m;
|
|
try {
|
|
m = SmilesToMol(smi);
|
|
} catch (MolSanitizeException &) {
|
|
m = nullptr;
|
|
}
|
|
TEST_ASSERT(m == nullptr);
|
|
TEST_ASSERT(sstrm.str().find("6 7 8 9 10") != std::string::npos);
|
|
delete m;
|
|
}
|
|
{
|
|
sstrm.str("");
|
|
std::string smi = "c1cccc1.c1cccc1";
|
|
ROMol *m;
|
|
try {
|
|
m = SmilesToMol(smi);
|
|
} catch (MolSanitizeException &) {
|
|
m = nullptr;
|
|
}
|
|
TEST_ASSERT(m == nullptr);
|
|
TEST_ASSERT(sstrm.str().find("0 1 2 3 4") != std::string::npos);
|
|
delete m;
|
|
}
|
|
rdErrorLog->ClearTee();
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue868() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue "
|
|
"#868: inappropriate warning from MergeQueryHs"
|
|
<< std::endl;
|
|
std::stringstream sstrm;
|
|
rdWarningLog->SetTee(sstrm);
|
|
{
|
|
sstrm.str("");
|
|
|
|
std::string sma = "[SX3](=O)[O-,#1]";
|
|
RWMol *m = SmartsToMol(sma);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
MolOps::mergeQueryHs(*m);
|
|
TEST_ASSERT(
|
|
sstrm.str().find(
|
|
"merging explicit H queries involved in ORs is not supported") !=
|
|
std::string::npos);
|
|
TEST_ASSERT(sstrm.str().find("This query will not be merged") !=
|
|
std::string::npos);
|
|
delete m;
|
|
}
|
|
{
|
|
sstrm.str("");
|
|
|
|
std::string sma = "[SX3](=O)[O-,H1]";
|
|
RWMol *m = SmartsToMol(sma);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
MolOps::mergeQueryHs(*m);
|
|
TEST_ASSERT(sstrm.str().find("merging explicit H queries involved in "
|
|
"ORs is not supported") == std::string::npos);
|
|
TEST_ASSERT(sstrm.str().find("This query will not be merged") ==
|
|
std::string::npos);
|
|
delete m;
|
|
}
|
|
{
|
|
sstrm.str("");
|
|
|
|
std::string sma = "[SX3](=O)[O-,H]";
|
|
RWMol *m = SmartsToMol(sma);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 3);
|
|
MolOps::mergeQueryHs(*m);
|
|
TEST_ASSERT(sstrm.str().find("merging explicit H queries involved in "
|
|
"ORs is not supported") == std::string::npos);
|
|
TEST_ASSERT(sstrm.str().find("This query will not be merged") ==
|
|
std::string::npos);
|
|
delete m;
|
|
}
|
|
rdWarningLog->ClearTee();
|
|
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue908() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 908: "
|
|
"AddHs() using 3D coordinates with 2D conformations"
|
|
<< std::endl;
|
|
{
|
|
std::string mb =
|
|
"\n RDKit 2D\n\n 4 3 0 0 0 0 0 0 0 0999 "
|
|
"V2000\n "
|
|
" -0.0000 -1.5000 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 "
|
|
"0\n -0.0000 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 "
|
|
"0 "
|
|
" 0\n 1.2990 0.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 "
|
|
" "
|
|
"0 0\n -1.2990 0.7500 0.0000 Cl 0 0 0 0 0 0 0 0 0 "
|
|
"0 "
|
|
" 0 0\n 2 1 1 1\n 2 3 1 0\n 2 4 1 0\nM END\n";
|
|
RWMol *m = MolBlockToMol(mb);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 4);
|
|
MolOps::addHs(*m, false, true);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
TEST_ASSERT(feq(m->getConformer().getAtomPos(4).z, 0.0));
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue962() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue 962: "
|
|
"Kekulization issues post successful smiles parsing"
|
|
<< std::endl;
|
|
{
|
|
std::string smi = "C2*c1ccccc1C2";
|
|
RWMol *m = SmilesToMol(smi, 0, false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 9);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1));
|
|
TEST_ASSERT(m->getBondBetweenAtoms(2, 1));
|
|
m->updatePropertyCache();
|
|
MolOps::Kekulize(*m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(2, 1)->getBondType() == Bond::SINGLE);
|
|
|
|
delete m;
|
|
}
|
|
{ // this one did not cause problems before, but verify!
|
|
std::string smi = "*2Cc1ccccc1C2";
|
|
RWMol *m = SmilesToMol(smi, 0, false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 9);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1));
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 8));
|
|
m->updatePropertyCache();
|
|
MolOps::Kekulize(*m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 8)->getBondType() == Bond::SINGLE);
|
|
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue1021() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 1021: "
|
|
"AssignStereochemistry() giving incorrect results after "
|
|
"FastFindRings()"
|
|
<< std::endl;
|
|
{
|
|
std::string smi = "C[C@H]1CC2CCCC(C1)[C@H]2N";
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 11);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(9)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
m->clearComputedProps();
|
|
bool cleanit = true, force = true;
|
|
MolOps::assignStereochemistry(*m, cleanit, force);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(9)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
m->clearComputedProps();
|
|
MolOps::fastFindRings(*m);
|
|
MolOps::assignStereochemistry(*m, cleanit, force);
|
|
TEST_ASSERT(m->getAtomWithIdx(1)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
TEST_ASSERT(m->getAtomWithIdx(9)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
void testGithubIssue607() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 607: "
|
|
"AssignAtomChiralTagsFromStructure() not recognizing chiral S"
|
|
<< std::endl;
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
ROMol *m = MolFileToMol(pathName + "1a9u.zwitterion.sdf");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 27);
|
|
MolOps::assignChiralTypesFrom3D(*m);
|
|
|
|
TEST_ASSERT(m->getAtomWithIdx(26)->getAtomicNum() == 16);
|
|
TEST_ASSERT(m->getAtomWithIdx(26)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
}
|
|
{
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
ROMol *m = MolFileToMol(pathName + "1a9u.sdf");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 27);
|
|
MolOps::assignChiralTypesFrom3D(*m);
|
|
|
|
TEST_ASSERT(m->getAtomWithIdx(26)->getAtomicNum() == 16);
|
|
TEST_ASSERT(m->getAtomWithIdx(26)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
}
|
|
{ // convert S -> Se and test again
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
ROMol *m = MolFileToMol(pathName + "1a9u.zwitterion.sdf");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 27);
|
|
m->getAtomWithIdx(26)->setAtomicNum(34);
|
|
MolOps::assignChiralTypesFrom3D(*m);
|
|
TEST_ASSERT(m->getAtomWithIdx(26)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
}
|
|
{ // convert S -> Se and test again
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
ROMol *m = MolFileToMol(pathName + "1a9u.sdf");
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 27);
|
|
m->getAtomWithIdx(26)->setAtomicNum(34);
|
|
MolOps::assignChiralTypesFrom3D(*m);
|
|
TEST_ASSERT(m->getAtomWithIdx(26)->getChiralTag() != Atom::CHI_UNSPECIFIED);
|
|
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testGithubIssue1204() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 1204: "
|
|
"Support tetravalent and hexavalent Te"
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "F[Te](F)(F)(F)(F)F";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "F[Te](F)(F)(F)";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1478() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 1478: " << std::endl
|
|
<< " Aromatic rings composed solely of dummy atoms should not be "
|
|
"kekulized"
|
|
<< std::endl;
|
|
{ // basics
|
|
std::string smiles = "*:1:*:*:*:*:*:1";
|
|
RWMol *m = SmilesToMol(smiles, false);
|
|
TEST_ASSERT(m);
|
|
m->updatePropertyCache();
|
|
MolOps::Kekulize(*m);
|
|
for (unsigned int i = 0; i < m->getNumBonds(); ++i) {
|
|
TEST_ASSERT(m->getBondWithIdx(i)->getBondType() == Bond::AROMATIC);
|
|
}
|
|
delete m;
|
|
}
|
|
|
|
{ // fused rings where one is kekulized
|
|
std::string smiles = "*:1:*:*:*:*:2:*:1cccc2";
|
|
RWMol *m = SmilesToMol(smiles, false);
|
|
TEST_ASSERT(m);
|
|
m->updatePropertyCache();
|
|
MolOps::Kekulize(*m);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(0, 1)->getBondType() == Bond::AROMATIC);
|
|
TEST_ASSERT(m->getBondBetweenAtoms(6, 7)->getBondType() != Bond::AROMATIC);
|
|
delete m;
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1439() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 1439: " << std::endl
|
|
<< "RemoveHs() removes H atom attached to dummy if it came from AddHs()"
|
|
<< std::endl;
|
|
{ // basics
|
|
std::string smiles = "F";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
MolOps::addHs(*m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
m->getAtomWithIdx(0)->setAtomicNum(0);
|
|
MolOps::removeHs(*m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1281() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 1281: " << std::endl
|
|
<< "RDKit gets stuck on PubChem CID 102128817" << std::endl;
|
|
{ // basics
|
|
std::string smiles =
|
|
"COC1=CC=C(C=C1)C2C3=C(C=CC4=CC=CC=C43)OC5=CC6=C(C=C5)C7=NC8=C9C=CC1="
|
|
"CC9=C(N8)N=C3C4=C5C=CC(=C4)OC4=C(C(C8=C(C=CC9=CC=CC=C98)OC8=CC9=C(C="
|
|
"C8)C8=NC9=NC9=C%10C=C(C=CC%10=C(N9)N=C9C%10=C(C=C(C=C%10)OC%10=C2C2="
|
|
"CC=CC=C2C=C%10)C(=N9)NC2=NC(=N8)C8=C2C=C(C=C8)OC2=C(C(C8=C(C=CC9=CC="
|
|
"CC=C98)OC8=CC9=C(C=C8)C(=NC5=N3)N=C9NC6=N7)C3=CC=C(C=C3)OC)C3=CC=CC="
|
|
"C3C=C2)OC2=C(C(C3=C(O1)C=CC1=CC=CC=C13)C1=CC=C(C=C1)OC)C1=CC=CC=C1C="
|
|
"C2)C1=CC=C(C=C1)OC)C1=CC=CC=C1C=C4";
|
|
{
|
|
RWMol *m = SmilesToMol(smiles, 0, false);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 204);
|
|
TEST_ASSERT(m->getNumBonds() == 244);
|
|
bool ok = false;
|
|
try {
|
|
MolOps::findSSSR(*m);
|
|
} catch (const ValueErrorException &) {
|
|
ok = true;
|
|
}
|
|
TEST_ASSERT(ok);
|
|
delete m;
|
|
}
|
|
{
|
|
bool ok = false;
|
|
try {
|
|
RWMol *m = SmilesToMol(smiles);
|
|
// Can never get here:
|
|
delete m;
|
|
} catch (const ValueErrorException &) {
|
|
ok = true;
|
|
}
|
|
TEST_ASSERT(ok);
|
|
}
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1605() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue "
|
|
"1605: Inappropriate bad valence exception during "
|
|
"partial sanitization. "
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "C1=CC=CC=C1N(=O)=O";
|
|
{ // easy to test; we shouldn't throw an exception. :-)
|
|
RWMol *m = SmilesToMol(smiles, 0, false);
|
|
TEST_ASSERT(m);
|
|
unsigned int failed;
|
|
MolOps::sanitizeMol(
|
|
*m, failed,
|
|
MolOps::SANITIZE_SETAROMATICITY | MolOps::SANITIZE_ADJUSTHS);
|
|
TEST_ASSERT(!failed);
|
|
delete m;
|
|
}
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1622() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue "
|
|
"1622: add MDL aromaticity perception"
|
|
<< std::endl;
|
|
{
|
|
// rings that should be aromatic
|
|
string aromaticSmis[] = {"C1=CC=CC=C1", // benzene, of course
|
|
// heterocyclics
|
|
"N1=CC=CC=C1", // pyridine
|
|
"N1=CC=CC=N1", // pyridazine
|
|
"N1=CC=CN=C1", // pyrimidine
|
|
"N1=CC=NC=C1", // pyrazine
|
|
"N1=CN=CN=C1", // 1,3,5-triazine
|
|
// polycyclic aromatics
|
|
"C1=CC2=CC=CC=CC2=C1", // azulene
|
|
"C1=CC=CC2=CC=CC=C12", // 6-6 fused
|
|
"C1=CC2=CC=CC=CC=C12", // 4-8 fused
|
|
"C1=CC=C2C(=C1)N=CC=N2", // 6-6 with Ns
|
|
"C1=CN=CC2C=CC=CC1=2", // 6-6
|
|
"C1=CC=C2C(=C1)N=C3C=CC=CC3=N2", // 6-6-6
|
|
"C1=CN=NC2C=CC=CC1=2", // 6-6 with Ns
|
|
// macrocycle aromatics
|
|
"C1=CC=CC=CC=CC=C1", // 10 atoms
|
|
"C1=CC=CC=CC=CC=CC=CC=CC=CC=C1", // 18 atoms
|
|
"N1=CN=NC=CC=CC=CC=CC=CC=CC=CC=CC=CC=CC=CC=CC=C1",
|
|
"EOS"};
|
|
unsigned int i = 0;
|
|
while (aromaticSmis[i] != "EOS") {
|
|
string smi = aromaticSmis[i];
|
|
// std::cerr << smi << std::endl;
|
|
int debugParse = 0;
|
|
bool sanitize = false;
|
|
RWMol *mol = SmilesToMol(smi, debugParse, sanitize);
|
|
TEST_ASSERT(mol);
|
|
unsigned int whatFailed = 0;
|
|
unsigned int sanitFlags =
|
|
MolOps::SANITIZE_ALL ^ MolOps::SANITIZE_SETAROMATICITY;
|
|
MolOps::sanitizeMol(*mol, whatFailed, sanitFlags);
|
|
MolOps::setAromaticity(*mol, MolOps::AROMATICITY_MDL);
|
|
TEST_ASSERT(mol->getAtomWithIdx(0)->getIsAromatic())
|
|
delete mol;
|
|
++i;
|
|
}
|
|
}
|
|
{
|
|
// rings that should not be aromatic
|
|
string nonaromaticSmis[] = {
|
|
"C1=C[N]C=C1", // radicals are not two electron donors
|
|
// exocyclic double bonds disqualify us
|
|
"C1(=O)C=CNC=C1", "C1(=C)C=CC(=C)C=C1", "C1(=O)C=CC(=O)C=C1",
|
|
|
|
"C1#CC=CC=C1", // not benzyne
|
|
// five-membered heterocycles
|
|
"C1=COC=C1", // furan
|
|
"C1=CSC=C1", // thiophene
|
|
"C1=CNC=C1", // pyrrole
|
|
"C1=COC=N1", // oxazole
|
|
"C1=CSC=N1", // thiazole
|
|
"C1=CNC=N1", // imidzole
|
|
"C1=CNN=C1", // pyrazole
|
|
"C1=CON=C1", // isoxazole
|
|
"C1=CSN=C1", // isothiazole
|
|
"C1=CON=N1", // 1,2,3-oxadiazole
|
|
"C1=CNN=N1", // 1,2,3-triazole
|
|
"N1=CSC=N1", // 1,3,4-thiadiazole
|
|
"C1=CS(=O)C=C1", // not sure how to classify this example from the
|
|
// OEChem docs
|
|
// outside the second rows
|
|
"C1=CC=C[Si]=C1", "C1=CC=CC=P1",
|
|
// 5-membered heterocycles outside the second row
|
|
"C1=C[Se]C=C1", "C1=C[Te]C=C1",
|
|
|
|
"EOS"};
|
|
unsigned int i = 0;
|
|
while (nonaromaticSmis[i] != "EOS") {
|
|
string smi = nonaromaticSmis[i];
|
|
// std::cerr << smi << std::endl;
|
|
int debugParse = 0;
|
|
bool sanitize = false;
|
|
RWMol *mol = SmilesToMol(smi, debugParse, sanitize);
|
|
TEST_ASSERT(mol);
|
|
unsigned int whatFailed = 0;
|
|
unsigned int sanitFlags =
|
|
MolOps::SANITIZE_ALL ^ MolOps::SANITIZE_SETAROMATICITY;
|
|
MolOps::sanitizeMol(*mol, whatFailed, sanitFlags);
|
|
MolOps::setAromaticity(*mol, MolOps::AROMATICITY_MDL);
|
|
TEST_ASSERT(!(mol->getAtomWithIdx(0)->getIsAromatic()))
|
|
delete mol;
|
|
++i;
|
|
}
|
|
}
|
|
|
|
{
|
|
// ring systems where part is aromatic, part not
|
|
string mixedaromaticSmis[] = {
|
|
"O1C=CC2=CC=CC=C12", "S1C=CC2=CC=CC=C12",
|
|
"N1C2=CC=CC=C2C2=CC=CC=C12", "N1C=CC2=CC=CC=C12",
|
|
"N1C=NC2=CC=CC=C12", "N1C=NC2=CN=CN=C12",
|
|
"C1CCCC2=CC3=CCCCC3=CC2=1", "EOS"};
|
|
unsigned int i = 0;
|
|
while (mixedaromaticSmis[i] != "EOS") {
|
|
string smi = mixedaromaticSmis[i];
|
|
// std::cerr << smi << std::endl;
|
|
int debugParse = 0;
|
|
bool sanitize = false;
|
|
RWMol *mol = SmilesToMol(smi, debugParse, sanitize);
|
|
TEST_ASSERT(mol);
|
|
unsigned int whatFailed = 0;
|
|
unsigned int sanitFlags =
|
|
MolOps::SANITIZE_ALL ^ MolOps::SANITIZE_SETAROMATICITY;
|
|
MolOps::sanitizeMol(*mol, whatFailed, sanitFlags);
|
|
MolOps::setAromaticity(*mol, MolOps::AROMATICITY_MDL);
|
|
TEST_ASSERT(!(mol->getAtomWithIdx(0)->getIsAromatic()))
|
|
TEST_ASSERT(
|
|
(mol->getAtomWithIdx(mol->getNumAtoms() - 1)->getIsAromatic()))
|
|
delete mol;
|
|
++i;
|
|
}
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1703() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue "
|
|
"1703: Dative bonds interfere with kekulization and "
|
|
"the perception of aromaticity"
|
|
<< std::endl;
|
|
{ // start with zero-order bonds
|
|
SmilesParserParams ps;
|
|
ps.sanitize = false;
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("C1=CC=NC=N1.[Fe]", ps));
|
|
TEST_ASSERT(mol);
|
|
mol->addBond(5, 6, Bond::ZERO);
|
|
MolOps::sanitizeMol(*mol);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(0, 1)->getIsAromatic());
|
|
TEST_ASSERT(mol->getAtomWithIdx(5)->getIsAromatic());
|
|
MolOps::Kekulize(*mol);
|
|
}
|
|
{ // and dative bonds:
|
|
SmilesParserParams ps;
|
|
ps.sanitize = false;
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("C1=CC=NC=N1->[Fe]", ps));
|
|
TEST_ASSERT(mol);
|
|
MolOps::sanitizeMol(*mol);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(0, 1)->getIsAromatic());
|
|
TEST_ASSERT(mol->getAtomWithIdx(5)->getIsAromatic());
|
|
MolOps::Kekulize(*mol);
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1614() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing github issue "
|
|
"1614: AssignStereochemistry incorrectly removing "
|
|
"CIS/TRANS bond stereo"
|
|
<< std::endl;
|
|
#if 1
|
|
{
|
|
RWMol m;
|
|
m.addAtom(new Atom(9), true, true);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addAtom(new Atom(17), true, true);
|
|
m.addBond(0, 1, Bond::SINGLE);
|
|
m.addBond(2, 3, Bond::SINGLE);
|
|
m.addBond(1, 2, Bond::DOUBLE);
|
|
m.getBondBetweenAtoms(1, 2)->setStereoAtoms(0, 3);
|
|
m.getBondBetweenAtoms(1, 2)->setStereo(Bond::STEREOTRANS);
|
|
m.updatePropertyCache();
|
|
|
|
{
|
|
RWMol nm(m);
|
|
bool force = true, cleanIt = true;
|
|
MolOps::setDoubleBondNeighborDirections(nm);
|
|
|
|
MolOps::assignStereochemistry(nm, cleanIt, force);
|
|
// nm.debugMol(std::cerr);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(1, 2)->getStereo() > Bond::STEREOANY);
|
|
std::string smi = MolToSmiles(nm, true);
|
|
std::cerr << smi << std::endl;
|
|
TEST_ASSERT(smi == "F/C=C/Cl");
|
|
}
|
|
{
|
|
RWMol nm(m);
|
|
MolOps::addHs(nm);
|
|
bool force = true, cleanIt = true;
|
|
MolOps::setDoubleBondNeighborDirections(nm);
|
|
MolOps::assignStereochemistry(nm, cleanIt, force);
|
|
// nm.debugMol(std::cerr);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(1, 2)->getStereo() > Bond::STEREOANY);
|
|
std::string smi = MolToSmiles(nm, true);
|
|
std::cerr << smi << std::endl;
|
|
TEST_ASSERT(smi == "[H]/C(F)=C(/[H])Cl");
|
|
}
|
|
}
|
|
|
|
{
|
|
RWMol m;
|
|
m.addAtom(new Atom(9), true, true);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addAtom(new Atom(17), true, true);
|
|
m.addBond(0, 1, Bond::SINGLE);
|
|
m.addBond(3, 2, Bond::SINGLE);
|
|
m.addBond(1, 2, Bond::DOUBLE);
|
|
m.getBondBetweenAtoms(1, 2)->setStereoAtoms(0, 3);
|
|
m.getBondBetweenAtoms(1, 2)->setStereo(Bond::STEREOTRANS);
|
|
m.updatePropertyCache();
|
|
|
|
{
|
|
RWMol nm(m);
|
|
bool force = true, cleanIt = true;
|
|
MolOps::setDoubleBondNeighborDirections(nm);
|
|
|
|
MolOps::assignStereochemistry(nm, cleanIt, force);
|
|
// nm.debugMol(std::cerr);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(1, 2)->getStereo() > Bond::STEREOANY);
|
|
std::string smi = MolToSmiles(nm, true);
|
|
std::cerr << smi << std::endl;
|
|
TEST_ASSERT(smi == "F/C=C/Cl");
|
|
}
|
|
}
|
|
{
|
|
RWMol m;
|
|
m.addAtom(new Atom(9), true, true);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addAtom(new Atom(17), true, true);
|
|
m.addBond(1, 0, Bond::SINGLE);
|
|
m.addBond(2, 3, Bond::SINGLE);
|
|
m.addBond(1, 2, Bond::DOUBLE);
|
|
m.getBondBetweenAtoms(1, 2)->setStereoAtoms(0, 3);
|
|
m.getBondBetweenAtoms(1, 2)->setStereo(Bond::STEREOTRANS);
|
|
m.updatePropertyCache();
|
|
|
|
{
|
|
RWMol nm(m);
|
|
bool force = true, cleanIt = true;
|
|
MolOps::setDoubleBondNeighborDirections(nm);
|
|
|
|
MolOps::assignStereochemistry(nm, cleanIt, force);
|
|
// nm.debugMol(std::cerr);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(1, 2)->getStereo() > Bond::STEREOANY);
|
|
std::string smi = MolToSmiles(nm, true);
|
|
std::cerr << smi << std::endl;
|
|
TEST_ASSERT(smi == "F/C=C/Cl");
|
|
}
|
|
}
|
|
|
|
{
|
|
RWMol m;
|
|
m.addAtom(new Atom(9), true, true);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addAtom(new Atom(17), true, true);
|
|
m.addBond(0, 1, Bond::SINGLE);
|
|
m.addBond(2, 3, Bond::SINGLE);
|
|
m.addBond(1, 2, Bond::DOUBLE);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addAtom(new Atom(6), true, true);
|
|
m.addBond(1, 5, Bond::SINGLE);
|
|
m.addBond(2, 4, Bond::SINGLE);
|
|
|
|
m.getBondBetweenAtoms(1, 2)->setStereoAtoms(0, 3);
|
|
m.getBondBetweenAtoms(1, 2)->setStereo(Bond::STEREOTRANS);
|
|
m.updatePropertyCache();
|
|
|
|
{
|
|
RWMol nm(m);
|
|
bool force = true, cleanIt = true;
|
|
MolOps::setDoubleBondNeighborDirections(nm);
|
|
|
|
MolOps::assignStereochemistry(nm, cleanIt, force);
|
|
// nm.debugMol(std::cerr);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(1, 2)->getStereo() > Bond::STEREOANY);
|
|
std::string smi = MolToSmiles(nm, true);
|
|
std::cerr << smi << std::endl;
|
|
TEST_ASSERT(smi == "C/C(F)=C(/C)Cl");
|
|
}
|
|
}
|
|
#endif
|
|
#if 1
|
|
{
|
|
RWMol *m = SmilesToMol("F/C=C(\\C/C=C/C)C/C=C\\F", false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::sanitizeMol(*m);
|
|
|
|
{
|
|
RWMol nm(*m);
|
|
MolOps::setDoubleBondNeighborDirections(nm);
|
|
// nm.debugMol(std::cerr);
|
|
bool force = true, cleanIt = true;
|
|
MolOps::assignStereochemistry(nm, cleanIt, force);
|
|
// nm.debugMol(std::cerr);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(4, 5)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(8, 9)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOE);
|
|
}
|
|
delete m;
|
|
}
|
|
#endif
|
|
|
|
{
|
|
RWMol *m = SmilesToMol("FC=C(C/C=C/C)C/C=C\\F", false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::sanitizeMol(*m);
|
|
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2));
|
|
m->getBondBetweenAtoms(1, 2)->setStereoAtoms(0, 3);
|
|
m->getBondBetweenAtoms(1, 2)->setStereo(Bond::STEREOCIS);
|
|
|
|
{
|
|
RWMol nm(*m);
|
|
MolOps::setDoubleBondNeighborDirections(nm);
|
|
// nm.debugMol(std::cerr);
|
|
bool force = true, cleanIt = true;
|
|
MolOps::assignStereochemistry(nm, cleanIt, force);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(4, 5)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(8, 9)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOE);
|
|
}
|
|
delete m;
|
|
}
|
|
|
|
#if 1
|
|
{
|
|
RWMol *m = SmilesToMol("F/C=C(\\C/C=C/C)C/C=C\\C", false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::sanitizeMol(*m);
|
|
|
|
{
|
|
RWMol nm(*m);
|
|
MolOps::setDoubleBondNeighborDirections(nm);
|
|
bool force = true, cleanIt = true;
|
|
MolOps::assignStereochemistry(nm, cleanIt, force);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(4, 5)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(8, 9)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOE);
|
|
}
|
|
delete m;
|
|
}
|
|
#endif
|
|
{
|
|
RWMol *m = SmilesToMol("FC=C(C/C=C/C)C/C=C\\C", false, false);
|
|
TEST_ASSERT(m);
|
|
MolOps::sanitizeMol(*m);
|
|
|
|
TEST_ASSERT(m->getBondBetweenAtoms(1, 2));
|
|
m->getBondBetweenAtoms(1, 2)->setStereoAtoms(0, 3);
|
|
m->getBondBetweenAtoms(1, 2)->setStereo(Bond::STEREOCIS);
|
|
|
|
{
|
|
RWMol nm(*m);
|
|
MolOps::setDoubleBondNeighborDirections(nm);
|
|
bool force = true, cleanIt = true;
|
|
MolOps::assignStereochemistry(nm, cleanIt, force);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(4, 5)->getStereo() == Bond::STEREOE);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(8, 9)->getStereo() == Bond::STEREOZ);
|
|
TEST_ASSERT(nm.getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOE);
|
|
}
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1810() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue "
|
|
"1810: removeHs() should not remove H atoms that are "
|
|
"contributing to the definition of a stereo bond"
|
|
<< std::endl;
|
|
{
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("F/C=C/[H]"));
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 4);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOE);
|
|
}
|
|
{
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("F/C=C(/F)[H]"));
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 4);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOE);
|
|
}
|
|
{
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("F/C=C(/[H])F"));
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 4);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(1, 2)->getStereo() == Bond::STEREOZ);
|
|
}
|
|
#if 1
|
|
{
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("FC=C(F)[H]", false, false));
|
|
TEST_ASSERT(mol);
|
|
MolOps::sanitizeMol(*mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 5);
|
|
mol->getBondBetweenAtoms(1, 2)->setStereoAtoms(0, 4);
|
|
mol->getBondBetweenAtoms(1, 2)->setStereo(Bond::STEREOTRANS);
|
|
MolOps::removeHs(*mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 4);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(1, 2)->getStereoAtoms()[0] == 0);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(1, 2)->getStereoAtoms()[1] == 3);
|
|
}
|
|
#endif
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1936() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing Github issue "
|
|
"1936: Bad aromaticity for rings with radical carbocations"
|
|
<< std::endl;
|
|
{
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("C1=CC=C[C+]C=C1"));
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 7);
|
|
TEST_ASSERT(mol->getAtomWithIdx(4)->getNumRadicalElectrons() == 1);
|
|
TEST_ASSERT(!mol->getAtomWithIdx(0)->getIsAromatic());
|
|
}
|
|
|
|
{ // the original report
|
|
std::string pathName = getenv("RDBASE");
|
|
pathName += "/Code/GraphMol/test_data/";
|
|
std::unique_ptr<RWMol> mol(MolFileToMol(pathName + "github1936.mol"));
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 7);
|
|
TEST_ASSERT(mol->getAtomWithIdx(4)->getNumRadicalElectrons() == 1);
|
|
TEST_ASSERT(!mol->getAtomWithIdx(0)->getIsAromatic());
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1928() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing Github issue "
|
|
"1928: incorrect aromatic SMILES generated for structure"
|
|
<< std::endl;
|
|
{
|
|
std::unique_ptr<ROMol> mol(
|
|
SmilesToMol("N1C2=CC3=CC=CC=C3OC1=CC1=C(O2)C=CC=C1"));
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 19);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(0, 1)->getBondType() == Bond::SINGLE);
|
|
TEST_ASSERT(!mol->getBondBetweenAtoms(0, 1)->getIsAromatic());
|
|
TEST_ASSERT(!mol->getAtomWithIdx(0)->getIsAromatic());
|
|
}
|
|
{ // the original report
|
|
std::unique_ptr<ROMol> mol(SmilesToMol(
|
|
"C12=C3C=CC=C1CCC(=O)C2=C4OC5=CC=CC6=C5C(=C(N4)O3)C(=O)CC6"));
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 27);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(20, 21)->getBondType() ==
|
|
Bond::SINGLE);
|
|
TEST_ASSERT(!mol->getBondBetweenAtoms(20, 21)->getIsAromatic());
|
|
TEST_ASSERT(!mol->getAtomWithIdx(21)->getIsAromatic());
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub1990() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue "
|
|
"1990: removeHs screws up bond stereo"
|
|
<< std::endl;
|
|
{
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("F/C=C/F"));
|
|
TEST_ASSERT(mol);
|
|
MolOps::addHs(*mol);
|
|
MolOps::removeHs(*mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 4);
|
|
TEST_ASSERT(mol->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
}
|
|
{ // make sure that stereo is not removed when it comes from Hs:
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("F/C=C/F"));
|
|
TEST_ASSERT(mol);
|
|
MolOps::addHs(*mol);
|
|
TEST_ASSERT(mol->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
mol->getBondWithIdx(1)->getStereoAtoms()[0] = 4;
|
|
MolOps::removeHs(*mol);
|
|
TEST_ASSERT(mol->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
mol->getBondWithIdx(1)->getStereoAtoms()[0] = 0;
|
|
}
|
|
{ // make sure that stereo is not removed when it comes from Hs:
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("F/C=C/F"));
|
|
TEST_ASSERT(mol);
|
|
MolOps::addHs(*mol);
|
|
TEST_ASSERT(mol->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
mol->getBondWithIdx(1)->getStereoAtoms()[1] = 5;
|
|
MolOps::removeHs(*mol);
|
|
TEST_ASSERT(mol->getBondWithIdx(1)->getStereoAtoms().size() == 2);
|
|
mol->getBondWithIdx(1)->getStereoAtoms()[1] = 3;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testRemoveAndTrackIsotopes() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing removeAndTrackIsotopes parameter. "
|
|
<< std::endl;
|
|
struct IsotopicHsCount {
|
|
IsotopicHsCount(const ROMol &mol) {
|
|
for (auto b : mol.bonds()) {
|
|
const auto ba = b->getBeginAtom();
|
|
const auto ea = b->getEndAtom();
|
|
if (ba->getAtomicNum() == 1 && ba->getIsotope()) {
|
|
++d_map[ea->getIdx()];
|
|
} else if (ea->getAtomicNum() == 1 && ea->getIsotope()) {
|
|
++d_map[ba->getIdx()];
|
|
}
|
|
}
|
|
}
|
|
// get the number of isotopic Hs attached to atom idx
|
|
unsigned int at(unsigned int idx) {
|
|
auto it = d_map.find(idx);
|
|
return (it == d_map.end() ? 0 : it->second);
|
|
}
|
|
// count total number of isotopes in the molecule
|
|
unsigned int total() {
|
|
return std::accumulate(
|
|
d_map.begin(), d_map.end(), 0U,
|
|
[](unsigned int s, const std::pair<unsigned int, unsigned int> &p) {
|
|
return s + p.second;
|
|
});
|
|
}
|
|
static void countExplicitImplicitHs(const ROMol &m, unsigned int &expl,
|
|
unsigned int &impl) {
|
|
expl = 0;
|
|
impl = 0;
|
|
for (auto a : m.atoms()) {
|
|
expl += a->getNumExplicitHs();
|
|
impl += a->getNumImplicitHs();
|
|
}
|
|
}
|
|
std::map<unsigned int, unsigned int> d_map;
|
|
};
|
|
// CHEMBL2024142
|
|
auto m =
|
|
"[2H]C1=C(C(=C2C(=C1[2H])C(=O)C(=C(C2=O)C([2H])([2H])[2H])C/C=C(\\C)/CC([2H])([2H])/C=C(/CC/C=C(\\C)/CCC=C(C)C)\\C([2H])([2H])[2H])[2H])[2H]"_smiles;
|
|
TEST_ASSERT(m.get());
|
|
std::unique_ptr<IsotopicHsCount> m_isotopicHsPerHeavy(
|
|
new IsotopicHsCount(*m));
|
|
unsigned int m_numExplicitHs;
|
|
unsigned int m_numImplicitHs;
|
|
IsotopicHsCount::countExplicitImplicitHs(*m, m_numExplicitHs,
|
|
m_numImplicitHs);
|
|
TEST_ASSERT(m_numExplicitHs == 0);
|
|
TEST_ASSERT(m_numImplicitHs == 28);
|
|
TEST_ASSERT(m_isotopicHsPerHeavy->total() == 12);
|
|
MolOps::RemoveHsParameters ps;
|
|
ps.removeAndTrackIsotopes = true;
|
|
std::unique_ptr<ROMol> mNoH(removeHs(*static_cast<ROMol *>(m.get()), ps));
|
|
TEST_ASSERT(mNoH->getAtomWithIdx(0)->getAtomicNum() == 6);
|
|
TEST_ASSERT(mNoH->getAtomWithIdx(0)->hasProp(common_properties::_isotopicHs));
|
|
std::vector<unsigned int> isoHs;
|
|
TEST_ASSERT(mNoH->getAtomWithIdx(0)->getPropIfPresent(
|
|
common_properties::_isotopicHs, isoHs));
|
|
TEST_ASSERT(isoHs.size() == 1);
|
|
TEST_ASSERT(isoHs.front() == 2);
|
|
TEST_ASSERT(mNoH->getAtomWithIdx(30)->getAtomicNum() == 6);
|
|
TEST_ASSERT(
|
|
!mNoH->getAtomWithIdx(30)->hasProp(common_properties::_isotopicHs));
|
|
|
|
IsotopicHsCount mNoH_isotopicHsPerHeavy(*mNoH);
|
|
unsigned int mNoH_numExplicitHs;
|
|
unsigned int mNoH_numImplicitHs;
|
|
IsotopicHsCount::countExplicitImplicitHs(*mNoH, mNoH_numExplicitHs,
|
|
mNoH_numImplicitHs);
|
|
TEST_ASSERT(mNoH_numExplicitHs == 0);
|
|
TEST_ASSERT(mNoH_numImplicitHs == 40);
|
|
TEST_ASSERT(mNoH_isotopicHsPerHeavy.total() == 0);
|
|
std::unique_ptr<ROMol> mH(MolOps::addHs(*mNoH));
|
|
std::unique_ptr<IsotopicHsCount> mH_isotopicHsPerHeavy(
|
|
new IsotopicHsCount(*mH));
|
|
unsigned int mH_numExplicitHs;
|
|
unsigned int mH_numImplicitHs;
|
|
IsotopicHsCount::countExplicitImplicitHs(*mH, mH_numExplicitHs,
|
|
mH_numImplicitHs);
|
|
TEST_ASSERT(mH_numExplicitHs == 0);
|
|
TEST_ASSERT(mH_numImplicitHs == 0);
|
|
MatchVectType match;
|
|
TEST_ASSERT(SubstructMatch(*mH, *m, match));
|
|
TEST_ASSERT(match.size() == m->getNumAtoms());
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->total() == 12);
|
|
std::unique_ptr<ROMol> mH2(MolOps::removeHs(*mH));
|
|
TEST_ASSERT(m->getNumAtoms() == mH2->getNumAtoms());
|
|
std::unique_ptr<IsotopicHsCount> mH2_isotopicHsPerHeavy(
|
|
new IsotopicHsCount(*mH2));
|
|
unsigned int mH2_numExplicitHs;
|
|
unsigned int mH2_numImplicitHs;
|
|
IsotopicHsCount::countExplicitImplicitHs(*mH2, mH2_numExplicitHs,
|
|
mH2_numImplicitHs);
|
|
MatchVectType matchH2;
|
|
TEST_ASSERT(SubstructMatch(*m, *mH2, matchH2));
|
|
TEST_ASSERT(matchH2.size() == m->getNumAtoms());
|
|
TEST_ASSERT(mH2_isotopicHsPerHeavy->total() == 12);
|
|
TEST_ASSERT(mH2_numExplicitHs == 28);
|
|
TEST_ASSERT(mH2_numImplicitHs == 0);
|
|
for (auto p : matchH2) {
|
|
TEST_ASSERT(mH2_isotopicHsPerHeavy->at(p.first) ==
|
|
m_isotopicHsPerHeavy->at(p.second));
|
|
}
|
|
|
|
// shuffle atoms before adding Hs; result should not change
|
|
std::vector<unsigned int> randomOrder(mNoH->getNumAtoms());
|
|
std::iota(randomOrder.begin(), randomOrder.end(), 0U);
|
|
std::shuffle(randomOrder.begin(), randomOrder.end(),
|
|
std::default_random_engine());
|
|
std::unique_ptr<ROMol> mNoHRen(MolOps::renumberAtoms(*mNoH, randomOrder));
|
|
mH.reset(MolOps::addHs(*mNoHRen));
|
|
mH_isotopicHsPerHeavy.reset(new IsotopicHsCount(*mH));
|
|
IsotopicHsCount::countExplicitImplicitHs(*mH, mH_numExplicitHs,
|
|
mH_numImplicitHs);
|
|
TEST_ASSERT(mH_numExplicitHs == 0);
|
|
TEST_ASSERT(mH_numImplicitHs == 0);
|
|
MatchVectType matchRen;
|
|
TEST_ASSERT(SubstructMatch(*mH, *m, matchRen));
|
|
TEST_ASSERT(match != matchRen);
|
|
TEST_ASSERT(match.size() == matchRen.size());
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->total() == 12);
|
|
mH2.reset(MolOps::removeHs(*mH));
|
|
TEST_ASSERT(m->getNumAtoms() == mH2->getNumAtoms());
|
|
mH2_isotopicHsPerHeavy.reset(new IsotopicHsCount(*mH2));
|
|
IsotopicHsCount::countExplicitImplicitHs(*mH2, mH2_numExplicitHs,
|
|
mH2_numImplicitHs);
|
|
MatchVectType matchH2Ren;
|
|
TEST_ASSERT(SubstructMatch(*m, *mH2, matchH2Ren));
|
|
TEST_ASSERT(matchH2 != matchH2Ren);
|
|
TEST_ASSERT(matchH2.size() == matchH2Ren.size());
|
|
TEST_ASSERT(mH2_isotopicHsPerHeavy->total() == 12);
|
|
TEST_ASSERT(mH2_numExplicitHs == 28);
|
|
TEST_ASSERT(mH2_numImplicitHs == 0);
|
|
for (auto p : matchH2Ren) {
|
|
TEST_ASSERT(mH2_isotopicHsPerHeavy->at(p.first) ==
|
|
m_isotopicHsPerHeavy->at(p.second));
|
|
}
|
|
|
|
// Add isotopes incrementally only on some atoms at a time
|
|
// This should add 4 isotopes
|
|
UINT_VECT onlyOnAtoms{0, 12};
|
|
mH.reset(MolOps::addHs(*mNoH, false, false, &onlyOnAtoms));
|
|
mH_isotopicHsPerHeavy.reset(new IsotopicHsCount(*mH));
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->total() == 4);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(0) == 1);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(12) == 3);
|
|
// This should add 4 more isotopes
|
|
onlyOnAtoms = UINT_VECT{1, 2, 18};
|
|
mH.reset(MolOps::addHs(*mH, false, false, &onlyOnAtoms));
|
|
mH_isotopicHsPerHeavy.reset(new IsotopicHsCount(*mH));
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->total() == 8);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(0) == 1);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(1) == 1);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(2) == 1);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(12) == 3);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(18) == 2);
|
|
// This should add the last 4 isotopes
|
|
onlyOnAtoms = UINT_VECT{5, 32};
|
|
mH.reset(MolOps::addHs(*mH, false, false, &onlyOnAtoms));
|
|
mH_isotopicHsPerHeavy.reset(new IsotopicHsCount(*mH));
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->total() == 12);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(0) == 1);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(1) == 1);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(2) == 1);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(5) == 1);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(12) == 3);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(18) == 2);
|
|
TEST_ASSERT(mH_isotopicHsPerHeavy->at(32) == 3);
|
|
match.clear();
|
|
TEST_ASSERT(SubstructMatch(*mH, *m, match));
|
|
TEST_ASSERT(match.size() == mH->getNumAtoms());
|
|
for (auto p : match) {
|
|
auto m_nIso = m_isotopicHsPerHeavy->at(p.first);
|
|
if (!m_nIso) {
|
|
continue;
|
|
}
|
|
auto mH_nIso = mH_isotopicHsPerHeavy->at(p.second);
|
|
TEST_ASSERT(m_nIso == mH_nIso);
|
|
}
|
|
|
|
// Check that chirality on centers which bear both non-isotopic
|
|
// and isotopic Hs is preserved after...
|
|
std::set<Atom::ChiralType> chiralTypeSet;
|
|
std::set<Atom::ChiralType> chiralTypeSetAfterAddHs;
|
|
std::set<Atom::ChiralType> chiralTypeSetAfterRemoveAllHsAddHs;
|
|
std::set<Atom::ChiralType> chiralTypeSetAfterRemoveAllHsAddHsRemoveHs;
|
|
for (unsigned int i : {0, 1}) {
|
|
unsigned int hIdx = i + 24;
|
|
std::string expectedCipCode(1, 'R' + i);
|
|
std::unique_ptr<ROMol> mChiral(new ROMol(*m));
|
|
mChiral->getAtomWithIdx(23)->setChiralTag(Atom::CHI_TETRAHEDRAL_CW);
|
|
mChiral->getAtomWithIdx(hIdx)->setIsotope(0);
|
|
MolOps::assignStereochemistry(*mChiral, true, true);
|
|
TEST_ASSERT(mChiral->getAtomWithIdx(23)->getProp<std::string>(
|
|
common_properties::_CIPCode) == expectedCipCode);
|
|
chiralTypeSet.insert(mChiral->getAtomWithIdx(23)->getChiralTag());
|
|
// 1) ...Adding Hs
|
|
mH.reset(MolOps::addHs(*mChiral));
|
|
MolOps::assignStereochemistry(*mH, true, true);
|
|
match.clear();
|
|
TEST_ASSERT(mH->getAtomWithIdx(23)->getProp<std::string>(
|
|
common_properties::_CIPCode) == expectedCipCode);
|
|
chiralTypeSetAfterAddHs.insert(mH->getAtomWithIdx(23)->getChiralTag());
|
|
// 2) ...Removing all Hs including isotopes and then putting them back
|
|
mNoH.reset(MolOps::removeHs(*static_cast<ROMol *>(mChiral.get()), ps));
|
|
mH.reset(MolOps::addHs(*mNoH));
|
|
MolOps::assignStereochemistry(*mH, true, true);
|
|
match.clear();
|
|
TEST_ASSERT(SubstructMatch(*mH, *mChiral, match));
|
|
TEST_ASSERT(match.size() == mChiral->getNumAtoms());
|
|
TEST_ASSERT(mH->getAtomWithIdx(match[23].second)
|
|
->getProp<std::string>(common_properties::_CIPCode) ==
|
|
expectedCipCode);
|
|
chiralTypeSetAfterRemoveAllHsAddHs.insert(
|
|
mH->getAtomWithIdx(match[23].second)->getChiralTag());
|
|
// 3) ...Removing non-isotopic Hs
|
|
mNoH.reset(MolOps::removeHs(*mH));
|
|
MolOps::assignStereochemistry(*mNoH, true, true);
|
|
TEST_ASSERT(mNoH->getAtomWithIdx(match[23].second)
|
|
->getProp<std::string>(common_properties::_CIPCode) ==
|
|
expectedCipCode);
|
|
chiralTypeSetAfterRemoveAllHsAddHsRemoveHs.insert(
|
|
mNoH->getAtomWithIdx(match[23].second)->getChiralTag());
|
|
}
|
|
// CIP chirality is preserved because when all Hs are removed
|
|
// the parity is inverted on one of the enantiomers such that
|
|
// chirality is preserved also when Hs are implicit.
|
|
// So we must find a single parity before calling removeHs,
|
|
// and two afterwards.
|
|
TEST_ASSERT(chiralTypeSet.size() == 1 &&
|
|
*chiralTypeSet.begin() == Atom::CHI_TETRAHEDRAL_CW);
|
|
TEST_ASSERT(chiralTypeSetAfterAddHs.size() == 1 &&
|
|
*chiralTypeSetAfterAddHs.begin() == Atom::CHI_TETRAHEDRAL_CW);
|
|
TEST_ASSERT(chiralTypeSetAfterRemoveAllHsAddHs.size() == 2);
|
|
TEST_ASSERT(chiralTypeSetAfterRemoveAllHsAddHsRemoveHs.size() == 2);
|
|
|
|
// Check that chirality on centers which bear different
|
|
// H isotopes is preserved after...
|
|
chiralTypeSet.clear();
|
|
chiralTypeSetAfterAddHs.clear();
|
|
chiralTypeSetAfterRemoveAllHsAddHs.clear();
|
|
chiralTypeSetAfterRemoveAllHsAddHsRemoveHs.clear();
|
|
for (unsigned int i : {0, 1}) {
|
|
unsigned int hIdx = i + 24;
|
|
std::string expectedCipCode(1, 'R' + i);
|
|
std::unique_ptr<ROMol> mChiral(new ROMol(*m));
|
|
mChiral->getAtomWithIdx(23)->setChiralTag(Atom::CHI_TETRAHEDRAL_CCW);
|
|
mChiral->getAtomWithIdx(hIdx)->setIsotope(3);
|
|
MolOps::assignStereochemistry(*mChiral, true, true);
|
|
TEST_ASSERT(mChiral->getAtomWithIdx(23)->getProp<std::string>(
|
|
common_properties::_CIPCode) == expectedCipCode);
|
|
chiralTypeSet.insert(mChiral->getAtomWithIdx(23)->getChiralTag());
|
|
// 1) ...Adding Hs
|
|
mH.reset(MolOps::addHs(*mChiral));
|
|
MolOps::assignStereochemistry(*mH, true, true);
|
|
match.clear();
|
|
TEST_ASSERT(mH->getAtomWithIdx(23)->getProp<std::string>(
|
|
common_properties::_CIPCode) == expectedCipCode);
|
|
chiralTypeSetAfterAddHs.insert(mH->getAtomWithIdx(23)->getChiralTag());
|
|
// 2) ...Removing all Hs including isotopes and then putting them back
|
|
mNoH.reset(MolOps::removeHs(*static_cast<ROMol *>(mChiral.get()), ps));
|
|
mH.reset(MolOps::addHs(*mNoH));
|
|
|
|
MolOps::assignStereochemistry(*mH, true, true);
|
|
match.clear();
|
|
TEST_ASSERT(SubstructMatch(*mH, *mChiral, match));
|
|
TEST_ASSERT(match.size() == mChiral->getNumAtoms());
|
|
TEST_ASSERT(mH->getAtomWithIdx(match[23].second)
|
|
->getProp<std::string>(common_properties::_CIPCode) ==
|
|
expectedCipCode);
|
|
chiralTypeSetAfterRemoveAllHsAddHs.insert(
|
|
mH->getAtomWithIdx(match[23].second)->getChiralTag());
|
|
// 3) ...Removing non-isotopic Hs
|
|
mNoH.reset(MolOps::removeHs(*mH));
|
|
MolOps::assignStereochemistry(*mNoH, true, true);
|
|
TEST_ASSERT(mNoH->getAtomWithIdx(match[23].second)
|
|
->getProp<std::string>(common_properties::_CIPCode) ==
|
|
expectedCipCode);
|
|
chiralTypeSetAfterRemoveAllHsAddHsRemoveHs.insert(
|
|
mNoH->getAtomWithIdx(match[23].second)->getChiralTag());
|
|
}
|
|
// In this case we should find a single parity throughout
|
|
// as inverting the positions of 2H and 3H will trigger
|
|
// an inversion in CIP chirality without need for parity change
|
|
TEST_ASSERT(chiralTypeSet.size() == 1 &&
|
|
*chiralTypeSet.begin() == Atom::CHI_TETRAHEDRAL_CCW);
|
|
TEST_ASSERT(chiralTypeSetAfterAddHs.size() == 1 &&
|
|
*chiralTypeSetAfterAddHs.begin() == Atom::CHI_TETRAHEDRAL_CCW);
|
|
TEST_ASSERT(chiralTypeSetAfterRemoveAllHsAddHs.size() == 1 &&
|
|
*chiralTypeSetAfterRemoveAllHsAddHs.begin() ==
|
|
Atom::CHI_TETRAHEDRAL_CCW);
|
|
TEST_ASSERT(chiralTypeSetAfterRemoveAllHsAddHsRemoveHs.size() == 1 &&
|
|
*chiralTypeSetAfterRemoveAllHsAddHsRemoveHs.begin() ==
|
|
Atom::CHI_TETRAHEDRAL_CCW);
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub3854() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 3854: "
|
|
"AddHs creates H atom with nan coordinates on edge case 2D structure"
|
|
<< std::endl;
|
|
|
|
std::string molb = R"CTAB(
|
|
RDKit 2D
|
|
|
|
7 8 0 0 1 0 0 0 0 0999 V2000
|
|
5.0014 0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
4.1764 0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
3.3514 0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
2.9389 1.1271 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
3.3514 1.8412 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
4.1764 1.8412 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
4.5889 1.1271 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
2 1 1 1
|
|
7 1 1 1
|
|
2 3 1 0
|
|
2 7 1 0
|
|
3 4 1 0
|
|
4 5 1 0
|
|
5 6 1 0
|
|
7 6 1 0
|
|
M END)CTAB";
|
|
bool sanitize = true;
|
|
bool removeHs = false;
|
|
std::unique_ptr<ROMol> m(MolBlockToMol(molb, sanitize, removeHs));
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 7);
|
|
|
|
bool explicitOnly = false;
|
|
bool addCoords = true;
|
|
std::vector<unsigned> onlyOnAtoms = {1, 6};
|
|
std::unique_ptr<ROMol> m2(
|
|
MolOps::addHs(*m, explicitOnly, addCoords, &onlyOnAtoms));
|
|
TEST_ASSERT(m2);
|
|
TEST_ASSERT(m2->getNumAtoms() == 9);
|
|
|
|
auto conf = m2->getConformer();
|
|
for (auto i = 7; i < 9; ++i) {
|
|
auto atom_pos = conf.getAtomPos(i);
|
|
TEST_ASSERT(!isnan(atom_pos.x) && !isnan(atom_pos.y) && !isnan(atom_pos.z));
|
|
}
|
|
|
|
// check that we bisect the correct angle and point outside the rings
|
|
auto v71 = conf.getAtomPos(7) - conf.getAtomPos(1);
|
|
auto v21 = conf.getAtomPos(2) - conf.getAtomPos(1);
|
|
auto v01 = conf.getAtomPos(0) - conf.getAtomPos(1);
|
|
auto v61 = conf.getAtomPos(6) - conf.getAtomPos(1);
|
|
TEST_ASSERT(fabs(fabs(v71.dotProduct(v01)) - fabs(v71.dotProduct(v21))) <
|
|
1e-3);
|
|
TEST_ASSERT(v71.dotProduct(v61) < -1e-4);
|
|
|
|
auto v86 = conf.getAtomPos(8) - conf.getAtomPos(6);
|
|
auto v06 = conf.getAtomPos(0) - conf.getAtomPos(6);
|
|
auto v56 = conf.getAtomPos(5) - conf.getAtomPos(6);
|
|
auto v16 = conf.getAtomPos(1) - conf.getAtomPos(6);
|
|
TEST_ASSERT(fabs(fabs(v86.dotProduct(v56)) - fabs(v86.dotProduct(v06))) <
|
|
1e-3);
|
|
TEST_ASSERT(v86.dotProduct(v16) < -1e-4);
|
|
}
|
|
|
|
#ifdef RDK_USE_URF
|
|
void testRingFamilies() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing ring family calculation. "
|
|
<< std::endl;
|
|
{
|
|
std::string smiles = "C(C1C2C3C41)(C2C35)C45"; // cubane
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 8);
|
|
TEST_ASSERT(!m->getRingInfo()->areRingFamiliesInitialized());
|
|
MolOps::findRingFamilies(*m);
|
|
TEST_ASSERT(m->getRingInfo()->isInitialized());
|
|
TEST_ASSERT(m->getRingInfo()->areRingFamiliesInitialized());
|
|
int numURF = RDL_getNofURF(m->getRingInfo()->dp_urfData.get());
|
|
int numRC = RDL_getNofRC(m->getRingInfo()->dp_urfData.get());
|
|
TEST_ASSERT(numRC == 6);
|
|
TEST_ASSERT(numURF == 6);
|
|
|
|
int numRings = m->getRingInfo()->numRingFamilies();
|
|
TEST_ASSERT(numRings == 6);
|
|
numRings = m->getRingInfo()->numRings();
|
|
TEST_ASSERT(numRings == 6);
|
|
|
|
delete m;
|
|
}
|
|
{
|
|
std::string smiles = "C1CC2CCC1CC1CCC(CC1)CC1CCC(CC1)CC1CCC(CC1)C2";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 28);
|
|
TEST_ASSERT(!m->getRingInfo()->areRingFamiliesInitialized());
|
|
MolOps::findRingFamilies(*m);
|
|
TEST_ASSERT(m->getRingInfo()->isInitialized());
|
|
TEST_ASSERT(m->getRingInfo()->areRingFamiliesInitialized());
|
|
int numURF = RDL_getNofURF(m->getRingInfo()->dp_urfData.get());
|
|
int numRC = RDL_getNofRC(m->getRingInfo()->dp_urfData.get());
|
|
// std::cerr << " URF, RC " << numURF << " " << numRC << std::endl;
|
|
TEST_ASSERT(numURF == 5);
|
|
TEST_ASSERT(numRC == 20);
|
|
int numRings = m->getRingInfo()->numRings();
|
|
// std::cerr << "num rings: " << numRings << std::endl;
|
|
TEST_ASSERT(numRings == 14);
|
|
TEST_ASSERT(m->getRingInfo()->numRingFamilies() == 5);
|
|
delete m;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
#else
|
|
void testRingFamilies() {}
|
|
#endif
|
|
|
|
void testSetTerminalAtomCoords() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing adding "
|
|
"coordinates to a terminal atom. "
|
|
<< std::endl;
|
|
auto mol = R"CTAB(
|
|
RDKit 2D
|
|
|
|
6 6 0 0 0 0 0 0 0 0999 V2000
|
|
1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.7500 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.7500 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.7500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.7500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0
|
|
2 3 1 0
|
|
3 4 2 0
|
|
4 5 1 0
|
|
5 6 2 0
|
|
6 1 1 0
|
|
M END)CTAB"_ctab;
|
|
auto atom = new Atom(0);
|
|
auto idx = mol->addAtom(atom);
|
|
delete atom;
|
|
mol->addBond(idx, 0);
|
|
MolOps::setTerminalAtomCoords(static_cast<ROMol &>(*mol), idx, 0);
|
|
auto &coord = mol->getConformer().getAtomPos(idx);
|
|
TEST_ASSERT(coord.x > 2.499 && coord.x < 2.501);
|
|
TEST_ASSERT(coord.y > -0.001 && coord.y < 0.001);
|
|
TEST_ASSERT(coord.z > -0.001 && coord.z < 0.001);
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testGet3DDistanceMatrix() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n testing get3DDistanceMat(). " << std::endl;
|
|
auto mol = R"CTAB(bogus example
|
|
RDKit 3D
|
|
|
|
3 2 0 0 0 0 0 0 0 0999 V2000
|
|
0.0000 0.0000 0.1000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.2000 0.0000 0.1000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
2.5000 0.0000 0.1000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0
|
|
2 3 1 0
|
|
M END)CTAB"_ctab;
|
|
TEST_ASSERT(mol);
|
|
|
|
double *dm = MolOps::get3DDistanceMat(*mol);
|
|
TEST_ASSERT(dm);
|
|
TEST_ASSERT(dm[0] == 0.0);
|
|
TEST_ASSERT(dm[1] == 1.2);
|
|
TEST_ASSERT(dm[2] == 2.5);
|
|
TEST_ASSERT(dm[3] == 1.2);
|
|
TEST_ASSERT(dm[4] == 0.0);
|
|
TEST_ASSERT(dm[5] == 1.3);
|
|
TEST_ASSERT(dm[6] == 2.5);
|
|
TEST_ASSERT(dm[7] == 1.3);
|
|
TEST_ASSERT(dm[8] == 0.0);
|
|
// this will use a cached version:
|
|
double *dm2 = MolOps::get3DDistanceMat(*mol);
|
|
TEST_ASSERT(dm == dm2)
|
|
|
|
int confId = -1;
|
|
bool useAtomWts = true;
|
|
dm = MolOps::get3DDistanceMat(*mol, confId, useAtomWts);
|
|
TEST_ASSERT(dm);
|
|
TEST_ASSERT(dm[0] == 1.0);
|
|
TEST_ASSERT(dm[1] == 1.2);
|
|
TEST_ASSERT(dm[2] == 2.5);
|
|
TEST_ASSERT(dm[3] == 1.2);
|
|
TEST_ASSERT(dm[4] == 1.0);
|
|
TEST_ASSERT(dm[5] == 1.3);
|
|
TEST_ASSERT(dm[6] == 2.5);
|
|
TEST_ASSERT(dm[7] == 1.3);
|
|
TEST_ASSERT(dm[8] == 6.0 / 8.0);
|
|
|
|
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
|
|
}
|
|
|
|
void testGithub5099() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing github issue 5099: "
|
|
"Removing H preserving only wedged ones strips all H"
|
|
<< std::endl;
|
|
|
|
std::string smi{"FC([H])(O)Cl"};
|
|
std::unique_ptr<RWMol> m{SmilesToMol(smi, false, false)};
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
m->getBondBetweenAtoms(1, 2)->setBondDir(Bond::BondDir::BEGINWEDGE);
|
|
|
|
auto ps = MolOps::RemoveHsParameters();
|
|
ps.showWarnings = false;
|
|
|
|
// Remove all but Wedged/dashed H
|
|
ps.removeWithWedgedBond = false;
|
|
ps.removeDefiningBondStereo = true;
|
|
ps.removeDegreeZero = true;
|
|
ps.removeDummyNeighbors = true;
|
|
ps.removeHigherDegrees = true;
|
|
ps.removeHydrides = true;
|
|
ps.removeInSGroups = true;
|
|
ps.removeIsotopes = true;
|
|
ps.removeMapped = true;
|
|
ps.removeNonimplicit = true;
|
|
ps.removeOnlyHNeighbors = true;
|
|
ps.removeWithQuery = true;
|
|
|
|
removeHs(*m, ps);
|
|
|
|
// H shouldn't be removed
|
|
TEST_ASSERT(m->getNumAtoms() == 5);
|
|
}
|
|
|
|
int main() {
|
|
RDLog::InitLogs();
|
|
// boost::logging::enable_logs("rdApp.debug");
|
|
|
|
test1();
|
|
test2();
|
|
test3();
|
|
test4();
|
|
test5();
|
|
// test6();
|
|
test7();
|
|
test8();
|
|
test9();
|
|
test10();
|
|
test12();
|
|
testIssue183();
|
|
testIssue188();
|
|
testIssue189();
|
|
testShortestPath();
|
|
testIssue190();
|
|
testIssue211();
|
|
testIssue210();
|
|
testIssue212();
|
|
testAddHsCoords();
|
|
testAddConformers();
|
|
testSanitOps();
|
|
testIssue252();
|
|
testIssue276();
|
|
testHsAndAromaticity();
|
|
testSFIssue1694023();
|
|
testSFIssue1719053();
|
|
testSFIssue1811276();
|
|
testSFIssue1836576();
|
|
testChiralityAndRemoveHs();
|
|
testSFIssue1894348();
|
|
testSFIssue1942657();
|
|
testSFIssue1968608();
|
|
testHybridization();
|
|
testAromaticityEdges();
|
|
testSFNetIssue2196817();
|
|
testSFNetIssue2208994();
|
|
testSFNetIssue2313979();
|
|
testSFNetIssue2316677();
|
|
testSFNetIssue2951221();
|
|
testSFNetIssue2952255();
|
|
testSFNetIssue3185548();
|
|
testSFNetIssue3349243();
|
|
testFastFindRings();
|
|
testSanitizeNonringAromatics();
|
|
testSFNetIssue3349243();
|
|
testBasicCanon();
|
|
testSFNetIssue3549146();
|
|
testSFNetIssue249();
|
|
testSFNetIssue256();
|
|
testSFNetIssue266();
|
|
testSFNetIssue266();
|
|
testSFNetIssue272();
|
|
testGitHubIssue8();
|
|
testGitHubIssue42();
|
|
testGitHubIssue65();
|
|
testGitHubIssue72();
|
|
testRenumberAtoms();
|
|
testGithubIssue141();
|
|
testZBO();
|
|
testMolAssignment();
|
|
|
|
testAtomAtomMatch();
|
|
testGithubIssue190();
|
|
testMolFragsWithQuery();
|
|
test11();
|
|
testGithubIssue418();
|
|
testGithubIssue432();
|
|
testGithubIssue443();
|
|
testGithubIssue447();
|
|
testGetMolFrags();
|
|
testGithubIssue510();
|
|
testGithubIssue526();
|
|
testGithubIssue539();
|
|
testGithubIssue678();
|
|
testGithubIssue717();
|
|
testGithubIssue754();
|
|
testGithubIssue805();
|
|
testGithubIssue518();
|
|
testKekulizeErrorReporting();
|
|
testGithubIssue868();
|
|
testSimpleAromaticity();
|
|
testGithubIssue1730();
|
|
testCustomAromaticity();
|
|
testGithubIssue908();
|
|
testGithubIssue962();
|
|
|
|
testGithubIssue1021();
|
|
testGithubIssue607();
|
|
testAdjustQueryProperties();
|
|
testGithubIssue1204();
|
|
testSetBondStereo();
|
|
|
|
testBondSetStereoAtoms();
|
|
testGithub1478();
|
|
testGithub1439();
|
|
testGithub1281();
|
|
testGithub1605();
|
|
testGithub1614();
|
|
testGithub1622();
|
|
testGithub1703();
|
|
testGithub1810();
|
|
testGithub1936();
|
|
testGithub1928();
|
|
testGithub1990();
|
|
testPotentialStereoBonds();
|
|
testRingFamilies();
|
|
testRemoveAndTrackIsotopes();
|
|
testGithub3854();
|
|
testSetTerminalAtomCoords();
|
|
testGet3DDistanceMatrix();
|
|
testGithub5099();
|
|
|
|
return 0;
|
|
}
|