00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef IMPCORE_HIERARCHY_H
00010 #define IMPCORE_HIERARCHY_H
00011
00012 #include "core_config.h"
00013 #include "internal/hierarchy_helpers.h"
00014 #include "internal/ArrayOnAttributesHelper.h"
00015
00016 #include <IMP/SingletonModifier.h>
00017 #include <IMP/Particle.h>
00018 #include <IMP/Model.h>
00019 #include <IMP/Decorator.h>
00020 #include <IMP/internal/PrefixStream.h>
00021
00022 #include <limits>
00023 #include <vector>
00024 #include <deque>
00025
00026 IMPCORE_BEGIN_NAMESPACE
00027
00028
00029
00030
00031
00032 #ifndef SWIG
00033 class Hierarchy;
00034 #endif
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 class IMPCOREEXPORT HierarchyTraits
00046 #ifndef SWIG
00047 : public internal::ArrayOnAttributesHelper<ParticleKey, Particle*,
00048 internal::HierarchyData>
00049 #endif
00050 {
00051 template <class HD>
00052 void clear_caches(HD d) {
00053 d.get_particle()->clear_caches();
00054 if (d.get_parent()) clear_caches(d.get_parent());
00055 }
00056 friend class Hierarchy;
00057 typedef internal::ArrayOnAttributesHelper<ParticleKey, Particle*,
00058 internal::HierarchyData> P;
00059
00060 template <class HD>
00061 void on_add(Particle * p, HD d, unsigned int i) {
00062 d.get_particle()->add_attribute(P::get_data().parent_key_, p);
00063 d.get_particle()->add_attribute(P::get_data().parent_index_key_, i);
00064 clear_caches(d);
00065 }
00066 void on_change(Particle *, Particle* p, unsigned int oi,
00067 unsigned int ni) {
00068 p->set_value(P::get_data().parent_index_key_, ni);
00069 }
00070 template <class HD>
00071 void on_remove(Particle *, HD d) {
00072 clear_caches(d);
00073 d.get_particle()->remove_attribute(P::get_data().parent_index_key_);
00074 d.get_particle()->remove_attribute(P::get_data().parent_key_);
00075 }
00076 template <class HD>
00077 Particle *get_value(HD d) const {
00078 return d.get_particle();
00079 }
00080 template <class HD>
00081 unsigned int get_index(Particle *, HD d) {
00082 return d.get_parent_index();
00083 }
00084
00085 using P::get_value;
00086
00087 template <class T>
00088 void audit_value(T t) const {
00089 IMP_USAGE_CHECK(t.get_traits().get_name() == get_name(),
00090 "Mixing hierarchies of type " << get_name()
00091 << " and type " << t.get_traits().get_name());
00092 }
00093
00094 const Hierarchy wrap(Particle* p) const;
00095
00096 public:
00097 HierarchyTraits(){}
00098
00099 HierarchyTraits(std::string name);
00100
00101 std::string get_name() const {
00102 return get_prefix();
00103 }
00104
00105 bool operator==(const HierarchyTraits &o) const {
00106 return get_name() == o.get_name();
00107 }
00108 };
00109
00110
00111 class Hierarchy;
00112
00113 #ifdef IMP_DOXYGEN
00114
00115
00116
00117
00118
00119 class GenericHierarchies: public GenericHierarchiesTemp {};
00120
00121
00122
00123
00124
00125
00126 class GenericHierarchiesTemp: public IMP::ParticlesTemp {};
00127
00128 #else
00129 typedef DecoratorsWithTraits<Hierarchy, Particles,
00130 HierarchyTraits> GenericHierarchies;
00131 typedef DecoratorsWithTraits<Hierarchy, ParticlesTemp, HierarchyTraits>
00132 GenericHierarchiesTemp;
00133 #endif
00134
00135
00136
00137
00138
00139
00140
00141
00142 class IMPCOREEXPORT Hierarchy: public Decorator
00143 {
00144 typedef Decorator P;
00145
00146 IMP_DECORATOR_ARRAY_DECL(public, Hierarchy, Child, child, children,
00147 traits_, Hierarchy, GenericHierarchies);
00148 public:
00149 IMP_DECORATOR_TRAITS(Hierarchy, Decorator,
00150 HierarchyTraits, traits,
00151 get_default_traits());
00152
00153
00154
00155 static Hierarchy setup_particle(Particle *p,
00156 HierarchyTraits traits
00157 =Hierarchy::get_default_traits()) {
00158 add_required_attributes_for_child(p, traits);
00159 return Hierarchy(p, traits);
00160 }
00161
00162
00163
00164
00165
00166 static Hierarchy setup_particle(Particle *p,
00167 const Particles &children,
00168 HierarchyTraits traits
00169 =Hierarchy::get_default_traits()) {
00170 add_required_attributes_for_child(p, traits);
00171 Hierarchy h(p, traits);
00172 for (unsigned int i=0; i< children.size(); ++i) {
00173 if (!Hierarchy::particle_is_instance(children[i], traits)) {
00174 add_required_attributes_for_child(children[i], traits);
00175 }
00176 Hierarchy c(children[i], traits);
00177 h.add_child(c);
00178 }
00179 return h;
00180 }
00181
00182
00183
00184 static bool particle_is_instance(Particle *p,
00185 HierarchyTraits traits
00186 =Hierarchy::get_default_traits()){
00187 return has_required_attributes_for_child(p, traits);
00188 }
00189 #if 0
00190
00191
00192 GenericHierarchiesTemp get_children() const {
00193 GenericHierarchiesTemp ps(get_number_of_children(), get_traits());
00194 for (unsigned int i=0; i< get_number_of_children(); ++i) {
00195 ps.set(i, get_child(i));
00196 }
00197 return ps;
00198 }
00199 #endif
00200
00201
00202
00203
00204 Hierarchy get_parent() const {
00205 IMP_DECORATOR_GET(traits_.get_data().parent_key_, Particle*,
00206 return This(VALUE, traits_),
00207 return This());
00208 }
00209
00210
00211
00212
00213
00214 int get_parent_index() const {
00215 IMP_DECORATOR_GET(traits_.get_data().parent_index_key_,
00216 Int, return VALUE, return -1);
00217 }
00218
00219
00220 bool has_parent() const {
00221 return get_particle()->has_attribute(traits_.get_data().parent_key_);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230 int get_child_index(Hierarchy c) const;
00231
00232 IMP_NO_DOXYGEN(void validate_node() const);
00233
00234 IMP_NO_DOXYGEN(void validate() const);
00235
00236
00237 static const HierarchyTraits& get_default_traits();
00238
00239 #ifndef IMP_DOXYGEN
00240 const ParticlesTemp& get_leaves() const;
00241 #endif
00242 };
00243
00244
00245 IMP_OUTPUT_OPERATOR(Hierarchy);
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 class IMPCOREEXPORT HierarchyVisitor
00256 {
00257 public:
00258 HierarchyVisitor() {}
00259
00260 virtual bool operator()(Hierarchy p) = 0;
00261 virtual ~HierarchyVisitor() {}
00262 };
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 class IMPCOREEXPORT ModifierVisitor: public HierarchyVisitor
00274 {
00275 IMP::internal::OwnerPointer<SingletonModifier> sm_;
00276 public:
00277 ModifierVisitor(SingletonModifier *sm): sm_(sm) {}
00278 virtual bool operator()(Hierarchy p) {
00279 sm_->apply(p.get_particle());
00280 return true;
00281 }
00282 virtual ~ModifierVisitor() {}
00283 };
00284
00285
00286
00287 #if !defined (SWIG) && !defined(IMP_DOXYGEN)
00288 namespace internal {
00289 template <class F, class Out>
00290 struct Gather: public HierarchyVisitor
00291 {
00292
00293 Gather(F f, Out out): f_(f), out_(out) {}
00294 bool operator()(Hierarchy p) {
00295 if (f_(p)) {
00296 *out_=p;
00297 ++out_;
00298 }
00299 return true;
00300 }
00301
00302 Out get_out() const {
00303 return out_;
00304 }
00305 private:
00306 F f_;
00307 Out out_;
00308 };
00309
00310 }
00311 #endif
00312
00313 inline const Hierarchy HierarchyTraits::wrap(Particle* p) const {
00314 return Hierarchy(p, *this);
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 template <class HD, class F>
00328 F breadth_first_traversal(HD d, F f)
00329 {
00330 std::deque<HD > stack;
00331 stack.push_back(d);
00332
00333 do {
00334 HD cur= stack.front();
00335 stack.pop_front();
00336 if (f(cur)) {
00337
00338 for (int i=cur.get_number_of_children()-1; i>=0; --i) {
00339 stack.push_back(cur.get_child(i));
00340 }
00341 }
00342 } while (!stack.empty());
00343 return f;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352 template <class HD, class F>
00353 F depth_first_traversal(HD d, F f)
00354 {
00355 std::vector<HD> stack;
00356 stack.push_back(d);
00357
00358 do {
00359 HD cur= stack.back();
00360 stack.pop_back();
00361 if (f(cur)) {
00362
00363 for (int i=cur.get_number_of_children()-1; i>=0; --i) {
00364 stack.push_back(cur.get_child(i));
00365 }
00366 }
00367 } while (!stack.empty());
00368 return f;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 template <class HD, class F>
00398 F breadth_first_traversal_with_data(HD d, F f, typename F::result_type i)
00399 {
00400 typedef std::pair<typename F::result_type, HD> DP;
00401 std::deque<DP > stack;
00402 stack.push_back(DP(i, d));
00403
00404 do {
00405 DP cur= stack.front();
00406 stack.pop_front();
00407 typename F::result_type r= f(cur.second.get_particle(), cur.first);
00408
00409 for (int i=cur.second.get_number_of_children()-1; i>=0; --i) {
00410 stack.push_back(std::make_pair(r, cur.second.get_child(i)));
00411 }
00412 } while (!stack.empty());
00413 return f;
00414 }
00415
00416
00417
00418
00419
00420
00421
00422 template <class HD, class F>
00423 F depth_first_traversal_with_data(HD d, F f, typename F::result_type i)
00424 {
00425 typedef std::pair<typename F::result_type, HD> DP;
00426 std::vector<DP> stack;
00427 stack.push_back(DP(i, d));
00428
00429 do {
00430 DP cur= stack.back();
00431 stack.pop_back();
00432 typename F::result_type r=f(cur.second, cur.first);
00433
00434 for (int i=cur.second.get_number_of_children()-1; i>=0; --i) {
00435 stack.push_back(DP(r, cur.second.get_child(i)));
00436 }
00437 } while (!stack.empty());
00438 return f;
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 template <class PD>
00450 struct HierarchyPrinter
00451 {
00452 private:
00453 struct RefCountedStream: public RefCounted,
00454 public IMP::internal::PrefixStream{
00455 RefCountedStream(std::ostream *out): IMP::internal::PrefixStream(out){}
00456 };
00457 mutable Pointer<RefCountedStream> out_;
00458 public:
00459 HierarchyPrinter(std::ostream &out,
00460 unsigned int max_depth):
00461 out_(new RefCountedStream(&out)),
00462 md_(max_depth)
00463 {}
00464
00465 typedef unsigned int result_type;
00466 int operator()(Hierarchy hd, unsigned int depth) const {
00467 if (depth > md_) return depth+1;
00468 std::string prefix;
00469 for (unsigned int i=0; i< depth; ++i) {
00470 prefix+=" ";
00471 }
00472 out_->set_prefix(prefix);
00473 if (hd == Hierarchy() || hd.get_number_of_children()==0) {
00474 *out_ << "-";
00475 } else {
00476 *out_ << "+";
00477 }
00478 *out_ << "Particle " << hd.get_particle()->get_name() << std::endl;
00479 out_->set_prefix(prefix+" ");
00480 PD nd= PD::decorate_particle(hd.get_particle());
00481 if (nd != PD()) {
00482 nd.show(*out_);
00483 } else {
00484 *out_ << "*******";
00485 }
00486 *out_ << std::endl;
00487 return depth+1;
00488 }
00489 unsigned int md_;
00490 };
00491
00492
00493
00494
00495
00496
00497
00498 template <class ND>
00499 std::ostream &show(Hierarchy h, std::ostream &out=std::cout,
00500 unsigned int max_depth
00501 = std::numeric_limits<unsigned int>::max())
00502 {
00503 depth_first_traversal_with_data(h, HierarchyPrinter<ND>(out, max_depth), 0);
00504 return out;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513 struct HierarchyCounter: public HierarchyVisitor
00514 {
00515 HierarchyCounter(): ct_(0) {}
00516
00517
00518 bool operator()(Hierarchy) {
00519 ++ct_;
00520 return true;
00521 }
00522
00523 unsigned int get_count() const {
00524 return ct_;
00525 }
00526 private:
00527
00528 unsigned int ct_;
00529 };
00530
00531
00532
00533
00534
00535 template <class Out, class F>
00536 Out gather(Hierarchy h, F f, Out out)
00537 {
00538 internal::Gather<F,Out> gather(f,out);
00539 depth_first_traversal(h, gather);
00540 return gather.get_out();
00541 }
00542
00543
00544
00545
00546
00547 template <class Out, class K, class V>
00548 Out gather_by_attribute(Hierarchy h, K k, V v, Out out)
00549 {
00550 internal::Gather<internal::MatchAttribute<K, V>,Out>
00551 gather(internal::MatchAttribute<K,V>(k,v),
00552 out);
00553 depth_first_traversal(h, gather);
00554 return gather.get_out();
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564 template <class Out, class K0, class V0, class K1, class V1>
00565 Out gather_by_attributes(Hierarchy h, K0 k0,
00566 V0 v0, K1 k1, V1 v1, Out out)
00567 {
00568 internal::Gather<internal::MatchAttributes<K0, V0, K1, V1>,Out>
00569 gather(internal::MatchAttributes<K0,V0, K1, V1>(k0,v0, k1, v1),
00570 out);
00571 depth_first_traversal(h, gather);
00572 return gather.get_out();
00573 }
00574
00575
00576
00577
00578
00579
00580 template <class HD, class F>
00581 HD breadth_first_find(HD h, F f)
00582 {
00583 if (f(h.get_particle())) return h;
00584 std::vector<HD> stack;
00585 stack.push_back(h);
00586
00587 do {
00588 HD cur= stack.back();
00589 stack.pop_back();
00590
00591 for (int i=cur.get_number_of_children()-1; i>=0; --i) {
00592 HD hd= cur.get_child(i);
00593 if (f(hd.get_particle())) {
00594 return hd;
00595 } else {
00596 stack.push_back(hd);
00597 }
00598 }
00599 } while (!stack.empty());
00600 return HD();
00601 }
00602
00603
00604
00605
00606
00607
00608 IMPCOREEXPORT GenericHierarchiesTemp
00609 get_leaves(Hierarchy mhd);
00610
00611
00612
00613
00614 IMPCOREEXPORT GenericHierarchiesTemp
00615 get_internal(Hierarchy mhd);
00616
00617
00618
00619
00620 IMPCOREEXPORT GenericHierarchiesTemp
00621 get_all_descendants(Hierarchy mhd);
00622
00623
00624
00625 inline Hierarchy get_root(Hierarchy h) {
00626 while (h.has_parent()) {
00627 h= h.get_parent();
00628 }
00629 return h;
00630 }
00631
00632 IMPCORE_END_NAMESPACE
00633
00634 #endif