IMP  2.0.1
The Integrative Modeling Platform
particle_states.h
Go to the documentation of this file.
1 /**
2  * \file IMP/domino/particle_states.h
3  * \brief A beyesian infererence-based sampler.
4  *
5  * Copyright 2007-2013 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPDOMINO_PARTICLE_STATES_H
10 #define IMPDOMINO_PARTICLE_STATES_H
11 
12 #include <IMP/domino/domino_config.h>
13 #include "domino_macros.h"
14 #include "Subset.h"
15 #include "Assignment.h"
16 #include <IMP/Sampler.h>
17 #include <IMP/macros.h>
18 #include <IMP/SingletonContainer.h>
20 #include <IMP/algebra/Vector3D.h>
21 #include <IMP/core/rigid_bodies.h>
23 #include <IMP/internal/OwnerPointer.h>
24 #include <IMP/base/Vector.h>
25 #include <IMP/base/map.h>
26 #include <IMP/base/InputAdaptor.h>
28 
29 IMPDOMINO_BEGIN_NAMESPACE
30 /** Handle the states for a particular particle (or "class" of
31  particles. For example a state enumerator class could take
32  a bounding box and a number,n, and generate n points in the
33  bounding box. Then the get_number function woudld return
34  n and update_to_state would modify the particle to have the
35  coordiantes for state i.
36  */
37 class IMPDOMINOEXPORT ParticleStates: public IMP::base::Object {
38 public:
39  ParticleStates(std::string name="ParticleStates %1%"): Object(name){}
40  virtual unsigned int get_number_of_particle_states() const=0;
41  virtual void load_particle_state(unsigned int, Particle*) const=0;
42  //! Return an embedding of the state
43  /** By default this just returns a 1D vector containing the index.
44  The vector needs to have the same dimension for each value of
45  i.
46  */
47  virtual algebra::VectorKD get_embedding(unsigned int i) const {
48  Floats f(1,i);
49  return algebra::VectorKD(f.begin(), f.end());
50  }
51  //! Return the state closest to a given embedding
52  virtual unsigned int get_nearest_state(const algebra::VectorKD &v) const {
53  IMP_INTERNAL_CHECK(v.get_dimension()==1, "This is not a defaultly produced"
54  << " embedding.");
55  IMP_INTERNAL_CHECK(v[0] >=0 && v[0] < get_number_of_particle_states(),
56  "Out of range state found, this is not a default "
57  << "embedding.");
58  return static_cast<unsigned int>(v[0]);
59  }
60  virtual ~ParticleStates();
61 };
62 
64 
65 /** Store the association between particles and the classes
66  which manage their states. I'm not a huge fan of having
67  this class, but I haven't thought of a better way to store
68  the information that is easily exposed to python
69  and gets to all the right places. It is initialized internally
70  in the DominoSampler.
71  */
72 class IMPDOMINOEXPORT ParticleStatesTable: public IMP::base::Object {
73  typedef IMP::base::map<Particle*,
74  IMP::OwnerPointer<ParticleStates> > Map;
75  Map enumerators_;
76  friend class DominoSampler;
77  public:
78  ParticleStatesTable(): Object("ParticleStatesTable%1%"){}
79  // implementation methods use this to get the enumerator
80  ParticleStates* get_particle_states(Particle *p) const {
81  IMP_USAGE_CHECK(enumerators_.find(p) != enumerators_.end(),
82  "I don't know about particle " << p->get_name());
83  return enumerators_.find(p)->second;
84  }
85  bool get_has_particle(Particle *p) const {
86  return enumerators_.find(p) != enumerators_.end();
87  }
88  ParticlesTemp get_particles() const {
89  ParticlesTemp ret;
90  ret.reserve(enumerators_.size());
91  for (Map::const_iterator it= enumerators_.begin();
92  it != enumerators_.end(); ++it) {
93  ret.push_back(it->first);
94  }
95  std::sort(ret.begin(), ret.end());
96  return ret;
97  }
98  //! Return the subset corresponding to all the particles
99  Subset get_subset() const {
100  return Subset(get_particles());
101  }
102  /** One can set the states more than once. If you do that, be
103  careful.
104  */
106  IMP_USAGE_CHECK(e->get_number_of_particle_states() >0,
107  "Cannot have 0 states for a particle: \""
108  << p->get_name() << "\"\n");
109  enumerators_[p]=e;
110  }
112 };
113 
115 
116 
117 /** Store the state index in the particle. The particle must
118  already have the attribute in question.
119 */
120 class IMPDOMINOEXPORT IndexStates: public ParticleStates {
121  unsigned int n_;
122  IntKey k_;
123 public:
124  /** n is the number of states and k is the attribute key
125  to use.*/
126  IndexStates(unsigned int n, IntKey k=IntKey("state")):
127  ParticleStates("IndexStates %1%"), n_(n), k_(k){}
129 };
130 
131 /** Store a set of states which explicitly define the XYZ coordinates of
132  the particle in question.
133 */
134 class IMPDOMINOEXPORT XYZStates: public ParticleStates {
135  algebra::Vector3Ds states_;
137 public:
138  XYZStates(const algebra::Vector3Ds &states):
139  ParticleStates("XYZStates %1%"), states_(states),
140  nn_(new algebra::NearestNeighbor3D(states)) {}
141  algebra::Vector3D get_vector(unsigned int i) const {
142  IMP_USAGE_CHECK(i < states_.size(),
143  "Out of range");
144  return states_[i];
145  }
146  algebra::VectorKD get_embedding(unsigned int i) const {
147  IMP_USAGE_CHECK(i < states_.size(),
148  "Out of range");
149  return states_[i];
150  }
151  unsigned int get_nearest_state(const algebra::VectorKD &v) const {
152  return nn_->get_nearest_neighbors(v, 1)[0];
153  }
155 };
156 
157 /** Store a set of states which explicitly define the
158  transformation coordinates of the particle in question.
159 */
160 class IMPDOMINOEXPORT RigidBodyStates: public ParticleStates {
162  double scale_;
164 public:
166  double scale=1);
167  algebra::ReferenceFrame3D get_reference_frame(unsigned int i) const {
168  IMP_USAGE_CHECK(i < states_.size(),
169  "Out of range");
170  return states_[i];
171  }
172  algebra::VectorKD get_embedding(unsigned int i) const;
173  unsigned int get_nearest_state(const algebra::VectorKD &v) const;
175 };
176 
177 /** Store a set of states which explicitly define the
178  internal transformation of a rigid member
179 */
180 class IMPDOMINOEXPORT NestedRigidBodyStates: public ParticleStates {
181  algebra::Transformation3Ds states_;//states of a nested rigid body
182  double scale_;
184 public:
185  /**
186  \param[in] states states of a rigid member with respect to its parent
187  \param[in] scale an estimate of the radius of the rigid bodies used.
188  Unfortunately, this is hard to determine automatically in the right
189  place.
190  */
192  double scale=100);
193  algebra::Transformation3D get_transformation(unsigned int i) const {
194  IMP_USAGE_CHECK(i < states_.size(),
195  "Out of range");
196  return states_[i];
197  }
198  algebra::VectorKD get_embedding(unsigned int i) const;
199  unsigned int get_nearest_state(const algebra::VectorKD &v) const;
201 };
202 
203 /** Combine two particle states together. They must both have the same
204  number of states.
205 */
206 class IMPDOMINOEXPORT CompoundStates: public ParticleStates {
207  IMP::OwnerPointer<ParticleStates> a_, b_;
208 public:
210  ParticleStates("CompoundStates %1%"), a_(a), b_(b){}
212 };
213 
214 /** Load particle states for a set of particles based on the state
215  index of a single particle, This can be used to implement compound
216  objects (like rigid bodies), where state i of the particle being
217  sampled causes a set of representation balls to be moved to
218  certain locations.
219 */
220 class IMPDOMINOEXPORT RecursiveStates: public ParticleStates {
221  Subset s_;
222  Assignments ss_;
223  IMP::OwnerPointer<ParticleStatesTable> pst_;
224  ScopedScoreState sss_;
225  public:
227  Subset s, const Assignments &ss,
228  ParticleStatesTable * pst);
230 };
231 
232 
233 /** Permute the states of a particle. This might be useful when
234  trying to sample from a too large set of Assignments. However,
235  it will break many filters, so use with care.
236 */
237 class IMPDOMINOEXPORT PermutationStates: public ParticleStates {
238  IMP::OwnerPointer<ParticleStates> inner_;
239  IMP::base::Vector<int> permutation_;
240  public:
242  /** Return the index of the ith state in the inner ParticleState
243  object.*/
244  unsigned int get_inner_state(unsigned int i) const {
245  IMP_CHECK_OBJECT(this);
246  IMP_USAGE_CHECK(i < permutation_.size(), "Out of range inner state");
247  unsigned int cur= permutation_[i];
248  IMP_INTERNAL_CHECK(cur < inner_->get_number_of_particle_states(),
249  "Out of range state returned. This is perplexing.");
250  return cur;
251  }
253 };
254 
255 #ifndef IMP_DOXYGEN
256 inline unsigned int
257 PermutationStates::get_number_of_particle_states() const {
258  return inner_->get_number_of_particle_states();
259 }
260 inline void
261 PermutationStates::load_particle_state(unsigned int i, Particle *p) const {
262  return inner_->load_particle_state(get_inner_state(i), p);
263 }
264 #endif
265 
266 
267 /** Accept either particles, decorators or ParticleStatesTable
268  as an imput to define a list of particle.*/
270 #ifndef SWIG
271  public ParticlesTemp, public base::InputAdaptor
272 #else
273  public base::InputAdaptor
274 #endif
275 {
276 public:
278  ParticlesTemp(pst->get_particles()) {
279  }
280  ParticlesAdaptor(const ParticlesTemp &ps): ParticlesTemp(ps.begin(),
281  ps.end()){}
282 };
283 
284 IMPDOMINO_END_NAMESPACE
285 
286 #endif /* IMPDOMINO_PARTICLE_STATES_H */