Friedel-Crafts selectivity

User 870ab5b546

07-09-2007 13:58:38

Hi,





In your Friedel-Crafts reaction definition, you have the charge on the aromatic atoms determine the selectivity [-energyE(ratom(1))], but steric factors also play a large role. In the case of toluene, the charge factor predicts that the major product is ortho, but, in fact, the major product is para. I can increase the tolerance slightly to give both products, but how can I rewrite the selectivity rule so that the major product is para?





I also suggest you expand your Friedel-Crafts example to include acyl anhydrides. Add O to the possibilities for atom 3, and add this exclude rule:





(match(ratom(3), "[O:1]", 1) && !match(ratom(3), "O=C[O:1]C=O", 1))





-- Bob

ChemAxon d76e6e95eb

07-09-2007 18:16:52

Your comment is right, no steric effect is considered in the current selectivity rule. You can combine the existing electronic effect with steric using the for example the stericHindrance function.





The stericHyndrance function calculates the geometry of the lowest energy conformer of the given molecule and uses the distances and covalent radii for calculating the steric hindrance of an atom.





The stericEffectIndex performes similar calculation but uses topological distances. Though this latter is very fast (no geometry optimization), it is not perfect for the effect of ortho substituents like isopropyl or isobuthyl.





These two functions are available at the moment, I am very interested in your opinion of their applicability.





(We plan to design a new topological function sometimes in the future which can provide better rapid hindrance prediction.)

User 870ab5b546

07-09-2007 18:26:50

Well, we need to say that if the difference in energyE between two ratom(1) possibilities is less than a certain amount, then the selectivity is determined by sterics.





I don't know how to write that in Chemical Terms Language, but perhaps you do.





BTW, I just started using dreidingEnergy(product(0)) > 100 as an exclude rule for intramolecular reactions, and it works very nicely to rule out cyclization reactions of trans-alkenes and alkynes, meta substitution in intramolecular Friedel-Crafts reactions, etc. I needed to acquire the Geometry plugin to use it.

User 870ab5b546

10-09-2007 14:41:27

All right, I'm trying to write an appropriate selectivity rule, and I am getting bizarre error messages.





The reaction is nitration:





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


<MDocument>


  <MChemicalStruct>


    <reaction>


      <propertyList>


        <property dictRef="NAME" title="NAME">


          <scalar><![CDATA[arene nitration]]></scalar>


        </property>


      </propertyList>


      <reactantList>


        <molecule molID="m1">


          <atomArray


              atomID="a1 a2"


              elementType="C H"


              mrvMap="1 2"


              mrvQueryProps="a1 0"


              x2="-8.620575316403775 -8.620575316403775"


              y2="11.09088749380601 12.630887493806009"


              />


          <bondArray>


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


          </bondArray>


        </molecule>


      </reactantList>


      <productList>


        <molecule molID="m2">


          <atomArray


              atomID="a1 a2 a3 a4"


              elementType="N C O O"


              formalCharge="1 0 0 -1"


              mrvMap="3 1 0 0"


              mrvQueryProps="0 a1 0 0"


              x2="9.966641700900924 10.069514351401217 8.632962579072888 11.30032082272896"


              y2="11.82239134287164 10.285831152778506 12.592391342871641 12.59239134287164"


              />


          <bondArray>


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


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


            <bond atomRefs2="a1 a3" order="2" />


          </bondArray>


        </molecule>


      </productList>


    </reaction>


  </MChemicalStruct>


</MDocument>






I want to find those ratom(1) whose energyE() is within 0.3 of the minimum energyE(ratom(1)), and select the least hindered one. My best shot at a selectivity rule is,





minE = min(energyE(ratom(1)));


-stericHindrance(filter(reactant(0), "energyE(ratom(1)) - minE <= 0.3"))





I get this ReactionException:





Code:
chemaxon.reaction.ReactionException: Error while evaluating expression:


