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