IMP logo

Hierarchy.h

Go to the documentation of this file.
00001 /**
00002  *  \file atom/Hierarchy.h
00003  *  \brief Decorator for helping deal with a hierarchy of molecules.
00004  *
00005  *  Copyright 2007-2011 IMP Inventors. All rights reserved.
00006  *
00007  */
00008 
00009 #ifndef IMPATOM_HIERARCHY_H
00010 #define IMPATOM_HIERARCHY_H
00011 
00012 #include "atom_config.h"
00013 #include <IMP/core/utility.h>
00014 #include <IMP/core/Hierarchy.h>
00015 #include "bond_decorators.h"
00016 #include "atom_macros.h"
00017 #include <IMP/core/XYZR.h>
00018 #include <IMP/core/rigid_bodies.h>
00019 
00020 #include <IMP/Particle.h>
00021 #include <IMP/Model.h>
00022 
00023 #include <vector>
00024 #include <deque>
00025 
00026 
00027 #define IMP_GET_AS_DECL(UCName, lcname, CAPSNAME)       \
00028   UCName get_as_##lcname() const;
00029 
00030 // figure out how to inline
00031 #define IMP_GET_AS_DEF(UCName, lcname, CAPSNAME)        \
00032   UCName Hierarchy::get_as_##lcname() const {           \
00033     if (UCName::particle_is_instance(get_particle())) { \
00034       return UCName(get_particle());                    \
00035     } else {                                            \
00036       return UCName();                                  \
00037     }                                                   \
00038   }
00039 
00040 // DOMAIN is defined to be 1 by a fedora math header
00041 #define IMP_FOREACH_HIERARCHY_TYPE_LIST(macro)      \
00042   macro(Atom, atom, ATOM_TYPE),                     \
00043     macro(Residue, residue, RESIDUE_TYPE),          \
00044     macro(Chain, chain, CHAIN_TYPE),                \
00045     macro(Molecule, molecule, MOLECULE_TYPE),       \
00046     macro(Domain, domain, DOMAIN_TYPE),             \
00047     macro(Fragment, fragment, FRAGMENT_TYPE),       \
00048     macro(core::XYZ, xyz, XYZ_TYPE),                \
00049     macro(core::XYZR, xyzr, XYZR_TYPE),             \
00050     macro(Mass, mass, MASS_TYPE)
00051 
00052 // DOMAIN is defined to be 1 by a fedora math header
00053 #define IMP_FOREACH_HIERARCHY_TYPE_STATEMENTS(macro)  \
00054   macro(Atom, atom, ATOM_TYPE);                \
00055   macro(Residue, residue, RESIDUE_TYPE);       \
00056   macro(Chain, chain, CHAIN_TYPE);             \
00057   macro(Molecule, molecule, MOLECULE_TYPE);    \
00058   macro(Domain, domain, DOMAIN_TYPE);          \
00059   macro(Fragment, fragment, FRAGMENT_TYPE);    \
00060   macro(core::XYZ, xyz, XYZ_TYPE);             \
00061   macro(core::XYZR, xyzr, XYZR_TYPE);          \
00062   macro(Mass, mass, MASS_TYPE)
00063 
00064 // DOMAIN is defined to be 1 by a fedora math header
00065 #define IMP_FOREACH_HIERARCHY_TYPE_FUNCTIONS(macro)    \
00066   macro(Atom, atom, ATOM_TYPE)                         \
00067   macro(Residue, residue, RESIDUE_TYPE)                \
00068   macro(Chain, chain, CHAIN_TYPE)                      \
00069   macro(Molecule, molecule, MOLECULE_TYPE)             \
00070   macro(Domain, domain, DOMAIN_TYPE)                   \
00071   macro(Fragment, fragment, FRAGMENT_TYPE)             \
00072   macro(core::XYZ, xyz, XYZ_TYPE)                      \
00073   macro(core::XYZR, xyzr, XYZR_TYPE)                   \
00074   macro(Mass, mass, MASS_TYPE)                         \
00075   IMP_REQUIRE_SEMICOLON_NAMESPACE
00076 
00077 
00078 #define IMP_CAPS_NAME(UCName, lcname, CAPSNAME) \
00079   CAPSNAME
00080 
00081 
00082 IMPATOM_BEGIN_NAMESPACE
00083 class Atom;
00084 class Residue;
00085 class Domain;
00086 class Fragment;
00087 class Chain;
00088 class Molecule;
00089 class Mass;
00090 
00091 class Hierarchy;
00092 
00093 
00094 #ifdef IMP_DOXYGEN
00095 
00096 #else
00097 typedef IMP::Decorators< Hierarchy,
00098                          IMP::core::GenericHierarchies> Hierarchies;
00099 typedef IMP::Decorators< Hierarchy,
00100                          IMP::core::GenericHierarchiesTemp> HierarchiesTemp;
00101 #endif
00102 
00103 //! The standard decorator for manipulating molecular structures.
00104 /** \imp represents molecular structures using the Hierachy decorator.
00105     Molecules and collections of molecules each are stored as a
00106     hierarchy (or tree) where the resolution of the representation increases
00107     as you move further from the root. That is, if a parent has
00108     some particular property (eg, marks out a volume by having
00109     a x,y,z coordinates and a radius), then the children should have
00110     a higher resolution form of that information (eg, mark out a more
00111     detailed excluded volume by defining a set of balls which having
00112     approximately the same total volume).
00113 
00114     \section tree_basics Tree Basics
00115     In a tree you have a set of nodes, represented by Hierarchy particles.
00116     Each node can have a node can have at most one parent. The node with no
00117     parent is known as the root of the tree.
00118 
00119     Here is a simple example with a protein with three residues. Two of the
00120     residues have atoms, where as the third is coarse grained.
00121     \dotgraph{\dot
00122     digraph example {
00123     node [shape=record\, fontname= Helvetica\, fontsize=10]
00124       a [label="Protein A (the root)"];
00125       b [label="Residue 0"\, URL="Residue"];
00126       c [label="Residue 1"];
00127       cp [label="Residue 2"];
00128       d0 [label="CA"];
00129       e0 [label="CA"];
00130       d1 [label="C"];
00131       e1 [label="C"];
00132       d2 [label="N"];
00133       e2 [label="N"];
00134       a -> b [arrowhead="open"];
00135       a -> c [arrowhead="open"]
00136       a -> cp [arrowhead="open"];
00137       b -> d0 [arrowhead="open"];
00138       c -> e0 [arrowhead="open"];
00139       b -> d1 [arrowhead="open"];
00140       c -> e1 [arrowhead="open"];
00141       b -> d2 [arrowhead="open"];
00142       c -> e2 [arrowhead="open"];
00143     }
00144     \enddot
00145     }
00146 
00147 
00148     The nodes in the hierarchy can correspond to arbitrary bits of a
00149     molecule and do not need to have any biological significant. For
00150     example we could introduce a fragment containing residues 0 and 1:
00151     \dotgraph{\dot
00152     digraph example {
00153     node [shape=record\, fontname= Helvetica\, fontsize=10]
00154       a [label="Protein A (the root)"\, URL="\ref B"];
00155       aa [label="Fragment 0"];
00156       b [label="Residue 0"];
00157       c [label="Residue 1"];
00158       cp [label="Residue 2"];
00159       d0 [label="CA"];
00160       e0 [label="CA"];
00161       d1 [label="C"];
00162       e1 [label="C"];
00163       d2 [label="N"];
00164       e2 [label="N"];
00165       a -> aa [arrowhead="open"];
00166       aa -> b [arrowhead="open"];
00167       aa -> c [arrowhead="open"]
00168       a -> cp [arrowhead="open"];
00169       b -> d0 [arrowhead="open"];
00170       c -> e0 [arrowhead="open"];
00171       b -> d1 [arrowhead="open"];
00172       c -> e1 [arrowhead="open"];
00173       b -> d2 [arrowhead="open"];
00174       c -> e2 [arrowhead="open"];
00175     }
00176     \enddot}
00177 
00178 
00179     A hierarchy can have any tree structure as long as:
00180     - the type of the parent makes sense for the child: eg a Residue
00181     cannot be the parent of a Chain.
00182     - the leaves always have coordinates, radius and mass
00183     - all particles in hierarchy are from the same model
00184     - all Atoms has a Residue for as parent
00185     - any Atom with a non-heterogen atom type is part of a protein,
00186     DNA or RNA molecule.
00187     - all Residue children of a particle appear in order based
00188       on their index
00189     - all Atom children in of a particle appear in order of their
00190       AtomType
00191 
00192     The get_is_valid() method checks some of these properties. Any
00193     method taking a hierarchy as an argument should do
00194     \code
00195     IMP_USAGE_CHECK(h.get_is_valid(), "Invalid hierarchy as input");
00196     \endcode
00197     to make sure the hierarchy makes sense.
00198 
00199     A number of decorator types are associated with the Hierarchy
00200     to store the information associated with that node in the
00201     hierarchy. Examples include Residue, Atom, XYZ, Chain, XYZR,
00202     Mass, Domain, Molecule etc.
00203     We provide a get_as_x() function for each such decorator which
00204     returns either X() (a null type) if the node is not a particle
00205     of type x, or an X decorator wrapping the current particle if
00206     it is.
00207 
00208     \ingroup hierarchy
00209     \ingroup decorators
00210     \see Atom
00211     \see Residue
00212     \see Chain
00213     \see Molecule
00214     \see Domain
00215     \see Fragment
00216     \see Mass
00217  */
00218 class IMPATOMEXPORT Hierarchy: public core::Hierarchy
00219 {
00220   typedef core::Hierarchy H;
00221 public:
00222   IMP_NO_DOXYGEN(typedef boost::false_type DecoratorHasTraits);
00223   explicit Hierarchy(Particle *p): H(p, get_traits()) {
00224   }
00225 
00226   //! null constructor
00227   Hierarchy() {}
00228 
00229   //! cast a particle which has the needed attributes
00230   static Hierarchy decorate_particle(Particle *p) {
00231     H::decorate_particle(p, get_traits());
00232     return Hierarchy(p);
00233   }
00234 
00235   //! The traits must match
00236   Hierarchy(IMP::core::Hierarchy h): H(h) {
00237     IMP_USAGE_CHECK(h.get_traits() == get_traits(),
00238               "Cannot construct a IMP.atom.Hierarchy from a general "
00239               " IMP.core.Hierarchy");
00240   }
00241 
00242   /** Create a Hierarchy of level t by adding the needed
00243       attributes. */
00244   static Hierarchy setup_particle(Particle *p) {
00245     H::setup_particle(p, get_traits());
00246     return Hierarchy(p);
00247   }
00248 
00249   /** Check if the particle has the needed attributes for a
00250    cast to succeed */
00251   static bool particle_is_instance(Particle *p){
00252     return H::particle_is_instance(p, get_traits());
00253   }
00254 
00255   //! Return true if the hierarchy is valid.
00256   /** Print information about the hierarchy if print_info is
00257       true and things are invalid.
00258       \note Returning true only means that no problems were
00259       found, it can't check everything.*/
00260   bool get_is_valid(bool print_info) const;
00261   //! Add a child and check that the types are appropriate
00262   /** A child must have a type that is listed before the parent in the
00263       Type enum list.
00264    */
00265   unsigned int add_child(Hierarchy o) {
00266     IMP_USAGE_CHECK(o != *this, "Can't add something as its own child: "
00267                     << o);
00268     return H::add_child(o);
00269   }
00270 
00271   //! Add a child and check that the types are appropriate
00272   /** A child must have a type that is listed before the parent in the
00273       Type enum list.
00274    */
00275   void add_child_at(Hierarchy o, unsigned int i) {
00276     IMP_USAGE_CHECK(o != *this, "Can't add something as its own child: "
00277                     << o);
00278     H::add_child_at(o, i);
00279   }
00280 
00281   /** Get the ith child */
00282   Hierarchy get_child(unsigned int i) const {
00283     H hd=  H::get_child(i);
00284     return Hierarchy(hd);
00285   }
00286   HierarchiesTemp get_children() const {
00287     HierarchiesTemp ret(get_number_of_children());
00288     for (unsigned int i=0; i< get_number_of_children(); ++i) {
00289       ret[i]= get_child(i);
00290     }
00291     return ret;
00292   }
00293 
00294 
00295   /** Get the parent particle. */
00296   Hierarchy get_parent() const {
00297     H hd= H::get_parent();
00298     if (hd == H()) {
00299       return Hierarchy();
00300     } else {
00301       return Hierarchy(hd);
00302     }
00303   }
00304 
00305   /** \name Methods to get associated decorators
00306 
00307       We provide a number of helper methods to get associated
00308       decorators for the current node in the hierarchy. As an
00309       example, if the particle decorated by this decorator is
00310       a Residue particle, then get_as_residue() return
00311       Residue(get_particle()), if not it returns Residue().
00312       @{
00313    */
00314   IMP_FOREACH_HIERARCHY_TYPE_FUNCTIONS(IMP_GET_AS_DECL);
00315   /** @} */
00316 
00317   //! Get the molecular hierarchy HierararchyTraits.
00318   static const IMP::core::HierarchyTraits& get_traits();
00319 
00320   // swig overwrites __repr__ if it is inherited
00321   IMP_SHOWABLE(Hierarchy);
00322 };
00323 
00324 IMP_OUTPUT_OPERATOR(Hierarchy);
00325 
00326 
00327 
00328 #ifdef IMP_DOXYGEN
00329 /** The different types which can be passed to get_by_type()
00330  */
00331 enum GetByType {ATOM_TYPE, RESIDUE_TYPE, CHAIN_TYPE, MOLECULE_TYPE.
00332                 DOMAIN_TYPE, FRAGMENT_TYPE,
00333                 XYZ_TYPE,XYZR_TYPE,MASS_TYPE};
00334 #else
00335 enum GetByType {
00336   IMP_FOREACH_HIERARCHY_TYPE_LIST(IMP_CAPS_NAME)
00337 };
00338 #endif
00339 
00340 /**
00341    Gather all the molecular particles of a certain level
00342    in the molecular hierarchy
00343    \ingroup hierarchy
00344    \relatesalso Hierarchy
00345 */
00346 IMPATOMEXPORT HierarchiesTemp
00347 get_by_type(Hierarchy mhd, GetByType t);
00348 
00349 
00350 //! Get the residue with the specified index
00351 /** Find the leaf containing the residue with the appropriate index.
00352     This is the PDB index, not the offset in the chain (if they are different).
00353 
00354     The function returns a Hierarchy, rather than a Residue since the
00355     residue may not be explicitly represented and may just be part of some
00356     fragment.
00357 
00358     \throw ValueException if mhd's type is not one of CHAIN, PROTEIN, NUCLEOTIDE
00359     \return Hierarchy() if that residue is not found.
00360 
00361     \ingroup hierarchy
00362     \relatesalso Hierarchy
00363  */
00364 IMPATOMEXPORT Hierarchy
00365 get_residue(Hierarchy mhd, unsigned int index);
00366 
00367 
00368 //! Create a fragment containing the specified nodes
00369 /** A particle representing the fragment is created and initialized.
00370 
00371     The Fragment is inserted as a child of the parent (and the particles are
00372     removed). The particles become children of the fragment.
00373 
00374     \throw ValueException If all the particles do not have the same parent.
00375     \ingroup hierarchy
00376     \relatesalso Hierarchy
00377  */
00378 IMPATOMEXPORT Hierarchy
00379 create_fragment(const HierarchiesTemp &ps);
00380 
00381 //! Get the bonds internal to this tree
00382 /**     \relatesalso Hierarchy
00383         \see Bond
00384         \relatesalso Bond
00385  */
00386 IMPATOMEXPORT Bonds
00387 get_internal_bonds(Hierarchy mhd);
00388 
00389 
00390 //! Return the root of the hierarchy
00391 /** \relatesalso Hierarchy */
00392 inline Hierarchy get_root(Hierarchy h) {
00393   while (h.get_parent()) {
00394     h= h.get_parent();
00395   }
00396   return h;
00397 }
00398 
00399 /** \relatesalso Hierarchy */
00400 inline HierarchiesTemp get_leaves(Hierarchy h) {
00401   return HierarchiesTemp(IMP::core::get_leaves(h));
00402 }
00403 
00404 //! Print out a molecular hierarchy
00405 /** \relatesalso Hierarchy
00406  */
00407 inline void show(Hierarchy h, std::ostream &out=std::cout) {
00408    IMP::core::show<Hierarchy>(h, out);
00409 }
00410 
00411 //! Rigidify a molecule or collection of molecules.
00412 /** The rigid body created has all the leaves as members and a
00413     member rigid body for each internal node in the tree.
00414 
00415     A name can be passed as it is not easy to automatically pick
00416     a decent name.
00417     \see create_aligned_rigid_body()
00418     \relatesalso Hierarchy
00419     \relatesalso IMP::core::RigidBody
00420 */
00421 IMPATOMEXPORT IMP::core::RigidBody create_rigid_body(const Hierarchies& h,
00422                         std::string name=std::string("created rigid body"));
00423 
00424 /** \see create_rigid_body(const HierarchiesTemp&)
00425  */
00426 IMPATOMEXPORT IMP::core::RigidBody create_rigid_body(Hierarchy h);
00427 
00428 //! Rigidify a molecule or collection of molecules.
00429 /** This method is identical to create_rigid_body() except that
00430     the chosen reference frame is aligned with that of reference
00431     (which must have exactly the same set of particles). This allows
00432     one to make sure the rigid body is equivalent when you have several
00433     copies of the same molecule.
00434 
00435     \relatesalso Hierarchy
00436     \relatesalso IMP::core::RigidBody
00437 */
00438 IMPATOMEXPORT IMP::core::RigidBody create_compatible_rigid_body(Hierarchy h,
00439                                                      Hierarchy reference);
00440 
00441 
00442 #ifndef IMP_DOXYGEN
00443 IMPATOMEXPORT IMP::core::RigidBody setup_as_rigid_body(Hierarchy h);
00444 #endif
00445 
00446 //! Return true if the piece of hierarchy should be classified as a heterogen
00447 /** For the purposes of classification, a heterogen is anything that
00448     - is a heterogen atom (one whose name starts with HET:)
00449     - is or is part of a Residue that is not a normal protein, rna or
00450       dna residue
00451     - or is not part of a Chain
00452     For the moment, this can only be called on residues or atoms.
00453 */
00454 IMPATOMEXPORT bool get_is_heterogen(Hierarchy h);
00455 
00456 //! Clone the Hierarchy
00457 /** This method copies the Bond, Bonded, Atom,
00458     Residue, and Domain data and the particle name to the
00459     new copies in addition to the Hierarchy relationships.
00460 
00461     \relatesalso Hierarchy
00462 */
00463 IMPATOMEXPORT
00464 Hierarchy create_clone(Hierarchy d);
00465 
00466 //! Clone the node in the Hierarchy
00467 /** This method copies the  Atom,
00468     Residue, Chain and Domain data and the particle name.
00469 
00470     \relatesalso Hierarchy
00471 */
00472 IMPATOMEXPORT
00473 Hierarchy create_clone_one(Hierarchy d);
00474 
00475 
00476 //! Delete the Hierarchy
00477 /** All bonds connecting to these atoms are destroyed as are
00478     hierarchy links in the Hierarchy and the particles are
00479     removed from the Model.
00480     \relatesalso Hierarchy
00481 */
00482 IMPATOMEXPORT
00483 void destroy(Hierarchy d);
00484 
00485 
00486 
00487 //! Get a bounding box for the Hierarchy
00488 /** This bounding box is that of the highest (in the CS sense of a tree
00489     growing down from the root) cut
00490     through the tree where each node in the cut has x,y,z, and r.
00491     That is, if the root has x,y,z,r then it is the bounding box
00492     of that sphere. If only the leaves have radii, it is the bounding
00493     box of the leaves. If no such cut exists, the behavior is undefined.
00494     \relatesalso Hierarchy
00495     \relatesalso IMP::algebra::BoundingBoxD
00496  */
00497 IMPATOMEXPORT
00498 algebra::BoundingBoxD<3> get_bounding_box(const Hierarchy &h);
00499 
00500 
00501 /** See get_bounding_box() for more details.
00502     \relatesalso Hierarchy
00503  */
00504 IMPATOMEXPORT
00505 algebra::SphereD<3> get_bounding_sphere(const Hierarchy &h);
00506 
00507 
00508 IMPATOM_END_NAMESPACE
00509 
00510 
00511 #endif  /* IMPATOM_HIERARCHY_H */

Generated on Thu Mar 24 2011 02:01:39 for IMP by doxygen 1.7.3