minE = min(energyE(ratom(1))); -stericHindrance(filter(reactant(0), "energyE(ratom(1)) - minE <= 0.3"))


    Error while compiling expression:


energyE(ratom(1)) - minE <= 0.3


    Syntax Error (implicit multiplication not enabled)


        at chemaxon.reaction.ReactionPerformer.reactHit(ReactionPerformer.java:987)


        at chemaxon.reaction.ReactionPerformer.reactOne(ReactionPerformer.java:823)


        at chemaxon.reaction.ReactionPerformer.reactBase(ReactionPerformer.java:767)


        at chemaxon.reaction.ReactionPerformer.react(ReactionPerformer.java:749)


        at chemaxon.reaction.Reactor.reactMain(Reactor.java:1582)


        at chemaxon.reaction.Reactor.react(Reactor.java:1522)






Where the heck does implicit multiplication appear in the expression?





I've tried many other versions of the rule, none of which appear to work any better. For example, if I omit reactant(0) from the filter expression or change it to ratom(1), I get this error message:





Code:
SynthSolver: caught ReactionException:


could not convert to double[]: java.lang.Object@13ebe7b


chemaxon.reaction.ReactionException: could not convert to double[]: java.lang.Object@13ebe7b


        at chemaxon.reaction.ReactionPerformer.reactHit(ReactionPerformer.java:987)


        at chemaxon.reaction.ReactionPerformer.reactOne(ReactionPerformer.java:823)


        at chemaxon.reaction.ReactionPerformer.reactBase(ReactionPerformer.java:767)


        at chemaxon.reaction.ReactionPerformer.react(ReactionPerformer.java:749)


        at chemaxon.reaction.Reactor.reactMain(Reactor.java:1582)


        at chemaxon.reaction.Reactor.react(Reactor.java:1522)






Zsolt wrote that you were trying to make Chemical Terms easier for chemists to use than a programming language. I think you have a ways to go toward that goal. It would help a lot if your error messages were more transparent.

User 870ab5b546

11-09-2007 14:14:42

I get the same error when I formulate the selectivity rule this way:





-stericHindrance(filter(ratom(1), "energyE() - minValue(ratom(1), 'energyE()') <= 0.03"))








Code:
chemaxon.reaction.ReactionException: Error while evaluating expression:


-stericHindrance(filter(ratom(1), "energyE() - minValue(ratom(1), 'energyE()') <= 0.03"))


    Error while compiling expression:


energyE() - minValue(ratom(1), 'energyE()') <= 0.03


    Syntax Error (implicit multiplication not enabled)


        at chemaxon.reaction.ReactionPerformer.reactHit(ReactionPerformer.java:987)


        at chemaxon.reaction.ReactionPerformer.reactOne(ReactionPerformer.java:823)


        at chemaxon.reaction.ReactionPerformer.reactBase(ReactionPerformer.java:767)


        at chemaxon.reaction.ReactionPerformer.react(ReactionPerformer.java:749)


        at chemaxon.reaction.Reactor.reactMain(Reactor.java:1582)


        at chemaxon.reaction.Reactor.react(Reactor.java:1522)






If instead I formulate two separate rules:





Selectivity: -energyE(ratom(1))


Exclude: stericHindrance(ratom(2)) - minValue(ratom(2), "stericHindrance()") >= 0.001





I no longer get a ReactionException, but it's as if I did not have the exclude rule at all.

ChemAxon e08c317633

11-09-2007 17:12:23

Hi Bob,





I have corrected some errors in your Chemical Terms expression. The corrected expression will not throw any exceptions, but still will not work as you expect:





Code:
minE = min(energyE(ratom(1)));


-stericHindrance(reactant(0), min(filter(ratom(1), "energyE() - minE <= 0.03")))






Corrected errors, remarks:





1. The filter Chemical Terms function returns an atom index array, and if stericHindrance() function gets this array as input parameter then it will return an array too (the steric hindrance of all atoms ordered by atom index). The returned array will be interpreted by Reactor as a multiple selectivity rule (see Reaction rules section of the Reactor manual).


