IMP  2.4.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/kernel/Particle.h>
21 #include <IMP/kernel/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  a 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 having
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 a 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  //! \deprecated_at{2.3} Check explicitly instead. */
211  IMPATOM_DEPRECATED_METHOD_DECL(2.3)
212  static Hierarchy decorate_particle(kernel::Particle *p) {
213  IMPATOM_DEPRECATED_METHOD_DEF(2.3, "Check explicitly instead");
214  if (get_is_setup(p))
215  return Hierarchy(p);
216  else
217  return Hierarchy();
218  }
219  /** Setup the particle as a hierarchy and add the passed particles
220  as children. */
223  H::setup_particle(p, get_traits());
224  Hierarchy ret(p);
225  for (unsigned int i = 0; i < children.size(); ++i) {
226  if (!get_is_setup(p->get_model(), children[i])) {
227  setup_particle(p->get_model(), children[i]);
228  }
229  ret.add_child(Hierarchy(p->get_model(), children[i]));
230  }
231  return ret;
232  }
233 
235  return setup_particle(p->get_model(), p->get_index());
236  }
237 
238  /** \deprecated_at{2.2} Use get_is_setup() instead. */
239  static bool particle_is_instance(kernel::Particle *p) {
240  return H::get_is_setup(p, get_traits());
241  }
242  static bool get_is_setup(kernel::Particle *p) {
243  return H::get_is_setup(p, get_traits());
244  }
245  /** \deprecated_at{2.2} Use get_is_setup() instead. */
246  static bool particle_is_instance(kernel::Model *m, kernel::ParticleIndex p) {
247  return H::get_is_setup(m->get_particle(p), get_traits());
248  }
249 #endif
250 
252  : H(m, pi, get_traits()) {}
253 
255  : H(pi.get_model(), pi.get_particle_index(), get_traits()) {}
256 
257  //! null constructor
259 
260  //! The traits must match
261  explicit Hierarchy(IMP::core::Hierarchy h) : H(h) {
263  h != IMP::core::Hierarchy() || h.get_decorator_traits() == get_traits(),
264  "Cannot construct a IMP.atom.Hierarchy from a general "
265  " IMP.core.Hierarchy");
266  }
267 
268  /** Create a Hierarchy of level t by adding the needed
269  attributes. */
273  H::setup_particle(m, pi, get_traits());
274  Hierarchy ret(m, pi);
275  for (unsigned int i = 0; i < children.size(); ++i) {
276  if (!get_is_setup(m, children[i])) {
277  setup_particle(m, children[i]);
278  }
279  ret.add_child(Hierarchy(m, children[i]));
280  }
281  return ret;
282  }
283 
284  /** Check if the particle has the needed attributes for a
285  cast to succeed */
287  return H::get_is_setup(m->get_particle(p), get_traits());
288  }
289 
290  //! Return true if the hierarchy is valid.
291  /** Print information about the hierarchy if print_info is
292  true and things are invalid.
293  \note Returning true only means that no problems were
294  found, it can't check everything.*/
295  bool get_is_valid(bool print_info) const;
296  //! Add a child and check that the types are appropriate
297  /** A child must have a type that is listed before the parent in the
298  Type enum list.
299  */
301  IMP_USAGE_CHECK(o != *this, "Can't add something as its own child");
302  H::add_child(o);
303  }
304 
305 #ifndef IMP_DOXYGEN
306  void show(std::ostream &out, std::string delimiter) const;
307 #endif
308 
309  /** Get the ith child based on the order they were added. */
310  Hierarchy get_child(unsigned int i) const {
311  H hd = H::get_child(i);
312  return Hierarchy(hd);
313  }
314  //! Return the children in the order they were added
316  Hierarchies ret(get_number_of_children());
317  for (unsigned int i = 0; i < get_number_of_children(); ++i) {
318  ret[i] = get_child(i);
319  }
320  return ret;
321  }
322 
323  //! Get the children in a container of your choosing, eg kernel::ParticlesTemp
324  template <class C>
325  C get_children() const {
326  C ret(get_number_of_children());
327  for (unsigned int i = 0; i < get_number_of_children(); ++i) {
328  ret[i] = get_child(i);
329  }
330  return ret;
331  }
332 
333  /** Get the parent particle. */
335  H hd = H::get_parent();
336  if (hd == H()) {
337  return Hierarchy();
338  } else {
339  return Hierarchy(hd);
340  }
341  }
342 
343  /** \name Methods to get associated decorators
344 
345  We provide a number of helper methods to get associated
346  decorators for the current node in the hierarchy. As an
347  example, if the particle decorated by this decorator is
348  a Residue particle, then get_as_residue() returns
349  Residue(get_particle()), if not it returns Residue().
350  @{
351  */
352  IMP_ATOM_FOREACH_HIERARCHY_TYPE_FUNCTIONS(IMP_ATOM_GET_AS_DECL);
353  /** @} */
354 
355  //! Get the molecular hierarchy HierarchyTraits.
356  static const IMP::core::HierarchyTraits &get_traits();
357 
358  // swig overwrites __repr__ if it is inherited
360 };
361 
362 IMP_DECORATORS_DEF(Hierarchy, Hierarchies);
363 
364 #ifdef IMP_DOXYGEN
365 /** The different types which can be passed to get_by_type()
366  */
367 enum GetByType {
368  ATOM_TYPE,
369  RESIDUE_TYPE,
370  CHAIN_TYPE,
371  MOLECULE_TYPE,
372  DOMAIN_TYPE,
373  FRAGMENT_TYPE,
374  XYZ_TYPE,
375  XYZR_TYPE,
376  MASS_TYPE,
377  STATE_TYPE
378 };
379 #else
380 enum GetByType {
381  IMP_ATOM_FOREACH_HIERARCHY_TYPE_LIST(IMP_ATOM_CAPS_NAME)
382 };
383 #endif
384 
385 /**
386  Gather all the molecular particles of a certain level
387  in the molecular hierarchy.
388 */
389 IMPATOMEXPORT Hierarchies get_by_type(Hierarchy mhd, GetByType t);
390 
391 //! Get the residue with the specified index
392 /** Find the leaf containing the residue with the appropriate index.
393  This is the PDB index, not the offset in the chain (if they are different).
394 
395  The function returns a Hierarchy, rather than a Residue since the
396  residue may not be explicitly represented and may just be part of some
397  fragment.
398 
399  \throw ValueException if mhd's type is not one of CHAIN, PROTEIN, NUCLEOTIDE
400  \return Hierarchy() if that residue is not found.
401 
402  \see Hierarchy
403  */
404 IMPATOMEXPORT Hierarchy get_residue(Hierarchy mhd, unsigned int index);
405 
406 //! Create a fragment containing the specified nodes
407 /** A particle representing the fragment is created and initialized.
408 
409  The Fragment is inserted as a child of the parent (and the particles are
410  removed). The particles become children of the fragment.
411 
412  \throw ValueException If all the particles do not have the same parent.
413  \see Hierarchy
414  */
415 IMPATOMEXPORT Hierarchy create_fragment(const Hierarchies &ps);
416 
417 //! Get the bonds internal to this tree
418 /** \see Hierarchy
419  \see Bond
420  */
421 IMPATOMEXPORT Bonds get_internal_bonds(Hierarchy mhd);
422 
423 //! Return the root of the hierarchy
424 /** \see Hierarchy */
426  while (h.get_parent()) {
427  h = h.get_parent();
428  }
429  return h;
430 }
431 
432 /** \see Hierarchy */
435 }
436 
437 /** \see Hierarchy */
440  for (unsigned int i = 0; i < h.size(); ++i) {
441  core::GenericHierarchies cur = IMP::core::get_leaves(h[i]);
442  ret.insert(ret.end(), cur.begin(), cur.end());
443  }
444  return get_as<Hierarchies>(ret);
445 }
446 
447 //! Print out a molecular hierarchy
448 /** \see Hierarchy
449  */
450 inline void show(Hierarchy h, std::ostream &out = std::cout) {
451  IMP::core::show<Hierarchy>(h, out);
452 }
453 
454 //! Rigidify a molecule or collection of molecules.
455 /** The rigid body created has all the leaves as members and a
456  member rigid body for each internal node in the tree. The
457  particle created to be the rigid body is returned.
458 
459  A name can be passed as it is not easy to automatically pick
460  a decent name.
461  \see create_aligned_rigid_body()
462  \see Hierarchy
463  \see IMP::core::RigidBody
464 */
466  const Hierarchies &h, std::string name = std::string("created rigid body"));
467 
468 /** \see create_rigid_body(const Hierarchies&)
469  */
470 IMPATOMEXPORT IMP::core::RigidBody create_rigid_body(Hierarchy h);
471 
472 //! Rigidify a molecule or collection of molecules.
473 /** This method is identical to create_rigid_body() except that
474  the chosen reference frame is aligned with that of reference
475  (which must have exactly the same set of particles). This allows
476  one to make sure the rigid body is equivalent when you have several
477  copies of the same molecule.
478 
479  \see Hierarchy
480  \see IMP::core::RigidBody
481 */
483  Hierarchy h, Hierarchy reference);
484 
485 #ifndef IMP_DOXYGEN
486 IMPATOMEXPORT IMP::core::RigidBody setup_as_rigid_body(Hierarchy h);
487 #endif
488 
489 //! Return true if the piece of hierarchy should be classified as a heterogen
490 /** For the purposes of classification, a heterogen is anything that
491  - is a heterogen atom (one whose name starts with HET:)
492  - is or is part of a Residue that is not a normal protein, rna or
493  dna residue
494  - or is not part of a Chain
495  For the moment, this can only be called on residues or atoms.
496 */
497 IMPATOMEXPORT bool get_is_heterogen(Hierarchy h);
498 
499 //! Clone the Hierarchy
500 /** This method copies the Bond, Bonded, Atom,
501  Residue, and Domain data and the particle name to the
502  new copies in addition to the Hierarchy relationships.
503 
504  \see Hierarchy
505 */
506 IMPATOMEXPORT Hierarchy create_clone(Hierarchy d);
507 
508 //! Clone the node in the Hierarchy
509 /** This method copies the Atom,
510  Residue, Chain and Domain data and the particle name.
511 
512  \see Hierarchy
513 */
514 IMPATOMEXPORT Hierarchy create_clone_one(Hierarchy d);
515 
516 //! Delete the Hierarchy
517 /** All bonds connecting to these atoms are destroyed as are
518  hierarchy links in the Hierarchy and the particles are
519  removed from the kernel::Model. If this particle has a parent, it is
520  removed from the parent.
521  \see Hierarchy
522 */
523 IMPATOMEXPORT void destroy(Hierarchy d);
524 
525 //! Get a bounding box for the Hierarchy
526 /** This bounding box is that of the highest (in the CS sense of a tree
527  growing down from the root) cut
528  through the tree where each node in the cut has x,y,z, and r.
529  That is, if the root has x,y,z,r then it is the bounding box
530  of that sphere. If only the leaves have radii, it is the bounding
531  box of the leaves. If no such cut exists, the behavior is undefined.
532  \see Hierarchy
533  \see IMP::algebra::BoundingBoxD
534  */
535 IMPATOMEXPORT algebra::BoundingBoxD<3> get_bounding_box(const Hierarchy &h);
536 
537 /** See get_bounding_box() for more details.
538  \see Hierarchy
539  */
540 IMPATOMEXPORT algebra::Sphere3D get_bounding_sphere(const Hierarchy &h);
541 
542 IMPATOM_END_NAMESPACE
543 
544 #endif /* IMPATOM_HIERARCHY_H */
Decorator for helping deal with a hierarchy.
Various important functionality for implementing decorators.
Hierarchy get_parent() const
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.
ParticleIndex get_index() const
returns the particle index of this particle in its model
Particle * get_particle(ParticleIndex p) const
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.
Bonds get_internal_bonds(Hierarchy mhd)
Get the bonds internal to this tree.
static bool get_is_setup(kernel::Model *m, kernel::ParticleIndex p)
#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.
C get_children() const
Get the children in a container of your choosing, eg kernel::ParticlesTemp.
Hierarchy get_root(Hierarchy h)
Return the root of the hierarchy.
Hierarchy create_fragment(const Hierarchies &ps)
Create a fragment containing the specified nodes.
static Hierarchy setup_particle(kernel::Model *m, ParticleIndex pi, DecoratorTraits tr=get_default_decorator_traits())
The standard decorator for manipulating molecular structures.
static Hierarchy setup_particle(kernel::Model *m, kernel::ParticleIndex pi, kernel::ParticleIndexesAdaptor children=kernel::ParticleIndexesAdaptor())
Hierarchies get_by_type(Hierarchy mhd, GetByType t)
functionality for defining rigid bodies
BoundingBoxD< 3 > get_bounding_box(const Cone3D &g)
Definition: Cone3D.h:64
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
Class to handle individual model particles.
Storage of a model, its restraints, constraints and particles.
Classes to handle individual model particles. (Note that implementation of inline functions in in int...
void destroy(Hierarchy d)
Delete the Hierarchy.
Various important macros for implementing decorators.
void show(Hierarchy h, std::ostream &out=std::cout)
Print out a molecular hierarchy.
IMP::core::RigidBody create_rigid_body(Hierarchy h)
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:170
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.
Class for storing model, its restraints, constraints, and particles.
Definition: kernel/Model.h:73