IMP logo
IMP Reference Guide  2.6.0
The Integrative Modeling Platform
atom/Hierarchy.h
Go to the documentation of this file.
1 /**
2  * \file IMP/atom/Hierarchy.h
3  * \brief Decorator for helping deal with a hierarchy of molecules.
4  *
5  * Copyright 2007-2016 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPATOM_HIERARCHY_H
10 #define IMPATOM_HIERARCHY_H
11 
12 #include <IMP/atom/atom_config.h>
13 #include <IMP/core/utility.h>
14 #include <IMP/core/Hierarchy.h>
15 #include "bond_decorators.h"
16 #include "atom_macros.h"
17 #include <IMP/core/XYZR.h>
18 #include <IMP/core/rigid_bodies.h>
19 
20 #include <IMP/Particle.h>
21 #include <IMP/Model.h>
22 
23 #include <vector>
24 #include <deque>
25 
26 #define IMP_ATOM_GET_AS_DECL(UCName, lcname, CAPSNAME) \
27  IMPATOM_DEPRECATED_METHOD_DECL(2.6) \
28  UCName get_as_##lcname() const;
29 
30 // figure out how to inline
31 #define IMP_ATOM_GET_AS_DEF(UCName, lcname, CAPSNAME) \
32  UCName Hierarchy::get_as_##lcname() const { \
33  IMPATOM_DEPRECATED_METHOD_DEF(2.6, "Use decorators instead"); \
34  if (UCName::get_is_setup(get_particle())) { \
35  return UCName(get_particle()); \
36  } else { \
37  return UCName(); \
38  } \
39  }
40 
41 // DOMAIN is defined to be 1 by a fedora math header
42 #define IMP_ATOM_FOREACH_HIERARCHY_TYPE_LIST(macro) \
43  macro(Atom, atom, ATOM_TYPE), macro(Residue, residue, RESIDUE_TYPE), \
44  macro(Chain, chain, CHAIN_TYPE), \
45  macro(Molecule, molecule, MOLECULE_TYPE), \
46  macro(Domain, domain, DOMAIN_TYPE), \
47  macro(Fragment, fragment, FRAGMENT_TYPE), \
48  macro(core::XYZ, xyz, XYZ_TYPE), macro(core::XYZR, xyzr, XYZR_TYPE), \
49  macro(Mass, mass, MASS_TYPE), \
50  macro(State, state, STATE_TYPE)
51 
52 // DOMAIN is defined to be 1 by a fedora math header
53 #define IMP_ATOM_FOREACH_HIERARCHY_TYPE_STATEMENTS(macro) \
54  macro(Atom, atom, ATOM_TYPE); \
55  macro(Residue, residue, RESIDUE_TYPE); \
56  macro(Chain, chain, CHAIN_TYPE); \
57  macro(Molecule, molecule, MOLECULE_TYPE); \
58  macro(Domain, domain, DOMAIN_TYPE); \
59  macro(Fragment, fragment, FRAGMENT_TYPE); \
60  macro(core::XYZ, xyz, XYZ_TYPE); \
61  macro(core::XYZR, xyzr, XYZR_TYPE); \
62  macro(Mass, mass, MASS_TYPE); \
63  macro(State, state, STATE_TYPE)
64 
65 // DOMAIN is defined to be 1 by a fedora math header
66 #define IMP_ATOM_FOREACH_HIERARCHY_TYPE_FUNCTIONS(macro) \
67  macro(Atom, atom, ATOM_TYPE) macro(Residue, residue, RESIDUE_TYPE) \
68  macro(Chain, chain, CHAIN_TYPE) macro(Molecule, molecule, MOLECULE_TYPE) \
69  macro(Domain, domain, DOMAIN_TYPE) \
70  macro(Fragment, fragment, FRAGMENT_TYPE) macro(core::XYZ, xyz, XYZ_TYPE) \
71  macro(core::XYZR, xyzr, XYZR_TYPE) macro(Mass, mass, MASS_TYPE) \
72  macro(State, state, STATE_TYPE)
73  IMP_REQUIRE_SEMICOLON_NAMESPACE
74 
75 #define IMP_ATOM_CAPS_NAME(UCName, lcname, CAPSNAME) CAPSNAME
76 
77 IMPATOM_BEGIN_NAMESPACE
78 class Atom;
79 class Residue;
80 class Domain;
81 class Fragment;
82 class Chain;
83 class Molecule;
84 class Mass;
85 class State;
86 class Representation;
87 
88 IMP_DECORATORS_DECL(Hierarchy, Hierarchies);
89 
90 //! The standard decorator for manipulating molecular structures.
91 /** \imp represents molecular structures using the Hierarchy decorator.
92  Molecules and collections of molecules each are stored as a
93  hierarchy (or tree) where the resolution of the representation increases
94  as you move further from the root. That is, if a parent has
95  some particular property (eg, marks out a volume by having
96  x,y,z coordinates and a radius), then the children should have
97  a higher resolution form of that information (eg, mark out a more
98  detailed excluded volume by defining a set of balls which have
99  approximately the same total volume).
100 
101  \section tree_basics Tree Basics
102  In a tree you have a set of nodes, represented by Hierarchy particles.
103  Each node can have at most one parent. The node with no
104  parent is known as the root of the tree.
105 
106  Here is a simple example with a protein with three residues. Two of the
107  residues have atoms, where as the third is coarse grained.
108  \dotgraph{\dot
109  digraph example {
110  node [shape=record\, fontname= Helvetica\, fontsize=10]
111  a [label="Protein A (the root)"];
112  b [label="Residue 0"\, URL="Residue"];
113  c [label="Residue 1"];
114  cp [label="Residue 2"];
115  d0 [label="CA"];
116  e0 [label="CA"];
117  d1 [label="C"];
118  e1 [label="C"];
119  d2 [label="N"];
120  e2 [label="N"];
121  a -> b [arrowhead="open"];
122  a -> c [arrowhead="open"]
123  a -> cp [arrowhead="open"];
124  b -> d0 [arrowhead="open"];
125  c -> e0 [arrowhead="open"];
126  b -> d1 [arrowhead="open"];
127  c -> e1 [arrowhead="open"];
128  b -> d2 [arrowhead="open"];
129  c -> e2 [arrowhead="open"];
130  }
131  \enddot
132  }
133 
134 
135  The nodes in the hierarchy can correspond to arbitrary bits of a
136  molecule and do not need to have any biological significance. For
137  example we could introduce a fragment containing residues 0 and 1:
138  \dotgraph{\dot
139  digraph example {
140  node [shape=record\, fontname= Helvetica\, fontsize=10]
141  a [label="Protein A (the root)"];
142  aa [label="Fragment 0"];
143  b [label="Residue 0"];
144  c [label="Residue 1"];
145  cp [label="Residue 2"];
146  d0 [label="CA"];
147  e0 [label="CA"];
148  d1 [label="C"];
149  e1 [label="C"];
150  d2 [label="N"];
151  e2 [label="N"];
152  a -> aa [arrowhead="open"];
153  aa -> b [arrowhead="open"];
154  aa -> c [arrowhead="open"]
155  a -> cp [arrowhead="open"];
156  b -> d0 [arrowhead="open"];
157  c -> e0 [arrowhead="open"];
158  b -> d1 [arrowhead="open"];
159  c -> e1 [arrowhead="open"];
160  b -> d2 [arrowhead="open"];
161  c -> e2 [arrowhead="open"];
162  }
163  \enddot}
164 
165 
166  A hierarchy can have any tree structure as long as:
167  - the type of the parent makes sense for the child: eg a Residue
168  cannot be the parent of a Chain.
169  - the leaves always have coordinates, radius and mass
170  - all particles in the hierarchy are from the same model
171  - all Atoms have a Residue as the parent
172  - any Atom with a non-heterogen atom type is part of a protein,
173  DNA or RNA molecule
174  - all Residue children of a particle appear in order based
175  on their index
176  - all Atom children of a particle appear in order of their
177  AtomType
178  - if a node has residue indexes, all its descendants down to the
179  residue level also do.
180 
181  The get_is_valid() method checks some of these properties. Any
182  method taking a hierarchy as an argument should do
183  \code
184  IMP_USAGE_CHECK(h.get_is_valid(), "Invalid hierarchy as input");
185  \endcode
186  to make sure the hierarchy makes sense.
187 
188  A number of decorator types are associated with the Hierarchy
189  to store the information associated with that node in the
190  hierarchy. Examples include Residue, Atom, XYZ, Chain, XYZR,
191  Mass, Domain, Molecule etc.
192 
193  \note Deleting a Hierarchy, like deleting any decorator, will not
194  delete the underlying Particle or remove any children. To do
195  that, call destroy().
196 
197  \see Atom
198  \see Residue
199  \see Chain
200  \see Molecule
201  \see Domain
202  \see Fragment
203  \see Mass
204  \see State
205  \see Representation
206  */
207 class IMPATOMEXPORT Hierarchy : public core::Hierarchy {
208  typedef core::Hierarchy H;
209 
210  public:
211 #ifndef IMP_DOXYGEN
212  typedef boost::false_type DecoratorHasTraits;
213 
214  //! Setup the particle as a hierarchy; add the passed particles as children.
216  ParticleIndexesAdaptor children) {
217  H::setup_particle(p, get_traits());
218  Hierarchy ret(p);
219  for (unsigned int i = 0; i < children.size(); ++i) {
220  if (!get_is_setup(p->get_model(), children[i])) {
221  setup_particle(p->get_model(), children[i]);
222  }
223  ret.add_child(Hierarchy(p->get_model(), children[i]));
224  }
225  return ret;
226  }
227 
228  static Hierarchy setup_particle(Particle *p) {
229  return setup_particle(p->get_model(), p->get_index());
230  }
231 
232  static bool get_is_setup(Particle *p) {
233  return H::get_is_setup(p, get_traits());
234  }
235 #endif
236 
238  : H(m, pi, get_traits()) {}
239 
241  : H(pi.get_model(), pi.get_particle_index(), get_traits()) {}
242 
243  //! Null constructor
245 
246  //! The traits must match
247  explicit Hierarchy(IMP::core::Hierarchy h) : H(h) {
249  h != IMP::core::Hierarchy() || h.get_decorator_traits() == get_traits(),
250  "Cannot construct a IMP.atom.Hierarchy from a general "
251  " IMP.core.Hierarchy");
252  }
253 
254  //! Create a Hierarchy of level t by adding the needed attributes.
256  ParticleIndexesAdaptor children =
258  H::setup_particle(m, pi, get_traits());
259  Hierarchy ret(m, pi);
260  for (unsigned int i = 0; i < children.size(); ++i) {
261  if (!get_is_setup(m, children[i])) {
262  setup_particle(m, children[i]);
263  }
264  ret.add_child(Hierarchy(m, children[i]));
265  }
266  return ret;
267  }
268 
269  //! Check if the particle has the needed attributes for a cast to succeed
270  static bool get_is_setup(Model *m, ParticleIndex p) {
271  return H::get_is_setup(m->get_particle(p), get_traits());
272  }
273 
274  //! Return true if the hierarchy is valid.
275  /** Print information about the hierarchy if print_info is
276  true and things are invalid.
277  \note Returning true only means that no problems were
278  found; it can't check everything.*/
279  bool get_is_valid(bool print_info=false) const;
280 
281  //! Add a child and check that the types are appropriate
282  /** A child must have a type that is listed before the parent in the
283  Type enum list.
284  */
286  IMP_USAGE_CHECK(o != *this, "Can't add something as its own child");
287  H::add_child(o);
288  }
289 
290 #ifndef IMP_DOXYGEN
291  void show(std::ostream &out, std::string delimiter) const;
292 #endif
293 
294  //! Get the ith child based on the order they were added.
295  Hierarchy get_child(unsigned int i) const {
296  H hd = H::get_child(i);
297  return Hierarchy(hd);
298  }
299  //! Return the children in the order they were added
301  Hierarchies ret(get_number_of_children());
302  for (unsigned int i = 0; i < get_number_of_children(); ++i) {
303  ret[i] = get_child(i);
304  }
305  return ret;
306  }
307 
308  //! Get the children in a container of your choosing, eg ParticlesTemp
309  template <class C>
310  C get_children() const {
311  C ret(get_number_of_children());
312  for (unsigned int i = 0; i < get_number_of_children(); ++i) {
313  ret[i] = get_child(i);
314  }
315  return ret;
316  }
317 
318  //! Get the parent particle.
320  H hd = H::get_parent();
321  if (hd == H()) {
322  return Hierarchy();
323  } else {
324  return Hierarchy(hd);
325  }
326  }
327 
328 #ifndef IMP_DOXYGEN
329  IMP_ATOM_FOREACH_HIERARCHY_TYPE_FUNCTIONS(IMP_ATOM_GET_AS_DECL);
330 #endif
331 
332  //! Get the molecular hierarchy HierarchyTraits.
333  static const IMP::core::HierarchyTraits &get_traits();
334 
335  // swig overwrites __repr__ if it is inherited
337 };
338 
339 IMP_DECORATORS_DEF(Hierarchy, Hierarchies);
340 
341 #ifdef IMP_DOXYGEN
342 //! The different types which can be passed to get_by_type()
343 enum GetByType {
344  ATOM_TYPE,
345  RESIDUE_TYPE,
346  CHAIN_TYPE,
347  MOLECULE_TYPE,
348  DOMAIN_TYPE,
349  FRAGMENT_TYPE,
350  XYZ_TYPE,
351  XYZR_TYPE,
352  MASS_TYPE,
353  STATE_TYPE
354 };
355 #else
356 enum GetByType {
357  IMP_ATOM_FOREACH_HIERARCHY_TYPE_LIST(IMP_ATOM_CAPS_NAME)
358 };
359 #endif
360 
361 //! Gather all the molecular particles of a certain level in the hierarchy.
362 /** \relates Hierarchy */
363 IMPATOMEXPORT Hierarchies get_by_type(Hierarchy mhd, GetByType t);
364 
365 //! Get the residue with the specified index
366 /** Find the leaf containing the residue with the appropriate index.
367  This is the PDB index, not the offset in the chain (if they are different).
368 
369  The function returns a Hierarchy, rather than a Residue since the
370  residue may not be explicitly represented and may just be part of some
371  fragment.
372 
373  \throw ValueException if mhd's type is not one of CHAIN, PROTEIN, NUCLEOTIDE
374  \return Hierarchy() if that residue is not found.
375 
376  \relates Hierarchy
377  */
378 IMPATOMEXPORT Hierarchy get_residue(Hierarchy mhd, unsigned int index);
379 
380 //! Create a fragment containing the specified nodes
381 /** A particle representing the fragment is created and initialized.
382 
383  The Fragment is inserted as a child of the parent (and the particles are
384  removed). The particles become children of the fragment.
385 
386  \throw ValueException If all the particles do not have the same parent.
387  \relates Hierarchy
388  */
389 IMPATOMEXPORT Hierarchy create_fragment(const Hierarchies &ps);
390 
391 //! Get the bonds internal to this tree
392 /** \relates Hierarchy
393  \see Bond
394  */
395 IMPATOMEXPORT Bonds get_internal_bonds(Hierarchy mhd);
396 
397 //! Return the root of the hierarchy
398 /** \relates Hierarchy */
400  while (h.get_parent()) {
401  h = h.get_parent();
402  }
403  return h;
404 }
405 
406 /** \relates Hierarchy */
409 }
410 
411 /** \relates Hierarchy */
413  ParticlesTemp ret;
414  for (unsigned int i = 0; i < h.size(); ++i) {
415  core::GenericHierarchies cur = IMP::core::get_leaves(h[i]);
416  ret.insert(ret.end(), cur.begin(), cur.end());
417  }
418  return get_as<Hierarchies>(ret);
419 }
420 
421 //! Print out a molecular hierarchy
422 /** \relates Hierarchy
423  */
424 inline void show(Hierarchy h, std::ostream &out = std::cout) {
425  IMP::core::show<Hierarchy>(h, out);
426 }
427 
428 //! Rigidify a molecule or collection of molecules.
429 /** The rigid body created has all the leaves as members and a
430  member rigid body for each internal node in the tree. The
431  particle created to be the rigid body is returned.
432 
433  A name can be passed as it is not easy to automatically pick
434  a decent name.
435  \see create_aligned_rigid_body()
436  \see Hierarchy
437  \see IMP::core::RigidBody
438 */
440  const Hierarchies &h, std::string name = std::string("created rigid body"));
441 
442 /** \see create_rigid_body(const Hierarchies&)
443  */
445 
446 //! Rigidify a molecule or collection of molecules.
447 /** This method is identical to create_rigid_body() except that
448  the chosen reference frame is aligned with that of reference
449  (which must have exactly the same set of particles). This allows
450  one to make sure the rigid body is equivalent when you have several
451  copies of the same molecule.
452 
453  \see Hierarchy
454  \see IMP::core::RigidBody
455 */
457  Hierarchy h, Hierarchy reference);
458 
459 #ifndef IMP_DOXYGEN
460 IMPATOMEXPORT IMP::core::RigidBody setup_as_rigid_body(Hierarchy h);
461 #endif
462 
463 //! Return true if the piece of hierarchy should be classified as a heterogen
464 /** For the purposes of classification, a heterogen is anything that
465  - is a heterogen atom (one whose name starts with HET:)
466  - is or is part of a Residue that is not a normal protein, rna or
467  dna residue
468  - or is not part of a Chain
469 
470  For the moment, this can only be called on residues or atoms.
471  \relates Hierarchy
472 */
473 IMPATOMEXPORT bool get_is_heterogen(Hierarchy h);
474 
475 //! Clone the Hierarchy
476 /** This method copies the Bond, Bonded, Atom,
477  Residue, and Domain data and the particle name to the
478  new copies in addition to the Hierarchy relationships.
479 
480  \relates Hierarchy
481 */
482 IMPATOMEXPORT Hierarchy create_clone(Hierarchy d);
483 
484 //! Clone the node in the Hierarchy
485 /** This method copies the Atom,
486  Residue, Chain and Domain data and the particle name.
487 
488  \relates Hierarchy
489 */
490 IMPATOMEXPORT Hierarchy create_clone_one(Hierarchy d);
491 
492 //! Delete the Hierarchy
493 /** All bonds connecting to these atoms are destroyed as are
494  hierarchy links in the Hierarchy and the particles are
495  removed from the Model. If this particle has a parent, it is
496  removed from the parent.
497  \relates Hierarchy
498 */
499 IMPATOMEXPORT void destroy(Hierarchy d);
500 
501 //! Get a bounding box for the Hierarchy
502 /** This bounding box is that of the highest (in the CS sense of a tree
503  growing down from the root) cut
504  through the tree where each node in the cut has x,y,z, and r.
505  That is, if the root has x,y,z,r then it is the bounding box
506  of that sphere. If only the leaves have radii, it is the bounding
507  box of the leaves. If no such cut exists, the behavior is undefined.
508  \relates Hierarchy
509  \see IMP::algebra::BoundingBoxD
510  */
511 IMPATOMEXPORT algebra::BoundingBoxD<3> get_bounding_box(const Hierarchy &h);
512 
513 /** See get_bounding_box() for more details.
514  \relates Hierarchy
515  */
516 IMPATOMEXPORT algebra::Sphere3D get_bounding_sphere(const Hierarchy &h);
517 
518 IMPATOM_END_NAMESPACE
519 
520 #endif /* IMPATOM_HIERARCHY_H */
Particle * get_particle(ParticleIndex p) const
Decorator for helping deal with a hierarchy.
Various important functionality for implementing decorators.
Hierarchy get_parent() const
Get the parent particle.
Hierarchies get_leaves(const Hierarchies &h)
Hierarchy create_clone(Hierarchy d)
Clone the Hierarchy.
void add_child(Hierarchy o)
Add a child and check that the types are appropriate.
IMP::core::RigidBody create_compatible_rigid_body(Hierarchy h, Hierarchy reference)
Rigidify a molecule or collection of molecules.
Hierarchy()
Null constructor.
Storage of a model, its restraints, constraints and particles.
void destroy(Hierarchy d)
Delete the Hierarchy.
#define IMP_SHOWABLE(Name)
Hierarchy create_fragment(const Hierarchies &ps)
Create a fragment containing the specified nodes.
GenericHierarchies get_leaves(Hierarchy mhd)
Get all the leaves of the bit of hierarchy.
Hierarchies get_children() const
Return the children in the order they were added.
Contains decorators for a bond.
Class for storing model, its restraints, constraints, and particles.
Definition: Model.h:72
C get_children() const
Get the children in a container of your choosing, eg ParticlesTemp.
Bonds get_internal_bonds(Hierarchy mhd)
Get the bonds internal to this tree.
static Hierarchy setup_particle(Model *m, ParticleIndex pi, ParticleIndexesAdaptor children=ParticleIndexesAdaptor())
Create a Hierarchy of level t by adding the needed attributes.
Hierarchy get_root(Hierarchy h)
Return the root of the hierarchy.
The standard decorator for manipulating molecular structures.
algebra::Sphere3D get_bounding_sphere(const Hierarchy &h)
GetByType
The different types which can be passed to get_by_type()
Hierarchy get_residue(Hierarchy mhd, unsigned int index)
Get the residue with the specified index.
functionality for defining rigid bodies
BoundingBoxD< 3 > get_bounding_box(const Cone3D &g)
Definition: Cone3D.h:64
static Hierarchy setup_particle(Model *m, ParticleIndex pi, DecoratorTraits tr=get_default_decorator_traits())
Define the type for a type of hierarchy.
Hierarchy create_clone_one(Hierarchy d)
Clone the node in the Hierarchy.
Hierarchy get_child(unsigned int i) const
Get the ith child based on the order they were added.
bool get_is_valid() const
Returns true if constructed with a non-default constructor.
Definition: Decorator.h:200
Classes to handle individual model particles. (Note that implementation of inline functions is in int...
std::ostream & show(Hierarchy h, std::ostream &out=std::cout)
Print the hierarchy using a given decorator to display each node.
void show(Hierarchy h, std::ostream &out=std::cout)
Print out a molecular hierarchy.
Various important macros for implementing decorators.
static bool get_is_setup(Model *m, ParticleIndex p)
Check if the particle has the needed attributes for a cast to succeed.
IMP::core::RigidBody create_rigid_body(Hierarchy h)
Class to handle individual model particles.
Definition: Particle.h:37
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:168
ParticleIndex get_index() const
returns the particle index of this particle in its model
A decorator for helping deal with a generalized hierarchy.
A decorator for a rigid body.
Definition: rigid_bodies.h:75
bool get_is_heterogen(Hierarchy h)
Return true if the piece of hierarchy should be classified as a heterogen.
Hierarchies get_by_type(Hierarchy mhd, GetByType t)
Gather all the molecular particles of a certain level in the hierarchy.
Hierarchies get_leaves(Hierarchy h)
Decorator for a sphere-like particle.
Hierarchy(IMP::core::Hierarchy h)
The traits must match.