IMP
2.0.0
The Integrative Modeling Platform
Main Page
Related Pages
Modules
Namespaces
Classes
Files
Examples
File List
File Members
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 <
IMP/base/check_macros.h
>
13
#include <
IMP/base/log_macros.h
>
14
#include <
IMP/base/showable_macros.h
>
15
#include <
IMP/base/warning_macros.h
>
16
17
/** \name Macros to aid with implementing decorators
18
19
These macros are here to aid in implementation of IMP::Decorator
20
objects. The first two declare/define the expected methods. The
21
remainder help implement basic functions.
22
23
@{
24
*/
25
26
//! Define the basic things needed by a Decorator.
27
/** The macro defines the following methods
28
- a default constructor Decorator::Decorator()
29
30
It also declares:
31
- IMP::Decorator::show()
32
- IMP::Decorator::decorate_particle()
33
- IMP::Decorator::Decorator()
34
35
Finally, it expects methods corresponding to
36
- IMP::Decorator::particle_is_instance()
37
- IMP::Decorator::setup_particle()
38
39
You also implement static methods \c get_x_key() to return each of the
40
keys used. These static methods, which must be defined in the \c .cpp
41
file, should declare the key itself as a \c static member variable to
42
avoid initializing the key if the decorator is not used.
43
44
See IMP::Decorator for a more detailed description
45
of decorators.
46
47
\param[in] Name is the name of the decorator, such as XYZR
48
\param[in] Parent The class name for the parent of this class,
49
typically Decorator
50
51
\see IMP_DECORATOR_WITH_TRAITS()
52
*/
53
#define IMP_DECORATOR(Name, Parent) \
54
public: \
55
/* Should be private but SWIG accesses it through the comparison
56
macros*/
\
57
IMP_NO_DOXYGEN(typedef Parent ParentDecorator); \
58
Name(): Parent(){} \
59
Name(Model *m, ParticleIndex id): Parent(m, id) { \
60
IMP_INTERNAL_CHECK(particle_is_instance(m->get_particle(id)), \
61
"Particle " << m->get_particle(id)->get_name() \
62
<< " missing required attributes for decorator " \
63
<< #Name << "\n" \
64
<< base::ShowFull(m->get_particle(id))); \
65
} \
66
explicit Name(::IMP::kernel::Particle *p): Parent(p) { \
67
IMP_INTERNAL_CHECK(particle_is_instance(p), \
68
"Particle " << p->get_name() \
69
<< " missing required attributes for decorator " \
70
<< #Name << "\n" << base::ShowFull(p)); \
71
} \
72
static Name decorate_particle(::IMP::kernel::Particle *p) { \
73
IMP_CHECK_OBJECT(p); \
74
if (!particle_is_instance(p)) { \
75
return Name(); \
76
} \
77
return Name(p); \
78
} \
79
IMP_SHOWABLE(Name)
80
81
82
//! Define the basic things needed by a Decorator which has a traits object.
83
/** This macro is the same as IMP_DECORATOR() except that an extra object
84
of type TraitsType is passed after the particle to
85
- IMP::Decorator::particle_is_instance()
86
- IMP::Decorator::setup_particle()
87
As in the IMP::core::XYZR or IMP::core::Hierarchy,
88
this object can be used to parameterize the Decorator. The traits
89
object is stored in the decorator and made accessible through
90
the get_traits() method.
91
*/
92
#define IMP_DECORATOR_WITH_TRAITS(Name, Parent, TraitsType, traits_name, \
93
default_traits) \
94
private: \
95
TraitsType traits_; \
96
public: \
97
IMP_NO_DOXYGEN(typedef Parent ParentDecorator); \
98
Name(){} \
99
Name(Model *m, ParticleIndex id, const TraitsType &tr): Parent(m, id), \
100
traits_(tr) { \
101
IMP_INTERNAL_CHECK(particle_is_instance(m->get_particle(id), tr), \
102
"Particle " << m->get_particle(id)->get_name() \
103
<< " missing required attributes for decorator " \
104
<< #Name << "\n" << Showable(m->get_particle(id))); \
105
} \
106
Name(const TraitsType &tr): \
107
traits_(tr) {} \
108
explicit Name(::IMP::kernel::Particle *p, \
109
const TraitsType &tr=default_traits): \
110
Parent(p), traits_(tr) { \
111
IMP_INTERNAL_CHECK(particle_is_instance(p, tr), \
112
"Particle " << p->get_name() \
113
<< " missing required attributes " \
114
<< " for decorator " \
115
<< #Name << "\n" << Showable(p)); \
116
} \
117
static Name decorate_particle(::IMP::kernel::Particle *p, \
118
const TraitsType &tr=default_traits) { \
119
if (!particle_is_instance(p, tr)) return Name(); \
120
else return Name(p, tr); \
121
} \
122
IMP_SHOWABLE(Name); \
123
const TraitsType &get_##traits_name() const { \
124
return get_decorator_traits(); \
125
} \
126
typedef Parent DecoratorTraitsBase; \
127
typedef TraitsType DecoratorTraits; \
128
const DecoratorTraits& get_decorator_traits() const {return traits_;} \
129
static const DecoratorTraits& get_default_decorator_traits() { \
130
static TraitsType dt= default_traits; \
131
return dt; \
132
} \
133
IMP_NO_DOXYGEN(typedef boost::true_type DecoratorHasTraits)
134
135
136
//! Perform actions dependent on whether a particle has an attribute.
137
/** A common pattern is to check if a particle has a particular attribute,
138
do one thing if it does and another if it does not. This macro implements
139
that pattern. It requires that the method get_particle() return the
140
particle being used.
141
142
\param[in] AttributeKey The key for the attribute
143
\param[in] Type The type for the attribute ("Int", "Float", "String")
144
\param[in] has_action The action to take if the Particle has the attribute.
145
The attribute value is stored in the variable VALUE.
146
\param[in] not_has_action The action to take if the Particle does not have
147
the attribute.
148
\see IMP_DECORATOR_GET()
149
\see IMP_DECORATOR_GET_SET()
150
151
*/
152
#define IMP_DECORATOR_GET(AttributeKey, Type, has_action, not_has_action) \
153
do { \
154
if (get_model()->get_has_attribute(AttributeKey, get_particle_index())) { \
155
Type VALUE = get_model()->get_attribute(AttributeKey, \
156
get_particle_index()); \
157
has_action; \
158
} else { \
159
not_has_action; \
160
} \
161
} while (false)
162
163
164
165
//! Set an attribute, creating it if it does not already exist.
166
/** Another common pattern is to have an assumed value if the attribute
167
is not there. Then, you sometimes need to set the value whether it
168
is there or not.
169
\see IMP_DECORATOR_GET()
170
\see IMP_DECORATOR_GET_SET()
171
*/
172
#define IMP_DECORATOR_SET(AttributeKey, value) \
173
do { \
174
if (get_model()->get_has_attribute(AttributeKey, \
175
get_particle_index())) { \
176
get_model()->set_attribute(AttributeKey, \
177
get_particle_index(), \
178
value); \
179
} else { \
180
get_model()->add_attribute(AttributeKey, \
181
get_particle_index(), \
182
value); \
183
} \
184
} while (false)
185
186
187
//! Define methods for getting and setting a particular simple field
188
/** This macro defines methods to get and set a particular attribute.
189
190
\param[in] name The lower case name of the attribute
191
\param[in] AttributeKey The AttributeKey object controlling
192
the attribute.
193
\param[in] Type The type of the attribute (upper case).
194
\param[in] ReturnType The type to return from the get.
195
\see IMP_DECORATOR_GET()
196
\see IMP_DECORATOR_SET()
197
*/
198
#define IMP_DECORATOR_GET_SET(name, AttributeKey, Type, ReturnType) \
199
ReturnType get_##name() const { \
200
return static_cast<ReturnType>(get_model() \
201
->get_attribute(AttributeKey, \
202
get_particle_index())); \
203
} \
204
void set_##name(ReturnType t) { \
205
get_model()->set_attribute(AttributeKey, get_particle_index(), t); \
206
} \
207
IMP_REQUIRE_SEMICOLON_CLASS(getset##name)
208
209
210
//! Define methods for getting and setting an optional simple field.
211
/** See IMP_DECORATOR_GET_SET(). The difference is that here you can provide
212
a default value to use if the decorator does not have the attribute.
213
214
\param[in] name The lower case name of the attribute
215
\param[in] AttributeKey The expression to get the required attribute key.
216
\param[in] Type The type of the attribute (upper case).
217
\param[in] ReturnType The type to return from the get.
218
\param[in] default_value The value returned if the attribute is missing.
219
*/
220
#define IMP_DECORATOR_GET_SET_OPT(name, AttributeKey, Type, \
221
ReturnType, default_value) \
222
ReturnType get_##name() const { \
223
IMP_DECORATOR_GET(AttributeKey, Type, \
224
return static_cast<ReturnType>(VALUE), \
225
return default_value); \
226
} \
227
void set_##name(ReturnType t) { \
228
IMP_DECORATOR_SET(AttributeKey, t); \
229
} \
230
IMP_REQUIRE_SEMICOLON_CLASS(getset_##name)
231
232
233
#ifdef IMP_DOXYGEN
234
#define IMP_DECORATORS_DECL(Name, PluralName)
235
#define IMP_DECORATORS_DEF(Name, PluralName)
236
237
238
//! Define the types for storing sets of decorators
239
/** The macro defines the types PluralName and PluralNameTemp.
240
*/
241
#define IMP_DECORATORS(Name, PluralName, Parent)
242
243
#else
244
#define IMP_DECORATORS_DECL(Name, PluralName) \
245
class Name; \
246
typedef IMP::base::Vector<Name> PluralName
247
248
#define IMP_DECORATORS_DEF(Name, PluralName) \
249
/* needed so there is no ambiguity with operator->*/
\
250
inline std::ostream &operator<<(std::ostream &out, Name n) { \
251
n.show(out); \
252
return out; \
253
} \
254
255
256
#define IMP_DECORATORS(Name, PluralName, Parent) \
257
IMP_DECORATORS_DECL(Name, PluralName); \
258
IMP_DECORATORS_DEF(Name, PluralName)
259
260
#endif
261
262
#ifdef IMP_DOXYGEN
263
//! Define the types for storing sets of decorators
264
/** The macro defines the types PluralName and PluralNameTemp.
265
*/
266
#define IMP_DECORATORS_WITH_TRAITS(Name, PluralName, Parent)
267
268
#else
269
#define IMP_DECORATORS_WITH_TRAITS(Name, PluralName, Parent) \
270
/* needed so there is no ambiguity with operator->*/
\
271
inline std::ostream &operator<<(std::ostream &out, Name n) { \
272
n.show(out); \
273
return out; \
274
} \
275
typedef IMP::base::Vector<Name> PluralName
276
277
#endif
278
279
//! Create a decorator that computes some sort of summary info on a set
280
/** Examples include a centroid or a cover for a set of particles.
281
282
\param[in] Name The name for the decorator
283
\param[in] Parent the parent decorator type
284
\param[in] Members the way to pass a set of particles in
285
*/
286
#define IMP_SUMMARY_DECORATOR_DECL(Name, Parent, Members) \
287
class IMPCOREEXPORT Name: public Parent { \
288
IMP_CONSTRAINT_DECORATOR_DECL(Name); \
289
public: \
290
IMP_DECORATOR(Name, Parent); \
291
static Name setup_particle(Particle *p, \
292
const Members &members); \
293
static Name setup_particle(Particle *p, \
294
Refiner *ref); \
295
~Name(); \
296
static bool particle_is_instance(Particle *p) { \
297
return p->has_attribute(get_constraint_key()); \
298
} \
299
IMP_NO_DOXYGEN(typedef boost::false_type DecoratorHasTraits); \
300
private: \
301
/* hide set methods*/
\
302
void set_coordinates() {}; \
303
void set_coordinates_are_optimized()const{} \
304
void set_coordinate() const {} \
305
void set_radius()const{} \
306
}; \
307
IMP_DECORATORS(Name, Name##s, Parent##s)
308
309
310
/** See IMP_SUMMARY_DECORATOR_DECL()
311
\param[in] Name The name for the decorator
312
\param[in] Parent the parent decorator type
313
\param[in] Members the way to pass a set of particles in
314
\param[in] create_modifier the statements to create the modifier
315
which computes the summary info. It should be called mod.
316
*/
317
#define IMP_SUMMARY_DECORATOR_DEF(Name, Parent, Members, create_modifier) \
318
Name Name::setup_particle(Particle *p, const Members &ps) { \
319
Refiner *ref=new FixedRefiner(ps); \
320
create_modifier; \
321
if (!Parent::particle_is_instance(p)) Parent::setup_particle(p); \
322
set_constraint(mod, new DerivativesToRefined(ref), p); \
323
return Name(p); \
324
} \
325
Name Name::setup_particle(Particle *p, Refiner *ref) { \
326
create_modifier; \
327
if (!Parent::particle_is_instance(p)) Parent::setup_particle(p); \
328
set_constraint(mod, new DerivativesToRefined(ref), p); \
329
return Name(p); \
330
} \
331
Name::~Name(){} \
332
IMP_NO_DOXYGEN(void Name::show(std::ostream &out) const { \
333
out << #Name << " at " << static_cast<Parent>(*this); \
334
}) \
335
IMP_CONSTRAINT_DECORATOR_DEF(Name)
336
337
338
#endif
/* IMPKERNEL_DECORATOR_MACROS_H */