All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openscience.cdk.tools.StructureResonanceGenerator Maven / Gradle / Ivy

There is a newer version: 2.9
Show newest version
/* Copyright (C) 2006-2007  Miguel Rojas 
 *
 * Contact: [email protected]
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.openscience.cdk.tools;

import java.util.ArrayList;
import java.util.List;

import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.aromaticity.Aromaticity;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtomContainerSet;
import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IReactionSet;
import org.openscience.cdk.isomorphism.UniversalIsomorphismTester;
import org.openscience.cdk.isomorphism.matchers.QueryAtomContainer;
import org.openscience.cdk.isomorphism.matchers.QueryAtomContainerCreator;
import org.openscience.cdk.reaction.IReactionProcess;
import org.openscience.cdk.reaction.type.PiBondingMovementReaction;
import org.openscience.cdk.reaction.type.RearrangementAnionReaction;
import org.openscience.cdk.reaction.type.RearrangementCationReaction;
import org.openscience.cdk.reaction.type.RearrangementLonePairReaction;
import org.openscience.cdk.reaction.type.RearrangementRadicalReaction;
import org.openscience.cdk.reaction.type.SharingLonePairReaction;
import org.openscience.cdk.reaction.type.parameters.IParameterReact;
import org.openscience.cdk.reaction.type.parameters.SetReactionCenter;

/**
 * 

This class try to generate resonance structure for a determinate molecule.

*

Make sure that the molecule has the corresponding lone pair electrons * for each atom. You can use the method:

 LonePairElectronChecker 
*

It is needed to call the addExplicitHydrogensToSatisfyValency * from the class tools.HydrogenAdder.

*

It is based on rearrangements of electrons and charge

*

The method is based on call by reactions which occur in a resonance.

* *
 * StructureResonanceGenerator srG = new StructureReseonanceGenerator(true,true,true,true,false);
 * MoleculeSet setOf = srG.getResonances(new Molecule());
 * 
* *

We have the possibility to localize the reactive center. Good method if you * want to localize the reaction in a fixed point

*
atoms[0].setFlag(CDKConstants.REACTIVE_CENTER,true);
*

Moreover you must put the parameter as true

*

If the reactive center is not localized then the reaction process will * try to find automatically the possible reactive center.

* * @author Miguel Rojas * @cdk.created 2006-5-05 * @cdk.module reaction * @cdk.githash * * @see org.openscience.cdk.reaction.IReactionProcess */ public class StructureResonanceGenerator { private ILoggingTool logger = LoggingToolFactory .createLoggingTool(StructureResonanceGenerator.class); private List reactionsList = new ArrayList(); /**Generate resonance structure without looking at the symmetry*/ private boolean lookingSymmetry; /** TODO: REACT: some time takes too much time. At the moment fixed to 50 structures*/ private int maxStructures = 50; /** * Construct an instance of StructureResonanceGenerator. Default restrictions * are initiated. * * @see #setDefaultReactions() */ public StructureResonanceGenerator() { this(false); } /** * Construct an instance of StructureResonanceGenerator. Default restrictions * are initiated. * * @param lookingSymmetry Specify if the resonance generation is based looking at the symmetry * @see #setDefaultReactions() */ public StructureResonanceGenerator(boolean lookingSymmetry) { logger.info("Initiate StructureResonanceGenerator"); this.lookingSymmetry = lookingSymmetry; setDefaultReactions(); } /** * Set the reactions that must be used in the generation of the resonance. * * @param newReactionsList The IReactionsProcess's to use * * @see #getReactions() * @see #setReactions(java.util.List) * @see IReactionProcess */ public void setReactions(List newReactionsList) { reactionsList = newReactionsList; } /** * Get the reactions that must be presents in the generation of the resonance. * * @return The reactions to be imposed * * * @see #setDefaultReactions() */ public List getReactions() { return this.reactionsList; } /** * Set the number maximal of resonance structures to be found. The * algorithm breaks the process when is came to this number. * * @param maxStruct The maximal number */ public void setMaximalStructures(int maxStruct) { maxStructures = maxStruct; } /** * Get the number maximal of resonance structures to be found. * * @return The maximal number */ public int getMaximalStructures() { return maxStructures; } /** * Set the default reactions that must be presents to generate the resonance. * * @see #getReactions() */ public void setDefaultReactions() { callDefaultReactions(); } private void callDefaultReactions() { List paramList = new ArrayList(); IParameterReact param = new SetReactionCenter(); param.setParameter(Boolean.FALSE); paramList.add(param); IReactionProcess type = new SharingLonePairReaction(); try { type.setParameterList(paramList); } catch (CDKException e) { e.printStackTrace(); } reactionsList.add(type); type = new PiBondingMovementReaction(); List paramList2 = new ArrayList(); IParameterReact param2 = new SetReactionCenter(); param2.setParameter(Boolean.FALSE); paramList2.add(param2); try { type.setParameterList(paramList2); } catch (CDKException e) { e.printStackTrace(); } reactionsList.add(type); type = new RearrangementAnionReaction(); try { type.setParameterList(paramList); } catch (CDKException e) { e.printStackTrace(); } reactionsList.add(type); type = new RearrangementCationReaction(); try { type.setParameterList(paramList); } catch (CDKException e) { e.printStackTrace(); } reactionsList.add(type); type = new RearrangementLonePairReaction(); try { type.setParameterList(paramList); } catch (CDKException e) { e.printStackTrace(); } reactionsList.add(type); type = new RearrangementRadicalReaction(); try { type.setParameterList(paramList); } catch (CDKException e) { e.printStackTrace(); } reactionsList.add(type); } /** * Get the resonance structures from an {@link IAtomContainer}. * * @param molecule The IAtomContainer to analyze * @return The different resonance structures */ public IAtomContainerSet getStructures(IAtomContainer molecule) { int countStructure = 0; IAtomContainerSet setOfMol = molecule.getBuilder().newInstance(IAtomContainerSet.class); setOfMol.addAtomContainer(molecule); for (int i = 0; i < setOfMol.getAtomContainerCount(); i++) { IAtomContainer mol = setOfMol.getAtomContainer(i); for (IReactionProcess aReactionsList : reactionsList) { IReactionProcess reaction = aReactionsList; IAtomContainerSet setOfReactants = molecule.getBuilder().newInstance(IAtomContainerSet.class); setOfReactants.addAtomContainer(mol); try { IReactionSet setOfReactions = reaction.initiate(setOfReactants, null); if (setOfReactions.getReactionCount() != 0) for (int k = 0; k < setOfReactions.getReactionCount(); k++) for (int j = 0; j < setOfReactions.getReaction(k).getProducts().getAtomContainerCount(); j++) { IAtomContainer product = setOfReactions.getReaction(k).getProducts() .getAtomContainer(j); if (!existAC(setOfMol, product)) { setOfMol.addAtomContainer(product); countStructure++; if (countStructure > maxStructures) return setOfMol; } } } catch (CDKException e) { e.printStackTrace(); } } } return setOfMol; } /** * Get the container which is found resonance from a {@link IAtomContainer}. * It is based on looking if the order of the bond changes. * * @param molecule The IAtomContainer to analyze * @return The different containers */ public IAtomContainerSet getContainers(IAtomContainer molecule) { IAtomContainerSet setOfCont = molecule.getBuilder().newInstance(IAtomContainerSet.class); IAtomContainerSet setOfMol = getStructures(molecule); if (setOfMol.getAtomContainerCount() == 0) return setOfCont; /* extraction of all bonds which has been produced a changes of order */ List bondList = new ArrayList(); for (int i = 1; i < setOfMol.getAtomContainerCount(); i++) { IAtomContainer mol = setOfMol.getAtomContainer(i); for (int j = 0; j < mol.getBondCount(); j++) { IBond bond = molecule.getBond(j); if (!mol.getBond(j).getOrder().equals(bond.getOrder())) { if (!bondList.contains(bond)) bondList.add(bond); } } } if (bondList.size() == 0) return null; int[] flagBelonging = new int[bondList.size()]; for (int i = 0; i < flagBelonging.length; i++) flagBelonging[i] = 0; int[] position = new int[bondList.size()]; int maxGroup = 1; /* Analysis if the bond are linked together */ List newBondList = new ArrayList(); newBondList.add(bondList.get(0)); int pos = 0; for (int i = 0; i < newBondList.size(); i++) { if (i == 0) flagBelonging[i] = maxGroup; else { if (flagBelonging[position[i]] == 0) { maxGroup++; flagBelonging[position[i]] = maxGroup; } } IBond bondA = newBondList.get(i); for (int ato = 0; ato < 2; ato++) { IAtom atomA1 = bondA.getAtom(ato); List bondA1s = molecule.getConnectedBondsList(atomA1); for (int j = 0; j < bondA1s.size(); j++) { IBond bondB = bondA1s.get(j); if (!newBondList.contains(bondB)) for (int k = 0; k < bondList.size(); k++) if (bondList.get(k).equals(bondB)) if (flagBelonging[k] == 0) { flagBelonging[k] = maxGroup; pos++; newBondList.add(bondB); position[pos] = k; } } } //if it is final size and not all are added if (newBondList.size() - 1 == i) for (int k = 0; k < bondList.size(); k++) if (!newBondList.contains(bondList.get(k))) { newBondList.add(bondList.get(k)); position[i + 1] = k; break; } } /* creating containers according groups */ for (int i = 0; i < maxGroup; i++) { IAtomContainer container = molecule.getBuilder().newInstance(IAtomContainer.class); for (int j = 0; j < bondList.size(); j++) { if (flagBelonging[j] != i + 1) continue; IBond bond = bondList.get(j); IAtom atomA1 = bond.getAtom(0); IAtom atomA2 = bond.getAtom(1); if (!container.contains(atomA1)) container.addAtom(atomA1); if (!container.contains(atomA2)) container.addAtom(atomA2); container.addBond(bond); } setOfCont.addAtomContainer(container); } return setOfCont; } /** * Get the container which the atom is found on resonance from a {@link IAtomContainer}. * It is based on looking if the order of the bond changes. Return null * is any is found. * * @param molecule The IAtomContainer to analyze * @param atom The IAtom * @return The container with the atom */ public IAtomContainer getContainer(IAtomContainer molecule, IAtom atom) { IAtomContainerSet setOfCont = getContainers(molecule); if (setOfCont == null) return null; for (IAtomContainer container : setOfCont.atomContainers()) { if (container.contains(atom)) return container; } return null; } /** * Get the container which the bond is found on resonance from a {@link IAtomContainer}. * It is based on looking if the order of the bond changes. Return null * is any is found. * * @param molecule The IAtomContainer to analyze * @param bond The IBond * @return The container with the bond */ public IAtomContainer getContainer(IAtomContainer molecule, IBond bond) { IAtomContainerSet setOfCont = getContainers(molecule); if (setOfCont == null) return null; for (IAtomContainer container : setOfCont.atomContainers()) { if (container.contains(bond)) return container; } return null; } /** * Search if the setOfAtomContainer contains the atomContainer * * * @param set ISetOfAtomContainer object where to search * @param atomContainer IAtomContainer to search * @return True, if the atomContainer is contained */ private boolean existAC(IAtomContainerSet set, IAtomContainer atomContainer) { IAtomContainer acClone = null; try { acClone = (IAtomContainer) atomContainer.clone(); if (!lookingSymmetry) { /* remove all aromatic flags */ for (IAtom atom : acClone.atoms()) atom.setFlag(CDKConstants.ISAROMATIC, false); for (IBond bond : acClone.bonds()) bond.setFlag(CDKConstants.ISAROMATIC, false); } } catch (CloneNotSupportedException e1) { e1.printStackTrace(); } for (int i = 0; i < acClone.getAtomCount(); i++) // if(acClone.getAtom(i).getID() == null) acClone.getAtom(i).setID("" + acClone.getAtomNumber(acClone.getAtom(i))); if (lookingSymmetry) { try { Aromaticity.cdkLegacy().apply(acClone); } catch (CDKException e) { e.printStackTrace(); } } else { if (!lookingSymmetry) { /* remove all aromatic flags */ for (IAtom atom : acClone.atoms()) atom.setFlag(CDKConstants.ISAROMATIC, false); for (IBond bond : acClone.bonds()) bond.setFlag(CDKConstants.ISAROMATIC, false); } } for (int i = 0; i < set.getAtomContainerCount(); i++) { IAtomContainer ss = set.getAtomContainer(i); for (int j = 0; j < ss.getAtomCount(); j++) // if(ss.getAtom(j).getID() == null) ss.getAtom(j).setID("" + ss.getAtomNumber(ss.getAtom(j))); try { if (!lookingSymmetry) { QueryAtomContainer qAC = QueryAtomContainerCreator.createSymbolChargeIDQueryContainer(acClone); if (new UniversalIsomorphismTester().isIsomorph(ss, qAC)) { QueryAtomContainer qAC2 = QueryAtomContainerCreator .createSymbolAndBondOrderQueryContainer(acClone); if (new UniversalIsomorphismTester().isIsomorph(ss, qAC2)) return true; } } else { QueryAtomContainer qAC = QueryAtomContainerCreator.createSymbolAndChargeQueryContainer(acClone); Aromaticity.cdkLegacy().apply(ss); if (new UniversalIsomorphismTester().isIsomorph(ss, qAC)) return true; } } catch (CDKException e1) { System.err.println(e1); logger.error(e1.getMessage()); logger.debug(e1); } } return false; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy