I've developed this into the modules PDLx::Mask and PDLx::MaskedData. For now, they're just up at github & bitbucket:
https://github.com/djerius/PDLx-Mask https://bitbucket.org/djerius/pdlx-mask See the end of the .pm files for complete docs. There's a dependency on https://github.com/djerius/PDLx-DetachedObject Comments appreciated. Diab On Tue, Oct 11, 2016 at 11:26 AM, Diab Jerius <djer...@cfa.harvard.edu> wrote: > Masking out elements of piddles is something that PDL has supported > for a long time via bad values. This works well if all operations > performed on the piddle respect bad values, and it doesn't quite > matter that you may be overwriting a value with the bad value (at > worst, you keep a copy of the original, unmasked piddle) > > One can also use an external mask (i.e. a boolean/byte piddle) and > use that to select elements to operate on. This works well when > there are multiple piddles which share the same mask, and you > don't want to alter the values in the masked piddles. > > There are some applications where the combination of approaches makes > sense: having an external mask which is used to set bad values in > copies of piddles. When the mask is changed, the piddles are updated > to reflect the changes in the mask. > > I've written and duplicated this code enough times that it's time to > come up with an abstraction to handle the machinations, and I'd like > to make sure that the design is properly reviewed.. > > There are two classes involved, the Mask class and the MaskedPiddle > class (all names are placedholders) with a publisher/subscriber > (pub/sub) relationship. > > The Mask class subclasses PDL, and "is" a boolean/byte piddle. It > should only be changed using the value() method (which installs a new > piddle) or the (overridden) set() or assign (.=, &=, |=, etc) methods. > When it is changed, it calls the update() method on all of the > MaskedPiddle objects which have been registered to it using its > subscribe() method. > > MaskedPiddle is also a subclass of PDL, and can have any type. When > created it is passed an existing data piddle and either an existing Mask > object or a mask piddle (which will be the basis for a Mask object > unique to the MaskedPiddle object). It will register with the Mask > object so it will receive updates. Updates will be effected by its > update() method, which uses the Mask object to set elements in a > *copy* of the data piddle to either the bad value or some other > specified value. The copy is what will be exposed to > PDL operations on the MaskedPiddle object. > > It, like Mask, should only be changed using the value() [which > installs a new piddle] or the (overridden) set() or .=/assign methods. > > There's a further wrinkle. If the piddle represented by a MaskedPiddle > object has existing bad values, they *may* be reflected in the Mask > that is registered with it, and will be propagated to all of the other > piddles registered with that Mask. Any changes in the badness of a > MaskedPiddle will be propagated through its registered Mask to the > other registered piddles as well. > > The Mask class keeps track of the (lazily evaluated) number of > elements, and the MaskedPiddle class keeps track of lazily evaluated > summary statistics (e.g., dsum, etc.) These will be invalidated when > Masks or MaskedPiddles are changed. > > This doesn't require any new machinery in PDL (other than a wished for > method of making piddles read only so that all of the piddles remain > synchronized). > > > Any thoughts on this approach or something I've missed? > > Thanks, > > Diab ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ pdl-devel mailing list pdl-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/pdl-devel