I have modified it to


Code:
min(filter(...))



to select only one atom index from the indexes filter(...) returns. Using this expression it will be a "simple" selectivity rule. The multiple selectivity rule will work, but has no useful chemical meaning.





2. In reaction context stericHindrance() function also requires a molecule parameter if the atom parameter is not referenced by atom map (e.g. ratom(1)), but by atom index:


Code:
stericHindrance(reactant(0), <atomIndex>)



The documentation says nothing about this, we will correct it.





3.
Code:
minE = min(energyE(ratom(1)));



This expression does not really make sense: "energyE(ratom(1))" returns only one value, and the minimum of this one value is the value itself.





4. In the filtering expression of the filter function it is advised to use only one function that calculates atomic results. I have replaced the second part of the filtering expression with minE "constant".





I hope this helps,


Zsolt

User 870ab5b546

11-09-2007 17:36:20

Yes, that helps some. At least it explains why I was getting incomprehensible error messages.





But, like you said, it doesn't give me the result I want. The filter expression returns an array of atoms, and I want to find the one with the least steric hindrance. But stericHindrance() doesn't operate on arrays (edited: it does operate on arrays), and the Chemical Terms language doesn't have a for loop that I could use to loop through all the atoms returned by the filter function to see which has the smallest steric hindrance.





I tried breaking the expressions up: steric hindrance in Selectivity and energy in Reactivity:





Code:
        <property dictRef="REACTIVITY" title="REACTIVITY">


          <scalar><![CDATA[minE = min(energyE(ratom(1)));


energyE(ratom(1)) - minE < 0.03]]></scalar>


        </property>


        <property dictRef="SELECTIVITY" title="SELECTIVITY">


          <scalar><![CDATA[-stericHindrance(ratom(1))]]></scalar>


        </property>






I thought that the reactivity rule would keep any atom with an energy more than 0.03 above the minimum from reacting. But it does not appear to work that way; instead, the reactivity rule is pretty much ignored, and I get meta and para products, even with anisole as the substrate, and no matter how small I make the constant. What am I doing wrong now?





When I change the reactivity rule above to an Exclude rule, I get a ReactionException. It doesn't like the minE = min(energyE(ratom(1))); expression.

ChemAxon e08c317633

13-09-2007 14:54:13

bobgr wrote:
Yes, that helps some. At least it explains why I was getting incomprehensible error messages.





But, like you said, it doesn't give me the result I want. The filter expression returns an array of atoms, and I want to find the one with the least steric hindrance. But stericHindrance() doesn't operate on arrays (edited: it does operate on arrays), and the Chemical Terms language doesn't have a for loop that I could use to loop through all the atoms returned by the filter function to see which has the smallest steric hindrance.
Yes, it's true. After the JChem 5.0 release we will start redesigning the Chemical Terms language. We will consider to support for loops.
Quote:
I tried breaking the expressions up: steric hindrance in Selectivity and energy in Reactivity:





Code:
        <property dictRef="REACTIVITY" title="REACTIVITY">


          <scalar><![CDATA[minE = min(energyE(ratom(1)));


energyE(ratom(1)) - minE < 0.03]]></scalar>


        </property>


        <property dictRef="SELECTIVITY" title="SELECTIVITY">


          <scalar><![CDATA[-stericHindrance(ratom(1))]]></scalar>


        </property>






I thought that the reactivity rule would keep any atom with an energy more than 0.03 above the minimum from reacting. But it does not appear to work that way; instead, the reactivity rule is pretty much ignored, and I get meta and para products, even with anisole as the substrate, and no matter how small I make the constant. What am I doing wrong now?
In fact


Code:
energyE(ratom(1)) - minE



in your expression will always be equal to zero. I think you translate


Code:
minE = min(energyE(ratom(1)))



expression like this: "calculate the energyE of each atom, that can be ratom(1) in reaction", so for e.g. toluene you expect this expression to return the minimum of the 3 possible values.





