Custom MolComparator problem

User f93c2abd9d

05-11-2008 21:16:46

Hello everyone. I work with bobgr, and we are having a problem using a customized MolComparator provided by ChemAxon. We are currently using JChem 5.1.


Code:
package com.prenhall.epoch.chem;





import chemaxon.sss.search.MolComparator;


import chemaxon.struc.StereoConstants;





/**


 * A wavy bond matches only to another wavy bond


 * @see http://www.chemaxon.com/forum/viewpost6379.html


 * @see http://www.chemaxon.com/forum/viewpost7841.html


 * @author Tamas Csizmazia


 * @since  JChem 5.0


 */


public final class StereoANDComparator extends MolComparator implements StereoC


    public StereoANDComparator() {


    }


    public boolean compareAtoms(int queryAtom, int targetAtom) {


        int qParity = query.getLocalParity(queryAtom);


        int tParity = target.getLocalParity(targetAtom);


        System.out.println("StereoANDComparator.compareAtoms: "


                + "qParity = " + qParity


                + ", tParity = " + tParity


                + ", PARITY_UNSPEC = " + PARITY_UNSPEC);


        return (qParity == tParity || qParity == PARITY_UNSPEC);


    }


}





Note that we have modified the original code with debugging output code.





We use this StereoANDComparator in the following code block:


Code:
MolSearch search = new MolSearch(); 


MolSearchOptions searchOpts = new MolSearchOptions(); 


StereoANDComparator stereoANDComparator = new stereoANDComparator();





searchOpts.setSearchType(SearchConstants.EXACT);


search.addComparator(stereoANDComparator);


searchOpts.setStereoSearchType(SearchConstants.STEREO_SPECIFIC);


searchOpts.setDoubleBondStereoMatchingMode(StereoConstants.DBS_ALL); 


searchOpts.setVagueBondLevel(SearchConstants.VAGUE_BOND_OFF);


// required for comparing nonaromatized aromatic rings


searchOpts.setStereoModel(SearchConstants.STEREO_MODEL_GLOBAL);


searchOpts.setChargeMatching(SearchConstants.CHARGE_MATCHING_EXACT);


searchOpts.setIsotopeMatching(SearchConstants.ISOTOPE_MATCHING_EXACT);


searchOpts.setRadicalMatching(SearchConstants.RADICAL_MATCHING_EXACT);





search.setSearchOptions(searchOpts);


search.setTarget(respMol);


search.setQuery(authMol);





boolean res1 = search.isMatching();


return res1;





When the above code is run, the debugging code in StereoANDComparator is never run (there is no output to System.out). So what are we failing to do to tell the MolSearch object to actually use the stereoANDComparator instead of its default XOR behavior?





Our intent is to only change the parity checking portion of the default behavior, with all search options having their normal effect. If we call super.compareAtoms(queryAtom, targetAtom) at the beginning of StereoANDComparator.compareAtoms(), and follow it with our own parity checking code as above, will this provide the effect we want? If not, how might we change only the parity checking portion of the default behavior of MolComparator?





Thanks.

ChemAxon 7c2d26e5cf

05-11-2008 22:35:56

I have moved this topic to the JChem forum since it is rather connect to JChem than Marvin.

ChemAxon a9ded07333

06-11-2008 11:09:45

Hi Jay,





At the line
Code:
search.addComparator(stereoANDComparator);
the molcomparator is added to the search object's own searchOptions object. However, at the line
Code:
search.setSearchOptions(searchOpts);
this searchOptions object is replaced with another one that does not contain the molcomparator.





Solution: substitute
Code:
MolSearchOptions searchOpts = new MolSearchOptions();
with
Code:
MolSearchOptions searchOpts = search.getSearchOptions();






It is also possible that the debug code in the molcomparator won't run in case the search can reveal earlier the non-matching of the molecules (e.g the number of heavy atoms are different (exact/perfect search)).





Best regards,


Tamás

ChemAxon a9ded07333

06-11-2008 14:44:28

I have to confess that my example code (StereoANDComparator) contains a bug!





MolComparators were designed for internal use and we made them public because of their usefulness. MolComparators gots internal atom indices as parameters instead of original atom indices so they must be converted using the getOrigTargetAtom and getOrigQueryAtom methods.


The fixed code is the following (without debug information):





Code:
    public boolean compareAtoms(int queryAtom, int targetAtom) {


        int qParity = query.getLocalParity(getOrigQueryAtom(queryAtom));


        int tParity = target.getLocalParity(getOrigTargetAtom(targetAtom));


        return (qParity == tParity || qParity == PARITY_UNSPEC);


    }








I will correct the examples on our homepage soon.





Best regards,


Tamás

User f93c2abd9d

12-11-2008 13:55:54

Thank you for the prompt responses. Unfortunately, we had some other issues come up that had to be resolved before I could test this, so pardon the late response, and I hope nobody minds me bumping this thread.





I implemented the above suggestions and everything appears to be working. Thank you very much for your help and I'll be sure to let you know if we have any more problems with this.

User f93c2abd9d

