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

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

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;

import com.hfg.chem.format.ChemIOException;
import com.hfg.exception.ProgrammingException;
import com.hfg.util.StringUtil;
import com.hfg.util.collection.OrderedMap;
import com.hfg.util.io.RuntimeIOException;
import com.hfg.util.io.StreamUtil;

//------------------------------------------------------------------------------
/**
 Valence Model for assigning valence values to Atoms.
 

@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 ValenceModel { public OrderedMap> mValenceValueMap = new OrderedMap<>(); private static final int[] ZERO_VALUE = new int[] { 0 }; public static final ValenceModel MDL_Pre2017 = new ValenceModel(); public static final ValenceModel MDL_2017 = new ValenceModel(); static { MDL_Pre2017.load("rsrc/MDL_ValenceModelPre2017.txt"); MDL_2017.load("rsrc/MDL_ValenceModel2017.txt"); } //########################################################################## // CONSTRUCTORS //########################################################################## //--------------------------------------------------------------------------- private ValenceModel() { } //########################################################################## // PUBLIC METHODS //########################################################################## //--------------------------------------------------------------------------- /** Returns the values for the number of valence electrons for the element with the specified charge. Used when calculating implicit hydrogens for a compound. */ public int[] getValences(Element inElement, int inCharge) { int[] values = null; Map elementValences = mValenceValueMap.get(inElement); if (elementValences != null) { values = elementValences.get(inCharge); } return values != null ? values : ZERO_VALUE; } //-------------------------------------------------------------------------- public int calculateImplicitHCount(Atom inAtom) { Integer implicitHCount = null; // Don't calculate implicit hydrogens if an explicit value has been specified if (null == inAtom.getHCount()) { int bondOrder = 0; List bonds = inAtom.getBonds(); if (bonds != null) { for (CovalentBond bond : bonds) { // TODO: Should we bail if bonds to hydrogens are present? bondOrder += bond.getBondOrder(); } } // TODO: Should the hCount hydrogens have already been added with bonds? Integer charge = inAtom.getCharge(); if (charge != null && charge < 0) { bondOrder += Math.abs(charge); } if (inAtom.isAromatic()) { bondOrder++; } int[] defaultValences = getValences(inAtom.getElement(), charge != null ? charge : 0); if (defaultValences != null) { // Find the next highest valence for (int i = 0; i < defaultValences.length; i++) { if (defaultValences[i] >= bondOrder) { implicitHCount = defaultValences[i] - bondOrder; break; } } } inAtom.setImplicitHCount(implicitHCount); } return implicitHCount != null ? implicitHCount : 0; } //########################################################################## // PRIVATE METHODS //########################################################################## //--------------------------------------------------------------------------- private void load(String inRsrc) { InputStream stream = getClass().getResourceAsStream(inRsrc); if (null == stream) { throw new ProgrammingException("The rsrc " + StringUtil.singleQuote(inRsrc) + " couldn't be found!?"); } BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(stream)); String line; int lineNum = 0; while ((line = reader.readLine()) != null) { lineNum++; if (!StringUtil.isSet(line) // Skip blank lines || 1 == lineNum // Skip the header line || line.startsWith("#")) // Skip comment lines { continue; } String[] fields = line.split(";", -1); // -1 as the limit keeps it from discarding trailing empty fields if (fields.length != 11) { throw new ChemIOException(String.format("Unexpected number of fields (%d) on line %d of %s!", fields.length, lineNum, inRsrc)); } Element element = Element.valueOf(fields[1].trim()); if (null == element) { throw new ChemIOException(String.format("Unrecognized element (%s) on line %d of %s!", fields[1], lineNum, inRsrc)); } OrderedMap values = new OrderedMap<>(7); for (int i = 2; i < 11; i++) { if (StringUtil.isSet(fields[i])) { String[] valenceValueStrings = fields[i].trim().split(","); if (valenceValueStrings.length > 1 || ! valenceValueStrings[0].equals("0")) { int charge = i - 5; int[] valenceValues = new int[valenceValueStrings.length]; for (int j = 0; j < valenceValueStrings.length; j++) { valenceValues[j] = Integer.parseInt(valenceValueStrings[j]); } values.put(charge, valenceValues); } } } mValenceValueMap.put(element, values); } } catch (IOException e) { throw new RuntimeIOException("Problem parsing " + inRsrc + "!"); } finally { StreamUtil.close(reader); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy