//# 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