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

Reply via email to