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