IMP logo
IMP Reference Guide  2.14.0
The Integrative Modeling Platform
decorator_macros.h
Go to the documentation of this file.
1 /**
2  * \file IMP/decorator_macros.h
3  * \brief Various general useful macros for IMP.
4  *
5  * Copyright 2007-2020 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPKERNEL_DECORATOR_MACROS_H
10 #define IMPKERNEL_DECORATOR_MACROS_H
11 #include <IMP/kernel_config.h>
12 #include "particle_index.h"
13 #include "Particle.h"
14 #include "Decorator.h"
15 #include <IMP/check_macros.h>
16 #include <IMP/log_macros.h>
17 #include <IMP/showable_macros.h>
18 #include <IMP/warning_macros.h>
19 
20 
21 
22 /** Implement the needed methods for a decorator based on
23  - setup_particle()
24  - get_is_setup()
25  methods that you provide.
26 */
27 #define IMP_DECORATOR_METHODS(Name, Parent) \
28  public: \
29  /* Should be private but SWIG accesses it through the
30  comparison
31  macros*/ IMP_NO_DOXYGEN( \
32  typedef Parent ParentDecorator); \
33  Name() : Parent() {} \
34  Name(::IMP::Model *m, ::IMP::ParticleIndex id) \
35  : Parent(m, id) { \
36  IMP_INTERNAL_CHECK( \
37  get_is_setup(m, id), \
38  "Particle " << m->get_particle_name(id) \
39  << " missing required attributes for decorator " \
40  << #Name); \
41  } \
42  explicit Name(const IMP::ParticleAdaptor &d) : Parent(d) { \
43  IMP_INTERNAL_CHECK( \
44  get_is_setup(d.get_model(), d.get_particle_index()), \
45  "Particle " << d.get_model()->get_particle_name( \
46  d.get_particle_index()) \
47  << " missing required attributes for decorator " \
48  << #Name); \
49  } \
50  static bool get_is_setup(const IMP::ParticleAdaptor &p) { \
51  return get_is_setup(p.get_model(), p.get_particle_index()); \
52  } \
53  IMP_SHOWABLE(Name)
54 
55 
56 
57 /** Implement the needed methods for a decorator based on
58  - setup_particle()
59  - get_is_setup()
60  methods that you provide.
61 */
62 #define IMP_DECORATOR_WITH_TRAITS_METHODS(Name, Parent, TraitsType, \
63  traits_name, default_traits) \
64  private: \
65  TraitsType traits_; \
66  \
67  public: \
68  typedef TraitsType DecoratorTraits; \
69  const DecoratorTraits &get_decorator_traits() const { return traits_; } \
70  static const DecoratorTraits &get_default_decorator_traits() { \
71  static TraitsType dt = default_traits; \
72  return dt; \
73  } \
74  /* Should be private but SWIG accesses it through the
75  comparison
76  macros*/ IMP_NO_DOXYGEN( \
77  typedef Parent ParentDecorator); \
78  IMP_NO_DOXYGEN(typedef boost::true_type DecoratorHasTraits); \
79  Name() : Parent() {} \
80  Name(::IMP::Model *m, ::IMP::ParticleIndex id, \
81  const TraitsType &tr = default_traits) \
82  : Parent(m, id), traits_(tr) { \
83  IMP_INTERNAL_CHECK( \
84  get_is_setup(m, id, tr), \
85  "Particle " << m->get_particle_name(id) \
86  << " missing required attributes for decorator " \
87  << #Name); \
88  } \
89  explicit Name(const IMP::ParticleAdaptor &d, \
90  const TraitsType &tr = default_traits) \
91  : Parent(d), traits_(tr) { \
92  IMP_INTERNAL_CHECK( \
93  get_is_setup(d.get_model(), d.get_particle_index(), tr), \
94  "Particle " << d.get_model()->get_particle_name( \
95  d.get_particle_index()) \
96  << " missing required attributes for decorator " \
97  << #Name); \
98  } \
99  static bool get_is_setup(const IMP::ParticleAdaptor &p, \
100  const TraitsType &tr = default_traits) { \
101  return get_is_setup(p.get_model(), p.get_particle_index(), tr); \
102  } \
103  IMP_SHOWABLE(Name)
104 
105 /** Decorators need to be able to be set up from Particles, ParticleIndexes
106  and other Decorators. To help keep things uniform, we provide macros
107  to declare the setup functions. These macros expect that an appropriate
108  `do_setup_particle(Model *, ParticleIndex, args...)` function is
109  defined.
110 */
111 #define IMP_DECORATOR_SETUP_0(Name) \
112  /** Setup the particle so it can be used with this decorator. */ \
113  static Name setup_particle(Model *m, ParticleIndex pi) { \
114  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
115  "Particle " << m->get_particle_name(pi) \
116  << " already set up as " << #Name); \
117  do_setup_particle(m, pi); \
118  return Name(m, pi); \
119  } \
120  static Name setup_particle(IMP::ParticleAdaptor decorator) { \
121  return setup_particle(decorator.get_model(), \
122  decorator.get_particle_index()); \
123  }
124 /** \see IMP_DECORATOR_SETUP_0() */
125 #define IMP_DECORATOR_SETUP_1(Name, FirstArgumentType, first_argument_name) \
126  /** Setup the particle so that it can be used with this decorator */ \
127  static Name setup_particle(Model *m, ParticleIndex pi, \
128  FirstArgumentType first_argument_name) { \
129  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
130  "Particle " << m->get_particle_name(pi) \
131  << " already set up as " << #Name); \
132  do_setup_particle(m, pi, first_argument_name); \
133  return Name(m, pi); \
134  } \
135  /** \see setup_particle(m, pi, first_argument_name) */ \
136  static Name setup_particle(IMP::ParticleAdaptor decorator, \
137  FirstArgumentType first_argument_name) { \
138  return setup_particle(decorator.get_model(), \
139  decorator.get_particle_index(), \
140  first_argument_name); \
141  }
142 
143 /** \see IMP_DECORATOR_SETUP_0() */
144 #define IMP_DECORATOR_SETUP_2(Name, FirstArgumentType, first_argument_name, \
145  SecondArgumentType, second_argument_name) \
146  /** Setup the particle so it can be used with this decorator. */ \
147  static Name setup_particle(Model *m, ParticleIndex pi, \
148  FirstArgumentType first_argument_name, \
149  SecondArgumentType second_argument_name) { \
150  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
151  "Particle " << m->get_particle_name(pi) \
152  << " already set up as " << #Name); \
153  do_setup_particle(m, pi, first_argument_name, second_argument_name); \
154  return Name(m, pi); \
155  } \
156  static Name setup_particle(IMP::ParticleAdaptor decorator, \
157  FirstArgumentType first_argument_name, \
158  SecondArgumentType second_argument_name) { \
159  return setup_particle(decorator.get_model(), \
160  decorator.get_particle_index(), first_argument_name, \
161  second_argument_name); \
162  }
163 /** \see IMP_DECORATOR_SETUP_0() */
164 #define IMP_DECORATOR_SETUP_3(Name, FirstArgumentType, first_argument_name, \
165  SecondArgumentType, second_argument_name, \
166  ThirdArgumentType, third_argument_name) \
167  /** Setup the particle so it can be used with this decorator. */ \
168  static Name setup_particle(Model *m, ParticleIndex pi, \
169  FirstArgumentType first_argument_name, \
170  SecondArgumentType second_argument_name, \
171  ThirdArgumentType third_argument_name) { \
172  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
173  "Particle " << m->get_particle_name(pi) \
174  << " already set up as " << #Name); \
175  do_setup_particle(m, pi, first_argument_name, second_argument_name, \
176  third_argument_name); \
177  return Name(m, pi); \
178  } \
179  static Name setup_particle(IMP::ParticleAdaptor decorator, \
180  FirstArgumentType first_argument_name, \
181  SecondArgumentType second_argument_name, \
182  ThirdArgumentType third_argument_name) { \
183  return setup_particle(decorator.get_model(), \
184  decorator.get_particle_index(), first_argument_name, \
185  second_argument_name, third_argument_name); \
186  }
187 /** \see IMP_DECORATOR_SETUP_0() */
188 #define IMP_DECORATOR_SETUP_4(Name, FirstArgumentType, first_argument_name, \
189  SecondArgumentType, second_argument_name, \
190  ThirdArgumentType, third_argument_name, \
191  FourthArgumentType, fourth_argument_name) \
192  /** Setup the particle so it can be used with this decorator. */ \
193  static Name setup_particle(Model *m, ParticleIndex pi, \
194  FirstArgumentType first_argument_name, \
195  SecondArgumentType second_argument_name, \
196  ThirdArgumentType third_argument_name, \
197  FourthArgumentType fourth_argument_name) { \
198  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
199  "Particle " << m->get_particle_name(pi) \
200  << " already set up as " << #Name); \
201  do_setup_particle(m, pi, first_argument_name, second_argument_name, \
202  third_argument_name, fourth_argument_name); \
203  return Name(m, pi); \
204  } \
205  static Name setup_particle(IMP::ParticleAdaptor decorator, \
206  FirstArgumentType first_argument_name, \
207  SecondArgumentType second_argument_name, \
208  ThirdArgumentType third_argument_name, \
209  FourthArgumentType fourth_argument_name) { \
210  return setup_particle(decorator.get_model(), \
211  decorator.get_particle_index(), first_argument_name, \
212  second_argument_name, third_argument_name, \
213  fourth_argument_name); \
214  }
215 
216 /** \see IMP_DECORATOR_SETUP_0() */
217 #define IMP_DECORATOR_SETUP_5(Name, \
218  FirstArgumentType, first_argument_name, \
219  SecondArgumentType, second_argument_name, \
220  ThirdArgumentType, third_argument_name, \
221  FourthArgumentType, fourth_argument_name, \
222  FifthArgumentType, fifth_argument_name) \
223  /** Setup the particle so it can be used with this decorator. */ \
224  static Name setup_particle(Model *m, ParticleIndex pi, \
225  FirstArgumentType first_argument_name, \
226  SecondArgumentType second_argument_name, \
227  ThirdArgumentType third_argument_name, \
228  FourthArgumentType fourth_argument_name, \
229  FifthArgumentType fifth_argument_name) { \
230  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
231  "Particle " << m->get_particle_name(pi) \
232  << " already set up as " << #Name); \
233  do_setup_particle(m, pi, first_argument_name, second_argument_name, \
234  third_argument_name, fourth_argument_name, \
235  fifth_argument_name); \
236  return Name(m, pi); \
237  } \
238  static Name setup_particle(IMP::ParticleAdaptor decorator, \
239  FirstArgumentType first_argument_name, \
240  SecondArgumentType second_argument_name, \
241  ThirdArgumentType third_argument_name, \
242  FourthArgumentType fourth_argument_name, \
243  FifthArgumentType fifth_argument_name) { \
244  return setup_particle(decorator.get_model(), \
245  decorator.get_particle_index(), first_argument_name, \
246  second_argument_name, third_argument_name, \
247  fourth_argument_name, fifth_argument_name); \
248  }
249 
250 /** Decorators need to be able to be set up from Particles, ParticleIndexes
251  and other Decorators. To help keep things uniform, we provide macros
252  to declare the setup functions. These macros expect that an appropriate
253  `do_setup_particle(Model *, ParticleIndex, args...)` function is
254  defined. But any docs needed before the macro invocation.
255 */
256 #define IMP_DECORATOR_TRAITS_SETUP_0(Name) \
257  /** Setup the particle so it can be used with this decorator. */ \
258  static Name setup_particle( \
259  Model *m, ParticleIndex pi, \
260  DecoratorTraits tr = get_default_decorator_traits()) { \
261  do_setup_particle(m, pi, tr); \
262  return Name(m, pi, tr); \
263  } \
264  static Name setup_particle( \
265  IMP::ParticleAdaptor d, \
266  DecoratorTraits tr = get_default_decorator_traits()) { \
267  do_setup_particle(d.get_model(), d.get_particle_index(), tr); \
268  return Name(d.get_model(), d.get_particle_index(), tr); \
269  }
270 /** \see IMP_DECORATOR_TRAITS_SETUP_0() */
271 #define IMP_DECORATOR_TRAITS_SETUP_1(Name, FirstArgumentType, \
272  first_argument_name) \
273  static Name setup_particle( \
274  Model *m, ParticleIndex pi, \
275  FirstArgumentType first_argument_name, \
276  DecoratorTraits tr = get_default_decorator_traits()) { \
277  do_setup_particle(m, pi, first_argument_name, tr); \
278  return Name(m, pi, tr); \
279  } \
280  static Name setup_particle( \
281  IMP::ParticleAdaptor d, FirstArgumentType first_argument_name, \
282  DecoratorTraits tr = get_default_decorator_traits()) { \
283  do_setup_particle(d.get_model(), d.get_particle_index(), \
284  first_argument_name, tr); \
285  return Name(d.get_model(), d.get_particle_index(), tr); \
286  }
287 /** \see IMP_DECORATOR_TRAITS_SETUP_0() */
288 #define IMP_DECORATOR_TRAITS_SETUP_2(Name, FirstArgumentType, \
289  first_argument_name, SecondArgumentType, \
290  second_argument_name) \
291  static Name setup_particle( \
292  Model *m, ParticleIndex pi, \
293  FirstArgumentType first_argument_name, \
294  SecondArgumentType second_argument_name, \
295  DecoratorTraits tr = get_default_decorator_traits()) { \
296  do_setup_particle(m, pi, first_argument_name, second_argument_name, tr); \
297  return Name(m, pi, tr); \
298  } \
299  static Name setup_particle( \
300  IMP::ParticleAdaptor d, FirstArgumentType first_argument_name, \
301  SecondArgumentType second_argument_name, \
302  DecoratorTraits tr = get_default_decorator_traits()) { \
303  do_setup_particle(d.get_model(), d.get_particle_index(), \
304  first_argument_name, second_argument_name, tr); \
305  return Name(d.get_model(), d.get_particle_index(), tr); \
306  }
307 
308 //! Perform actions dependent on whether a particle has an attribute.
309 /** A common pattern is to check if a particle has a particular attribute,
310  do one thing if it does and another if it does not. This macro implements
311  that pattern. It requires that the method get_particle_index() return the
312  particle being used.
313 
314  \param[in] AttributeKey The key for the attribute
315  \param[in] Type The type for the attribute ("Int", "Float", "String")
316  \param[in] has_action The action to take if the Particle has the attribute.
317  The attribute value is stored in the variable VALUE.
318  \param[in] not_has_action The action to take if the Particle does not have
319  the attribute.
320  \see IMP_DECORATOR_GET()
321  \see IMP_DECORATOR_GET_SET()
322 
323 */
324 #define IMP_DECORATOR_GET(AttributeKey, Type, has_action, not_has_action) \
325  do { \
326  if (get_model()->get_has_attribute(AttributeKey, get_particle_index())) { \
327  Type VALUE = \
328  get_model()->get_attribute(AttributeKey, get_particle_index()); \
329  has_action; \
330  } else { \
331  not_has_action; \
332  } \
333  } while (false)
334 
335 //! Set an attribute, creating it if it does not already exist.
336 /** Another common pattern is to have an assumed value if the attribute
337  is not there. Then, you sometimes need to set the value whether it
338  is there or not.
339  \see IMP_DECORATOR_GET()
340  \see IMP_DECORATOR_GET_SET()
341 */
342 #define IMP_DECORATOR_SET(AttributeKey, value) \
343  do { \
344  if (get_model()->get_has_attribute(AttributeKey, get_particle_index())) { \
345  get_model()->set_attribute(AttributeKey, get_particle_index(), value); \
346  } else { \
347  get_model()->add_attribute(AttributeKey, get_particle_index(), value); \
348  } \
349  } while (false)
350 
351 //! Define methods for getting and setting a particular simple field
352 /** This macro defines methods to get and set a particular attribute.
353 
354  \param[in] name The lower case name of the attribute
355  \param[in] AttributeKey The AttributeKey object controlling
356  the attribute.
357  \param[in] Type The type of the attribute (upper case).
358  \param[in] ReturnType The type to return from the get.
359  \see IMP_DECORATOR_GET()
360  \see IMP_DECORATOR_SET()
361 */
362 #define IMP_DECORATOR_GET_SET(name, AttributeKey, Type, ReturnType) \
363  /** returns the value of the name attribute */ \
364  ReturnType get_##name() const { \
365  return static_cast<ReturnType> \
366  (get_model()->get_attribute(AttributeKey, get_particle_index())); \
367  } \
368  /** sets the value of the name attribute to t */ \
369  void set_##name(ReturnType t) { \
370  get_model()->set_attribute(AttributeKey, get_particle_index(), t); \
371  } \
372  IMP_REQUIRE_SEMICOLON_CLASS(getset##name)
373 
374 //! Define methods for getting and setting an optional simple field.
375 /** See IMP_DECORATOR_GET_SET(). The difference is that here you can provide
376  a default value to use if the decorator does not have the attribute.
377 
378  \param[in] name The lower case name of the attribute
379  \param[in] AttributeKey The expression to get the required attribute key.
380  \param[in] Type The type of the attribute (upper case).
381  \param[in] ReturnType The type to return from the get.
382  \param[in] default_value The value returned if the attribute is missing.
383 */
384 #define IMP_DECORATOR_GET_SET_OPT(name, AttributeKey, Type, ReturnType, \
385  default_value) \
386  /** returns the value of the name attribute, or default_value if \
387  the name attribute is missing */ \
388  ReturnType get_##name() const { \
389  IMP_DECORATOR_GET(AttributeKey, Type, \
390  return static_cast<ReturnType>(VALUE), \
391  return default_value); \
392  } \
393  /** sets the name attribute to t */ \
394  void set_##name(ReturnType t) { IMP_DECORATOR_SET(AttributeKey, t); } \
395  IMP_REQUIRE_SEMICOLON_CLASS(getset_##name)
396 
397 #define IMP_DECORATORS_DECL(Name, PluralName) \
398  class Name; \
399  typedef IMP::Vector<Name> PluralName
400 
401 #ifndef IMP_DOXYGEN
402 #define IMP_DECORATORS_DEF(Name, PluralName) \
403  /* needed so there is no ambiguity with operator->*/ \
404  inline std::ostream &operator<<(std::ostream &out, Name n) { \
405  n.show(out); \
406  return out; \
407  }
408 #else
409 #define IMP_DECORATORS_DEF(Name, PluralName)
410 #endif
411 
412 //! Define the types for storing sets of decorators
413 /** The macro defines the types PluralName and PluralNameTemp.
414  Parent is unused and remains for backward compatibility
415  */
416 #define IMP_DECORATORS(Name, PluralName, Parent) \
417  IMP_DECORATORS_DECL(Name, PluralName); \
418  IMP_DECORATORS_DEF(Name, PluralName)
419 
420 //! Define the types for storing sets of decorators
421 /** The macro defines the types PluralName and PluralNameTemp.
422  */
423 #define IMP_DECORATORS_WITH_TRAITS(Name, PluralName, Parent) \
424  /* needed so there is no ambiguity with operator->*/ \
425  inline std::ostream &operator<<(std::ostream &out, Name n) { \
426  n.show(out); \
427  return out; \
428  } \
429  typedef IMP::Vector<Name> PluralName
430 
431 
432 /**
433  Declares Decorator methods that allows (privately) setting a constraint
434  and publicly getting that constraint
435  */
436 #define IMP_CONSTRAINT_DECORATOR_DECL(Name) \
437  private: \
438  static ObjectKey get_constraint_key(); \
439  /** set a constraint associated with this decorator that applies 'before'
440  and 'after' before and after evaluation. The constraint is added as
441  a model ScoreState. If before and after are Null, the constraint is
442  reset and removed from the model list of score states.
443  */ \
444  static void set_constraint(SingletonModifier* before, \
445  SingletonDerivativeModifier* after, Model* m, \
446  ParticleIndex pi); \
447  \
448  public: \
449  Constraint* get_constraint() const { \
450  return dynamic_cast<Constraint*>( \
451  get_particle()->get_value(get_constraint_key())); \
452  } \
453  IMP_REQUIRE_SEMICOLON_CLASS(constraint)
454 
455 /**
456  Defines Decorator methods that allows (privately) setting a constraint
457  and publicly getting that constraint. The constraint is added as a
458  score state to the model.
459  */
460 #define IMP_CONSTRAINT_DECORATOR_DEF(Name) \
461  ObjectKey Name::get_constraint_key() { \
462  static ObjectKey ret(#Name " score state"); \
463  return ret; \
464  } \
465  void Name::set_constraint(SingletonModifier* before, \
466  SingletonDerivativeModifier* after, Model* m, \
467  ParticleIndex pi) { \
468  if (!after && !before) { \
469  if (m->get_has_attribute(get_constraint_key(), pi)) { \
470  m->remove_score_state(dynamic_cast<ScoreState*>( \
471  m->get_attribute(get_constraint_key(), pi))); \
472  m->remove_attribute(get_constraint_key(), pi); \
473  } \
474  } else { \
475  Constraint* ss = new core::SingletonConstraint( \
476  before, after, m, pi, \
477  std::string(#Name "updater for ") + m->get_particle_name(pi)); \
478  m->add_attribute(get_constraint_key(), pi, ss); \
479  m->add_score_state(ss); \
480  } \
481  } \
482  IMP_REQUIRE_SEMICOLON_NAMESPACE
483 
484 
485 /** Register a function that can be used to check that the particle
486  is valid with respect to the decorator. The function should take
487  a Particle* as an argument and return a bool. It should throw
488  an exception if something is wrong.
489 
490  This macro should only be used in a .cpp file.
491 */
492 #define IMP_CHECK_DECORATOR(Name, function) \
493  IMP::internal::ParticleCheck Name##pc(Name::get_is_setup, function);
494 
495 
496 //! Create a decorator that computes some sort of summary info on a set
497 /** Examples include a centroid or a cover for a set of particles.
498 
499  \param[in] Name The name for the decorator
500  \param[in] Parent the parent decorator type
501  \param[in] Members the way to pass a set of particles in
502  \param[in] SetupDoc extra documentation for setup
503 */
504 #define IMP_SUMMARIZE_DECORATOR_DECL(Name, Parent, Members, SetupDoc) \
505  class IMPCOREEXPORT Name : public Parent { \
506  IMP_CONSTRAINT_DECORATOR_DECL(Name); \
507  private: \
508  /** Sets up Name over particles in pis */ \
509  static void do_setup_particle(Model *m, ParticleIndex pi, \
510  const ParticleIndexes &pis); \
511  /** Sets up Name over particles passed by applying the refiner
512  over the particle pi
513  */ \
514  static void do_setup_particle(Model *m, ParticleIndex pi, \
515  Refiner *ref); \
516  \
517  public: \
518  IMP_DECORATOR_METHODS(Name, Parent); \
519  /** Sets up Name over members, and constrains Name to be
520  computed before model evaluation and to propagate derivatives
521  following model evaluation.
522  SetupDoc
523  */ \
524  IMP_DECORATOR_SETUP_1(Name, ParticleIndexesAdaptor, members); \
525  /** Sets up Name over particles passed by applying the refiner
526  over the particle pi, and constrains Name to be computed before
527  model evaluation and to propagate derivatives following model
528  evaluation.
529  SetupDoc
530  */ \
531  IMP_DECORATOR_SETUP_1(Name, Refiner *, refiner); \
532  static bool get_is_setup(Model *m, ParticleIndex pi) { \
533  return m->get_has_attribute(get_constraint_key(), pi); \
534  } \
535  IMP_NO_DOXYGEN(typedef boost::false_type DecoratorHasTraits); \
536  \
537  private: \
538  /* hide set methods*/ \
539  void set_coordinates() {}; \
540  void set_coordinates_are_optimized() const {} \
541  void set_coordinate() const {} \
542  void set_radius() const {} \
543  }; \
544  IMP_DECORATORS(Name, Name##s, Parent##s)
545 
546 
547 /** \see IMP_SUMMARIZE_DECORATOR_DECL()
548  \param[in] Name The name for the decorator
549  \param[in] Parent the parent decorator type
550  \param[in] Members the way to pass a set of particles in
551  \param[in] create_pre_modifier the statements to create the
552  SingletonModifier which computes the summary info,
553  using refiner 'ref'
554  \param[in] create_post_modifier a SingletonDerivativeModifier for
555  the derivatives of the summary back to its members,
556  using refiner 'ref'
557 */
558 #define IMP_SUMMARIZE_DECORATOR_DEF(Name, Parent, Members, \
559  create_pre_modifier, \
560  create_post_modifier) \
561  void Name::do_setup_particle(Model *m, ParticleIndex pi, \
562  const ParticleIndexes &pis) { \
563  Refiner *ref = new FixedRefiner(IMP::get_particles(m, pis)); \
564  SingletonModifier* pre_mod = create_pre_modifier; \
565  SingletonDerivativeModifier* post_mod = create_post_modifier; \
566  if (!Parent::get_is_setup(m, pi)) Parent::setup_particle(m, pi); \
567  set_constraint(pre_mod, post_mod, m, pi); \
568  } \
569  \
570  void Name::do_setup_particle(Model *m, ParticleIndex pi, \
571  Refiner *ref) { \
572  SingletonModifier* pre_mod = create_pre_modifier; \
573  SingletonDerivativeModifier* post_mod = create_post_modifier; \
574  if (!Parent::get_is_setup(m, pi)) Parent::setup_particle(m, pi); \
575  set_constraint(pre_mod, post_mod, m, pi); \
576  } \
577  \
578  void Name::show(std::ostream &out) const { \
579  out << #Name << " at " << static_cast<Parent>(*this); \
580  } \
581  IMP_CONSTRAINT_DECORATOR_DEF(Name)
582 
583 #endif /* IMPKERNEL_DECORATOR_MACROS_H */
The base class for decorators.
Various general useful functions for IMP.
Various general useful macros for IMP.
Logging and error reporting support.
Classes to handle individual model particles. (Note that implementation of inline functions is in int...
Exception definitions and assertions.
Various general useful macros for IMP.