com.hfg.chem.ValenceModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com_hfg Show documentation
Show all versions of com_hfg Show documentation
com.hfg xml, html, svg, and bioinformatics utility library
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);
}
}
}