IMP logo
IMP Reference Guide  develop.4eee3cf66f,2026/08/01
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-2026 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/Refiner.h>
17 #include <IMP/algebra/Vector3D.h>
18 #include <IMP/algebra/Rotation3D.h>
21 #include <Eigen/Dense>
22 
23 IMPCORE_BEGIN_NAMESPACE
24 
25 IMP_DECORATORS_DECL(RigidMember, RigidMembers);
26 IMP_DECORATORS_DECL(RigidBodyMember, RigidBodyMembers);
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 updating 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  // remove a member associated with xyz coords
122  void remove_point_member(ParticleIndex pi);
123 
124  // remove a member associated with a reference frame
125  void remove_rigid_body_member(ParticleIndex pi);
126 
127  public:
128  RigidMembers get_rigid_members() const;
129 
130  //! Get key for rotation quaternion.
132  return internal::rigid_body_data().quaternion_;
133  }
134 
135  //! Returns a list of all members that are not themselves decorated as
136  //! rigid bodies, in the form of particle indexes.
138  static ParticleIndexes empty;
139  if (get_model()->get_has_attribute(internal::rigid_body_data().members_,
140  get_particle_index())) {
141  return get_model()->get_attribute(internal::rigid_body_data().members_,
143  } else {
144  return empty;
145  }
146  }
147 
148  //! Get all members that are themselves decorated as rigid bodies,
149  //! as model particle indexes
151  static ParticleIndexes empty;
152  if (get_model()->get_has_attribute(
153  internal::rigid_body_data().body_members_, get_particle_index())) {
154  return get_model()->get_attribute(
155  internal::rigid_body_data().body_members_, get_particle_index());
156  } else {
157  return empty;
158  }
159  }
160 
161  //! Get the particle indexes of any member of this rigid body, regardless
162  //! of whether it is itself a rigid body or not
164  return get_member_particle_indexes() + get_body_member_particle_indexes();
165  }
166 
168 
169  /**
170  Create a rigid body for pi with the particle indexes ps as its members.
171  The coordinates of pi are set to the center of mass of ps and the rotation
172  of its reference frame is based on the diagonalized inertia tensor of ps.
173 
174  @note If size(ps)=1, then its reference frame is copied if it is a
175  rigid body, or its rotation is set to identity if it is not
176  a rigid body.
177  */
179 
180  /**
181  Create a rigid body with the passed reference frame as its initial
182  position.
183  */
185 
186  //! Make the rigid body no longer rigid.
187  /** If this rigid body has been added as a member of another rigid body,
188  it must be removed first. */
189  static void teardown_particle(RigidBody rb);
190 
191  IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(RigidBody);
192  ~RigidBody();
193 
194  //! Return true if the particle is a rigid body
195  static bool get_is_setup(Model *m, ParticleIndex pi) {
196  return internal::get_has_required_attributes_for_body(m, pi);
197  }
198 
199  // SWIG doesn't support using, so the method is wrapped
200  //! Get the coordinates of the particle
201  //! (= translation from local to global rigid body coordinates)
203 
204  //! returns the rotation of the particle
205  //! (= rotation from local to global rigid body orientation)
207  return get_reference_frame().get_transformation_to().get_rotation();
208  }
209 
210  //! Get the reference frame of this rigid body, which enables
211  //! transformation between the local rigid body coordinates
212  //! global coordinates
215  get_model()->get_attribute(internal::rigid_body_data().quaternion_,
217  IMP_USAGE_CHECK_FLOAT_EQUAL(v.get_squared_magnitude(), 1,
218  "Rotation is not a unit vector: " << v);
219  /*if (v.get_squared_magnitude() > 0){
220  v = v.get_unit_vector();
221  } else {
222  v = algebra::VectorD<4>(1,0,0,0);
223  }*/
224  bool assume_normalized = true;
225  IMP::algebra::Rotation3D rot(v, assume_normalized);
228  }
229 
230  //! Set the current reference frame
231  /** All members of the rigid body will have their coordinates updated
232  immediately.
233  \see IMP::core::transform(RigidBody,const algebra::Transformation3D&)
234  \see set_reference_frame_lazy()
235  */
236  void set_reference_frame(const IMP::algebra::ReferenceFrame3D &tr);
237 
238  //! Change the reference, delay updating the members until evaluate
239  /** \see set_reference_frame()
240  */
241  inline void set_reference_frame_lazy
243  {
246  get_model()->set_attribute(internal::rigid_body_data().quaternion_,
247  get_particle_index(), v);
249  }
250 
251 #ifndef SWIG
252 #ifndef IMP_DOXYGEN
253  //! 'expert' method for setting the reference more quickly
254  //! use at own risk
255  inline void set_rotation_lazy_using_internal_tables
256  (const IMP::algebra::Rotation3D &rot,
257  IMP::algebra::Vector4D* quaternion_table)
258  {
260  rot.get_quaternion();
261  int pi=get_particle_index().get_index();
262  quaternion_table[pi] = v;
263  }
264 
265  //! 'expert' method for setting the reference more quickly
266  //! use at own risk
267  inline void apply_rotation_lazy_using_internal_tables
268  (const IMP::algebra::Rotation3D &rot,
269  IMP::algebra::Vector4D* quaternion_table)
270  {
271  int pi=get_particle_index().get_index();
273  ( quaternion_table[pi][0],
274  quaternion_table[pi][1],
275  quaternion_table[pi][2],
276  quaternion_table[pi][3] );
278  (cur_rot*rot).get_quaternion();;
279  quaternion_table[pi] = v;
280  }
281 
282 #endif // IMP_DOXYGEN
283 #endif // SWIG
284 
285 
286 
287 
288  /** Update the reference frame of the rigid body based on aligning
289  the current global coordinates of the passed rigid body members
290  onto their old local coordinates. Non-passed members are ignored.
291 
292  This method is useful for updating the rigid body after new
293  global coordinates were loaded for the members. The members are
294  passed explicitly since, typically, some are desired to just
295  move along with the newly loaded rigid body.
296 
297  \note This requires at least three members that are not colinear
298  to work.
299  */
300  void set_reference_frame_from_members(const ParticleIndexes &members);
301 
302  //! Pull back global adjoints from members.
303  /** Adjoints (reverse-mode sensitivities) are partial derivatives of the
304  score with respect to intermediate values in the scoring function
305  computation, such as the global coordinates of a bead within a rigid
306  body or the global reference frame of a nested rigid body.
307 
308  This function pulls back (back-propagates) global adjoints and local
309  torque on all members to the global rotation, global coordinates, and
310  local torque on this rigid body and the internal coordinates and
311  rotation of any non-rigid members.
312 
313  This is called by an internal score state after scoring function
314  evaluation and is not meant to be called by the user.
315  */
316  void pull_back_members_adjoints(DerivativeAccumulator &da);
317 
318  //! Pull back global adjoints from member that is a point.
319  /**
320  @param pi index of member particle
321  @param da accumulator for the adjoints
322  */
323  void pull_back_member_adjoints(ParticleIndex pi,
324  DerivativeAccumulator &da);
325 
326 #ifndef SWIG
327  /** Same as above, but uses fewer allocations.
328 
329  @param pi index of member particle
330  @param T transformation from this body's local coordinates to global
331  @param x local coordinates of the member
332  @param Dy adjoint on the member's global coordinates
333  @param Dx adjoint on the member's local coordinates
334  @param DT adjoint on the transformation
335  @param xtorque torque contribution from Dy in local coordinates
336  @param da accumulator for the adjoints
337  */
338  void pull_back_member_adjoints(ParticleIndex pi,
339  const algebra::Transformation3D &T,
341  algebra::Vector3D &Dy,
342  algebra::Vector3D &Dx,
343  algebra::Transformation3DAdjoint &DT,
344  algebra::Vector3D &xtorque,
345  DerivativeAccumulator &da);
346 #endif
347 
348  //! Pull back global adjoints from member that is also a rigid body.
349  /**
350  @param pi index of member particle
351  @param da accumulator for the adjoints
352  */
353  void pull_back_body_member_adjoints(ParticleIndex pi,
354  DerivativeAccumulator &da);
355 
356 #ifndef SWIG
357  /** Same as above, but uses fewer allocations.
358 
359  @param pi index of member particle
360  @param TA transformation from this body's local coordinates to global
361  @param TB transformation from member's local coordinates to this
362  body's local coordinates
363  @param DTC adjoint on composition of TA and TB, which is the
364  transformation from the member's local coordinates to
365  global
366  @param DTA adjoint on TA
367  @param DTB adjoint on TB
368  @param betatorque torque contribution from DTC in local coordinates at
369  beta, the position of the member in local coordinates.
370  @param da accumulator for the adjoints
371  */
372  void pull_back_body_member_adjoints(ParticleIndex pi,
373  const algebra::Transformation3D &TA,
374  algebra::Transformation3D &TB,
375  algebra::Transformation3DAdjoint &DTC,
376  algebra::Transformation3DAdjoint &DTA,
377  algebra::Transformation3DAdjoint &DTB,
378  algebra::Vector3D &betatorque,
379  DerivativeAccumulator &da);
380 #endif
381 
382  /** Add to quaternion derivative of this rigid body
383  Note that this method does not update the torque.
384 
385  @param qderiv Derivative wrt to quaternion taking local coordinates to
386  global.
387  @param da Object for accumulating derivatives
388  */
389  inline void add_to_rotational_derivatives(const algebra::Vector4D &qderiv,
390  DerivativeAccumulator &da);
391 
392  /** Add torque to derivative table of this rigid body
393  Note that this method does not update the quaternion derivatives, so should
394  be used by optimizers that rely on torque only (e.g. BrownianDynamics)
395 
396  @param torque_local Torque vector in local reference frame,
397  in units of kCal/Mol/Radian
398  @param da Object for accumulating derivatives
399  */
400  inline void add_to_torque(const algebra::Vector3D &torque_local,
401  DerivativeAccumulator &da);
402 
403 
404  /** The units are kCal/Mol/Radian */
406  return get_model()->get_derivative(
407  internal::rigid_body_data().torque_, get_particle_index());
408  }
409 
410 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
411  //! expert method for fast const-access to internal torque table
412  static algebra::Vector3D const* access_torque_data(IMP::Model const* m)
413  {
414  Vector3DDerivKey k = internal::rigid_body_data().torque_;
415  return m->access_derivative_data(k);
416  }
417 
418  //! expert method for fast access to internal torque table
419  static algebra::Vector3D *access_torque_data(IMP::Model *m)
420  {
421  Vector3DDerivKey k = internal::rigid_body_data().torque_;
422  return m->access_derivative_data(k);
423  }
424 
425  //! expert method for fast const-access to internal quaternion table
426  static algebra::Vector4D const* access_quaternion_data(IMP::Model const* m)
427  {
428  Vector4DDerivKey k = internal::rigid_body_data().quaternion_;
429  return m->::IMP::internal::Vector4DDerivAttributeTable::access_attribute_data(k);
430  }
431 
432  //! expert method for fast access to internal quaternion table
433  static algebra::Vector4D *access_quaternion_data(IMP::Model *m)
434  {
435  Vector4DDerivKey k = internal::rigid_body_data().quaternion_;
436  return m->::IMP::internal::Vector4DDerivAttributeTable::access_attribute_data(k);
437  }
438 
439 
440 #endif
441 
442  //! Returns true if the rigid body coordinates are flagged as
443  //! optimized for Optimizer objects
444  bool get_coordinates_are_optimized() const;
445 
446  //! Set whether the rigid body coordinates are flagged as optimized
447  //! for Optimizer objects
448  void set_coordinates_are_optimized(bool tf);
449 
450  //! Normalize the quaternion
451  void normalize_rotation();
452 
453  //! Update the global coordinates of the members based on
454  //! their local coordinates and this rigid body's reference frame
455  void update_members();
456 
457  //! Get the derivatives of the quaternion
458  algebra::VectorD<4> get_rotational_derivatives() const;
459 
460 #ifndef IMP_DOXYGEN
461  unsigned int get_number_of_members() const {
462  return get_body_member_particle_indexes().size() +
463  get_member_particle_indexes().size();
464  }
465 
466  RigidBodyMember get_member(unsigned int i) const;
467 #endif
468  //! Add a proper member that moves rigidly with this rigid body,
469  //! properly handling rigid bodies and XYZ particles.
470  /**
471  Add p to the list of members. If p is a valid RigidBody, it is added
472  as a rigid body member, otherwise it is added as a point member
473  (for which the rotation is not tracked). By default, p is considered
474  a strictly rigid member, in that its local coordinates are not expected
475  to change independently.
476 
477  The radius of the rigid body is updated to reflect the new member.
478 
479  \see add_non_rigid_member
480  */
481  void add_member(ParticleIndexAdaptor p);
482 
483  /** Add a non-rigid member, for which internal coordinates may change
484  independently.
485 
486  @note Currently RigidBody non-rigid members are not handled properly.
487  */
488  void add_non_rigid_member(ParticleIndexAdaptor p);
489 
490  /** Set whether a particular member is flagged as a rigid member
491  or as a non-rigid member. This affects the way the rigid body
492  updates the coordinates and / or reference frame of its members.
493 
494  It is also permissible to modify the internal coordinates of
495  non-rigid members during sampling, e.g. using IMP::core::BallMover.
496  Rigid members, on the other hand, are assumed to have fixed
497  internal coordinates.
498 
499  The radius of the rigid body is updated to reflect this change.
500  */
501  void set_is_rigid_member(ParticleIndex pi, bool tf);
502 
503  //! Remove the member from this rigid body.
504  /** The member can be either a rigid body member or a point
505  member, either rigid or non-rigid.
506 
507  The radius of the rigid body is updated to reflect the removed member.
508 
509  \throw UsageException if the given particle is not a member of this body.
510  */
511  void remove_member(ParticleIndexAdaptor p);
512 };
513 
514 #ifndef IMP_DOXYGEN
515 // inline implementation
516 void RigidBody::add_to_rotational_derivatives(const algebra::Vector4D &qderiv,
517  DerivativeAccumulator &da) {
518  get_model()->add_to_derivative(internal::rigid_body_data().quaternion_,
519  get_particle_index(), qderiv, da);
520 }
521 
522 
523 // inline implementation
524 void RigidBody::add_to_torque(const algebra::Vector3D &torque_local,
525  DerivativeAccumulator &da) {
526  get_model()->add_to_derivative(internal::rigid_body_data().torque_,
527  get_particle_index(), torque_local, da);
528 }
529 
530 #endif
531 
532 
533 /** It is often useful to store precalculated properties of the rigid body
534  for later use. These need to be cleared out when the rigid body changes.
535  To make sure this happens, register the key here.
536 */
537 void IMPCOREEXPORT add_rigid_body_cache_key(ObjectKey k);
538 
539 //! A member of a rigid body, it has internal (local) coordinates
540 class IMPCOREEXPORT RigidBodyMember : public XYZ {
542 
543  RigidBody get_rigid_body() const;
544 
545  //! Return the internal (local) coordinates of this member
546  /** These coordinates are relative to the reference frame of the
547  rigid body that owns it
548  */
550  return get_model()->get_internal_coordinates(get_particle_index());
551  }
552 
553  //! set the internal (local) coordinates for this member
555  get_model()->get_internal_coordinates(get_particle_index()) = v;
556  get_rigid_body().get_model()->clear_particle_caches(get_particle_index());
557  }
558 
559  //! Set the internal (local) coordinates of this member,
560  //! assuming it is a rigid body itself
561  /** Set the internal (local) coordinates of this rigid body
562  relative to the reference frame of the rigid body that owns it
563  */
566  get_model()->get_has_attribute(
567  internal::rigid_body_data().lquaternion_, get_particle_index()),
568  "Can only set the internal transformation if member is"
569  << " a rigid body itself.");
570  set_internal_coordinates(v.get_translation());
571 
572  get_model()->set_attribute(internal::rigid_body_data().lquaternion_,
575  get_rigid_body().get_model()->clear_particle_caches(get_particle_index());
576  }
577 
578  //! Return the internal (local) coordinates of this member,
579  //! assuming it is a rigid body itself
580  /** Return the internal (local) coordinates of this rigid body
581  relative to the reference frame of the rigid body that owns it
582  */
585  get_model()->get_has_attribute(
586  internal::rigid_body_data().lquaternion_, get_particle_index()),
587  "Can only get the internal transformation if member is a "
588  << "rigid body itself.");
589  algebra::Vector3D tr =
590  get_model()->get_internal_coordinates(get_particle_index());
592  get_model()->get_attribute(internal::rigid_body_data().lquaternion_,
593  get_particle_index()), true);
594  return algebra::Transformation3D(rot, tr);
595  }
596 
597  ~RigidBodyMember();
598  //! sets the global coordinates of this member using XYZ::set_coordinates()
599  // this is here since SWIG doesn't like "using" statements
600  void set_coordinates(const algebra::Vector3D &center) {
601  XYZ::set_coordinates(center);
602  }
603 
604 #ifndef IMP_DOXYGEN
605  //! Set the global coordinates from the internal coordinates,
606  //! using tr as a reference frame
608  set_coordinates(tr.get_transformed(get_internal_coordinates()));
609  }
610 #endif
611  IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(RigidBodyMember);
612 
613  //! return true if it is a rigid member
615  return internal::get_has_required_attributes_for_member(m, p);
616  }
617 
618  static FloatKeys get_internal_coordinate_keys() {
619  return internal::rigid_body_data().child_keys_;
620  }
621 
622  static Vector4DDerivKey get_internal_rotation_key() {
623  return internal::rigid_body_data().lquaternion_;
624  }
625 };
626 
627 //! A decorator for a particle that is part of a rigid body, and is
628 //! actually rigid
629 /**
630  RigidMember particles, as opposed to NonRigidMember particles, are
631  not expected to change their internal (local) coordinates or
632  reference frames, and their global coordinates are expected to
633  change only through setting the coordinates (or reference frame) of
634  the rigid body that owns them.
635 
636  \see RigidBody
637  */
638 class IMPCOREEXPORT RigidMember : public RigidBodyMember {
639  public:
641 
642  IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(RigidMember);
643  ~RigidMember();
644 
645  //! return true if it is a rigid member
647  return internal::get_has_required_attributes_for_rigid_member(m, p);
648  }
649 };
650 
651 //! A decorator for a particle that is part of a rigid body but not rigid
652 /** NonRigidMembers, like RigidMembers, have internal coordinates and move
653  along with the rigid body. However, it is expected that their internal
654  coordinates will change, and so they are not part of structures that
655  assume rigidity.
656 
657  \see RigidBody
658  */
659 class IMPCOREEXPORT NonRigidMember : public RigidBodyMember {
660  public:
662  IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(NonRigidMember);
663  ~NonRigidMember();
664 
665  //! return true if it is a rigid member
666  static bool get_is_setup(Model *m, ParticleIndex p) {
667  return internal::get_has_required_attributes_for_non_member(m, p);
668  }
669 
670  //! Add to derivatives of local coordinates.
671  /** @param deriv_parent The derivative vector in local coordinates of the
672  parent rigid body.
673  @param da Accumulates the derivative over the local translation.
674  */
676  DerivativeAccumulator &da) {
677  for (unsigned int i = 0; i < 3; ++i) {
678  get_model()->add_to_derivative(get_internal_coordinate_keys()[i],
679  get_particle_index(), deriv_parent[i], da);
680  }
681  }
682 
683  /** Add to internal quaternion derivatives of this non-rigid body
684 
685  @param qderiv Derivative wrt to quaternion taking local coordinates to
686  parent.
687  @param da Object for accumulating derivatives
688  */
690  DerivativeAccumulator &da) {
692  get_model()->get_has_attribute(
693  get_internal_rotation_key(), get_particle_index()),
694  "Can only set derivatives of internal rotation if member is a "
695  << "rigid body itself.");
696  get_model()->add_to_derivative(get_internal_rotation_key(),
697  get_particle_index(), qderiv, da);
698  }
699 
700 
701  //! Get derivatives wrt translation component of internal transformation.
703  algebra::Vector3D ret;
704  for (unsigned int i = 0; i < 3; ++i) {
705  ret[i] = get_model()->get_derivative(
706  get_internal_coordinate_keys()[i], get_particle_index());
707  }
708  return ret;
709  }
710 
711  //! Get derivatives wrt quaternion component of internal transformation.
713  return get_model()->get_derivative(
714  get_internal_rotation_key(), get_particle_index());
715  }
716 };
717 
718 #ifndef IMP_DOXYGEN
719 
720 class IMPCOREEXPORT RigidMembersRefiner : public Refiner {
721  public:
722  RigidMembersRefiner(std::string name = "RigidMembersRefiner%d")
723  : Refiner(name) {}
724  virtual bool get_can_refine(Particle *) const override;
725 #ifndef SWIG
726  using Refiner::get_refined;
727 #endif
728  virtual const ParticlesTemp get_refined(Particle *) const
729  override;
731  Model *m, const ParticleIndexes &pis) const override;
732  IMP_OBJECT_METHODS(RigidMembersRefiner);
733 };
734 
735 namespace internal {
736 IMPCOREEXPORT RigidMembersRefiner *get_rigid_members_refiner();
737 }
738 #endif
739 
740 //! Transform a rigid body
741 /** The transformation is applied current conformation of the rigid
742  body, as opposed to replacing the current conformation, as in
743  RigidBody::set_reference_frame().
744 
745  \see RigidBody
746  \see algebra::Transformation3D
747 */
748 inline void transform(RigidBody a, const algebra::Transformation3D &tr) {
750 }
751 
752 /** Compute the rigid body reference frame given a set of input particles.
753  */
754 IMPCOREEXPORT algebra::ReferenceFrame3D get_initial_reference_frame(
755  Model *m, const ParticleIndexes &pis);
756 
757 inline algebra::ReferenceFrame3D get_initial_reference_frame(
758  const ParticlesTemp &ps) {
759  if (ps.empty()) {
760  return algebra::ReferenceFrame3D();
761  }
762  return get_initial_reference_frame(ps[0]->get_model(),
763  get_indexes(ps));
764 }
765 
766 /** Create a set of rigid bodies that are bound together for efficiency.
767  These rigid bodies cannot nest or have other dependencies among them.
768 
769  All rigid bodies have the default reference frame.
770 
771  \note Do not use this with DOMINO as all the rigid bodies use the same
772  ScoreState and so will be considered inter-dependent.
773 */
774 IMPCOREEXPORT ParticlesTemp create_rigid_bodies(Model *m,
775  unsigned int n,
776  bool no_members =
777  false);
778 
779 IMP_DECORATORS_DEF(RigidMember, RigidMembers);
780 IMP_DECORATORS(RigidBody, RigidBodies, XYZs);
781 
782 /** Show the rigid body hierarchy rooted at passed body. */
783 IMPCOREEXPORT void show_rigid_body_hierarchy(RigidBody rb,
784  TextOutput out =
785  TextOutput(std::cout));
786 
787 //! Return the index of the outer-most rigid body containing the member.
788 /** Use this to, for example, group particles into rigid bodies. */
789 IMPCOREEXPORT ParticleIndex get_root_rigid_body(RigidMember m);
790 
791 IMPCORE_END_NAMESPACE
792 
793 #endif /* IMPCORE_RIGID_BODIES_H */
void set_internal_coordinates(const algebra::Vector3D &v) const
set the internal (local) coordinates for this member
Definition: rigid_bodies.h:554
Simple 3D transformation class.
ParticleIndex get_particle_index() const
Returns the particle index decorated by this decorator.
Definition: Decorator.h:211
algebra::Vector3D get_internal_derivatives() const
Get derivatives wrt translation component of internal transformation.
Definition: rigid_bodies.h:702
A Cartesian vector in D-dimensions.
Definition: VectorD.h:38
algebra::Vector4D get_internal_rotational_derivatives() const
Get derivatives wrt quaternion component of internal transformation.
Definition: rigid_bodies.h:712
static Vector4DDerivKey get_rotation_key()
Get key for rotation quaternion.
Definition: rigid_bodies.h:131
A member of a rigid body, it has internal (local) coordinates.
Definition: rigid_bodies.h:540
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:202
IMP::algebra::Rotation3D get_rotation() const
Definition: rigid_bodies.h:206
#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
Take Decorator, Particle or ParticleIndex.
Model * get_model() const
Returns the Model containing the particle.
Definition: Decorator.h:214
void add_to_internal_rotational_derivatives(const algebra::Vector4D &qderiv, DerivativeAccumulator &da)
Definition: rigid_bodies.h:689
ParticlesTemp create_rigid_bodies(Model *m, unsigned int n, bool no_members=false)
Index< ParticleIndexTag > ParticleIndex
Definition: base_types.h:194
Key< 19 > Vector4DDerivKey
The type used to identify 4D vector attributes&derivatives in the Particles.
Definition: base_types.h:114
bool get_coordinates_are_optimized() const
Get whether the coordinates are optimized.
Definition: XYZ.h:89
void add_rigid_body_cache_key(ObjectKey k)
VectorD< 4 > Vector4D
Definition: VectorD.h:411
A more IMP-like version of the std::vector.
Definition: Vector.h:50
const Vector4D & get_quaternion() const
Return the quaternion so that it can be stored.
Definition: Rotation3D.h:245
Simple XYZ decorator.
A reference frame in 3D.
void show_rigid_body_hierarchy(RigidBody rb, TextOutput out=TextOutput(std::cout))
Take Decorator, Particle or ParticleIndex.
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:122
Class for storing model, its restraints, constraints, and particles.
Definition: Model.h:86
const Rotation3D & get_rotation() const
Return the rotation associated with this transformation.
algebra::Vector3D get_torque() const
Definition: rigid_bodies.h:405
static bool get_is_setup(Model *m, ParticleIndexAdaptor p)
return true if it is a rigid member
Definition: rigid_bodies.h:646
virtual bool get_can_refine(Particle *) const
Return true if this refiner can refine that particle.
Definition: Refiner.h:60
void set_reference_frame(const IMP::algebra::ReferenceFrame3D &tr)
Set the current reference frame.
Refine a particle into a list of particles.
VectorD< 3 > Vector3D
Definition: VectorD.h:407
void set_coordinates(const algebra::Vector3D &v)
set all coordinates from a vector
Definition: XYZ.h:62
const Transformation3D & get_transformation_to() const
Return transformation from local to global coordinates.
static bool get_is_setup(Model *m, ParticleIndex pi)
Return true if the particle is a rigid body.
Definition: rigid_bodies.h:195
const ParticleIndexes & get_member_particle_indexes() const
Definition: rigid_bodies.h:137
static bool get_is_setup(Model *m, ParticleIndexAdaptor p)
return true if it is a rigid member
Definition: rigid_bodies.h:614
virtual ModelObjectsTemp do_get_inputs(Model *m, const ParticleIndexes &pis) const =0
Overload this method to specify the inputs.
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
Simple 3D vector class.
void add_to_internal_derivatives(const algebra::Vector3D &deriv_parent, DerivativeAccumulator &da)
Add to derivatives of local coordinates.
Definition: rigid_bodies.h:675
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:659
Simple 3D rotation class.
void set_internal_transformation(const algebra::Transformation3D &v)
Definition: rigid_bodies.h:564
Key< 4 > ObjectKey
The type used to identify an Object attribute.
Definition: base_types.h:48
3D rotation class.
Definition: Rotation3D.h:52
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:600
#define IMP_DECORATOR_METHODS(Name, Parent)
Abstract class to implement hierarchical methods.
Definition: Refiner.h:36
Class to handle individual particles of a Model object.
Definition: Particle.h:45
#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:748
A reference frame in 3D.
ParticleIndexes get_member_indexes() const
Definition: rigid_bodies.h:163
DensityMap * get_transformed(const DensityMap *input, const algebra::Transformation3D &tr, double threshold)
Return a new density map containing a rotated version of the old one.
const ParticleIndexes & get_body_member_particle_indexes() const
Definition: rigid_bodies.h:150
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:583
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)
Get the indexes from a list of particles.
static bool get_is_setup(Model *m, ParticleIndex p)
return true if it is a rigid member
Definition: rigid_bodies.h:666
Class for adding derivatives from restraints to the model.
const algebra::Vector3D & get_internal_coordinates() const
Return the internal (local) coordinates of this member.
Definition: rigid_bodies.h:549
IMP::algebra::ReferenceFrame3D get_reference_frame() const
Definition: rigid_bodies.h:213