/*
* Copyright (c) 1998-2012 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 java.text.DecimalFormat;
import java.util.concurrent.ExecutionException;
import chemaxon.util.concurrent.WorkUnit;
import chemaxon.util.concurrent.WorkUnitFactory;
import chemaxon.util.concurrent.workunitmgmt.WorkUnitManager;
import chemaxon.util.concurrent.marvin.MolInputProducer;
import chemaxon.marvin.plugin.concurrent.PluginWorkUnit;
import chemaxon.marvin.calculations.pKaPlugin;
import chemaxon.marvin.plugin.PluginException;
import chemaxon.struc.Molecule;
import chemaxon.formats.MolImporter;
/**
* Sample application for concurrent {@link chemaxon.marvin.calculations.pKaPlugin}
* calculation processing.
* The pKa result is stored in a dedicated result object, the plugin is
* reused within one work unit for different input molecules.
*
* @author Nora Mate
* @since Marvin 5.0
*/
public class pKaPluginApplication extends ConcurrentPluginApplication {
/**
* Stores pKa results.
*/
static class pKaResult {
double[] acidicpKa = null;
int[] acidicIndexes = null;
double[] basicpKa = null;
int[] basicIndexes = null;
/**
* Constructor.
* @param count the number of strongest pKa values to be computed
*/
pKaResult(int count) {
acidicpKa = new double[count];
acidicIndexes = new int[count];
basicpKa = new double[count];
basicIndexes = new int[count];
}
/**
* Provides string representation.
* @return the string representation
*/
public String toString() {
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(2);
StringBuffer sb = new StringBuffer();
sb.append("\nAcidic: ");
for (int i=0; i < acidicpKa.length; ++i) {
if (acidicIndexes[i] == -1) {
break;
}
// [acidic pKa value] : [1-based atom index] ;
sb.append(df.format(acidicpKa[i])+":"+(acidicIndexes[i]+1)+"; ");
}
sb.append("\nBasic: ");
for (int i=0; i < basicpKa.length; ++i) {
if (basicIndexes[i] == -1) {
break;
}
// [basic pKa value] : [1-based atom index] ;
sb.append(df.format(basicpKa[i])+":"+(basicIndexes[i]+1)+"; ");
}
return new String(sb);
}
}
/**
* {@link chemaxon.util.concurrent.WorkUnit} implementation for pKa calculation.
* This {@link chemaxon.marvin.calculations.pKaPlugin} wrapper is a work unit
* used for parallel execution in the ChemAxon concurrent framework.
* Refer to the {@link chemaxon.util.concurrent} package for details.
*/
static class pKaWorkUnit extends PluginWorkUnit {
private int count = 0;
/**
* Constructor.
* Creates the {@link chemaxon.marvin.calculations.pKaPlugin} object.
* @param count the number of strongest pKa values to be computed,
* 0
for all values
*/
public pKaWorkUnit(int count) {
setPlugin(new pKaPlugin());
this.count = count;
}
/**
* Returns the pKa result.
* @return the pKa results in a result object
*/
public Object getResult() throws Exception {
pKaPlugin p = (pKaPlugin) plugin;
pKaResult result = new pKaResult((count == 0) ? p.getAtomCount() : count);
p.getMacropKaValues(pKaPlugin.ACIDIC, result.acidicpKa, result.acidicIndexes);
p.getMacropKaValues(pKaPlugin.BASIC, result.basicpKa, result.basicIndexes);
return result;
}
}
/**
* Factory that creates {@link pKaWorkUnit} objects.
*/
static class pKaWorkUnitFactory implements WorkUnitFactory {
private int count = 0;
/**
* Constructor.
*/
public pKaWorkUnitFactory() {
}
/**
* Constructor. Sets the number of strongest pKa values to be computed.
* @param count the number of pKa values to be computed, 0
for all
*/
public pKaWorkUnitFactory(int count) {
setCount(count);
}
/**
* Sets the number of strongest pKa values to be computed.
* @param pH the number of pKa values to be computed, 0
for all
*/
public void setCount(int count) {
this.count = count;
}
/**
* Creates a {@link pKaWorkUnit} object.
* @return the created {@link pKaWorkUnit} object
*/
public WorkUnit createWorkUnit() throws Exception {
return new pKaWorkUnit(count);
}
}
/**
* Consumes the result.
* @param result the result object returned by {@link pKaWorkUnit#call()}
*/
protected void consume(Object result) {
if (result instanceof Exception) {
System.err.println("Error during pKa calculation.");
((Exception) result).printStackTrace();
return;
}
System.out.println((pKaResult) result);
}
/**
* The main pKa calculation process.
* @param importer the molecule importer
* @param count the number of strongest pKa values to be computed, 0
for all
*/
public void process(MolImporter importer, int count) throws Exception {
MolInputProducer inputProducer = new MolInputProducer(importer);
try {
process(inputProducer, new pKaWorkUnitFactory(count));
} finally {
inputProducer.close();
WorkUnitManager.getInstance().shutdownNow();
}
}
/**
* Usage: java pKaPluginApplication [count] [molFile]
* The count sets the number of strongest pKa values to be computed.
* Omit the count value to get all values.
*/
static public void main(String[] args) throws Exception {
int count = 0;
String molFile = null;
if (args.length > 0) {
try {
count = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
molFile = args[0];
}
if (args.length > 1) {
try {
count = Integer.parseInt(args[1]);
} catch (NumberFormatException e) {
if (molFile == null) {
molFile = args[1];
} else {
System.err.println("Usage:\n java pKaPluginApplication [count] [molFile]");
return;
}
}
}
} else {
System.err.println("Usage:\n java pKaPluginApplication [count] [molFile]");
return;
}
pKaPluginApplication app = new pKaPluginApplication();
MolImporter importer = (molFile == null) ? new MolImporter(System.in) : new MolImporter(molFile);
app.process(importer, count);
}
}