12-11-2008 18:14:06

Well, something is still not right. It does not seem that getOrigQueryAtom() and getOrigTargetAtom() are working properly. We added some more debugging output, and this is what we are seeing when we use StereoANDComparator.


Code:
StereoANDComparator.compareAtoms: query = CC1CCCC[C@H]1O, target = CC1CCCC[C@H]1O;


queryAtom = 0, getOrigQueryAtom(queryAtom) = 0, targetAtom = 6, getOrigTargetAtom(targetAtom) = 6;


qAtom O1 has parity 0; tAtom O7 has parity 0;


PARITY_EITHER = 48, PARITY_UNSPEC = 64


StereoANDComparator.compareAtoms: query = CC1CCCC[C@H]1O, target = CC1CCCC[C@H]1O;


queryAtom = 1, getOrigQueryAtom(queryAtom) = 1, targetAtom = 4, getOrigTargetAtom(targetAtom) = 4;


qAtom C2 has parity 16; tAtom C5 has parity 48;


PARITY_EITHER = 48, PARITY_UNSPEC = 64


StereoANDComparator.compareAtoms: query = CC1CCCC[C@H]1O, target = CC1CCCC[C@H]1O;


queryAtom = 1, getOrigQueryAtom(queryAtom) = 1, targetAtom = 5, getOrigTargetAtom(targetAtom) = 5;


qAtom C2 has parity 16; tAtom C6 has parity 32;


PARITY_EITHER = 48, PARITY_UNSPEC = 64


matchExact: JChem search result is false





Notice that both methods are returning exactly the same number as their parameter. I do not believe this is correct, and the final results are definitely not correct. Any ideas?

ChemAxon a9ded07333

13-11-2008 10:34:17

In most cases queryAtom = getOrigQueryAtom(queryAtom) and targetAtom = getOrigTargetAtom(targetAtom) (there can be differences e.g. when one uses explicit H).





Queries and targets seems to be the same for me. Could you attach these molecules in their original format?





Regards,


Tamás

User f93c2abd9d

14-11-2008 14:10:40

The query is:


Code:
<?xml version="1.0" ?>


<cml>


<MDocument>


  <MChemicalStruct>


    <molecule molID="m1">


      <atomArray>


        <atom id="a1" elementType="C"


              x2="-1.7806249260902405" y2="1.3956588846943596" />


        <atom id="a2" elementType="C"


              x2="-3.114294267138499" y2="0.6256419441353192" />


        <atom id="a3" elementType="C"


              x2="-3.114294267138499" y2="-0.9143919369827618" />


        <atom id="a4" elementType="C"


              x2="-1.7806249260902405" y2="-1.6844088775418022" />


        <atom id="a5" elementType="C"


              x2="-0.44695558504198196" y2="-0.9143919369827618" />


        <atom id="a6" elementType="C"


              x2="-0.44695558504198196" y2="0.6256419441353192" />


        <atom id="a7" elementType="O"


              x2="0.8867235367860538" y2="1.3956419441353192" />


        <atom id="a8" elementType="C"


              x2="0.8867235367860538" y2="-1.6843919369827618" />


      </atomArray>


      <bondArray>


        <bond atomRefs2="a1 a2" order="1" />


        <bond atomRefs2="a1 a6" order="1" />


        <bond atomRefs2="a2 a3" order="1" />


        <bond atomRefs2="a3 a4" order="1" />


        <bond atomRefs2="a4 a5" order="1" />


        <bond atomRefs2="a5 a6" order="1" />


        <bond atomRefs2="a6 a7" order="1">


          <bondStereo>W</bondStereo>


        </bond>


        <bond atomRefs2="a5 a8" order="1">


          <bondStereo convention="MDL" conventionValue="4" />


        </bond>


      </bondArray>


    </molecule>


  </MChemicalStruct>


</MDocument>


</cml>



The target is:


Code:
<?xml version="1.0" ?>


<cml>


<MDocument>


  <MChemicalStruct>


    <molecule molID="m1">


      <atomArray>


        <atom id="a1" elementType="C"


              x2="-0.9624999761581421" y2="1.3956588846943596" />


        <atom id="a2" elementType="C"


              x2="-2.2961693172064006" y2="0.6256419441353192" />


        <atom id="a3" elementType="C"


              x2="-2.2961693172064006" y2="-0.9143919369827618" />


        <atom id="a4" elementType="C"


              x2="-0.9624999761581421" y2="-1.6844088775418022" />


        <atom id="a5" elementType="C"


              x2="0.3711693648901164" y2="-0.9143919369827618" />


        <atom id="a6" elementType="C"


              x2="0.3711693648901164" y2="0.6256419441353192" />


        <atom id="a7" elementType="O"


              x2="1.7048484867181521" y2="1.3956419441353192" />


        <atom id="a8" elementType="C"


              x2="1.7048484867181521" y2="-1.6843919369827618" />


      </atomArray>


      <bondArray>


        <bond atomRefs2="a1 a2" order="1" />


        <bond atomRefs2="a1 a6" order="1" />


        <bond atomRefs2="a2 a3" order="1" />


        <bond atomRefs2="a3 a4" order="1" />


        <bond atomRefs2="a4 a5" order="1" />


        <bond atomRefs2="a5 a6" order="1" />


        <bond atomRefs2="a5 a8" order="1">


          <bondStereo convention="MDL" conventionValue="4" />


        </bond>


        <bond atomRefs2="a6 a7" order="1">


          <bondStereo>W</bondStereo>


        </bond>


      </bondArray>


    </molecule>


  </MChemicalStruct>


