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