IMP  2.2.0
The Integrative Modeling Platform
kernel/Decorator.h
Go to the documentation of this file.
1 /**
2  * \file IMP/kernel/Decorator.h \brief The base class for decorators.
3  *
4  * Copyright 2007-2014 IMP Inventors. All rights reserved.
5  *
6  */
7 
8 #ifndef IMPKERNEL_DECORATOR_H
9 #define IMPKERNEL_DECORATOR_H
10 
11 #include <IMP/kernel/kernel_config.h>
12 #include "base_types.h"
13 #include <IMP/base/Object.h>
14 #include <IMP/base/WeakPointer.h>
15 #include "Model.h"
16 #include "utility.h"
17 #include "Constraint.h"
18 #include "internal/utility.h"
20 #include <IMP/base/Vector.h>
21 #include <IMP/base/Value.h>
22 
23 IMPKERNEL_BEGIN_NAMESPACE
24 class ParticleAdaptor;
25 
26 /**
27 Representation of the structure in \imp is via a collection of
28 Particle objects. However, since particles are general purpose, they
29 provide a basic set of tools for managing the data (e.g.
30 IMP::kernel::Model::add_attribute(), IMP::kernel::Model::get_value()
31 etc). Decorators wrap (or \quote{decorate}) particles to provide a much
32 richer interface. For example, most particles have Cartesian
33 coordinates. The class IMP::core::XYZ decorates such a particle to
34 provide functions to get and set the Cartesian coordinates as well as
35 compute distances between particles.
36 \code
37 d0= IMP.core.XYZ(p0)
38 d1= IMP.core.XYZ(p1)
39 print IMP.core.distance(d0,d1)
40 print d0.get_coordinates()
41 \endcode
42 
43 \par Decorator basics
44 
45 \note The `get_is_setup()` and `setup_particle()` functions mentioned below
46 can take any of either an IMP::kernel::Model* and IMP::kernel::ParticleIndex
47 pair, an IMP::kernel::Paricle* or another decorator to identify the particle.
48 We use various of those below.
49 
50 Dealing with decorators and particles has two main parts
51 -# setting up the particle to be used with that decorator
52 -# decorating the particle.
53 
54 To set up a particle to be used with the IMP::core::XYZ decorator we do
55 \code
56 d0= IMP.core.XYZ.setup_particle(m, pi, IMP.algebra.Vector3D(0,2,3))
57 \endcode
58 The method calls also decorates the particle and returns the decorator
59 which can now be used to manipulate the particle. For example we can
60 access the coordinates \c (0,2,3) by doing
61 \code
62 print d0.get_coordinates()
63 \endcode
64 We now say the particle is an XYZ particle. If that particle is
65 encountered later when we do not have the existing decorator available,
66 we can decorate it again (since it is already set up) by doing
67 \code
68 d1= IMP.core.XYZ(m, pi)
69 \endcode
70 
71 If you do not know if \c p has been set up for the XYZ decorator, you can
72 ask with
73 \code
74 if IMP.core.XYZ.get_is_setup(m, pi):
75 \endcode
76 
77 More abstractly, decorators can be used to
78 - maintain invariants: e.g. an IMP::atom::Bond particle always connects
79  two other particles, both of which are IMP::atom::Bonded particles.
80 - add functionality: e.g. you can get the coordinates as an
81  IMP::algebra::Vector3D
82 - provide uniform names for attributes: so you do not use \quote{x} some places
83 and \quote{X} other places
84 
85 To see a list of all available decorators and to see what functions
86 all decorators have, look at the list of classes which inherit from
87 IMP::Decorator, below.
88 
89 See the IMP::example::ExampleDecorator %example for how to implement a
90 simple decorator.
91 
92 \note Decorator objects are ordered based on the address of the wrapped
93 particle. Like pointers, they are logical values so can be in \c if
94 statements.
95 
96 \implementation{Decorator, IMP_DECORATOR, IMP::example::ExampleDecorator}
97 \n\n For efficiency reasons attribute keys should always be created
98 lazily (at the time of the first use), and not be created as static
99 variables. The reason for this is that initialized attribute keys result
100 in space being allocated in decorators, even before they are used.\n\n
101 Implementors should consult IMP::example::ExampleDecorator,
102 IMP_DECORATOR_METHODS(), IMP_DECORATOR_WITH_TRAITS_METHODS(),
103 IMP_DECORATOR_GET().
104 
105 A decorator can be cast to a IMP::kernel::Particle* in C++. You have to
106 use the Decorator::get_particle() function in Python.
107 
108 \note It is undefined behavior to use a decorator constructed on
109 a particle that is no longer part of a model. Since constructing
110 decorators is very cheap, you probably should not store decorators,
111 and then would not have this problem.
112 
113 See example::ExampleDecorator to see what a minimal decorator looks like.
114 */
115 class IMPKERNELEXPORT Decorator : public base::Value {
116  private:
118  ParticleIndex pi_;
119  int compare(base::Object* o) const {
120  if (o < get_particle())
121  return -1;
122  else if (o > get_particle())
123  return 1;
124  else
125  return 0;
126  }
127 
128  protected:
129  Decorator(Model* m, ParticleIndex pi) : model_(m), pi_(pi) {}
130  Decorator() {}
131 
132 #ifndef IMP_DOXYGEN
133  public:
134 #endif
135  explicit Decorator(ParticleAdaptor p);
136 
137  public:
138 #ifdef _MSC_VER
139  typedef Particle* ParticleP;
140 #endif
141 #ifndef IMP_DOXYGEN
142  bool __eq__(base::Object* o) const { return operator==(o); }
143  bool __ne__(base::Object* o) const { return operator!=(o); }
144  bool __lt__(base::Object* o) const { return operator<(o); }
145  bool __gt__(base::Object* o) const { return operator>(o); }
146  bool __ge__(base::Object* o) const { return operator>=(o); }
147  bool __le__(base::Object* o) const { return operator<=(o); }
148 #ifndef SWIG
149  bool operator==(base::Object* o) const { return (compare(o) == 0); }
150  bool operator!=(base::Object* o) const { return (compare(o) != 0); }
151  bool operator<(base::Object* o) const { return (compare(o) < 0); }
152  bool operator>(base::Object* o) const { return (compare(o) > 0); }
153  bool operator>=(base::Object* o) const { return !(compare(o) < 0); }
154  bool operator<=(base::Object* o) const { return !(compare(o) > 0); }
155 
156  bool operator==(Particle* o) const { return (compare(o) == 0); }
157  bool operator!=(Particle* o) const { return (compare(o) != 0); }
158  bool operator<(Particle* o) const { return (compare(o) < 0); }
159  bool operator>(Particle* o) const { return (compare(o) > 0); }
160  bool operator>=(Particle* o) const { return !(compare(o) < 0); }
161  bool operator<=(Particle* o) const { return !(compare(o) > 0); }
162 #endif
163 #endif
164 
165  /** Returns the particle decorated by this decorator.*/
167  if (!model_)
168  return nullptr;
169  else {
170  IMP_USAGE_CHECK(model_->get_particle(pi_),
171  "Particle " << pi_ << " is no longer part of the model.");
172  return model_->get_particle(pi_);
173  }
174  }
175 
176 #if !defined(SWIG)
177  operator Particle*() const { return get_particle(); }
178  Particle* operator->() const { return get_particle(); }
179  operator ParticleIndex() const { return get_particle_index(); }
180 #endif
181 
182  /** Returns the particle index decorated by this decorator.*/
183  ParticleIndex get_particle_index() const { return pi_; }
184 
185  /** \brief Returns the Model containing the particle. */
186  Model* get_model() const { return model_; }
187 
188  IMP_HASHABLE_INLINE(Decorator, return boost::hash_value(get_particle()););
189 
190 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
191  typedef boost::false_type DecoratorHasTraits;
192 #endif
193 };
194 
195 #ifndef IMP_DOXYGEN
196 /** Check that the particle satisfies invariants registered by decorators.
197  */
198 IMPKERNELEXPORT void check_particle(Particle* p);
199 #endif
200 
201 IMPKERNEL_END_NAMESPACE
202 
203 #endif /* IMPKERNEL_DECORATOR_H */
ParticleIndex get_particle_index() const
Particle * get_particle() const
Basic types used by IMP.
Model * get_model() const
Returns the Model containing the particle.
#define IMP_HASHABLE_INLINE(name, hashret)
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Basic types used by IMP.
int compare(const VectorD< D > &a, const VectorD< D > &b)
lexicographic comparison of two vectors
Definition: VectorD.h:179
A class for storing lists of IMP items.
Various general useful macros for IMP.
Class to handle individual model particles.
Storage of a model, its restraints, constraints and particles.
Common base class for heavy weight IMP objects.
Definition: base/Object.h:106
A base class for constraints.
A nullptr-initialized pointer to an Object.
For backwards compatibility.
A shared base class to help in debugging and things.
IMP::kernel::Decorator Decorator
IMP::kernel::ParticleIndex ParticleIndex
Class for storing model, its restraints, constraints, and particles.
Definition: kernel/Model.h:72