-
Notifications
You must be signed in to change notification settings - Fork 1
/
BondTools.java
619 lines (576 loc) · 23.3 KB
/
BondTools.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
/* $Revision$ $Author$ $Date$
*
* Copyright (C) 2002-2003 The Jmol Project
* Copyright (C) 2003-2007 The Chemistry Development Kit (CDK) project
*
* Contact: cdk-devel@lists.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
* All we ask is that proper credit is given for our work, which includes
* - but is not limited to - adding the above copyright notice to the beginning
* of your source code files, and to any copyright notice that you may distribute
* with programs based on this work.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.openscience.cdk.geometry;
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.graph.invariant.MorganNumbersTools;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IBond;
import javax.vecmath.Point2d;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
/**
* A set of static utility classes for geometric calculations on {@link IBond}s.
* The methods for detecting stereo configurations are described in CDK news, vol 2, p. 64 - 66.
*
* @author shk3
* @cdk.created 2005-08-04
* @cdk.module standard
* @cdk.githash
*/
@TestClass("org.openscience.cdk.geometry.BondToolsTest")
public class BondTools {
// FIXME: class JavaDoc should use {@cdk.cite BLA} for the CDK News article
/**
* Tells if a certain bond is center of a valid double bond configuration.
*
* @param container The atomcontainer.
* @param bond The bond.
* @return true=is a potential configuration, false=is not.
*/
@TestMethod("testIsValidDoubleBondConfiguration_IAtomContainer_IBond")
public static boolean isValidDoubleBondConfiguration(IAtomContainer container, IBond bond) {
//org.openscience.cdk.interfaces.IAtom[] atoms = bond.getAtoms();
List<IAtom> connectedAtoms = container.getConnectedAtomsList(bond.getAtom(0));
IAtom from = null;
for (IAtom connectedAtom : connectedAtoms) {
if (connectedAtom != bond.getAtom(1)) {
from = connectedAtom;
}
}
boolean[] array = new boolean[container.getBondCount()];
for (int i = 0; i < array.length; i++) {
array[i] = true;
}
if (isStartOfDoubleBond(container, bond.getAtom(0), from, array) && isEndOfDoubleBond(container, bond.getAtom(1), bond.getAtom(0), array) && !bond.getFlag(CDKConstants.ISAROMATIC)) {
return (true);
} else {
return (false);
}
}
/**
* Says if two atoms are in cis or trans position around a double bond.
* The atoms have to be given to the method like this: firstOuterAtom - firstInnerAtom = secondInnterAtom - secondOuterAtom
*
* @param firstOuterAtom See above.
* @param firstInnerAtom See above.
* @param secondInnerAtom See above.
* @param secondOuterAtom See above.
* @param ac The atom container the atoms are in.
* @return true=trans, false=cis.
* @exception CDKException The atoms are not in a double bond configuration (no double bond in the middle, same atoms on one side)
*/
@TestMethod("testIsCisTrans_IAtom_IAtom_IAtom_IAtom_IAtomContainer")
public static boolean isCisTrans(IAtom firstOuterAtom, IAtom firstInnerAtom, IAtom secondInnerAtom, IAtom secondOuterAtom, IAtomContainer ac) throws CDKException {
if (!isValidDoubleBondConfiguration(ac, ac.getBond(firstInnerAtom, secondInnerAtom))) {
throw new CDKException("There is no valid double bond configuration between your inner atoms!");
}
boolean firstDirection = isLeft(firstOuterAtom, firstInnerAtom, secondInnerAtom);
boolean secondDirection = isLeft(secondOuterAtom, secondInnerAtom, firstInnerAtom);
return firstDirection == secondDirection;
}
/**
* Says if an atom is on the left side of a another atom seen from a certain
* atom or not
*
* @param whereIs The atom the position of which is returned
* @param viewFrom The atom from which to look
* @param viewTo The atom to which to look
* @return true=is left, false = is not
*/
@TestMethod("testIsLeft_IAtom_IAtom_IAtom")
public static boolean isLeft(IAtom whereIs, IAtom viewFrom, IAtom viewTo) {
double angle = giveAngleBothMethods(viewFrom, viewTo, whereIs, false);
if (angle < 0) {
return (false);
} else {
return (true);
}
}
/**
* Returns true if the two atoms are within the distance fudge
* factor of each other.
*
* @param atom1 Description of Parameter
* @param atom2 Description of Parameter
* @param distanceFudgeFactor Description of Parameter
* @return Description of the Returned Value
* @cdk.keyword join-the-dots
* @cdk.keyword bond creation
*/
@TestMethod("testCloseEnoughToBond_IAtom_IAtom_double")
public static boolean closeEnoughToBond(IAtom atom1, IAtom atom2, double distanceFudgeFactor) {
if (atom1 != atom2) {
double distanceBetweenAtoms = atom1.getPoint3d().distance(atom2.getPoint3d());
double bondingDistance = atom1.getCovalentRadius() + atom2.getCovalentRadius();
if (distanceBetweenAtoms <= (distanceFudgeFactor * bondingDistance)) {
return true;
}
}
return false;
}
/**
* Gives the angle between two lines starting at atom from and going to to1
* and to2. If bool=false the angle starts from the middle line and goes from
* 0 to PI or 0 to -PI if the to2 is on the left or right side of the line. If
* bool=true the angle goes from 0 to 2PI.
*
* @param from the atom to view from.
* @param to1 first direction to look in.
* @param to2 second direction to look in.
* @param bool true=angle is 0 to 2PI, false=angel is -PI to PI.
* @return The angle in rad.
*/
@TestMethod("testGiveAngleBothMethods_IAtom_IAtom_IAtom_boolean")
public static double giveAngleBothMethods(IAtom from, IAtom to1, IAtom to2, boolean bool) {
return giveAngleBothMethods(from.getPoint2d(), to1.getPoint2d(), to2.getPoint2d(),bool);
}
@TestMethod("testGiveAngleBothMethods_Point2d_Point2d_Point2d_boolean")
public static double giveAngleBothMethods(Point2d from, Point2d to1, Point2d to2, boolean bool) {
double[] A = new double[2];
from.get(A);
double[] B = new double[2];
to1.get(B);
double[] C = new double[2];
to2.get(C);
double angle1 = Math.atan2((B[1] - A[1]), (B[0] - A[0]));
double angle2 = Math.atan2((C[1] - A[1]), (C[0] - A[0]));
double angle = angle2 - angle1;
if (angle2 < 0 && angle1 > 0 && angle2 < -(Math.PI / 2)) {
angle = Math.PI + angle2 + Math.PI - angle1;
}
if (angle2 > 0 && angle1 < 0 && angle1 < -(Math.PI / 2)) {
angle = -Math.PI + angle2 - Math.PI - angle1;
}
if (bool && angle < 0) {
return (2 * Math.PI + angle);
} else {
return (angle);
}
}
/**
* Says if an atom is the end of a double bond configuration
*
* @param atom The atom which is the end of configuration
* @param container The atomContainer the atom is in
* @param parent The atom we came from
* @param doubleBondConfiguration The array indicating where double bond
* configurations are specified (this method ensures that there is
* actually the possibility of a double bond configuration)
* @return false=is not end of configuration, true=is
*/
private static boolean isEndOfDoubleBond(IAtomContainer container, IAtom atom, IAtom parent, boolean[] doubleBondConfiguration) {
if (container.getBondNumber(atom, parent) == -1 || doubleBondConfiguration.length <= container.getBondNumber(atom, parent) || !doubleBondConfiguration[container.getBondNumber(atom, parent)]) {
return false;
}
int hcount;
if (atom.getHydrogenCount() == CDKConstants.UNSET) hcount = 0;
else hcount = atom.getHydrogenCount();
int lengthAtom = container.getConnectedAtomsList(atom).size() + hcount;
if (parent.getHydrogenCount() == CDKConstants.UNSET) hcount = 0;
else hcount = parent.getHydrogenCount();
int lengthParent = container.getConnectedAtomsList(parent).size() + hcount;
if (container.getBond(atom, parent) != null) {
if (container.getBond(atom, parent).getOrder() == CDKConstants.BONDORDER_DOUBLE && (lengthAtom == 3 || (lengthAtom == 2 && atom.getSymbol().equals("N"))) && (lengthParent == 3 || (lengthParent == 2 && parent.getSymbol().equals("N")))) {
List<IAtom> atoms = container.getConnectedAtomsList(atom);
IAtom one = null;
IAtom two = null;
for (IAtom conAtom : atoms) {
if (conAtom != parent && one == null) {
one = conAtom;
} else if (conAtom != parent && one != null) {
two = conAtom;
}
}
String[] morgannumbers = MorganNumbersTools.getMorganNumbersWithElementSymbol(container);
if ((one != null && two == null && atom.getSymbol().equals("N") && Math.abs(giveAngleBothMethods(parent, atom, one, true)) > Math.PI / 10) || (!atom.getSymbol().equals("N") && one != null && two != null && !morgannumbers[container.getAtomNumber(one)].equals(morgannumbers[container.getAtomNumber(two)]))) {
return (true);
} else {
return (false);
}
}
}
return (false);
}
/**
* Says if an atom is the start of a double bond configuration
*
* @param a The atom which is the start of configuration
* @param container The atomContainer the atom is in
* @param parent The atom we came from
* @param doubleBondConfiguration The array indicating where double bond
* configurations are specified (this method ensures that there is
* actually the possibility of a double bond configuration)
* @return false=is not start of configuration, true=is
*/
private static boolean isStartOfDoubleBond(IAtomContainer container, IAtom a, IAtom parent, boolean[] doubleBondConfiguration) {
int hcount;
if (a.getHydrogenCount() == CDKConstants.UNSET) hcount = 0;
else hcount = a.getHydrogenCount();
int lengthAtom = container.getConnectedAtomsList(a).size() + hcount;
if (lengthAtom != 3 && (lengthAtom != 2 && !(a.getSymbol().equals("N")))) {
return (false);
}
List<IAtom> atoms = container.getConnectedAtomsList(a);
IAtom one = null;
IAtom two = null;
boolean doubleBond = false;
IAtom nextAtom = null;
for (IAtom atom : atoms) {
if (atom != parent && container.getBond(atom, a).getOrder() == CDKConstants.BONDORDER_DOUBLE && isEndOfDoubleBond(container, atom, a, doubleBondConfiguration)) {
doubleBond = true;
nextAtom = atom;
}
if (atom != nextAtom && one == null) {
one = atom;
} else if (atom != nextAtom && one != null) {
two = atom;
}
}
String[] morgannumbers = MorganNumbersTools.getMorganNumbersWithElementSymbol(container);
if (one != null && ((!a.getSymbol().equals("N") && two != null && !morgannumbers[container.getAtomNumber(one)].equals(morgannumbers[container.getAtomNumber(two)]) && doubleBond && doubleBondConfiguration[container.getBondNumber(a, nextAtom)]) || (doubleBond && a.getSymbol().equals("N") && Math.abs(giveAngleBothMethods(nextAtom, a, parent, true)) > Math.PI / 10))) {
return (true);
} else {
return (false);
}
}
/**
* Says if an atom as a center of a tetrahedral chirality.
* This method uses wedge bonds. 3D coordinates are not taken into account. If there
* are no wedge bonds around a potential stereo center, it will not be found.
*
*@param atom The atom which is the center
*@param container The atomContainer the atom is in
*@return 0=is not tetrahedral;>1 is a certain depiction of
* tetrahedrality (evaluated in parse chain)
*/
@TestMethod("testIsTetrahedral_IAtomContainer_IAtom_boolean")
public static int isTetrahedral(IAtomContainer container, IAtom atom, boolean strict)
{
List<IAtom> atoms = container.getConnectedAtomsList(atom);
if (atoms.size() != 4)
{
return (0);
}
java.util.List<IBond> bonds = container.getConnectedBondsList(atom);
int up = 0;
int down = 0;
for (IBond bond : bonds) {
if (bond.getStereo() == CDKConstants.STEREO_BOND_NONE || bond.getStereo() == CDKConstants.STEREO_BOND_UNDEFINED) {
}
if (bond.getStereo() == CDKConstants.STEREO_BOND_UP) {
up++;
}
if (bond.getStereo() == CDKConstants.STEREO_BOND_DOWN) {
down++;
}
}
if (up == 1 && down == 1)
{
return 1;
}
if (up == 2 && down == 2)
{
if (stereosAreOpposite(container, atom))
{
return 2;
}
return 0;
}
if (up == 1 && down == 0 && !strict)
{
return 3;
}
if (down == 1 && up == 0 && !strict)
{
return 4;
}
if (down == 2 && up == 1 && !strict)
{
return 5;
}
if (down == 1 && up == 2 && !strict)
{
return 6;
}
return 0;
}
/**
* Says if an atom as a center of a trigonal-bipyramidal or actahedral
* chirality. This method uses wedge bonds. 3D coordinates are not taken into account. If there
* are no wedge bonds around a potential stereo center, it will not be found.
*
*@param atom The atom which is the center
*@param container The atomContainer the atom is in
*@return true=is square planar, false=is not
*/
@TestMethod("testIsTrigonalBipyramidalOrOctahedral_IAtomContainer_IAtom")
public static int isTrigonalBipyramidalOrOctahedral(IAtomContainer container, IAtom atom)
{
List<IAtom> atoms = container.getConnectedAtomsList(atom);
if (atoms.size() < 5 || atoms.size() > 6)
{
return (0);
}
java.util.List<IBond> bonds = container.getConnectedBondsList(atom);
int up = 0;
int down = 0;
for (IBond bond : bonds) {
if (bond.getStereo() == CDKConstants.STEREO_BOND_UNDEFINED || bond.getStereo() == CDKConstants.STEREO_BOND_NONE) {
}
if (bond.getStereo() == CDKConstants.STEREO_BOND_UP) {
up++;
}
if (bond.getStereo() == CDKConstants.STEREO_BOND_DOWN) {
down++;
}
}
if (up == 1 && down == 1)
{
if(atoms.size()==5)
return 1;
else
return 2;
}
return 0;
}
/**
* Says if an atom as a center of any valid stereo configuration or not.
* This method uses wedge bonds. 3D coordinates are not taken into account. If there
* are no wedge bonds around a potential stereo center, it will not be found.
*
*@param stereoAtom The atom which is the center
*@param container The atomContainer the atom is in
*@return true=is a stereo atom, false=is not
*/
@TestMethod("testIsStereo_IAtomContainer_IAtom")
public static boolean isStereo(IAtomContainer container, IAtom stereoAtom)
{
List<IAtom> atoms = container.getConnectedAtomsList(stereoAtom);
if (atoms.size() < 4 || atoms.size() > 6)
{
return (false);
}
List<IBond> bonds = container.getConnectedBondsList(stereoAtom);
int stereo = 0;
for (IBond bond : bonds) {
if (bond.getStereo() != 0) {
stereo++;
}
}
if (stereo == 0)
{
return false;
}
int differentAtoms = 0;
for (int i = 0; i < atoms.size(); i++)
{
boolean isDifferent = true;
for (int k = 0; k < i; k++)
{
if (atoms.get(i).getSymbol().equals(atoms.get(k).getSymbol()))
{
isDifferent = false;
break;
}
}
if (isDifferent)
{
differentAtoms++;
}
}
if (differentAtoms != atoms.size())
{
long[] morgannumbers = MorganNumbersTools.getMorganNumbers(container);
List<String> differentSymbols = new ArrayList<String>();
for (IAtom atom : atoms) {
if (!differentSymbols.contains(atom.getSymbol())) {
differentSymbols.add(atom.getSymbol());
}
}
int[] onlyRelevantIfTwo = new int[2];
if (differentSymbols.size() == 2)
{
for (IAtom atom : atoms) {
if (differentSymbols.indexOf(atom.getSymbol()) == 0) {
onlyRelevantIfTwo[0]++;
} else {
onlyRelevantIfTwo[1]++;
}
}
}
boolean[] symbolsWithDifferentMorganNumbers = new boolean[differentSymbols.size()];
List<Long>[] symbolsMorganNumbers = new ArrayList[symbolsWithDifferentMorganNumbers.length];
for (int i = 0; i < symbolsWithDifferentMorganNumbers.length; i++)
{
symbolsWithDifferentMorganNumbers[i] = true;
symbolsMorganNumbers[i] = new ArrayList<Long>();
}
for (IAtom atom : atoms) {
int elementNumber = differentSymbols.indexOf(atom.getSymbol());
if (symbolsMorganNumbers[elementNumber].contains(morgannumbers[container.getAtomNumber(atom)])) {
symbolsWithDifferentMorganNumbers[elementNumber] = false;
} else {
symbolsMorganNumbers[elementNumber].add(morgannumbers[container.getAtomNumber(atom)]);
}
}
int numberOfSymbolsWithDifferentMorganNumbers = 0;
for (boolean symbolWithDifferentMorganNumber : symbolsWithDifferentMorganNumbers) {
if (symbolWithDifferentMorganNumber) {
numberOfSymbolsWithDifferentMorganNumbers++;
}
}
if (numberOfSymbolsWithDifferentMorganNumbers != differentSymbols.size())
{
if ((atoms.size() == 5 || atoms.size() == 6) && (numberOfSymbolsWithDifferentMorganNumbers + differentAtoms > 2 || (differentAtoms == 2 && onlyRelevantIfTwo[0] > 1 && onlyRelevantIfTwo[1] > 1)))
{
return (true);
}
return isSquarePlanar(container, stereoAtom) && (numberOfSymbolsWithDifferentMorganNumbers + differentAtoms > 2 || (differentAtoms == 2 && onlyRelevantIfTwo[0] > 1 && onlyRelevantIfTwo[1] > 1));
}
}
return (true);
}
/**
* Says if an atom as a center of a square planar chirality.
* This method uses wedge bonds. 3D coordinates are not taken into account. If there
* are no wedge bonds around a potential stereo center, it will not be found.
*
*@param atom The atom which is the center
*@param container The atomContainer the atom is in
*@return true=is square planar, false=is not
*/
@TestMethod("testIsSquarePlanar_IAtomContainer_IAtom")
public static boolean isSquarePlanar(IAtomContainer container, IAtom atom)
{
List<IAtom> atoms = container.getConnectedAtomsList(atom);
if (atoms.size() != 4)
{
return (false);
}
List<IBond> bonds = container.getConnectedBondsList(atom);
int up = 0;
int down = 0;
for (IBond bond : bonds) {
if (bond.getStereo() == CDKConstants.STEREO_BOND_UNDEFINED || bond.getStereo() == CDKConstants.STEREO_BOND_NONE) {
}
if (bond.getStereo() == CDKConstants.STEREO_BOND_UP) {
up++;
}
if (bond.getStereo() == CDKConstants.STEREO_BOND_DOWN) {
down++;
}
}
return up == 2 && down == 2 && !stereosAreOpposite(container, atom);
}
/**
* Says if of four atoms connected two one atom the up and down bonds are
* opposite or not, i. e.if it's tetrehedral or square planar. The method
* does not check if there are four atoms and if two or up and two are down
*
*@param atom The atom which is the center
*@param container The atomContainer the atom is in
*@return true=are opposite, false=are not
*/
@TestMethod("testStereosAreOpposite_IAtomContainer_IAtom")
public static boolean stereosAreOpposite(IAtomContainer container, IAtom atom)
{
List<IAtom> atoms = container.getConnectedAtomsList(atom);
TreeMap<Double, Integer> hm = new TreeMap<Double, Integer>();
for (int i = 1; i < atoms.size(); i++)
{
hm.put(giveAngle(atom, atoms.get(0), atoms.get(i)), i);
}
Object[] ohere = hm.values().toArray();
int stereoOne = container.getBond(atom, atoms.get(0)).getStereo();
int stereoOpposite = container.getBond(atom, atoms.get((Integer) ohere[1])).getStereo();
return stereoOpposite == stereoOne;
}
/**
* Calls giveAngleBothMethods with bool = true
*
*@param from the atom to view from
*@param to1 first direction to look in
*@param to2 second direction to look in
*@return The angle in rad from 0 to 2*PI
*/
@TestMethod("testGiveAngle_IAtom_IAtom_IAtom")
public static double giveAngle(IAtom from, IAtom to1, IAtom to2)
{
return (giveAngleBothMethods(from, to1, to2, true));
}
/**
* Calls giveAngleBothMethods with bool = false
*
*@param from the atom to view from
*@param to1 first direction to look in
*@param to2 second direction to look in
*@return The angle in rad from -PI to PI
*/
@TestMethod("testGiveAngleFromMiddle_IAtom_IAtom_IAtom")
public static double giveAngleFromMiddle(IAtom from, IAtom to1, IAtom to2)
{
return (giveAngleBothMethods(from, to1, to2, false));
}
@TestMethod("testMakeUpDownBonds_IAtomContainer")
public static void makeUpDownBonds(IAtomContainer container){
for (int i = 0; i < container.getAtomCount(); i++) {
IAtom a = container.getAtom(i);
if (container.getConnectedAtomsList(a).size() == 4) {
int up = 0;
int down = 0;
int hs = 0;
IAtom h = null;
for (int k = 0; k < 4; k++) {
IAtom conAtom = container.getConnectedAtomsList(a).get(k);
int stereo = container.getBond(a,conAtom).getStereo();
if (stereo == CDKConstants.STEREO_BOND_UP) {
up++;
}
else if (stereo == CDKConstants.STEREO_BOND_DOWN) {
down++;
}
else if (stereo == CDKConstants.STEREO_BOND_NONE && conAtom.getSymbol().equals("H")) {
h = conAtom;
hs++;
} else {
h = null;
}
}
if (up == 0 && down == 1 && h != null && hs == 1) {
container.getBond(a, h).setStereo(CDKConstants.STEREO_BOND_UP);
}
if (up == 1 && down == 0 && h != null && hs == 1) {
container.getBond(a, h).setStereo(CDKConstants.STEREO_BOND_DOWN);
}
}
}
}
}