Skip to content

Commit

Permalink
fixed a few issues with rule bond query features
Browse files Browse the repository at this point in the history
  • Loading branch information
thsa committed Dec 16, 2024
1 parent daafd11 commit 9c011dc
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ public ChemicalRule(String name, String idcode, float panalty) {

public void initialize() {
Reaction rxn = ReactionEncoder.decode(mIDCode, false);
if (rxn.getReactants() != 1 || rxn.getProducts() != 1)
System.out.println("ERROR: Rule '"+mName+"' doesn't contain exactly one reactant and one product!");
if (!rxn.isFragment())
System.out.println("ERROR: Rule '"+mName+"' reactant and product are not marked as fragment!");
mReactant = rxn.getReactant(0);
mProduct = rxn.getProduct(0);
mReactant.ensureHelperArrays(Molecule.cHelperNeighbours);
Expand Down Expand Up @@ -137,8 +141,28 @@ public void initialize() {
}
}
}

calculatePenalty();
}

private void calculatePenalty() {
MappingScorer scorer = new MappingScorer(mReactant, mProduct);
int[] reactantMapNo = new int[mReactant.getAllAtoms()];
for (int i=0; i<mReactant.getAllAtoms(); i++)
reactantMapNo[i] = mReactant.getAtomMapNo(i);
int[] productMapNo = new int[mProduct.getAllAtoms()];
for (int i=0; i<mProduct.getAllAtoms(); i++)
productMapNo[i] = mProduct.getAtomMapNo(i);

mPanalty = -scorer.scoreMapping(scorer.createReactantToProductAtomMap(reactantMapNo, productMapNo)) * 0.25f;
// mPanalty = -scorer.scoreMapping(scorer.createReactantToProductAtomMap(reactantMapNo, productMapNo)) - 1.5f; // is a positive value

// The idea is that when a rule is applied, then the score should be better than
// the simple calculated score from bond changes, because we know that we use
// reasonable chemistry. How much better, whether a constant of whether rule-dependent
// remains to be determined...
}

