~ubuntu-branches/ubuntu/maverick/cdk/maverick

« back to all changes in this revision

Viewing changes to src/org/openscience/cdk/aromaticity/HueckelAromaticityDetector.java

  • Committer: Bazaar Package Importer
  • Author(s): Paul Cager
  • Date: 2008-04-09 21:17:53 UTC
  • Revision ID: james.westby@ubuntu.com-20080409211753-46lmjw5z8mx5pd8d
Tags: upstream-1.0.2
ImportĀ upstreamĀ versionĀ 1.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  $RCSfile: $
 
2
 *  $Author: egonw $
 
3
 *  $Date: 2007-04-21 02:22:30 +0200 (Sat, 21 Apr 2007) $
 
4
 *  $Revision: 8224 $
 
5
 *
 
6
 *  Copyright (C) 2002-2007  The Chemistry Development Kit (CDK) project
 
7
 *
 
8
 *  Contact: cdk-devel@lists.sourceforge.net
 
9
 *
 
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.
 
18
 *
 
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.
 
23
 *
 
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.
 
27
 */
 
28
package org.openscience.cdk.aromaticity;
 
29
 
 
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;
 
37
 
 
38
/**
 
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
 
43
 * these ChemObjects.
 
44
 *
 
45
 * @author         steinbeck
 
46
 * @author         kaihartmann
 
47
 * @cdk.module     standard
 
48
 * @cdk.created    2001-09-04
 
49
 * 
 
50
 * @see org.openscience.cdk.CDKConstants
 
51
 */
 
52
public class HueckelAromaticityDetector
 
53
{
 
54
 
 
55
        static LoggingTool logger = new LoggingTool(HueckelAromaticityDetector.class);
 
56
        AllRingsFinder ringFinder = null;
 
57
        static IRingSet ringSet=null;
 
58
        static long timeout=5000;
 
59
 
 
60
 
 
61
        public static IRingSet getRingSet() {
 
62
                return ringSet;
 
63
        }
 
64
 
 
65
        /**
 
66
         * Retrieves the set of all rings and performs an aromaticity detection based
 
67
         * on Hueckels 4n+2 rule.
 
68
         *
 
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 
 
73
         */
 
74
        public static boolean detectAromaticity(IAtomContainer atomContainer) throws CDKException
 
75
        {
 
76
                return (detectAromaticity(atomContainer, true));
 
77
        }
 
78
 
 
79
 
 
80
        /**
 
81
         * Uses precomputed set of ALL rings and performs an aromaticity detection
 
82
         * based on Hueckels 4n+2 rule.
 
83
         *
 
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  
 
88
         */
 
89
        public static boolean detectAromaticity(IAtomContainer atomContainer, IRingSet ringSet) throws org.openscience.cdk.exception.CDKException
 
90
        {
 
91
                return (detectAromaticity(atomContainer, ringSet, true));
 
92
        }
 
93
 
 
94
 
 
95
        /**
 
96
         *  Retrieves the set of all rings and performs an aromaticity detection based
 
97
         *  on Hueckels 4n + 2 rule.
 
98
         *
 
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
 
102
         *                              rings
 
103
         *@return                       True, if molecule has aromatic features                                  
 
104
         *@exception CDKException       Thrown in case of errors or an 
 
105
         *                              AllRingsFinder timeout
 
106
         */
 
107
        public static boolean detectAromaticity(IAtomContainer atomContainer, boolean removeAromatictyFlags) throws org.openscience.cdk.exception.CDKException
 
108
        {
 
109
                return detectAromaticity(atomContainer, removeAromatictyFlags, null);
 
110
        }
 
111
 
 
112
 
 
113
        /**
 
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
 
123
         *                              rings
 
124
         *@return                       True, if molecule has aromatic features                                  
 
125
         *@exception CDKException       Thrown in case of errors or an 
 
126
         *                              AllRingsFinder timeout
 
127
         */
 
128
        public static boolean detectAromaticity(IAtomContainer atomContainer, boolean removeAromatictyFlags, AllRingsFinder arf) throws org.openscience.cdk.exception.CDKException
 
129
        {
 
130
                logger.debug("Entered Aromaticity Detection");
 
131
                logger.debug("Starting AllRingsFinder");
 
132
                long before = System.currentTimeMillis();
 
133
                if (arf == null)
 
134
                {
 
135
                        arf = new AllRingsFinder();
 
136
                        arf.setTimeout(timeout);
 
137
                }
 
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)
 
143
                {
 
144
                        return detectAromaticity(atomContainer, ringSet, removeAromatictyFlags);
 
145
                }
 
146
                return false;
 
147
        }
 
148
 
 
149
 
 
150
        /**
 
151
         *  Uses precomputed set of ALL rings and performs an aromaticity detection
 
152
         *  based on Hueckels 4n + 2 rule.
 
153
         *
 
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
 
159
         *                                aromatic feature
 
160
         */
 
161
        public static boolean detectAromaticity(IAtomContainer atomContainer, IRingSet ringSet, boolean removeAromaticityFlags)
 
