3
* $Date: 2007-01-04 18:46:10 +0100 (Thu, 04 Jan 2007) $
6
* Copyright (C) 2005-2007 The Chemistry Development Kit (CDK) project
8
* Contact: cdk-devel@lists.sourceforge.net
10
* This program is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU Lesser General Public License
12
* as published by the Free Software Foundation; either version 2.1
13
* of the License, or (at your option) any later version.
14
* All we ask is that proper credit is given for our work, which includes
15
* - but is not limited to - adding the above copyright notice to the beginning
16
* of your source code files, and to any copyright notice that you may distribute
17
* with programs based on this work.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU Lesser General Public License for more details.
24
* You should have received a copy of the GNU Lesser General Public License
25
* along with this program; if not, write to the Free Software
26
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28
package org.openscience.cdk.geometry;
30
import javax.vecmath.Point3d;
32
import org.openscience.cdk.Atom;
33
import org.openscience.cdk.AtomContainer;
34
import org.openscience.cdk.tools.LoggingTool;
35
import org.openscience.cdk.interfaces.IAtom;
38
* Calculator of radial distribution functions. The RDF has bins defined around
39
* a point, i.e. the first bin starts at 0 Å and ends at 0.5*resolution
40
* Å, and the second bins ends at 1.5*resulution Å.
42
* <p>By default, the RDF is unweighted. By implementing and registering a
43
* <code>RDFWeightFunction</code>, the RDF can become weighted. For example,
44
* to weight according to partial charge interaction, this code could be used:
46
* RDFCalculator calculator = new RDFCalculator(0.0, 5.0, 0.1, 0.0,
47
* new RDFWeightFunction() {
48
* public double calculate(Atom atom, Atom atom2) {
49
* return atom.getCharge()*atom2.getCharge();
57
* @author Egon Willighagen
58
* @cdk.created 2005-01-10
60
* @cdk.keyword radial distribution function
63
* @see org.openscience.cdk.geometry.IRDFWeightFunction
65
public class RDFCalculator {
67
private LoggingTool logger;
69
private double startCutoff;
70
private double cutoff;
71
private double resolution;
72
private double peakWidth;
74
private IRDFWeightFunction weightFunction;
77
* Constructs a RDF calculator that calculates a unweighted, digitized
80
* @param startCutoff radial length in Ångstrom at which the RDF starts
81
* @param cutoff radial length in Ångstrom at which the RDF stops
82
* @param resolution width of the bins
83
* @param peakWidth width of the gaussian applied to the peaks in Ångstrom
85
public RDFCalculator(double startCutoff, double cutoff, double resolution,
87
this(startCutoff, cutoff, resolution, peakWidth, null);
91
* Constructs a RDF calculator that calculates a digitized
94
* @param startCutoff radial length in Ångstrom at which the RDF starts
95
* @param cutoff radial length in Ångstrom at which the RDF stops
96
* @param resolution width of the bins
97
* @param peakWidth width of the gaussian applied to the peaks in Ångstrom
98
* @param weightFunction the weight function. If null, then an unweighted RDF is
101
public RDFCalculator(double startCutoff, double cutoff, double resolution,
102
double peakWidth, IRDFWeightFunction weightFunction) {
103
logger = new LoggingTool(this);
105
this.startCutoff = startCutoff;
106
this.cutoff = cutoff;
107
this.resolution = resolution;
108
this.peakWidth = peakWidth;
109
this.weightFunction = weightFunction;
113
* Calculates a RDF for <code>Atom</code> atom in the environment
114
* of the atoms in the <code>AtomContainer</code>.
116
public double[] calculate(AtomContainer container, Atom atom) {
117
int length = (int)((cutoff-startCutoff)/resolution) + 1;
118
logger.debug("Creating RDF of length ", length);
120
// the next we need for Gaussian smoothing
121
int binsToFillOnEachSide = (int)(peakWidth*3.0/resolution);
122
double sigmaSquare = Math.pow(peakWidth, 2.0);
123
double[] factors = new double[binsToFillOnEachSide];
124
for (int binCounter=0; binCounter<binsToFillOnEachSide; binCounter++) {
125
factors[binCounter] = Math.exp(-1.0*(Math.pow(((double)binCounter)*resolution, 2.0))/sigmaSquare);
128
// this we need always
129
double[] rdf = new double[length];
130
double distance = 0.0;
133
Point3d atomPoint = atom.getPoint3d();
134
java.util.Iterator atomsInContainer = container.atoms();
135
while (atomsInContainer.hasNext()) {
136
IAtom atomInContainer = (IAtom)atomsInContainer.next();
137
distance = atomPoint.distance(atomInContainer.getPoint3d());
138
index = (int)((distance-startCutoff)/this.resolution);
140
if (weightFunction != null) {
141
weight = weightFunction.calculate(atom, atomInContainer);
143
rdf[index] += weight; // unweighted
144
if (this.peakWidth > 0.0) {
145
// apply Gaussian smoothing
146
for (int binCounter=1; binCounter<=binsToFillOnEachSide; binCounter++) {
147
if ((index - binCounter) >= 0) {
148
rdf[index - binCounter] += weight*factors[binCounter];
150
if ((index + binCounter) < length) {
151
rdf[index + binCounter] += weight*factors[binCounter];