mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-03 21:44:30 +08:00
trimethylcyclohexane chirality error (#8272)
* Fix for trimethylcyclohexane error * removed unused variable * removed debugging code
This commit is contained in:
@@ -654,31 +654,53 @@ void flagRingStereo(ROMol &mol,
|
||||
if (!knownAtoms[aidx] && (!possibleAtoms || !possibleAtoms->test(aidx))) {
|
||||
continue;
|
||||
}
|
||||
if (!ringIsOddSized) {
|
||||
// find the index of the atom on the opposite side of the even-sized
|
||||
// ring
|
||||
auto oppositeIdx = aring[(ai + halfSize) % sz];
|
||||
bool toAtomOppositePossible = false;
|
||||
auto oppositeAtom = mol.getAtomWithIdx(oppositeIdx);
|
||||
for (auto bond : mol.atomBonds(oppositeAtom)) {
|
||||
auto bidx = bond->getIdx();
|
||||
if ((knownBonds[bidx] ||
|
||||
(possibleBonds && possibleBonds->test(bidx))) &&
|
||||
std::find(bring.begin(), bring.end(), bidx) == bring.end()) {
|
||||
toAtomOppositePossible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (knownAtoms[oppositeIdx] ||
|
||||
(possibleAtoms && possibleAtoms->test(oppositeIdx)) ||
|
||||
toAtomOppositePossible) {
|
||||
nHere += 1 + toAtomOppositePossible;
|
||||
possibleAtomsInRing.set(aidx);
|
||||
possibleAtomsInRing.set(oppositeIdx);
|
||||
mol.getAtomWithIdx(aidx)->setProp(
|
||||
common_properties::_ringStereoOtherAtom, oppositeIdx);
|
||||
continue;
|
||||
for (unsigned int ringDivisor : {2, 3}) {
|
||||
bool ringIsMultipleOfDivisor = ((sz % ringDivisor) == 0);
|
||||
auto incrementSize = sz / ringDivisor;
|
||||
|
||||
if (ringIsMultipleOfDivisor) {
|
||||
// find the two indices of the atoms 1/3 the way around the ring
|
||||
|
||||
unsigned int otherFoundByBondCount = 0;
|
||||
unsigned int otherFoundByAtomCount = 0;
|
||||
for (unsigned int indexIncrement = incrementSize; indexIncrement < sz;
|
||||
indexIncrement += incrementSize) {
|
||||
auto otherIdx = aring[(ai + indexIncrement) % sz];
|
||||
auto otherAtom = mol.getAtomWithIdx(otherIdx);
|
||||
|
||||
for (auto bond : mol.atomBonds(otherAtom)) {
|
||||
auto bidx = bond->getIdx();
|
||||
if ((knownBonds[bidx] ||
|
||||
(possibleBonds && possibleBonds->test(bidx))) &&
|
||||
std::find(bring.begin(), bring.end(), bidx) == bring.end()) {
|
||||
otherFoundByBondCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (otherFoundByBondCount == 0) {
|
||||
if (knownAtoms[otherIdx] ||
|
||||
(possibleAtoms && possibleAtoms->test(otherIdx))) {
|
||||
otherFoundByAtomCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (otherFoundByBondCount == ringDivisor - 1 ||
|
||||
otherFoundByAtomCount == ringDivisor - 1) {
|
||||
nHere += 1 + otherFoundByBondCount;
|
||||
for (unsigned int indexIncrement = 0; indexIncrement < sz;
|
||||
indexIncrement += incrementSize) {
|
||||
possibleAtomsInRing.set(aring[(ai + indexIncrement) % sz]);
|
||||
}
|
||||
if (ringDivisor == 2) {
|
||||
mol.getAtomWithIdx(aidx)->setProp(
|
||||
common_properties::_ringStereoOtherAtom,
|
||||
aring[(ai + incrementSize) % sz]);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2301,8 +2301,8 @@ TEST_CASE("ring bond stereochemistry in CXSMILES") {
|
||||
{"C1CCCCC=CCCC1 |c:5|", "C1=C\\CCCCCCCC/1 |c:0|"},
|
||||
{"C1CCCC/C=C/CCC1 |c:5|", "C1=C\\CCCCCCCC/1 |c:0|"},
|
||||
{"C1=CCCCCCCCC1 |ctu:0|", "C1=CCCCCCCCC1 |ctu:0|"},
|
||||
{"C=CCCCCCCCC |ctu:0|",
|
||||
"C=CCCCCCCCC"} // we don't write the markers for non-ring bonds
|
||||
{"C=CCCCCCCCC |ctu:0|", "C=CCCCCCCCC"}
|
||||
// we don't write the markers for non-ring bonds
|
||||
};
|
||||
for (const auto &[smi, val] : tests) {
|
||||
std::unique_ptr<RWMol> m{SmilesToMol(smi)};
|
||||
@@ -2993,45 +2993,71 @@ TEST_CASE("Ignore atom map numbers") {
|
||||
}
|
||||
|
||||
TEST_CASE("Github #7340", "[Reaction][CX][CXSmiles]") {
|
||||
SECTION("Test getCXExtensions with a Vector"){
|
||||
SECTION("Test getCXExtensions with a Vector") {
|
||||
// Create the MOL_SPTR_VECT to hold the molecular pointers
|
||||
const auto mols = {
|
||||
"CCO* |$;;;_R1$(0,0,0;1.5,0,0;1.5,1.5,0;0,1.5,0)|"_smiles,
|
||||
"C1CCCCC1 |$;label2;$|"_smiles,
|
||||
"CC(=O)O |$;label1;$|"_smiles,
|
||||
"*-C-* |$star_e;;star_e$,Sg:n:1::ht|"_smiles,
|
||||
"CCO* |$;;;_R1$(0,0,0;1.5,0,0;1.5,1.5,0;0,1.5,0)|"_smiles,
|
||||
"C1CCCCC1 |$;label2;$|"_smiles,
|
||||
"CC(=O)O |$;label1;$|"_smiles,
|
||||
"*-C-* |$star_e;;star_e$,Sg:n:1::ht|"_smiles,
|
||||
};
|
||||
|
||||
std::vector<ROMol *> mol_vect;
|
||||
mol_vect.reserve(mols.size());
|
||||
for (const auto& mol : mols) {
|
||||
mol_vect.push_back(mol.get());
|
||||
for (const auto &mol : mols) {
|
||||
mol_vect.push_back(mol.get());
|
||||
}
|
||||
|
||||
// Write to smiles to populate atom and bond output order properties
|
||||
for (const auto& entry : mol_vect) {
|
||||
for (const auto &entry : mol_vect) {
|
||||
MolToSmiles(*entry);
|
||||
}
|
||||
|
||||
std::string cxExt = SmilesWrite::getCXExtensions(mol_vect, RDKit::SmilesWrite::CXSmilesFields::CX_ALL);
|
||||
std::string cxExt = SmilesWrite::getCXExtensions(
|
||||
mol_vect, RDKit::SmilesWrite::CXSmilesFields::CX_ALL);
|
||||
|
||||
CHECK(cxExt == "|(0,1.5,;1.5,1.5,;1.5,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,),$_R1;;;;;label2;;;;;;label1;;;star_e;;star_e$,Sg:n:15::ht:::|");
|
||||
CHECK(
|
||||
cxExt ==
|
||||
"|(0,1.5,;1.5,1.5,;1.5,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,;0,0,),$_R1;;;;;label2;;;;;;label1;;;star_e;;star_e$,Sg:n:15::ht:::|");
|
||||
}
|
||||
|
||||
SECTION("Expects an error"){
|
||||
SECTION("Expects an error") {
|
||||
const auto mols = {
|
||||
"CCO* |$;;;_R1$(0,0,0;1.5,0,0;1.5,1.5,0;0,1.5,0)|"_smiles,
|
||||
"C1CCCCC1 |$;label2;$|"_smiles,
|
||||
"CC(=O)O |$;label1;$|"_smiles,
|
||||
"*-C-* |$star_e;;star_e$,Sg:n:1::ht|"_smiles,
|
||||
"CCO* |$;;;_R1$(0,0,0;1.5,0,0;1.5,1.5,0;0,1.5,0)|"_smiles,
|
||||
"C1CCCCC1 |$;label2;$|"_smiles,
|
||||
"CC(=O)O |$;label1;$|"_smiles,
|
||||
"*-C-* |$star_e;;star_e$,Sg:n:1::ht|"_smiles,
|
||||
};
|
||||
|
||||
std::vector<ROMol *> mol_vect;
|
||||
mol_vect.reserve(mols.size());
|
||||
for (const auto& mol : mols) {
|
||||
mol_vect.push_back(mol.get());
|
||||
for (const auto &mol : mols) {
|
||||
mol_vect.push_back(mol.get());
|
||||
}
|
||||
|
||||
CHECK_THROWS_AS(SmilesWrite::getCXExtensions(mol_vect, RDKit::SmilesWrite::CXSmilesFields::CX_ALL), ValueErrorException);
|
||||
CHECK_THROWS_AS(SmilesWrite::getCXExtensions(
|
||||
mol_vect, RDKit::SmilesWrite::CXSmilesFields::CX_ALL),
|
||||
ValueErrorException);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("trimethylcyclohexane") {
|
||||
SECTION("Basic") {
|
||||
UseLegacyStereoPerceptionFixture useLegacy(false);
|
||||
|
||||
auto smi = "C[C@H]1C[C@@H](C)C[C@@H](C)C1";
|
||||
RDKit::v2::SmilesParse::SmilesParserParams smilesParserParams;
|
||||
auto m1 = RDKit::v2::SmilesParse::MolFromSmiles(smi, smilesParserParams);
|
||||
auto smiOut = RDKit::MolToCXSmiles(*m1);
|
||||
CHECK(smiOut == "C[C@@H]1C[C@H](C)C[C@H](C)C1");
|
||||
}
|
||||
SECTION("WithEnhancedStereo") {
|
||||
UseLegacyStereoPerceptionFixture useLegacy(false);
|
||||
|
||||
auto smi = "C[C@H]1C[C@@H](C)C[C@@H](C)C1 |o1:1,o2:6,o3:3|";
|
||||
RDKit::v2::SmilesParse::SmilesParserParams smilesParserParams;
|
||||
auto m1 = RDKit::v2::SmilesParse::MolFromSmiles(smi, smilesParserParams);
|
||||
auto smiOut = RDKit::MolToCXSmiles(*m1);
|
||||
CHECK(smiOut == "C[C@H]1C[C@H](C)C[C@H](C)C1 |o1:1,o2:3,o3:6|");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user