home
about
news
download
doc
source
systems
tests
bugs
contact
IMP Reference Guide
develop.7cb8855c60,2024/10/08
The Integrative Modeling Platform
IMP Manual
Reference Guide
Tutorial Index
Modules
Classes
Examples
include
IMP
version 20241008.develop.7cb8855c60
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 */
Decorator.h
The base class for decorators.
particle_index.h
Functions and adaptors for dealing with particle indexes.
warning_macros.h
Macros to control compiler warnings.
log_macros.h
Logging and error reporting support.
Particle.h
Classes to handle individual model particles. (Note that implementation of inline functions is in int...
check_macros.h
Helper macros for throwing and handling exceptions.
showable_macros.h
Macros to help with objects that can be printed to a stream.