inconsistency in behavior

User 870ab5b546

14-07-2007 23:34:00

Hi,





I have created the attached reaction definition for E2 elimination reactions. In the Reaction Editor, the first example in the attached file (cyclohexylacetylide + isopropyl bromide -> cyclohexylacetylene + propene + Br-) works just fine. But when I draw the same substrates in a Marvin window, with or without a React arrow, and submit them to the following code:





Code:
   public static Molecule[] doCalc(String reactants, String reactionDef) {


        try {


            Molecule substrate = MolImporter.importMol(reactants);


            return doCalc(substrate, reactionDef);


        } catch (MolFormatException e) {


            System.out.println("SynthSolver: caught MolFormatException on:\n"


                + reactants + "\n" + e.getMessage());


        }   


        return null;


    } // doCalc(AppConfig, String, String)


           


    private static Molecule[] doCalc(Molecule substrate, String reactionDef) {


        try {


            println("SynthSolver.doCalc: reactionDef:\n" + reactionDef);


            println("SynthSolver.doCalc: substrate:\n"


                    + substrate.toFormat("mrv")); 


            Molecule reactionmol =


                    new MolHandler(reactionDef).getMolecule();


            RxnMolecule reaction


                    = RxnMolecule.getReaction(reactionmol);


            if (reaction == null) {


                System.out.println("SynthSolver.doCalc: reaction "


                        + "definition molecule is null.");


                return null;


            }   


            Reactor reactor = new Reactor();


            reactor.setReaction(reaction);


            Molecule[] splitSubstrates =


                    substrate.cloneMolecule().convertToFrags();


            if (splitSubstrates.length <= 1) {


                 reactor.setReactant(substrate);


            } else {


                reactor.setReactants(splitSubstrates);


            }


            Molecule[] products = reactor.react();





            if (products != null) {


                println("SynthSolver.doCalc: "


                        + (products.length == 1


                            ?  "one product" : products.length + " products")


                        + " calculated.");


                for (int i = 0; i < products.length; i++)


                    println("Product " + (i + 1) + ":\n"


                            + products[i].toFormat("mrv"));


            } else println("SynthSolver.doCalc: zero products calculated.");


            return products;


        } catch (MolFormatException e) {


            System.out.println("SynthSolver.doCalc: caught MolFormatException "


                + "on reaction definition:\n"


                + reactionDef + "\n" + e.getMessage());


        } catch (ReactionException e) {


            System.out.println("SynthSolver.doCalc: caught ReactionException:\n"


                + e.getMessage());


        }


        return null;


    } // doCalc(Molecule, String)






the method calculates no products. (When I omit the convertToFrags() step, I get a ReactionException, with the message that Reactor requires two substrates, not one.) Can you give me any insight into what I am doing wrong?





I should mention that another reaction that I designed, for SN2 substitution, works just fine with nearly the same pair of substrates (just removing one C from the alkyl bromide). So it looks to me like the Java code is OK. But I can't figure out why there is a difference in behavior.





We are using JChem 3.2.6 and Marvin 4.1.8.





I'm sorry to bother you with amateurish questions like these, but I have spent hours on this problem and made no headway.

ChemAxon d76e6e95eb

16-07-2007 09:20:59

My collegue who is expert in the API of Reactor will check the problem tomorrow.

ChemAxon e08c317633

17-07-2007 10:08:06

There is no inconsistency. I think the error is caused by this line:





Code:
Molecule[] splitSubstrates =


                    substrate.cloneMolecule().convertToFrags();






When you convert the molecule to fragments using convertToFrags() method there is no guarantee that you get the fragments in the order they are present in the reaction schema. If the order of the reactants in the splitSubstrates array is not the required order, then you will not get the expected products.





If all of your reactants have only one fragment, and the String reactants parameter of your public static Molecule[] doCalc(String reactants, String reactionDef) method is a SMILES string (fragments are separated with dots), then you can use the setReactants(java.lang.String) method of the Reactor to set the reactants. Otherwise you should read the input reactants separately, make a Molecule[] array that contains the reactants in right order, and pass this array to Reactor with setReactants(Molecule[]) method.





I hope this helps.


Zsolt

User 870ab5b546

17-07-2007 11:26:27

Interesting...





I have no control over the order in which the students draw the reactants, let alone the order in which convertToFrags() defragments the response Molecule, so I guess I need to check all permutations of the fragments in turn and see if I get products from any of them.





Perhaps, as a future enhancement, you might consider making the result of react() independent of the order in which the reagents are presented. From a chemist's point of view, the order should not matter. Also, I was not able to find this information in the documentation. Perhaps it's there, and I just missed it, but, if not, you should make it clear, because it is counterintuitive.





Thanks, your response to both questions was very helpful.





-- Bob

User 870ab5b546

17-07-2007 18:23:01

I am happy to report that when I test all permutations of the substrates, the reaction works.





For those who might need the code in the future, here it is:





Code:
    private static Molecule[] doCalc(Molecule substrate, String reactionDef) {


        try {


            // println("SynthSolver.doCalc: reactionDef:\n" + reactionDef); 


            println("SynthSolver.doCalc: substrate:\n"


                    + substrate.toFormat("mrv"));


            Molecule reactionmol =


                    new MolHandler(reactionDef).getMolecule();


            RxnMolecule reaction


                    = RxnMolecule.getReaction(reactionmol);


            if (reaction == null) {


                System.out.println("SynthSolver.doCalc: reaction "


                        + "definition molecule is null.");


                return null;


            }


            Reactor reactor = new Reactor();


            reactor.setReaction(reaction);


            Molecule[] splitSubstrates =


                    substrate.cloneMolecule().convertToFrags();


            Molecule[] products = null;


            if (splitSubstrates.length <= 1) {


                reactor.setReactant(substrate);


                products = reactor.react();


            } else {


                ArrayList<Molecule[]> allPerms = getPermutations(splitSubstrates);


                int numPerms = allPerms.size();


                println("SynthSolver.doCalc: found " + numPerms


                        + " permutations of the "


                        + splitSubstrates.length + " substrates.");


                for (int i = 0; i < numPerms; i++) {


                    println("Trying permutation " + (i + 1) + "...");


                    reactor.setReactants(allPerms.get(i));


                    products = reactor.react();


                    if (products != null) break;


                } // for each permutation of the substrates


            } // if splitSubstrates.length <= 1





            if (products != null) {


                println("SynthSolver.doCalc: "


                        + (products.length == 1


                            ?  "one product" : products.length + " products")


                        + " calculated.");


                for (int i = 0; i < products.length; i++)


                    println("Product " + (i + 1) + ":\n"


                            + products[i].toFormat("mrv"));


            } else println("SynthSolver.doCalc: zero products calculated.");


            return products;


        } catch (MolFormatException e) {


            System.out.println("SynthSolver.doCalc: caught MolFormatException "


                + "on reaction definition:\n"


                + reactionDef + "\n" + e.getMessage());


        } catch (ReactionException e) {


            System.out.println("SynthSolver.doCalc: caught ReactionException:\n"


                + e.getMessage());


        }


        return null;


    } // doCalc(Molecule, String)





    // The following three methods are adapted from


    // http://www.cs.princeton.edu/introcs/23recursion/Permutations.java.html


    // get ArrayList of N! permutations of the substrates


    public static ArrayList<Molecule[]> getPermutations(Molecule[] substrates) {


        int N = substrates.length;


        ArrayList<Molecule[]> allPerms = new ArrayList<Molecule[]>();


        permute(substrates, N, allPerms);


        return allPerms;


    }





    private static void permute(Molecule[] substrates, int n,


            ArrayList<Molecule[]> allPerms) {


        if (n == 1) {


            allPerms.add((Molecule[]) substrates.clone());


            return;


        }


        for (int i = 0; i < n; i++) {


            swap(substrates, i, n - 1);


            permute(substrates, n - 1, allPerms);


            swap(substrates, i, n - 1);


        }


    }





    // swap the Molecules at indices i and j


    private static void swap(Molecule[] substrates, int i, int j) {


        Molecule c;


        c = substrates[i]; substrates[i] = substrates[j]; substrates[j] = c;


    }

User 870ab5b546

18-07-2007 04:51:15

OK, same reaction, new problem. I want to design the following behavior: if the possible reactive atoms (4) have different numbers of connections, choose the one with more connections; otherwise, choose the one with a larger steric index. So 3-bromo-1-butene and any anionic base should give 1,3-butadiene (and not 1,2-butadiene), but 2-bromobutane should give 2-butene (and not 1-butene). I tried writing the selectivity rule this way:





connections(ratom(4)) || stericEffectIndex(ratom(4))





But this rule converts 2-bromobutane to 1-butene, not to 2-butene. If I omit the connections test, then I correctly get 2-butene, but then 3-bromo-1-butene is converted to 1,2-butadiene. It seems that Reactor ignores the second condition, even if there is no exclusive solution to the first condition. What can I do to get the behavior I want?