No, that's not the case. Reactor first generates the reactions using the input reactants, and then checks if the rules apply.


Let's see an example: your arene nitration reaction, input reactant is toluene.





(1) ignore reactivity and selectivity rule


Code:
react -n rs -r nitration.mrv "CC1=CC=CC=C1"


CC1=C(C=CC=C1)[N+]([O-])=O


CC1=CC(=CC=C1)[N+]([O-])=O


CC1=CC=C(C=C1)[N+]([O-])=O





With ignored reactivity and selectivity rules 3 products are generated (ortho, meta, para), as it is expected.





(2) ignore only selectivity rule


Code:
react -n s -r nitration.mrv "CC1=CC=CC=C1"


CC1=C(C=CC=C1)[N+]([O-])=O


CC1=CC(=CC=C1)[N+]([O-])=O


CC1=CC=C(C=C1)[N+]([O-])=O





With ignored selectivity rule the same products are generated as in (1), because e.g. in ortho case "ratom(1)" in reactivity rule refers only to the "ortho" carbon atom, so if we substitute the "energyE(ratom(1))" subexpression with its calculated value - suppose it is 2.31 for the ortho carbon - then the "energyE(ratom(1)) - min(energyE(ratom(1)))" expression will be "2.31 - min(2.31)" and this will always be zero, independently of the actual localization energy value, so the reactivity rule "0 < 0.03" will always return true, it will not filter out any reactants.





(3) ignore only reactivity rule


Code:
react -n r -r nitration.mrv "CC1=CC=CC=C1"


CC1=CC=C(C=C1)[N+]([O-])=O





In this case only selectivity rule applies. Selectivity rule will differentiate between the products of your reaction. Steric hindrance values for ortho, meta and para carbons of toluene: 0.98, 0.94, 0.93, so the product sets will be ordered like this:


Code:
CC1=CC=C(C=C1)[N+]([O-])=O    -0.93


CC1=CC(=CC=C1)[N+]([O-])=O    -0.94


CC1=C(C=CC=C1)[N+]([O-])=O    -0.98








Because |-0.94 - (-0.93)| > 0.0001 (0.0001 is the default tolerance) only the first product set will be returned.





I hope this explanation helps.
Quote:
When I change the reactivity rule above to an Exclude rule, I get a ReactionException. It doesn't like the minE = min(energyE(ratom(1))); expression.
Assignments can not be used in exclude rule. They also can not be used in reactivity rule if there is an exclude rule.





Regards,


Zsolt

User 870ab5b546

14-09-2007 00:04:19

Thank you for the explanation of why my expressions weren't working. Although my head hurts now.





I am glad to hear that you are redesigning the Chemical Terms Language. If I cannot express a rule as simple as, "Among the C atoms with charges within 0.03 units of the minimum, choose the least hindered," there is a serious problem.





I would be happy to contribute to the development of a more versatile Chemical Terms Language. I strongly suggest you use an existing programming language such as Java as a model for developing a new Chemical Terms Language. Whether you make it object-oriented is less relevant than making rules read in a logical, self-evident fashion. I would like to see a rule that would read something like this:





Code:
// ratom(1) is the set of atoms satisfying the reaction definition;


// the following code restricts the set


int minE = ratom(1).min(energyE());


for each ratom(1) atom


   if (energyE(atom) - minE > 0.03)


      ratom(1).remove(atom);


ratom(1) = ratom(1).minAtom(stericHindrance());


// or, if multiple products are desired:


// ratom(1).sort(stericHindrance(), ASCENDING));


reaction.set(ratom(1));








I would like to see the filter expressions disappear entirely. They are very confusing to write and hard to read. I would also like to see the plugin calculations look much more like they do in the API.





I don't think chemists will have a harder time learning how to use a Chemical Terms Language with simple terms like if, for, etc. than they will learning the existing language.

ChemAxon d76e6e95eb

