OK, one additional problem: When I go to my pKa calculator using Marvin JS 15.6.29, I get a runtime Java error:
org.apache.jasper.JasperException: An exception occurred processing JSP page /public/pKa.jsp at line 59
56: plugin.setpKaPrefixType(pKaPlugin.DYNAMICpKaPREFIX);
57: plugin.setModel(pKaPlugin.MODEL_LARGE);
58: plugin.setConsiderTautomerization(true);
59: plugin.setMolecule(molecule);
60: plugin.run();
61: } // if use JChem
62: final double[][] allAtomPKs = (useJChem ? null
Stacktrace:
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:521)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:430)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
root cause
java.lang.RuntimeException: MultiFaceAtom does not have any visible face
chemaxon.struc.graphics.MAtomSetPoint$MultiFaceAtom.getVisible(MAtomSetPoint.java:101)
chemaxon.struc.graphics.MAtomSetPoint.finishCloning(MAtomSetPoint.java:581)
chemaxon.struc.graphics.MElectronContainer.finishCloning(MElectronContainer.java:211)
chemaxon.struc.MDocument.<init>(MDocument.java:349)
chemaxon.struc.MDocument.<init>(MDocument.java:291)
chemaxon.struc.MDocument.cloneDocument(MDocument.java:489)
chemaxon.struc.MDocument.cloneMainMoleculeGraph(MDocument.java:509)
chemaxon.struc.MDocument.cloneMainMolecule(MDocument.java:500)
chemaxon.struc.Molecule.cloneMoleculeWithDocument(Molecule.java:1222)
chemaxon.calculations.Interaction.setMolecule(Interaction.java:71)
chemaxon.calculations.Tautomerization.calcDonorAcceptorSites(Tautomerization.java:1671)
chemaxon.calculations.Tautomerization.initCalc(Tautomerization.java:2233)
chemaxon.calculations.Tautomerization.calculateDACouples(Tautomerization.java:11924)
chemaxon.calculations.Tautomerization.createDACouples(Tautomerization.java:11886)
chemaxon.calculations.CanonicTautomer.calcCanonicalTautomer(CanonicTautomer.java:524)
chemaxon.calculations.Tautomerization.calculateCanonicTau(Tautomerization.java:936)
chemaxon.calculations.Tautomerization.generateCanonicTautomer(Tautomerization.java:869)
chemaxon.calculations.Tautomerization.createCanonicTautomer(Tautomerization.java:814)
chemaxon.marvin.calculations.TautomerizationPlugin.run(TautomerizationPlugin.java:845)
chemaxon.marvin.calculations.pKaPlugin.createModifiedInputMolecule(pKaPlugin.java:703)
chemaxon.marvin.plugin.CalculatorPlugin.setMolecule(CalculatorPlugin.java:966)
chemaxon.marvin.plugin.CalculatorPlugin.setMolecule(CalculatorPlugin.java:906)
chemaxon.marvin.plugin.CalculatorPlugin.setMolecule(CalculatorPlugin.java:884)
chemaxon.marvin.plugin.CalculatorPlugin.setMolecule(CalculatorPlugin.java:867)
org.apache.jsp.public_.pKa_jsp._jspService(pKa_jsp.java:145)
This problem does not occur with Marvin JS 14.11.10.
Now, here is the code that calculates the pKa values. Note that we always use dynamic pKas, and we use the largest range of pKas that we can. I ran the calculation in JChem mode (instead of in the mode of ACE's modified version) just to make sure that none of my code was messing things up. We are using JChem 15.4.27.
final String substrate = request.getParameter("substrate");
final boolean useJChem = true; // "JChem".equals(request.getParameter("method"));
Molecule origMolecule = null;
Molecule molecule = null;
String[] pKas;
String[] pKbs;
final double[] molpKas = {0, 0, 0};
final double[] molpKbs = {0, 0, 0};
final int[] molpKaAtms = {0, 0, 0};
final int[] molpKbAtms = {0, 0, 0};
int numAtoms = 0;
int origNumAtoms = 0;
final NumberFormat numberFormat = NumberFormat.getInstance();
numberFormat.setMaximumFractionDigits(1);
numberFormat.setMinimumFractionDigits(1);
if (substrate != null) {
origMolecule = MolImporter.importMol(substrate);
molecule = MolImporter.importMol(substrate);
origNumAtoms = molecule.getAtomCount();
molecule.aromatize(MoleculeGraph.AROM_BASIC);
ChemUtils.stripMetalsNoClone(molecule);
numAtoms = molecule.getAtomCount();
pKas = new String[numAtoms];
pKbs = new String[numAtoms];
final pKaPlugin plugin = new pKaPlugin();
if (useJChem) {
plugin.setMaxIons(8); // default 8
plugin.setBasicpKaLowerLimit(pKaFunctions.SMALLEST_PKA);
plugin.setAcidicpKaUpperLimit(pKaFunctions.LARGEST_PKA);
plugin.setMicropKaCalc(true);
plugin.setpKaPrefixType(pKaPlugin.DYNAMICpKaPREFIX);
plugin.setModel(pKaPlugin.MODEL_LARGE);
plugin.setConsiderTautomerization(true);
plugin.setMolecule(molecule);
plugin.run();
} // if use JChem
final double[][] allAtomPKs = (useJChem ? null
: pKaFunctions.pKapKbAtoms(molecule));
// if (!useJChem) Utils.alwaysPrint("pKa.jsp: allAtomPKs = ", allAtomPKs);
for (int atmIdx = 0; atmIdx < numAtoms; atmIdx++) {
pKas[atmIdx] = "";
pKbs[atmIdx] = "";
final MolAtom atm = molecule.getAtom(atmIdx);
if (ChemUtils.isMulticenterAtom(atm)
|| ("H".equals(atm.getSymbol()) && atm.getCharge() == 0
&& !"[H][H]".equals(MolString.toString(molecule, Utils.SMILES))))
continue;
final boolean bears_H =
atm.getImplicitHcount() + atm.getExplicitHcount() > 0;
double[] atomPKs = null;
if (useJChem) {
final double[] pKaAcidic = (bears_H ?
plugin.getpKaValues(atmIdx, pKaPlugin.ACIDIC)
: null);
final double[] pKaBasic =
plugin.getpKaValues(atmIdx, pKaPlugin.BASIC);
atomPKs = new double[] {
(pKaAcidic != null ? pKaAcidic[0] : Double.NaN),
(pKaBasic != null ? pKaBasic[0] : Double.NaN)
};
} else atomPKs = allAtomPKs[atmIdx];
if (!Double.isNaN(atomPKs[0])) {
pKas[atmIdx] = numberFormat.format(atomPKs[0]);
} // else Utils.alwaysPrint("no acidic pKa for atom ", atm, atmIdx + 1);
if (!Double.isNaN(atomPKs[1])) {
pKbs[atmIdx] = numberFormat.format(atomPKs[1]);
} // else Utils.alwaysPrint("no basic pKa for atom ", atm, atmIdx + 1);
} // for each atom in the molecule
if (useJChem) {
plugin.getMacropKaValues(pKaPlugin.ACIDIC, molpKas, molpKaAtms);
plugin.getMacropKaValues(pKaPlugin.BASIC, molpKbs, molpKbAtms);
} // if use JChem or ACE method
} else { // substrate is null
pKas = new String[0];
pKbs = new String[0];
} // if substrate is/is not null