All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.chem.ElementalComposition Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
package com.hfg.chem;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import com.hfg.util.CompareUtil;
import com.hfg.util.StringUtil;
import com.hfg.util.collection.CollectionUtil;
import com.hfg.util.collection.OrderedMap;

//------------------------------------------------------------------------------
/**
 Container for elemental composition data.
 
@author J. Alex Taylor, hairyfatguy.com
*/ //------------------------------------------------------------------------------ // com.hfg XML/HTML Coding Library // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com // [email protected] //------------------------------------------------------------------------------ public class ElementalComposition implements Comparable { private Map mMap = new OrderedMap<>(10); private String mChemicalFormula; //########################################################################## // CONSTRUCTORS //########################################################################## //-------------------------------------------------------------------------- public ElementalComposition() { } //-------------------------------------------------------------------------- public ElementalComposition(Map inMap) { add(inMap); } //-------------------------------------------------------------------------- public ElementalComposition(Map inMap, int inNum) { add(inMap, inNum); } //-------------------------------------------------------------------------- public ElementalComposition(ElementalComposition inElementalComposition) { add(inElementalComposition); } //-------------------------------------------------------------------------- public ElementalComposition(ElementalComposition inElementalComposition, int inNum) { add(inElementalComposition, inNum); } //########################################################################## // PUBLIC METHODS //########################################################################## //-------------------------------------------------------------------------- @Override public String toString() { return getChemicalFormula(); } //-------------------------------------------------------------------------- @Override public int hashCode() { int hashcode = 31; for (Element element : mMap.keySet()) { hashcode = hashcode + 31 * element.hashCode() * mMap.get(element).intValue(); } return hashcode; } //-------------------------------------------------------------------------- @Override public boolean equals(Object inObj) { boolean result = false; if (inObj != null) { result = (0 == compareTo(inObj)); } return result; } //-------------------------------------------------------------------------- @Override public int compareTo(Object inObj) { int result = -1; if (inObj instanceof ElementalComposition) { result = CompareUtil.compare(getChemicalFormula(), ((ElementalComposition)inObj).getChemicalFormula()); } return result; } //-------------------------------------------------------------------------- public Collection keySet() { return mMap != null ? mMap.keySet() : null; } //-------------------------------------------------------------------------- public Map toMap() { return mMap != null ? Collections.unmodifiableMap(mMap) : null; } //-------------------------------------------------------------------------- public Float get(Element inElement) { return mMap != null ? mMap.get(inElement) : null; } //-------------------------------------------------------------------------- public Float put(Element inElement, int inCount) { return put(inElement, (float) inCount); } //-------------------------------------------------------------------------- public Float put(Element inElement, float inCount) { clearCalculatedProperties(); if (null == mMap) { mMap = new OrderedMap<>(10); } return mMap.put(inElement, inCount); } //-------------------------------------------------------------------------- public ElementalComposition add(ElementalComposition inValue) { return add(inValue, 1); } //-------------------------------------------------------------------------- public ElementalComposition add(ElementalComposition inValue, int inNum) { if (inValue != null && CollectionUtil.hasValues(inValue.mMap)) { for (Element element : inValue.keySet()) { addAtoms(element, inValue.get(element) * inNum); } } return this; } //-------------------------------------------------------------------------- public ElementalComposition add(Matter inValue) { if (inValue != null) { Map elementalComposition = inValue.getElementalComposition(); if (elementalComposition != null) { add(elementalComposition); } } return this; } //-------------------------------------------------------------------------- public ElementalComposition add(Map inMap) { return add(inMap, 1); } //-------------------------------------------------------------------------- public ElementalComposition add(Map inMap, int inNum) { if (CollectionUtil.hasValues(inMap)) { for (Element element : inMap.keySet()) { addAtoms(element, inMap.get(element) * inNum); } } return this; } //-------------------------------------------------------------------------- public ElementalComposition addAtoms(Element inElement, int inNum) { return addAtoms(inElement, Float.valueOf(inNum)); } //-------------------------------------------------------------------------- public ElementalComposition addAtoms(Element inElement, float inNum) { if (null == mMap) { mMap = new OrderedMap<>(10); } Float count = mMap.get(inElement); float newCount = inNum + (count != null ? count : 0); mMap.put(inElement, newCount); clearCalculatedProperties(); return this; } //-------------------------------------------------------------------------- public ElementalComposition remove(Matter inValue) { return remove(inValue != null ? inValue.getElementalComposition() : null, 1); } //-------------------------------------------------------------------------- public ElementalComposition remove(Map inMap) { return remove(inMap, 1); } //-------------------------------------------------------------------------- public ElementalComposition remove(Map inMap, int inNum) { if (CollectionUtil.hasValues(inMap)) { for (Element element : inMap.keySet()) { addAtoms(element, inMap.get(element) * -inNum); } } return this; } //-------------------------------------------------------------------------- public ElementalComposition remove(ElementalComposition inValue) { return remove(inValue, 1); } //-------------------------------------------------------------------------- public ElementalComposition remove(ElementalComposition inValue, int inNum) { if (inValue != null) { for (Element element : inValue.keySet()) { addAtoms(element, - inValue.get(element) * inNum); } } return this; } //-------------------------------------------------------------------------- public void clear() { mMap = null; clearCalculatedProperties(); } //-------------------------------------------------------------------------- /** Returns a chemical formula String like 'C5H11NO'. If carbon is present, it is listed first followed by the other elements in ascending mass order. Symbols for isotopes are enclosed in square brackets such as '[2H]2O' for deuterated water. @return the chemical formula string */ public String getChemicalFormula() { if (null == mChemicalFormula) { mChemicalFormula = getChemicalFormula(false); } return mChemicalFormula; } //-------------------------------------------------------------------------- /** Returns a chemical formula String like 'C₅H₁₁NO'. If carbon is present, it is listed first followed by the other elements in ascending mass order. Symbols for isotopes are enclosed in square brackets such as '[²H]₂O' for deuterated water. @return the chemical formula string */ public String getChemicalFormulaWithSubscripts() { return getChemicalFormula(true); } //########################################################################## // PRIVATE METHODS //########################################################################## //-------------------------------------------------------------------------- private void clearCalculatedProperties() { mChemicalFormula = null; } //-------------------------------------------------------------------------- private String getChemicalFormula(boolean inUseSubscripts) { StringBuilder compositionString = new StringBuilder(); if (CollectionUtil.hasValues(mMap)) { List elements = new ArrayList<>(mMap.keySet()); Collections.sort(elements); if (elements.remove(Element.CARBON)) { Float count = mMap.get(Element.CARBON); if (count != null && count != 0) { String countString = (count == count.intValue() ? count.intValue() + "" : String.format("%3.1f", count.floatValue()) + ""); if (inUseSubscripts) { countString = StringUtil.toSubscript(countString); } compositionString.append("C" + (count == 1 ? "" : (count < 0 ? "(" + countString + ")" : countString))); } } else if (elements.remove(Element.NITROGEN)) { Float count = mMap.get(Element.NITROGEN); if (count != null && count != 0) { String countString = (count == count.intValue() ? count.intValue() + "" : String.format("%3.1f", count.floatValue()) + ""); if (inUseSubscripts) { countString = StringUtil.toSubscript(countString); } compositionString.append("N" + (count == 1 ? "" : (count < 0 ? "(" + countString + ")" : countString))); } } for (Element element : elements) { Float count = mMap.get(element); // Encode pure isotopes in square brackets like "[²H]" for deuterium if (count != null && count != 0) { String countString = (count == count.intValue() ? count.intValue() + "" : String.format("%3.1f", count.floatValue()) + ""); String symbol; if (null == element) { symbol = "*"; } else { symbol = element.getSymbol(); if (inUseSubscripts) { countString = StringUtil.toSubscript(countString); if (element instanceof Isotope) { symbol = StringUtil.toSuperscript(((Isotope) element).getMassNumber()) + ((Isotope) element).getElement().getSymbol(); } } } compositionString.append((element instanceof Isotope ? "[" + symbol + "]" : symbol) + (count == 1 ? "" : (count < 0 ? "(" + countString + ")" : countString))); } } } return compositionString.length() > 0 ? compositionString.toString() : null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy