Skip to content

Commit eaca6dc

Browse files
committed
fixed rare issue non-thread-safe default InventorTemplate list
1 parent 95ce0dd commit eaca6dc

File tree

9 files changed

+91
-70
lines changed

9 files changed

+91
-70
lines changed

src/main/java/com/actelion/research/chem/coords/InventorDefaultTemplateList.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
package com.actelion.research.chem.coords;
3636

3737
import com.actelion.research.chem.IDCodeParserWithoutCoordinateInvention;
38+
import com.actelion.research.chem.Molecule;
3839
import com.actelion.research.chem.SSSearcherWithIndex;
3940
import com.actelion.research.chem.StereoMolecule;
4041

@@ -48,23 +49,24 @@ public class InventorDefaultTemplateList extends ArrayList<InventorTemplate> {
4849
private static final String[] DEFAULT_TEMPLATE = {
4950
// fullerene
5051
"gkvt@@@@LddTTTrbTRTRTRRRRRRRRRRRRRrVRrIh\\IAaQxlY@gRHdJCJcRXlv_CfJx|A\\hRHejiLaQjTje^kSjtFcIhvXmVKMjt{lN{Kavy\\^wGjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjh@@vo@HBC@PhLN@bPhtFKCcpDbILaRhtzCIbsX\\nOO`JDbqDjSKdJeJmQjtz}Ahr[LVkMnpz\\nwGj{PBhBdBlBBBjBfBnBaBiBeBmBcBkBgBoB`bhbdblbbbjbfbnbabibebmbcbkbgbob`RhRdRlRbRjRfRnRaRiReRmRcRkRgRoR`rhrdrlrbrjrfrnrarirermrcrkrgror`JhJdJlJbJjJfJnJaJiJeJmJcJkJgJoJ`jhjdjljbjjjfjnjajijej` !BnkjyVwsVr|iQn|Q|goTZWPIJwbudnRkVYBez]siZymNJZUqNFBqZWxS~iCXVU]SeRjwrtSPAjkvXLpBAZauDPzq]PfMlecrMnkv|@\\SFD`m|mWiEoCXp`SIe_J[l|[XCbloTV`[Gc@FJGopyyoOlFQfUy^w\\Bgz|",
51-
"gcrt@@@@LdbbbbTRbRbRbRRRRRRRRRRRRVRrVQIA`HtRGAaIxZAHfShTjCIbqylQGKgqdBaXeQJeruBiPitZmFoPZLFSYbvZlVGMnsZ]vWSmr{]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUT@@[G`DAA`HTFG@QHTZCEaqxBQDfPiTZ]AdqYlNWGgpEBQXbUIerEReVhuZ]^`tYMfKUfwX]NW[jkPBhBdBlBbBjBfBnBaBiBeBmBcBkBgBoB`bhbdblbbbjbfbnbabibebmbcbkbgbob`RhRdRlRbRjRfRnRaRiReRmRcRkRgRoR`rhrdrlrbrjrfrnrarirermrcrkrgror`JhJdJlJbJjJfJnJaJiJeJmJcJkJgJoJ`jhjdjljbjjjfjnjajij` !B^cR]`]Fm]QkfljE\\p\u007FUVfgOmFXsQe_gXPyXis_wF|vUUX_XbxpzU]HUFgYViwFo~@uemc@}~T\u007FIEPioYVwr]JnM~[ZEC\\g}~o_pUfdo~irsklTLiyVJshnw^iVAsZ`_~}PYkckURH{FYMImFaRaccUlCZSHMfP",
52+
"gcrt@@@@LdbbbbTRbRbRbRRRRRRRRRRRRVRrVQIA`HtRGAaIxZAHfShTjCIbqylQGKgqdBaXeQJeruBiPitZmFoPZLFSYbvZlVGMnsZ]vWSmr{]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUT@@[G`DAA`HTFG@QHTZCEaqxBQDfPiTZ]AdqYlNWGgpEBQXbUIerEReVhuZ]^`tYMfKUfwX]NW[jkPBhBdBlBbBjBfBnBaBiBeBmBcBkBgBoB`bhbdblbbbjbfbnbabibebmbcbkbgbob`RhRdRlRbRjRfRnRaRiReRmRcRkRgRoR`rhrdrlrbrjrfrnrarirermrcrkrgror`JhJdJlJbJjJfJnJaJiJeJmJcJkJgJoJ`jhjdjljbjjjfjnjajij` !B^cR]`]Fm]QkfljE\\p?UVfgOmFXsQe_gXPyXis_wF|vUUX_XbxpzU]HUFgYViwFo~@uemc@}~T?IEPioYVwr]JnM~[ZEC\\g}~o_pUfdo~irsklTLiyVJshnw^iVAsZ`_~}PYkckURH{FYMImFaRaccUlCZSHMfP",
5253

5354
// adamantane
5455
"dml@@Dje^VGiyZjjjh@vtHSBinFU@ !BPTCTy[skMzUPF`AJbBixEZHS[Il",
5556
"dml@@DjYVvGiyZjjjh@vtHSBinFU@ !BwLo~BJ~UquhXBinZ\\ykA@F_eMrT",
56-
"dml@@LdfbbQX^fUZjjj`C[PaLJfxYT !BzxIHVc{OiJVRpprePho~]}y\u007FwLl",
57-
"deL@@DjUYkfEijjjj@MeBDpj[ad !B\u007FaA\u007FMVr[AvkKzm_jKvVbD{sk",
57+
"dml@@LdfbbQX^fUZjjj`C[PaLJfxYT !BzxIHVc{OiJVRpprePho~]}y?wLl",
58+
"deL@@DjUYkfEijjjj@MeBDpj[ad !B?aA?MVr[AvkKzm_jKvVbD{sk",
5859

5960
// cubane
60-
"dil@@LddTQRl[NX^Fjjjj@MiBDpj[a@ !BPfL@\u007Fox@M~T@\u007Fox@\u007F`C~@@",
61+
"dil@@LddTQRl[NX^Fjjjj@MiBDpj[a@ !BPfL@?ox@M~T@?ox@?`C~@@",
6162
"daL@@DjYtKJqjynjjjj@MaBDpj[` !B`bL@_gx@@Gy~@Gx@_`@",
6263
};
6364

6465
public InventorDefaultTemplateList() {
6566
SSSearcherWithIndex searcher = new SSSearcherWithIndex();
6667
for (String idcode:DEFAULT_TEMPLATE) {
6768
StereoMolecule fragment = new IDCodeParserWithoutCoordinateInvention().getCompactMolecule(idcode);
69+
fragment.ensureHelperArrays(Molecule.cHelperCIP);
6870
long[] ffp = searcher.createLongIndex(fragment);
6971
InventorTemplate template = new InventorTemplate(fragment, ffp, false);
7072
template.normalizeCoordinates();

src/main/java/com/actelion/research/chem/coords/InventorTemplate.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
import com.actelion.research.chem.StereoMolecule;
44

55
public class InventorTemplate {
6-
private StereoMolecule mFragment;
7-
private long[] mFFP;
6+
private final StereoMolecule mFragment;
7+
private final long[] mFFP;
88
private double mAVBL;
9-
private boolean mKeepAbsoluteOrientation;
9+
private final boolean mKeepAbsoluteOrientation;
1010

1111
public InventorTemplate(StereoMolecule fragment, long[] ffp, boolean keepAbsoluteOrientation) {
1212
mFragment = fragment;

src/main/java/org/openmolecules/chem/conf/gen/BaseConformer.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ public class BaseConformer extends Conformer {
3737
private static final int ESCAPE_STEPS = 4; // how often we apply this rotation trying to solve the collision
3838
private static final double MIN_ESCAPE_GAIN_PER_STEP = 0.05;
3939

40-
private short[][] mTorsion;
41-
private short[][] mFrequency;
42-
private double[][] mLikelyhood; // considering directly connected rigid fragments (frequency and collision strain)
43-
private int[] mBestTorsionIndex;
44-
private RotatableBond[] mRotatableBond;
45-
private ArrayList<TorsionSetEliminationRule> mEliminationRuleList;
46-
private Random mRandom;
40+
private final short[][] mTorsion;
41+
private final short[][] mFrequency;
42+
private final double[][] mLikelyhood; // considering directly connected rigid fragments (frequency and collision strain)
43+
private final int[] mBestTorsionIndex;
44+
private final RotatableBond[] mRotatableBond;
45+
private final ArrayList<TorsionSetEliminationRule> mEliminationRuleList;
46+
private final Random mRandom;
4747
private int mConformerCount;
4848

4949
public BaseConformer(StereoMolecule mol, RigidFragment[] rigidFragment, RotatableBond[] rotatableBond, int[] fragmentPermutation, Random random) {
@@ -116,9 +116,9 @@ public ArrayList<TorsionSetEliminationRule> getEliminationRules() {
116116
}
117117

118118
/**
119-
* Calculates a random torsion index giving torsions with higher likelyhoods
119+
* Calculates a random torsion index giving torsions with higher likelihoods
120120
* (i.e. frequencies and collision strains) a higher chance to be selected.
121-
* With a progress value of 0.0 selection likelyhoods are proportional to
121+
* With a progress value of 0.0 selection likelihoods are proportional to
122122
* the torsion frequencies. With increasing progress value the higher frequent
123123
* torsions are less and less preferred until 1.0 without any preference.
124124
* @param random

src/main/java/org/openmolecules/chem/conf/gen/RigidFragment.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,21 @@ public double getConformerLikelihood(int i) {
7777
return mConformerLikelihood[i];
7878
}
7979

80+
/**
81+
* Returns the conformer index with the lowest strain.
82+
*/
83+
public int getMostLikelyConformerIndex() {
84+
double highestLikelihood = 0;
85+
int highestIndex = -1;
86+
for (int t=0; t<mConformerLikelihood.length; t++) {
87+
if (highestLikelihood < mConformerLikelihood[t]) {
88+
highestLikelihood = mConformerLikelihood[t];
89+
highestIndex = t;
90+
}
91+
}
92+
return highestIndex;
93+
}
94+
8095
/**
8196
* Calculates a random conformer index giving conformers with lower strains
8297
* a higher chance to be selected. With a progress value of 0.0 selection

src/main/java/org/openmolecules/chem/conf/gen/RotatableBond.java

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
/**
3838
* A RotatableBond knows the two rigid fragments within a molecule
3939
* that are connected by this bond. It also knows about possible torsion
40-
* states with associated likelyhoods, which are taken from COD statistics
40+
* states with associated likelihoods, which are taken from COD statistics
4141
* and modified to account for collisions due to bulky groups in the molecule.
4242
* It knows the smaller half of the molecule and rotate the smaller half to
4343
* a given torsion angle.
@@ -47,15 +47,17 @@ public class RotatableBond {
4747
private static final short[] SIXTY_DEGREE_FREQUENCY = { 17, 17, 17, 17, 17, 17};
4848
private static final short[][] SIXTY_DEGREE_RANGE = { {-20,20},{40,80},{100,140},{160,200},{220,260},{280,320}};
4949

50-
private RigidFragment mFragment1,mFragment2;
50+
private final RigidFragment mFragment1,mFragment2;
5151
private String mTorsionID;
52-
private int mRotationCenter,mBond,mFragmentNo1,mFragmentNo2;
53-
private boolean mBondAtomsInFragmentOrder;
52+
private int mRotationCenter;
53+
private final int mBond,mFragmentNo1,mFragmentNo2;
54+
private final boolean mBondAtomsInFragmentOrder;
5455
private float mBondRelevance;
5556
private short[] mDefaultTorsion;
5657
private short[] mDefaultFrequency;
5758
private short[][] mDefaultTorsionRange;
58-
private int[] mTorsionAtom,mRearAtom,mSmallerSideAtomList;
59+
private final int[] mTorsionAtom,mRearAtom;
60+
private int[] mSmallerSideAtomList;
5961

6062
public RotatableBond(StereoMolecule mol, int bond, int[] fragmentNo, int[] disconnectedFragmentNo,
6163
int disconnectedFragmentSize, RigidFragment[] fragment) {
@@ -64,8 +66,6 @@ public RotatableBond(StereoMolecule mol, int bond, int[] fragmentNo, int[] disco
6466

6567
public RotatableBond(StereoMolecule mol, int bond, int[] fragmentNo, int[] disconnectedFragmentNo,
6668
int disconnectedFragmentSize, RigidFragment[] fragment, boolean use60degreeSteps) {
67-
if (TorsionDB.getTorsionFrequencies("gGP`@dfyjidNcGI[WQCP`<")[0]==-1)
68-
System.out.println("ERROR");
6969
mBond = bond;
7070
mTorsionAtom = new int[4];
7171
mRearAtom = new int[2];
@@ -85,10 +85,6 @@ public RotatableBond(StereoMolecule mol, int bond, int[] fragmentNo, int[] disco
8585

8686
mBondAtomsInFragmentOrder = (fragmentNo[mol.getBondAtom(0, bond)] == mFragmentNo1);
8787

88-
if (TorsionDB.getTorsionFrequencies("gGP`@dfyjidNcGI[WQCP`<")[0]==-1)
89-
System.out.println("ERROR");
90-
91-
9288
if (use60degreeSteps) {
9389
mDefaultTorsion = SIXTY_DEGREE_TORSION;
9490
mDefaultFrequency = SIXTY_DEGREE_FREQUENCY;
@@ -150,7 +146,7 @@ private void predictAtomSequence(StereoMolecule mol) {
150146
}
151147

152148
// A TorsionPrediction does not distinguish hetero atoms from carbons a positions 0 and 3.
153-
// Therefore we can treat two sp2 neighbors as equivalent when predicting torsions.
149+
// Therefore, we can treat two sp2 neighbors as equivalent when predicting torsions.
154150
if (mol.getAtomPi(mTorsionAtom[1]) == 0 && mol.getConnAtoms(mTorsionAtom[1]) == 3) {
155151
mTorsionAtom[0] = -1;
156152
}
@@ -266,13 +262,6 @@ public short[][] getDefaultTorsionRanges() {
266262
return mDefaultTorsionRange;
267263
}
268264

269-
/**
270-
* @return the likelyhood of torsion i among all torsions of this bond
271-
**
272-
public double getTorsionLikelyhood(int t) {
273-
return mLikelyhood[t];
274-
} */
275-
276265
/**
277266
* @return atoms of the smaller half of the molecule excluding anchor atom
278267
*/

src/main/java/org/openmolecules/chem/conf/gen/TorsionSetStrategy.java

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,23 @@ public abstract class TorsionSetStrategy {
7474
protected ConformerGenerator mConformerGenerator;
7575
protected RotatableBond[] mRotatableBond;
7676
protected RigidFragment[] mRigidFragment;
77-
private TorsionSetEncoder mTorsionSetEncoder;
78-
private int mFragmentCount,mCollisionCount,mMaxTotalCount,mPermutationCount,mSuccessCount;
77+
private final TorsionSetEncoder mTorsionSetEncoder;
78+
private int mCollisionCount;
79+
private int mMaxTotalCount;
80+
private int mPermutationCount;
81+
private int mSuccessCount;
7982
private boolean mUsingSecondChoices;
80-
private int[][][] mBondsBetweenFragments;
81-
private int[][] mConnFragmentNo;
82-
private int[][] mConnRotatableBondNo;
83-
private int[] mGraphFragment;
84-
private int[] mGraphBond;
85-
private int[] mGraphParent;
86-
private boolean[] mGraphFragmentHandled;
83+
private final int[][][] mBondsBetweenFragments;
84+
private final int[][] mConnFragmentNo;
85+
private final int[][] mConnRotatableBondNo;
86+
private final int[] mGraphFragment;
87+
private final int[] mGraphBond;
88+
private final int[] mGraphParent;
89+
private final boolean[] mGraphFragmentHandled;
8790
private double mLowestCollisionStrain;
88-
private UniqueList<TorsionSet> mTorsionSetList;
89-
private SortedList<TorsionSet> mSecondChoiceList;
90-
private SortedList<TorsionSetWithEliminationRuleStrain> mStrainedTorsionSetCache;
91+
private final UniqueList<TorsionSet> mTorsionSetList;
92+
private final SortedList<TorsionSet> mSecondChoiceList;
93+
private final SortedList<TorsionSetWithEliminationRuleStrain> mStrainedTorsionSetCache;
9194
private TorsionSet mBestUnacceptableTorsionSet;
9295

9396
public TorsionSetStrategy(ConformerGenerator conformerGenerator) {
@@ -97,10 +100,10 @@ public TorsionSetStrategy(ConformerGenerator conformerGenerator) {
97100
mTorsionSetEncoder = new TorsionSetEncoder(mRigidFragment, mRotatableBond);
98101

99102
// create arrays of neighbor fragment no's
100-
mFragmentCount = 0;
103+
int fragmentCount = 0;
101104
for (RotatableBond rb:mRotatableBond)
102-
mFragmentCount = Math.max(mFragmentCount, Math.max(1+rb.getFragmentNo(0), 1+rb.getFragmentNo(1)));
103-
int[] count = new int[mFragmentCount];
105+
fragmentCount = Math.max(fragmentCount, Math.max(1+rb.getFragmentNo(0), 1+rb.getFragmentNo(1)));
106+
int[] count = new int[fragmentCount];
104107
for (RotatableBond rb:mRotatableBond) {
105108
count[rb.getFragmentNo(0)]++;
106109
count[rb.getFragmentNo(1)]++;
@@ -123,14 +126,14 @@ public TorsionSetStrategy(ConformerGenerator conformerGenerator) {
123126
count[f2]++;
124127
}
125128

126-
mGraphFragment = new int[mFragmentCount];
127-
mGraphBond = new int[mFragmentCount];
128-
mGraphParent = new int[mFragmentCount];
129-
mGraphFragmentHandled = new boolean[mFragmentCount];
129+
mGraphFragment = new int[fragmentCount];
130+
mGraphBond = new int[fragmentCount];
131+
mGraphParent = new int[fragmentCount];
132+
mGraphFragmentHandled = new boolean[fragmentCount];
130133

131134
// initialize array for rotatable bond sequences from fragment pairs
132-
mBondsBetweenFragments = new int[mFragmentCount][][];
133-
for (int f1=1; f1<mFragmentCount; f1++) {
135+
mBondsBetweenFragments = new int[fragmentCount][][];
136+
for (int f1 = 1; f1<fragmentCount; f1++) {
134137
mBondsBetweenFragments[f1] = new int[f1][];
135138
for (int f2=0; f2<f1; f2++)
136139
mBondsBetweenFragments[f1][f2] = getRotatableBondsBetween(f1, f2);
@@ -484,9 +487,9 @@ protected double[] getBondAndFragmentCollisionIntensities(TorsionSet collidingTo
484487

485488

486489
/**
487-
* With best current knowledge about colliding torsion combinations
490+
* With the best current knowledge about colliding torsion combinations
488491
* and based on the individual frequencies of currently active torsions
489-
* this method returns the conformers's overall contribution to the
492+
* this method returns the conformer's overall contribution to the
490493
* total set of non colliding conformers.
491494
* @return this conformer's contribution to all conformers
492495
*/

src/main/java/org/openmolecules/chem/conf/gen/TorsionSetStrategyAdaptiveRandom.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@
3232

3333
public class TorsionSetStrategyAdaptiveRandom extends TorsionSetStrategyRandom {
3434
private static final int MAX_TRIES_FOR_NEW = 64;
35-
private boolean mStartWithMostProbable;
35+
private final boolean mStartWithMostProbable;
3636

3737
/**
3838
* This torsion set strategy produces random sets of torsion indices until a torsion set
3939
* collides. Then it updates individual torsion indices of those rotatable bonds
4040
* that connect colliding fragments.
4141
* Torsion indices are picked either by pure random or with a twisted likelyhood
42-
* towards towards those angles, that show higher frequencies in the CSD.
42+
* towards those angles, that show higher frequencies in the COD/CSD.
4343
* @param conformerGenerator
4444
* @param preferLikelyTorsions if set then more frequent torsions are picked with higher probability
4545
* @param startWithMostProbable if true then the first torsion set returned contains for every bond the most frequent torsion
@@ -53,12 +53,8 @@ public TorsionSetStrategyAdaptiveRandom(ConformerGenerator conformerGenerator, b
5353

5454
@Override
5555
public TorsionSet createTorsionSet(TorsionSet previousTorsionSet) {
56-
if (previousTorsionSet == null) {
57-
if (mStartWithMostProbable)
58-
return createTorsionSet(new int[mRotatableBond.length], new int[mRigidFragment.length]);
59-
else
60-
return super.createTorsionSet(null);
61-
}
56+
if (previousTorsionSet == null)
57+
return super.createTorsionSet(mStartWithMostProbable);
6258

6359
if (previousTorsionSet.getCollisionStrainSum() == 0.0)
6460
return super.createTorsionSet(previousTorsionSet);

src/main/java/org/openmolecules/chem/conf/gen/TorsionSetStrategyLikelySystematic.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
* @author Thomas Sander
3737
*/
3838
public class TorsionSetStrategyLikelySystematic extends TorsionSetStrategy {
39-
private int[] mCurrentMaxTorsionIndex,mCurrentMaxConformerIndex;
39+
private final int[] mCurrentMaxTorsionIndex;
40+
private final int[] mCurrentMaxConformerIndex;
4041
private TorsionSet[] mAvailableTorsionSet;
4142
private int mAvailableTorsionSetIndex;
4243

src/main/java/org/openmolecules/chem/conf/gen/TorsionSetStrategyRandom.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232

3333
public class TorsionSetStrategyRandom extends TorsionSetStrategy {
3434
private static final int MAX_TRIES_FOR_NEW = 64;
35-
private Random mRandom;
36-
private boolean mPreferLikelyTorsions;
35+
private final Random mRandom;
36+
private final boolean mPreferLikelyTorsions;
3737

3838
/**
3939
* This simple TorsionSetStrategy produces random sets of torsion indexes in a loop.
@@ -64,6 +64,14 @@ public Random getRandom() {
6464
*/
6565
@Override
6666
public TorsionSet createTorsionSet(TorsionSet previousTorsionSet) {
67+
return createTorsionSet(mPreferLikelyTorsions);
68+
}
69+
70+
/**
71+
* Build a new set of torsion angles by pure or biased random picking.
72+
* @return a random and new torsion index set.
73+
*/
74+
public TorsionSet createTorsionSet(boolean startWithMostProbable) {
6775
if (getTorsionSetCount() == getPermutationCount())
6876
return null; // if we have found all permutations
6977

@@ -76,7 +84,14 @@ public TorsionSet createTorsionSet(TorsionSet previousTorsionSet) {
7684
if (count++ == MAX_TRIES_FOR_NEW)
7785
return null;
7886

79-
if (mPreferLikelyTorsions) {
87+
if (startWithMostProbable && getTorsionSetCount() == 0) {
88+
for (int rf=0; rf<mRigidFragment.length; rf++)
89+
conformerIndex[rf] = mRigidFragment[rf].getMostLikelyConformerIndex();
90+
BaseConformer baseConformer = mConformerGenerator.getBaseConformer(conformerIndex);
91+
for (int rb=0; rb<mRotatableBond.length; rb++)
92+
torsionIndex[rb] = baseConformer.getMostLikelyTorsionIndexes()[rb];
93+
}
94+
else if (mPreferLikelyTorsions) {
8095
double progress = (double)count/(double)MAX_TRIES_FOR_NEW;
8196
for (int rf=0; rf<mRigidFragment.length; rf++)
8297
conformerIndex[rf] = mRigidFragment[rf].getLikelyRandomConformerIndex(mRandom.nextDouble(), progress);

0 commit comments

Comments
 (0)