casa
$Rev:20696$
|
00001 //# MaskedLattice.h: Abstract base class for array-like classes with masks 00002 //# Copyright (C) 1998,1999,2000 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: MaskedLattice.h 20739 2009-09-29 01:15:15Z Malte.Marquarding $ 00027 00028 #ifndef LATTICES_MASKEDLATTICE_H 00029 #define LATTICES_MASKEDLATTICE_H 00030 00031 00032 //# Includes 00033 #include <lattices/Lattices/Lattice.h> 00034 00035 namespace casa { //# NAMESPACE CASA - BEGIN 00036 00037 //# Forward Declarations 00038 class LatticeRegion; 00039 00040 00041 // <summary> 00042 // A templated, abstract base class for array-like objects with masks. 00043 // </summary> 00044 00045 // <use visibility=export> 00046 00047 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="dLattice.cc"> 00048 // </reviewed> 00049 00050 // <prerequisite> 00051 // <li> <linkto class="IPosition"> IPosition </linkto> 00052 // <li> Abstract Base class Inheritance - try "Advanced C++" by James 00053 // O. Coplien, Ch. 5. 00054 // </prerequisite> 00055 00056 // <etymology> 00057 // Lattice: "A regular, periodic configuration of points, particles, 00058 // or objects, throughout an area of a space..." (American Heritage Directory) 00059 // This definition matches our own: an n-dimensional arrangement of items, 00060 // on regular orthogonal axes. 00061 // </etymology> 00062 00063 // <synopsis> 00064 // This pure abstract base class defines the operations which may be performed 00065 // on any concrete class derived from it. It has only a few non-pure virtual 00066 // member functions. 00067 // The fundamental contribution of this class, therefore, is that it 00068 // defines the operations derived classes must provide: 00069 // <ul> 00070 // <li> how to extract a "slice" (or sub-array, or subsection) from 00071 // a Lattice. 00072 // <li> how to copy a slice in. 00073 // <li> how to get and put a single element 00074 // <li> how to apply a function to all elements 00075 // <li> various shape related functions. 00076 // </ul> 00077 // <note role=tip> Lattices are always zero origined. </note> 00078 // </synopsis> 00079 00080 // <example> 00081 // Because Lattice is an abstract base class, an actual instance of this 00082 // class cannot be constructed. However the interface it defines can be used 00083 // inside a function. This is always recommended as it allows Functions 00084 // which have Lattices as arguments to work for any derived class. 00085 // 00086 // I will give a few examples here and then refer the reader to the 00087 // <linkto class="ArrayLattice">ArrayLattice</linkto> class (a memory resident 00088 // Lattice) and the <linkto class="PagedArray">PagedArray</linkto> class (a 00089 // disk based Lattice) which contain further examples with concrete 00090 // classes (rather than an abstract one). All the examples shown below are used 00091 // in the <src>dLattice.cc</src> demo program. 00092 // 00093 // <h4>Example 1:</h4> 00094 // This example calculates the mean of the Lattice. Because Lattices can be too 00095 // large to fit into physical memory it is not good enough to simply use 00096 // <src>getSlice</src> to read all the elements into an Array. Instead the 00097 // Lattice is accessed in chunks which can fit into memory (the size is 00098 // determined by the <src>maxPixels</src> and <src>niceCursorShape</src> 00099 // functions). The <src>LatticeIterator::cursor()</src> function then returns 00100 // each of these chunks as an Array and the standard Array based functions are 00101 // used to calculate the mean on each of these chunks. Functions like this one 00102 // are the recommended way to access Lattices as the 00103 // <linkto class="LatticeIterator">LatticeIterator</linkto> will correctly 00104 // setup any required caches. 00105 // 00106 // <srcblock> 00107 // Complex latMean(const Lattice<Complex>& lat) { 00108 // const uInt cursorSize = lat.advisedMaxPixels(); 00109 // const IPosition cursorShape = lat.niceCursorShape(cursorSize); 00110 // const IPosition latticeShape = lat.shape(); 00111 // Complex currentSum = 0.0f; 00112 // size_t nPixels = 0; 00113 // RO_LatticeIterator<Complex> iter(lat, 00114 // LatticeStepper(latticeShape, cursorShape)); 00115 // for (iter.reset(); !iter.atEnd(); iter++){ 00116 // currentSum += sum(iter.cursor()); 00117 // nPixels += iter.cursor().nelements(); 00118 // } 00119 // return currentSum/nPixels; 00120 // } 00121 // </srcblock> 00122 // 00123 // <h4>Example 2:</h4> 00124 // Sometimes it will be neccesary to access slices of a Lattice in a nearly 00125 // random way. Often this can be done using the subSection commands in the 00126 // <linkto class="LatticeStepper">LatticeStepper</linkto> class. But it is also 00127 // possible to use the getSlice and putSlice functions. The following example 00128 // does a two-dimensional Real to Complex Fourier transform. This example is 00129 // restricted to four-dimensional Arrays (unlike the previous example) and does 00130 // not set up any caches (caching is currently only used with PagedArrays). So 00131 // only use getSlice and putSlice when things cannot be done using 00132 // LatticeIterators. 00133 // 00134 // <srcblock> 00135 // void FFT2DReal2Complex(Lattice<Complex>& result, 00136 // const Lattice<Float>& input){ 00137 // AlwaysAssert(input.ndim() == 4, AipsError); 00138 // const IPosition shape = input.shape(); 00139 // const uInt nx = shape(0); 00140 // AlwaysAssert (nx > 1, AipsError); 00141 // const uInt ny = shape(1); 00142 // AlwaysAssert (ny > 1, AipsError); 00143 // const uInt npol = shape(2); 00144 // const uInt nchan = shape(3); 00145 // const IPosition resultShape = result.shape(); 00146 // AlwaysAssert(resultShape.nelements() == 4, AipsError); 00147 // AlwaysAssert(resultShape(3) == nchan, AipsError); 00148 // AlwaysAssert(resultShape(2) == npol, AipsError); 00149 // AlwaysAssert(resultShape(1) == ny, AipsError); 00150 // AlwaysAssert(resultShape(0) == nx/2 + 1, AipsError); 00151 // 00152 // const IPosition inputSliceShape(4,nx,ny,1,1); 00153 // const IPosition resultSliceShape(4,nx/2+1,ny,1,1); 00154 // COWPtr<Array<Float> > 00155 // inputArrPtr(new Array<Float>(inputSliceShape.nonDegenerate())); 00156 // Array<Complex> resultArray(resultSliceShape.nonDegenerate()); 00157 // FFTServer<Float, Complex> FFT2D(inputSliceShape.nonDegenerate()); 00158 // 00159 // IPosition start(4,0); 00160 // Bool isARef; 00161 // for (uInt c = 0; c < nchan; c++){ 00162 // for (uInt p = 0; p < npol; p++){ 00163 // isARef = input.getSlice(inputArrPtr, 00164 // Slicer(start,inputSliceShape), True); 00165 // FFT2D.fft(resultArray, *inputArrPtr); 00166 // result.putSlice(resultArray, start); 00167 // start(2) += 1; 00168 // } 00169 // start(2) = 0; 00170 // start(3) += 1; 00171 // } 00172 // } 00173 // </srcblock> 00174 // 00175 // <h4>Example 3:</h4> 00176 // Occasionally you may want to access a few elements of a Lattice without 00177 // all the difficulty involved in setting up Iterators or calling getSlice 00178 // and putSlice. This is demonstrated in the example below and uses the 00179 // parenthesis operator, along with the LatticeValueRef companion 00180 // class. Using these functions to access many elements of a Lattice is not 00181 // recommended as this is the slowest access method. 00182 // 00183 // In this example an ideal point spread function will be inserted into an 00184 // empty Lattice. As with the previous examples all the action occurs 00185 // inside a function because Lattice is an interface (abstract) class. 00186 // 00187 // <srcblock> 00188 // void makePsf(Lattice<Float>& psf) { 00189 // const IPosition centrePos = psf.shape()/2; 00190 // psf.set(0.0f); // this sets all the elements to zero 00191 // // As it uses a LatticeIterator it is efficient 00192 // psf(centrePos) = 1; // This sets just the centre element to one 00193 // AlwaysAssert(near(psf(centrePos), 1.0f, 1E-6), AipsError); 00194 // AlwaysAssert(near(psf(centrePos*0), 0.0f, 1E-6), AipsError); 00195 // } 00196 // </srcblock> 00197 // </example> 00198 00199 // <motivation> 00200 // Creating an abstract base class which provides a common interface between 00201 // memory and disk based arrays has a number of advantages. 00202 // <ul> 00203 // <li> It allows functions common to all arrays to be written independent 00204 // of the way the data is stored. This is illustrated in the three examples 00205 // above. 00206 // <li> It reduces the learning curve for new users who only have to become 00207 // familiar with one interface (ie. Lattice) rather than distinct interfaces 00208 // for different array types. 00209 // </ul> 00210 // </motivation> 00211 00212 //# <todo asof="1996/07/01"> 00213 //# <li> 00214 //# </todo> 00215 00216 template <class T> class MaskedLattice : public Lattice<T> 00217 { 00218 //# Make members of parent class known. 00219 public: 00220 using Lattice<T>::ndim; 00221 using Lattice<T>::shape; 00222 00223 public: 00224 // Default constructor. 00225 MaskedLattice() 00226 : itsDefRegPtr(0) {;} 00227 00228 // Copy constructor. 00229 MaskedLattice (const MaskedLattice<T>&); 00230 00231 // a virtual destructor is needed so that it will use the actual destructor 00232 // in the derived class 00233 virtual ~MaskedLattice(); 00234 00235 // Make a copy of the object (reference semantics). 00236 // <group> 00237 virtual MaskedLattice<T>* cloneML() const = 0; 00238 virtual Lattice<T>* clone() const; 00239 // </group> 00240 00241 // Has the object really a mask? 00242 // The default implementation returns True if the MaskedLattice has 00243 // a region with a mask. 00244 virtual Bool isMasked() const; 00245 00246 // Does the lattice have a pixelmask? 00247 // The default implementation returns False. 00248 virtual Bool hasPixelMask() const; 00249 00250 // Get access to the pixelmask. 00251 // An exception is thrown if the lattice does not have a pixelmask. 00252 // <group> 00253 virtual const Lattice<Bool>& pixelMask() const; 00254 virtual Lattice<Bool>& pixelMask(); 00255 // </group> 00256 00257 // Get the region used. 00258 // This is in principle the region pointed to by <src>getRegionPtr</src>. 00259 // However, if that pointer is 0, it returns a LatticeRegion for the 00260 // full image. 00261 const LatticeRegion& region() const; 00262 00263 // Get the mask or a slice from the mask. 00264 // This is the mask formed by combination of the possible pixelmask of the 00265 // lattice and the possible mask of the region taken from the lattice. 00266 // If there is no mask, it still works fine. 00267 // In that case it sizes the buffer correctly and sets it to True. 00268 // <group> 00269 Bool getMask (COWPtr<Array<Bool> >& buffer, 00270 Bool removeDegenerateAxes=False) const; 00271 Bool getMaskSlice (COWPtr<Array<Bool> >& buffer, const Slicer& section, 00272 Bool removeDegenerateAxes=False) const; 00273 Bool getMaskSlice (COWPtr<Array<Bool> >& buffer, const IPosition& start, 00274 const IPosition& shape, 00275 Bool removeDegenerateAxes=False) const; 00276 Bool getMaskSlice (COWPtr<Array<Bool> >& buffer, const IPosition& start, 00277 const IPosition& shape, const IPosition& stride, 00278 Bool removeDegenerateAxes=False) const; 00279 Bool getMask (Array<Bool>& buffer, 00280 Bool removeDegenerateAxes=False); 00281 Bool getMaskSlice (Array<Bool>& buffer, const Slicer& section, 00282 Bool removeDegenerateAxes=False); 00283 Bool getMaskSlice (Array<Bool>& buffer, const IPosition& start, 00284 const IPosition& shape, 00285 Bool removeDegenerateAxes=False); 00286 Bool getMaskSlice (Array<Bool>& buffer, const IPosition& start, 00287 const IPosition& shape, const IPosition& stride, 00288 Bool removeDegenerateAxes=False); 00289 Array<Bool> getMask (Bool removeDegenerateAxes=False) const; 00290 Array<Bool> getMaskSlice (const Slicer& section, 00291 Bool removeDegenerateAxes=False) const; 00292 Array<Bool> getMaskSlice (const IPosition& start, 00293 const IPosition& shape, 00294 Bool removeDegenerateAxes=False) const; 00295 Array<Bool> getMaskSlice (const IPosition& start, 00296 const IPosition& shape, const IPosition& stride, 00297 Bool removeDegenerateAxes=False) const; 00298 // </group> 00299 00300 // The function (in the derived classes) doing the actual work. 00301 // These functions are public, so they can be used internally in the 00302 // various Lattice classes. 00303 // <br>However, doGetMaskSlice does not call Slicer::inferShapeFromSource 00304 // to fill in possible unspecified section values. Therefore one 00305 // should normally use one of the getMask(Slice) functions. doGetMaskSlice 00306 // should be used with care and only when performance is an issue. 00307 // <br>The default implementation gets the mask from the region 00308 // and fills the buffer with True values if there is no region. 00309 virtual Bool doGetMaskSlice (Array<Bool>& buffer, const Slicer& section); 00310 00311 protected: 00312 // Assignment can only be used by derived classes. 00313 MaskedLattice<T>& operator= (const MaskedLattice<T>&); 00314 00315 // Get a pointer to the region used. 00316 // It can return 0 meaning that the MaskedLattice is the full lattice. 00317 virtual const LatticeRegion* getRegionPtr() const = 0; 00318 00319 private: 00320 mutable LatticeRegion* itsDefRegPtr; 00321 }; 00322 00323 00324 00325 } //# NAMESPACE CASA - END 00326 00327 #ifndef CASACORE_NO_AUTO_TEMPLATES 00328 #include <lattices/Lattices/MaskedLattice.tcc> 00329 #endif //# CASACORE_NO_AUTO_TEMPLATES 00330 #endif