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