PDLx::MaskedData - Automatically synchronize data and valid data masks


  use 5.10.0;

  use PDLx::MaskedData;

  $data1 = PDLx::MaskedData->new( sequence(9) );
  say $data1;    # [0 1 2 3 4 5 6 7 8]

  # grab the mask
  $mask = $data1->mask;
  say $mask;    # [1 1 1 1 1 1 1 1 1]

  # create another masked piddle with the same mask
  my $pdl = $data1 + 1;

  $data2 = PDLx::MaskedData->new( $pdl, $mask );

  say $data2;    # [1 2 3 4 5 6 7 8 9]

  # update the mask
  $mask->set( 3, 0 );
  say $mask;     # [1 1 1 0 1 1 1 1 1]

  # and see it propagate
  say $data1;    # [0 1 2 0 4 5 6 7 8]
  say $data2;    # [1 2 3 0 5 6 7 8 9]

  # use bad values for $data1
  # notice that the invalid element is now bad
  say $data1;    # [0 1 2 BAD 4 5 6 7 8]

  # push invalid values upstream to the shared mask
  say $data1;    # [BAD 1 2 BAD 4 5 6 7 8]

  # see the mask change
  say $mask;     # [0 1 1 0 1 1 1 1 1]

  # and see the other piddle change
  say $data2;    # [0 2 3 0 5 6 7 8 9]


Typically PDL uses bad values to mark elements in a piddle which contain invalid data. When multiple piddles should have the same elements marked as invalid, a separate mask piddle (whose values are true for valid data and false otherwise) is often used.

PDLx::MaskedData (in concert with PDLx::Mask) simplifies the management of mutiple piddles sharing the same mask. PDLx::Mask is the shared mask, and PDLx::MaskedData is a specialized piddle which will dynamically respond to changes in the mask, so that they are always up-to-date.

Additionally, invalid elements in a data piddle may automatically be added to the shared mask, so that there is a consistent view of valid elements across all data piddles.


PDLx::MaskedData is a subclass of PDL which manages a masked piddle. It can be used directly as a piddle, but be careful not to change its contents inadvertently. It should only be manipulated via the provided methods or overloaded operators.

It maintains two views of the data:

  1. the original base data; and

  2. the effective data, which is the base data with an applied mask. The invalid data elements may either be set as bad values, or may be set to any other value (e.g. 0).


Methods specific to PDLx::MaskedData


  $data = PDLx::MaskedData->new( $base_data );
  $data = PDLx::MaskedData->new( $base_data, $mask );
  $data = PDLx::MaskedData->new( base => $base_data, %options );

Create a masked piddle using the passed data piddle as the base data. It does not copy the passed piddle.

An optional mask may be provided (see below for details). If not provided, one will be created. The newly created object will be subscribed to the mask object;


A data piddle. If the piddle has the bad data flag set, masked elements are set to the piddle's bad value. Otherwise masked elements are set to the value of the mask_value option.

mask => scalar | piddle | PDLx::Mask object

An optional initial mask. If it is a piddle, it will be used as a base mask for a new PDLx::Mask object; it will not be copied. If not specified, all data elements are valid.

mask_value => scalar

If the piddle's bad flag is not set, this specifies the value of invalid elements in the effective data. It defaults to 0.

apply_mask => boolean

If true, the mask is applied to the data. This defaults to true. See "EXAMPLES/Secondary Masks" in PDlx::Mask for an application.

data_mask => boolean

If true, any invalid elements in the base data are replicated in the mask. It defaults to false.


  $base = $data->base;

This returns the base data. Don't alter the returned piddle!


  $pdl = $data->data;
  $pdl = $data->data( $new_data );

Return the effective data, optionally altering the base data. Don't alter the returned piddle!

If passed a piddle, it is copied to the base data and the update method is called.

Note that the $data object can also be used directly without calling this method.


  $mask = $data->mask;

This returns the mask as a PDLx::Mask object.

  $data->mask( $new_mask );

This replaces the mask, detaching $data from the previous mask object. To instead alter the mask object, use the mask object's methods, e.g.:

  $data->mask->mask( $new_mask );


  $nvalid_elements = $data->nvalid;

The number of valid elements in the effective data. This is lazily evaluated and cached.



Update the effective data. This should never be required by user code.

If $data->data_mask is true, $data->mask->update is called, otherwise the result of applying the mask to the base data is stored as the effective data.



Subscribe to $data's mask. Usually this is not necessary; see "EXAMPLES/Intermittant Secondary Masks" in PDLx-Mask for why this might be useful.


  $data->unsubscribe( %options );

Subscribe to $data's mask. Usually this is not necessary; see "EXAMPLES/Intermittant Secondary Masks" in PDLx-Mask for why this might be useful.


reset_data_storage => boolean

If true (the default), memory used to store the effective data is reclaimed if possible. If $data will be resubscribed to a mask, it's more efficient to not perform this step.


  $bool = $data->is_subscribed;

Returns true if $data is subscribed to its mask.

Overridden methods


  $pdl = $data->copy;

Returns a copy of the effective data as an ordinary piddle.


This is a fatal operation.


This is a fatal operation if the passed value is non-zero.


   $data->set( $pos, $value);

This updates the base data at position $pos to $value and invokes the update method.


   $data->setbadat( $pos );

This sets the base data at position $pos to the bad value and invokes the update method.



This is a lazily evaluated and cached version of the PDL dsum method.


Please report any bugs or feature requests to, or through the web interface at



Version 0.01


Copyright (c) 2016 The Smithsonian Astrophysical Observatory

PDLx::MaskedData is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <>.


Diab Jerius <>