Chemical Data Processing Library C++ API - Version 1.4.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 
68  {
69 
70  public:
75 
87 
89 
91 
101  void calculate(const MolecularGraph& molgraph, Math::Vector2DArray& coords);
102 
103  private:
104  class RingInfo
105  {
106 
107  public:
108  void init(const MolecularGraph*, const Fragment&, std::size_t, std::size_t);
109 
110  const Fragment& getFragment() const;
111 
112  const Util::BitSet& getAtomMask() const;
113  const Util::BitSet& getBondMask() const;
114 
115  double getPriority() const;
116  void setPriority(double);
117 
118  std::size_t getSize() const;
119 
120  private:
121  const Fragment* fragment;
122  Util::BitSet atomMask;
123  Util::BitSet bondMask;
124  double priority;
125  };
126 
127  class LGNode;
128 
129  class LGEdge
130  {
131 
132  public:
133  enum Type
134  {
135 
136  BOND_EDGE,
137  SPIRO_EDGE
138  };
139 
140  void init(const MolecularGraph*, const Atom*, LGNode*, LGNode*, std::size_t);
141  void init(const MolecularGraph*, const Bond*, LGNode*, LGNode*, std::size_t);
142 
143  const Atom* getSpiroCenter() const;
144  const Bond* getBond() const;
145 
146  LGNode* otherNode(const LGNode*) const;
147 
148  Type getType() const;
149  std::size_t getID() const;
150 
151  bool hasConfigConstraint() const;
152  bool configConstraintFulfilled(const Math::Vector2DArray&) const;
153 
154  private:
155  bool initConfigInfo();
156 
157  const MolecularGraph* molGraph;
158  const Atom* spiroCenter;
159  const Bond* bond;
160  LGNode* node1;
161  LGNode* node2;
162  Type type;
163  bool hasConfig;
164  unsigned int configuration;
165  const Atom* configRefAtoms[2];
166  std::size_t id;
167  };
168 
169  typedef std::vector<std::size_t> AtomIndexList;
170  typedef std::vector<const Bond*> BondList;
171  typedef std::vector<LGNode*> NodeList;
172 
173  class LGNode
174  {
175 
176  public:
177  enum Type
178  {
179 
180  RING_SYS = 0x1,
181  CHAIN_ATOM = 0x2,
182  END_ATOM = 0x3
183  };
184 
185  enum Direction
186  {
187 
188  UP,
189  DOWN
190  };
191 
192  virtual ~LGNode() {}
193 
194  void init(const MolecularGraph* molgraph);
195 
196  virtual void addEdge(const Atom*, const LGEdge*) = 0;
197 
198  virtual void getChildNodes(NodeList&) const = 0;
199 
200  virtual void init() = 0;
201 
202  virtual void createChildLayouts() = 0;
203 
204  virtual double getPriority() const = 0;
205 
206  virtual std::size_t getChainID() const = 0;
207 
208  virtual void layout() = 0;
209  virtual bool layout(double, const Math::Vector2D&, std::size_t&, std::size_t, bool) = 0;
210 
211  virtual bool layoutChildNodes(std::size_t&, std::size_t, bool) = 0;
212 
213  virtual Type getType() const = 0;
214 
215  virtual double getAngularDemand(const Atom*) const;
216 
217  virtual bool setParentEdge(const LGEdge*, Direction) = 0;
218 
219  protected:
220  std::size_t countAtomCollisions(const AtomIndexList&, const AtomIndexList&, const Math::Vector2DArray&);
221  std::size_t countAtomCollisionsForAtom(std::size_t, const AtomIndexList&, const Math::Vector2DArray&);
222 
223  std::size_t countBondCollisions(const BondList&, const BondList&, const Math::Vector2DArray&);
224  std::size_t countBondCollisionsForBond(const Bond*, const BondList&, const Math::Vector2DArray&);
225 
226  std::size_t countAtomBondCollisions(const AtomIndexList&, const BondList&, const Math::Vector2DArray&);
227  std::size_t countBondCollisionsForAtom(std::size_t, const BondList&, const Math::Vector2DArray&);
228 
229  std::size_t countBondAtomCollisions(const BondList&, const AtomIndexList&, const Math::Vector2DArray&);
230  std::size_t countAtomCollisionsForBond(const Bond*, const AtomIndexList&, const Math::Vector2DArray&);
231 
232  bool testAtomBondCollision(std::size_t, const Bond*, const Math::Vector2DArray&);
233 
235  {
236 
237  NodeLayoutInfo(const LGEdge* edge, double angle):
238  edge(edge), angle(angle) {}
239 
240  const LGEdge* edge;
241  double angle;
242  };
243 
244  typedef std::vector<NodeLayoutInfo> NodeLayoutInfoList;
245  typedef std::pair<double, double> AngleRange;
246 
247  class EdgePriorityGreaterCmpFunc;
248 
249  class LinkedNodePriorityLessCmpFunc;
250  class LinkedNodePriorityEqualCmpFunc;
251 
252  class NodeLayoutInfoListEqualCmpFunc;
253 
254  const MolecularGraph* molGraph;
255  };
256 
257  typedef std::list<RingInfo*> RingInfoList;
258  typedef std::vector<const LGEdge*> EdgeList;
259 
260  class RingSysNode : public LGNode
261  {
262 
263  public:
264  RingSysNode();
265 
266  void init(const MolecularGraph*, const RingInfo*, Math::Vector2DArray&,
267  AtomIndexList&, BondList&);
268 
269  const Util::BitSet& getAtomMask() const;
270  const Util::BitSet& getBondMask() const;
271 
272  bool containsAtom(std::size_t) const;
273 
274  bool addRing(const RingInfo*);
275 
276  void addEdge(const Atom*, const LGEdge*);
277 
278  void getChildNodes(NodeList&) const;
279 
280  void init();
281 
282  double getPriority() const;
283 
284  std::size_t getChainID() const;
285 
286  void layout();
287  bool layout(double, const Math::Vector2D&, std::size_t&, std::size_t, bool);
288 
289  bool layoutChildNodes(std::size_t&, std::size_t, bool);
290 
291  Type getType() const;
292 
293  double getAngularDemand(const Atom*) const;
294 
295  bool setParentEdge(const LGEdge*, Direction);
296 
297  private:
298  bool layoutChildNodes(double, double, bool, double, std::size_t&, std::size_t, bool);
299  bool layoutChildNodes(std::size_t, std::size_t&, std::size_t, bool);
300 
301  void createChildLayouts();
302  void createChildLayouts(const Atom*, EdgeList&);
303 
304  bool layout(std::size_t, const Math::Vector2D&, double, bool, double, std::size_t&, std::size_t);
305 
306  void transformCoords(std::size_t, const Math::Vector2D&, double, bool, double);
307 
308  double transformEdgeAngle(double) const;
309 
310  void copyCoords();
311 
312  void commitAtomAndBondList() const;
313 
314  void calcCoords();
315 
316  void calcCoordsForRing(const RingInfo*);
317  void calcCoordsForRingSegment(const RingInfo*);
318 
319  void refineLayout();
320 
321  void initSpringLayoutParams();
322  void performSpringLayout();
323 
324  void performDistGeomLayout();
325  bool needDistGeomLayout() const;
326  bool addBondStereoDGConstraints(const RingInfo* ring_info);
327  void addBondAngleDGConstraints(const RingInfo* ring_info);
328  void addDefaultDGConstraints();
329 
330  const Chem::Atom* getExoBondAtom(const RingInfo* ring_info, const Atom& atom, std::size_t rings_nbrs[2]) const;
331 
332  Math::Vector2D computePartialDerivatives(std::size_t) const;
333  Math::Vector2D computePartialDerivative(std::size_t, std::size_t) const;
334 
335  bool layoutFinished(bool, double, double&, double&) const;
336 
337  void distributeWeightFactors(std::size_t, double, const Math::ULMatrix&);
338 
339  void calcFreeSweeps();
340 
341  bool getNextRingSegment(const RingInfo*);
342 
343  double calcCongestionFactor(const Math::Vector2D&) const;
344  double calcCongestionFactor(const Math::Vector2D&, const Util::BitSet&) const;
345 
346  typedef Util::DGCoordinatesGenerator<2, double> DGCoordsGenerator;
347  typedef std::pair<std::size_t, std::size_t> DistConstraintKey;
348  typedef boost::unordered_set<DistConstraintKey> DistConstraintKeySet;
349  typedef std::vector<const RingInfo*> RingInfoList;
350  typedef std::list<const RingInfo*> RingLayoutQueue;
351  typedef std::map<std::size_t, EdgeList> EdgeListMap;
352  typedef std::map<const Atom*, AngleRange> AngleRangeMap;
353  typedef std::deque<std::size_t> RingSegment;
354  typedef std::vector<std::vector<NodeLayoutInfoList> > NodeLayoutInfoListTable;
355  typedef std::vector<std::size_t> LayoutIndexTable;
356  typedef std::vector<const Atom*> AtomTable;
357  typedef std::vector<Math::Vector2D> EnergyDerivativeTable;
358  typedef std::vector<double> WeightFactorTable;
359 
360  Util::BitSet atomMask;
361  Util::BitSet bondMask;
362  Util::BitSet procAtomMask;
363  Util::BitSet tmpBitMask;
364  double priority;
365  RingInfoList ringList;
366  RingLayoutQueue ringLayoutQueue;
367  RingSegment ringSegment;
368  EdgeListMap edgeListMap;
369  AngleRangeMap freeSweepMap;
370  AtomIndexList atomList;
371  BondList bondList;
372  AtomIndexList* procAtomList;
373  BondList* procBondList;
374  Math::Vector2DArray localCoords;
375  Math::Vector2DArray* outputCoords;
376  const LGEdge* parentEdge;
377  const Atom* parentEdgeAtom;
378  EdgeList parentEdgeAtomEdges;
379  NodeLayoutInfoListTable childLayouts;
380  LayoutIndexTable childLayoutIndexTable;
381  AtomTable edgeAtomTable;
382  Math::Vector2D parentPos;
383  std::size_t rsysLayoutIndex;
384  double parentEdgeAngle;
385  double rsysRotAngle;
386  double rsysAxisAngle;
387  bool flipped;
388  WeightFactorTable layoutWeightFactors;
389  EnergyDerivativeTable layoutEnergyDerivatives;
390  Math::DMatrix layoutAtomDistances;
391  Math::DMatrix layoutSpringStrengths;
392  DGCoordsGenerator dgCoordsGenerator;
393  DistConstraintKeySet setDistConstraints;
394  };
395 
396  class AtomNode : public LGNode
397  {
398 
399  public:
400  void init(const MolecularGraph*, const Atom*, double, Math::Vector2DArray&, AtomIndexList&, BondList&);
401 
402  void addEdge(const Atom*, const LGEdge*);
403 
404  const Atom* getAtom() const;
405  std::size_t getAtomIndex() const;
406 
407  void getChildNodes(NodeList&) const;
408 
409  void init();
410 
411  double getPriority() const;
412 
413  std::size_t getChainID() const;
414 
415  void setChainID(std::size_t);
416 
417  void layout();
418  bool layout(double, const Math::Vector2D&, std::size_t&, std::size_t, bool);
419 
420  bool layoutChildNodes(std::size_t&, std::size_t, bool);
421 
422  Type getType() const;
423 
424  bool setParentEdge(const LGEdge*, Direction);
425 
426  private:
427  struct LayoutParameters
428  {
429 
430  LayoutParameters(std::size_t num_colls):
431  numCollisions(num_colls) {}
432 
433  std::size_t numCollisions;
434  double bondLength{0.0};
435  double edgeAngle{0.0};
436  };
437 
438  void layout(double, double, const Math::Vector2D&, std::size_t, std::size_t, LayoutParameters&);
439 
440  std::size_t getChildNodeTypePattern() const;
441 
442  void createChildLayouts();
443 
444  void createChildLayoutsD1();
445  void createChildLayoutsD2();
446  void createChildLayoutsD3();
447  void createChildLayoutsD4();
448  void createChildLayoutsDN();
449 
450  void removeChildLayoutSymmetryDuplicates();
451 
452  void removeParentEdge();
453 
454  void sortChildEdges();
455 
456  typedef std::vector<NodeLayoutInfoList> NodeLayoutInfoListTable;
457 
458  const Atom* atom;
459  std::size_t atomIndex;
460  bool isHydrogen;
461  Type type;
462  double priority;
463  std::size_t chainID;
464  AtomIndexList* procAtomList;
465  BondList* procBondList;
466  Math::Vector2DArray* outputCoords;
467  Direction chainDirection;
468  double parentEdgeAngle;
469  EdgeList edges;
470  const LGEdge* parentEdge;
471  NodeLayoutInfoListTable childLayouts;
472  std::size_t childLayoutIndex;
473  Direction childChainDirections[4];
474  };
475 
476  typedef std::pair<Math::Vector2D, Math::Vector2D> BoundingBox;
477 
478  void init(const MolecularGraph&, Math::Vector2DArray&);
479 
480  void extractRingInformation();
481 
482  void calcAtomPriorities();
483  void calcRingPriorities();
484 
485  void layoutComponents(Math::Vector2DArray&);
486  void layoutComponent(const Fragment&, Math::Vector2DArray&);
487 
488  void alignComponents(Math::Vector2DArray&);
489 
490  void moveComponent(const BoundingBox&, double, double, const Fragment&, Math::Vector2DArray&);
491  void addPoint(BoundingBox&, const Math::Vector2D&) const;
492  void calcBounds(BoundingBox&, const Fragment&, Math::Vector2DArray&) const;
493 
494  void createLayoutTree(const Fragment&, Math::Vector2DArray&);
495  void createRingSysNodes(const Fragment&, Math::Vector2DArray&);
496  void createAtomNodes(const Fragment&, Math::Vector2DArray&);
497  void createBondEdges(const Fragment&);
498  void createSpiroEdges(const Fragment&);
499 
500  void setAtomNodeChainIDs();
501 
502  void findLongestNodePath(AtomNode*, const AtomNode*);
503 
504  void createBFSNodeList();
505  void initNodes() const;
506 
507  void layoutNodes();
508  bool layoutChildNodes(std::size_t);
509 
510  LGEdge* allocEdge(const Atom*, LGNode*, LGNode*);
511  LGEdge* allocEdge(const Bond*, LGNode*, LGNode*);
512 
513  RingInfo* allocRingInfo(const Fragment&);
514  RingSysNode* allocRingSysNode(const RingInfo*, Math::Vector2DArray&);
515 
516  AtomNode* allocAtomNode(const Atom*, Math::Vector2DArray&);
517 
518  void freeAllocEdges();
519  void freeAllocRingInfos();
520  void freeAllocRingSysNodes();
521  void freeAllocAtomNodes();
522 
523  typedef std::vector<AtomNode*> AtomNodeList;
524  typedef std::vector<std::size_t> AtomPriorityTable;
525  typedef Util::ObjectStack<RingInfo> RingInfoCache;
526  typedef Util::ObjectStack<RingSysNode> RingSysNodeCache;
527  typedef Util::ObjectStack<AtomNode> AtomNodeCache;
528  typedef Util::ObjectStack<LGEdge> EdgeCache;
529  typedef std::vector<RingSysNode*> RingSysNodeList;
530 
531  const MolecularGraph* molGraph;
532  RingInfoCache ringInfoCache;
533  RingSysNodeCache ringSysNodeCache;
534  AtomNodeCache atomNodeCache;
535  EdgeCache edgeCache;
536  EdgeList edgeList;
537  RingInfoList ringList;
538  RingSysNodeList ringSysNodeList;
539  AtomNodeList atomNodeList;
540  RingInfoList tmpRingList;
541  NodeList bfsNodeList;
542  AtomNodeList atomNodeTable;
543  AtomNodeList longestAtomNodePath;
544  AtomNodeList currAtomNodePath;
545  AtomIndexList procAtomList;
546  BondList procBondList;
547  Util::BitSet atomMask;
548  Util::BitSet ringAtomMask;
549  Util::BitSet tmpBitMask;
550  AtomPriorityTable atomPriorityTable;
551  std::size_t numAtoms;
552  std::size_t numBonds;
553  bool strictLayoutGeometry;
554  std::size_t numLayoutCollisions;
555  std::size_t maxNumLayoutCollisions;
556  std::size_t backtrackingCount;
557  std::size_t nextEdgeID;
558  };
559  } // namespace Chem
560 } // namespace CDPL
561 
562 #endif // CDPL_CHEM_ATOM2DCOORDINATESCALCULATOR_HPP
Declaration of 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 class CDPL::Util::ObjectStack.
Definition of class CDPL::Math::VectorArray.
Generates 2D coordinates for the atoms of a molecular graph.
Definition: Atom2DCoordinatesCalculator.hpp:68
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
Abstract base class representing a chemical atom and its bonded neighborhood.
Definition: Atom.hpp:58
Concrete implementation of the Chem::MolecularGraph interface that stores references to selectable Ch...
Definition: Fragment.hpp:60
Abstract base class for data structures that represent chemical structures as molecular graphs.
Definition: MolecularGraph.hpp:60
CDPL_BIOMOL_API const std::string & getChainID(const Chem::Atom &atom)
Returns the value of the Biomol::AtomProperty::CHAIN_ID property of the atom atom.
CDPL_BIOMOL_API void setChainID(Chem::Atom &atom, const std::string &id)
Sets the value of the Biomol::AtomProperty::CHAIN_ID property of the atom atom to 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)
Returns the value of the Chem::AtomProperty::TYPE property of the atom atom.
Matrix< unsigned long > ULMatrix
Unbounded dense matrix holding unsigned integers of type unsigned long.
Definition: Matrix.hpp:3479
CVector< double, 2 > Vector2D
Bounded 2 element vector holding floating-point values of type double.
Definition: Vector.hpp:3213
VectorArray< Vector2D > Vector2DArray
Array storing vectors of type Math::Vector2D.
Definition: VectorArray.hpp:82
boost::dynamic_bitset BitSet
Dynamic bitset class.
Definition: BitSet.hpp:46
The namespace of the Chemical Data Processing Library.
Definition: Atom2DCoordinatesCalculator.hpp:235
const LGEdge * edge
Definition: Atom2DCoordinatesCalculator.hpp:240
double angle
Definition: Atom2DCoordinatesCalculator.hpp:241
NodeLayoutInfo(const LGEdge *edge, double angle)
Definition: Atom2DCoordinatesCalculator.hpp:237