</MDocument>


</cml>

ChemAxon a9ded07333

18-11-2008 17:23:37

Thanks for the info, I could reproduce the error, we are investigating the problem and return to you soon.





Regards,


Tamás

User 870ab5b546

23-11-2008 00:50:41

Hi Tamas, any progress on this problem?

ChemAxon a9ded07333

24-11-2008 10:43:14

For better performance we optimize the query molecule and during this optimization in some cases we lose parity. We haven't decided yet how to fix this bug but there is a workaround: use


Code:
searchOpts.setKeepQueryOrder(true);
in your code in order to cancel optimization.

User 870ab5b546

24-11-2008 14:41:14

Thanks, it helps.





What is the chemical difference between parity 0 and PARITY_UNSPEC?





Maybe a better way of asking this question: Can a user even set the parity of an atom to PARITY_UNSPEC, or is it for API use only?





And can an atom that it is not a stereocenter have a parity of PARITY_UNSPEC?

ChemAxon 25dcd765a3

25-11-2008 14:55:03

Hi Bob,





PARITY_UNSPEC is a flag used usually in case of SMARTS strings.





The definition is the following:


@<c><n>? chiral or unspec chirality <c><n> or unspecified





Eg:


C[C@?H](F)O matches if chirality is as specified or is not specified





This flag can be used if and only if some parity definition is given.





see also:


http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html





So regarding your questions:
Quote:
Can a user even set the parity of an atom to PARITY_UNSPEC, or is it for API use only
It is not possible from GUI.
Quote:
And can an atom that it is not a stereocenter have a parity of PARITY_UNSPEC?
Yes but it has no meaning at all.





Andras

ChemAxon a9ded07333

05-12-2008 11:17:11

Here is a short summary of our inner discussions and solution on this problem:





The StereoANDComparator is assumed to compare plain, up, down and wavy bonds during search in a way described here.


We used local parity for checking equality but it sometimes may be misleading in case of up and down bonds (e.g. when the atom order is changed for some reasons). Fortunately, wavy bond recognition always works and our search algorithm takes care of the other cases. So it needs to modify only the StereoANDComparator in the following way:


Code:



public boolean compareAtoms(int queryAtom, int targetAtom) {


    int qParity = query.getLocalParity(getOrigQueryAtom(queryAtom));


    int tParity = target.getLocalParity(getOrigTargetAtom(targetAtom));


    return !(qParity == PARITY_EITHER && tParity != PARITY_EITHER);


}








Regards,


Tamás

User 870ab5b546

05-12-2008 13:28:26

Thanks, it appears to work.





One question: doesn't the modified method above *replace* the compareAtoms() method in the superclass? If so, do we need to call the superclass compareAtoms() method from the modified method to make sure all other considerations (charge, isotope, etc.) are made before we look at the wavy bonds?

ChemAxon a9ded07333

08-12-2008 10:18:00

In MolComparator compareAtoms() and compareBonds() don't do anything, they always return true, so you don't have to call them. All other comparisons are made at another point by the search algorithm.

ChemAxon 42004978e8

08-12-2008 11:52:39

Hi Bob,





One additional comment. The "usual" comparisons (atom type, stereo, radical....) are either way executed (if not disabled with the search options.) The comparisons in the custom molcomparators are additionally executed. They are executed only if all other comparisons return true. Hence they can only harden the conditions for matching.





Bye,


Robert

User 870ab5b546

31-03-2010 13:12:27










cheese wrote:
For better performance we optimize the query molecule and during this optimization in some cases we lose parity. We haven't decided yet how to fix this bug but there is a workaround: use











Code:
searchOpts.setKeepQueryOrder(true);

in your code in order to cancel optimization.

Hi guys,


Have you yet fixed the bug that made this line of code necessary?


-- Bob

User 870ab5b546

14-03-2011 15:00:33










bobgr wrote:










cheese wrote:
For better performance we optimize the query molecule and during this optimization in some cases we lose parity. We haven't decided yet how to fix this bug but there is a workaround: use











Code:
searchOpts.setKeepQueryOrder(true);

in your code in order to cancel optimization.

Hi guys,


Have you yet fixed the bug that made this line of code necessary?


-- Bob



Hi,  I was looking through our code and I noticed we never removed this line because we never got word whether the bug had been fixed.  So, has it?

ChemAxon 42004978e8

25-03-2011 16:04:35

Hi Bob,


 


That line is still necessary. We perform search after rearranging the query. We don't plan to change that. Parity is calculated based on atom indexes, so it's affected by rearranging. 


Bye,


Robi