162
        {
 
163
                boolean foundSomething = false;
 
164
                if (removeAromaticityFlags)
 
165
                {
 
166
                        for (int f = 0; f < atomContainer.getAtomCount(); f++)
 
167
                        {
 
168
                                atomContainer.getAtom(f).setFlag(CDKConstants.ISAROMATIC, false);
 
169
                        }
 
170
                        for (int f = 0; f < atomContainer.getBondCount(); f++)
 
171
                        {
 
172
                                atomContainer.getBond(f).setFlag(CDKConstants.ISAROMATIC, false);
 
173
                        }
 
174
                        for (int f = 0; f < ringSet.getAtomContainerCount(); f++)
 
175
                        {
 
176
                                ((IRing) ringSet.getAtomContainer(f)).setFlag(CDKConstants.ISAROMATIC, false);
 
177
                        }
 
178
                }
 
179
 
 
180
                IRing ring = null;
 
181
                //RingSetManipulator.sort(ringSet);
 
182
                for (int f = 0; f < ringSet.getAtomContainerCount(); f++)
 
183
                {
 
184
                        ring = (IRing) ringSet.getAtomContainer(f);
 
185
                        logger.debug("Testing for aromaticity in ring no ", f);
 
186
                        if (AromaticityCalculator.isAromatic(ring, atomContainer))
 
187
                        {
 
188
                                ring.setFlag(CDKConstants.ISAROMATIC, true);
 
189
 
 
190
                                for (int g = 0; g < ring.getAtomCount(); g++)
 
191
                                {
 
192
                                        ring.getAtom(g).setFlag(CDKConstants.ISAROMATIC, true);
 
193
                                }
 
194
 
 
195
                                for (int g = 0; g < ring.getBondCount(); g++)
 
196
                                {
 
197
                                        ring.getBond(g).setFlag(CDKConstants.ISAROMATIC, true);
 
198
                                }
 
199
 
 
200
                                foundSomething = true;
 
201
                                logger.debug("This ring is aromatic: ", f);
 
202
                        } else
 
203
                        {
 
204
                                logger.debug("This ring is *not* aromatic: ", f);
 
205
                        }
 
206
                }
 
207
                return foundSomething;
 
208
        }
 
209
 
 
210
 
 
211
        /**
 
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.
 
215
         *
 
216
         *@param  ringset  the RingSet to set the flags for
 
217
         */
 
218
        public static void setRingFlags(IRingSet ringset)
 
219
        {
 
220
                for (int i = 0; i < ringset.getAtomContainerCount(); i++)
 
221
                {
 
222
                        boolean aromatic = true;
 
223
                        IRing ring = (IRing) ringset.getAtomContainer(i);
 
224
                        for (int j = 0; j < ring.getAtomCount(); j++)
 
225
                        {
 
226
                                if (ring.getAtom(j).getFlag(CDKConstants.ISAROMATIC) != true)
 
227
                                {
 
228
                                        aromatic = false;
 
229
                                        break;
 
230
                                }
 
231
                        }
 
232
                        if (aromatic)
 
233
                        {
 
234
                                ring.setFlag(CDKConstants.ISAROMATIC, true);
 
235
                        } else
 
236
                        {
 
237
                                ring.setFlag(CDKConstants.ISAROMATIC, false);
 
238
                        }
 
239
                }
 
240
        }
 
241
 
 
242
 
 
243
        /*
 
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.
 
247
         *
 
248
         *@param  ringFinder  The value to assign ringFinder.
 
249
         *@see                org.openscience.cdk.ringsearch.AllRingsFinder
 
250
         */
 
251
//      public void setRingFinder(AllRingsFinder ringFinder)
 
252
//      {
 
253
//              this.ringFinder = ringFinder;
 
254
//      }
 
255
 
 
256
        /**
 
257
         * Sets the timeout for the AllRingsFinder. The default is 5000ms.
 
258
         * 
 
259
         * @param timeout  The timeout for the AllRingsFinder.
 
260
         */
 
261
        public static void setTimeout(long timeout) {
 
262
                HueckelAromaticityDetector.timeout = timeout;
 
263
        }
 
264
 
 
265
        /*
 
266
         *  public static boolean isAromatic(AtomContainer ac, Ring ring)
 
267
         *  {
 
268
         *  return AromaticityCalculator.isAromatic(ring, ac);
 
269
         *  }
 
270
         *  *   public static boolean isAromatic(AtomContainer ac, Ring ring)
 
271
         *  {
 
272
         *  int piElectronCount = 0;
 
273
         *  int freeElectronPairCount = 0;
 
274
         *  Atom atom = null;
 
275
         *  Bond bond = null;
 
276
         *  int aromaCounter = 0;
 
277
         *  logger.debug("isAromatic() -> ring.size(): " + ring.getAtomCount());
 
278
         *  for (int g = 0; g < ring.getAtomCount(); g++)
 
279
         *  {
 
280
         *  atom = ring.getAtomAt(g);
 
281
         *  if ("O-N-S-P".indexOf(atom.getSymbol()) > -1)
 
282
         *  {
 
283
         *  freeElectronPairCount += 1;
 
284
         *  }
 
285
         *  if (atom.getFlag(CDKConstants.ISAROMATIC))
 
286
         *  {
 
287
         *  aromaCounter ++;
 
288
         *  }
 
289
         *  }
 
290
         *  for (int g = 0; g < ring.getElectronContainerCount(); g++) {
 
291
         *  ElectronContainer ec = ring.getElectronContainerAt(g);
 
292
         *  if (ec instanceof org.openscience.cdk.interfaces.Bond) {
 
293
         *  bond = (Bond)ec;
 
294
         *  if (bond.getOrder() > 1) {
 
295
         *  piElectronCount += 2*(bond.getOrder()-1);
 
296
         *  }
 
297
         *  }
 
298
         *  }
 
299
         *  for (int f = 0; f < ((ring.getAtomCount() - 2)/4) + 2; f ++)
 
300
         *  {
 
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;
 
310
         *  }
 
311
         *  return false;
 
312
         *  }
 
313
         */
 
314
}
 
315