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