Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: joelib/molecule/JOEMol.java


1   ///////////////////////////////////////////////////////////////////////////////
2   //  Filename: $RCSfile: JOEMol.java,v $
3   //  Purpose:  Atom representation.
4   //  Language: Java
5   //  Compiler: JDK 1.4
6   //  Authors:  Joerg K. Wegner
7   //  Version:  $Revision: 1.73 $
8   //            $Date: 2003/12/09 17:51:29 $
9   //            $Author: wegner $
10  //  Original Author: ???, OpenEye Scientific Software
11  //  Original Version: babel 2.0a1
12  //
13  //  Copyright (c) Dept. Computer Architecture, University of Tuebingen, Germany
14  //
15  //  This program is free software; you can redistribute it and/or modify
16  //  it under the terms of the GNU General Public License as published by
17  //  the Free Software Foundation version 2 of the License.
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 General Public License for more details.
23  ///////////////////////////////////////////////////////////////////////////////
24  package joelib.molecule;
25  
26  import joelib.data.JOEDataType;
27  import joelib.data.JOEElementTable;
28  import joelib.data.JOEGenericData;
29  import joelib.data.JOEPairData;
30  import joelib.data.JOEPhModel;
31  import joelib.data.JOEVirtualBond;
32  
33  import joelib.desc.DescResult;
34  import joelib.desc.DescriptorException;
35  import joelib.desc.DescriptorHelper;
36  
37  import joelib.desc.types.GraphPotentials;
38  
39  import joelib.io.IOType;
40  import joelib.io.IOTypeHolder;
41  import joelib.io.JOEFileFormat;
42  import joelib.io.MoleculeFileType;
43  import joelib.io.MoleculeIOException;
44  import joelib.io.PropertyWriter;
45  
46  import joelib.math.Matrix3x3;
47  import joelib.math.XYZVector;
48  
49  import joelib.ring.JOERing;
50  import joelib.ring.JOERingData;
51  import joelib.ring.JOERingSearch;
52  
53  import joelib.smiles.JOEMol2Smi;
54  
55  import joelib.sort.ArraySizeComparator;
56  import joelib.sort.QuickInsertSort;
57  
58  import joelib.util.JHM;
59  import joelib.util.JOEBitVec;
60  import joelib.util.JOEHelper;
61  
62  import joelib.util.database.AbstractDatabase;
63  
64  import joelib.util.iterator.AtomIterator;
65  import joelib.util.iterator.BondIterator;
66  import joelib.util.iterator.ConformerIterator;
67  import joelib.util.iterator.GenericDataIterator;
68  import joelib.util.iterator.NativeValueIterator;
69  import joelib.util.iterator.NbrAtomIterator;
70  import joelib.util.iterator.ResidueIterator;
71  import joelib.util.iterator.RingIterator;
72  
73  import joelib.util.types.AtomHCount;
74  import joelib.util.types.AtomZPos;
75  
76  /*==========================================================================*
77   * IMPORTS
78   *==========================================================================*/
79  import java.io.ByteArrayOutputStream;
80  import java.io.IOException;
81  
82  import java.util.Vector;
83  
84  import org.apache.log4j.Category;
85  
86  
87  /*==========================================================================*
88   * CLASS DECLARATION
89   *========================================================================== */
90  
91  /**
92   * Molecule representation.
93   *
94   * <p>
95   * There are different possibilities to build a molecule.
96   * <ol>
97   * <li>Using SMILES notation to build a molecule.<br>
98   * <blockquote><pre>
99   * JOEMol mol=new JOEMol();
100  * String smiles="c1cc(OH)cc1";
101  * if (!JOESmilesParser.smiToMol(mol, smiles, setTitle.toString()))
102  * {
103  *   System.err.println("SMILES entry \"" + smiles + "\" could not be loaded.");
104  * }
105  * System.out.println(mol.toString());
106  * </pre></blockquote>
107  * </li>
108  *
109  * <li>Using plain atoms and bonds to build a molecule.<br>
110  * <blockquote><pre>
111  * JOEMol mol = new JOEMol();
112  * // start molecule modification
113  * mol.beginModify();
114  * mol.reserveAtoms(2);
115  *
116  * // build carbon atom
117  * JOEAtom C = new JOEAtom();
118  * atomC.setAtomicNum(6);
119  *
120  * // build molecule
121  * for (int i=0; i&lt;2; i++) {
122  *   mol.addAtom(atom);
123  * }
124  *
125  * // add double bond
126  * mol.addBond(1,2, 2);
127  *
128  * //end molecule modification and store all
129  * //coordinates in coordinate array
130  * mol.endModify();
131  * </pre></blockquote>
132  * </li>
133  * 2D coordinates can be generated using {@link joelib.util.cdk.CDKTools} which uses
134  * the structure layout module from the <a href="http://cdk.sourceforge.net/">CDK</a>.<br>
135  * 3D coordinates can be
136  * generated using an external processing module ({@link joelib.ext.External}), if available,
137  * for 3D generation programs, like
138  * <a href="http://www2.chemie.uni-erlangen.de/software/corina/" target="_top">Corina</a>.
139  *
140  * <p>
141  * For speed optimization of loading descriptor molecule files have a
142  * look at the {@link joelib.desc.ResultFactory}.
143  *
144  * @author     wegnerj
145  * @license    GPL
146  * @cvsversion    $Revision: 1.73 $, $Date: 2003/12/09 17:51:29 $
147  * @cite clr98complexity
148  * @cite zup89c
149  * @cite fig96
150  * @cite gm78
151  * @cite smilesFormat
152  * @see joelib.smiles.JOESmilesParser
153  * @see joelib.util.cdk.CDKTools
154  * @see joelib.ext.External
155  * @see joelib.ext.Title2Data
156  */
157 public class JOEMol implements Cloneable, java.io.Serializable
158 {
159     //~ Static fields/initializers /////////////////////////////////////////////
160 
161     /*-------------------------------------------------------------------------*
162      * public static member variables
163      *------------------------------------------------------------------------- */
164 
165     /**
166      *  Obtain a suitable logger.
167      */
168     private static Category logger = Category.getInstance(
169             "joelib.molecule.JOEMol");
170 
171     /**
172      *  Molecule flag: SSSR calculated.
173      */
174     public final static int JOE_SSSR_MOL = (1 << 1);
175 
176     /**
177      *  Molecule flag: rings perceived.
178      */
179     public final static int JOE_RINGFLAGS_MOL = (1 << 2);
180 
181     /**
182      *  Molecule flag: aromaticity calculated.
183      */
184     public final static int JOE_AROMATIC_MOL = (1 << 3);
185 
186     /**
187      *  Molecule flag: atom types perceived.
188      */
189     public final static int JOE_ATOMTYPES_MOL = (1 << 4);
190 
191     /**
192      *  Molecule flag: atom chirality flags perceived.
193      */
194     public final static int JOE_CHIRALITY_MOL = (1 << 5);
195 
196     /**
197      *  Molecule flag: partitial charges perceived.
198      */
199     public final static int JOE_PCHARGE_MOL = (1 << 6);
200 
201     /**
202      *  Molecule flag: atom hybridisation perceived.
203      */
204     public final static int JOE_HYBRID_MOL = (1 << 8);
205 
206     /**
207      *  Molecule flag: implicit valences perceived.
208      */
209     public final static int JOE_IMPVAL_MOL = (1 << 9);
210 
211     /**
212      *  Molecule flag: kekulization perceived.
213      */
214     public final static int JOE_KEKULE_MOL = (1 << 10);
215 
216     /**
217      *  Molecule flag: closure bonds perceived.
218      */
219     public final static int JOE_CLOSURE_MOL = (1 << 11);
220 
221     /**
222      *  Molecule flag: H atoms added molecule.
223      */
224     public final static int JOE_H_ADDED_MOL = (1 << 12);
225 
226     /**
227      *  Molecule flag: PH value perceived.
228      */
229     public final static int JOE_PH_CORRECTED_MOL = (1 << 13);
230 
231     /**
232      *  Molecule flag: aromaticity corrected molecule.
233      */
234     public final static int JOE_AROM_CORRECTED_MOL = (1 << 14);
235 
236     /**
237      *  Molecule flag: chain molecule.
238      */
239     public final static int JOE_CHAINS_MOL = (1 << 15);
240 
241     /**
242      *  Molecule flag: current conformer.
243      */
244     public final static int JOE_CURRENT_CONFORMER = (1 << 16);
245 
246     //-1 not necessary because int in Java 32 bit value;
247 
248     /*-------------------------------------------------------------------------*
249      * private static member variables
250      *------------------------------------------------------------------------- */
251     private final static int JOE_ATOM_INCREMENT = 100;
252 
253     //  private final static int JOE_BOND_INCREMENT = 100;
254     private final static IOType DEFAULT_IO_TYPE = IOTypeHolder.instance()
255                                                               .getIOType("SDF");
256 
257     //~ Instance fields ////////////////////////////////////////////////////////
258 
259     /**
260      *  Holds additional molecule data, e.g. atom, bond or moelcule properties.
261      */
262     protected GenericDataHolder genericData;
263 
264     /**
265      * Molecule compressed.
266      */
267 
268     //  protected boolean _compressed;
269 
270     /**
271      *  Molecule input type.
272      */
273     protected IOType _itype;
274 
275     /**
276      *  Molecule output type.
277      */
278     protected IOType _otype;
279 
280     /**
281      *  Title for this molecule.
282      */
283     protected String _title;
284 
285     /**
286      *  Atoms of this molecule.
287      *
288      * @see    joelib.molecule.JOEAtom
289      */
290     protected Vector _atom;
291 
292     /**
293      *  Bonds of this molecule.
294      *
295      * @see    joelib.molecule.JOEBond
296      */
297     protected Vector _bond;
298 
299     /**
300      *  Description of the Field
301      */
302     protected Vector _pose;
303 
304     /**
305      * Residues for this molecule.
306      */
307     protected Vector _residue;
308 
309     /**
310      *  Of type double[].
311      */
312     protected Vector _vconf;
313 
314     /**
315      *  Coordinate array of the atom positions.
316      */
317     protected double[] _c;
318 
319     /**
320      *  Description of the Field
321      */
322     protected double[] _xyz_pose;
323 
324     /**
325      * Automatic formal charge calculation.
326      */
327     protected boolean _autoFormalCharge;
328 
329     /**
330      * Automatic partial charge calculation.
331      */
332     protected boolean _autoPartialCharge;
333 
334     /**
335      *  Energy of this molecule.
336      */
337     protected double _energy;
338 
339     /**
340      *  Description of the Field
341      */
342     protected int _access;
343 
344     /**
345      *  Description of the Field
346      */
347     protected int _cur_pose_idx;
348 
349     /*-------------------------------------------------------------------------*
350      * protected member variables
351      *------------------------------------------------------------------------- */
352 
353     /**
354      *  Molecule flags.
355      *
356      * @see    joelib.molecule.JOEMol#JOE_SSSR_MOL
357      * @see    joelib.molecule.JOEMol#JOE_RINGFLAGS_MOL
358      * @see    joelib.molecule.JOEMol#JOE_AROMATIC_MOL
359      * @see    joelib.molecule.JOEMol#JOE_ATOMTYPES_MOL
360      * @see    joelib.molecule.JOEMol#JOE_CHIRALITY_MOL
361      * @see    joelib.molecule.JOEMol#JOE_PCHARGE_MOL
362      * @see    joelib.molecule.JOEMol#JOE_HYBRID_MOL
363      * @see    joelib.molecule.JOEMol#JOE_IMPVAL_MOL
364      * @see    joelib.molecule.JOEMol#JOE_KEKULE_MOL
365      * @see    joelib.molecule.JOEMol#JOE_CLOSURE_MOL
366      * @see    joelib.molecule.JOEMol#JOE_H_ADDED_MOL
367      * @see    joelib.molecule.JOEMol#JOE_PH_CORRECTED_MOL
368      * @see    joelib.molecule.JOEMol#JOE_AROM_CORRECTED_MOL
369      * @see    joelib.molecule.JOEMol#JOE_CHAINS_MOL
370      * @see    joelib.molecule.JOEMol#JOE_CURRENT_CONFORMER
371      */
372     protected int _flags;
373 
374     /**
375      *  Modification counter.
376      *
377      * @see #getMod()
378      */
379     protected int _mod;
380 
381     /**
382      *  Number of atoms in this molecule.
383      */
384     protected int _natoms;
385 
386     /**
387      *  Number of bonds in this molecule.
388      */
389     protected int _nbonds;
390     private int hash = 0;
391 
392     //~ Constructors ///////////////////////////////////////////////////////////
393 
394     /*-------------------------------------------------------------------------*
395      * constructor / desctructor
396      *------------------------------------------------------------------------- */
397 
398     /**
399      *  Constructor for the <tt>JOEMol</tt>. The 'Structured Data File'
400      *  (SDF) molecule data format is used for default.
401      *
402      * @see #JOEMol(IOType, IOType)
403      * @see #JOEMol(JOEMol)
404      * @see #JOEMol(JOEMol, boolean)
405      * @see #JOEMol(JOEMol, boolean, String[])
406      * @cite mdlMolFormat
407      */
408     public JOEMol()
409     {
410         this(DEFAULT_IO_TYPE, DEFAULT_IO_TYPE);
411     }
412 
413     /**
414      *  Constructor for the <tt>JOEMol</tt>.
415      *
416      * @param  itype  input type for this molecule
417      * @param  otype  output type for this molecule
418      *
419      * @see #JOEMol()
420      * @see #JOEMol(JOEMol)
421      * @see #JOEMol(JOEMol, boolean)
422      * @see #JOEMol(JOEMol, boolean, String[])
423      */
424     public JOEMol(IOType itype, IOType otype)
425     {
426         _natoms = _nbonds = 0;
427         _mod = 0;
428         _access = 0;
429         _energy = 0.0f;
430         _itype = itype;
431         _otype = otype;
432         _atom = new Vector(20, JOE_ATOM_INCREMENT);
433         _bond = new Vector(20);
434         genericData = new GenericDataHolder(this, 5, 250);
435         _title = "";
436         _c = null;
437         _flags = 0;
438         _vconf = new Vector();
439         _xyz_pose = null;
440         _pose = new Vector();
441         _residue = new Vector();
442         _cur_pose_idx = 0;
443         _autoPartialCharge = true;
444         _autoFormalCharge = true;
445 
446         //    _compressed = false;
447     }
448 
449     /**
450      * Constructor for the <tt>JOEMol</tt>.
451      *
452      * @param  source  The source molecule
453      * @param  cloneDesc  clones the PairData descriptors if <tt>true</tt>
454      * @param  descriptors  the descriptors to clone. If <tt>null</tt> all descriptors are cloned
455      *
456      * @see #JOEMol()
457      * @see #JOEMol(IOType, IOType)
458      * @see #JOEMol(JOEMol)
459      * @see #JOEMol(JOEMol, boolean)
460      */
461     public JOEMol(final JOEMol source, boolean cloneDesc, String[] descriptors)
462     {
463         _atom = new Vector(20, JOE_ATOM_INCREMENT);
464         _bond = new Vector(20);
465         _vconf = new Vector();
466         _pose = new Vector();
467         _residue = new Vector();
468         genericData = new GenericDataHolder(this, 5, 250);
469         set(source, cloneDesc, descriptors);
470     }
471 
472     /**
473      * Constructor for the <tt>JOEMol</tt>.
474      *
475      * @param  source  The source molecule
476      * @param  cloneDesc  clones the PairData descriptors if <tt>true</tt>
477      *
478      * @see #JOEMol()
479      * @see #JOEMol(IOType, IOType)
480      * @see #JOEMol(JOEMol)
481      * @see #JOEMol(JOEMol, boolean)
482      * @see #JOEMol(JOEMol, boolean, String[])
483      */
484     public JOEMol(final JOEMol source, boolean cloneDesc)
485     {
486         this(source, cloneDesc, null);
487     }
488 
489     /**
490      * Clones the molecule without data elements.
491      *
492      * @param  source  The source molecule
493      *
494      * @see #JOEMol()
495      * @see #JOEMol(IOType, IOType)
496      * @see #JOEMol(JOEMol, boolean)
497      * @see #JOEMol(JOEMol, boolean, String[])
498      */
499     public JOEMol(final JOEMol source)
500     {
501         this(source, false, null);
502     }
503 
504     //~ Methods ////////////////////////////////////////////////////////////////
505 
506     /**
507      *  Sets the add attribute of the <tt>JOEMol</tt> object
508      *
509      * @param  source  The new add value
510      * @return         Description of the Return Value
511      */
512     public JOEMol setAdd(final JOEMol source)
513     {
514         JOEMol src = source;
515         JOEAtom atom;
516         JOEBond bond;
517         AtomIterator ait = src.atomIterator();
518         BondIterator bit = src.bondIterator();
519 
520         beginModify();
521 
522         int prevatms = numAtoms();
523 
524         _title += ("_" + src.getTitle());
525 
526         while (ait.hasNext())
527         {
528             atom = ait.nextAtom();
529             addAtom(atom);
530         }
531 
532         while (bit.hasNext())
533         {
534             bond = bit.nextBond();
535             addBond(bond);
536             addBond(bond.getBeginAtomIdx() + prevatms,
537                 bond.getEndAtomIdx() + prevatms, bond.getBO());
538         }
539 
540         endModify();
541 
542         return this;
543     }
544 
545     /**
546      *  Sets the aromaticCorrected attribute of the <tt>JOEMol</tt> object
547      */
548     public void setAromaticCorrected()
549     {
550         setFlag(JOE_AROM_CORRECTED_MOL);
551     }
552 
553     /**
554      *  Sets the aromaticPerceived attribute of the <tt>JOEMol</tt> object
555      */
556     public void setAromaticPerceived()
557     {
558         setFlag(JOE_AROMATIC_MOL);
559     }
560 
561     /**
562      *  Gets an atom of the <tt>JOEMol</tt> object Atom index must be between <tt>
563      *  1</tt> to <tt>numAtoms()</tt> .
564      *
565      * @param  idx  Description of the Parameter
566      * @return      The atom value
567      */
568     public JOEAtom getAtom(int idx)
569     {
570         if ((idx < 1) || (idx > numAtoms()))
571         {
572             //oeAssert(false);
573             //      throw new Exception("Requested Atom Out of Range");
574             logger.error("Requested atom (" + idx + ") out of range (1-" +
575                 numAtoms() + ").");
576 
577             return null;
578         }
579 
580         //        System.out.println("get: "+(idx - 1)+" "+_atom.get(idx - 1));
581         return (JOEAtom) _atom.get(idx - 1);
582     }
583 
584     /**
585      *  Sets the atomTypesPerceived attribute of the <tt>JOEMol</tt> object
586      */
587     public void setAtomTypesPerceived()
588     {
589         setFlag(JOE_ATOMTYPES_MOL);
590     }
591 
592     /**
593      *  Sets the flag if the automatic calculation of the formal charge of the
594      *  atoms is allowed. This is for example used in the PH value correction
595      *  method.
596      *
597      * @param  val  <tt>true</tt> if the calculation of the formal charge is
598      *      allowed.
599      */
600     public void setAutomaticFormalCharge(boolean val)
601     {
602         _autoFormalCharge = val;
603     }
604 
605     /**
606      *  Sets the automaticPartialCharge attribute of the <tt>JOEMol</tt> object
607      *
608      * @param  val  The new automaticPartialCharge value
609      */
610     public void setAutomaticPartialCharge(boolean val)
611     {
612         _autoPartialCharge = val;
613     }
614 
615     /**
616      *  Gets a bond of the <tt>JOEMol</tt> object. Bond index must be between <tt>
617      *  0</tt> to <tt>(numBonds()-1)</tt> .
618      *
619      * @param  idx  Description of the Parameter
620      * @return      The bond value
621      */
622     public JOEBond getBond(int idx)
623     {
624         if ((idx < 0) || (idx >= numBonds()))
625         {
626             //        throw new Exception("Requested Bond Out of Range");
627             logger.error("Requested bond (" + idx + ") out of range (0-" +
628                 (numBonds() - 1) + ").");
629 
630             return null;
631         }
632 
633         return (JOEBond) _bond.get(idx);
634     }
635 
636     /**
637      *  Gets the bond attribute of the <tt>JOEMol</tt> object Atom index must be
638      *  between <tt>1</tt> to <tt>numAtoms()</tt> .
639      *
640      * @param  bgn  atom index of the start atom
641      * @param  end  atom index of the end atom
642      * @return      The bond value
643      */
644     public JOEBond getBond(int bgn, int end)
645     {
646         return getBond(getAtom(bgn), getAtom(end));
647     }
648 
649     /**
650      *  Gets the bond attribute of the <tt>JOEMol</tt> object
651      *
652      * @param  bgn  Description of the Parameter
653      * @param  end  Description of the Parameter
654      * @return      The bond value
655      */
656     public JOEBond getBond(JOEAtom bgn, JOEAtom end)
657     {
658         JOEAtom nbr;
659         NbrAtomIterator nait = bgn.nbrAtomIterator();
660 
661         while (nait.hasNext())
662         {
663             nbr = nait.nextNbrAtom();
664 
665             if (nbr == end)
666             {
667                 return nait.actualBond();
668             }
669         }
670 
671         //oeAssert(false); //should never get here
672         return null;
673     }
674 
675     /**
676      *  Sets the chainsPerceived attribute of the <tt>JOEMol</tt> object
677      */
678     public void setChainsPerceived()
679     {
680         setFlag(JOE_CHAINS_MOL);
681     }
682 
683     /**
684      *  Gets the chiral attribute of the JOEMol object
685      *
686      * @return    The chiral value
687      */
688     public boolean isChiral()
689     {
690         JOEAtom atom;
691         AtomIterator ait = this.atomIterator();
692 
693         while (ait.hasNext())
694         {
695             atom = ait.nextAtom();
696 
697             if ((atom.isCarbon() || atom.isNitrogen()) &&
698                     (atom.getHvyValence() > 2) && atom.isChiral())
699             {
700                 return true;
701             }
702         }
703 
704         return false;
705     }
706 
707     /**
708      *  Sets the chiralityPerceived attribute of the <tt>JOEMol</tt> object
709      */
710     public void setChiralityPerceived()
711     {
712         setFlag(JOE_CHIRALITY_MOL);
713     }
714 
715     /**
716      *  Sets the closureBondsPerceived attribute of the <tt>JOEMol</tt> object
717      */
718     public void setClosureBondsPerceived()
719     {
720         setFlag(JOE_CLOSURE_MOL);
721     }
722 
723     /**
724      *  Sets the conformer attribute of the JOEMol object
725      *
726      * @param  i  The new conformer value
727      */
728     public void setConformer(int i)
729     {
730         _c = (double[]) _vconf.get(i);
731     }
732 
733     /**
734      *  Gets the conformer attribute of the JOEMol object
735      *
736      * @param  i  Description of the Parameter
737      * @return    The conformer value
738      */
739     public double[] getConformer(int i)
740     {
741         return (double[]) _vconf.get(i);
742     }
743 
744     /**
745      *  Sets the conformers attribute of the JOEMol object
746      *
747      * @param  v  The new conformers value (v is of type double[])
748      */
749     public void setConformers(Vector v)
750     {
751         //double[] fa;
752         //    for (int i = 0; i < _vconf.size(); i++)
753         //    {
754         //      fa = (double[]) _vconf.get(i);
755         //      fa = null;
756         //    }
757         _vconf.clear();
758 
759         //        _vconf = v;
760         _vconf.ensureCapacity(v.size());
761 
762         for (int i = 0; i < v.size(); i++)
763         {
764             _vconf.add(v.get(i));
765         }
766 
767         _c = (_vconf.size() == 0) ? null : (double[]) _vconf.get(0);
768     }
769 
770     /**
771      * Returns a {@link java.util.Vector} of all conformer coordinates (<tt>double[]</tt> values).
772      *
773      * @return    The conformers coordinates
774      */
775     public Vector getConformers()
776     {
777         return _vconf;
778     }
779 
780     /**
781      * Gets the coordinate array of this molecule.
782      *
783      * @return    The coordinates array
784      */
785     public double[] getCoordinates()
786     {
787         return (_c);
788     }
789 
790     /**
791      *  Sets the correctedForPH attribute of the <tt>JOEMol</tt> object
792      */
793     public void setCorrectedForPH()
794     {
795         setFlag(JOE_PH_CORRECTED_MOL);
796     }
797 
798     /**
799      *  Gets the correctedForPH attribute of the JOEMol object
800      *
801      * @return    The correctedForPH value
802      */
803     public boolean isCorrectedForPH()
804     {
805         return (hasFlag(JOE_PH_CORRECTED_MOL));
806     }
807 
808     /**
809      * Returns the first data entry of the given data type.
810      * If this data type don't exists in this molecule, <tt>null</tt>
811      * is returned.
812      *
813      * <p>
814      * There exist a lot of default data types which where defined in
815              * {@link JOEDataType}. These data types are used for caching ring
816              * searches and storing special data types like comments or virtual bonds.
817              * Furthermore there exist the most important data type {@link JOEPairData}
818              * for storing descriptor values. Read the {@link JOEDataType} description
819              * for details.
820      *
821      * @param  dt       data type
822      * @return     <tt>null</tt> if no element of this data type exists
823      * @see #getData(String)
824      * @see #getData(String, boolean)
825      * @see #genericDataIterator()
826      * @see #addData(JOEGenericData)
827      * @see #addData(JOEGenericData, boolean)
828      */
829     public JOEGenericData getData(JOEDataType dt)
830     {
831         return genericData.getData(dt);
832     }
833 
834     /**
835      * Returns the data entry with the given name, if multiple data entries
836      * exists only the first one is taken.
837      * If the data element is a {@link JOEPairData} element with a unparsed
838      * String value, the descriptor value will be automatically parsed from
839      * a String value to the representing result ({@link DescResult}) class.
840      * If no data element with this name exists in this molecule, <tt>null</tt>
841      * is returned.
842      *
843      * <p>
844      * There exist a lot of default data types which where defined in
845              * {@link JOEDataType}. These data types are used for caching ring
846              * searches and storing special data types like comments or virtual bonds.
847              * Furthermore there exist the most important data type {@link JOEPairData}
848              * for storing descriptor values. Read the {@link JOEDataType} description
849              * for details.
850      *
851      * <p>
852      * Missing descriptor values can be calculated by using
853      * {@link DescriptorHelper#descFromMol(JOEMol, String)}.<br>
854      * Example:
855      * <blockquote><pre>
856      * DescResult result=null;
857      * try
858      * {
859      *         result=DescriptorHelper.instance().descFromMol(mol, descriptorName);
860      * }
861      * catch (DescriptorException ex)
862      * {
863      *         // descriptor can not be calculated
864      * }
865      * </pre></blockquote>
866      * Notice the difference between {@link JOEGenericData} and
867      * {@link DescResult}. {@link DescResult} values can be added to
868      * molecules by using {@link JOEPairData}
869      * <blockquote><pre>
870      * JOEPairData dp = new JOEPairData();
871      * dp.setAttribute(descriptorName);
872      * dp.setValue(result);
873      * mol.addData(dp);
874      * </pre></blockquote>
875      *
876      * @param  s      The data element (descriptor) name
877      * @return     <tt>null</tt> if no element with this name exists
878      * @see #getData(JOEDataType)
879      * @see #getData(String, boolean)
880      * @see #genericDataIterator()
881      * @see #addData(JOEGenericData)
882      * @see #addData(JOEGenericData, boolean)
883      * @see JOEDataType
884      * @see JOEPairData
885      * @see DescResult
886      * @see GenericDataHolder#getData(String, boolean)
887      * @see DescriptorHelper#descFromMol(JOEMol, String)
888      * @see DescriptorHelper#descFromMol(JOEMol, String, DescResult)
889      * @see DescriptorHelper#descFromMol(JOEMol, String, DescResult, boolean)
890      */
891     public JOEGenericData getData(String s)
892     {
893         return genericData.getData(s, true);
894     }
895 
896     /**
897      * Returns the data entry with the given name, if multiple data entries
898      * exists only the first one is taken.
899      * If the data element is a {@link JOEPairData} the <tt>parse</tt> flag
900      * can be used to parse this data elements.
901      * If no data element with this name exists in this molecule, <tt>null</tt>
902      * is returned.
903      *
904      * <p>
905      * There exist a lot of default data types which where defined in
906              * {@link JOEDataType}. These data types are used for caching ring
907              * searches and storing special data types like comments or virtual bonds.
908              * Furthermore there exist the most important data type {@link JOEPairData}
909              * for storing descriptor values. Read the {@link JOEDataType} description
910              * for details.
911      *
912      * <p>
913      * Missing descriptor values can be calculated by using
914      * {@link DescriptorHelper#descFromMol(JOEMol, String)}.<br>
915      * Example:
916      * <blockquote><pre>
917      * DescResult result=null;
918      * try
919      * {
920      *         result=DescriptorHelper.instance().descFromMol(mol, descriptorName);
921      * }
922      * catch (DescriptorException ex)
923      * {
924      *         // descriptor can not be calculated
925      * }
926      * </pre></blockquote>
927      * Notice the difference between {@link JOEGenericData} and
928      * {@link DescResult}. {@link DescResult} values can be added to
929      * molecules by using {@link JOEPairData}
930      * <blockquote><pre>
931      * JOEPairData dp = new JOEPairData();
932      * dp.setAttribute(descriptorName);
933      * dp.setValue(result);
934      * mol.addData(dp);
935      * </pre></blockquote>
936      *
937      * @param  s       The data element (descriptor) name
938      * @param  parse   Parse data element
939      * @return     <tt>null</tt> if no element with this name exists
940      * @see #getData(JOEDataType)
941      * @see #getData(String)
942      * @see #genericDataIterator()
943      * @see #addData(JOEGenericData)
944      * @see #addData(JOEGenericData, boolean)
945      * @see JOEDataType
946      * @see JOEPairData
947      * @see DescResult
948      * @see GenericDataHolder#getData(String, boolean)
949      * @see DescriptorHelper#descFromMol(JOEMol, String)
950      * @see DescriptorHelper#descFromMol(JOEMol, String, DescResult)
951      * @see DescriptorHelper#descFromMol(JOEMol, String, DescResult, boolean)
952      */
953     public JOEGenericData getData(String s, boolean parse)
954     {
955         return genericData.getData(s, parse);
956     }
957 
958     /**
959      *  Sets the energy attribute of the <tt>JOEMol</tt> object
960      *
961      * @param  energy  The new energy value
962      */
963     public void setEnergy(double energy)
964     {
965         _energy = energy;
966     }
967 
968     /**
969      *  Gets the energy attribute of the <tt>JOEMol</tt> object
970      *
971      * @return    The energy value
972      */
973     public double getEnergy()
974     {
975         return (_energy);
976     }
977 
978     /**
979      * Gets mass given by isotopes (or most abundant isotope as necessary).
980      *
981      * @return    The molWt value
982      */
983     public double getExactMass()
984     {
985         double molwt = 0.0f;
986         JOEAtom atom;
987         AtomIterator ait = this.atomIterator();
988 
989         while (ait.hasNext())
990         {
991             atom = ait.nextAtom();
992             molwt += atom.getExactMass();
993         }
994 
995         return molwt;
996     }
997 
998     /**
999      *  Gets the firstAtom attribute of the <tt>JOEMol</tt> object
1000     *
1001     * @return    The firstAtom value
1002     */
1003    public JOEAtom getFirstAtom()
1004    {
1005        return ((_atom.size() == 0) ? null : (JOEAtom) _atom.get(0));
1006    }
1007
1008    /**
1009     *  Gets the flags attribute of the <tt>JOEMol</tt> object
1010     *
1011     * @return    The flags value
1012     * @see       joelib.molecule.JOEMol#JOE_SSSR_MOL
1013     * @see       joelib.molecule.JOEMol#JOE_RINGFLAGS_MOL
1014     * @see       joelib.molecule.JOEMol#JOE_AROMATIC_MOL
1015     * @see       joelib.molecule.JOEMol#JOE_ATOMTYPES_MOL
1016     * @see       joelib.molecule.JOEMol#JOE_CHIRALITY_MOL
1017     * @see       joelib.molecule.JOEMol#JOE_PCHARGE_MOL
1018     * @see       joelib.molecule.JOEMol#JOE_HYBRID_MOL
1019     * @see       joelib.molecule.JOEMol#JOE_IMPVAL_MOL
1020     * @see       joelib.molecule.JOEMol#JOE_KEKULE_MOL
1021     * @see       joelib.molecule.JOEMol#JOE_CLOSURE_MOL
1022     * @see       joelib.molecule.JOEMol#JOE_H_ADDED_MOL
1023     * @see       joelib.molecule.JOEMol#JOE_PH_CORRECTED_MOL
1024     * @see       joelib.molecule.JOEMol#JOE_AROM_CORRECTED_MOL
1025     * @see       joelib.molecule.JOEMol#JOE_CHAINS_MOL
1026     * @see       joelib.molecule.JOEMol#JOE_CURRENT_CONFORMER
1027     */
1028    public int getFlags()
1029    {
1030        return (_flags);
1031    }
1032
1033    //calculates the graph theoretical distance for every atom
1034    //and puts it into gtd
1035
1036    /**
1037     *  Gets the gTDVector attribute of the <tt>JOEMol</tt> object
1038     *
1039     * @param  gtd  Description of the Parameter
1040     * @return      The gTDVector value
1041     */
1042    public boolean getGTDVector(int[] gtd)
1043    {
1044        //gtd.clear();
1045        //gtd.setSize(numAtoms());
1046        if (gtd.length != numAtoms())
1047        {
1048            logger.error("gtd must have length of #atoms: " + numAtoms());
1049        }
1050
1051        int gtdcount;
1052
1053        int natom;
1054        JOEBitVec used = new JOEBitVec();
1055        JOEBitVec curr = new JOEBitVec();
1056        JOEBitVec next = new JOEBitVec();
1057        JOEAtom atom;
1058        JOEAtom atom1;
1059        JOEBond bond;
1060        AtomIterator ait = this.atomIterator();
1061
1062        next.clear();
1063
1064        while (ait.hasNext())
1065        {
1066            atom = ait.nextAtom();
1067            gtdcount = 0;
1068            used.clear();
1069            curr.clear();
1070            used.setBitOn(atom.getIdx());
1071            curr.setBitOn(atom.getIdx());
1072
1073            while (!curr.isEmpty())
1074            {
1075                next.clear();
1076
1077                //          for(natom=curr.nextSetBit(0); natom>=0; natom=curr.nextSetBit(natom+1))
1078                for (natom = curr.nextBit(-1); natom != curr.endBit();
1079                        natom = curr.nextBit(natom))
1080                {
1081                    atom1 = getAtom(natom);
1082
1083                    BondIterator bit = atom1.bondIterator();
1084
1085                    while (bit.hasNext())
1086                    {
1087                        bond = bit.nextBond();
1088
1089                        if (!used.bitIsOn(bond.getNbrAtomIdx(atom1)) &&
1090                                !curr.bitIsOn(bond.getNbrAtomIdx(atom1)))
1091                        {
1092                            if (!(bond.getNbrAtom(atom1)).isHydrogen())
1093                            {
1094                                next.setBitOn(bond.getNbrAtomIdx(atom1));
1095                            }
1096                        }
1097                    }
1098                }
1099
1100                used.set(next);
1101                curr.set(next);
1102                gtdcount++;
1103            }
1104
1105            gtd[atom.getIdx() - 1] = gtdcount;
1106        }
1107
1108        return true;
1109    }
1110
1111    /**
1112     *  Sets the hybridizationPerceived attribute of the <tt>JOEMol</tt> object
1113     */
1114    public void setHybridizationPerceived()
1115    {
1116        setFlag(JOE_HYBRID_MOL);
1117    }
1118
1119    /**
1120     *  Sets the hydrogensAdded attribute of the <tt>JOEMol</tt> object
1121     */
1122    public void setHydrogensAdded()
1123    {
1124        setFlag(JOE_H_ADDED_MOL);
1125    }
1126
1127    /**
1128     *  Sets the implicitValencePerceived attribute of the <tt>JOEMol</tt> object
1129     */
1130    public void setImplicitValencePerceived()
1131    {
1132        setFlag(JOE_IMPVAL_MOL);
1133    }
1134
1135    /**
1136     *  Sets the inputType attribute of the <tt>JOEMol</tt> object
1137     *
1138     * @param  type  The new inputType value
1139     */
1140    public void setInputType(IOType type)
1141    {
1142        _itype = type;
1143    }
1144
1145    /**
1146     *  Sets the kekulePerceived attribute of the <tt>JOEMol</tt> object
1147     */
1148    public void setKekulePerceived()
1149    {
1150        setFlag(JOE_KEKULE_MOL);
1151    }
1152
1153    /**
1154     *  Gets the mod attribute of the <tt>JOEMol</tt> object
1155     *
1156     * @return    The mod value
1157     */
1158    public int getMod()
1159    {
1160        return (_mod);
1161    }
1162
1163    /**
1164     *  Gets the title attribute of the <tt>JOEMol</tt> object.
1165     *
1166     * @return    The title value
1167     */
1168    public final String getTitle()
1169    {
1170        return _title;
1171    }
1172
1173    /**
1174     *  Gets the inputType attribute of the <tt>JOEMol</tt> object
1175     *
1176     * @return    The inputType value
1177     */
1178    public IOType getInputType()
1179    {
1180        return (_itype);
1181    }
1182
1183    /**
1184     * Gets standard molar mass given by IUPAC atomic masses.
1185     *
1186     * @return    The molWt value
1187     */
1188    public double getMolWt()
1189    {
1190        double molwt = 0.0f;
1191        JOEAtom atom;
1192        AtomIterator ait = this.atomIterator();
1193
1194        while (ait.hasNext())
1195        {
1196            atom = ait.nextAtom();
1197            molwt += atom.getAtomicMass();
1198        }
1199
1200        return molwt;
1201    }
1202
1203    /**
1204     *  Sets the outputType attribute of the <tt>JOEMol</tt> object
1205     *
1206     * @param  type  The new outputType value
1207     */
1208    public void setOutputType(IOType type)
1209    {
1210        _otype = type;
1211    }
1212
1213    /**
1214     *  Gets the outputType attribute of the <tt>JOEMol</tt> object
1215     *
1216     * @return    The outputType value
1217     */
1218    public IOType getOutputType()
1219    {
1220        return (_otype);
1221    }
1222
1223    /**
1224     *  Sets the partialChargesPerceived attribute of the <tt>JOEMol</tt> object
1225     */
1226    public void setPartialChargesPerceived()
1227    {
1228        setFlag(JOE_PCHARGE_MOL);
1229    }
1230
1231    /**
1232     *  Gets the residue attribute of the JOEMol object
1233     *
1234     * @param  idx  Description of the Parameter
1235     * @return      The residue value
1236     */
1237    public JOEResidue getResidue(int idx)
1238    {
1239        if ((idx < 0) || (idx >= numResidues()))
1240        {
1241            throw new IndexOutOfBoundsException("Residue with index " + idx +
1242                " does'nt exist.");
1243
1244            //return null;
1245        }
1246
1247        return ((JOEResidue) _residue.get(idx));
1248    }
1249
1250    /**
1251     *  Sets the ringAtomsAndBondsPerceived attribute of the <tt>JOEMol</tt>
1252     *  object
1253     */
1254    public void setRingAtomsAndBondsPerceived()
1255    {
1256        setFlag(JOE_RINGFLAGS_MOL);
1257    }
1258
1259    /**
1260     * Gets iterator for the Smallest Set of Smallest Rings (SSSR).
1261     *
1262     * <blockquote><pre>
1263     * RingIterator rit = mol.getRingIterator();
1264     * JOERing ring;
1265     * while(rit.hasNext())
1266     * {
1267     *   ring = rit.nextRing();
1268     *
1269     * }
1270     * </pre></blockquote>
1271     *
1272     * @return     The ring iterator
1273     * @see #getSSSR()
1274     * @see #findSSSR()
1275     * @see #atomIterator()
1276     * @see #bondIterator()
1277     * @see #conformerIterator()
1278     * @see #genericDataIterator
1279     * @see #nativeValueIterator()
1280     * @see RingIterator
1281     * @cite fig96
1282     */
1283    public RingIterator getRingIterator()
1284    {
1285        return new RingIterator(getSSSR());
1286    }
1287
1288    /**
1289     * Gets the Smallest Set of Smallest Rings (SSSR).
1290     *
1291     * @return    {@link java.util.Vector} of <tt>JOERing</tt>
1292     *
1293     * @see #getRingIterator()
1294     * @see #findSSSR()
1295     * @cite fig96
1296     */
1297    public synchronized Vector getSSSR()
1298    {
1299        if (!hasSSSRPerceived())
1300        {
1301            findSSSR();
1302        }
1303
1304        JOERingData rd = (JOERingData) getData(JOEDataType.JOE_RING_DATA);
1305
1306        return (rd.getData());
1307    }
1308
1309    /**
1310     *  Sets the sSSRPerceived attribute of the <tt>JOEMol</tt> object
1311     */
1312    public void setSSSRPerceived()
1313    {
1314        setFlag(JOE_SSSR_MOL);
1315    }
1316
1317    /**
1318     *  Sets the title attribute of the <tt>JOEMol</tt> object
1319     *
1320     * @param  title  The new title value
1321     */
1322    public void setTitle(String title)
1323    {
1324        _title = title;
1325    }
1326
1327    /**
1328     *  Sets the torsion attribute of the <tt>JOEMol</tt> object
1329     *
1330     * @param  a    The new torsion value
1331     * @param  b    The new torsion value
1332     * @param  c    The new torsion value
1333     * @param  d    The new torsion value
1334     * @param  ang  The new torsion value
1335     */
1336    public void setTorsion(JOEAtom a, JOEAtom b, JOEAtom c, JOEAtom d,
1337        double ang)
1338    {
1339        int[] tor = new int[4];
1340        Vector atoms = new Vector();
1341
1342        // of type int[1]
1343        int[] itmp;
1344
1345        tor[0] = a.getCIdx();
1346        tor[1] = b.getCIdx();
1347        tor[2] = c.getCIdx();
1348        tor[3] = d.getCIdx();
1349
1350        findChildren(atoms, b.getIdx(), c.getIdx());
1351
1352        int j;
1353
1354        for (j = 0; j < atoms.size(); j++)
1355        {
1356            itmp = (int[]) atoms.get(j);
1357            itmp[0] = (itmp[0] - 1) * 3;
1358        }
1359
1360        double v1x;
1361
1362        double v1y;
1363
1364        double v1z;
1365
1366        double v2x;
1367
1368        double v2y;
1369
1370        double v2z;
1371
1372        double v3x;
1373
1374        double v3y;
1375
1376        double v3z;
1377        double c1x;
1378        double c1y;
1379        double c1z;
1380        double c2x;
1381        double c2y;
1382        double c2z;
1383        double c3x;
1384        double c3y;
1385        double c3z;
1386        double c1mag;
1387        double c2mag;
1388        double radang;
1389        double costheta;
1390        double[] m = new double[9];
1391        double x;
1392        double y;
1393        double z;
1394        double mag;
1395        double rotang;
1396        double sn;
1397        double cs;
1398        double t;
1399        double tx;
1400        double ty;
1401        double tz;
1402
1403        //calculate the torsion angle
1404        v1x = (double) (_c[tor[0]] - _c[tor[1]]);
1405        v2x = (double) (_c[tor[1]] - _c[tor[2]]);
1406        v1y = (double) (_c[tor[0] + 1] - _c[tor[1] + 1]);
1407        v2y = (double) (_c[tor[1] + 1] - _c[tor[2] + 1]);
1408        v1z = (double) (_c[tor[0] + 2] - _c[tor[1] + 2]);
1409        v2z = (double) (_c[tor[1] + 2] - _c[tor[2] + 2]);
1410        v3x = (double) (_c[tor[2]] - _c[tor[3]]);
1411        v3y = (double) (_c[tor[2] + 1] - _c[tor[3] + 1]);
1412        v3z = (double) (_c[tor[2] + 2] - _c[tor[3] + 2]);
1413
1414        c1x = (v1y * v2z) - (v1z * v2y);
1415        c2x = (v2y * v3z) - (v2z * v3y);
1416        c1y = (-v1x * v2z) + (v1z * v2x);
1417        c2y = (-v2x * v3z) + (v2z * v3x);
1418        c1z = (v1x * v2y) - (v1y * v2x);
1419        c2z = (v2x * v3y) - (v2y * v3x);
1420        c3x = (c1y * c2z) - (c1z * c2y);
1421        c3y = (-c1x * c2z) + (c1z * c2x);
1422        c3z = (c1x * c2y) - (c1y * c2x);
1423
1424        c1mag = (c1x * c1x) + (c1y * c1y) + (c1z * c1z);
1425        c2mag = (c2x * c2x) + (c2y * c2y) + (c2z * c2z);
1426
1427        if ((c1mag * c2mag) < 0.01f)
1428        {
1429            costheta = 1.0f;
1430        }
1431
1432        //avoid div by zero error
1433        else
1434        {
1435            costheta = ((c1x * c2x) + (c1y * c2y) + (c1z * c2z)) / (double) (Math.sqrt(c1mag * c2mag));
1436        }
1437
1438        if (costheta < -0.999999f)
1439        {
1440            costheta = -0.999999f;
1441        }
1442
1443        if (costheta > 0.999999f)
1444        {
1445            costheta = 0.999999f;
1446        }
1447
1448        if (((v2x * c3x) + (v2y * c3y) + (v2z * c3z)) > 0.0f)
1449        {
1450            radang = (double) -Math.acos(costheta);
1451        }
1452        else
1453        {
1454            radang = (double) Math.acos(costheta);
1455        }
1456
1457        //
1458        // now we have the torsion angle (radang) - set up the rot matrix
1459        //
1460        //find the difference between current and requested
1461        rotang = ang - radang;
1462
1463        sn = (double) Math.sin(rotang);
1464        cs = (double) Math.cos(rotang);
1465        t = 1 - cs;
1466
1467        //normalize the rotation vector
1468        mag = (double) Math.sqrt((v2x * v2x) + (v2y * v2y) + (v2z * v2z));
1469        x = v2x / mag;
1470        y = v2y / mag;
1471        z = v2z / mag;
1472
1473        //set up the rotation matrix
1474        m[0] = (t * x * x) + cs;
1475        m[1] = (t * x * y) + (sn * z);
1476        m[2] = (t * x * z) - (sn * y);
1477        m[3] = (t * x * y) - (sn * z);
1478        m[4] = (t * y * y) + cs;
1479        m[5] = (t * y * z) + (sn * x);
1480        m[6] = (t * x * z) + (sn * y);
1481        m[7] = (t * y * z) - (sn * x);
1482        m[8] = (t * z * z) + cs;
1483
1484        //
1485        //now the matrix is set - time to rotate the atoms
1486        //
1487        tx = _c[tor[1]];
1488        ty = _c[tor[1] + 1];
1489        tz = _c[tor[1] + 2];
1490
1491        for (int i = 0; i < atoms.size(); i++)
1492        {
1493            j = ((int[]) atoms.get(i))[0];
1494            _c[j] -= tx;
1495            _c[j + 1] -= ty;
1496            _c[j + 2] -= tz;
1497            x = (_c[j] * m[0]) + (_c[j + 1] * m[1]) + (_c[j + 2] * m[2]);
1498            y = (_c[j] * m[3]) + (_c[j + 1] * m[4]) + (_c[j + 2] * m[5]);
1499            z = (_c[j] * m[6]) + (_c[j + 1] * m[7]) + (_c[j + 2] * m[8]);
1500            _c[j] = x;
1501            _c[j + 1] = y;
1502            _c[j + 2] = z;
1503            _c[j] += tx;
1504            _c[j + 1] += ty;
1505            _c[j + 2] += tz;
1506        }
1507    }
1508
1509    /**
1510     *  Gets the torsion attribute of the <tt>JOEMol</tt> object
1511     *
1512     * @param  a  Description of the Parameter
1513     * @param  b  Description of the Parameter
1514     * @param  c  Description of the Parameter
1515     * @param  d  Description of the Parameter
1516     * @return    The torsion value
1517     */
1518    public double getTorsion(int a, int b, int c, int d)
1519    {
1520        return (XYZVector.calcTorsionAngle(((JOEAtom) _atom.get(a - 1)).getVector(),
1521            ((JOEAtom) _atom.get(b - 1)).getVector(),
1522            ((JOEAtom) _atom.get(c - 1)).getVector(),
1523            ((JOEAtom) _atom.get(d - 1)).getVector()));
1524    }
1525
1526    /**
1527     *  Gets the torsion attribute of the <tt>JOEMol</tt> object
1528     *
1529     * @param  a  Description of the Parameter
1530     * @param  b  Description of the Parameter
1531     * @param  c  Description of the Parameter
1532     * @param  d  Description of the Parameter
1533     * @return    The torsion value
1534     */
1535    public double getTorsion(JOEAtom a, JOEAtom b, JOEAtom c, JOEAtom d)
1536    {
1537        return (XYZVector.calcTorsionAngle(a.getVector(), b.getVector(),
1538            c.getVector(), d.getVector()));
1539    }
1540
1541    /*-------------------------------------------------------------------------*
1542     * public methods
1543     *------------------------------------------------------------------------- */
1544
1545    /**
1546     * Adds (cloned) atom to the <tt>JOEMol</tt>.
1547     * Also checks for any bonds that should be made to the new atom.
1548     * Atoms starts with the index 1, which is a difference to bonds
1549     * which starts with the bond index 0.
1550     *
1551     * <p>
1552     * It's recommended calling the <tt>beginModify()</tt> method before the
1553     * first atom will be added and calling the <tt>endModify()</tt> method
1554     * after the last atom has been added. This causes, that the coordinates
1555     * of the atoms will also be stored in a coordinate array in the molecule.
1556     *
1557     * @param  atom  The <tt>JOEAtom</tt> to add, which will be deep cloned.
1558     * @return       <tt>true</tt> if successfull
1559     *
1560     * @see #addBond(int, int, int)
1561     * @see #addBond(int, int, int, int)
1562     * @see #addBond(int, int, int, int, int)
1563     * @see #addBond(JOEBond)
1564     * @see #beginModify()
1565     * @see #endModify()
1566     * @see #endModify(boolean)
1567     */
1568    public synchronized boolean addAtom(JOEAtom atom)
1569    {
1570        beginModify();
1571
1572        JOEAtom joeatom;
1573
1574        // = createAtom();
1575        joeatom = (JOEAtom) atom.clone();
1576        joeatom.setIdx(_natoms + 1);
1577
1578        //System.out.println("add idx:"+joeatom.getIdx());
1579        //System.out.println("add cidx:"+joeatom.getCIdx());
1580        joeatom.setParent(this);
1581
1582        //    if (_atom.size()==0 || _natoms+1 >= _atom.size())
1583        //    {
1584        //      // resize atom vector and fill new elements (automatically) with null
1585        //      _atom.setSize(_natoms+JOE_ATOM_INCREMENT);
1586        //      //for (int j =(_natoms+1); j<_atom.size();j++) _atom.set(j, null);
1587        //    }
1588        //    _atom.set(_natoms, oeatom);
1589        _atom.add(joeatom);
1590
1591        if (logger.isDebugEnabled())
1592        {
1593            logger.debug("Add atom " + _atom.get(_natoms) + " with index " +
1594                joeatom.getIdx());
1595        }
1596
1597        _natoms++;
1598
1599        if (hasData(JOEDataType.JOE_VIRTUAL_BOND_DATA))
1600        {
1601            /*add bonds that have been queued        */
1602            JOEVirtualBond vb;
1603
1604            GenericDataIterator gdit = genericDataIterator();
1605            JOEGenericData genericData;
1606            Vector verase = new Vector();
1607
1608            //JOEGenericData
1609            while (gdit.hasNext())
1610            {
1611                genericData = gdit.nextGenericData();
1612
1613                if (genericData.getDataType().equals(JOEDataType.JOE_VIRTUAL_BOND_DATA))
1614                {
1615                    vb = (JOEVirtualBond) genericData;
1616
1617                    if ((vb.getBgn() > _natoms) || (vb.getEnd() > _natoms))
1618                    {
1619                        continue;
1620                    }
1621
1622                    if ((joeatom.getIdx() == vb.getBgn()) ||
1623                            (joeatom.getIdx() == vb.getEnd()))
1624                    {
1625                        addBond(vb.getBgn(), vb.getEnd(), vb.getOrder(),
1626                            vb.getStereo());
1627                        verase.add(genericData);
1628                    }
1629                }
1630            }
1631
1632            if (verase.size() != 0)
1633            {
1634                deleteData(verase);
1635            }
1636        }
1637
1638        //System.out.println("end modify");
1639        endModify();
1640
1641        return true;
1642    }
1643
1644    /**
1645     * Adds a bond to the <tt>JOEMol</tt>.
1646     * Bonds starts with the index 0, which is a difference to atoms
1647     * which starts with the atom index 1.
1648     *
1649     * @param  first      The start atom index (atoms begins with index 1)
1650     * @param  second     The end atom index (atoms begins with index 1)
1651     * @param  order      The bond order
1652     * @return         <tt>true</tt> if successfull
1653     *
1654     * @see #addAtom(JOEAtom)
1655     * @see #addBond(int, int, int, int)
1656     * @see #addBond(int, int, int, int, int)
1657     * @see #addBond(JOEBond)
1658     * @see #connectTheDots()
1659     */
1660    public boolean addBond(int first, int second, int order)
1661    {
1662        return addBond(first, second, order, 0, -1);
1663    }
1664
1665    /**
1666     * Adds a bond to the <tt>JOEMol</tt>.
1667     * Bonds starts with the index 0, which is a difference to atoms
1668     * which starts with the atom index 1.
1669     *
1670     * @param  first      The start atom index (atoms begins with index 1)
1671     * @param  second     The end atom index (atoms begins with index 1)
1672     * @param  order      The bond order
1673     * @param  flags     The stereo flag
1674     * @return            <tt>true</tt> if successfull
1675     *
1676     * @see #addBond(int, int, int)
1677     * @see #addBond(int, int, int, int, int)
1678     * @see #addBond(JOEBond)
1679     * @see #connectTheDots()
1680     */
1681    public boolean addBond(int first, int second, int order, int flags)
1682    {
1683        return addBond(first, second, order, flags, -1);
1684    }
1685
1686    /**
1687     * Adds a bond to the <tt>JOEMol</tt>.
1688     * Bonds starts with the index 0, which is a difference to atoms
1689     * which starts with the atom index 1.
1690     *
1691     * @param  first      The start atom index (atoms begins with index 1)
1692     * @param  second     The end atom index (atoms begins with index 1)
1693     * @param  order      The bond order
1694     * @param  stereo     The stereo flag
1695     * @param  insertpos  The position at which the bond should be inserted
1696     * @return            <tt>true</tt> if successfull
1697     *
1698     * @see #addAtom(JOEAtom)
1699     * @see #addBond(int, int, int)
1700     * @see #addBond(int, int, int, int)
1701     * @see #addBond(JOEBond)
1702     * @see #connectTheDots()
1703     */
1704    public synchronized boolean addBond(int first, int second, int order,
1705        int stereo, int insertpos)
1706    {
1707        beginModify();
1708
1709        if (logger.isDebugEnabled())
1710        {
1711            logger.debug("addBond:" + first + " " + second + " " + order + " " +
1712                stereo + " " + insertpos);
1713        }
1714
1715        if (first == second)
1716        {
1717            logger.error("'Loop-Bond' is not allowed for atom " + first);
1718
1719            return false;
1720        }
1721
1722        if ((first <= numAtoms()) && (second <= numAtoms()))
1723        {
1724            //atoms exist
1725            JOEBond bond = createBond();
1726
1727            if (bond == null)
1728            {
1729                endModify();
1730
1731                return false;
1732            }
1733
1734            JOEAtom bgn;
1735
1736            JOEAtom end;
1737            bgn = getAtom(first);
1738            end = getAtom(second);
1739
1740            if ((bgn == null) || (end == null))
1741            {
1742                //        throw new Exception("Unable to add bond - invalid atom index");
1743                logger.error("Unable to add bond - invalid atom index");
1744
1745                return false;
1746            }
1747
1748            bond.set(_nbonds, bgn, end, order, stereo);
1749            bond.setParent(this);
1750
1751            //set aromatic flags if it has the appropriate order
1752            if (order == 5)
1753            {