Chemical Data Processing Library C++ API - Version 1.3.0
Atom2DCoordinatesCalculator.hpp
Go to the documentation of this file.
1 /*
2  * Atom2DCoordinatesCalculator.hpp
3  *
4  * This file is part of the Chemical Data Processing Toolkit
5  *
6  * Copyright (C) 2003 Thomas Seidel <thomas.seidel@univie.ac.at>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; see the file COPYING. If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23 
29 #ifndef CDPL_CHEM_ATOM2DCOORDINATESCALCULATOR_HPP
30 #define CDPL_CHEM_ATOM2DCOORDINATESCALCULATOR_HPP
31 
32 #include <cstddef>
33 #include <vector>
34 #include <list>
35 #include <deque>
36 #include <map>
37 #include <utility>
38 
39 #include <boost/unordered_set.hpp>
40 
41 #include "CDPL/Chem/APIPrefix.hpp"
43 #include "CDPL/Math/Matrix.hpp"
44 #include "CDPL/Util/BitSet.hpp"
47 
48 
49 namespace CDPL
50 {
51 
52  namespace Chem
53  {
54 
55  class Atom;
56  class Bond;
57  class MolecularGraph;
58  class Fragment;
59 
64  {
65 
66  public:
71 
82 
84 
86 
95  void calculate(const MolecularGraph& molgraph, Math::Vector2DArray& coords);
96 
97  private:
98  class RingInfo
99  {
100 
101  public:
102  void init(const MolecularGraph*, const Fragment&, std::size_t, std::size_t);
103 
104  const Fragment& getFragment() const;
105 
106  const Util::BitSet& getAtomMask() const;
107  const Util::BitSet& getBondMask() const;
108 
109  double getPriority() const;
110  void setPriority(double);
111 
112  std::size_t getSize() const;
113 
114  private:
115  const Fragment* fragment;
116  Util::BitSet atomMask;
117  Util::BitSet bondMask;
118  double priority;
119  };
120 
121  class LGNode;
122 
123  class LGEdge
124  {
125 
126  public:
127  enum Type
128  {
129 
130  BOND_EDGE,
131  SPIRO_EDGE
132  };
133 
134  void init(const MolecularGraph*, const Atom*, LGNode*, LGNode*, std::size_t);
135  void init(const MolecularGraph*, const Bond*, LGNode*, LGNode*, std::size_t);
136 
137  const Atom* getSpiroCenter() const;
138  const Bond* getBond() const;
139 
140  LGNode* otherNode(const LGNode*) const;
141 
142  Type getType() const;
143  std::size_t getID() const;
144 
145  bool hasConfigConstraint() const;
146  bool configConstraintFulfilled(const Math::Vector2DArray&) const;
147 
148  private:
149  bool initConfigInfo();
150 
151  const MolecularGraph* molGraph;
152  const Atom* spiroCenter;
153  const Bond* bond;
154  LGNode* node1;
155  LGNode* node2;
156  Type type;
157  bool hasConfig;
158  unsigned int configuration;
159  const Atom* configRefAtoms[2];
160  std::size_t id;
161  };
162 
163  typedef std::vector<std::size_t> AtomIndexList;
164  typedef std::vector<const Bond*> BondList;
165  typedef std::vector<LGNode*> NodeList;
166 
167  class LGNode
168  {
169 
170  public:
171  enum Type
172  {
173 
174  RING_SYS = 0x1,
175  CHAIN_ATOM = 0x2,
176  END_ATOM = 0x3
177  };
178 
179  enum Direction
180  {
181 
182  UP,
183  DOWN
184  };
185 
186  virtual ~LGNode() {}
187 
188  void init(const MolecularGraph* molgraph);
189 
190  virtual void addEdge(const Atom*, const LGEdge*) = 0;
191 
192  virtual void getChildNodes(NodeList&) const = 0;
193 
194  virtual void init() = 0;
195 
196  virtual void createChildLayouts() = 0;
197 
198  virtual double getPriority() const = 0;
199 
200  virtual std::size_t getChainID() const = 0;
201 
202  virtual void layout() = 0;
203  virtual bool layout(double, const Math::Vector2D&, std::size_t&, std::size_t, bool) = 0;
204 
205  virtual bool layoutChildNodes(std::size_t&, std::size_t, bool) = 0;
206 
207  virtual Type getType() const = 0;
208 
209  virtual double getAngularDemand(const Atom*) const;
210 
211  virtual bool setParentEdge(const LGEdge*, Direction) = 0;
212 
213  protected:
214  std::size_t countAtomCollisions(const AtomIndexList&, const AtomIndexList&, const Math::Vector2DArray&);
215  std::size_t countAtomCollisionsForAtom(std::size_t, const AtomIndexList&, const Math::Vector2DArray&);
216 
217  std::size_t countBondCollisions(const BondList&, const BondList&, const Math::Vector2DArray&);
218  std::size_t countBondCollisionsForBond(const Bond*, const BondList&, const Math::Vector2DArray&);
219 
220  std::size_t countAtomBondCollisions(const AtomIndexList&, const BondList&, const Math::Vector2DArray&);
221  std::size_t countBondCollisionsForAtom(std::size_t, const BondList&, const Math::Vector2DArray&);
222 
223  std::size_t countBondAtomCollisions(const BondList&, const AtomIndexList&, const Math::Vector2DArray&);
224  std::size_t countAtomCollisionsForBond(const Bond*, const AtomIndexList&, const Math::Vector2DArray&);
225 
226  bool testAtomBondCollision(std::size_t, const Bond*, const Math::Vector2DArray&);
227 
229  {
230 
231  NodeLayoutInfo(const LGEdge* edge, double angle):
232  edge(edge), angle(angle) {}
233 
234  const LGEdge* edge;
235  double angle;
236  };
237 
238  typedef std::vector<NodeLayoutInfo> NodeLayoutInfoList;
239  typedef std::pair<double, double> AngleRange;
240 
241  class EdgePriorityGreaterCmpFunc;
242 
243  class LinkedNodePriorityLessCmpFunc;
244  class LinkedNodePriorityEqualCmpFunc;
245 
246  class NodeLayoutInfoListEqualCmpFunc;
247 
248  const MolecularGraph* molGraph;
249  };
250 
251  typedef std::list<RingInfo*> RingInfoList;
252  typedef std::vector<const LGEdge*> EdgeList;
253 
254  class RingSysNode : public LGNode
255  {
256 
257  public:
258  RingSysNode();
259 
260  void init(const MolecularGraph*, const RingInfo*, Math::Vector2DArray&,
261  AtomIndexList&, BondList&);
262 
263  const Util::BitSet& getAtomMask() const;
264  const Util::BitSet& getBondMask() const;
265 
266  bool containsAtom(std::size_t) const;
267 
268  bool addRing(const RingInfo*);
269 
270  void addEdge(const Atom*, const LGEdge*);
271 
272  void getChildNodes(NodeList&) const;
273 
274  void init();
275 
276  double getPriority() const;
277 
278  std::size_t getChainID() const;
279 
280  void layout();
281  bool layout(double, const Math::Vector2D&, std::size_t&, std::size_t, bool);
282 
283  bool layoutChildNodes(std::size_t&, std::size_t, bool);
284 
285  Type getType() const;
286 
287  double getAngularDemand(const Atom*) const;
288 
289  bool setParentEdge(const LGEdge*, Direction);
290 
291  private:
292  bool layoutChildNodes(double, double, bool, double, std::size_t&, std::size_t, bool);
293  bool layoutChildNodes(std::size_t, std::size_t&, std::size_t, bool);
294 
295  void createChildLayouts();
296  void createChildLayouts(const Atom*, EdgeList&);
297 
298  bool layout(std::size_t, const Math::Vector2D&, double, bool, double, std::size_t&, std::size_t);
299 
300  void transformCoords(std::size_t, const Math::Vector2D&, double, bool, double);
301 
302  double transformEdgeAngle(double) const;
303 
304  void copyCoords();
305 
306  void commitAtomAndBondList() const;
307 
308  void calcCoords();
309 
310  void calcCoordsForRing(const RingInfo*);
311  void calcCoordsForRingSegment(const RingInfo*);
312 
313  void refineLayout();
314 
315  void initSpringLayoutParams();
316  void performSpringLayout();
317 
318  void performDistGeomLayout();
319  bool needDistGeomLayout() const;
320  bool addBondStereoDGConstraints(const RingInfo* ring_info);
321  void addBondAngleDGConstraints(const RingInfo* ring_info);
322  void addDefaultDGConstraints();
323 
324  const Chem::Atom* getExoBondAtom(const RingInfo* ring_info, const Atom& atom, std::size_t rings_nbrs[2]) const;
325 
326  Math::Vector2D computePartialDerivatives(std::size_t) const;
327  Math::Vector2D computePartialDerivative(std::size_t, std::size_t) const;
328 
329  bool layoutFinished(bool, double, double&, double&) const;
330 
331  void distributeWeightFactors(std::size_t, double, const Math::ULMatrix&);
332 
333  void calcFreeSweeps();
334 
335  bool getNextRingSegment(const RingInfo*);
336 
337  double calcCongestionFactor(const Math::Vector2D&) const;
338  double calcCongestionFactor(const Math::Vector2D&, const Util::BitSet&) const;
339 
340  typedef Util::DGCoordinatesGenerator<2, double> DGCoordsGenerator;
341  typedef std::pair<std::size_t, std::size_t> DistConstraintKey;
342  typedef boost::unordered_set<DistConstraintKey> DistConstraintKeySet;
343  typedef std::vector<const RingInfo*> RingInfoList;
344  typedef std::list<const RingInfo*> RingLayoutQueue;
345  typedef std::map<std::size_t, EdgeList> EdgeListMap;
346  typedef std::map<const Atom*, AngleRange> AngleRangeMap;
347  typedef std::deque<std::size_t> RingSegment;
348  typedef std::vector<std::vector<NodeLayoutInfoList> > NodeLayoutInfoListTable;
349  typedef std::vector<std::size_t> LayoutIndexTable;
350  typedef std::vector<const Atom*> AtomTable;
351  typedef std::vector<Math::Vector2D> EnergyDerivativeTable;
352  typedef std::vector<double> WeightFactorTable;
353 
354  Util::BitSet atomMask;
355  Util::BitSet bondMask;
356  Util::BitSet procAtomMask;
357  Util::BitSet tmpBitMask;
358  double priority;
359  RingInfoList ringList;
360  RingLayoutQueue ringLayoutQueue;
361  RingSegment ringSegment;
362  EdgeListMap edgeListMap;
363  AngleRangeMap freeSweepMap;
364  AtomIndexList atomList;
365  BondList bondList;
366  AtomIndexList* procAtomList;
367  BondList* procBondList;
368  Math::Vector2DArray localCoords;
369  Math::Vector2DArray* outputCoords;
370  const LGEdge* parentEdge;
371  const Atom* parentEdgeAtom;
372  EdgeList parentEdgeAtomEdges;
373  NodeLayoutInfoListTable childLayouts;
374  LayoutIndexTable childLayoutIndexTable;
375  AtomTable edgeAtomTable;
376  Math::Vector2D parentPos;
377  std::size_t rsysLayoutIndex;
378  double parentEdgeAngle;
379  double rsysRotAngle;
380  double rsysAxisAngle;
381  bool flipped;
382  WeightFactorTable layoutWeightFactors;
383  EnergyDerivativeTable layoutEnergyDerivatives;
384  Math::DMatrix layoutAtomDistances;
385  Math::DMatrix layoutSpringStrengths;
386  DGCoordsGenerator dgCoordsGenerator;
387  DistConstraintKeySet setDistConstraints;
388  };
389 
390  class AtomNode : public LGNode
391  {
392 
393  public:
394  void init(const MolecularGraph*, const Atom*, double, Math::Vector2DArray&, AtomIndexList&, BondList&);
395 
396  void addEdge(const Atom*, const LGEdge*);
397 
398  const Atom* getAtom() const;
399  std::size_t getAtomIndex() const;
400 
401  void getChildNodes(NodeList&) const;
402 
403  void init();
404 
405  double getPriority() const;
406 
407  std::size_t getChainID() const;
408 
409  void setChainID(std::size_t);
410 
411  void layout();
412  bool layout(double, const Math::Vector2D&, std::size_t&, std::size_t, bool);
413 
414  bool layoutChildNodes(std::size_t&, std::size_t, bool);
415 
416  Type getType() const;
417 
418  bool setParentEdge(const LGEdge*, Direction);
419 
420  private:
421  struct LayoutParameters
422  {
423 
424  LayoutParameters(std::size_t num_colls):
425  numCollisions(num_colls) {}
426 
427  std::size_t numCollisions;
428  double bondLength{0.0};
429  double edgeAngle{0.0};
430  };
431 
432  void layout(double, double, const Math::Vector2D&, std::size_t, std::size_t, LayoutParameters&);
433 
434  std::size_t getChildNodeTypePattern() const;
435 
436  void createChildLayouts();
437 
438  void createChildLayoutsD1();
439  void createChildLayoutsD2();
440  void createChildLayoutsD3();
441  void createChildLayoutsD4();
442  void createChildLayoutsDN();
443 
444  void removeChildLayoutSymmetryDuplicates();
445 
446  void removeParentEdge();
447 
448  void sortChildEdges();
449 
450  typedef std::vector<NodeLayoutInfoList> NodeLayoutInfoListTable;
451 
452  const Atom* atom;
453  std::size_t atomIndex;
454  bool isHydrogen;
455  Type type;
456  double priority;
457  std::size_t chainID;
458  AtomIndexList* procAtomList;
459  BondList* procBondList;
460  Math::Vector2DArray* outputCoords;
461  Direction chainDirection;
462  double parentEdgeAngle;
463  EdgeList edges;
464  const LGEdge* parentEdge;
465  NodeLayoutInfoListTable childLayouts;
466  std::size_t childLayoutIndex;
467  Direction childChainDirections[4];
468  };
469 
470  typedef std::pair<Math::Vector2D, Math::Vector2D> BoundingBox;
471 
472  void init(const MolecularGraph&, Math::Vector2DArray&);
473 
474  void extractRingInformation();
475 
476  void calcAtomPriorities();
477  void calcRingPriorities();
478 
479  void layoutComponents(Math::Vector2DArray&);
480  void layoutComponent(const Fragment&, Math::Vector2DArray&);
481 
482  void alignComponents(Math::Vector2DArray&);
483 
484  void moveComponent(const BoundingBox&, double, double, const Fragment&, Math::Vector2DArray&);
485  void addPoint(BoundingBox&, const Math::Vector2D&) const;
486  void calcBounds(BoundingBox&, const Fragment&, Math::Vector2DArray&) const;
487 
488  void createLayoutTree(const Fragment&, Math::Vector2DArray&);
489  void createRingSysNodes(const Fragment&, Math::Vector2DArray&);
490  void createAtomNodes(const Fragment&, Math::Vector2DArray&);
491  void createBondEdges(const Fragment&);
492  void createSpiroEdges(const Fragment&);
493 
494  void setAtomNodeChainIDs();
495 
496  void findLongestNodePath(AtomNode*, const AtomNode*);
497 
498  void createBFSNodeList();
499  void initNodes() const;
500 
501  void layoutNodes();
502  bool layoutChildNodes(std::size_t);
503 
504  LGEdge* allocEdge(const Atom*, LGNode*, LGNode*);
505  LGEdge* allocEdge(const Bond*, LGNode*, LGNode*);
506 
507  RingInfo* allocRingInfo(const Fragment&);
508  RingSysNode* allocRingSysNode(const RingInfo*, Math::Vector2DArray&);
509 
510  AtomNode* allocAtomNode(const Atom*, Math::Vector2DArray&);
511 
512  void freeAllocEdges();
513  void freeAllocRingInfos();
514  void freeAllocRingSysNodes();
515  void freeAllocAtomNodes();
516 
517  typedef std::vector<AtomNode*> AtomNodeList;
518  typedef std::vector<std::size_t> AtomPriorityTable;
519  typedef Util::ObjectStack<RingInfo> RingInfoCache;
520  typedef Util::ObjectStack<RingSysNode> RingSysNodeCache;
521  typedef Util::ObjectStack<AtomNode> AtomNodeCache;
522  typedef Util::ObjectStack<LGEdge> EdgeCache;
523  typedef std::vector<RingSysNode*> RingSysNodeList;
524 
525  const MolecularGraph* molGraph;
526  RingInfoCache ringInfoCache;
527  RingSysNodeCache ringSysNodeCache;
528  AtomNodeCache atomNodeCache;
529  EdgeCache edgeCache;
530  EdgeList edgeList;
531  RingInfoList ringList;
532  RingSysNodeList ringSysNodeList;
533  AtomNodeList atomNodeList;
534  RingInfoList tmpRingList;
535  NodeList bfsNodeList;
536  AtomNodeList atomNodeTable;
537  AtomNodeList longestAtomNodePath;
538  AtomNodeList currAtomNodePath;
539  AtomIndexList procAtomList;
540  BondList procBondList;
541  Util::BitSet atomMask;
542  Util::BitSet ringAtomMask;
543  Util::BitSet tmpBitMask;
544  AtomPriorityTable atomPriorityTable;
545  std::size_t numAtoms;
546  std::size_t numBonds;
547  bool strictLayoutGeometry;
548  std::size_t numLayoutCollisions;
549  std::size_t maxNumLayoutCollisions;
550  std::size_t backtrackingCount;
551  std::size_t nextEdgeID;
552  };
553  } // namespace Chem
554 } // namespace CDPL
555 
556 #endif // CDPL_CHEM_ATOM2DCOORDINATESCALCULATOR_HPP
Definition of the type CDPL::Util::BitSet.
Definition of the preprocessor macro CDPL_CHEM_API.
#define CDPL_CHEM_API
Tells the compiler/linker which classes, functions and variables are part of the library API.
Implementation of a distance geometry based coordinates generator.
Definition of matrix data types.
Definition of the class CDPL::Util::ObjectStack.
Definition of the class CDPL::Math::VectorArray.
Atom2DCoordinatesCalculator.
Definition: Atom2DCoordinatesCalculator.hpp:64
Atom2DCoordinatesCalculator(const MolecularGraph &molgraph, Math::Vector2DArray &coords)
Constructs the Atom2DCoordinatesCalculator instance and calculates 2D-coordinates for the atoms of th...
Atom2DCoordinatesCalculator()
Constructs the Atom2DCoordinatesCalculator instance.
Atom2DCoordinatesCalculator & operator=(const Atom2DCoordinatesCalculator &)=delete
void calculate(const MolecularGraph &molgraph, Math::Vector2DArray &coords)
Calculates 2D-coordinates for the atoms of the molecular graph molgraph.
Atom2DCoordinatesCalculator(const Atom2DCoordinatesCalculator &)=delete
Atom.
Definition: Atom.hpp:52
Fragment.
Definition: Fragment.hpp:52
MolecularGraph.
Definition: MolecularGraph.hpp:52
CDPL_BIOMOL_API const std::string & getChainID(const Chem::Atom &atom)
CDPL_BIOMOL_API void setChainID(Chem::Atom &atom, const std::string &id)
constexpr unsigned int DOWN
Specifies that the bond is directed downwards.
Definition: BondDirection.hpp:67
constexpr unsigned int UP
Specifies that the bond is directed upwards.
Definition: BondDirection.hpp:60
CDPL_CHEM_API unsigned int getType(const Atom &atom)
Matrix< unsigned long > ULMatrix
An unbounded dense matrix holding unsigned integers of type unsigned long.
Definition: Matrix.hpp:1824
CVector< double, 2 > Vector2D
A bounded 2 element vector holding floating point values of type double.
Definition: Vector.hpp:1632
VectorArray< Vector2D > Vector2DArray
An array of Math::Vector2D objects.
Definition: VectorArray.hpp:79
boost::dynamic_bitset BitSet
A dynamic bitset class.
Definition: BitSet.hpp:46
The namespace of the Chemical Data Processing Library.
Definition: Atom2DCoordinatesCalculator.hpp:229
const LGEdge * edge
Definition: Atom2DCoordinatesCalculator.hpp:234
double angle
Definition: Atom2DCoordinatesCalculator.hpp:235
NodeLayoutInfo(const LGEdge *edge, double angle)
Definition: Atom2DCoordinatesCalculator.hpp:231