IMP logo
IMP Reference Guide  2.20.2
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-2022 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  /**
111  @return a Name object that decorates particle pi
112  */ \
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  /** @return a Name object that decorates the particle specified by pa
121  \see setup_particle(m, p) */ \
122  static Name setup_particle(IMP::ParticleAdaptor pa) { \
123  return setup_particle(pa.get_model(), \
124  pa.get_particle_index()); \
125  }
126 /** \see IMP_DECORATOR_SETUP_0() */
127 #define IMP_DECORATOR_SETUP_1(Name, FirstArgumentType, first_argument_name) \
128  /**
129  @return a Name object that decorates particle pi
130  */ \
131  static Name setup_particle(Model *m, ParticleIndex pi, \
132  FirstArgumentType first_argument_name) { \
133  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
134  "Particle " << m->get_particle_name(pi) \
135  << " already set up as " << #Name); \
136  do_setup_particle(m, pi, first_argument_name); \
137  return Name(m, pi); \
138  } \
139  /** @return a Name object that decorates the particle specified by pa
140  \see setup_particle(m, pi, first_argument_name) */ \
141  static Name setup_particle(IMP::ParticleAdaptor pa, \
142  FirstArgumentType first_argument_name) { \
143  return setup_particle(pa.get_model(), \
144  pa.get_particle_index(), \
145  first_argument_name); \
146  }
147 
148 /** \see IMP_DECORATOR_SETUP_0() */
149 #define IMP_DECORATOR_SETUP_2(Name, FirstArgumentType, first_argument_name, \
150  SecondArgumentType, second_argument_name) \
151  /**
152  @return a Name object that decorates particle pi
153  */ \
154  static Name setup_particle(Model *m, ParticleIndex pi, \
155  FirstArgumentType first_argument_name, \
156  SecondArgumentType second_argument_name) { \
157  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
158  "Particle " << m->get_particle_name(pi) \
159  << " already set up as " << #Name); \
160  do_setup_particle(m, pi, first_argument_name, second_argument_name); \
161  return Name(m, pi); \
162  } \
163  /** @return a Name object that decorates the particle specified by pa
164  \see setup_particle(m, p, first_argument_name, second_argument_name)
165  */ \
166  static Name setup_particle(IMP::ParticleAdaptor pa, \
167  FirstArgumentType first_argument_name, \
168  SecondArgumentType second_argument_name) { \
169  return setup_particle(pa.get_model(), \
170  pa.get_particle_index(), first_argument_name, \
171  second_argument_name); \
172  }
173 /** \see IMP_DECORATOR_SETUP_0() */
174 #define IMP_DECORATOR_SETUP_3(Name, FirstArgumentType, first_argument_name, \
175  SecondArgumentType, second_argument_name, \
176  ThirdArgumentType, third_argument_name) \
177  /**
178  @return a Name object that decorates particle pi
179  */ \
180  static Name setup_particle(Model *m, ParticleIndex pi, \
181  FirstArgumentType first_argument_name, \
182  SecondArgumentType second_argument_name, \
183  ThirdArgumentType third_argument_name) { \
184  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
185  "Particle " << m->get_particle_name(pi) \
186  << " already set up as " << #Name); \
187  do_setup_particle(m, pi, first_argument_name, second_argument_name, \
188  third_argument_name); \
189  return Name(m, pi); \
190  } \
191  /** @return a Name object that decorates the particle specified by pa
192  \see setup_particle(m, pi, first_argument_name, second_argument_name,
193  third_argument_name) */ \
194  static Name setup_particle(IMP::ParticleAdaptor pa, \
195  FirstArgumentType first_argument_name, \
196  SecondArgumentType second_argument_name, \
197  ThirdArgumentType third_argument_name) { \
198  return setup_particle(pa.get_model(), \
199  pa.get_particle_index(), first_argument_name, \
200  second_argument_name, third_argument_name); \
201  }
202 /** \see IMP_DECORATOR_SETUP_0() */
203 #define IMP_DECORATOR_SETUP_4(Name, FirstArgumentType, first_argument_name, \
204  SecondArgumentType, second_argument_name, \
205  ThirdArgumentType, third_argument_name, \
206  FourthArgumentType, fourth_argument_name) \
207  /**
208  @return a Name object that decorates particle pi
209  */ \
210  static Name setup_particle(Model *m, ParticleIndex pi, \
211  FirstArgumentType first_argument_name, \
212  SecondArgumentType second_argument_name, \
213  ThirdArgumentType third_argument_name, \
214  FourthArgumentType fourth_argument_name) { \
215  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
216  "Particle " << m->get_particle_name(pi) \
217  << " already set up as " << #Name); \
218  do_setup_particle(m, pi, first_argument_name, second_argument_name, \
219  third_argument_name, fourth_argument_name); \
220  return Name(m, pi); \
221  } \
222  /** @return a Name object that decorates the particle specified by pa
223  \see setup_particle(m, pi, first_argument_name, second_argument_name,
224  third_argument_name, fourth_argument_name) */ \
225  static Name setup_particle(IMP::ParticleAdaptor pa, \
226  FirstArgumentType first_argument_name, \
227  SecondArgumentType second_argument_name, \
228  ThirdArgumentType third_argument_name, \
229  FourthArgumentType fourth_argument_name) { \
230  return setup_particle(pa.get_model(), \
231  pa.get_particle_index(), first_argument_name, \
232  second_argument_name, third_argument_name, \
233  fourth_argument_name); \
234  }
235 
236 /** \see IMP_DECORATOR_SETUP_0() */
237 #define IMP_DECORATOR_SETUP_5(Name, \
238  FirstArgumentType, first_argument_name, \
239  SecondArgumentType, second_argument_name, \
240  ThirdArgumentType, third_argument_name, \
241  FourthArgumentType, fourth_argument_name, \
242  FifthArgumentType, fifth_argument_name) \
243  /**
244  @return a Name object that decorates particle pi
245  */ \
246  static Name setup_particle(Model *m, ParticleIndex pi, \
247  FirstArgumentType first_argument_name, \
248  SecondArgumentType second_argument_name, \
249  ThirdArgumentType third_argument_name, \
250  FourthArgumentType fourth_argument_name, \
251  FifthArgumentType fifth_argument_name) { \
252  IMP_USAGE_CHECK(!get_is_setup(m, pi), \
253  "Particle " << m->get_particle_name(pi) \
254  << " already set up as " << #Name); \
255  do_setup_particle(m, pi, first_argument_name, second_argument_name, \
256  third_argument_name, fourth_argument_name, \
257  fifth_argument_name); \
258  return Name(m, pi); \
259  } \
260  /** @return a Name object that decorates the particle specified by pa
261  \see setup_particle(m, pi, first_argument_name, second_argument_name,
262  third_argument_name, fourth_argument_name, fifth_argument_name) */ \
263  static Name setup_particle(IMP::ParticleAdaptor pa, \
264  FirstArgumentType first_argument_name, \
265  SecondArgumentType second_argument_name, \
266  ThirdArgumentType third_argument_name, \
267  FourthArgumentType fourth_argument_name, \
268  FifthArgumentType fifth_argument_name) { \
269  return setup_particle(pa.get_model(), \
270  pa.get_particle_index(), first_argument_name, \
271  second_argument_name, third_argument_name, \
272  fourth_argument_name, fifth_argument_name); \
273  }
274 
275 /** Decorators need to be able to be set up from Particles, ParticleIndexes
276  and other Decorators. To help keep things uniform, we provide macros
277  to declare the setup functions. These macros expect that an appropriate
278  `do_setup_particle(Model *, ParticleIndex, args...)` function is
279  defined. But any docs needed before the macro invocation.
280 */
281 #define IMP_DECORATOR_TRAITS_SETUP_0(Name) \
282  /**
283  @return a Name object that decorates particle pi
284  */ \
285  static Name setup_particle( \
286  Model *m, ParticleIndex pi, \
287  DecoratorTraits tr = get_default_decorator_traits()) { \
288  do_setup_particle(m, pi, tr); \
289  return Name(m, pi, tr); \
290  } \
291  static Name setup_particle( \
292  IMP::ParticleAdaptor d, \
293  DecoratorTraits tr = get_default_decorator_traits()) { \
294  do_setup_particle(d.get_model(), d.get_particle_index(), tr); \
295  return Name(d.get_model(), d.get_particle_index(), tr); \
296  }
297 /** \see IMP_DECORATOR_TRAITS_SETUP_0() */
298 #define IMP_DECORATOR_TRAITS_SETUP_1(Name, FirstArgumentType, \
299  first_argument_name) \
300  static Name setup_particle( \
301  Model *m, ParticleIndex pi, \
302  FirstArgumentType first_argument_name, \
303  DecoratorTraits tr = get_default_decorator_traits()) { \
304  do_setup_particle(m, pi, first_argument_name, tr); \
305  return Name(m, pi, tr); \
306  } \
307  static Name setup_particle( \
308  IMP::ParticleAdaptor d, FirstArgumentType first_argument_name, \
309  DecoratorTraits tr = get_default_decorator_traits()) { \
310  do_setup_particle(d.get_model(), d.get_particle_index(), \
311  first_argument_name, tr); \
312  return Name(d.get_model(), d.get_particle_index(), tr); \
313  }
314 /** \see IMP_DECORATOR_TRAITS_SETUP_0() */
315 #define IMP_DECORATOR_TRAITS_SETUP_2(Name, FirstArgumentType, \
316  first_argument_name, SecondArgumentType, \
317  second_argument_name) \
318  static Name setup_particle( \
319  Model *m, ParticleIndex pi, \
320  FirstArgumentType first_argument_name, \
321  SecondArgumentType second_argument_name, \
322  DecoratorTraits tr = get_default_decorator_traits()) { \
323  do_setup_particle(m, pi, first_argument_name, second_argument_name, tr); \
324  return Name(m, pi, tr); \
325  } \
326  static Name setup_particle( \
327  IMP::ParticleAdaptor d, FirstArgumentType first_argument_name, \
328  SecondArgumentType second_argument_name, \
329  DecoratorTraits tr = get_default_decorator_traits()) { \
330  do_setup_particle(d.get_model(), d.get_particle_index(), \
331  first_argument_name, second_argument_name, tr); \
332  return Name(d.get_model(), d.get_particle_index(), tr); \
333  }
334 
335 //! Perform actions dependent on whether a particle has an attribute.
336 /** A common pattern is to check if a particle has a particular attribute,
337  do one thing if it does and another if it does not. This macro implements
338  that pattern. It requires that the method get_particle_index() return the
339  particle being used.
340 
341  \param[in] AttributeKey The key for the attribute
342  \param[in] Type The type for the attribute ("Int", "Float", "String")
343  \param[in] has_action The action to take if the Particle has the attribute.
344  The attribute value is stored in the variable VALUE.
345  \param[in] not_has_action The action to take if the Particle does not have
346  the attribute.
347  \see IMP_DECORATOR_GET()
348  \see IMP_DECORATOR_GET_SET()
349 
350 */
351 #define IMP_DECORATOR_GET(AttributeKey, Type, has_action, not_has_action) \
352  do { \
353  if (get_model()->get_has_attribute(AttributeKey, get_particle_index())) { \
354  Type VALUE = \
355  get_model()->get_attribute(AttributeKey, get_particle_index()); \
356  has_action; \
357  } else { \
358  not_has_action; \
359  } \
360  } while (false)
361 
362 //! Set an attribute, creating it if it does not already exist.
363 /** Another common pattern is to have an assumed value if the attribute
364  is not there. Then, you sometimes need to set the value whether it
365  is there or not.
366  \see IMP_DECORATOR_GET()
367  \see IMP_DECORATOR_GET_SET()
368 */
369 #define IMP_DECORATOR_SET(AttributeKey, value) \
370  do { \
371  if (get_model()->get_has_attribute(AttributeKey, get_particle_index())) { \
372  get_model()->set_attribute(AttributeKey, get_particle_index(), value); \
373  } else { \
374  get_model()->add_attribute(AttributeKey, get_particle_index(), value); \
375  } \
376  } while (false)
377 
378 //! Define methods for getting and setting a particular simple field
379 /** This macro defines methods to get and set a particular attribute.
380 
381  \param[in] name The lower case name of the attribute
382  \param[in] AttributeKey The AttributeKey object controlling
383  the attribute.
384  \param[in] Type The type of the attribute (upper case).
385  \param[in] ReturnType The type to return from the get.
386  \see IMP_DECORATOR_GET()
387  \see IMP_DECORATOR_SET()
388 */
389 #define IMP_DECORATOR_GET_SET(name, AttributeKey, Type, ReturnType) \
390  /** returns the value of the name attribute */ \
391  ReturnType get_##name() const { \
392  return static_cast<ReturnType> \
393  (get_model()->get_attribute(AttributeKey, get_particle_index())); \
394  } \
395  /** sets the value of the name attribute to t */ \
396  void set_##name(ReturnType t) { \
397  get_model()->set_attribute(AttributeKey, get_particle_index(), t); \
398  } \
399  IMP_REQUIRE_SEMICOLON_CLASS(getset##name)
400 
401 //! Define methods for getting and setting an optional simple field.
402 /** See IMP_DECORATOR_GET_SET(). The difference is that here you can provide
403  a default value to use if the decorator does not have the attribute.
404 
405  \param[in] name The lower case name of the attribute
406  \param[in] AttributeKey The expression to get the required attribute key.
407  \param[in] Type The type of the attribute (upper case).
408  \param[in] ReturnType The type to return from the get.
409  \param[in] default_value The value returned if the attribute is missing.
410 */
411 #define IMP_DECORATOR_GET_SET_OPT(name, AttributeKey, Type, ReturnType, \
412  default_value) \
413  /** returns the value of the name attribute, or default_value if \
414  the name attribute is missing */ \
415  ReturnType get_##name() const { \
416  IMP_DECORATOR_GET(AttributeKey, Type, \
417  return static_cast<ReturnType>(VALUE), \
418  return default_value); \
419  } \
420  /** sets the name attribute to t */ \
421  void set_##name(ReturnType t) { IMP_DECORATOR_SET(AttributeKey, t); } \
422  IMP_REQUIRE_SEMICOLON_CLASS(getset_##name)
423 
424 #define IMP_DECORATORS_DECL(Name, PluralName) \
425  class Name; \
426  typedef IMP::Vector<Name> PluralName
427 
428 #ifndef IMP_DOXYGEN
429 #define IMP_DECORATORS_DEF(Name, PluralName) \
430  /* needed so there is no ambiguity with operator->*/ \
431  inline std::ostream &operator<<(std::ostream &out, Name n) { \
432  n.show(out); \
433  return out; \
434  }
435 #else
436 #define IMP_DECORATORS_DEF(Name, PluralName)
437 #endif
438 
439 //! Define the types for storing sets of decorators
440 /** The macro defines the types PluralName and PluralNameTemp.
441  Parent is unused and remains for backward compatibility
442  */
443 #define IMP_DECORATORS(Name, PluralName, Parent) \
444  IMP_DECORATORS_DECL(Name, PluralName); \
445  IMP_DECORATORS_DEF(Name, PluralName)
446 
447 //! Define the types for storing sets of decorators
448 /** The macro defines the types PluralName and PluralNameTemp.
449  */
450 #define IMP_DECORATORS_WITH_TRAITS(Name, PluralName, Parent) \
451  /* needed so there is no ambiguity with operator->*/ \
452  inline std::ostream &operator<<(std::ostream &out, Name n) { \
453  n.show(out); \
454  return out; \
455  } \
456  typedef IMP::Vector<Name> PluralName
457 
458 
459 /**
460  Declares Decorator methods that allows (privately) setting a constraint
461  and publicly getting that constraint
462  */
463 #define IMP_CONSTRAINT_DECORATOR_DECL(Name) \
464  private: \
465  static ObjectKey get_constraint_key(); \
466  /** set a constraint associated with this decorator that applies 'before'
467  and 'after' before and after evaluation. The constraint is added as
468  a model ScoreState. If before and after are Null, the constraint is
469  reset and removed from the model list of score states.
470  */ \
471  static void set_constraint(SingletonModifier* before, \
472  SingletonDerivativeModifier* after, Model* m, \
473  ParticleIndex pi); \
474  \
475  public: \
476  Constraint* get_constraint() const { \
477  return dynamic_cast<Constraint*>( \
478  get_particle()->get_value(get_constraint_key())); \
479  } \
480  IMP_REQUIRE_SEMICOLON_CLASS(constraint)
481 
482 /**
483  Defines Decorator methods that allows (privately) setting a constraint
484  and publicly getting that constraint. The constraint is added as a
485  score state to the model.
486  */
487 #define IMP_CONSTRAINT_DECORATOR_DEF(Name, can_skip) \
488  ObjectKey Name::get_constraint_key() { \
489  static ObjectKey ret(#Name " score state"); \
490  return ret; \
491  } \
492  void Name::set_constraint(SingletonModifier* before, \
493  SingletonDerivativeModifier* after, Model* m, \
494  ParticleIndex pi) { \
495  if (!after && !before) { \
496  if (m->get_has_attribute(get_constraint_key(), pi)) { \
497  m->remove_score_state(dynamic_cast<ScoreState*>( \
498  m->get_attribute(get_constraint_key(), pi))); \
499  m->remove_attribute(get_constraint_key(), pi); \
500  } \
501  } else { \
502  Constraint* ss = new core::SingletonConstraint( \
503  before, after, m, pi, \
504  std::string(#Name "updater for ") + m->get_particle_name(pi), \
505  can_skip); \
506  m->add_attribute(get_constraint_key(), pi, ss); \
507  m->add_score_state(ss); \
508  } \
509  } \
510  IMP_REQUIRE_SEMICOLON_NAMESPACE
511 
512 
513 /** Register a function that can be used to check that the particle
514  is valid with respect to the decorator. The function should take
515  a Particle* as an argument and return a bool. It should throw
516  an exception if something is wrong.
517 
518  This macro should only be used in a .cpp file.
519 */
520 #define IMP_CHECK_DECORATOR(Name, function) \
521  IMP::internal::ParticleCheck Name##pc(Name::get_is_setup, function);
522 
523 
524 //! Create a decorator that computes some sort of summary info on a set
525 /** Examples include a centroid or a cover for a set of particles.
526 
527  \param[in] Name The name for the decorator
528  \param[in] Parent the parent decorator type
529  \param[in] Members the way to pass a set of particles in
530  \param[in] SetupDoc extra documentation for setup
531 */
532 #define IMP_SUMMARIZE_DECORATOR_DECL(Name, Parent, Members, SetupDoc) \
533  class IMPCOREEXPORT Name : public Parent { \
534  IMP_CONSTRAINT_DECORATOR_DECL(Name); \
535  private: \
536  /** Sets up Name over particles in pis */ \
537  static void do_setup_particle(Model *m, ParticleIndex pi, \
538  const ParticleIndexes &pis); \
539  /** Sets up Name over particles passed by applying the refiner
540  over the particle pi
541  */ \
542  static void do_setup_particle(Model *m, ParticleIndex pi, \
543  Refiner *ref); \
544  \
545  public: \
546  IMP_DECORATOR_METHODS(Name, Parent); \
547  /** Sets up Name over members, and constrains Name to be
548  computed before model evaluation and to propagate derivatives
549  following model evaluation.
550  SetupDoc
551  */ \
552  IMP_DECORATOR_SETUP_1(Name, ParticleIndexesAdaptor, members); \
553  /** Sets up Name over particles passed by applying the refiner
554  over the particle pi, and constrains Name to be computed before
555  model evaluation and to propagate derivatives following model
556  evaluation.
557  SetupDoc
558  */ \
559  IMP_DECORATOR_SETUP_1(Name, Refiner *, refiner); \
560  static bool get_is_setup(Model *m, ParticleIndex pi) { \
561  return m->get_has_attribute(get_constraint_key(), pi); \
562  } \
563  IMP_NO_DOXYGEN(typedef boost::false_type DecoratorHasTraits); \
564  \
565  private: \
566  /* hide set methods*/ \
567  void set_coordinates() {}; \
568  void set_coordinates_are_optimized() const {} \
569  void set_coordinate() const {} \
570  void set_radius() const {} \
571  }; \
572  IMP_DECORATORS(Name, Name##s, Parent##s)
573 
574 
575 /** \see IMP_SUMMARIZE_DECORATOR_DECL()
576  \param[in] Name The name for the decorator
577  \param[in] Parent the parent decorator type
578  \param[in] Members the way to pass a set of particles in
579  \param[in] create_pre_modifier the statements to create the
580  SingletonModifier which computes the summary info,
581  using refiner 'ref'
582  \param[in] create_post_modifier a SingletonDerivativeModifier for
583  the derivatives of the summary back to its members,
584  using refiner 'ref'
585  \param[in] can_skip set to true iff the modifiers do not need to be
586  called when the particle did not move
587 */
588 #define IMP_SUMMARIZE_DECORATOR_DEF(Name, Parent, Members, \
589  create_pre_modifier, \
590  create_post_modifier, can_skip) \
591  void Name::do_setup_particle(Model *m, ParticleIndex pi, \
592  const ParticleIndexes &pis) { \
593  Refiner *ref = new FixedRefiner(IMP::get_particles(m, pis)); \
594  SingletonModifier* pre_mod = create_pre_modifier; \
595  SingletonDerivativeModifier* post_mod = create_post_modifier; \
596  if (!Parent::get_is_setup(m, pi)) Parent::setup_particle(m, pi); \
597  set_constraint(pre_mod, post_mod, m, pi); \
598  } \
599  \
600  void Name::do_setup_particle(Model *m, ParticleIndex pi, \
601  Refiner *ref) { \
602  SingletonModifier* pre_mod = create_pre_modifier; \
603  SingletonDerivativeModifier* post_mod = create_post_modifier; \
604  if (!Parent::get_is_setup(m, pi)) Parent::setup_particle(m, pi); \
605  set_constraint(pre_mod, post_mod, m, pi); \
606  } \
607  \
608  void Name::show(std::ostream &out) const { \
609  out << #Name << " at " << static_cast<Parent>(*this); \
610  } \
611  IMP_CONSTRAINT_DECORATOR_DEF(Name, can_skip)
612 
613 #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.