To elaborate further on my proposal from last night, a particle bundle would look like the following (incorporating some unrelated proposed changes)
class XYZBundle { static FloatKey kx_, ky_, kz_; public: XYZBundle(Particle*p): p_(p){} static bool is_instance(Particle *p) { return p->has_attribute(kx_) && p->has_attribute(ky_) && p- >has_attribute(kz_); } typedef std::auto_ptr<XYZBundle> Pointer; Pointer cast(Pointer *p) { if (!is_instance(p)) return Pointer(); else return Pointer(new XYZBundle(p)); }
// either static XYZBundle::Pointer initialize(Particle *p) { p->add_attribute(kx_, 0); p->add_attribute(ky_, 0); p->add_attribute(kz_, 0); return Pointer(new XYZBundle(p)); } // or static XYZBundle::Pointer initialize(Particle *p, Float x, Float y, Float z) { p->add_attribute(kx_, x); p->add_attribute(ky_, y); p->add_attribute(kz_, z); return Pointer(new XYZBundle(p)); } Float get_x() const { return p->get_attribute(kx_); } void set_x(Float x) const { return p->set_attribute(kx_, x); } // etc };
The user class XYZBundle::Pointer xyzp= XYZBundle::initialize(p) to add the right fields or XYZBundle::Pointer xyzp= XYZBundle::cast(p) to use.
I am a bit uncomfortable about the faking aspect of the design especially without working reference counting. Since Bundles don't need to get passed back and forth from python, we could make the reference counting work. It might be better to just allocate Bundles on the stack. This removes a memory management issue at the cost of eliminating the possibility of using a NULL pointer to signify failure. So things would have to look more like
class XYZBundle { static FloatKey kx_, ky_, kz_; public: XYZBundle(Particle*p): p_(p){if (!is_instance(p)) p_=NULL;}
bool get_is_valid() const {return p_ != NULL;}
static bool is_instance(Particle *p) { return p->has_attribute(kx_) && p->has_attribute(ky_) && p- >has_attribute(kz_); }
// either static XYZBundle initialize(Particle *p) { IMP_assert(!is_instance(p)); p->add_attribute(kx_, 0); p->add_attribute(ky_, 0); p->add_attribute(kz_, 0); return XYZBundle(p); } // or static XYZBundle::Pointer initialize(Particle *p, Float x, Float y, Float z) { IMP_assert(!is_instance(p)); p->add_attribute(kx_, x); p->add_attribute(ky_, y); p->add_attribute(kz_, z); return XYZBundle(p); } Float get_x() const { return p->get_attribute(kx_); } void set_x(Float x) const { return p->set_attribute(kx_, x); } // etc };
the the user calls XYZBundle xyzb(p); and xyzb.is_valid() to manipulate a Particle and XYZBundle xyzb= XYZBundle::initialize(p); to initialize.
They should be called decorators, not bundles. Here is a cleaned version.
class XYZDecorator { static FloatKey kx_, ky_, kz_; public: XYZDecorator(Particle*p): p_(p){}
bool get_is_initialized() { return p_->has_attribute(kx_) && p_->has_attribute(ky_) && p_- >has_attribute(kz_); }
static XYZDecorator::Pointer initialize(Float x=nan, Float y=nan, Float z=nan) { IMP_assert(!is_instance(p_)); p_->add_attribute(kx_, x); p_->add_attribute(ky_, y); p_->add_attribute(kz_, z); }
Float get_x() const { return p_->get_attribute(kx_); }
void set_x(Float x) const { return p_->set_attribute(kx_, x); } // etc };
the user calls XYZDecorator xyz(p); then p.initialize(1,2,3); if needed p.get_x(); etc.
Daniel Russel wrote: > To elaborate further on my proposal from last night, a particle > bundle would look like the following (incorporating some unrelated > proposed changes) > > class XYZBundle { > static FloatKey kx_, ky_, kz_; > public: > XYZBundle(Particle*p): p_(p){} > static bool is_instance(Particle *p) { > return p->has_attribute(kx_) && p->has_attribute(ky_) && p- > >has_attribute(kz_); > } > typedef std::auto_ptr<XYZBundle> Pointer; > > Pointer cast(Pointer *p) { > if (!is_instance(p)) return Pointer(); > else return Pointer(new XYZBundle(p)); > } > > // either > static XYZBundle::Pointer initialize(Particle *p) { > p->add_attribute(kx_, 0); > p->add_attribute(ky_, 0); > p->add_attribute(kz_, 0); > return Pointer(new XYZBundle(p)); > } > // or > static XYZBundle::Pointer initialize(Particle *p, Float x, Float y, > Float z) { > p->add_attribute(kx_, x); > p->add_attribute(ky_, y); > p->add_attribute(kz_, z); > return Pointer(new XYZBundle(p)); > } > Float get_x() const { > return p->get_attribute(kx_); > } > void set_x(Float x) const { > return p->set_attribute(kx_, x); > } > // etc > }; > > The user class > XYZBundle::Pointer xyzp= XYZBundle::initialize(p) to add the right > fields > or > XYZBundle::Pointer xyzp= XYZBundle::cast(p) to use. > > I am a bit uncomfortable about the faking aspect of the design > especially without working reference counting. Since Bundles don't > need to get passed back and forth from python, we could make the > reference counting work. It might be better to just allocate Bundles > on the stack. This removes a memory management issue at the cost of > eliminating the possibility of using a NULL pointer to signify > failure. So things would have to look more like > > class XYZBundle { > static FloatKey kx_, ky_, kz_; > public: > XYZBundle(Particle*p): p_(p){if (!is_instance(p)) p_=NULL;} > > bool get_is_valid() const {return p_ != NULL;} > > static bool is_instance(Particle *p) { > return p->has_attribute(kx_) && p->has_attribute(ky_) && p- > >has_attribute(kz_); > } > > // either > static XYZBundle initialize(Particle *p) { > IMP_assert(!is_instance(p)); > p->add_attribute(kx_, 0); > p->add_attribute(ky_, 0); > p->add_attribute(kz_, 0); > return XYZBundle(p); > } > // or > static XYZBundle::Pointer initialize(Particle *p, Float x, Float y, > Float z) { > IMP_assert(!is_instance(p)); > p->add_attribute(kx_, x); > p->add_attribute(ky_, y); > p->add_attribute(kz_, z); > return XYZBundle(p); > } > Float get_x() const { > return p->get_attribute(kx_); > } > void set_x(Float x) const { > return p->set_attribute(kx_, x); > } > // etc > }; > > the the user calls > XYZBundle xyzb(p); and xyzb.is_valid() to manipulate a Particle > and > XYZBundle xyzb= XYZBundle::initialize(p); to initialize. > > > > _______________________________________________ > IMP-dev mailing list > IMP-dev@salilab.org > https://salilab.org/mailman/listinfo/imp-dev >
participants (1)
-
Daniel Russel