Simple fix to allow aromatic CIS/TRANS SMARTS to match molecules (#8192)

This commit is contained in:
Brian Kelley
2025-01-23 13:49:25 -05:00
committed by greg landrum
parent 3e04457d4e
commit 21b79c13e2
5 changed files with 43 additions and 3 deletions

View File

@@ -410,7 +410,19 @@ std::string getBondSmartsSimple(const Bond *bond,
} else if (descrip == "BondInRing") {
res += "@";
} else if (descrip == "SingleOrAromaticBond") {
// don't need to do anything here... :-)
auto dir = bond->getBondDir();
switch(dir) {
case Bond::ENDDOWNRIGHT: {
res += "\\";
break;
}
case Bond::ENDUPRIGHT: {
res += "/";
break;
}
default:
break;
}
} else if (descrip == "SingleOrDoubleBond") {
res += "-,=";
} else if (descrip == "DoubleOrAromaticBond") {
@@ -1040,4 +1052,4 @@ std::string MolFragmentToCXSmarts(const ROMol &mol,
return res;
}
} // namespace RDKit
} // namespace RDKit

View File

@@ -1733,6 +1733,7 @@ YY_RULE_SETUP
#line 362 "smarts.ll"
{ yylval->bond = new QueryBond(Bond::SINGLE);
yylval->bond->setBondDir(Bond::ENDDOWNRIGHT);
yylval->bond->setQuery(makeSingleOrAromaticBondQuery());
return BOND_TOKEN; }
YY_BREAK
case 153:
@@ -1740,6 +1741,7 @@ YY_RULE_SETUP
#line 366 "smarts.ll"
{ yylval->bond = new QueryBond(Bond::SINGLE);
yylval->bond->setBondDir(Bond::ENDUPRIGHT);
yylval->bond->setQuery(makeSingleOrAromaticBondQuery());
return BOND_TOKEN; }
YY_BREAK
case 154:

View File

@@ -360,10 +360,12 @@ A {
[\\]{1,2} { yylval->bond = new QueryBond(Bond::SINGLE);
yylval->bond->setBondDir(Bond::ENDDOWNRIGHT);
yylval->bond->setQuery(makeSingleOrAromaticBondQuery());
return BOND_TOKEN; }
[\/] { yylval->bond = new QueryBond(Bond::SINGLE);
yylval->bond->setBondDir(Bond::ENDUPRIGHT);
yylval->bond->setQuery(makeSingleOrAromaticBondQuery());
return BOND_TOKEN; }
\-\> {

View File

@@ -1167,6 +1167,16 @@ void testSmartsStereochem() {
_checkMatches("C/C=C/C", "C/C=C/C", 1, 4);
_checkMatches("C/C=C/C", "C\\C=C\\C", 1, 4);
_checkMatches("C/C=C/C", "C/C=C\\C", 1, 4);
// directional bonds are set to be a direction \ /
// and a query - SingleOrAromatic, make sure that this
// is their current representation
auto m1 = "C/C=C\\C"_smarts;
TEST_ASSERT(m1->getBondWithIdx(0)->hasQuery());
TEST_ASSERT(m1->getBondWithIdx(0)->getQuery()->getDescription() == "SingleOrAromaticBond");
auto m2 = "O=c1/c(=C/c2ccccc2)sc2n1-N-C-N-N=2"_smarts;
TEST_ASSERT(MolToSmarts(*m2) == "O=c1/c(=C/c2ccccc2)sc2n1-N-C-N-N=2");
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
}

View File

@@ -840,4 +840,18 @@ M END)CTAB"_ctab;
CHECK(SubstructMatch(*m_single, *m_aromatic, ps).size() == 1);
CHECK(SubstructMatch(*m_aromatic, *m_single, ps).size() == 1);
}
}
}
TEST_CASE("Github #7295", "CIS/TRANS in aromatic ring") {
SECTION("Smart CIS/TRANS bonds should match single or aromatic"){
SubstructMatchParameters ps;
auto query = "[O:1]=[c:2]1/[c:3](=[C:4]/[c:5]2:[c:10]:[c:9]:[c:8]:[c:7]:[c:6]:2):[s:11]:[c:12]2:[n:13]:1-[N:14]-[C:15]-[N:20]-[N:21]=2"_smarts;
auto mol = "[O:1]=[c:2]1/[c:3](=[CH:4]/[c:5]2[cH:6][cH:7][cH:8][cH:9][cH:10]2)[s:11][c:12]2[n:13]1[NH:14][C:15]1([CH2:16][CH2:17][CH2:18][CH2:19]1)[NH:20][N:21]=2"_smiles;
CHECK(SubstructMatch(*mol, *query, ps).size() == 1);
ps.useChirality = true;
CHECK(SubstructMatch(*mol, *query, ps).size() == 1);
auto mol2 = "[O:1]=[c:2]1\\[c:3](=[CH:4]/[c:5]2[cH:6][cH:7][cH:8][cH:9][cH:10]2)[s:11][c:12]2[n:13]1[NH:14][C:15]1([CH2:16][CH2:17][CH2:18][CH2:19]1)[NH:20][N:21]=2"_smiles;
CHECK(SubstructMatch(*mol2, *query, ps).size() == 0);
}
}