14-09-2007 14:24:44

You are right, the current syntax of the filter expressions is very hard to read, it is a known problem and we will try to make it much simpler. Furthermore, as Zsolt said, we will redesign the Chemical Terms language to have a simpler syntax in general.








Since the reengineering of Chemical Terms has not been started yet (though decided more than a year ago), the planned format is not yet fixed. However we do not plan to make it similar to Java! We would like to design a syntax, that can be easily learned by a chemist who has no programming experience.





Some features of Java we would like to avoid: case sensitivity, function parentheses even if there are no parameters, fixed parameter order, zero based indexing, the form of logic operators (||, &&).

User 870ab5b546

14-09-2007 14:53:22

You may be chasing a mirage when you say you would like to design a syntax that a chemist who has no programming experience can use. By definition, you are designing a programming language.





Having said that, you can certainly make the language more similar to Basic or AppleScript than to Java. How about this?





Code:
// ratom(1) is the set of atoms satisfying the reaction definition;


// the following code restricts the set


minE = minimum of energyE of each ratom(1);


for each atom in ratom(1)


   if (energyE of atom) - minE > 0.03


      then remove atom from ratom(1);


ratom(1) = atom with minimum of stericHindrance of each ratom(1);


// or, if multiple products are desired:


// sort ratom(1) by stericHindrance of each ratom(1), ascending;


ChemAxon d76e6e95eb

14-09-2007 15:17:08

No, we do not plan to make Chemical Terms a programming language. I do not exclude this possibility, but not at the moment. Conditonal expressions might appear (if), but we do not plan to add looping.

User 870ab5b546

14-09-2007 19:54:12

Zsolt wrote:
In fact


Code:
energyE(ratom(1)) - minE



in your expression will always be equal to zero. I think you translate


Code:
minE = min(energyE(ratom(1)))



expression like this: "calculate the energyE of each atom, that can be ratom(1) in reaction", so for e.g. toluene you expect this expression to return the minimum of the 3 possible values.





No, that's not the case. Reactor first generates the reactions using the input reactants, and then checks if the rules apply.


Can I replace ratom(1) in the expression above with a term that says, "any aromatic C atom"? For example,





Code:
minE = min(energyE(filter(reactant(0), "arom()")))






Or will energyE also not accept an array of atoms, like stericHindrance won't?





Why does pKa accept an array produced by filter(), but stericHindrance does not? Both are plugin calculations, after all.

ChemAxon e08c317633

17-09-2007 10:16:03

bobgr wrote:
Can I replace ratom(1) in the expression above with a term that says, "any aromatic C atom"? For example,





Code:
minE = min(energyE(filter(reactant(0), "arom()")))



Yes, you can. This is the expression you can use:


Code:
minE = min(energyE(reactant(0), filter(reactant(0), "aromaticAtom()")))
Quote:
Or will energyE also not accept an array of atoms, like stericHindrance won't?





Why does pKa accept an array produced by filter(), but stericHindrance does not? Both are plugin calculations, after all.
pKa(), energyE() and stericHindrance() functions all accept an array of atoms. My previous answer was not correct, I have edited it. Sorry for the mistake.





Regards,


Zsolt

User 870ab5b546

17-09-2007 12:18:49

Hooray! With your help, I have succeeded in writing rules for electrophilic aromatic substitution reactions that take both sterics and electronics into account.





Reactivity rule:





Code:
minE = min(energyE(reactant(0), filter(reactant(0), "aromaticAtom()")));


energyE(ratom(1)) - minE <= 0.05






Aromatic atoms must have localization energy close to the minimum of all aromatic atoms to provide the main product, but they don't have to be the absolute minimum.





Selectivity rule:





Code:
-stericHindrance(ratom(1))






Among atoms determined by the reactivity rule, aromatic atom with the least steric hindrance provides the main product.





Tolerance:





Code:
0.04






Excludes ortho product for most substituents except OH and O-.





Thanks again for your help!





-- Bob