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<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 {