com.actelion.research.chem.reaction.Transformer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
package com.actelion.research.chem.reaction;
import com.actelion.research.chem.Molecule;
import com.actelion.research.chem.SSSearcher;
import com.actelion.research.chem.StereoMolecule;
import com.actelion.research.util.SortedList;
import java.util.ArrayList;
import java.util.Arrays;
/**
* Like a Reactor, a Transformer uses a transformation rule (passed as generic Reaction) to apply defined
* bond changes to one or more real world molecules. It is much faster than a Reactor, but requires the given
* transformation to consist of one reactant and one product only. It also requires all atoms to be mapped.
* During Transformer construction the given Reaction is translated into rule list of bond changes.
* When a molecule is given with setMolecule(), then substructure search is performed to determine all
* possible matches of the transformation reactant. Matches, which would exceed an atom valence when applying the
* transformation, are sorted out. applyTransformation() can be called then up to the number of valid matches to
* construct transformed molecules.
*/
public class Transformer {
private SortedList mRuleList;
private int[] mMinFreeValence; // minimum required free valence on reactant atoms
private int mBondGain;
private StereoMolecule mReactant,mTargetMolecule;
private SSSearcher mSSSearcher;
private ArrayList mMatchList;
private String mName;
public Transformer(StereoMolecule reactant, StereoMolecule product, String name) {
mName = name;
reactant.ensureHelperArrays(Molecule.cHelperRings);
product.ensureHelperArrays(Molecule.cHelperRings);
mBondGain = product.getBonds() - reactant.getBonds();
mReactant = reactant;
mRuleList = new SortedList<>();
for (int bond=0; bond=0; i--) {
TransformerRule rule = mRuleList.get(i);
if (!rule.isFinished())
rule.finishNoProduct();
else if (mRuleList.get(i).isNoChange())
mRuleList.remove(i);
}
// calculate minimum free valence of reactant atoms
mMinFreeValence = new int[reactant.getAtoms()];
for (int i=0; i 0) ? dif : 0;
break;
}
}
}
mSSSearcher = new SSSearcher();
}
/**
* Use this method before calling applyTransformation() to actually perform the bond changes.
* This runs a substructure search of the transformation's reactant on the passed molecule
* to determine all possible matches and, thus, the number of possible transformations that
* can be applied on the molecule without causing a valence problem.
* @param molecule
* @param countMode one of SSSearch.cCountMode...
* @return number of valid transformation to be applied to this molecule
*/
public int setMolecule(StereoMolecule molecule, int countMode) {
mTargetMolecule = molecule;
mSSSearcher.setMol(mReactant, mTargetMolecule);
int matchMode = SSSearcher.cDefaultMatchMode;
if (mSSSearcher.findFragmentInMolecule(countMode, matchMode) == 0) {
mMatchList = null;
return 0;
}
// eliminate matches where reaction would exceed an atom valence
mMatchList = mSSSearcher.getMatchList();
for (int j=mMatchList.size()-1; j>=0; j--) {
int[] matchingAtom = mMatchList.get(j);
for (int k=0; k 0
&& mMinFreeValence[k] > mTargetMolecule.getFreeValence(matchingAtom[k])) {
mMatchList.remove(j);
break;
}
}
}
}
return mMatchList.size();
}
/**
* Creates a canonical representation of the bond state after the transformation
* without actually touching the molecule itself.
* Together with a history of created bonds states, this can be used to avoid
* transformations that lead to products that have been seen before.
* @return
*/
public int[] getTransformedBondList(StereoMolecule mol, int matchNo) {
mol.ensureHelperArrays(Molecule.cHelperNeighbours);
int[] buffer = new int[mol.getBonds()+mBondGain];
int index = 0;
int[] matchAtom = mMatchList.get(matchNo);
boolean[] bondHandled = new boolean[mol.getBonds()];
for (int i=0; i