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