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