RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
SingleConformerAlignment.h
Go to the documentation of this file.
1//
2// Copyright (C) 2026 David Cosgrove and other RDKit contributors
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10// Original author: David Cosgrove (CozChemIx Limited)
11//
12// This is the class that does optimises a moving molecule (fit)
13// to maximise its Gaussian overlap with the reference molecule (ref).
14// The optimiser is a modified BFGS taken in large part, but re-arranged
15// for readability, from the PubChem shape overlay code
16// https://github.com/ncbi/pubchem-align3d/blob/main/shape_neighbor.cpp
17
18#ifndef RDKIT_SINGLECONFORMERALIGNMENT_GUARD
19#define RDKIT_SINGLECONFORMERALIGNMENT_GUARD
20
21#include <array>
22
24#include <boost/dynamic_bitset.hpp>
26
27#include <RDGeneral/export.h>
29
30namespace RDKit {
31namespace GaussianShape {
34 /// @brief Do the overlay for a single conformer of fit against a single
35 /// conformer of ref. The output in scores is the rotation and translation
36 /// that moves fit to optimise its score with ref.
37 /// @param ref - the query molecule as 1D array of 4 * N entries. Each
38 /// block of 4 is the coords and atom radius
39 /// @param refTypes - the feature types for molecule ref
40 /// @param refCarbonRadii - whether each atom has a carbon radius
41 /// @param nRefShape - the number of atoms in ref
42 /// @param nRefColor - the number of features in ref
43 /// @param refShapeVol - overlap volume of ref with itself
44 /// @param refColorVol - color overlap of ref with itself
45 /// @param fit - the fit molecule as 1D array of 4 * N entries. Each
46 /// block of 4 is the coords and atom radius.
47 /// @param fitTypes - the feature types for fit molecule
48 /// @param fitCarbonRadii - whether each atom has a carbon radius
49 /// @param nFitShape - the number of atoms in fit
50 /// @param nFitColor - the number of features in fit
51 /// @param fitShapeVol - overlap volume of fit with itself
52 /// @param fitColorVol - color overlap of fit with itself
53 /// @param optimMode - optimisation mode
54 /// @param simAlpha - for the Tversky similarity, the alpha value
55 /// @param simBeta - for the Tversky similarity, the beta value
56 /// @param mixingParam - how to mix the 2 Tversky values
57 /// @param useCutoff - whether to use a distance cutoff in the volume
58 /// calculation
59 /// @param distCutoff - the cutoff to use if we're doing it.
60 /// @param maxIts - maximum number of iterations for optimiser
61 /// of optimiser
63 const std::vector<double> &ref, const int *refTypes,
64 const boost::dynamic_bitset<> *refCarbonRadii, int nRefShape,
65 int nRefColor, double refShapeVol, double refColorVol,
66 const std::vector<double> &fit, const int *fitTypes,
67 const boost::dynamic_bitset<> *fitCarbonRadii, int nFitShape,
68 int nFitColor, double fitShapeVol, double fitColorVol,
69 const std::array<double, 7> &initQuatTrans, OptimMode optimMode,
70 double simAlpha, double simBeta, double mixingParam, bool useCutoff,
71 double distCutoff, double shapeConvergenceCriterion, unsigned int maxIts);
72
76 delete;
78 delete;
80
81 void setQuatTrans(const std::array<double, 7> &quatTrans) {
82 d_quatTrans = quatTrans;
83 }
84
85 // Get the final transformation by adding the initial transformation
86 // and the optimised final answer.
88
89 // Calculate the combined, shape, and color Tversky scores as appropriate,
90 // plus the volume of the shape and color overlaps, in that order.
91 // Assumes that ref and fit are already in the correct configurations.
92 // If includeColor is passed in true, it will compute the color score
93 // irrespective of the value in d_optimMode. We still want the color
94 // score even if doing SHAPE_ONLY optimisation, for example.
95 std::array<double, 5> calcScores(const double *ref, const double *fit,
96 bool includeColor = false);
97 // This one applies the current quatTrans to the coords and then calculates
98 // the score.
99 std::array<double, 5> calcScores(bool includeColor = false);
100 // This one computes the scores from the given overlap volumes. Color score
101 // only calculated if the color volumes are non-zero.
102 std::array<double, 5> calcScores(const double shapeOvVol,
103 const double colorOvVol,
104 bool includeColor = true) const;
105
106 // Apply the quatTrans to the ref and fit shapes and put the results
107 // into their tmp equivalents. Ref is translated by the -ve of the
108 // translation, fit is rotated by the rotation bit.
109 void applyQuatTrans(const std::array<double, 7> &quatTrans);
110
111 // Calculate the overlap volume between A and B after the given "quaternion"
112 // has been applied. The "quaternion" is 7 elements, the first 4 the
113 // quaternion the last 3 the translation that currently form the
114 // transformation that overlays B onto A.
115 void calcVolumeAndGradients(const std::array<double, 7> &quatTrans,
116 double &shapeOvlpVol, double &colorOvlpVol,
117 std::array<double, 7> &gradients);
118
119 /// @brief Do the overlay, feeding the results into scores.
120 /// @return scores - the output scores and transformation to reproduce the
121 /// overlay - an array of size 20. Only the first 16 are used here. They are:
122 /// 0 - the combo score
123 /// 1 - the shape Tversky score
124 /// 2 - the color Tversky score
125 /// 3 - the shape overlap volume
126 /// 4 - the color overlap volume
127 /// 5 - the shape volume of fit
128 /// 6 - the shape volume of ref
129 /// 7 - the color volume of fit
130 /// 8 - the color volume of ref
131 /// 9-12 - the quaternion to rotate fit onto ref. Applied first.
132 /// 13-15 - the translation to move fit onto ref. Applied second.
133 /// 16-19 - not used at present, returned as zeros.
134 /// Returns false if it didn't finish with the allowed maximum number of
135 /// iterations.
136 bool doOverlay(std::array<double, 20> &scores, unsigned int cycle);
137
138 // Find the quaternion and translation that maximises the volume
139 // overlap appropriate to d_optimMode. Returns false if it didn't finish with
140 // the allowed maximum number of iterations.
141 bool optimise(unsigned int maxIters);
142
143 std::vector<double> d_ref;
144 std::vector<double> d_refTemp;
145 const int *d_refTypes;
146 const boost::dynamic_bitset<> *d_refCarbonRadii;
147 const int d_nRefShape;
148 const int d_nRefColor;
149 const double d_refShapeVol;
150 const double d_refColorVol;
151 std::vector<double> d_fit;
152 std::vector<double> d_fitTemp;
153 const int *d_fitTypes;
154 const boost::dynamic_bitset<> *d_fitCarbonRadii;
155 const int d_nFitShape;
156 const int d_nFitColor;
159 std::array<double, 7> d_initQuatTrans;
160 const OptimMode d_optimMode;
161 const double d_simAlpha;
162 const double d_simBeta;
163 const double d_mixingParam;
164 const bool d_useCutoff;
165 const double d_distCutoff2;
167 const unsigned int d_maxIts;
168 // The quaternion/translation as the optimisation proceeds
169 std::array<double, 7> d_quatTrans{1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
170 // The step sizes of the quaternion and translation during the
171 // optimisation. Taken from the PubChem code.
172 double d_qStepSize{-0.001};
173 double d_tStepSize{-0.01};
174 // Scratch space for the gradients dr/dQ of the fit molecule.
175 std::vector<double> d_gradConverters;
176};
177
178// Compute the volume overlap and optionally "quaternion" gradients for the
179// overlap volume of ref and fit, wrt fit. fit is the original coords of
180// the fit molecule, fitTemp is those subject to any transformation applied
181// by the quaternion we're using to optimise the overlap volume. If
182// gradients is null, they won't be calculated. They are assumed to be
183// initialised correctly.
184// This is for the atoms/shape features.
185double calcVolAndGrads(const double *ref, int numRefPts,
186 const boost::dynamic_bitset<> *refCarbonRadii,
187 const double *fit, int numFitPts,
188 const boost::dynamic_bitset<> *fitCarbonRadii,
189 std::vector<double> &gradConverters,
190 const bool useCutoff, const double distCutoff2,
191 const double *quat = nullptr,
192 double *gradients = nullptr);
193// This one is for the features, and only calculates values if the types
194// of 2 features match.
195double calcVolAndGrads(const double *ref, int numRefPts, const int *refTypes,
196 const double *fit, int numFitPts, const int *fitTypes,
197 int numFitShape, std::vector<double> &gradConverters,
198 const bool useCutoff, const double distCutoff2,
199 const double *quat, double *gradients);
200
201} // namespace GaussianShape
202} // namespace RDKit
203
204#endif // RDKIT_SINGLECONFORMERALIGNMENT_GUARD
#define RDKIT_GAUSSIANSHAPE_EXPORT
Definition export.h:233
double calcVolAndGrads(const double *ref, int numRefPts, const boost::dynamic_bitset<> *refCarbonRadii, const double *fit, int numFitPts, const boost::dynamic_bitset<> *fitCarbonRadii, std::vector< double > &gradConverters, const bool useCutoff, const double distCutoff2, const double *quat=nullptr, double *gradients=nullptr)
Std stuff.
std::array< double, 5 > calcScores(const double *ref, const double *fit, bool includeColor=false)
void setQuatTrans(const std::array< double, 7 > &quatTrans)
SingleConformerAlignment & operator=(SingleConformerAlignment &&other)=delete
SingleConformerAlignment(const SingleConformerAlignment &other)=delete
std::array< double, 5 > calcScores(bool includeColor=false)
void applyQuatTrans(const std::array< double, 7 > &quatTrans)
SingleConformerAlignment & operator=(const SingleConformerAlignment &other)=delete
bool doOverlay(std::array< double, 20 > &scores, unsigned int cycle)
Do the overlay, feeding the results into scores.
SingleConformerAlignment(SingleConformerAlignment &&other)=delete
std::array< double, 5 > calcScores(const double shapeOvVol, const double colorOvVol, bool includeColor=true) const
SingleConformerAlignment(const std::vector< double > &ref, const int *refTypes, const boost::dynamic_bitset<> *refCarbonRadii, int nRefShape, int nRefColor, double refShapeVol, double refColorVol, const std::vector< double > &fit, const int *fitTypes, const boost::dynamic_bitset<> *fitCarbonRadii, int nFitShape, int nFitColor, double fitShapeVol, double fitColorVol, const std::array< double, 7 > &initQuatTrans, OptimMode optimMode, double simAlpha, double simBeta, double mixingParam, bool useCutoff, double distCutoff, double shapeConvergenceCriterion, unsigned int maxIts)
Do the overlay for a single conformer of fit against a single conformer of ref. The output in scores ...
void getFinalQuatTrans(RDGeom::Transform3D &xform) const
void calcVolumeAndGradients(const std::array< double, 7 > &quatTrans, double &shapeOvlpVol, double &colorOvlpVol, std::array< double, 7 > &gradients)