From 2fdc652ceeac0ea52e6992e5c3b7318cfca161ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Tue, 29 Oct 2024 08:49:50 +0100 Subject: [PATCH] feat: update OCL to v2024.10.2 --- openchemlib | 2 +- .../com/actelion/research/chem/Canonizer.java | 33 ++-- .../research/chem/ExtendedMolecule.java | 28 ++- .../research/chem/IsomericSmilesCreator.java | 2 +- .../actelion/research/chem/SSSearcher.java | 8 + .../descriptor/DescriptorWeightsHelper.java | 2 +- .../chem/shredder/FragmentGeometry3D.java | 27 ++- .../research/chem/shredder/Fragmenter3D.java | 2 +- .../editor/BondQueryFeatureDialogBuilder.java | 9 +- .../gui/editor/GenericEditorArea.java | 159 ++++++++++-------- 10 files changed, 164 insertions(+), 108 deletions(-) diff --git a/openchemlib b/openchemlib index e30c9f88..6cb49c86 160000 --- a/openchemlib +++ b/openchemlib @@ -1 +1 @@ -Subproject commit e30c9f88bb90c9b1ee688c121ee8ecfb2cc043c4 +Subproject commit 6cb49c868a3e03c6b91343be10cb80279112077c diff --git a/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/Canonizer.java b/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/Canonizer.java index 56f5d038..6beda750 100644 --- a/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/Canonizer.java +++ b/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/Canonizer.java @@ -170,12 +170,12 @@ public class Canonizer { private boolean[] mNitrogenQualifiesForParity; private ArrayList mFragmentList; private ArrayList mTHParityNormalizationGroupList; - private int mMode,mNoOfRanks,mNoOfPseudoGroups; + private final int mMode; + private int mNoOfRanks,mNoOfPseudoGroups; private boolean mIsOddParityRound; - private boolean mZCoordinatesAvailable,mAllHydrogensAreExplicit; + private final boolean mZCoordinatesAvailable,mAllHydrogensAreExplicit; private boolean mCIPParityNoDistinctionProblem; private boolean mEncodeAvoid127; - private boolean mGraphGenerated; private int mGraphRings,mFeatureBlock; private int[] mGraphAtom; @@ -184,9 +184,10 @@ public class Canonizer { private int[] mGraphFrom; private int[] mGraphClosure; - private String mIDCode, mEncodedCoords,mMapping; - private StringBuilder mEncodingBuffer; - private int mEncodingBitsAvail,mEncodingTempData,mAtomBits,mMaxConnAtoms; + private String mIDCode, mEncodedCoords,mMapping; + private StringBuilder mEncodingBuffer; + private int mEncodingBitsAvail,mEncodingTempData,mMaxConnAtoms; + private final int mAtomBits; /** * Runs a canonicalization procedure for the given molecule that creates unique atom ranks, @@ -204,7 +205,7 @@ public Canonizer(StereoMolecule mol) { * If mode includes ENCODE_ATOM_CUSTOM_LABELS, than custom atom labels are * considered for the atom ranking and are encoded into the idcode.
* If mode includes COORDS_ARE_3D, then getEncodedCoordinates() always returns - * a 3D-encoding even if all z-coordinates are 0.0. Otherwise coordinates are + * a 3D-encoding even if all z-coordinates are 0.0. Otherwise, coordinates are * encoded in 3D only, if at least one of the z-coords is not 0.0. * @param mol * @param mode 0 or one or more of CONSIDER...TOPICITY, CREATE..., ENCODE_ATOM_CUSTOM_LABELS, ASSIGN_PARITIES_TO_TETRAHEDRAL_N, COORDS_ARE_3D @@ -226,17 +227,7 @@ public Canonizer(StereoMolecule mol, int mode) { mZCoordinatesAvailable = ((mode & COORDS_ARE_3D) != 0) || mMol.is3D(); - mAllHydrogensAreExplicit = false; - if (mMol.getAllAtoms() > mMol.getAtoms() - && !mMol.isFragment()) { - mAllHydrogensAreExplicit = true; - for (int i=0; i * If keepPositionAndScale==false, then coordinate encoding will be relative, * i.e. scale and absolute positions get lost during the encoding. - * Otherwise the encoding retains scale and absolute positions.
+ * Otherwise, the encoding retains scale and absolute positions.
* If the molecule has 3D-coordinates and if there are no implicit hydrogen atoms, * i.e. all hydrogen atoms are explicitly available with their coordinates, then * hydrogen 3D-coordinates are also encoded despite the fact that the idcode itself does diff --git a/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/ExtendedMolecule.java b/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/ExtendedMolecule.java index db7c7ae1..b901fdba 100644 --- a/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/ExtendedMolecule.java +++ b/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/ExtendedMolecule.java @@ -1445,7 +1445,28 @@ public boolean supportsImplicitHydrogen(int atom) { } /** - * Calculates and return the number of implicit hydrogens at atom. + * Calculates and returns the number of implicit hydrogens of the molecule. + * For hydrogens atoms, metals except Al, or a noble gases, 0 is assumed. + * For all other atom kinds the number of implicit hydrogens is basically + * the lowest typical valence that is compatible with the occupied valence, + * minus the occupied valence corrected by atom charge and radical state. + * If this molecule is a fragment, then 0 is returned. + * @return number of implicit hydrogens of the molecule + */ + public int getImplicitHydrogens() { + if (mIsFragment) + return 0; + + ensureHelperArrays(cHelperNeighbours); + int implicitHydrogens = 0; + for (int atom=0; atom> Molecule.cBondQFRingSizeShift) return true; + if (ringSize <= 2) { // ring size 8-11 is encoded as 1; ring size >=12 is encoded as 2 + int moleculeRingSize = mMolecule.getBondRingSize(moleculeBond); + if (ringSize == 1) + return (moleculeRingSize >= 8) && (moleculeRingSize <= 12); + else + return moleculeRingSize >= 12; + } + boolean found = false; RingCollection ringSet = mMolecule.getRingSet(); for (int i=0; i liSubGraphIndices, Molecule3D molecule3D){ diff --git a/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/shredder/FragmentGeometry3D.java b/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/shredder/FragmentGeometry3D.java index 0a7eb563..986419c8 100644 --- a/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/shredder/FragmentGeometry3D.java +++ b/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/shredder/FragmentGeometry3D.java @@ -74,7 +74,7 @@ private Coordinates[] determineAlignmentCoords() { coords[i] = mMol.getCoordinates(mExitVector[i].rootAtom); coords[mExitVector.length + i] = mMol.getCoordinates(mExitVector[i].exitAtom); - // for lonely hydrogens (selected H connects to other exit atom) + // for lonely hydrogens (single selected H connecting to non-selected exit atom) // we need to place the root coord (hydrogen) further away from the exit atom, // to reflect the longer bond length of a C-C compared to H-C if (mMol.getAtomicNo(mExitVector[i].rootAtom) == 1) @@ -123,9 +123,10 @@ public boolean equals(FragmentGeometry3D geometry) { * is returned. * @param geometry the geometry to be aligned with this * @param permutation permutation index for equivalent root atoms of the passed geometry + * @param rmsdHolder null or double[1] to receive RMSD value * @return rotation matrix or null, depending on whether alignment is acceptable */ - public double[][] alignRootAndExitAtoms(FragmentGeometry3D geometry, int permutation, double maxRMSD) { + public double[][] alignRootAndExitAtoms(FragmentGeometry3D geometry, int permutation, double[] rmsdHolder, double maxRMSD) { ExitVector[] geomEV = geometry.mExitVector; Coordinates[] coords = new Coordinates[2*geomEV.length]; for (int i=0; i maxRMSD ? null : matrix; + double rmsd = Coordinates.getRmsd(mAlignmentCoords, coords); + if (rmsdHolder != null) + rmsdHolder[0] = rmsd; + + return rmsd > maxRMSD ? null : matrix; } - public boolean hasMatchingExitVectors(FragmentGeometry3D geometry, Coordinates[] coords, int permutation, double maxAngleDivergence) { - maxAngleDivergence *= Math.PI / 180; - for (int i = 0; i maxAngleDivergence) - return false; + angleDif[i] = v1.getAngle(v2) * 180 / Math.PI; + if (angleDif[i] > maxAngleDivergence) + qualifies = false; } - return true; + if (angleHolder != null) + angleHolder[0] = angleDif; + return qualifies; } public int getPermutationCount() { diff --git a/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/shredder/Fragmenter3D.java b/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/shredder/Fragmenter3D.java index 89d76417..409450d0 100644 --- a/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/shredder/Fragmenter3D.java +++ b/src/com/actelion/research/gwt/chemlib/com/actelion/research/chem/shredder/Fragmenter3D.java @@ -55,7 +55,7 @@ public ArrayList buildFragments(StereoMolecule mol, boolean withHydr int fragmentCount = mol.getFragmentNumbers(fragmentNo, isRotatableBond, true); int[] atomCount = new int[fragmentCount]; - for (int atom=0; atom= 12"); mDialog.add(mComboBoxRingSize, 1,13,3,13); mCBMatchFormalOrder = mDialog.createCheckBox("Match formal bond order"); @@ -223,7 +225,7 @@ else if (aromState == Molecule.cBondQFNotAromatic) mComboBoxRing.setSelectedIndex(0); int ringSize = (queryFeatures & Molecule.cBondQFRingSize) >> Molecule.cBondQFRingSizeShift; - mComboBoxRingSize.setSelectedIndex((ringSize == 0) ? 0 : ringSize-2); + mComboBoxRingSize.setSelectedIndex((ringSize == 0) ? 0 : (ringSize <= 2) ? ringSize+5 : ringSize-2); if ((queryFeatures & Molecule.cBondQFBridge) != 0) { mCBIsBridge.setSelected(true); @@ -361,9 +363,12 @@ else if (mComboBoxRing.getSelectedIndex() == 4) { if (mComboBoxRingSize.getSelectedIndex() != 0) { int ringSize = mComboBoxRingSize.getSelectedIndex() + 2; + if (ringSize > 7) // ringsize 8-11 is encoded as 1; ringsize >12 is encoded as 2 + ringSize -= 7; int implicitSize = mMol.getBondRingSize(bond); - if (ringSize != implicitSize) + if (ringSize <= 2 || ringSize != implicitSize) { // options 1 and 2 cover spans and cannot be implicit queryFeatures |= (ringSize << Molecule.cBondQFRingSizeShift); + } } } diff --git a/src/com/actelion/research/gwt/chemlib/com/actelion/research/gui/editor/GenericEditorArea.java b/src/com/actelion/research/gwt/chemlib/com/actelion/research/gui/editor/GenericEditorArea.java index 3e81c7d8..6299313b 100644 --- a/src/com/actelion/research/gwt/chemlib/com/actelion/research/gui/editor/GenericEditorArea.java +++ b/src/com/actelion/research/gwt/chemlib/com/actelion/research/gui/editor/GenericEditorArea.java @@ -985,75 +985,8 @@ private void eventHappened(GenericMouseEvent e) { switch (mPendingRequest) { case cRequestNewChain: - double lastX, lastY; - if (mChainAtoms>0) { - lastX = mChainAtomX[mChainAtoms - 1]; - lastY = mChainAtomY[mChainAtoms - 1]; - } else { - lastX = 0; - lastY = 0; - } - double avbl = getScaledAVBL(); - double s0 = (int)avbl; - double s1 = (int)(0.866 * avbl); - double s2 = (int)(0.5 * avbl); - double dx = mX2 - mX1; - double dy = mY2 - mY1; - if (Math.abs(dy)>Math.abs(dx)) { - mChainAtoms = (int)(2 * Math.abs(dy) / (s0 + s2)); - if (Math.abs(dy) % (s0 + s2)>s0) { - mChainAtoms++; - } - mChainAtomX = new double[mChainAtoms]; - mChainAtomY = new double[mChainAtoms]; - if (mX20) { - mChainAtom = new int[mChainAtoms]; - for (int i = 0; i 0) { + lastX1 = (int)Math.round(mChainAtomX[0]); + lastY1 = (int)Math.round(mChainAtomY[0]); + } + if (lastChainAtoms > 1) { + lastX2 = (int)Math.round(mChainAtomX[1]); + lastY2 = (int)Math.round(mChainAtomY[1]); + } + + double exitAngle = 0; + if (mAtom1 == -1 || mMol.getAllConnAtomsPlusMetalBonds(mAtom1) == 0) { + exitAngle = Math.PI / 3 * Math.round(mouseAngle * 3 / Math.PI); + } + else if (mMol.getAllConnAtomsPlusMetalBonds(mAtom1) == 1) { + double bondAngle = mMol.getBondAngle(mMol.getConnAtom(mAtom1, 0), mAtom1); + double candidate1 = bondAngle - Math.PI / 3; + double candidate2 = bondAngle + Math.PI / 3; + exitAngle = Math.abs(Molecule.getAngleDif(mouseAngle, candidate1)) + < Math.abs(Molecule.getAngleDif(mouseAngle, candidate2)) ? candidate1 : candidate2; + } + else { + double[] connAngle = new double[mMol.getAllConnAtomsPlusMetalBonds(mAtom1)]; + for (int i=0; i Math.PI / 3 ? 0 : (int)(Math.sqrt(mdx*mdx + mdy*mdy) / avbl); + if (mChainAtoms > 0) { + if (mChainAtomX == null || mChainAtomX.length < mChainAtoms) { + mChainAtomX = new double[mChainAtoms]; + mChainAtomY = new double[mChainAtoms]; + } + double[] dx = new double[2]; + double[] dy = new double[2]; + double nextAngle = Molecule.getAngleDif(mouseAngle, exitAngle) < 0 ? exitAngle - Math.PI / 3 : exitAngle + Math.PI / 3; + dx[0] = avbl * Math.sin(exitAngle); + dy[0] = avbl * Math.cos(exitAngle); + dx[1] = avbl * Math.sin(nextAngle); + dy[1] = avbl * Math.cos(nextAngle); + for (int i=0; i 1) + && (lastX2 != (int)Math.round(mChainAtomX[1]) + || lastY2 != (int)Math.round(mChainAtomY[1]))); + } + public void showHelpDialog() { mUIHelper.showHelpDialog("/html/editor/editor.html", "Structure Editor Help"); } @@ -2369,7 +2390,7 @@ private void suggestNewX2AndY2(int atom) { double newAngle = Math.PI * 2 / 3; if (atom != -1) { - double angle[] = new double[MAX_CONNATOMS + 1]; + double[] angle = new double[MAX_CONNATOMS + 1]; for (int i = 0; i