org.openscience.cdk.geometry.volume.VABCVolume Maven / Gradle / Ivy
/* Copyright (C) 2011 Egon Willighagen
*
* Contact: [email protected]
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.openscience.cdk.geometry.volume;
import java.util.HashMap;
import java.util.Map;
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.aromaticity.Aromaticity;
import org.openscience.cdk.config.AtomTypeFactory;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.graph.Cycles;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtomType;
import org.openscience.cdk.interfaces.IRingSet;
/**
* Calculates the Van der Waals volume using the method proposed
* in {@cdk.cite Zhao2003}. The method is limited to molecules
* with the following elements: H, C, N, O, F, Cl, Br, I,
* P, S, As, B, Si, Se, and Te.
*
* @cdk.module standard
* @cdk.keyword volume, molecular
* @cdk.githash
*/
public class VABCVolume {
/**
* Values are taken from the spreadsheet where possible. The values in the
* paper are imprecise.
*/
@SuppressWarnings("serial")
private static Map bondiiVolumes = new HashMap() {
{
put("H", 7.2382293504);
put("C", 20.5795259250667);
put("N", 15.5985308577667);
put("O", 14.7102267005611);
put("Cl", 22.4492971208333);
put("Br", 26.5218483279667);
put("F", 13.3057882007064);
put("I", 32.5150310206656);
put("S", 24.4290240576);
put("P", 24.4290240576);
put("As", 26.5218483279667);
put("B", 40.48); // value missing from spreadsheet; taken from paper
put("Se", 28.7309115245333);
put("Si", 38.7923854248);
}
};
private static AtomTypeFactory atomTypeList = null;
/**
* Calculates the volume for the given {@link IAtomContainer}. This methods assumes
* that atom types have been perceived.
*
* @param molecule {@link IAtomContainer} to calculate the volume of.
* @return the volume in cubic Ångström.
*/
public static double calculate(IAtomContainer molecule) throws CDKException {
if (atomTypeList == null) {
atomTypeList = AtomTypeFactory.getInstance("org/openscience/cdk/dict/data/cdk-atom-types.owl",
molecule.getBuilder() // take whatever we got first
);
}
double sum = 0.0;
int totalHCount = 0;
for (IAtom atom : molecule.atoms()) {
Double bondiiVolume = bondiiVolumes.get(atom.getSymbol());
if (bondiiVolume == null) throw new CDKException("Unsupported element.");
sum += bondiiVolume;
// add volumes of implicit hydrogens?
IAtomType type = atomTypeList.getAtomType(atom.getAtomTypeName());
if (type == null) throw new CDKException("Unknown atom type for atom: " + atom.getSymbol());
if (type.getFormalNeighbourCount() == null)
throw new CDKException("Formal neighbor count not given for : " + type.getAtomTypeName());
int hCount = type.getFormalNeighbourCount() - molecule.getConnectedBondsCount(atom);
sum += (hCount * bondiiVolumes.get("H"));
totalHCount += hCount;
}
sum -= 5.92 * (molecule.getBondCount() + totalHCount);
boolean[] originalFlags = molecule.getFlags();
Aromaticity.cdkLegacy().apply(molecule);
IRingSet ringSet = Cycles.sssr(molecule).toRingSet();
if (ringSet.getAtomContainerCount() > 0) {
int aromRingCount = 0;
int nonAromRingCount = 0;
for (IAtomContainer ring : ringSet.atomContainers()) {
if (ringIsAromatic(ring)) {
aromRingCount++;
} else {
nonAromRingCount++;
}
}
molecule.setFlags(originalFlags);
sum -= 14.7 * aromRingCount;
sum -= 3.8 * nonAromRingCount;
}
return sum;
}
private static boolean ringIsAromatic(IAtomContainer ring) {
for (IAtom atom : ring.atoms()) {
if (!atom.getFlag(CDKConstants.ISAROMATIC)) return false;
}
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy