//# MaskedArray.h: A templated N-D masked array class with zero origin.
//# Copyright (C) 1993,1994,1995,1996,1997,1999,2000,2005
//# Associated Universities, Inc. Washington DC, USA.
//#
//# This library is free software; you can redistribute it and/or modify it
//# under the terms of the GNU Library General Public License as published by
//# the Free Software Foundation; either version 2 of the License, or (at your
//# option) any later version.
//#
//# This library 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 Library General Public
//# License for more details.
//#
//# You should have received a copy of the GNU Library General Public License
//# along with this library; if not, write to the Free Software Foundation,
//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
//#
//# Correspondence concerning AIPS++ should be addressed as follows:
//# Internet email: aips2-request@nrao.edu.
//# Postal address: AIPS++ Project Office
//# National Radio Astronomy Observatory
//# 520 Edgemont Road
//# Charlottesville, VA 22903-2475 USA
//#
//# $Id$
#ifndef CASA_MASKEDARRAY2_H
#define CASA_MASKEDARRAY2_H
//# Includes
#include "ArrayLogical.h"
#include "ArrayFwd.h"
#include "IPosition.h"
#include "MaskLogiArrFwd.h"
namespace casacore { //# NAMESPACE CASACORE - BEGIN
//# Forward declarations
//#
//# Array.h cannot be included in this header file. Anything needed
//# from it must be forwarded. This is why LogicalArrayFwd.h is
//# included instead of LogicalArray.h .
//#
class Slicer;
// Class for masking an Array for operations on that Array.
//
//
//
//
// Array
// LogicalArray
//
//
//
// MaskedArray is a class for masking elements of an Array while performing
// operations on that Array.
//
//
//
// A MaskedArray is an association between an Array and a mask. The mask
// selects elements of the Array. Only elements of the Array where the
// corresponding element of the mask is true are defined. Thus, operations
// on a MaskedArray only operate on those elements of the Array where the
// corresponding element of the mask is true.
//
// A MaskedArray should be thought of as a manipulator for an Array, analogous
// to an iterator. It allows one to perform whole Array operations on selected
// elements of the Array.
//
// The mask used in the constructor for the MaskedArray must conform to
// the Array, thus have the same shape.
// The internal mask is (will be) copy constructed with reference semantics
// from the input mask. Therefore, it is (will be) possible to change the
// internal mask by changing values in the input mask *after* the MaskedArray
// has been constructed. To ensure that the internal mask is independent of
// the input mask after construction, use mask.copy() as the input argument.
//
// One can explicitly construct a MaskedArray from an Array and a mask or
// a MaskedArray and a mask. One can also use operator() on an Array or
// a MaskedArray to implicitly create a MaskedArray.
//
// One can create a MaskedArray from a MaskedArray and a mask. The resulting
// MaskedArray has as its Array the Array from the original MaskedArray.
// The mask for the resulting MaskedArray is the AND of the mask from the
// original MaskedArray and the input mask.
//
// Any operation involving a MaskedArray or a set of MaskedArrays is only
// performed for those elements where the AND of the masks is true.
//
// Any operation involving a MaskedArray or a set of MaskedArrays results
// in a MaskedArray whose mask is the AND of the masks of the original
// MaskedArrays. The only exception to this is assignment, where the
// mask determines which elements of the underlying Array are assigned.
//
// Masks, which are LogicalArrays, can be constructed by logical operations
// involving Arrays. They can also, of course, be constructed by individually
// setting individual elements of an LogicalArray.
//
// MaskedArrays constructed directly from Arrays are by default writeable.
// MaskedArrays constructed indirectly from Arrays by operator()
// are writeable if the Array is non-const and are readonly if the
// Array is const.
// MaskedArrays constructed from other MaskedArrays, either directly by
// constructors or indirectly by operator(), are by default
// writeable if the input MaskedArray is writeable, and readonly if the
// input MaskedArray is readonly.
//
// A given MaskedArray can be set to be readonly. One specifies
// this in the constructor with the bool argument isreadonly,
// or calls the setReadOnly() member function.
// A MaskedArray which would default to be readonly cannot be forced to
// be writeable. It will remain readonly even if the bool argument
// isreadonly is set to be false.
//
// The isReadOnly(), member function is used to test whether
// the MaskedArray is readonly.
//
// Member functions which change the MaskedArray test to see whether
// the MaskedArray is readonly, and throw an ArrayError exception if
// it is. These member functions are:
//
// - operator=()
//
- getRWArray()
//
- getRWArrayStorage()
//
- putArrayStorage()
//
//
// The copy() member function makes a deep copy of a MaskedArray.
// By default it returns a writeable MaskedArray, but the MaskedArray
// returned can be made readonly by using the bool argument "isreadonly"
// to copy() (or by calling setReadOnly() on the new MaskedArray).
//
// The valid elements of the MaskedArray can be manipulated as a
// "compressed" Array which contains only the valid elements.
// The number of elements in this "compressed" Array is the number of valid
// elements in the MaskedArray, nelementsValid().
// The "compressed" Array can have any shape which meets this requirement.
// The MaskedArray can have any shape.
//
// The getCompressedArray() member functions get a compressed
// Array from the valid members of the MaskedArray, while the
// setCompressedArray() member function sets the valid members
// of the MaskedArray from the input compressed Array.
//
// Many mathematical and logical global operators and functions which operate
// on MaskedArrays are defined. Typically, they are defined for all sensible
// combinations of MaskedArrays, Arrays, and scalars.
//
// Mathematical global operators and functions are defined in
// Arrays/MaskArrMath.h .
// The list is:
//
// - operator+= ()
//
- operator-= ()
//
- operator*= ()
//
- operator/= ()
//
- operator+ ()
//
- operator- ()
//
- operator* ()
//
- operator/ ()
//
- sin ()
//
- cos ()
//
- tan ()
//
- asin ()
//
- acos ()
//
- atan ()
//
- sinh ()
//
- cosh ()
//
- tanh ()
//
- exp ()
//
- log ()
//
- log10 ()
//
- sqrt ()
//
- abs ()
//
- fabs ()
//
- ceil ()
//
- floor ()
//
- atan2 ()
//
- fmod ()
//
- pow ()
//
- minMax ()
//
- min ()
//
- max ()
//
- indgen ()
//
- sum ()
//
- sumsquares ()
//
- product ()
//
- mean ()
//
- variance ()
//
- stddev ()
//
- avdev ()
//
- median ()
//
- square ()
//
- cube ()
//
//
// Logical global operators and functions are defined in
// Arrays/MaskArrLogi.h .
// The list is:
//
// - allLE ()
//
- allLT ()
//
- allGE ()
//
- allGT ()
//
- allEQ ()
//
- allNE ()
//
- allAND ()
//
- allOR ()
//
- anyLE ()
//
- anyLT ()
//
- anyGE ()
//
- anyGT ()
//
- anyEQ ()
//
- anyNE ()
//
- anyAND ()
//
- anyOR ()
//
- operator<= ()
//
- operator< ()
//
- operator>= ()
//
- operator< ()
//
- operator== ()
//
- operator!= ()
//
- operator&& ()
//
- operator|| ()
//
//
//
//
// Use an explicit MaskedArray to limit the maximum value of an Array.
//
//
// Vector arr (20);
// . . .
// MaskedArray marr (arr, (arr > 5));
// marr = 5;
//
//
// This sets all elements of arr which are greater than 5 to 5.
//
//
//
// Use an implicit MaskedArray to limit the minimum value of an Array.
//
//
// Vector arr (20);
// . . .
// arr (arr < 0) = 0;
//
//
// This sets all elements of arr which are less than 0 to 0.
//
//
//
// It does not matter where in an expression the MaskedArrays are located.
// The operation is only performed on those elements where the AND of the
// masks is true.
//
// The following expressions are all equivalent.
// The first (and second) expressions are the most efficient, since the sum
// is only performed for those elements where ((a > 0) && (b > 0)).
// The third example is less efficient, since the sum is performed for
// all elements of a and b, and then the assignment is only performed for
// those elements where ((a > 0) && (b > 0)).
//
//
// Vector arr (20);
// Vector a (20);
// Vector b (20);
// . . .
// arr = a(a > 0) + b(b > 0);
//
// arr = a(b > 0) + b(a > 0);
//
// arr ((a > 0) && (b > 0)) = a + b;
//
// arr = (a + b) ((a > 0) && (b > 0));
//
// arr (a > 0) = a + b(b > 0);
//
//
//
// All of these expressions set those elements of arr where
// ((a > 0) && (b > 0)) to a + b. Those elements of arr where the condition
// is false are unchanged.
//
//
//
// This example extracts the valid elements of the MaskedArray as a
// "compressed" Vector, manipulates this Vector, and then puts the result
// back into the MaskedArray.
//
//
// Matrix arr (20,5);
// . . .
// MaskedArray marr (arr, (arr>0) && (arr<10));
// Vector vec (marr.getCompressedArray());
// . . .
// marr.setCompressedArray (vec);
//
//
//
//
//
// A MaskedArray is an association between an Array and a LogicalArray which
// masks the Array. It allows one to perform whole Array manipulations
// with a single expression, selecting those elements of the Array to modify
// based either on a logical expression, typically involving some of the
// Arrays involved in the expression, or based on a specifically set mask.
//
//
//
masked_array_type operator()(const IPosition &start, const IPosition &end);
// Along the ith axis, every inc[i]'th element is chosen.
masked_array_type operator()(const IPosition &start, const IPosition &end,
const IPosition &inc);
//
// Get a reference to an array using a Slicer.
masked_array_type operator()(const Slicer&);
// Make a copy of the masked array.
//
// This is a deep copy. The Array and mask components of the returned
// MaskedArray are deep copies of the Array and mask in the input
// MaskedArray pointed to by this. In other words, the Array and mask
// in the output MaskedArray are completely independent of those in
// the input MaskedArray.
//
// By default, the MaskedArray returned is writeable. If
// isreadonly is true, then the MaskedArray
// returned is readonly.
//
//
masked_array_type copy(bool isreadonly) const;
masked_array_type copy() const;
//
// Return the internal Array.
const array_type & getArray() const;
// Return the internal Array, writeable.
//
//
// ArrayError
//
//
array_type & getRWArray() const;
// Return the (const) internal Mask.
const mask_type & getMask() const;
// The dimensionality of this masked array.
size_t ndim() const;
// The number of elements of this masked array.
// This is the number of elements in the underlying Array.
//
size_t nelements() const;
size_t size() const
{ return nelements(); }
//
// The number of valid elements of this masked array.
// This is the number of elements of the mask which are TRUE.
size_t nelementsValid() const;
// Check to see if the masked array is consistent. This is about the same
// thing as checking for invariants. If AIPS_DEBUG is defined, this is
// invoked after construction and on entry to most member functions.
bool ok() const;
// Are the shapes identical?
//
bool conform(const array_type &other) const;
bool conform(const masked_array_type &other) const;
//
// The length of each axis.
const IPosition& shape() const
{ return pArray->shape(); }
// Is the array read only?
bool isReadOnly() const
{ return isRO; }
// Set the array to be read only.
void setReadOnly() const;
// Copy the values in inarray to this, only copying those elements
// for which the corresponding mask element is true.
//
// ArrayConformanceError
// ArrayError
//
// TODO rename, see copy assignment operator.
masked_array_type &operator=(const array_type &inarray);
masked_array_type &operator=(array_type&& inarray);
// Copies/moves the values in other to this, only copying those elements
// for which the logical AND of the corresponding mask elements
// of both MaskedArrays is true.
//
//
// ArrayConformanceError
// ArrayError
//
//
//
// TODO this should be renamed: assignment operator should make
// obervable state equal, which should thus include getArray().
masked_array_type &operator=(const masked_array_type &other);
masked_array_type &operator=(masked_array_type&& other);
//
// Set every element of this array to "value", only setting those elements
// for which the corresponding mask element is true.
// In other words, a scalar behaves as if it were a constant conformant
// array.
//
//
// ArrayError
//
//
masked_array_type &operator=(const T &value);
// Return a "compressed" Array containing only the valid
// elements of the MaskedArray. The number of elements in the
// Array will be nelementsValid() for the
// MaskedArray. The MaskedArray can have any shape.
//
// The returned Array will have dimension one.
Array getCompressedArray () const;
// The returned Array will have the input shape. This shape must
// give the returned Array the required number of elements.
//
//
// ArrayError
//
//
Array getCompressedArray (const IPosition & shape) const;
//
// Fill the argument "compressed" Array with only the
// valid elements of the MaskedArray. The size of the
// Array must be nelementsValid() for the MaskedArray.
// The Array can have any shape which meets this requirement.
// The MaskedArray can have any shape.
//
//
// ArrayError
//
//
void getCompressedArray (array_type & inarr) const;
// Set only the valid elements of the MaskedArray from the argument
// "compressed" Array. The size of the
// Array must be nelementsValid() for the MaskedArray.
// The Array can have any shape which meets this requirement.
// The MaskedArray can have any shape.
//
//
// ArrayError
//
//
void setCompressedArray (const array_type& inarr);
// Manipulate the storage for the underlying Array.
// See the description of the corresponding Array functions
// for more information.
//
const T * getArrayStorage (bool &deleteIt) const;
//
//
// ArrayError
//
//
T * getRWArrayStorage (bool &deleteIt) const;
//
void freeArrayStorage(const T *&storage, bool deleteIt) const;
//
//
// ArrayError
//
//
void putArrayStorage(T *&storage, bool deleteAndCopy) const;
//
// Manipulate the storage for the underlying Mask.
// See the description of the corresponding Array functions
// for more information.
//
const LogicalArrayElem *getMaskStorage (bool &deleteIt) const;
//
void freeMaskStorage(const LogicalArrayElem *&storage, bool deleteIt) const;
//
protected:
// The array.
std::unique_ptr pArray;
// The mask.
std::unique_ptr pMask;
// Cache the number of valid elements.
size_t nelemValid;
// Is the number of valid elements cache OK?
// i.e. has it been calculated?
bool nelemValidIsOK;
// Is the array read only?
bool isRO;
};
// General global functions for MaskedArrays, and MaskedArrays and Arrays.
//
//
//
// Array
// LogicalArray
// MaskedArray
//
//
//
// These are generally useful global functions which operate on all
// MaskedArrays, or on MaskedArrays and Arrays.
//
//
//
// MaskedArray general global functions -- General global
// functions for MaskedArrays, and between MaskedArrays and Arrays.
//
//
//
// Test conformance for masked arrays and arrays of different types.
// Are the shapes identical?
//
//
//
template
bool conform2 (const MaskedArray &left, const Array &right);
template
bool conform2 (const Array &left, const MaskedArray &right);
template
bool conform2 (const MaskedArray &left, const MaskedArray &right);
//
//
//
} //# NAMESPACE CASACORE - END
#include "MaskedArray.tcc"
#endif