IMP logo
IMP Reference Guide  2.8.0
The Integrative Modeling Platform
rigid_bodies.h
Go to the documentation of this file.
1 /**
2  * \file IMP/core/rigid_bodies.h
3  * \brief functionality for defining rigid bodies
4  *
5  * Copyright 2007-2017 IMP Inventors. All rights reserved.
6  */
7 
8 #ifndef IMPCORE_RIGID_BODIES_H
9 #define IMPCORE_RIGID_BODIES_H
10 
11 #include <IMP/core/core_config.h>
12 #include "internal/rigid_bodies.h"
13 
14 #include "XYZ.h"
15 #include "XYZR.h"
16 #include <IMP/SingletonContainer.h>
17 #include <IMP/SingletonModifier.h>
18 #include <IMP/Refiner.h>
19 #include <IMP/algebra/Vector3D.h>
20 #include <IMP/algebra/Rotation3D.h>
23 
24 IMPCORE_BEGIN_NAMESPACE
25 
26 IMP_DECORATORS_DECL(RigidMember, RigidMembers);
27 
28 //! A decorator for a rigid body
29 /** A rigid body particle describes a set of particles, known
30  as the members, which move rigidly together. The rigid body
31  is represented as an algebra::ReferenceFrame3D coupled
32  with local coordinates (RigidMember::get_internal_coordinates())
33  for the members expressed in that reference frame. The
34  global coordinates of the members are accessed, as with
35  other global coordinates, via the XYZ::get_coordinates().
36 
37  Since the
38  members are simply a set of particles which move together
39  they don't (necessarily) define a shape. For example,
40  the members of the rigid body made from a molecular hierarchy
41  would include particles corresponding to intermediate levels
42  of the hierarchy. As a result, methods
43  that use rigid bodies usually should simply take the list of
44  particles they are interested in and then check for rigid
45  bodies internally.
46 
47  The initial reference of the rigid body is computed from
48  the coordinates, masses and radii of the particles
49  passed to the constructor, based on diagonalizing the
50  inertial tensor (which is not stored, currently).
51 
52  RigidBodies can be nested (that is, a RigidBody can have
53  another RigidBody as a member). This can be useful for
54  organizational reasons as well as for accelerating
55  computations since operations are affected by
56  the total number of children contained in the rigid body
57  being operated on. Examples of this include collision detection
58  where if you have multiple representations of geometry at
59  different resolutions it is faster to put each of them
60  in a separate rigid body and then create one rigid body
61  containing all of them.
62 
63  It is often desirable to randomize the orientation of a rigid
64  body:
65  \include randomize_rigid_body.py
66 
67  \usesconstraint
68 
69  \see RigidMember
70  \see NonRigidMember
71  \see RigidBodyMover
72  \see RigidClosePairsFinder
73  \see RigidBodyDistancePairScore
74  */
75 class IMPCOREEXPORT RigidBody : public XYZ {
76  private:
77  /* Computes the coordinates of p given its internal (local)
78  coordinates and the current position and orientation of the
79  rigid body.
80  */
82 
83  void add_member_internal(Particle *p,
84  const algebra::ReferenceFrame3D &rf);
85 
86  void on_change();
87 
88  static void teardown_constraints(Particle *p);
89 
90  static ObjectKey get_constraint_key_0();
91 
92  static ObjectKey get_constraint_key_1();
93 
94  // setup rigid body attributes with particles in ps, using their
95  // center of mass, inertia tensor to initialize the reference frame
96  static void do_setup_particle(Model *m, ParticleIndex pi,
98 
99  // setup a rigid body with specified reference frame
100  static void do_setup_particle(Model *m, ParticleIndex pi,
101  const algebra::ReferenceFrame3D &rf);
102 
103  void setup_score_states();
104 
105  // add a member associated with xyz coords (if it has a ref frame,
106  // it is still being ignored)
107  void add_point_member(ParticleIndex pi);
108 
109  // add a member associated with a reference frame
110  void add_rigid_body_member(ParticleIndex pi);
111 
112  public:
113  RigidMembers get_rigid_members() const;
114 
115  //! Returns a list of all members that are not themselves decorated as
116  //! rigid bodies, in the form of particle indexes.
118  static ParticleIndexes empty;
119  if (get_model()->get_has_attribute(internal::rigid_body_data().members_,
120  get_particle_index())) {
121  return get_model()->get_attribute(internal::rigid_body_data().members_,
123  } else {
124  return empty;
125  }
126  }
127 
128  //! Get all members that are themselves decorated as rigid bodies,
129  //! as model particle indexes
131  static ParticleIndexes empty;
132  if (get_model()->get_has_attribute(
133  internal::rigid_body_data().body_members_, get_particle_index())) {
134  return get_model()->get_attribute(
135  internal::rigid_body_data().body_members_, get_particle_index());
136  } else {
137  return empty;
138  }
139  }
140 
141  //! Get the particle indexes of any member of this rigid body, regardless
142  //! of whether it is itself a rigid body or not
144  return get_member_particle_indexes() + get_body_member_particle_indexes();
145  }
146 
148 
149  /**
150  Create a rigid body for pi with the particle indexes ps as its members.
151  The coordinates of pi are set to the center of mass of ps and the rotation
152  of its reference frame is based on the diagonalized inertia tensor of ps.
153 
154  @note If size(ps)=1, then its reference frame is copied if it is a
155  rigid body, or its rotation is set to identity if it is not
156  a rigid body.
157  */
159 
160  /**
161  Create a rigid body with the passed reference frame as its initial
162  position.
163  */
165 
166  //! Make the rigid body no longer rigid.
167  static void teardown_particle(RigidBody rb);
168 
169  IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(RigidBody);
170  ~RigidBody();
171 
172  //! Return true if the particle is a rigid body
173  static bool get_is_setup(Model *m, ParticleIndex pi) {
174  return internal::get_has_required_attributes_for_body(m, pi);
175  }
176 
177  // swig doesn't support using, so the method is wrapped
178  //! Get the coordinates of the particle
179  //! (= translation from local to global rigid body coordinates)
181 
182  //! returns the rotation of the particle
183  //! (= rotation from local to global rigid body orientation)
185  return get_reference_frame().get_transformation_to().get_rotation();
186  }
187 
188  //! Get the reference frame of this rigid body, which enables
189  //! trnasformation between the local rigid body coordinates
190  //! global coordinates
193  get_model()->get_attribute(internal::rigid_body_data().quaternion_[0],
195  get_model()->get_attribute(internal::rigid_body_data().quaternion_[1],
197  get_model()->get_attribute(internal::rigid_body_data().quaternion_[2],
199  get_model()->get_attribute(internal::rigid_body_data().quaternion_[3],
200  get_particle_index()));
201  IMP_USAGE_CHECK_FLOAT_EQUAL(v.get_squared_magnitude(), 1,
202  "Rotation is not a unit vector: " << v);
203  /*if (v.get_squared_magnitude() > 0){
204  v = v.get_unit_vector();
205  } else {
206  v = algebra::VectorD<4>(1,0,0,0);
207  }*/
208  bool assume_normalized = true;
209  IMP::algebra::Rotation3D rot(v, assume_normalized);
212  }
213 
214  //! Set the current reference frame
215  /** All members of the rigid body will have their coordinates updated
216  immediately.
217  \see IMP::core::transform(RigidBody,const algebra::Transformation3D&)
218  \see set_reference_frame_lazy()
219  */
220  void set_reference_frame(const IMP::algebra::ReferenceFrame3D &tr);
221 
222  //! Change the reference, delay updating the members until evaluate
223  /** \see set_reference_frame()
224  */
225  inline void set_reference_frame_lazy
227  {
230  get_particle()->set_value(internal::rigid_body_data().quaternion_[0], v[0]);
231  get_particle()->set_value(internal::rigid_body_data().quaternion_[1], v[1]);
232  get_particle()->set_value(internal::rigid_body_data().quaternion_[2], v[2]);
233  get_particle()->set_value(internal::rigid_body_data().quaternion_[3], v[3]);
235  }
236 
237 #ifndef SWIG
238 #ifndef IMP_DOXYGEN
239  //! 'expert' method for setting the reference more quickly
240  //! use at own risk
241  inline void set_rotation_lazy_using_internal_tables
242  (const IMP::algebra::Rotation3D &rot,
243  double* quaternion_tables[])
244  {
246  rot.get_quaternion();
247  int pi=get_particle_index().get_index();
248  quaternion_tables[0][pi]=v[0];
249  quaternion_tables[1][pi]=v[1];
250  quaternion_tables[2][pi]=v[2];
251  quaternion_tables[3][pi]=v[3];
252  }
253 
254  //! 'expert' method for setting the reference more quickly
255  //! use at own risk
256  inline void apply_rotation_lazy_using_internal_tables
257  (const IMP::algebra::Rotation3D &rot,
258  double* quaternion_tables[])
259  {
260  int pi=get_particle_index().get_index();
262  ( quaternion_tables[0][pi],
263  quaternion_tables[1][pi],
264  quaternion_tables[2][pi],
265  quaternion_tables[3][pi] );
267  (cur_rot*rot).get_quaternion();;
268  quaternion_tables[0][pi]=v[0];
269  quaternion_tables[1][pi]=v[1];
270  quaternion_tables[2][pi]=v[2];
271  quaternion_tables[3][pi]=v[3];
272  }
273 
274 #endif // IMP_DOXYGEN
275 #endif // SWIG
276 
277 
278 
279 
280  /** Update the reference frame of the rigid body based on aligning
281  the current global coordinates of the passed rigid body members
282  onto their old local coordinates. Non-passed members are ignored.
283 
284  This method is useful for updating the rigid body after new
285  global coordinates were loaded for the members. The members are
286  passed explicitly since, typically, some are desired to just
287  move along with the newly loaded rigid body.
288 
289  \note This requires at least three members that are not colinear
290  to work.
291  */
292  void set_reference_frame_from_members(const ParticleIndexes &members);
293 
294  /** Update the translational and rotational derivatives
295  on the rigid body center of mass, using the Cartesian derivative
296  vector at a speicified location (the point where the force is
297  being applied).
298 
299  Updates both the quaternion derivatives and the torque.
300 
301  @param local_derivative The derivative vector in local rigid body coordinates
302  @param local_location The location where the derivative is taken in local
303  rigid body coordinates
304  @param da Accumulates the output derivative over the rigid body
305  center of mass (translation and rotation torque, quaternion)
306  */
307  inline void add_to_derivatives(const algebra::Vector3D &local_derivative,
308  const algebra::Vector3D &local_location,
309  DerivativeAccumulator &da);
310 
311  /** Faster version of the above, if all is cached.
312 
313  @param local_derivative The derivative vector in local rigid body coordinates
314  @param global_derivative The derivative vector in global coordinates
315  @param local_location The location where the derivative is taken in local
316  rigid body coordinates
317  @param rot_local_to_global Rotation matrix from local rigid body to
318  global coordinates
319  @param da Accumulates the output derivative over the rigid body
320  center of mass (translation and rotation torque, quaternion)
321  */
322  inline void add_to_derivatives(const algebra::Vector3D &local_derivative,
323  const algebra::Vector3D &global_derivative,
324  const algebra::Vector3D &local_location,
325  const algebra::Rotation3D &rot_local_to_global,
326  DerivativeAccumulator &da);
327 
328  /** Add torque to derivative table of this rigid body
329  Note that this method does not update the quaternion derivatives, so should
330  be used by optimizers that rely on torque only (e.g. BrownianDynamics)
331 
332  @param torque_local Torque vector in local reference frame,
333  in units of kCal/Mol/Radian
334  @param da Object for accumulating derivatives
335  */
336  inline void add_to_torque(const algebra::Vector3D &torque_local,
337  DerivativeAccumulator &da);
338 
339 
340  /** The units are kCal/Mol/Radian */
342  algebra::Vector3D ret;
343  for (unsigned int i = 0; i < 3; ++i) {
344  ret[i] = get_model()->get_derivative(
345  internal::rigid_body_data().torque_[i], get_particle_index());
346  }
347  return ret;
348  }
349 
350 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
351  //! expert method for fast const-access to internal torque
352  //! of coordinate #i table
353  static double const* access_torque_i_data
354  (IMP::Model const* m, unsigned int i)
355  {
356  IMP_USAGE_CHECK(i<3,"torque is 3 dimensional");
357  FloatKey k=
358  internal::rigid_body_data().torque_[i];
359  double const* ret=m->access_derivative_data(k);
360  return ret;
361  }
362 
363  //! expert method for fast access to internal torque
364  //! of coordinate #i table
365  static double* access_torque_i_data
366  (IMP::Model* m, unsigned int i)
367  {
368  IMP_USAGE_CHECK(i<3,"torque is 3 dimensional");
369  FloatKey k=
370  internal::rigid_body_data().torque_[i];
371  double* ret=m->access_derivative_data(k);
372  return ret;
373  }
374 
375  //! expert method for fast const-access to internal quaternion coordinate #i table
376  static double const* access_quaternion_i_data
377  (IMP::Model const* m, unsigned int i)
378  {
379  IMP_USAGE_CHECK(i<4,"quaternion is 4 dimensional");
380  FloatKey k=
381  internal::rigid_body_data().quaternion_[i];
382  double const* ret=m->access_attribute_data(k);
383  return ret;
384  }
385 
386  //! expert method for fast access to internal quaternion coordinate #i table
387  static double* access_quaternion_i_data
388  (IMP::Model* m, unsigned int i)
389  {
390  IMP_USAGE_CHECK(i<4,"quaternion is 4 dimensional");
391  FloatKey k=
392  internal::rigid_body_data().quaternion_[i];
393  double* ret=m->access_attribute_data(k);
394  return ret;
395  }
396 
397 
398 #endif
399 
400  //! Returns true if the rigid body coordinates are flagged as
401  //! optimized for Optimizer objects
402  bool get_coordinates_are_optimized() const;
403 
404  //! Set whether the rigid body coordinates are flagged as optimized
405  //! for Optimizer objects
406  void set_coordinates_are_optimized(bool tf);
407 
408  //! Normalize the quaternion
409  void normalize_rotation();
410 
411  //! Update the global coordinates of the members based on
412  //! their local coordinates and this rigid body's reference frame
413  void update_members();
414 
415  //! Get the derivatives of the quaternion
416  algebra::VectorD<4> get_rotational_derivatives() const;
417 
418 #ifndef IMP_DOXYGEN
419  unsigned int get_number_of_members() const {
420  return get_body_member_particle_indexes().size() +
421  get_member_particle_indexes().size();
422  }
423 
424  RigidMember get_member(unsigned int i) const;
425 #endif
426  //! Add a proper member that moves rigidly with this rigid body,
427  //! properly handling rigid bodies and XYZ particles.
428  /**
429  Add p to the list of members. If p is a valid RigidBody, it is added
430  as a rigid body member, otherwise it is added as a point member
431  (for which the rotation is not tracked). By default, p is considered
432  a strictly rigid member, in that its local coordinates are not expected
433  to change independently.
434 
435  \see add_non_rigid_member
436  */
437  void add_member(ParticleIndexAdaptor p);
438 
439  /** Add a non-rigid member, for which internal coordinates may change
440  independently.
441 
442  @note Currently RigidBody non-rigid members are not handled properly.
443  */
444  void add_non_rigid_member(ParticleIndexAdaptor p);
445 
446  /** Set whether a particular member is flagged as a rigid member
447  or as a non-rigid member. This affects the way the rigid body
448  updates the coordinates and / or reference frame of its members.
449  */
450  void set_is_rigid_member(ParticleIndex pi, bool tf);
451 };
452 
453 #ifndef IMP_DOXYGEN
454 // inline implementation
455 void RigidBody::add_to_torque(const algebra::Vector3D &torque_local,
456  DerivativeAccumulator &da) {
457  for (unsigned int i = 0; i < 3; ++i) {
458  get_model()->add_to_derivative(internal::rigid_body_data().torque_[i],
459  get_particle_index(), torque_local[i], da);
460  }
461 }
462 
463 
464 // inline implementation
465 void RigidBody::add_to_derivatives(const algebra::Vector3D &deriv_local,
466  const algebra::Vector3D &deriv_global,
467  const algebra::Vector3D &local,
468  const algebra::Rotation3D &rot_local_to_global,
469  DerivativeAccumulator &da) {
470  // IMP_LOG_TERSE( "Accumulating rigid body derivatives" << std::endl);
471  XYZ::add_to_derivatives(deriv_global, da);
472  algebra::VectorD<4> q(0, 0, 0, 0);
473  for (unsigned int j = 0; j < 4; ++j) {
474  algebra::Vector3D v = rot_local_to_global.get_derivative(local, j);
475  q[j] = deriv_global * v;
476  }
477  for (unsigned int j = 0; j < 4; ++j) {
478  get_model()->add_to_derivative(internal::rigid_body_data().quaternion_[j],
479  get_particle_index(), q[j], da);
480  }
481  algebra::Vector3D torque = algebra::get_vector_product(local, deriv_local);
482  for (unsigned int i = 0; i < 3; ++i) {
483  get_model()->add_to_derivative(internal::rigid_body_data().torque_[i],
484  get_particle_index(), torque[i], da);
485  }
486 }
487 
488 // inline implementation
489 void RigidBody::add_to_derivatives(const algebra::Vector3D &deriv_local,
490  const algebra::Vector3D &local,
491  DerivativeAccumulator &da) {
492  algebra::Rotation3D rot_local_to_global =
493  get_reference_frame().get_transformation_to().get_rotation();
494  const algebra::Vector3D deriv_global = rot_local_to_global * deriv_local;
495  add_to_derivatives(deriv_local, deriv_global, local,
496  rot_local_to_global, da);
497 }
498 #endif
499 
500 
501 /** It is often useful to store precalculated properties of the rigid body
502  for later use. These need to be cleared out when the rigid body changes.
503  To make sure this happens, register the key here.
504 */
505 void IMPCOREEXPORT add_rigid_body_cache_key(ObjectKey k);
506 
507 //! A member of a rigid body, it has internal (local) coordinates
508 class IMPCOREEXPORT RigidBodyMember : public XYZ {
510 
511  RigidBody get_rigid_body() const;
512 
513  //! Return the internal (local) coordinates of this member
514  /** These coordinates are relative to the reference frame of the
515  rigid body that owns it
516  */
518  return get_model()->get_internal_coordinates(get_particle_index());
519  }
520 
521  //! set the internal (local) coordinates for this member
523  get_model()->get_internal_coordinates(get_particle_index()) = v;
524  get_rigid_body().get_model()->clear_particle_caches(get_particle_index());
525  }
526 
527  //! Set the internal (local) coordinates of this member,
528  //! assuming it is a rigid body itself
529  /** Set the internal (local) coordinates of this rigid body
530  relative to the reference frame of the rigid body that owns it
531  */
534  get_model()->get_has_attribute(
535  internal::rigid_body_data().lquaternion_[0], get_particle_index()),
536  "Can only set the internal transformation if member is"
537  << " a rigid body itself.");
538  set_internal_coordinates(v.get_translation());
539 
540  get_model()->set_attribute(internal::rigid_body_data().lquaternion_[0],
542  v.get_rotation().get_quaternion()[0]);
543  get_model()->set_attribute(internal::rigid_body_data().lquaternion_[1],
545  v.get_rotation().get_quaternion()[1]);
546  get_model()->set_attribute(internal::rigid_body_data().lquaternion_[2],
548  v.get_rotation().get_quaternion()[2]);
549  get_model()->set_attribute(internal::rigid_body_data().lquaternion_[3],
551  v.get_rotation().get_quaternion()[3]);
552  get_rigid_body().get_model()->clear_particle_caches(get_particle_index());
553  }
554 
555  //! Return the internal (local) coordinates of this member,
556  //! assuming it is a rigid body itself
557  /** Return the internal (local) coordinates of this rigid body
558  relative to the reference frame of the rigid body that owns it
559  */
562  get_model()->get_has_attribute(
563  internal::rigid_body_data().lquaternion_[0], get_particle_index()),
564  "Can only set the internal transformation if member is a "
565  << "rigid body itself.");
566  algebra::Vector3D tr =
567  get_model()->get_internal_coordinates(get_particle_index());
569  get_model()->get_attribute(internal::rigid_body_data().lquaternion_[0],
571  get_model()->get_attribute(internal::rigid_body_data().lquaternion_[1],
573  get_model()->get_attribute(internal::rigid_body_data().lquaternion_[2],
575  get_model()->get_attribute(internal::rigid_body_data().lquaternion_[3],
576  get_particle_index()));
577  return algebra::Transformation3D(rot, tr);
578  }
579 
580  ~RigidBodyMember();
581  //! sets the global coordinates of this member using XYZ::set_coordinates()
582  // this is here since swig does like using statements
583  void set_coordinates(const algebra::Vector3D &center) {
584  XYZ::set_coordinates(center);
585  }
586 
587 #ifndef IMP_DOXYGEN
588  //! Set the global coordinates from the internal coordinates,
589  //! using tr as a reference frame
591  set_coordinates(tr.get_transformed(get_internal_coordinates()));
592  }
593 #endif
594  IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(RigidBodyMember);
595 
596  //! return true if it is a rigid member
598  return internal::get_has_required_attributes_for_member(m, p);
599  }
600 
601  static FloatKeys get_internal_coordinate_keys() {
602  return internal::rigid_body_data().child_keys_;
603  }
604 };
605 
606 //! A decorator for a particle that is part of a rigid body, and is
607 //! actually rigid
608 /**
609  RigidMember particles, as opposed to NonRigidMember particles, are
610  not expected to change their internal (local) coordinates or
611  reference frames, and their global coordinates are expected to
612  change only through setting the coordinates (or reference frame) of
613  the rigid body that owns them.
614 
615  \see RigidBody
616  */
617 class IMPCOREEXPORT RigidMember : public RigidBodyMember {
618  public:
620 
621  IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(RigidMember);
622  ~RigidMember();
623 
624  //! return true if it is a rigid member
626  return internal::get_has_required_attributes_for_rigid_member(m, p);
627  }
628 };
629 
630 //! A decorator for a particle that is part of a rigid body but not rigid
631 /** NonRigidMembers, like RigidMembers, have internal coordinates and move
632  along with the rigid body. However, it is expected that their internal
633  coordinates will change, and so they are not part of structures that
634  assume rigidity.
635 
636  \see RigidBody
637  */
638 class IMPCOREEXPORT NonRigidMember : public RigidBodyMember {
639  public:
641  IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(NonRigidMember);
642  ~NonRigidMember();
643 
644  //! return true if it is a rigid member
645  static bool get_is_setup(Model *m, ParticleIndex p) {
646  return internal::get_has_required_attributes_for_non_member(m, p);
647  }
648 };
649 
650 #ifndef IMP_DOXYGEN
651 
652 class IMPCOREEXPORT RigidMembersRefiner : public Refiner {
653  public:
654  RigidMembersRefiner(std::string name = "RigidMembersRefiner%d")
655  : Refiner(name) {}
656  virtual bool get_can_refine(Particle *) const IMP_OVERRIDE;
657 #ifndef SWIG
658  using Refiner::get_refined;
659 #endif
660  virtual const ParticlesTemp get_refined(Particle *) const
661  IMP_OVERRIDE;
662  virtual ModelObjectsTemp do_get_inputs(
663  Model *m, const ParticleIndexes &pis) const IMP_OVERRIDE;
664  IMP_OBJECT_METHODS(RigidMembersRefiner);
665 };
666 
667 namespace internal {
668 IMPCOREEXPORT RigidMembersRefiner *get_rigid_members_refiner();
669 }
670 #endif
671 
672 //! Transform a rigid body
673 /** The transformation is applied current conformation of the rigid
674  body, as opposed to replacing the current conformation, as in
675  RigidBody::set_reference_frame().
676 
677  \see RigidBody
678  \see algebra::Transformation3D
679 */
680 inline void transform(RigidBody a, const algebra::Transformation3D &tr) {
681  a.set_reference_frame(get_transformed(a.get_reference_frame(), tr));
682 }
683 
684 /** Compute the rigid body reference frame given a set of input particles.
685  */
686 IMPCOREEXPORT algebra::ReferenceFrame3D get_initial_reference_frame(
687  Model *m, const ParticleIndexes &pis);
688 
689 inline algebra::ReferenceFrame3D get_initial_reference_frame(
690  const ParticlesTemp &ps) {
691  if (ps.empty()) {
692  return algebra::ReferenceFrame3D();
693  }
694  return get_initial_reference_frame(ps[0]->get_model(),
695  get_indexes(ps));
696 }
697 
698 /** Create a set of rigid bodies that are bound together for efficiency.
699  These rigid bodies cannot nest or have other dependencies among them.
700 
701  All rigid bodies have the default reference frame.
702 
703  \note Do not use this with DOMINO as all the rigid bodies use the same
704  ScoreState and so will be considered inter-dependent.
705 */
706 IMPCOREEXPORT ParticlesTemp create_rigid_bodies(Model *m,
707  unsigned int n,
708  bool no_members =
709  false);
710 
711 IMP_DECORATORS_DEF(RigidMember, RigidMembers);
712 IMP_DECORATORS(RigidBody, RigidBodies, XYZs);
713 
714 /** Show the rigid body hierarchy rooted at passed body. */
715 IMPCOREEXPORT void show_rigid_body_hierarchy(RigidBody rb,
716  TextOutput out =
717  TextOutput(std::cout));
718 
719 //! Return the index of the outer-most rigid body containing the member.
720 /** Use this to, for example, group particles into rigid bodies. */
721 IMPCOREEXPORT ParticleIndex get_root_rigid_body(RigidMember m);
722 
723 IMPCORE_END_NAMESPACE
724 
725 #endif /* IMPCORE_RIGID_BODIES_H */
void add_to_derivatives(const algebra::Vector3D &v, DerivativeAccumulator &d)
Add the vector v to the derivative vector of the x,y,z coordinates.
Definition: XYZ.h:82
void set_internal_coordinates(const algebra::Vector3D &v) const
set the internal (local) coordinates for this member
Definition: rigid_bodies.h:522
A Modifier on ParticlesTemp.
Simple 3D transformation class.
ParticleIndex get_particle_index() const
Returns the particle index decorated by this decorator.
Definition: Decorator.h:188
Key< 0 > FloatKey
The type used to identify float attributes in the Particles.
Definition: base_types.h:32
A member of a rigid body, it has internal (local) coordinates.
Definition: rigid_bodies.h:508
A container for Singletons.
ParticleIndex get_root_rigid_body(RigidMember m)
Return the index of the outer-most rigid body containing the member.
#define IMP_USAGE_CHECK_FLOAT_EQUAL(expra, exprb, message)
Definition: check_macros.h:178
algebra::Vector3D get_coordinates() const
Definition: rigid_bodies.h:180
IMP::algebra::Rotation3D get_rotation() const
Definition: rigid_bodies.h:184
#define IMP_DECORATOR_SETUP_1(Name, FirstArgumentType, first_argument_name)
#define IMP_OBJECT_METHODS(Name)
Define the basic things needed by any Object.
Definition: object_macros.h:25
Model * get_model() const
Returns the Model containing the particle.
Definition: Decorator.h:191
ParticlesTemp create_rigid_bodies(Model *m, unsigned int n, bool no_members=false)
Index< ParticleIndexTag > ParticleIndex
Definition: base_types.h:154
bool get_coordinates_are_optimized() const
Get whether the coordinates are optimized.
Definition: XYZ.h:89
void add_rigid_body_cache_key(ObjectKey k)
A more IMP-like version of the std::vector.
Definition: Vector.h:39
const Vector4D & get_quaternion() const
Return the quaternion so that it can be stored.
Definition: Rotation3D.h:200
Simple XYZ decorator.
A reference frame in 3D.
void show_rigid_body_hierarchy(RigidBody rb, TextOutput out=TextOutput(std::cout))
void clear_particle_caches(ParticleIndex pi)
Clear all the cache attributes of a given particle.
IMP::Vector< IMP::WeakPointer< ModelObject > > ModelObjectsTemp
Definition: base_types.h:82
Class for storing model, its restraints, constraints, and particles.
Definition: Model.h:72
const Rotation3D & get_rotation() const
Return the rotation associated with this transformation.
algebra::Vector3D get_torque() const
Definition: rigid_bodies.h:341
static bool get_is_setup(Model *m, ParticleIndexAdaptor p)
return true if it is a rigid member
Definition: rigid_bodies.h:625
virtual bool get_can_refine(Particle *) const
Return true if this refiner can refine that particle.
Definition: Refiner.h:51
Vector3D get_vector_product(const Vector3D &p1, const Vector3D &p2)
Return the vector product (cross product) of two vectors.
Definition: Vector3D.h:31
void set_reference_frame(const IMP::algebra::ReferenceFrame3D &tr)
Set the current reference frame.
A Cartesian vector in D-dimensions.
Definition: VectorD.h:52
Refine a particle into a list of particles.
void set_coordinates(const algebra::Vector3D &v)
set all coordinates from a vector
Definition: XYZ.h:62
const Transformation3D & get_transformation_to() const
static bool get_is_setup(Model *m, ParticleIndex pi)
Return true if the particle is a rigid body.
Definition: rigid_bodies.h:173
const ParticleIndexes & get_member_particle_indexes() const
Definition: rigid_bodies.h:117
static bool get_is_setup(Model *m, ParticleIndexAdaptor p)
return true if it is a rigid member
Definition: rigid_bodies.h:597
Represent an XYZR particle with a sphere.
void set_attribute(TypeKey attribute_key, ParticleIndex particle, Type value)
set the value of particle attribute with the specified key
A decorator for a particle with x,y,z coordinates.
Definition: XYZ.h:30
const algebra::Vector3D & get_coordinates() const
Convert it to a vector.
Definition: XYZ.h:109
virtual const ParticlesTemp get_refined(Particle *a) const =0
Refine the passed particle into a set of particles.
Vector3D get_transformed(const Vector3D &o) const
Transform.
A decorator for a particle that is part of a rigid body but not rigid.
Definition: rigid_bodies.h:638
Simple 3D rotation class.
void set_internal_transformation(const algebra::Transformation3D &v)
Definition: rigid_bodies.h:532
Particle * get_particle() const
Returns the particle decorated by this decorator.
Definition: Decorator.h:171
Key< 4 > ObjectKey
The type used to identify an Object attribute.
Definition: base_types.h:48
3D rotation class.
Definition: Rotation3D.h:46
void set_coordinates_are_optimized(bool tf) const
Set whether the coordinates are optimized.
Definition: XYZ.h:95
void set_coordinates(const algebra::Vector3D &center)
sets the global coordinates of this member using XYZ::set_coordinates()
Definition: rigid_bodies.h:583
#define IMP_DECORATOR_METHODS(Name, Parent)
VectorD< 3 > Vector3D
Definition: VectorD.h:395
Abstract class to implement hierarchical methods.
Definition: Refiner.h:34
Simple 3D vector class.
Class to handle individual particles of a Model object.
Definition: Particle.h:41
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:168
#define IMP_DECORATORS(Name, PluralName, Parent)
Define the types for storing sets of decorators.
void transform(RigidBody a, const algebra::Transformation3D &tr)
Transform a rigid body.
Definition: rigid_bodies.h:680
A reference frame in 3D.
ParticleIndexes get_member_indexes() const
Definition: rigid_bodies.h:143
const ParticleIndexes & get_body_member_particle_indexes() const
Definition: rigid_bodies.h:130
A decorator for a rigid body.
Definition: rigid_bodies.h:75
const Vector3D & get_translation() const
Return the translation vector associated with this transformation.
algebra::Transformation3D get_internal_transformation() const
Definition: rigid_bodies.h:560
Type get_attribute(TypeKey attribute_key, ParticleIndex particle)
get the value of the particle attribute with the specified key
Decorator for a sphere-like particle.
ParticleIndexes get_indexes(const ParticlesTemp &ps)
static bool get_is_setup(Model *m, ParticleIndex p)
return true if it is a rigid member
Definition: rigid_bodies.h:645
#define IMP_OVERRIDE
Cause a compile error if this method does not override a parent method.
const algebra::Vector3D & get_internal_coordinates() const
Return the internal (local) coordinates of this member.
Definition: rigid_bodies.h:517
IMP::algebra::ReferenceFrame3D get_reference_frame() const
Definition: rigid_bodies.h:191