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