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