org.xmlcml.cml.tools.FormulaTool 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.util.HashMap;
import java.util.Map;
import nu.xom.Node;
import nu.xom.Nodes;
import org.apache.log4j.Logger;
import org.xmlcml.cml.base.CMLConstants;
import org.xmlcml.cml.element.CMLFormula;
import org.xmlcml.cml.element.CMLMolecule;
import org.xmlcml.cml.graphics.CMLDrawable;
import org.xmlcml.cml.graphics.SVGElement;
import org.xmlcml.cml.graphics.SVGG;
import org.xmlcml.cml.graphics.SVGText;
import org.xmlcml.euclid.Real2;
/**
* additional tools for formula. not fully developed
*
* @author pmr
*
*/
public class FormulaTool extends AbstractSVGTool {
Logger logger = Logger.getLogger(FormulaTool.class.getName());
public enum Type {
ORGANIC(new String[]{"H", "B", "C", "N", "O", "F", "Si", "P", "S", "Cl", "Br", "I"}),
GROUP1(new String[]{"Li", "Na", "K", "Rb", "Cs", "Fr"});
private String[] elems;
private Type(String[] elems) {
this.elems = elems;
}
public String[] getElems() {
return elems;
}
public boolean contains(String elementType) {
if (elementType == null) {
return false;
}
for (String elem : elems) {
if (elem.equals(elementType)) {
return true;
}
}
return false;
}
public boolean includesAnyOf(String[] elementTypes) {
if (elementTypes == null) {
return false;
}
for (String elementType : elementTypes) {
if (contains(elementType)) {
return true;
}
}
return false;
}
public boolean includesAllOf(String[] elementTypes) {
if (elementTypes == null) {
return false;
}
for (String elementType : elementTypes) {
if (!contains(elementType)) {
return false;
}
}
return true;
}
public boolean includesNoneOf(String[] elementTypes) {
if (elementTypes == null) {
return true;
}
for (String elementType : elementTypes) {
if (contains(elementType)) {
return false;
}
}
return true;
}
}
/** dewisott */
public static String HYDROGEN_COUNT = "hydrogenCount";
private CMLFormula formula;
private AbstractFormulaIdNameDisplay formulaDisplay = FormulaDisplay.DEFAULT;
static Map concise2MoleculeMap;
/**
* constructor
*
* @param formula
* @deprecated use getOrCreateTool
*/
public FormulaTool(CMLFormula formula) {
if (formula == null) {
throw new RuntimeException("null formula");
}
this.formula = formula;
this.formula.setTool(this);
}
/**
* get formula.
*
* @return the formula
*/
public CMLFormula getFormula() {
return formula;
}
/** gets FormulaTool associated with formula.
* if null creates one and sets it in formula
* @param formula
* @return tool
*/
@SuppressWarnings("all")
public static FormulaTool getOrCreateTool(CMLFormula formula) {
FormulaTool formulaTool = (FormulaTool) formula.getTool();
if (formulaTool == null) {
formulaTool = new FormulaTool(formula);
formula.setTool(formulaTool);
}
return formulaTool;
}
private void enableFormulaDisplay() {
if (formulaDisplay == null) {
formulaDisplay = FormulaDisplay.DEFAULT;
}
}
public SVGElement createGraphicsElement(CMLDrawable drawable) {
enableFormulaDisplay();
String s = formula.getConcise();
g = (drawable == null) ? new SVGG() : drawable.createGraphicsElement();
SVGG svgg = new SVGG();
if (s != null) {
String[] ss = s.split(CMLConstants.S_SPACE);
// charge at end?
int evenLength = (ss.length % 2 == 1) ? ss.length - 1 : ss.length;
Real2 offset = new Real2(0.0, 0.0);
for (int i = 0; i < evenLength; i += 2) {
int isub = i+1;
SVGText atomSVG = new SVGText(offset, ss[i]);
atomSVG.setFontSize(formulaDisplay.getFontSizeAtom());
svgg.appendChild(atomSVG);
double widthFactorGuessingLowerCase = Math.min( ss[i].length(), 1.6);
offset = offset.plus(new Real2(
formulaDisplay.getFontSizeAtom() * formulaDisplay.getWidthFactor() *
widthFactorGuessingLowerCase,
0.0));
String countString = ss[isub];
int count = Integer.parseInt(countString);
if (count != 1) {
offset = offset.plus(new Real2(0.0, formulaDisplay.getSubscriptShift()));
SVGText countSVG = new SVGText(offset, countString);
countSVG.setFontSize(formulaDisplay.getFontSizeCount());
svgg.appendChild(countSVG);
offset = offset.plus(new Real2(formulaDisplay.getFontSizeCount() * countString.length() * formulaDisplay.getWidthFactor(), -formulaDisplay.getSubscriptShift()));
}
}
if (ss.length - evenLength == 1) {
String chargeString = ss[evenLength];
int charge = Integer.parseInt(chargeString);
if (charge == 1) {
chargeString = CMLConstants.S_PLUS;
} else if (charge == -1) {
chargeString = CMLConstants.S_MINUS;
}
offset = offset.plus(new Real2(0.0, formulaDisplay.getSuperscriptShift()));
SVGText chargeSVG = new SVGText(offset, chargeString);
chargeSVG.setFontSize(formulaDisplay.getFontSizeCharge());
svgg.appendChild(chargeSVG);
}
g.appendChild(svgg);
}
return g;
}
static CMLMolecule calculateMolecule(SMILESTool smilesTool, String smiles) {
smilesTool.parseSMILES(smiles);
return smilesTool.getMolecule();
}
public static Map ensureConcise2MoleculeMap() {
if (FormulaTool.concise2MoleculeMap == null) {
FormulaTool.concise2MoleculeMap = new HashMap();
SMILESTool smilesTool = new SMILESTool();
FormulaTool.concise2MoleculeMap.put("H 2", FormulaTool.calculateMolecule(smilesTool, "[H][H]"));
FormulaTool.concise2MoleculeMap.put("H 2 O 1", FormulaTool.calculateMolecule(smilesTool, "O"));
FormulaTool.concise2MoleculeMap.put("H 1 Br 1", FormulaTool.calculateMolecule(smilesTool, "Br"));
FormulaTool.concise2MoleculeMap.put("H 1 Cl 1", FormulaTool.calculateMolecule(smilesTool, "Cl"));
FormulaTool.concise2MoleculeMap.put("H 1 F 1", FormulaTool.calculateMolecule(smilesTool, "F"));
FormulaTool.concise2MoleculeMap.put("H 1 I 1", FormulaTool.calculateMolecule(smilesTool, "I"));
FormulaTool.concise2MoleculeMap.put("Br 2", FormulaTool.calculateMolecule(smilesTool, "BrBr"));
FormulaTool.concise2MoleculeMap.put("Cl 2", FormulaTool.calculateMolecule(smilesTool, "ClCl"));
// this creates a bug - java.lang.RuntimeException: duplicate id: a20
// at org.xmlcml.cml.tools.MoleculeTool.checkUnique(MoleculeTool.java:3021)
// FormulaTool.concise2MoleculeMap.put("O 2 S 1", FormulaTool.calculateMolecule(smilesTool, "O=S=O"));
// FormulaTool.concise2MoleculeMap.put("H 4 O 2", FormulaTool.calculateMolecule(smilesTool, "O.O"));
}
return FormulaTool.concise2MoleculeMap;
}
/**
* normalize all formulas which are descendant of node
* @param node
*/
public static void normalizeDescendantFormulas(Node node) {
Nodes formulas = node.query(".//*[local-name()='formula']");
for (int i = 0; i < formulas.size(); i++) {
((CMLFormula)formulas.get(i)).normalize();
}
}
public boolean hasAllElementsBelongingTo(Type type) {
String[] elementTypes = formula.getElementTypes();
return type.includesAllOf(elementTypes);
}
public boolean hasAnyElementsBelongingTo(Type type) {
String[] elementTypes = formula.getElementTypes();
return type.includesAnyOf(elementTypes);
}
public boolean hasNoElementsBelongingTo(Type type) {
String[] elementTypes = formula.getElementTypes();
return type.includesNoneOf(elementTypes);
}
public boolean hasAnyElementsBelongingTo(Type[] types) {
String[] elementTypes = formula.getElementTypes();
for (Type type : types) {
if (type.includesAnyOf(elementTypes)) {
return true;
}
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy