/* *****************************************************************************
* Copyright (c) 2008 The Bioclipse Project and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ola Spjuth
*
******************************************************************************/
package net.bioclipse.metaprint2d.ui.business;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.metaprint2d.MetaPrintCalculator;
import net.sf.metaprint2d.MetaPrintResult;
import net.sf.metaprint2d.mol2.Mol2Reader;
import net.sf.metaprint2d.mol2.Molecule;
import net.bioclipse.cdk.business.ICDKManager;
import net.bioclipse.cdk.domain.ICDKMolecule;
import net.bioclipse.core.ResourcePathTransformer;
import net.bioclipse.core.business.BioclipseException;
import net.bioclipse.core.domain.IMolecule;
import net.bioclipse.metaprint2d.Metaprinter;
import net.bioclipse.metaprint2d.ui.Activator;
import net.bioclipse.metaprint2d.ui.Metaprint2DConstants;
import net.bioclipse.metaprint2d.ui.cdk.CDK2MetaprintConverter;
import net.bioclipse.metaprint2d.ui.model.MetaPrint2DCalculation;
import net.bioclipse.metaprint2d.ui.prefs.MetaprintPrefs;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.io.formats.IChemFormat;
/**
*
* @author ola
*
*/
public class MetaPrint2DManager implements IMetaPrint2DManager{
private static final Logger logger = Logger.getLogger(MetaPrint2DManager.class);
ICDKManager cdk;
public Map<IEditorPart, MetaPrint2DCalculation> getCalculationMap() {
return calculationMap;
}
public void setCalculationMap(
Map<IEditorPart, MetaPrint2DCalculation> calculationMap) {
this.calculationMap = calculationMap;
}
Map<IEditorPart, MetaPrint2DCalculation> calculationMap;
public MetaPrint2DManager() {
cdk=net.bioclipse.cdk.business.Activator.getDefault().getJavaCDKManager();
calculationMap=new HashMap<IEditorPart, MetaPrint2DCalculation>();
}
public MetaPrint2DManager(ICDKManager cdkmanager) {
cdk=cdkmanager;
calculationMap=new HashMap<IEditorPart, MetaPrint2DCalculation>();
}
/**
* Namespace
*/
public String getManagerName() {
return "metaprint2d";
}
/**
* Calculate MetaPrint2D for an IMolecule
*/
public List<MetaPrintResult> calculate(IMolecule molecule) throws BioclipseException, InvocationTargetException {
ICDKMolecule cdkmol=cdk.asCDKMolecule( molecule);
ICDKMolecule clonemol = cdk.clone( cdkmol );
//Make sure we perform aromaticity detection before M2D
ICDKMolecule aromaticcdkmol = (ICDKMolecule) cdk.perceiveAromaticity( clonemol );
// ICDKMolecule noexplcdkmol = cdk.removeExplicitHydrogens( aromaticcdkmol );
// cdk.removeExplicitHydrogens( cdkmol );
// ICDKMolecule noimplcdkmol = (ICDKMolecule) cdk.addImplicitHydrogens( noexplcdkmol );
// ICDKMolecule noimplcdkmol = (ICDKMolecule) cdk.addImplicitHydrogens( aromaticcdkmol );
// System.out.println("--" + noimplcdkmol.getAtomContainer());
return doCalculation(aromaticcdkmol);
}
@SuppressWarnings("unchecked")
public List<MetaPrintResult> calculate(IMolecule molecule,
boolean storeResults) throws BioclipseException,
InvocationTargetException {
List<IMolecule> lst=new ArrayList<IMolecule>();
lst.add(molecule);
Map<IMolecule, List<MetaPrintResult>> ret = calculate(lst, storeResults);
if (ret!=null && ret.size()>0)
return (List<MetaPrintResult>) ret.values().toArray()[0];
else return null;
}
/**
* Calculate MetaPrint2D for a File containing a molecule
*/
public Map<IMolecule, List<MetaPrintResult>> calculate(IFile file) throws IOException, BioclipseException, CoreException, InvocationTargetException {
List<ICDKMolecule> cdkmols = cdk.loadMolecules(file);
return calculate(cdkmols, false);
}
public Map<IMolecule, List<MetaPrintResult>> calculate(IFile file,
boolean storeResults) throws IOException, BioclipseException,
CoreException, InvocationTargetException, CDKException {
List<ICDKMolecule> cdkmols=cdk.loadMolecules(file);
//Do calculation
Map<IMolecule, List<MetaPrintResult>> ret = calculate(cdkmols, storeResults);
//Store results
if (storeResults){
//If multiple mols
if (cdkmols.size()==1)
cdk.saveMolecule(cdkmols.get(0), file, true);
if (cdkmols.size()>1){
IChemFormat format=cdk.guessFormatFromExtension( file.getName() );
cdk.saveMolecules(cdkmols, file, format);
}
}
return ret;
}
/**
* Calculate MetaPrint2D for a path to a molecular file
* @throws CDKException
*/
public Map<IMolecule, List<MetaPrintResult>> calculate(String path)
throws IOException, BioclipseException, CoreException, InvocationTargetException, CDKException {
return calculate(ResourcePathTransformer.getInstance().transform(
path), false);
}
public Map<IMolecule, List<MetaPrintResult>> calculate(String path,
boolean storeResults) throws IOException, BioclipseException,
CoreException, InvocationTargetException, CDKException {
return calculate(ResourcePathTransformer.getInstance().transform(
path), true);
}
/**
* Perform the actual MetaPrint2D calculation
* @param cdkmol_in
* @return
* @throws InvocationTargetException
*/
private List<MetaPrintResult> doCalculation(ICDKMolecule cdkmol_in) throws InvocationTargetException{
//Get Metaprint engine. Throws exception if error.
MetaPrintCalculator metaprint = Metaprinter.getMetaprint();
if (metaprint==null){
logger.debug("Error loading metaprint database");
throw new UnsupportedOperationException("Error loading metaprint database");
}
// logger.debug("Calculating MetaPrint2D with DB: " + Metaprinter.getSpecies());
//Depict atom types
CDKHelper.perceiveSybylAtomTypes(cdkmol_in);
//Convert to Metaprint Molecule
Molecule metamol=null;
try {
metamol=CDK2MetaprintConverter
.getMetaprintMoleculeWithSybylTypes(cdkmol_in);
} catch (CDKException e) {
logger.error("Could not convert " +
"molecule with CDK. Reason: " + e.getMessage());
throw new InvocationTargetException( e);
}
//Predict m2d
List<MetaPrintResult> scores = metaprint.predictMetabolicSites(metamol);
return scores;
}
public Molecule doSybylAtomTyping(ICDKMolecule cdkmol_in) throws InvocationTargetException {
//Do sybyl atom typing
//==============================
String mol2path=null;
Molecule metamol=null;
//If ObenBabel selected for Atom Typing
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
if (store.getString(MetaprintPrefs.METAPRINT_ATOMTYPING).equals(MetaprintPrefs.OPENBABEL_ATOMTYPING)){
mol2path = convertToMol2WithOpenBabel(cdkmol_in);
try {
Mol2Reader in = new Mol2Reader(new FileReader(mol2path));
metamol = in.read();
} catch ( IOException e ) {
logger.debug("Could not convert " +
"molecule with OpenBabel. Reason: " + e.getMessage());
throw new UnsupportedOperationException("Could not convert " +
"molecule with OpenBabel. Reason: " + e.getMessage());
}
}
//Else, use CDK to get Sybyl atom types
else{
try {
ICDKMolecule cdkMol=cdk.asCDKMolecule( cdkmol_in);
metamol=CDK2MetaprintConverter.getMetaprintMoleculeWithSybylTypes(cdkMol);
} catch (CDKException e) {
logger.error("Could not convert " +
"molecule with CDK. Reason: " + e.getMessage());
throw new UnsupportedOperationException("Could not convert " +
"molecule with CDK. Reason: " + e.getMessage());
} catch (BioclipseException e) {
logger.error("Could not convert " +
"molecule with CDK. Reason: " + e.getMessage());
throw new UnsupportedOperationException("Could not convert " +
"molecule with CDK. Reason: " + e.getMessage());
}
}
//Atom typing done.
return metamol;
}
/**
* Do sybyl atom typing with CDK.
* @param cdkmol_in
* @return
* @throws InvocationTargetException
*/
public Molecule doCDKSybylAtomTyping(ICDKMolecule cdkmol_in) throws InvocationTargetException {
Molecule metamol=null;
try {
ICDKMolecule cdkMol=cdk.asCDKMolecule( cdkmol_in);
metamol=CDK2MetaprintConverter.getMetaprintMoleculeWithSybylTypes(cdkMol);
} catch (CDKException e) {
logger.error("Could not convert " +
"molecule with CDK. Reason: " + e.getMessage());
throw new UnsupportedOperationException("Could not convert " +
"molecule with CDK. Reason: " + e.getMessage());
} catch (BioclipseException e) {
logger.error("Could not convert " +
"molecule with CDK. Reason: " + e.getMessage());
throw new UnsupportedOperationException("Could not convert " +
"molecule with CDK. Reason: " + e.getMessage());
}
return metamol;
}
/**
* If OpenBabel used for sybyl atom typing, make sure it has a valid path
* or throw exception.
*/
private void verifyOpenBabelPath() {
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
if (store.getString(MetaprintPrefs.METAPRINT_ATOMTYPING).
equals(MetaprintPrefs.OPENBABEL_ATOMTYPING)){
String openbabel_path=store.getString( MetaprintPrefs.OPENBABEL_PATH );
if (openbabel_path==null){
logger.debug( "Openbabel path not set. " +
"Please set in Preferences > Metaprint2d" );
throw new UnsupportedOperationException("Openbabel path not set. " +
"Please set in Preferences > Metaprint2d");
}
File obfile=new File(openbabel_path);
if (obfile.canRead()==false){
logger.debug( "Cannot read openbabel at location: '" +
openbabel_path + "'. Please set correct path in " +
"Preferences > Metaprint2d" );
throw new UnsupportedOperationException("Cannot read openbabel " +
"at location: '" + openbabel_path + "'. " +
"Please set correct path in Preferences > Metaprint2d");
}
}
}
/**
* Convert a ICDKMolecule to a mol2 file
* @param cdkmol the molecule to convert
* @return String with absolute path to mol2 file
* @throws InvocationTargetException
*/
private String convertToMol2WithOpenBabel(ICDKMolecule cdkmol) throws InvocationTargetException {
String filename=null;
try {
File tmpfile=File.createTempFile( "m2d", "bioc" );
filename=tmpfile.getAbsolutePath();
} catch ( IOException e ) {
System.out.println("Cant write metaprint temp file in default temp dir.");
e.printStackTrace();
throw new InvocationTargetException(e);
}
if (filename==null){
System.out.println("Cant write metaprint temp file in default temp dir.");
throw new IllegalArgumentException("Cant write metaprint temp file in default temp dir.");
}
try {
cdk.saveMolecule(cdkmol, filename);
} catch (BioclipseException e) {
logger.debug("Error serializing molecule to MDL: " + e.getMessage());
throw new InvocationTargetException(e);
} catch (CoreException e) {
System.out.println("Error writing file: " + filename + ". Reason: " + e.getMessage());
throw new InvocationTargetException(e);
}
System.out.println("Wrote molfile: " + filename);
//Convert to mol2. Update name by adding .mol2
String mol2path=runBabelConvertMolToMol2(new File(filename));
return mol2path;
}
/**
* Convert the input file to mol2.
* @param savefile file to be converted.
* @return Path to new mol2 file
*/
private String runBabelConvertMolToMol2( File savefile ) {
IPreferenceStore store = PlatformUI.getPreferenceStore();
String openbabel_path=store.getString( MetaprintPrefs.OPENBABEL_PATH );
File obfile=new File(openbabel_path);
if (obfile.canRead()==false){
logger.debug("Cannot read openbabel at location: '" + openbabel_path + "'. Please set correct path in Preferences > Metaprint2d");
throw new IllegalArgumentException( "Cannot read openbabel at location: '" + openbabel_path + "'. Please set correct path in Preferences > Metaprint2d" );
}
String command=openbabel_path+" -imol " + savefile.getAbsolutePath() + " -omol2 " + savefile.getAbsolutePath()+".mol2";
try {
Process ext_proc=Runtime.getRuntime().exec(command, null, null);
//Get output of process and send to BioclipseConsole
BufferedReader d = new BufferedReader(new InputStreamReader(ext_proc.getInputStream()));
String str="";
while ((str = d.readLine()) != null) {
System.out.println("> " + str);
}
} catch ( IOException e ) {
e.printStackTrace();
}
return savefile.getAbsolutePath()+".mol2";
}
public Map<IMolecule, List<MetaPrintResult>> calculate(List<? extends IMolecule> mols) throws BioclipseException, InvocationTargetException {
return calculate(mols,false);
}
/**
* Calculate M2D for a list of molecules and optionally store as properties
* in atomcontainer.
*/
public Map<IMolecule, List<MetaPrintResult>> calculate(
List<? extends IMolecule> mols, boolean storeResults)
throws BioclipseException, InvocationTargetException {
Map<IMolecule, List<MetaPrintResult>> results =
new HashMap<IMolecule, List<MetaPrintResult>>();
for (IMolecule mol : mols){
List<MetaPrintResult> res = calculate(mol);
if (storeResults){
ICDKMolecule cdkmol=cdk.asCDKMolecule( mol);
cdkmol.getAtomContainer().setProperty(
Metaprint2DConstants.METAPRINT_RESULT_PROPERTY,
res.toString());
results.put(cdkmol, res);
}else{
results.put(mol, res);
}
}
return results;
}
public void clear(ICDKMolecule mol){
mol.getAtomContainer().removeProperty(
Metaprint2DConstants.METAPRINT_RESULT_PROPERTY);
}
public void clear(List<? extends ICDKMolecule> mols){
for (ICDKMolecule mol : mols){
mol.getAtomContainer().removeProperty(
Metaprint2DConstants.METAPRINT_RESULT_PROPERTY);
}
}
public String getActiveDatabase() {
return Metaprinter.getSpecies().toString();
}
public void setDataBase( String database ) {
if (database==null) throw new IllegalArgumentException("database cannot be null");
if ( (database.equalsIgnoreCase( "all")) ||
(database.equalsIgnoreCase( "dog")) ||
(database.equalsIgnoreCase( "rat")) ||
(database.equalsIgnoreCase( "human"))
){
//Valid string
Metaprinter.setSpecies( database );
return;
}
throw new IllegalArgumentException(database +
" is not a valid metaprint2d database "
+ "(must be one of All, Dog, Rat, and Human). ");
}
}