casacore
MaskedLattice.h
Go to the documentation of this file.
1//# MaskedLattice.h: Abstract base class for array-like classes with masks
2//# Copyright (C) 1998,1999,2000
3//# Associated Universities, Inc. Washington DC, USA.
4//#
5//# This library is free software; you can redistribute it and/or modify it
6//# under the terms of the GNU Library General Public License as published by
7//# the Free Software Foundation; either version 2 of the License, or (at your
8//# option) any later version.
9//#
10//# This library is distributed in the hope that it will be useful, but WITHOUT
11//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13//# License for more details.
14//#
15//# You should have received a copy of the GNU Library General Public License
16//# along with this library; if not, write to the Free Software Foundation,
17//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18//#
19//# Correspondence concerning AIPS++ should be addressed as follows:
20//# Internet email: aips2-request@nrao.edu.
21//# Postal address: AIPS++ Project Office
22//# National Radio Astronomy Observatory
23//# 520 Edgemont Road
24//# Charlottesville, VA 22903-2475 USA
25//#
26//# $Id$
27
28#ifndef LATTICES_MASKEDLATTICE_H
29#define LATTICES_MASKEDLATTICE_H
30
31
32//# Includes
33#include <casacore/casa/aips.h>
34#include <casacore/lattices/Lattices/Lattice.h>
35
36namespace casacore { //# NAMESPACE CASACORE - BEGIN
37
38//# Forward Declarations
39class LatticeRegion;
40
41
42// <summary>
43// A templated, abstract base class for array-like objects with masks.
44// </summary>
45
46// <use visibility=export>
47
48// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="dLattice.cc">
49// </reviewed>
50
51// <prerequisite>
52// <li> <linkto class="IPosition"> IPosition </linkto>
53// <li> Abstract Base class Inheritance - try "Advanced C++" by James
54// O. Coplien, Ch. 5.
55// </prerequisite>
56
57// <etymology>
58// Lattice: "A regular, periodic configuration of points, particles,
59// or objects, throughout an area of a space..." (American Heritage Directory)
60// This definition matches our own: an n-dimensional arrangement of items,
61// on regular orthogonal axes.
62// </etymology>
63
64// <synopsis>
65// This pure abstract base class defines the operations which may be performed
66// on any concrete class derived from it. It has only a few non-pure virtual
67// member functions.
68// The fundamental contribution of this class, therefore, is that it
69// defines the operations derived classes must provide:
70// <ul>
71// <li> how to extract a "slice" (or sub-array, or subsection) from
72// a Lattice.
73// <li> how to copy a slice in.
74// <li> how to get and put a single element
75// <li> how to apply a function to all elements
76// <li> various shape related functions.
77// </ul>
78// <note role=tip> Lattices are always zero origined. </note>
79// </synopsis>
80
81// <example>
82// Because Lattice is an abstract base class, an actual instance of this
83// class cannot be constructed. However the interface it defines can be used
84// inside a function. This is always recommended as it allows Functions
85// which have Lattices as arguments to work for any derived class.
86//
87// I will give a few examples here and then refer the reader to the
88// <linkto class="ArrayLattice">ArrayLattice</linkto> class (a memory resident
89// Lattice) and the <linkto class="PagedArray">PagedArray</linkto> class (a
90// disk based Lattice) which contain further examples with concrete
91// classes (rather than an abstract one). All the examples shown below are used
92// in the <src>dLattice.cc</src> demo program.
93//
94// <h4>Example 1:</h4>
95// This example calculates the mean of the Lattice. Because Lattices can be too
96// large to fit into physical memory it is not good enough to simply use
97// <src>getSlice</src> to read all the elements into an Array. Instead the
98// Lattice is accessed in chunks which can fit into memory (the size is
99// determined by the <src>maxPixels</src> and <src>niceCursorShape</src>
100// functions). The <src>LatticeIterator::cursor()</src> function then returns
101// each of these chunks as an Array and the standard Array based functions are
102// used to calculate the mean on each of these chunks. Functions like this one
103// are the recommended way to access Lattices as the
104// <linkto class="LatticeIterator">LatticeIterator</linkto> will correctly
105// setup any required caches.
106//
107// <srcblock>
108// Complex latMean(const Lattice<Complex>& lat) {
109// const uInt cursorSize = lat.advisedMaxPixels();
110// const IPosition cursorShape = lat.niceCursorShape(cursorSize);
111// const IPosition latticeShape = lat.shape();
112// Complex currentSum = 0.0f;
113// size_t nPixels = 0;
114// RO_LatticeIterator<Complex> iter(lat,
115// LatticeStepper(latticeShape, cursorShape));
116// for (iter.reset(); !iter.atEnd(); iter++){
117// currentSum += sum(iter.cursor());
118// nPixels += iter.cursor().nelements();
119// }
120// return currentSum/nPixels;
121// }
122// </srcblock>
123//
124// <h4>Example 2:</h4>
125// Sometimes it will be neccesary to access slices of a Lattice in a nearly
126// random way. Often this can be done using the subSection commands in the
127// <linkto class="LatticeStepper">LatticeStepper</linkto> class. But it is also
128// possible to use the getSlice and putSlice functions. The following example
129// does a two-dimensional Real to Complex Fourier transform. This example is
130// restricted to four-dimensional Arrays (unlike the previous example) and does
131// not set up any caches (caching is currently only used with PagedArrays). So
132// only use getSlice and putSlice when things cannot be done using
133// LatticeIterators.
134//
135// <srcblock>
136// void FFT2DReal2Complex(Lattice<Complex>& result,
137// const Lattice<Float>& input){
138// AlwaysAssert(input.ndim() == 4, AipsError);
139// const IPosition shape = input.shape();
140// const uInt nx = shape(0);
141// AlwaysAssert (nx > 1, AipsError);
142// const uInt ny = shape(1);
143// AlwaysAssert (ny > 1, AipsError);
144// const uInt npol = shape(2);
145// const uInt nchan = shape(3);
146// const IPosition resultShape = result.shape();
147// AlwaysAssert(resultShape.nelements() == 4, AipsError);
148// AlwaysAssert(resultShape(3) == nchan, AipsError);
149// AlwaysAssert(resultShape(2) == npol, AipsError);
150// AlwaysAssert(resultShape(1) == ny, AipsError);
151// AlwaysAssert(resultShape(0) == nx/2 + 1, AipsError);
152//
153// const IPosition inputSliceShape(4,nx,ny,1,1);
154// const IPosition resultSliceShape(4,nx/2+1,ny,1,1);
155// COWPtr<Array<Float> >
156// inputArrPtr(new Array<Float>(inputSliceShape.nonDegenerate()));
157// Array<Complex> resultArray(resultSliceShape.nonDegenerate());
158// FFTServer<Float, Complex> FFT2D(inputSliceShape.nonDegenerate());
159//
160// IPosition start(4,0);
161// Bool isARef;
162// for (uInt c = 0; c < nchan; c++){
163// for (uInt p = 0; p < npol; p++){
164// isARef = input.getSlice(inputArrPtr,
165// Slicer(start,inputSliceShape), True);
166// FFT2D.fft(resultArray, *inputArrPtr);
167// result.putSlice(resultArray, start);
168// start(2) += 1;
169// }
170// start(2) = 0;
171// start(3) += 1;
172// }
173// }
174// </srcblock>
175//
176// <h4>Example 3:</h4>
177// Occasionally you may want to access a few elements of a Lattice without
178// all the difficulty involved in setting up Iterators or calling getSlice
179// and putSlice. This is demonstrated in the example below and uses the
180// parenthesis operator, along with the LatticeValueRef companion
181// class. Using these functions to access many elements of a Lattice is not
182// recommended as this is the slowest access method.
183//
184// In this example an ideal point spread function will be inserted into an
185// empty Lattice. As with the previous examples all the action occurs
186// inside a function because Lattice is an interface (abstract) class.
187//
188// <srcblock>
189// void makePsf(Lattice<Float>& psf) {
190// const IPosition centrePos = psf.shape()/2;
191// psf.set(0.0f); // this sets all the elements to zero
192// // As it uses a LatticeIterator it is efficient
193// psf(centrePos) = 1; // This sets just the centre element to one
194// AlwaysAssert(near(psf(centrePos), 1.0f, 1E-6), AipsError);
195// AlwaysAssert(near(psf(centrePos*0), 0.0f, 1E-6), AipsError);
196// }
197// </srcblock>
198// </example>
199
200// <motivation>
201// Creating an abstract base class which provides a common interface between
202// memory and disk based arrays has a number of advantages.
203// <ul>
204// <li> It allows functions common to all arrays to be written independent
205// of the way the data is stored. This is illustrated in the three examples
206// above.
207// <li> It reduces the learning curve for new users who only have to become
208// familiar with one interface (ie. Lattice) rather than distinct interfaces
209// for different array types.
210// </ul>
211// </motivation>
212
213//# <todo asof="1996/07/01">
214//# <li>
215//# </todo>
216
217template <class T> class MaskedLattice : public Lattice<T>
218{
219 //# Make members of parent class known.
220public:
221 using Lattice<T>::ndim;
222 using Lattice<T>::shape;
223
224public:
225 // Default constructor.
227 : itsDefRegPtr(0) {;}
228
229 // Copy constructor.
231
232 // a virtual destructor is needed so that it will use the actual destructor
233 // in the derived class
234 virtual ~MaskedLattice();
235
236 // Make a copy of the object (reference semantics).
237 // <group>
238 virtual MaskedLattice<T>* cloneML() const = 0;
239 virtual Lattice<T>* clone() const;
240 // </group>
241
242 // Has the object really a mask?
243 // The default implementation returns True if the MaskedLattice has
244 // a region with a mask.
245 virtual Bool isMasked() const;
246
247 // Does the lattice have a pixelmask?
248 // The default implementation returns False.
249 virtual Bool hasPixelMask() const;
250
251 // Get access to the pixelmask.
252 // An exception is thrown if the lattice does not have a pixelmask.
253 // <group>
254 virtual const Lattice<Bool>& pixelMask() const;
256 // </group>
257
258 // Get the region used.
259 // This is in principle the region pointed to by <src>getRegionPtr</src>.
260 // However, if that pointer is 0, it returns a LatticeRegion for the
261 // full image.
262 const LatticeRegion& region() const;
263
264 // Get the mask or a slice from the mask.
265 // This is the mask formed by combination of the possible pixelmask of the
266 // lattice and the possible mask of the region taken from the lattice.
267 // If there is no mask, it still works fine.
268 // In that case it sizes the buffer correctly and sets it to True.
269 // <group>
271 Bool removeDegenerateAxes=False) const;
272 Bool getMaskSlice (COWPtr<Array<Bool> >& buffer, const Slicer& section,
273 Bool removeDegenerateAxes=False) const;
274 Bool getMaskSlice (COWPtr<Array<Bool> >& buffer, const IPosition& start,
275 const IPosition& shape,
276 Bool removeDegenerateAxes=False) const;
277 Bool getMaskSlice (COWPtr<Array<Bool> >& buffer, const IPosition& start,
278 const IPosition& shape, const IPosition& stride,
279 Bool removeDegenerateAxes=False) const;
281 Bool removeDegenerateAxes=False);
282 Bool getMaskSlice (Array<Bool>& buffer, const Slicer& section,
283 Bool removeDegenerateAxes=False);
284 Bool getMaskSlice (Array<Bool>& buffer, const IPosition& start,
285 const IPosition& shape,
286 Bool removeDegenerateAxes=False);
287 Bool getMaskSlice (Array<Bool>& buffer, const IPosition& start,
288 const IPosition& shape, const IPosition& stride,
289 Bool removeDegenerateAxes=False);
290 Array<Bool> getMask (Bool removeDegenerateAxes=False) const;
292 Bool removeDegenerateAxes=False) const;
294 const IPosition& shape,
295 Bool removeDegenerateAxes=False) const;
297 const IPosition& shape, const IPosition& stride,
298 Bool removeDegenerateAxes=False) const;
299 // </group>
300
301 // The function (in the derived classes) doing the actual work.
302 // These functions are public, so they can be used internally in the
303 // various Lattice classes.
304 // <br>However, doGetMaskSlice does not call Slicer::inferShapeFromSource
305 // to fill in possible unspecified section values. Therefore one
306 // should normally use one of the getMask(Slice) functions. doGetMaskSlice
307 // should be used with care and only when performance is an issue.
308 // <br>The default implementation gets the mask from the region
309 // and fills the buffer with True values if there is no region.
310 virtual Bool doGetMaskSlice (Array<Bool>& buffer, const Slicer& section);
311
312protected:
313 // Assignment can only be used by derived classes.
315
316 // Get a pointer to the region used.
317 // It can return 0 meaning that the MaskedLattice is the full lattice.
318 virtual const LatticeRegion* getRegionPtr() const = 0;
319
320private:
322};
323
324
325
326} //# NAMESPACE CASACORE - END
327
328#ifndef CASACORE_NO_AUTO_TEMPLATES
329#include <casacore/lattices/Lattices/MaskedLattice.tcc>
330#endif //# CASACORE_NO_AUTO_TEMPLATES
331#endif
virtual IPosition shape() const =0
Return the shape of the Lattice including all degenerate axes (ie.
virtual uInt ndim() const
Return the number of axes in this Lattice.
Bool getMask(COWPtr< Array< Bool > > &buffer, Bool removeDegenerateAxes=False) const
Get the mask or a slice from the mask.
MaskedLattice< T > & operator=(const MaskedLattice< T > &)
Assignment can only be used by derived classes.
MaskedLattice()
Default constructor.
Array< Bool > getMaskSlice(const IPosition &start, const IPosition &shape, Bool removeDegenerateAxes=False) const
Array< Bool > getMaskSlice(const Slicer &section, Bool removeDegenerateAxes=False) const
Bool getMaskSlice(COWPtr< Array< Bool > > &buffer, const Slicer &section, Bool removeDegenerateAxes=False) const
virtual Bool doGetMaskSlice(Array< Bool > &buffer, const Slicer &section)
The function (in the derived classes) doing the actual work.
virtual Lattice< Bool > & pixelMask()
Array< Bool > getMask(Bool removeDegenerateAxes=False) const
Bool getMaskSlice(COWPtr< Array< Bool > > &buffer, const IPosition &start, const IPosition &shape, Bool removeDegenerateAxes=False) const
virtual const LatticeRegion * getRegionPtr() const =0
Get a pointer to the region used.
Bool getMaskSlice(Array< Bool > &buffer, const IPosition &start, const IPosition &shape, const IPosition &stride, Bool removeDegenerateAxes=False)
virtual MaskedLattice< T > * cloneML() const =0
Make a copy of the object (reference semantics).
virtual Lattice< T > * clone() const
Make a copy of the derived object (reference semantics).
Bool getMaskSlice(Array< Bool > &buffer, const IPosition &start, const IPosition &shape, Bool removeDegenerateAxes=False)
const LatticeRegion & region() const
Get the region used.
MaskedLattice(const MaskedLattice< T > &)
Copy constructor.
virtual Bool hasPixelMask() const
Does the lattice have a pixelmask? The default implementation returns False.
virtual ~MaskedLattice()
a virtual destructor is needed so that it will use the actual destructor in the derived class
Array< Bool > getMaskSlice(const IPosition &start, const IPosition &shape, const IPosition &stride, Bool removeDegenerateAxes=False) const
virtual Bool isMasked() const
Has the object really a mask? The default implementation returns True if the MaskedLattice has a regi...
virtual const Lattice< Bool > & pixelMask() const
Get access to the pixelmask.
Bool getMaskSlice(Array< Bool > &buffer, const Slicer &section, Bool removeDegenerateAxes=False)
LatticeRegion * itsDefRegPtr
Bool getMaskSlice(COWPtr< Array< Bool > > &buffer, const IPosition &start, const IPosition &shape, const IPosition &stride, Bool removeDegenerateAxes=False) const
Bool getMask(Array< Bool > &buffer, Bool removeDegenerateAxes=False)
this file contains all the compiler specific defines
Definition: mainpage.dox:28
const Bool False
Definition: aipstype.h:44
bool Bool
Define the standard types used by Casacore.
Definition: aipstype.h:42