casacore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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>
35 
36 namespace casacore { //# NAMESPACE CASACORE - BEGIN
37 
38 //# Forward Declarations
39 class 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 
217 template <class T> class MaskedLattice : public Lattice<T>
218 {
219  //# Make members of parent class known.
220 public:
221  using Lattice<T>::ndim;
222  using Lattice<T>::shape;
223 
224 public:
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;
255  virtual Lattice<Bool>& pixelMask();
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>
270  Bool getMask (COWPtr<Array<Bool> >& buffer,
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;
280  Bool getMask (Array<Bool>& buffer,
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;
291  Array<Bool> getMaskSlice (const Slicer& section,
292  Bool removeDegenerateAxes=False) const;
293  Array<Bool> getMaskSlice (const IPosition& start,
294  const IPosition& shape,
295  Bool removeDegenerateAxes=False) const;
296  Array<Bool> getMaskSlice (const IPosition& start,
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 
312 protected:
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 
320 private:
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
A Vector of integers, for indexing into Array&lt;T&gt; objects.
Definition: IPosition.h:118
MaskedLattice< T > & operator=(const MaskedLattice< T > &)
Assignment can only be used by derived classes.
virtual const Lattice< Bool > & pixelMask() const
Get access to the pixelmask.
virtual Lattice< T > * clone() const
Make a copy of the derived object (reference semantics).
Bool getMaskSlice(COWPtr< Array< Bool > > &buffer, const Slicer &section, Bool removeDegenerateAxes=False) const
A templated, abstract base class for array-like objects with masks.
Definition: ImageConcat.h:46
virtual Bool hasPixelMask() const
Does the lattice have a pixelmask? The default implementation returns False.
virtual const LatticeRegion * getRegionPtr() const =0
Get a pointer to the region used.
virtual Bool isMasked() const
Has the object really a mask? The default implementation returns True if the MaskedLattice has a regi...
Bool getMask(COWPtr< Array< Bool > > &buffer, Bool removeDegenerateAxes=False) const
Get the mask or a slice from the mask.
A templated, abstract base class for array-like objects.
Definition: Functional.h:37
virtual IPosition shape() const =0
Return the shape of the Lattice including all degenerate axes (ie.
virtual MaskedLattice< T > * cloneML() const =0
Make a copy of the object (reference semantics).
LatticeExprNode ndim(const LatticeExprNode &expr)
1-argument function to get the dimensionality of a lattice.
Copy-On-Write-Pointer class - allows control of copy based on constness.
Definition: COWPtr.h:185
virtual Bool doGetMaskSlice(Array< Bool > &buffer, const Slicer &section)
The function (in the derived classes) doing the actual work.
bool Bool
Define the standard types used by Casacore.
Definition: aipstype.h:42
const Bool False
Definition: aipstype.h:44
TableExprNode shape(const TableExprNode &array)
Function operating on any scalar or array resulting in a Double array containing the shape...
Definition: ExprNode.h:1987
MaskedLattice()
Default constructor.
Specify which elements to extract from an n-dimensional array.
Definition: Slicer.h:288
virtual ~MaskedLattice()
a virtual destructor is needed so that it will use the actual destructor in the derived class ...
const LatticeRegion & region() const
Get the region used.
An optionally strided region in a Lattice.
Definition: LatticeRegion.h:74
LatticeRegion * itsDefRegPtr