/* * Copyright (c) 1998-2014 ChemAxon Ltd. All Rights Reserved. * * This software is the confidential and proprietary information of * ChemAxon. You shall not disclose such Confidential Information * and shall use it only in accordance with the terms of the agreements * you entered into with ChemAxon. */ import chemaxon.marvin.plugin.CalculatorPlugin; import chemaxon.marvin.plugin.PluginException; import chemaxon.struc.MolAtom; import chemaxon.struc.MolBond; import chemaxon.struc.Molecule; import chemaxon.license.LicenseHandler; import java.util.Properties; import java.util.StringTokenizer; /** * Plugin class to calculate Bemis-Murcko framework of input molecules. * * @author Gabor Imre * @author Zsolt Mohacsi */ public class BemisMurckoPlugin extends CalculatorPlugin { static private String[] TYPE_RANGE = new String[] { "structure", "atomcount", "bondcount" }; private Object[] types = new Object[] { "structure" }; /** The input molecule. */ private Molecule mol = null; /** The output format. */ private String format = null; /** * Structural framework will produce single atom instead of empty structure. */ private boolean keepSingleForAcyclic = true; /** * if structure contains multiple fragments then process only the largest * one after removing explicit H atoms. */ private boolean processOnlyLargestInputFragment = false; /** * if result contains multiple fragments then keep only the largest one. */ private boolean keepOnlyLargestResultFragment = false; /** * Returns the name of the plugin to be used by the License Manager. * @return identifier of the product */ public String getProductName() { return LicenseHandler.FREE_PLUGIN; } /** * Sets the input molecule. * @param mol is the input molecule * @throws PluginException on error */ protected void setInputMolecule(Molecule mol) throws PluginException { this.mol = mol; } /** * Sets the input parameters for the plugin. * Accepted parameters: *
true
if the plugin handles multifragment molecules,
* false
otherwise. This plugin handles multifragment molecules,
* so it returns true
.
* @return true because this plugin handles multifragment molecules
*/
public boolean handlesMultiFragmentMolecules() {
return true;
}
/**
* Sets behavior on acyclic input.
* @param b if set true then a single atom will be assigned to acyclic
* fragments. if false then acyclic fragments will be projected
* to empty structures
*/
public void setKeepSingleAtomForAcyclic(boolean b) {
this.keepSingleForAcyclic = b;
}
/**
* Set handling option for multifragment (disconnected) inputs.
* @param b if set true then the calculation will run only on the largest
* input fragment. Note that this necessarily yields the largest
* scaffold
*/
public void setProcessOnlyLargestInputFragment(boolean b) {
this.processOnlyLargestInputFragment = b;
}
/**
* Set handling option for multifragment (disconnected) results. Note that
* disconnected result can be caused by disconnected input or by further
* modifications of the scaffold generation algorithm
* @param b if set true then only the largest calculated scaffold will be
* returned. Note that the returned scaffold not necessarily
* calculated from the largest fragment.
*/
public void setKeepOnlyLargestResultFragment(boolean b) {
this.keepOnlyLargestResultFragment = b;
}
/**
* Runs the tool.
* @return true
* @throws PluginException on error
*/
public boolean run() throws PluginException {
mol = generateBemisMurckoFramework(mol, processOnlyLargestInputFragment,
keepOnlyLargestResultFragment, keepSingleForAcyclic);
return true;
}
/**
* Generates the Bemis-Murcko framework of the molecule.
* @param mol is the input molecule
* @param processOnlyLargestInputFragment if set true then the calculation
* will run only on the largest input fragment
* @param keepOnlyLargestResultFragment if set true then only the largest
* calculated scaffold will be returned
* @param keepSingleForAcyclic if set true then a single atom will be
* assigned to acyclic fragments
* @return the Bemis-Murcko framework of the molecule
*/
private static Molecule generateBemisMurckoFramework(Molecule mol,
boolean processOnlyLargestInputFragment,
boolean keepOnlyLargestResultFragment,
boolean keepSingleForAcyclic) {
if (processOnlyLargestInputFragment) {
mol = getLargestFragment(mol);
}
for (MolAtom atom : mol.getAtomArray()) {
atom.setAtno(6);
atom.setFlags(0);
}
for (MolBond bond : mol.getBondArray()) {
bond.setFlags(0);
bond.setType(1);
}
// remove side chains
boolean found = true;
while (found) {
found = false;
for (int i = 0; !found && i < mol.getAtomCount(); i++) {
int bci = mol.getAtom(i).getBondCount();
if (bci == 1) {
mol.removeAtom(i);
found = true;
} else if (!keepSingleForAcyclic && bci == 0) {
mol.removeAtom(i);
found = true;
}
}
}
if (keepOnlyLargestResultFragment) {
mol = getLargestFragment(mol);
}
return mol;
}
/**
* Returns the largest fragment of a structure
* {@link chemaxon.struc.Molecule#getAtomCount()} will be used to determine
* fragment size, so explicit and implicit hydrogenes are distinguished.
* Explicit hydrogenes count as any other atoms.
* @param mol the molecule
* @return the largest fragment.
*/
private static Molecule getLargestFragment(Molecule mol) {
Molecule[] frags = mol.cloneMolecule().convertToFrags();
if (frags.length > 1) {
int largestAtomCount = -1;
Molecule largestFragment = null;
for(int i = 0; i < frags.length; i++) {
if (frags[i].getAtomCount() > largestAtomCount) {
largestFragment = frags[i];
largestAtomCount = largestFragment.getAtomCount();
}
}
return largestFragment;
} else {
return mol;
}
}
/**
* Returns the Bemis-Murcko framework.
* @return the Bemis-Murcko framework
*/
public Molecule getBemisMurckoFramework() {
return mol;
}
/**
* Returns the number of atoms in the Bemis-Murcko framework.
* @return the number of atoms in the Bemis-Murcko framework
*/
public int getBemisMurckoFrameworkAtomCount() {
return getBemisMurckoFramework().getAtomCount();
}
/**
* Returns the number of bonds in the Bemis-Murcko framework.
* @return the number of bonds in the Bemis-Murcko framework
*/
public int getBemisMurckoFrameworkBondCount() {
return getBemisMurckoFramework().getBondCount();
}
/**
* Returns the result structure.
* @return the calculated framework
* @throws PluginException on error
*/
public Molecule getResultMolecule() throws PluginException {
Molecule resultMol = getBemisMurckoFramework();
resultMol.setProperty("Atom count", Integer.toString(getBemisMurckoFrameworkAtomCount()));
resultMol.setProperty("Bond count", Integer.toString(getBemisMurckoFrameworkBondCount()));
return resultMol;
}
/**
* Returns the result types.
* @return the result types
*/
public Object[] getResultTypes() {
return types;
}
/**
* Returns the result item for the specified key and index.
* @param type is the result type
* @param index is the result index
* @return the result item for the specified key and index
* @throws PluginException if the result cannot be returned
*/
public Object getResult(Object type, int index) throws PluginException {
String typestr = type.toString();
if (typestr.equalsIgnoreCase("structure")) {
return getBemisMurckoFramework();
} else if (typestr.equalsIgnoreCase("atomcount")) {
return new Integer(getBemisMurckoFrameworkAtomCount());
} else if (typestr.equalsIgnoreCase("bondcount")) {
return new Integer(getBemisMurckoFrameworkBondCount());
} else {
throw new PluginException("Unknown type: " + type);
}
}
/**
* Get a calculation result (returned by {@link getResultMolecule()} after
* a {@link run()} call in the given format {@link setFormat()}
* @param type this parameter is ignored
* @param index this patameter is ignored
* @param result result given by {@link getResultMolecule()}
* @return the string representatin in the given format
* @throws PluginException on error
*/
public String getResultAsString(Object type, int index, Object result)
throws PluginException {
if (result instanceof Molecule) {
Molecule mol = (Molecule) result;
return mol.toFormat(format);
} else if (result instanceof Integer) {
return String.valueOf(((Integer) result).intValue());
} else {
throw new PluginException("Cannot convert result to String: " + result);
}
}
@Override
public void standardize(Molecule mol) {
mol.ungroupSgroups();
mol.implicitizeHydrogens(MolAtom.ALL_H);
}
}