private boolean isTHParityInversion(int reactantAtom, int[] mapNoToProduct) {
boolean inversion = false;
if (mReactant.getAtomPi(reactantAtom) == 0) {
Expand Down Expand Up @@ -210,12 +234,12 @@ public float getPanalty() {
* scoring redundant mapping graphs, these should be sorted out early. Reasons for
* redundant matches may be:<br>
* - if the rule reactant is one fragment, this may be symmetrical Cn or Dn<br>
* - the rule reactant may contain multiple equivalent fragments, e.g. metathese<br>
* - matching atoms in the real reactant my be symmetrical<br>
* - the rule reactant may contain multiple equivalent fragments, e.g. metathesis<br>
* - matching atoms in the real reactant may be symmetrical<br>
* Otherwise, there certain causes may exist, that break these symmetries:<br>
* - a symmetrical rule fragment must not considered symmetrical, if it doesn't react
* - a symmetrical rule fragment must not be considered symmetrical, if it doesn't react
* symmetrically, i.e. if its matching rule product atoms are not equivalent anymore.
* - in case of multiple symmetrical fragments in the rule's reactant (e.g. metathese),
* - in case of multiple symmetrical fragments in the rule's reactant (e.g. metathesis),
* inverted/rotated individual fragment matches cause different products, that means
* that the relative match orientation of multiple symmetrical fragments breaks symmetry,
* if the real matching atoms are not equivalent.<br>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public class ChemicalRuleEnhancedReactionMapper implements IReactionMapper {
// Of course, when a rule is applied, then only the mapped region of the rule is used as a template to
// change bonding of the reaction the rule is applied to. Nevertheless, the rule's entire reactant is used
// for the substructure search that identifies applicability.
// NOTE: Rule reactions must contain one reactant and one product only (usually these consist of multiple fragments)!
// NOTE: You may use the idcodeexplorer.jar to generate new rules.
private static final ChemicalRule[] CHEMICAL_RULE = {
// With cleaned coordinates:
new ChemicalRule("d","gGQ@@eKtRA@!gGQ@@djqRA@#qMsT qM\\V#!B_qL@Dw}l@Fp@Dp !B@AL@[@@S@Fp@Dp##", 3.5f),
Expand All @@ -70,10 +72,10 @@ public class ChemicalRuleEnhancedReactionMapper implements IReactionMapper {
new ChemicalRule("Sakurai", "gOQH@wAINvZ@pdcFe@x@!gOQH@wAIgJi@pdcFe@x@#qreKx qrLkx#!BDpAl@IknDw|S@Fp@ !Bb@JH?_x@b@JH?Ven##", 4.5f),
new ChemicalRule("Mitsunobu", "gFP`ATfRhdPp`}KEYg]d@!gFP`ATfRhd`pekL{l`#qrLk qZLn#!B@hc}b@C~@h`YM` !B@hc}b@C~@h`YM`##", 4.5f),

new ChemicalRule("Aldol-Addition", "gOQ@AdTAcW@[Q^crJTLES`DO}b@!gGQ@@dsuVAcJg@H@#qYEbp qYub#!B@O{|b@Jw\\o{~@Oy? !Bb@K~@Hc}b@JH@`##", 1.5f),
new ChemicalRule("Aldol-Condensation", "gOQ@AdTAcW@[Q^crJTLES`DO}b@!gFQ@@`v|pblHHqIpB@#qYEbp q\\VM#!B@O{|b@Jw\\o{~@Oy? !BxpE?[@@S@Fp@Dp##", 2.5f),
new ChemicalRule("Acetal-Aldol-Addition", "dmdB@@serQS@sJjnl@p`Xir\\@`j\\@`!daxL@@[df[Zj|@qQdxACdxA@#qB@`OuX qBtM{#!B?[_}b@Jw_?{}mwk~?X`Bmwvw_[\\ !Bb@K~@Hc}b@Jw@h`BmpH##", 1.5f),
new ChemicalRule("Acetal-Aldol-Condensation", "dmdB@@serQS@sJjnl@p`Xir\\@`j\\@`!gNp`ITkez^@qTS`DJg@H@#qB@`OuX qOuS`#!B?[_}b@Jw_?{}mwk~?X`Bm?vw_[\\ !Bm?rH__y?b@K~_xa}##", 1.5f),
new ChemicalRule("Aldol-Addition", "gOQ@AdTAcS@[Q^crJTLES`DJsL?vH!gGQ@@dsuRAcJg@HUaX#qYEbp qYub#!BxOyBzLKg`dG~xG~{ !Bb@K~@Hc}FBIA@@##", 1.5f),
new ChemicalRule("Aldol-Condensation", "gOQ@AdTAcS@[Q^crJTLES`DJsL?vH!gFQ@@`rrpdlHHpipBEXf@#qYEbp q^aU#!B{ZRRqA?AQfyA@L_C !B}QFw@h`B_tnH_P##", 2.5f),
new ChemicalRule("Acetal-Aldol-Addition", "dmdB@@serQS@sJjfd@p`Xir\\@`j\\@aUJXK@!daxL@@[df[ZjT@qQdxACdxABjTqf@#qB@`OuX qBtM{#!B_]]}rHKWw?y}uy[~GJbBu{wWqG| !BfJK~TIa]fJJghg{`pP@##", 1.5f),
new ChemicalRule("Acetal-Aldol-Condensation", "dmdB@@serQS@sJjfd@p`Xir\\@`j\\@aUJXK@!gNp`CTjUiV@qQS`DJg@HUVXV@#qB@`OuX qqj{`#!B?[_}b@Jw_?{}m~[~[N@Bm?vwkN| !BfsK~yzPrw}m?rzQM##", 1.5f),
new ChemicalRule("Acetal-Aldol-Condensation-Cyclization", "dkLB@@ZURYUvUjljh@paHpr\\@`!didD@@yIfUXXHL@CFNS`D@#IXljNPY@@@ IXljIyA#!BbOw~_x`Bm?vH?[_}b@JH?_y?b@Jw?Xc} !BbOvH?Oy??`BH?Xa}?`C~_p##", 7.5f),
new ChemicalRule("Enolester-Cleavage", "gOQ`@fdscT`_Qp!gOQ`@cdTASS@P#q}Kr` q}cNP#!B@k]}mpC~@k]}mqdY !Bb@K~@Hc}BfzH@hc}##", 5.3f),

Expand All @@ -91,7 +93,7 @@ public class ChemicalRuleEnhancedReactionMapper implements IReactionMapper {
// two-step
new ChemicalRule("Elimination-Claisen", "gNp`AldTQji@~a`!gOP`@teTZdCzN@#qtHUX qtSi@#!Bm?vH?[\\B?g~H@hc} !B@AL@[@@S@Fp@DweA##", 4.5f),
new ChemicalRule("imineFormationAzaCope", "daZH@LAIMUjd@pRL@!daZH@HAAn]jd@p`@#IGfaLJ` IFDzfK@#!BDpAl@IkqDpAl@AL@[@@ !BFaFw@h`BbOw~@H`BbOt##", 8.5f),
new ChemicalRule("didehydroCopeWithAromatisation", "gNp@DiuVYDsj`rLwA`!gOp@DjWkB@@H#q]yr` q\\oQp#!Bm?vH@k\\Bm?w~_{_} !Bm?w~@Hc}mpJw@ox@##", 4.5f),
new ChemicalRule("didehydroCopeWithAromatisation", "gNp@Di]ejDcjcr|wK`!gOp@DjWkB@@H#qrLkx q\\oQp#!B?g~H?K_}bGvH?H`B !Bm?w~@Hc}mpJw@ox@##", 4.5f),

// multi-step with cyclisation/condensation
new ChemicalRule("symAldolNitrogenRing", "dovJ@GBfttf\\v\\qjViPCADGbDodnGp!doNJ@JCSmtefWTCaYjje@H#IlZXi]]yL~C IqMVCzaIim?#!BQtl_riY?Qtl_rfuvNCQ`uZd@NCQ`uVVu}?sA]P !B?`BH@ox@bGvH@k\\Bb@JH_Xa}b@K~_rYltUr|W@##", 0.5f),
Expand All @@ -114,6 +116,9 @@ public class ChemicalRuleEnhancedReactionMapper implements IReactionMapper {
new ChemicalRule("Epoxydation", "gB``ADcdCB@!gC``AhtUPGtt@#qqb qtQ#!BjW}Y\\YX@ !B?g~w?^Va##", 6.3f),
new ChemicalRule("oxydativePropargylAmine13Shift", "gKi@HDEZpLHOQP!gJY@BDeVXB#qMr` qNTh#!BqiXTy{U?mW| !B@Fp@DpAl@AL##", 6.5f),
new ChemicalRule("Baeyer-Villiger", "gFQ`@[dTAZ`LHP!gFQ`@jdrMPGtl@#qrak qrlK#!B_?{}mwvHs^FVP@ !BbOvH@oy?bOuQzP##", 7.5f),

// condensation with ring closure
new ChemicalRule("Hantzsch Thiazol", "gOYDGaDDHRTve`H!gKXHL@aJWFe`H#qB`ip qiV`#!B_vq?Dw}lL{y?[G|S !BTqa`FbpX?`@##", 3.5f),
};

private static boolean sInitialized;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ public class MappingScorer {
private static final boolean SCORE_SIMPLE = false;
private static final boolean SCORE_HYDROGEN = false;

private StereoMolecule mReactant,mProduct;
private final StereoMolecule mReactant,mProduct;

/**
* Instantiates a mapping scorer that judges the quality of a mapping by adding penalties for every bond
* being broken, created, or changed. In principle the panelty for any created or broken bond is 2.0,
* being broken, created, or changed. In principle the penalty for any created or broken bond is 2.0,
* and for any changed bond order is 1.0. A change from/to delocalized to/from single or double is considered
* a change. Broken or created bonds at typical break locations, e.g. ester cleavage, get slightly lower
* penalties than 2.0. Changes of implicit hydrogen counts contribute with a factor of 2.0.
Expand Down Expand Up @@ -97,6 +97,12 @@ public float scoreMapping(int[] reactantToProductAtom) {
for (int rBond=0; rBond<mReactant.getBonds(); rBond++) {
int rAtom1 = mReactant.getBondAtom(0, rBond);
int rAtom2 = mReactant.getBondAtom(1, rBond);

if (mReactant.isFragment()
&& ((mReactant.getAtomQueryFeatures(rAtom1) & Molecule.cAtomQFExcludeGroup) != 0
|| (mReactant.getAtomQueryFeatures(rAtom2) & Molecule.cAtomQFExcludeGroup) != 0))
continue;

int pAtom1 = reactantToProductAtom[rAtom1];
int pAtom2 = reactantToProductAtom[rAtom2];

Expand Down Expand Up @@ -138,6 +144,11 @@ public float scoreMapping(int[] reactantToProductAtom) {
}

for (int pBond=0; pBond<mProduct.getBonds(); pBond++) {
if (mProduct.isFragment()
&& ((mProduct.getAtomQueryFeatures(mProduct.getBondAtom(0, pBond)) & Molecule.cAtomQFExcludeGroup) != 0
|| (mProduct.getAtomQueryFeatures(mProduct.getBondAtom(1, pBond)) & Molecule.cAtomQFExcludeGroup) != 0))
continue;

if (!productBondHandled[pBond]) {
penalty += getBondCreateOrBreakPenalty(mProduct, pBond);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2872,7 +2872,7 @@ private void fireEventLater(EditorEvent e) {

/**
* Redraws the molecule(s) or the reaction after scaling coordinates.
* Then analyses fragment membership and recreate individual molecules, reaction, or markush structure
* Then analyses fragment membership and recreates individual molecules, reaction, or markush structure
* Then, fires molecule change events with userChange=false, i.e. external change.
*/
public void moleculeChanged() {
Expand Down

0 comments on commit 9c011dc

Please sign in to comment.