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