org.xmlcml.cml.tools.PolymerTool Maven / Gradle / Ivy
/**
* Copyright 2011 Peter Murray-Rust et. al.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xmlcml.cml.tools;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Node;
import nu.xom.Nodes;
import nu.xom.ParentNode;
import nu.xom.xslt.XSLTransform;
import org.apache.log4j.Logger;
import org.xmlcml.cml.attribute.main.CountExpressionAttribute;
import org.xmlcml.cml.base.AbstractTool;
import org.xmlcml.cml.base.CMLBuilder;
import org.xmlcml.cml.base.CMLConstants;
import org.xmlcml.cml.base.CMLElement;
import org.xmlcml.cml.base.CMLElements;
import org.xmlcml.cml.base.CMLUtil;
import org.xmlcml.cml.element.CMLBond;
import org.xmlcml.cml.element.CMLFragment;
import org.xmlcml.cml.element.CMLJoin;
import org.xmlcml.cml.element.CMLMolecule;
import org.xmlcml.cml.element.CMLMoleculeList;
import org.xmlcml.cml.element.CMLTorsion;
import org.xmlcml.cml.element.CMLTransform3;
import org.xmlcml.euclid.Transform3;
import org.xmlcml.euclid.Util;
/**
* tool to support polymer building. not fully developed
*
* @author pmr
*
* @deprecated all functionality is in FragmentTool
*/
public class PolymerTool extends AbstractTool {
private static Logger LOG = Logger.getLogger(PolymerTool.class.getName());
File OUTPUT_DIR = Util.getTestOutputDirectory(PolymerTool.class);
// root might be a molecule
private CMLMolecule molecule = null;
// or a moleculeList
private CMLMoleculeList moleculeList = null;
// in which case it generates child polymerTools
private List polymerToolList = new ArrayList();
// target
private FragmentTool.Convention targetLevel = FragmentTool.Convention.PML_COMPLETE;
// debug
private boolean debug = false;
// catalog
private ResourceManager resourceManager = null;
/** constructor.
*/
public PolymerTool() {
}
/** constructor.
*
* @param molecule
*/
public PolymerTool(CMLMolecule molecule) {
setMolecule(molecule);
}
/** constructor.
*
* @param element molecule or moleculeList
*/
public PolymerTool(CMLElement element) {
setElement(element);
}
/** set molecule.
*
* @param molecule
*/
public void setMolecule(CMLMolecule molecule) {
this.molecule = molecule;
}
/** set targetLevel.
*
* @param targetLevel
*/
public void setTargetLevel(FragmentTool.Convention targetLevel) {
this.targetLevel = targetLevel;
}
/** set debug.
*
* @param debug
*/
public void setDebug(boolean debug) {
this.debug = debug;
}
// /** set fileroot.
// *
// * @param fileroot
// */
// public void setFileroot(String fileroot) {
// this.fileroot = fileroot;
// }
/** set molecule or moleculeList
*
* @param element
*/
public void setElement(CMLElement element) {
if (element instanceof CMLMolecule) {
this.setMolecule((CMLMolecule) element);
} else if (element instanceof CMLMoleculeList) {
this.setMoleculeList((CMLMoleculeList) element);
} else {
throw new RuntimeException(
"must pass PolymerTool a molecule or moleculeList: found "+element.getClass());
}
}
/** constructor.
*
* @param moleculeList
*/
public PolymerTool(CMLMoleculeList moleculeList) {
this.setMoleculeList(moleculeList);
}
/** set moleculeList.
*
* @param moleculeList
*/
public void setMoleculeList(CMLMoleculeList moleculeList) {
this.moleculeList = moleculeList;
}
/** set molecule catalog
* @param resourceManager
*/
public void setResourceManager(ResourceManager resourceManager) {
this.resourceManager = resourceManager;
}
/** process current molecule with its convention attribute.
* the attribute can be re-adjusted by the process so this routine may be called
* several times in sequence.
*
*/
public void processConvention() {
if (moleculeList != null) {
LOG.debug("==========MOLLIST=========");
List nodes = CMLUtil.getQueryNodes(
moleculeList, CMLMolecule.NS+"[@countExpression]", CMLConstants.CML_XPATH);
if (nodes.size() == 1) {
CMLMolecule molecule0 = (CMLMolecule) nodes.get(0);
CountExpressionAttribute.generateAndInsertClones(molecule0);
molecule0.removeAttribute("countExpression");
}
CMLElements molecules = moleculeList.getMoleculeElements();
// moleculeList.debug("MOLPOL");
int i = 0;
for (CMLMolecule molecule0 : molecules) {
PolymerTool polymerTool = new PolymerTool(molecule0);
polymerTool.setResourceManager(this.resourceManager);
polymerToolList.add(polymerTool);
polymerTool.processConventionExhaustively();
LOG.debug("============ "+ i++ +" ================");
}
} else if (molecule != null){
String convention = molecule.getConvention();
if (convention == null) {
throw new RuntimeException("no convention given for: "+molecule.getId());
}
LOG.debug("=========="+convention+"=========");
if (false) {
//
} else if (convention.equals(FragmentTool.Convention.PML_INLINE_ATOM.v)) {
processInlineAtom();
} else if (convention.equals(FragmentTool.Convention.PML_CONCISE.v)) {
processConcise();
} else if (convention.equals(FragmentTool.Convention.PML_BASIC.v)) {
processBasic();
} else if (convention.equals(FragmentTool.Convention.PML_INTERMEDIATE.v)) {
processIntermediate();
} else if (convention.equals(FragmentTool.Convention.PML_EXPLICIT.v)) {
processExplicit();
} else if (convention.equals(FragmentTool.Convention.PML_COMPLETE.v)) {
LOG.debug("**********COMPLETE cannot be futher processed now ********");
// processZMatrix();
}
if (debug) {
debug(convention, molecule);
}
}
}
/** read moleculeList.
*
* @param filename
* @return list
* @throws Exception
*/
public CMLMoleculeList readMoleculeList(String filename) throws Exception {
CMLMoleculeList molList = null;
InputStream in = null;
in = Util.getInputStreamFromResource(filename);
if (in == null) {
molList = (CMLMoleculeList) new CMLBuilder().build(
new StringReader(
S_EMPTY
+ ""
+ " "
+ S_EMPTY)).getRootElement();
} else {
molList = (CMLMoleculeList) new CMLBuilder().build(in)
.getRootElement();
}
return molList;
}
/** debug.
*
* @param s
* @param molTest
*/
public void debug(String s, CMLElement molTest) {
if (molTest instanceof CMLMolecule) {
debug(s, (CMLMolecule) molTest) ;
} else if (molTest instanceof CMLMoleculeList) {
CMLElements molecules = ((CMLMoleculeList) molTest).getMoleculeElements();
for (CMLMolecule molecule : molecules) {
debug(s, molecule) ;
}
}
}
/** connection table as inline atoms.
* only for single molecule at present
*/
@SuppressWarnings("unused")
private void processInlineAtom() {
if (molecule != null){
String formula = molecule.getFormula();
if (formula == null) {
throw new RuntimeException("no formula given");
}
formula = formula.replace(S_NEWLINE, S_EMPTY);
formula = formula.replace(S_SPACE, S_EMPTY);
InlineMolecule inlineMolecule = new InlineMolecule(formula);
CMLMolecule cmlMolecule = inlineMolecule.getCmlMolecule();
molecule.setConvention(FragmentTool.Convention.PML_COMPLETE.v);
molecule.removeAttribute("formula");
} else {
throw new RuntimeException("must have molecule");
}
}
/** process concise formula.
*
* as of 2006-08-01 molecule with a typical concise formula looks like:
* note that within @formula all whitespace including newlines will be ignored.
* the molecule@formula is an inline description of the structure
* consisting of the fragments to be joined and some joining instructions.
* in some cases additional info is held, normally by macro variables (%foo);
* The detailed structure is:
* leftCap-bond-middle1(count)-bond-middle2(count)-bond-...
* middlen(count)-bond-rightCap
* leftCap, middle and rightCap are normally links/pointers to molecules
* in a dictionary/repository
*/
private void processConcise() {
if (moleculeList != null) {
} else if (molecule != null){
String formula = molecule.getFormula();
if (formula == null) {
throw new RuntimeException("no formula given");
}
formula = formula.replace(S_NEWLINE, S_EMPTY);
formula = formula.replace(S_SPACE, S_EMPTY);
boolean old = false;
if (old) {
// FragmentSequence fragmentSequence = new FragmentSequence(formula);
// CMLJoin topJoin = fragmentSequence.getCMLJoin();
// molecule.appendChild(topJoin);
// molecule.setConvention(Convention.PML_BASIC.value);
// molecule.removeAttribute("formula");
} else {
FragmentSequence fragmentSequence = new FragmentSequence(formula);
CMLMoleculeList topMoleculeList = fragmentSequence.getCMLMoleculeList();
molecule.appendChild(topMoleculeList);
molecule.setConvention(FragmentTool.Convention.PML_BASIC.v);
molecule.removeAttribute("formula");
}
} else {
throw new RuntimeException("must have molecule or moleculeList");
}
}
private void processBasic() {
CMLFragment fragment0 = (CMLFragment) molecule.getFirstCMLChild(CMLFragment.TAG);
if (fragment0 == null) {
throw new RuntimeException("expected fragment child");
}
FragmentTool fragmentTool = FragmentTool.getOrCreateTool(fragment0);
fragmentTool.processBasic(resourceManager);
}
// private static void recursiveProcessJoins(
// CMLMoleculeList moleculeList, CMLMolecule parent) {
//// * moleculeList
//// * complexMol?
//// * (join
//// * complexMol)?
//// * (join
//// * complexMol)?
// List childEntries = moleculeList.getChildCMLElements();
// CMLMolecule previousMolecule = parent;
// CMLJoin join = null;
// CMLLabel parentLabel = null;
// if (parent != null) {
// parentLabel = CMLLabel.getLabel(moleculeList, Position.PARENT);
// if (parentLabel == null) {
// throw new RuntimeException("moleculeList must have parent label: "+moleculeList.getId());
// }
// }
// for (int i = 0; i < childEntries.size(); i++) {
// CMLElement child = childEntries.get(i);
// if (parent == null && i == 0) {
// // only occurs at root of molecule
// if (child instanceof CMLMolecule) {
// join.addAtomRefs2ToJoinAndProcessDescendants(previousMolecule, (CMLMolecule) child, null);
// previousMolecule = (CMLMolecule) child;
// } else {
// throw new RuntimeException("Expected complex molecule");
// }
// } else if (child instanceof CMLJoin) {
// // trawl through join+molecule to find next molecule
// join = (CMLJoin) child;
// CMLMolecule molecule = null;
// for (int j = i+1; j < childEntries.size(); j++) {
// CMLElement nextChild = childEntries.get(j);
// i++;
// if (nextChild instanceof CMLMolecule) {
// molecule = (CMLMolecule) nextChild;
// break;
// } else if (nextChild instanceof CMLJoin) {
// throw new RuntimeException("Unexpected join");
// } else {
// LOG.debug("Skipped element: "+nextChild);
// }
// }
// if (molecule == null) {
// LOG.debug("Join has no following molecule sibling");
// }
// join.addAtomRefs2ToJoinAndProcessDescendants(previousMolecule, molecule, parentLabel);
// parentLabel = null;
// previousMolecule = molecule;
// } else if (child instanceof CMLLabel) {
// } else {
// LOG.debug("Skipped element: "+child);
// }
// }
// }
private void processIntermediate() {
// probably obsolete
//should consist of molecule (join, molecule)*
// give join default bond orders
List nodes = CMLUtil.getQueryNodes(molecule, ".//"+CMLJoin.NS+"[not(@order)]", CMLConstants.CML_XPATH);
for (Node node : nodes) {
((CMLJoin) node).setOrder(CMLBond.SINGLE_S);
}
// expand random torsions
List torsions = CMLUtil.getQueryNodes(molecule, ".//"+CMLTorsion.NS+"[@min and @max]", CMLConstants.CML_XPATH);
for (Node node : torsions) {
CMLTorsion torsion = (CMLTorsion) node;
String countExpression = "range("+torsion.getMin()+S_COMMA+torsion.getMax()+S_RBRAK;
int value = new CountExpressionAttribute(countExpression).calculateCountExpression();
torsion.setXMLContent((double)value);
torsion.removeAttribute("min");
torsion.removeAttribute("max");
torsion.debug("MINMAX");
}
// lookup referenced molecules
if (resourceManager == null) {
new Exception().printStackTrace();
throw new RuntimeException("Cannot processIntermediate without moleculeCatalog");
}
CMLElements subMoleculeList = molecule.getMoleculeElements();
for (int i = 0; i < subMoleculeList.size(); i++) {
}
molecule.setConvention(FragmentTool.Convention.PML_EXPLICIT.v);
}
/** convenience method to generate detailed molecules.
* iteratively calls processConvention until nothing more
* can be done.
* @throws RuntimeException
*/
public void processConventionExhaustively() throws RuntimeException {
processConventionExhaustively((FragmentTool.Convention) null);
}
/** convenience method to generate detailed molecules.
* iteratively calls processConvention until either noting more
* can be done or the convention reached is equal to convention
* @param convention terminating convention
* @throws RuntimeException
*/
private void processConventionExhaustively(FragmentTool.Convention convention) throws RuntimeException {
int i = 0;
if( convention == null ){
convention = FragmentTool.Convention.PML_DEFAULT_FINAL;
LOG.debug("Assuming target level: "+convention);
}
if (moleculeList != null) {
processConvention();
tidyMoleculeList();
} else if (molecule != null) {
while (true) {
if (i++ > 7) break;
String moleculeConvention = molecule.getConvention();
if (moleculeConvention == null ||
moleculeConvention.equals(S_EMPTY) ||
moleculeConvention.equals(convention.v) ||
moleculeConvention.equals(FragmentTool.Convention.PML_COMPLETE.v)) {
break;
}
try {
this.processConvention();
moleculeConvention = molecule.getConvention();
} catch (Throwable t) {
t.printStackTrace();
System.err.println("Unexpected throwable "+t+S_SPACE+molecule.getConvention());
throw new RuntimeException("cannot processConvention "+molecule.getConvention()+"; "+t);
}
}
} else {
throw new RuntimeException("null molecule and moleculeList");
}
}
private void tidyMoleculeList() {
CMLElements molecules = moleculeList.getMoleculeElements();
Transform3 fullTransform = new Transform3();
for (CMLMolecule molecule : molecules) {
List transforms = CMLUtil.getQueryNodes(molecule, CMLTransform3.NS, CMLConstants.CML_XPATH);
if (transforms.size() == 1) {
MoleculeTool moleculeTool = MoleculeTool.getOrCreateTool(molecule);
moleculeTool.transformCartesians(fullTransform);
CMLTransform3 transform = (CMLTransform3) transforms.get(0);
fullTransform = fullTransform.concatenate(transform.getEuclidTransform3());
}
}
// replace moleculelist by molecule (for Jmol)
molecule = new CMLMolecule();
CMLUtil.transferChildren(moleculeList, molecule);
ParentNode parent = moleculeList.getParent();
parent.replaceChild(moleculeList, molecule);
// obsolete moleculeList
moleculeList = null;
}
/** primary way of of running.
*
* @param infile
* @param debug
* @param fragments
* @param targetLevel
* @param outfileName
* @exception Exception
*/
public void processConventionExhaustively(
String infile, String fragments, String outfileName,
FragmentTool.Convention targetLevel, boolean debug) throws Exception {
Document doc = new CMLBuilder().build(new File(infile));
Nodes nodes = doc.query(CMLMolecule.NS+X_OR+CMLMoleculeList.NS, CMLConstants.CML_XPATH);
if (nodes.size() == 0) {
throw new RuntimeException("No CML Molecule(List) in file: "+infile);
}
CMLElement molecule = (CMLElement) nodes.get(0);
LOG.debug("Read input: "+infile+" ("+
molecule.getAttributeValue("title")+S_RBRAK);
this.setElement(molecule);
this.setResourceManager(new ResourceManager(new File(fragments).toURI()));
LOG.debug("Processing to level: "+targetLevel.v);
this.processConventionExhaustively(targetLevel);
write(outfileName);
}
/** process.
*/
public void processExplicit() {
throw new RuntimeException("probably obsolete");
}
/** write.
*
* @param outfileName
* @throws Exception
*/
public void write(String outfileName) throws Exception {
if (!outfileName.equals(S_EMPTY)) {
File outfile = new File(outfileName);
if (!outfile.exists()) {
File dir = outfile.getParentFile();
if (!dir.exists()) {
boolean ok = dir.mkdirs();
if (!ok) {
throw new RuntimeException("Cannot make new directory for: "+outfileName);
}
}
outfile.createNewFile();
}
FileOutputStream fos = new FileOutputStream(outfileName);
LOG.debug("Writing (level = "+targetLevel.v+"): "+outfileName);
((molecule != null) ? molecule : moleculeList).serialize(fos, 1);
}
}
/** create from template.
*
* @param stylesheetFilename
* @param parameters
* @param resourceManager
* @return fragment
*/
public static CMLFragment createFromTemplate(
String stylesheetFilename, List parameters, ResourceManager resourceManager) {
LOG.debug("XSL "+stylesheetFilename);
for (XSLParam param : parameters) {
LOG.debug(param.name + "=" + param.value);
}
Document dummyDoc = new Document(new Element("dummy"));
Element element = null;
Builder builder = new Builder();
try {
Document stylesheet = builder.build(stylesheetFilename);
XSLTransform transform = new XSLTransform(stylesheet);
for (XSLParam param : parameters) {
transform.setParameter(param.name, param.value);
}
element = (Element) transform.transform(dummyDoc).get(0);
} catch (Exception e) {
throw new RuntimeException("should never throw "+e);
}
String basicXML = CMLUtil.getCanonicalString(element);
CMLFragment fragment = null;
try {
fragment = (CMLFragment) new CMLBuilder().parseString(basicXML);
} catch (Exception e) {
throw new RuntimeException("should not throw: "+e.getMessage());
}
FragmentTool.getOrCreateTool(fragment).processAll(resourceManager);
return fragment;
}
private static void usage() {
Util.println("java org.xmlcml.cml.tools.PolymerTool1 [args]");
Util.println(" -INFILE filename // XML input file; must include convention ");
Util.println(" -OUTFILE filename // XML output file");
Util.println(" -BASIC, -INTERMEDIATE, -EXPLICIT, -COMPLETE");
Util.println(" -DEBUG");
Util.println(" OR; -TEMPLATE [-PARAM name value]* -CATALOG catalog");
}
/** runs Polymer Tool including building polymers.
* Reads an input file describing the polymer, links to fragment library and outputs
* to file at given level (default CARTESIAN).
*
* The commandline args are:
*
* - INFILE - input (must by in CML with a PML convention
* - FRAGMENTS - the catalog describing the location of fragments
* - OUTFILE - the output
* - BASIC | INTERMEDIATE | EXPLICIT | COMPLETE - target output level
* - DEBUG
*
* Typical usage could be:
*
* java org.xmlcml.cml.tools.PolymerTool1
* -INFILE C:\some\where\examples\experimental\branch2_concise.xml
* -FRAGMENTS C:\some\where\else\examples\molecules\catalog.xml
* -OUTFILE C:\temp\branch2.xml
* -DEBUG
*
*
* @param args
* -FILE filename //input tool
* [level] //output level (BASIC, INTERMEDIATE, EXPLICIT, COMPLETE, CARTESIAN)
*/
public static void main(String[] args) {
if (args.length == 0) {
usage();
// System.exit(0);
} else {
String infile = S_EMPTY;
String outfileName = S_EMPTY;
String fragments = S_EMPTY;
FragmentTool.Convention targetLevel = null;
String template = S_EMPTY;
List paramList = new ArrayList();
int i = 0;
boolean debug = true;
@SuppressWarnings("unused")
List debugList = new ArrayList();
while (i < args.length) {
if (args[i].equalsIgnoreCase("-INFILE")) {
infile = args[++i]; i++;
} else if (args[i].equalsIgnoreCase("-OUTFILE")) {
outfileName = args[++i]; i++;
} else if (args[i].equalsIgnoreCase("-BASIC")) {
targetLevel = FragmentTool.Convention.PML_BASIC; i++;
} else if (args[i].equalsIgnoreCase("-INTERMEDIATE")) {
targetLevel = FragmentTool.Convention.PML_INTERMEDIATE; i++;
} else if (args[i].equalsIgnoreCase("-EXPLICIT")) {
targetLevel = FragmentTool.Convention.PML_EXPLICIT; i++;
} else if (args[i].equalsIgnoreCase("-COMPLETE")) {
targetLevel = FragmentTool.Convention.PML_COMPLETE; i++;
} else if("-FRAGMENTS".equalsIgnoreCase(args[i])) {
fragments = args[++i];
i++;
} else if("-DEBUG".equalsIgnoreCase(args[i])) {
debug = true;
i++;
} else if (args[i].equalsIgnoreCase("-TEMPLATE")) {
template = args[++i]; i++;
// } else if (args[i].equalsIgnoreCase("-CATALOG")) {
// catalog = args[++i]; i++;
} else if (args[i].equalsIgnoreCase("-PARAM")) {
paramList.add(new XSLParam(args[++i], args[++i])); i++;
}else {
System.err.println("Bad arg "+ args[i]);
i++;
}
}
if (!S_EMPTY.equals(template)) {
// CatalogManager catalogManager = CatalogManager.getTopCatalogManager();
// Catalog moleculeCatalog = catalogManager.getCatalog(Catalog.MOLECULE_CATALOG);
if (!S_EMPTY.equals(outfileName)) {
// FileWriter fw = new FileWriter(outfileName);
}
} else {
if (targetLevel == null){
targetLevel = FragmentTool.Convention.PML_DEFAULT_FINAL;
LOG.debug("No level specified. Assuming level: "+targetLevel);
}
if(S_EMPTY.equals(fragments)) {
System.err.println("No fragments found; please give -FRAGMENTS");
}
if (!infile.equals(S_EMPTY)) {
try {
PolymerTool polymerTool = new PolymerTool();
polymerTool.processConventionExhaustively(
infile, fragments, outfileName, targetLevel, debug);
} catch (Exception e) {
System.err.println("ERROR... "+e);
e.printStackTrace();
}
}
}
}
}
}
class XSLParam {
String name;
String value;
XSLParam(String name, String value) {
this.name = name;
this.value = value;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy