IMP logo
IMP Reference Guide  develop.eb1b99edaa,2026/06/22
The Integrative Modeling Platform
Particle.h
Go to the documentation of this file.
1 /**
2  * \file IMP/Particle.h
3  * \brief Classes to handle individual model particles.
4  * (Note that implementation of inline functions is in internal)
5  *
6  * Copyright 2007-2023 IMP Inventors. All rights reserved.
7  *
8  */
9 
10 #ifndef IMPKERNEL_PARTICLE_H
11 #define IMPKERNEL_PARTICLE_H
12 
13 #include <IMP/kernel_config.h>
14 #include "base_types.h"
15 #include "DerivativeAccumulator.h"
16 #include "Model.h"
17 #include "ModelObject.h"
18 #include "particle_index.h"
19 #include "Key.h"
20 #include "internal/AttributeTable.h"
21 #include <IMP/Object.h>
22 #include <IMP/utility.h>
23 #include <IMP/Array.h>
24 #include <IMP/Pointer.h>
25 #include <IMP/check_macros.h>
26 #include <IMP/Vector3D.h>
27 #include <utility>
28 #include <cereal/access.hpp>
29 #include <cereal/types/base_class.hpp>
30 
31 IMPKERNEL_BEGIN_NAMESPACE
32 
33 //class Model;
34 class Changed;
35 class SaveOptimizeds;
36 
37 //! Class to handle individual particles of a Model object.
38 /** A particle is a lightweight object that serves as a place holder for the
39  particle index in a given Model object. The Model object itself stores
40  the particle attributes of various types:
41  Float, Int, String, Object, and WeakObject, and any data concerning the
42  optimization of these particles by Optimizer and Simulator classes.
43 
44 */
45 class IMPKERNELEXPORT Particle : public ModelObject {
46  private:
47 // doxygen produces funny docs for these things
48 #ifndef IMP_DOXYGEN
49  friend class Model;
50 #endif
51  ParticleIndex id_;
53 
54  public:
55  //! Construct a particle and add it to the Model
56  Particle(Model *m, std::string name);
57 
58  //! Construct a particle and add it to the Model
59  Particle(Model *m);
60 
61 #ifndef IMP_DOXYGEN
62  Particle() {}
63 
64 #define IMP_KERNEL_PARTICLE_ATTRIBUTE_TYPE_DECL(UCName, lcname, Value) \
65  inline void add_attribute(UCName##Key name, Value initial_value); \
66  inline void remove_attribute(UCName##Key name); \
67  inline bool has_attribute(UCName##Key name) const; \
68  inline Value get_value(UCName##Key name) const; \
69  inline void set_value(UCName##Key name, Value value); \
70  inline void add_cache_attribute(UCName##Key name, Value value); \
71  inline UCName##Keys get_##lcname##_keys() const
72 
73  IMP_KERNEL_PARTICLE_ATTRIBUTE_TYPE_DECL(Float, float, Float);
74  IMP_KERNEL_PARTICLE_ATTRIBUTE_TYPE_DECL(Floats, floats, Floats);
75 #ifndef SWIG
76  IMP_KERNEL_PARTICLE_ATTRIBUTE_TYPE_DECL(Vector3D, vector3d,
77  Vector3D);
78 #endif
79  IMP_KERNEL_PARTICLE_ATTRIBUTE_TYPE_DECL(Int, int, Int);
80  IMP_KERNEL_PARTICLE_ATTRIBUTE_TYPE_DECL(Ints, ints, Ints);
81  IMP_KERNEL_PARTICLE_ATTRIBUTE_TYPE_DECL(String, string, String);
82  IMP_KERNEL_PARTICLE_ATTRIBUTE_TYPE_DECL(Object, object, Object *);
83  IMP_KERNEL_PARTICLE_ATTRIBUTE_TYPE_DECL(WeakObject, weak_object, Object *);
84 
85 #define IMP_KERNEL_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DECL(UCName, lcname, Value) \
86  inline void add_attribute(UCName##Key name, Value initial_value); \
87  inline void remove_attribute(UCName##Key name); \
88  inline bool has_attribute(UCName##Key name) const; \
89  inline Value get_value(UCName##Key name) const; \
90  inline void set_value(UCName##Key name, Value value)
91 
92  IMP_KERNEL_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DECL(SparseString, string, String);
93  IMP_KERNEL_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DECL(SparseInt, int, Int);
94  IMP_KERNEL_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DECL(SparseFloat, float, Float);
95  IMP_KERNEL_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DECL(SparseParticleIndex,
96  particle_index, ParticleIndex);
97 
98  /** @name Float Attributes
99  Float attributes can be optimized, meaning an Optimizer class is
100  allowed to change their value in order to improve the score.
101  As a result, there are a number of specialized methods to manipulate
102  the value of float attributes.
103 
104  All distances are assumed to be in angstroms
105  and derivatives in kcal/mol/angstrom. This is not enforced.
106  */
107  /*@{*/
108  /** add attribute name to the attributes table of this particle
109 
110  @param name attribute key
111  @param initial_value initial value for the attribute
112  @param optimized whether to flag this attribute as optimized
113  */
114  void add_attribute(FloatKey name, const Float initial_value, bool optimized);
115 
116  /** Adds value to the derivatives table of the
117  specified particle attribute
118 
119  @param key the attribute key whose derivative is updated
120  @param value the derivative value to be added
121  @param da a derivative accumulator for reweighting derivatives
122  */
123  void add_to_derivative(FloatKey key, Float value,
124  const DerivativeAccumulator &da);
125 
126  void add_to_derivative(Vector3DDerivKey key, const Vector3D &value,
127  const DerivativeAccumulator &da);
128 
129  void add_to_derivative(Vector4DDerivKey key, const Vector4D &value,
130  const DerivativeAccumulator &da);
131 
132  void set_is_optimized(FloatKey k, bool tf);
133  void set_is_optimized(Vector3DDerivKey k, bool tf);
134  void set_is_optimized(Vector4DDerivKey k, bool tf);
135 
136  //! returns true if key k is marked by model as optimized
137  inline bool get_is_optimized(FloatKey k) const;
138  inline bool get_is_optimized(Vector3DDerivKey k) const;
139  inline bool get_is_optimized(Vector4DDerivKey k) const;
140 
141  //! returns the derivative of the specified particle attribute
142  inline Float get_derivative(FloatKey k) const;
143 
144  //! returns the derivative of the specified particle attribute
145  inline Vector3D get_derivative(Vector3DDerivKey k) const;
146 
147  //! returns the derivative of the specified particle attribute
148  inline Vector4D get_derivative(Vector4DDerivKey k) const;
149  /** @} */
150 
151  /** \name Particle attributes
152  @{
153  */
154  void add_attribute(ParticleIndexKey k, Particle *v);
155  bool has_attribute(ParticleIndexKey k);
156  void set_value(ParticleIndexKey k, Particle *v);
157  inline Particle *get_value(ParticleIndexKey k) const;
158  void remove_attribute(ParticleIndexKey k);
159  ParticleIndexKeys get_particle_keys() const;
160  /** @} */
161 
162  //! Print out all the attributes
163  void show(std::ostream &out = std::cout) const;
164 
165  //! Get whether the particle is active.
166  /** Restraints referencing the particle are only evaluated for 'active'
167  particles.
168  \return true it the particle is active.
169  */
170  bool get_is_active() const;
171 #endif
172 
173  //! returns the particle index of this particle in its model
174  ParticleIndex get_index() const;
175 
176 #if !defined(IMP_DOXYGEN)
177  void clear_caches() override;
178 #endif
179  protected:
180  virtual ModelObjectsTemp do_get_inputs() const override final {
181  return ModelObjectsTemp();
182  }
183  virtual ModelObjectsTemp do_get_outputs() const override final {
184  return ModelObjectsTemp();
185  }
186 
187  private:
188  friend class cereal::access;
189  template<class Archive> void serialize(Archive &ar) {
190  ar(cereal::base_class<ModelObject>(this), id_);
191  }
192 };
193 
194 // for swig
195 class Decorator;
196 
197 /** An adaptor that enable to implicitly pass particles to other
198  functions or constructors by passing either the particle itself
199  (in Python), a decorator to the particle, or a raw/smart IMP
200  pointer to the particle (in C++)
201 */
202 class IMPKERNELEXPORT ParticleAdaptor : public InputAdaptor {
203  Model *m_;
204  ParticleIndex pi_;
205 
206  public:
207  ParticleAdaptor() : m_(nullptr), pi_() {}
208  //! convert p to itself
209  ParticleAdaptor(Particle *p) : m_(p->get_model()), pi_(p->get_index()) {}
210  //! convert d to the particle it decorates
211  ParticleAdaptor(const Decorator &d);
212 #ifndef SWIG
214  : m_(p->get_model()), pi_(p->get_index()) {}
215  ParticleAdaptor(IMP::WeakPointer<Particle> p)
216  : m_(p->get_model()), pi_(p->get_index()) {}
217  ParticleAdaptor(IMP::PointerMember<Particle> p)
218  : m_(p->get_model()), pi_(p->get_index()) {}
219 #endif
220  Model *get_model() const { return m_; }
221  ParticleIndex get_particle_index() const { return pi_; }
222 };
223 
224 
225 /****************** Inline methods ***************/
226 
227 #ifndef IMP_DOXYGEN
228 
229 bool Particle::get_is_optimized(FloatKey k) const {
230  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used.");
231  return get_model()->get_is_optimized(k, id_);
232 }
233 
234 bool Particle::get_is_optimized(Vector3DDerivKey k) const {
235  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used.");
236  return get_model()->get_is_optimized(k, id_);
237 }
238 
239 bool Particle::get_is_optimized(Vector4DDerivKey k) const {
240  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used.");
241  return get_model()->get_is_optimized(k, id_);
242 }
243 
244 Float Particle::get_derivative(FloatKey k) const {
245  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used.");
246  return get_model()->get_derivative(k, id_);
247 }
248 
249 Vector3D Particle::get_derivative(Vector3DDerivKey k) const {
250  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used.");
251  return get_model()->get_derivative(k, id_);
252 }
253 
254 Vector4D Particle::get_derivative(Vector4DDerivKey k) const {
255  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used.");
256  return get_model()->get_derivative(k, id_);
257 }
258 
259 Particle *Particle::get_value(ParticleIndexKey k) const {
260  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used.");
261  return get_model()->get_particle(get_model()->get_attribute(k, id_));
262 }
263 
264 #define IMP_PARTICLE_ATTRIBUTE_TYPE_DEF(UCName, lcname, Value) \
265  void Particle::add_attribute(UCName##Key name, Value initial_value) { \
266  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
267  get_model()->add_attribute(name, id_, initial_value); \
268  } \
269  void Particle::remove_attribute(UCName##Key name) { \
270  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
271  get_model()->remove_attribute(name, id_); \
272  } \
273  bool Particle::has_attribute(UCName##Key name) const { \
274  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
275  return get_model()->get_has_attribute(name, id_); \
276  } \
277  Value Particle::get_value(UCName##Key name) const { \
278  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
279  return get_model()->get_attribute(name, id_); \
280  } \
281  void Particle::set_value(UCName##Key name, Value value) { \
282  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
283  get_model()->set_attribute(name, id_, value); \
284  } \
285  UCName##Keys Particle::get_##lcname##_keys() const { \
286  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
287  return get_model()->internal::UCName##AttributeTable::get_attribute_keys( \
288  id_); \
289  } \
290  void Particle::add_cache_attribute(UCName##Key name, Value value) { \
291  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
292  return get_model()->add_cache_attribute(name, id_, value); \
293  }
294 
295 IMP_PARTICLE_ATTRIBUTE_TYPE_DEF(Float, float, Float);
296 IMP_PARTICLE_ATTRIBUTE_TYPE_DEF(Floats, floats, Floats);
297 #ifndef SWIG
298 IMP_PARTICLE_ATTRIBUTE_TYPE_DEF(Vector3D, vector3d, Vector3D);
299 #endif
300 IMP_PARTICLE_ATTRIBUTE_TYPE_DEF(Int, int, Int);
301 IMP_PARTICLE_ATTRIBUTE_TYPE_DEF(Ints, ints, Ints);
302 IMP_PARTICLE_ATTRIBUTE_TYPE_DEF(String, string, String);
303 IMP_PARTICLE_ATTRIBUTE_TYPE_DEF(Object, object, Object *);
304 IMP_PARTICLE_ATTRIBUTE_TYPE_DEF(WeakObject, weak_object, Object *);
305 
306 #define IMP_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DEF(UCName, lcname, Value) \
307  void Particle::add_attribute(UCName##Key name, Value initial_value) { \
308  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
309  get_model()->add_attribute(name, id_, initial_value); \
310  } \
311  void Particle::remove_attribute(UCName##Key name) { \
312  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
313  get_model()->remove_attribute(name, id_); \
314  } \
315  bool Particle::has_attribute(UCName##Key name) const { \
316  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
317  return get_model()->get_has_attribute(name, id_); \
318  } \
319  Value Particle::get_value(UCName##Key name) const { \
320  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
321  return get_model()->get_attribute(name, id_); \
322  } \
323  void Particle::set_value(UCName##Key name, Value value) { \
324  IMP_USAGE_CHECK(get_is_active(), "Inactive particle used."); \
325  get_model()->set_attribute(name, id_, value); \
326  }
327 
328 IMP_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DEF(SparseString, string, String);
329 IMP_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DEF(SparseInt, int, Int);
330 IMP_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DEF(SparseFloat, float, Float);
331 IMP_SPARSE_PARTICLE_ATTRIBUTE_TYPE_DEF(SparseParticleIndex, particle_index,
332  ParticleIndex);
333 
334 #endif // DOXYGEN
335 
336 IMPKERNEL_END_NAMESPACE
337 #endif /* IMPKERNEL_PARTICLE_H */
virtual ModelObjectsTemp do_get_outputs() const overridefinal
Definition: Particle.h:183
Basic types used by IMP.
Key< 0 > FloatKey
The type used to identify float attributes in the Particles.
Definition: base_types.h:32
Smart pointer to Object-derived classes that does not refcount.
Definition: WeakPointer.h:77
Functions and adaptors for dealing with particle indexes.
IMP::Vector< Float > Floats
Standard way to pass a bunch of Float values.
Definition: types.h:46
#define IMP_OBJECT_METHODS(Name)
Define the basic things needed by any Object.
Definition: object_macros.h:25
Class for adding derivatives from restraints to the model.
Storage of a model, its restraints, constraints and particles.
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
Keys to cache lookup of attribute strings.
VectorD< 4 > Vector4D
Definition: VectorD.h:411
virtual void clear_caches()
Definition: Object.h:270
Classes to handle static sized arrays of things.
A smart pointer to a reference counted object.
Definition: Pointer.h:87
IMP::Vector< IMP::WeakPointer< ModelObject > > ModelObjectsTemp
Definition: base_types.h:122
Class for storing model, its restraints, constraints, and particles.
Definition: Model.h:86
Key< 17 > Vector3DDerivKey
The type used to identify 3D vector attributes&derivatives in the Particles.
Definition: base_types.h:106
Base class for objects in a Model that depend on other objects.
Definition: ModelObject.h:28
Key< 3 > ParticleIndexKey
The type used to identify a particle attribute in the Particles.
Definition: base_types.h:44
Ints get_index(const ParticlesTemp &particles, const Subset &subset, const Subsets &excluded)
Common base class for heavy weight IMP objects.
Definition: Object.h:111
VectorD< 3 > Vector3D
Definition: VectorD.h:407
A smart pointer to a ref-counted Object that is a class member.
Definition: Pointer.h:143
Various general useful functions for IMP.
Base class for objects in a Model that depend on other objects.
Interface to specialized Particle types (e.g. atoms)
Definition: Decorator.h:119
std::ostream & show(Hierarchy h, std::ostream &out=std::cout)
Print the hierarchy using a given decorator to display each node.
virtual ModelObjectsTemp do_get_inputs() const overridefinal
Definition: Particle.h:180
A nullptr-initialized pointer to an IMP Object.
Helper macros for throwing and handling exceptions.
A shared base class to help in debugging and things.
double Float
Basic floating-point value (could be float, double...)
Definition: types.h:19
Simple 3D vector class.
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
int Int
Basic integer value.
Definition: types.h:34
IMP::Vector< Int > Ints
Standard way to pass a bunch of Int values.
Definition: types.h:48
Convenience class to accept multiple input types.
Definition: InputAdaptor.h:25
std::string String
Basic string value.
Definition: types.h:43
Class for adding derivatives from restraints to the model.
ParticleAdaptor(Particle *p)
convert p to itself
Definition: Particle.h:209