IMP logo
IMP Reference Guide  2.7.0
The Integrative Modeling Platform
KinematicForest.h
Go to the documentation of this file.
1 /**
2  * \file IMP/kinematics/KinematicForest.h
3  * \brief Define and manipulate a kinematic structure over a model.
4  * \authors Dina Schneidman, Barak Raveh
5  *
6  * Copyright 2007-2017 IMP Inventors. All rights reserved.
7  */
8 
9 #ifndef IMPKINEMATICS_KINEMATIC_FOREST_H
10 #define IMPKINEMATICS_KINEMATIC_FOREST_H
11 
12 #include "kinematics_config.h"
13 #include <IMP/Model.h>
15 #include <IMP/kinematics/Joint.h>
17 #include <IMP/Object.h>
18 #include <IMP/Decorator.h>
19 #include <boost/unordered_set.hpp>
20 #include <IMP/exception.h>
21 #include <IMP/Object.h>
22 #include <IMP/check_macros.h>
23 #include <IMP/warning_macros.h>
24 #include <IMP/atom/Hierarchy.h>
25 #include <queue>
26 #include <algorithm>
27 
28 IMPKINEMATICS_BEGIN_NAMESPACE
29 
30 //! Define and manipulate a kinematic structure over a model.
31 /** The kinematic structure is defined as a
32  forest over model particles at a certain hierarchy, such that a
33  directed edge indicates the propagation of changes in internal
34  coordinates (joint values) to values of external (Cartesian)
35  coordinates.
36 
37  \see Joint
38  */
39 class IMPKINEMATICSEXPORT KinematicForest
40  : public Object // or ModelObject?
41  {
42  public:
44 
46 
47  // TODO: think about what foldtree scheme to use (star?),
48  /**
49  Builds a kinematic forest automatically from a hierarchy that
50  contains rigid bodies and adds a ScoreState to the model, to
51  make sure the internal and external coordinates are synced
52  before model updating
53  */
55 
56  /**
57  Adds a kinematic edge between parent and child,
58  using a TransformationJoint between them, and
59  decorating them as KinematicNodes if needed.
60  */
61  // NOTE: must have root on first call
62  // TODO: verify parent_rb is in tree
64  // create joint and associate it with parent and child
65  IMP_NEW(TransformationJoint, joint, (parent, child));
66  add_edge(joint);
67  return joint;
68  }
69 
70  /**
71  Adds a kinematic edge between the joint parent and child
72  rigid bodies, decorating them as KinematicNodes if needed.
73  The joint becomes owned by this KinematicForest, such that
74  changes to the joint are synchronized with the KinematicForest
75 
76  @note it is assumed that neither the joint or the rigid bodies in it
77  were previously added to a kinematic forest (might change in
78  future IMP versions)
79  */
80  void add_edge(Joint* joint);
81  /**
82  adds edges between each pair of consecutive rigid bodies in the list
83  rbs, using default TransformationJoint joints (transforming from one
84  rigid body to the next)
85 
86  @param rbs list of n consecutive rigid bodies
87  */
89  for (int i = 0; i < (int)rbs.size() - 1; i++) {
90  add_edge(rbs[i], rbs[i + 1]);
91  }
92  }
93 
94  //! rebuild tree (same topology but change directionality)
95  void reset_root(IMP::Particle* new_root) {
96  // TODO: implement
98  IMP_UNUSED(new_root);
99  }
100 
101  void update_all_internal_coordinates() {
102  IMP_LOG(VERBOSE, "updating internal coords needed?" << std::endl);
103  if (is_internal_coords_updated_) {
104  return;
105  }
106  IMP_LOG(VERBOSE, "updating!" << std::endl);
107  for (unsigned int i = 0; i < joints_.size(); i++) {
108  joints_[i]->update_joint_from_cartesian_witnesses();
109  }
110  is_internal_coords_updated_ = true;
111  }
112 
113  void update_all_external_coordinates() {
114  if (is_external_coords_updated_) {
115  return;
116  }
117  // tree BFS traversal from roots
118  std::queue<KinematicNode> q;
119  boost::unordered_set<KinematicNode>::iterator it;
120  for (it = roots_.begin(); it != roots_.end(); it++) {
121  q.push(*it);
122  }
123  while (!q.empty()) {
124  KinematicNode n = q.front();
125  q.pop();
126  JointsTemp out_joints = n.get_out_joints();
127  for (unsigned int i = 0; i < out_joints.size(); i++) {
128  Joint* joint_i = out_joints[i];
129  // TODO: add and implement to joint
130  joint_i->update_child_node_reference_frame();
131  q.push(KinematicNode(joint_i->get_child_node()));
132  }
133  }
134  is_external_coords_updated_ = true;
135  }
136 
137  //! return joints sorted by BFS traversal
139  Joints ret;
140  // tree BFS traversal from roots
141  std::queue<KinematicNode> q;
142  boost::unordered_set<KinematicNode>::iterator it;
143  for (it = roots_.begin(); it != roots_.end(); it++) q.push(*it);
144 
145  while (!q.empty()) {
146  KinematicNode n = q.front();
147  q.pop();
148  if (n.get_in_joint() != nullptr) ret.push_back(n.get_in_joint());
149 
150  JointsTemp out_joints = n.get_out_joints();
151  for (unsigned int i = 0; i < out_joints.size(); i++) {
152  Joint* joint_i = out_joints[i];
153  q.push(KinematicNode(joint_i->get_child_node()));
154  }
155  }
156  return ret;
157  }
158 
159  /**
160  notifies the tree that joint (internal) coordinates
161  have changed and therefore external coordinates are not
162  up to date
163  */
165  is_external_coords_updated_ = false;
166  }
167 
168  /**
169  notifies the tree that external Cartesian coordinates
170  have changed and therefore internal (joint) coordinates are not
171  up to date
172  */
174  is_internal_coords_updated_ = false;
175  }
176 
177  /**
178  sets the coordinates of a particle, and makes sure that particles
179  and joints in the tree will return correct external and internal
180  coordinates
181 
182  @param rb a rigid body that was previously added to the tree
183  @param c new coordinates
184  */
186  IMP_USAGE_CHECK(get_is_member(rb),
187  "A KinematicForest can only handle particles "
188  << " that were previously added to it");
189  rb.set_coordinates(c);
190  mark_external_coordinates_changed();
191  }
192 
193  /**
194  */
195  IMP::algebra::Vector3D get_coordinates_safe(IMP::core::RigidBody rb) const {
196  IMP_USAGE_CHECK(get_is_member(rb),
197  "A KinematicForest can only handle particles "
198  << " that were previously added to it");
199  const_cast<KinematicForest*>(this)->update_all_external_coordinates();
200  return rb.get_coordinates();
201  }
202 
203  /**
204  */
205  bool get_is_member(IMP::core::RigidBody rb) const {
206  Particle* p = rb.get_particle();
207  return KinematicNode::get_is_setup(p) &&
208  nodes_.find(KinematicNode(p)) != nodes_.end();
209  }
210 
211  // TODO: do we want to add safe access to rigid body members?
212 
213  /**
214  */
215  IMP::algebra::ReferenceFrame3D get_reference_frame_safe(
216  IMP::core::RigidBody rb) const {
217  IMP_USAGE_CHECK(get_is_member(rb),
218  "A KinematicForest can only handle particles "
219  << " that were previously added to it");
220  const_cast<KinematicForest*>(this)->update_all_external_coordinates();
221  return rb.get_reference_frame();
222  }
223 
224  /**
225  sets the reference frame of a rigid body, and makes sure that
226  particles and joints in the tree will return correct external
227  and internal coordinates when queried through the KinematicForest
228 
229  @param rb a rigid body that was previously added to the tree
230  @param r new reference frame
231  */
234  IMP_USAGE_CHECK(get_is_member(rb),
235  "A KinematicForest can only handle particles "
236  << " that were previously added to it");
237  rb.set_reference_frame(r);
238  mark_external_coordinates_changed();
239  }
240 
241  // TODO: handle derivatives, and safe getting / setting of them
242 
243  private:
244  IMP::Particles get_children(IMP::Particle parent) const;
245 
246  IMP::Particle get_parent(IMP::Particle child) const;
247 
248 #ifndef SWIG
249  friend std::ostream& operator<<(std::ostream& s, const KinematicForest& kt);
250 #endif
251 
252  private:
253  Model* m_;
254 
255  bool is_internal_coords_updated_;
256  bool is_external_coords_updated_;
257 
258  /** the root nodes that serves as spatial anchor to the
259  kinematic trees in the forest */
260  boost::unordered_set<KinematicNode> roots_;
261 
262  /** the set of nodes in the tree */
263  boost::unordered_set<KinematicNode> nodes_;
264 
265  Joints joints_;
266 };
267 
269 
270 IMPKINEMATICS_END_NAMESPACE
271 
272 #endif /* IMPKINEMATICS_KINEMATIC_FOREST_H */
The base class for decorators.
#define IMP_OBJECT_METHODS(Name)
Define the basic things needed by any Object.
Definition: object_macros.h:25
Storage of a model, its restraints, constraints and particles.
Exception definitions and assertions.
A reference frame in 3D.
a kinematic joints between rigid bodies that allows any transformation
#define IMP_NEW(Typename, varname, args)
Declare a ref counted pointer to a new object.
Definition: object_macros.h:64
IMP::Vector< IMP::WeakPointer< Joint > > JointsTemp
Definition: Joint.h:126
void reset_root(IMP::Particle *new_root)
rebuild tree (same topology but change directionality)
Class for storing model, its restraints, constraints, and particles.
Definition: Model.h:72
Decorator for helping deal with a hierarchy of molecules.
void set_reference_frame_safe(IMP::core::RigidBody rb, IMP::algebra::ReferenceFrame3D r)
void add_rigid_bodies_in_chain(IMP::core::RigidBodies rbs)
functionality for defining a kinematic joint between rigid bodies as part of a kinematic tree ...
The standard decorator for manipulating molecular structures.
void set_reference_frame(const IMP::algebra::ReferenceFrame3D &tr)
Set the current reference frame.
Common base class for heavy weight IMP objects.
Definition: Object.h:106
Various general useful macros for IMP.
#define IMP_UNUSED(variable)
void set_coordinates(const algebra::Vector3D &v)
set all coordinates from a vector
Definition: XYZ.h:62
void set_coordinates_safe(IMP::core::RigidBody rb, IMP::algebra::Vector3D c)
functionality for defining nodes on a kinematic chain
Particle * get_particle() const
Returns the particle decorated by this decorator.
Definition: Decorator.h:171
Joints get_ordered_joints() const
return joints sorted by BFS traversal
#define IMP_OBJECTS(Name, PluralName)
Define the types for storing lists of object pointers.
Definition: object_macros.h:44
A rigid body that is connected by a joint to other rigid bodies.
Definition: KinematicNode.h:26
Joint * add_edge(IMP::core::RigidBody parent, IMP::core::RigidBody child)
Exception definitions and assertions.
Base class for joints between rigid bodies in a kinematic tree.
Definition: Joint.h:30
A shared base class to help in debugging and things.
VectorD< 3 > Vector3D
Definition: VectorD.h:395
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_NOT_IMPLEMENTED
Use this to mark that the method is not implemented yet.
Definition: check_macros.h:81
A decorator for a rigid body.
Definition: rigid_bodies.h:75
Define and manipulate a kinematic structure over a model.
IMP::algebra::ReferenceFrame3D get_reference_frame() const
Definition: rigid_bodies.h:191