3
* $Date: 2007-04-21 02:22:30 +0200 (Sat, 21 Apr 2007) $
6
* Copyright (C) 2002-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.aromaticity;
30
import org.openscience.cdk.CDKConstants;
31
import org.openscience.cdk.exception.CDKException;
32
import org.openscience.cdk.interfaces.IAtomContainer;
33
import org.openscience.cdk.interfaces.IRing;
34
import org.openscience.cdk.interfaces.IRingSet;
35
import org.openscience.cdk.ringsearch.AllRingsFinder;
36
import org.openscience.cdk.tools.LoggingTool;
39
* The HueckelAromaticityDetector detects the aromaticity based on the Hueckel
40
* 4n+2 pi-electrons Rule. This is done by one of the detectAromaticity
41
* methods. They set the aromaticity flags of appropriate Atoms, Bonds and
42
* Rings. After the detection, you can use getFlag(CDKConstants.ISAROMATIC) on
47
* @cdk.module standard
48
* @cdk.created 2001-09-04
50
* @see org.openscience.cdk.CDKConstants
52
public class HueckelAromaticityDetector
55
static LoggingTool logger = new LoggingTool(HueckelAromaticityDetector.class);
56
AllRingsFinder ringFinder = null;
57
static IRingSet ringSet=null;
58
static long timeout=5000;
61
public static IRingSet getRingSet() {
66
* Retrieves the set of all rings and performs an aromaticity detection based
67
* on Hueckels 4n+2 rule.
69
* @param atomContainer AtomContainer to detect rings in
70
* @return True if the molecule has aromatic features
71
* @exception CDKException Thrown if something goes wrong or in
72
* case of a AllRingsFinder timeout
74
public static boolean detectAromaticity(IAtomContainer atomContainer) throws CDKException
76
return (detectAromaticity(atomContainer, true));
81
* Uses precomputed set of ALL rings and performs an aromaticity detection
82
* based on Hueckels 4n+2 rule.
84
* @param ringSet set of ALL rings
85
* @param atomContainer The AtomContainer to detect rings in
86
* @return True if molecule has aromatic features
87
* @exception org.openscience.cdk.exception.CDKException
89
public static boolean detectAromaticity(IAtomContainer atomContainer, IRingSet ringSet) throws org.openscience.cdk.exception.CDKException
91
return (detectAromaticity(atomContainer, ringSet, true));
96
* Retrieves the set of all rings and performs an aromaticity detection based
97
* on Hueckels 4n + 2 rule.
99
*@param removeAromatictyFlags When true, we leaves ChemObjects that
100
* are already marked as aromatic as they are
101
*@param atomContainer AtomContainer to be searched for
103
*@return True, if molecule has aromatic features
104
*@exception CDKException Thrown in case of errors or an
105
* AllRingsFinder timeout
107
public static boolean detectAromaticity(IAtomContainer atomContainer, boolean removeAromatictyFlags) throws org.openscience.cdk.exception.CDKException
109
return detectAromaticity(atomContainer, removeAromatictyFlags, null);
114
* Retrieves the set of all rings and performs an aromaticity detection based
115
* on Hueckels 4n + 2 rule. An AllRingsFinder with customized timeout may be
116
* assigned to this method.
117
*@param removeAromatictyFlags When true, we leaves ChemObjects that
118
* are already marked as aromatic as they are
119
*@param atomContainer AtomContainer to be searched for
120
*@param arf AllRingsFinder to be employed for the
121
* ringsearch. Use this to customize the
122
* AllRingsFinder timeout feature
124
*@return True, if molecule has aromatic features
125
*@exception CDKException Thrown in case of errors or an
126
* AllRingsFinder timeout
128
public static boolean detectAromaticity(IAtomContainer atomContainer, boolean removeAromatictyFlags, AllRingsFinder arf) throws org.openscience.cdk.exception.CDKException
130
logger.debug("Entered Aromaticity Detection");
131
logger.debug("Starting AllRingsFinder");
132
long before = System.currentTimeMillis();
135
arf = new AllRingsFinder();
136
arf.setTimeout(timeout);
138
ringSet = arf.findAllRings(atomContainer);
139
long after = System.currentTimeMillis();
140
logger.debug("time for finding all rings: " + (after - before) + " milliseconds");
141
logger.debug("Finished AllRingsFinder");
142
if (ringSet.getAtomContainerCount() > 0)
144
return detectAromaticity(atomContainer, ringSet, removeAromatictyFlags);
151
* Uses precomputed set of ALL rings and performs an aromaticity detection
152
* based on Hueckels 4n + 2 rule.
154
*@param ringSet set of ALL rings
155
*@param removeAromaticityFlags Leaves ChemObjects that are already marked as
156
* aromatic as they are
157
*@param atomContainer AtomContainer to be searched for rings
158
*@return True, if molecules contains an
161
public static boolean detectAromaticity(IAtomContainer atomContainer, IRingSet ringSet, boolean removeAromaticityFlags)
163
boolean foundSomething = false;
164
if (removeAromaticityFlags)
166
for (int f = 0; f < atomContainer.getAtomCount(); f++)
168
atomContainer.getAtom(f).setFlag(CDKConstants.ISAROMATIC, false);
170
for (int f = 0; f < atomContainer.getBondCount(); f++)
172
atomContainer.getBond(f).setFlag(CDKConstants.ISAROMATIC, false);
174
for (int f = 0; f < ringSet.getAtomContainerCount(); f++)
176
((IRing) ringSet.getAtomContainer(f)).setFlag(CDKConstants.ISAROMATIC, false);
181
//RingSetManipulator.sort(ringSet);
182
for (int f = 0; f < ringSet.getAtomContainerCount(); f++)
184
ring = (IRing) ringSet.getAtomContainer(f);
185
logger.debug("Testing for aromaticity in ring no ", f);
186
if (AromaticityCalculator.isAromatic(ring, atomContainer))
188
ring.setFlag(CDKConstants.ISAROMATIC, true);
190
for (int g = 0; g < ring.getAtomCount(); g++)
192
ring.getAtom(g).setFlag(CDKConstants.ISAROMATIC, true);
195
for (int g = 0; g < ring.getBondCount(); g++)
197
ring.getBond(g).setFlag(CDKConstants.ISAROMATIC, true);
200
foundSomething = true;
201
logger.debug("This ring is aromatic: ", f);
204
logger.debug("This ring is *not* aromatic: ", f);
207
return foundSomething;
212
* This method sets the aromaticity flags for a RingSet from the Atom flags.
213
* It can be used after the aromaticity detection to set the appropriate flags
214
* for a RingSet from the SSSR search.
216
*@param ringset the RingSet to set the flags for
218
public static void setRingFlags(IRingSet ringset)
220
for (int i = 0; i < ringset.getAtomContainerCount(); i++)
222
boolean aromatic = true;
223
IRing ring = (IRing) ringset.getAtomContainer(i);
224
for (int j = 0; j < ring.getAtomCount(); j++)
226
if (ring.getAtom(j).getFlag(CDKConstants.ISAROMATIC) != true)
234
ring.setFlag(CDKConstants.ISAROMATIC, true);
237
ring.setFlag(CDKConstants.ISAROMATIC, false);
244
* Sets the current AllRingsFinder instance Use this if you want to customize
245
* the timeout for the AllRingsFinder. AllRingsFinder is stopping its quest to
246
* find all rings after a default of 5 seconds.
248
*@param ringFinder The value to assign ringFinder.
249
*@see org.openscience.cdk.ringsearch.AllRingsFinder
251
// public void setRingFinder(AllRingsFinder ringFinder)
253
// this.ringFinder = ringFinder;
257
* Sets the timeout for the AllRingsFinder. The default is 5000ms.
259
* @param timeout The timeout for the AllRingsFinder.
261
public static void setTimeout(long timeout) {
262
HueckelAromaticityDetector.timeout = timeout;
266
* public static boolean isAromatic(AtomContainer ac, Ring ring)
268
* return AromaticityCalculator.isAromatic(ring, ac);
270
* * public static boolean isAromatic(AtomContainer ac, Ring ring)
272
* int piElectronCount = 0;
273
* int freeElectronPairCount = 0;
276
* int aromaCounter = 0;
277
* logger.debug("isAromatic() -> ring.size(): " + ring.getAtomCount());
278
* for (int g = 0; g < ring.getAtomCount(); g++)
280
* atom = ring.getAtomAt(g);
281
* if ("O-N-S-P".indexOf(atom.getSymbol()) > -1)
283
* freeElectronPairCount += 1;
285
* if (atom.getFlag(CDKConstants.ISAROMATIC))
290
* for (int g = 0; g < ring.getElectronContainerCount(); g++) {
291
* ElectronContainer ec = ring.getElectronContainerAt(g);
292
* if (ec instanceof org.openscience.cdk.interfaces.Bond) {
294
* if (bond.getOrder() > 1) {
295
* piElectronCount += 2*(bond.getOrder()-1);
299
* for (int f = 0; f < ((ring.getAtomCount() - 2)/4) + 2; f ++)
301
* logger.debug("isAromatic() -> freeElectronPairCount: " + freeElectronPairCount);
302
* logger.debug("isAromatic() -> piElectronCount: " + piElectronCount);
303
* logger.debug("isAromatic() -> f: " + f);
304
* logger.debug("isAromatic() -> (4 * f) + 2: " + ((4 * f) + 2));
305
* logger.debug("isAromatic() -> ring.size(): " + ring.getAtomCount());
306
* logger.debug("isAromatic() -> aromaCounter: " + aromaCounter);
307
* if (aromaCounter == ring.getAtomCount()) return true;
308
* else if ((piElectronCount == ring.getAtomCount())&&((4 * f) + 2 == piElectronCount)) return true;
309
* else if ((4 * f) + 2 == piElectronCount + (freeElectronPairCount * 2) && ring.getAtomCount() < piElectronCount + (freeElectronPairCount * 2)) return true;