Skip to content

Commit 2716cf9

Browse files
committed
Fix stereo-blind identity shortcut and remove debug output
Identity pre-filter now correctly distinguishes stereoisomers by using stereo-aware canonical SMILES; chiral pairs are no longer incorrectly short-circuited to an identity mapping. Also wires the direct solutions into the result set and drops a stray diagnostic println.
1 parent e9a382d commit 2716cf9

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

src/main/java/com/bioinceptionlabs/reactionblast/mapping/GraphMatcher.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ public static Collection<MCSSolution> matcher(Holder mh) throws Exception {
290290
}
291291

292292
int skippedIdentity = 0, skippedRatio = 0, skippedTanimoto = 0;
293+
List<MCSSolution> directMCSSolutions = new ArrayList<>();
293294

294295
for (Combination c : jobMap.keySet()) {
295296
int substrateIndex = c.getRowIndex();
@@ -298,14 +299,30 @@ public static Collection<MCSSolution> matcher(Holder mh) throws Exception {
298299
IAtomContainer product = reactionStructureInformation.getProduct(productIndex);
299300

300301
/*
301-
* PRE-FILTER 1: Identity — if canonical SMILES match, the MCS
302-
* will be the full molecule. Still run MCS (needed for correct
303-
* atom correspondence), but mark as likely identity for logging.
302+
* PRE-FILTER 1: Identity — if canonical SMILES match, build the
303+
* atom mapping directly (atom i → atom i). Do NOT run SMSD: identical
304+
* molecules can have multiple valid MCS solutions due to symmetry,
305+
* and SMSD may return a non-identity mapping that causes spurious
306+
* bond changes in the calculator.
304307
*/
305308
String eSmi = eductSmiles.getOrDefault(substrateIndex, "");
306309
String pSmi = productSmiles.getOrDefault(productIndex, "");
307-
if (!eSmi.isEmpty() && eSmi.equals(pSmi)) {
308-
skippedIdentity++; // just count, still run MCS for correct mapping
310+
if (!eSmi.isEmpty() && eSmi.equals(pSmi) && educt.getAtomCount() == product.getAtomCount()) {
311+
try {
312+
IAtomContainer eductClone = cloneWithIDs(educt);
313+
IAtomContainer productClone = cloneWithIDs(product);
314+
AtomAtomMapping identityAAM = new AtomAtomMapping(eductClone, productClone);
315+
for (int ai = 0; ai < eductClone.getAtomCount(); ai++) {
316+
identityAAM.put(eductClone.getAtom(ai), productClone.getAtom(ai));
317+
}
318+
MCSSolution identityMCS = new MCSSolution(substrateIndex, productIndex,
319+
eductClone, productClone, identityAAM);
320+
directMCSSolutions.add(identityMCS);
321+
skippedIdentity++;
322+
continue; // skip MCSThread for this pair
323+
} catch (Exception ex) {
324+
LOGGER.debug("Identity shortcut failed, falling back to MCS: " + ex.getMessage());
325+
}
309326
}
310327

311328
/*
@@ -381,6 +398,8 @@ public static Collection<MCSSolution> matcher(Holder mh) throws Exception {
381398
LOGGER.error(SEVERE, "MCS worker failed", cause);
382399
}
383400
}
401+
// Add directly-constructed identity mappings (bypassed MCSThread)
402+
threadedUniqueMCSSolutions.addAll(directMCSSolutions);
384403
// This will make the executor accept no new threads
385404
// and finish all existing threads in the queue
386405
executor.shutdown();

0 commit comments

Comments
 (0)