casacore
Loading...
Searching...
No Matches
LatticeIterator.h
Go to the documentation of this file.
1// # LatticeIterator.h: Iterators for Lattices: readonly or read/write
2// # Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2003
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_LATTICEITERATOR_H
27#define LATTICES_LATTICEITERATOR_H
28
29// # Includes
30#include <casacore/casa/aips.h>
31#include <casacore/lattices/Lattices/Lattice.h>
32#include <casacore/lattices/Lattices/LatticeIterInterface.h>
33#include <casacore/casa/Arrays/ArrayFwd.h>
34#include <memory>
35
36namespace casacore { // # NAMESPACE CASACORE - BEGIN
37
38// # Forward Declarations
39class IPosition;
41
42// <summary>
43// A readonly iterator for Lattices
44// </summary>
45
46// <use visibility=export>
47
48// <reviewed reviewer="Peter Barnes" date="1999/10/30" tests="tLatticeIterator.cc">
49// </reviewed>
50
51// <prerequisite>
52// <li> <linkto class="Lattice">Lattice</linkto>
53// <li> <linkto class="LatticeNavigator">LatticeNavigator</linkto>
54// <li> <linkto class="Array">Array</linkto>
55// </prerequisite>
56
57// <etymology>
58// The leading "RO" is shorthand for "readonly", which indicates that an
59// RO_LatticeIterator is used for traversing a Lattice, examining and
60// possibly extracting its contents, but not for modifying it.
61// </etymology>
62
63// <synopsis>
64// This class provides a convenient way to traverse any class derived from
65// Lattice. You can iterate through the Lattice's data from "start" to "end"
66// by calling <src>operator++</src>, and reverse direction by calling
67// <src>operator--</src>. You can return immediately to the beginning by
68// calling the <src>reset</src> function. The RO_LatticeIterator gives the
69// user the opportunity to methodically walk through the data, in an
70// efficient way.
71// <p>
72// The supplied <linkto class=LatticeNavigator>LatticeNavigator</linkto>
73// determines how to step through the Lattice. It can, for instance,
74// be line by line, but it can also be in a more complicated way.
75// When no navigator is supplied, a default navigator will be used
76// which steps in the optimum way.
77// <p>
78// A cursor (which is an <linkto class=Array>Array</linkto> object) is
79// used to return the data for each step in the iteration process.
80// Depending on the navigator used the cursor can have a different shape
81// for each step of the iteration. This is especially true when the
82// end of an axis is reached for a non-integrally fitting cursor shape.
83// <br> The cursor() function returns an Array which has the same
84// dimensionality as the Lattice. It is, however, also possible to get
85// an Array with a lower dimensionality by using the correct function
86// in the group <src>vectorCursor()</src>, <src>matrixCursor()</src>, and
87// <src>cubeCursor()</src>. Those functions remove (some) degenerated axes
88// resulting in a vector, matrix or cube.
89// When, for example, a LatticeStepper with shape [64,1,1] is used, the
90// <src>vectorCursor()</src> can be used. It will remove the degenerated
91// axes (length 1) and return the cursor as a Vector object. Note that
92// <src>matrixCursor()</src> cannot be used, because removing the degenerated
93// axes results in a 1D array.
94// <p>
95// Generally iterators should not be long-lived objects - create new ones
96// when needed rather than keeping one around for a long time to be
97// reused. This is because the cache memory used by the cursor will be
98// released when the iterator is destroyed.
99// <p>
100// The purpose of this class is to hide the possibly complicated
101// implementation and structure of the Lattice classes, and allow you to
102// iterate through a Lattice with the same ease as one iterates through a
103// Fortran or C vector. For example, and assuming that initialization has
104// been done properly, here's a typical 'for' loop:
105// <srcblock>
106// // code omitted which associates Lattice object and the iterator
107// for (iterator.reset(); !iterator.atEnd(); iterator++) {
108// meanValue = mean(iterator.cursor());
109// }
110// </srcblock>
111// The iterator's <src>cursor()</src> member function returns a reference to
112// that part of the Lattice data which is presently "seen" by the
113// LatticeIterator.
114// <p>
115// Before explaining the initialization of an iterator, the LatticeNavigator
116// class must be further introduced. This is an abstract base class, from which
117// concrete navigators are derived. After one of these is created, you
118// attach it to the LatticeIterator, and it provides a specific technique
119// for navigating through the Lattice. Different navigators deliver
120// different traversal schemes. The most basic is
121// <linkto class=LatticeStepper>LatticeStepper</linkto>, which
122// moves a specified shape sequentially through the Lattice -- for example,
123// by moving one plane at a time, front to back, through a cube. Another
124// (future) navigator might be designed to move a small, 2-dimensional plane
125// through a cube, centering each iteration on the brightest pixel of the
126// cube's plane, and ignoring the darker regions of the cube.
127// <p>
128// The performance and memory usage of an iteration through a lattice
129// (in particular through a <linkto class=PagedArray>PagedArray</linkto>)
130// depends very heavily on the navigator used. Currently there are three
131// navigators available:
132// <ol>
133// <li> <linkto class=LatticeStepper>LatticeStepper</linkto> steps
134// sequentially through a lattice with the given cursor shape.
135// This can use a lot of memory for the PagedArray cache.
136// <li> <linkto class=TiledLineStepper>TiledLineStepper</linkto>
137// steps line by line through a lattice. However, it is doing that
138// in such a way that as few tiles as possible need to kept in the
139// PagedArray cache. This reduces memory usage considerably.
140// <li> <linkto class=TileStepper>TileStepper</linkto> steps tile
141// by tile through a lattice. This navigator requires a PagedArray cache
142// of 1 tile only. However, it can only be used for application in which
143// the iteration order is not important (e.g. addition, determining max).
144// </ol>
145// The class <linkto class=LatticeApply>LatticeApply</linkto> is very useful
146// to iterate through a Lattice while applying an algorithm. It makes it
147// possible for the user to concentrate on the algorithm.
148// <p>
149// Here's a typical iterator declaration:
150// <srcblock>
151// RO_LatticeIterator<Float> iterator(pagedArray, stepper);
152// </srcblock>
153// The template identifier <src>Float</src> defines the data type of
154// Array object that will be the iterator's cursor.
155//<br>
156// The <src>pagedArray</src> constructor argument names a PagedArray object,
157// which is what the iterator will traverse. The <src>stepper</src>
158// argument is a LatticeStepper which defines the method of iteration.
159
160// <example>
161// When passed the name of a previously created PagedArray stored on disk,
162// this function will traverse the whole array, and report the average value
163// of all of the elements. Imagine that the filename contains a PagedArray
164// with dimension 64 x 64 x 8.
165// <srcblock>
166// void demonstrateIterator (const String& filename)
167// {
168// PagedArray<Float> pagedArray(filename);
169// IPosition latticeShape = pagedArray.shape();
170// cout << "paged array has shape: " << latticeShape << endl;
171//
172// // Construct the iterator. since we only want to read the PagedArray,
173// // use the read-only class, which disallows writing back to the cursor.
174// // No navigator is given, so the default TileStepper is used
175// // which ensures optimum performance.
176// RO_LatticeIterator<Float> iterator(pagedArray);
177//
178// // Add for each iteration step the sum of the cursor elements to the sum.
179// // Note that the cursor is an Array object and that the function sum
180// // is defined in ArrayMath.h.
181// Float runningSum = 0.0;
182// for (iterator.reset(); !iterator.atEnd(); iterator++) {
183// runningSum += sum(iterator.cursor());
184// }
185// cout << "average value, from demonstrateIterator: "
186// << runningSum / latticeShape.product() << endl;
187// }
188// </srcblock>
189// </example>
190
191// <motivation>
192// Iterator classes are a standard feature in C++ libraries -- they
193// provide convenience and allow the implementation of the "iteratee"
194// to be kept hidden.
195// </motivation>
196
197// # <todo asof="1995/09/12">
198// # <li>
199// # </todo>
200
201template <class T>
203 public:
204 // The default constructor creates an empty object which is practically
205 // unusable.
206 // It can only be used as the source or target of an assignment. It can
207 // also be used as the source for the copy constructor and the copy function.
208 // Other functions do not check if the object is empty and will usually
209 // give a segmentation fault.
210 // The function isNull() can be used to test if the object is empty.
212
213 // Construct the Iterator with the supplied data.
214 // It uses a TileStepper as the default iteration strategy.
215 // useRef=True means that if possible the cursor arrays returned
216 // reference the data in the underlying lattice. This is only possible
217 // for ArrayLattice objects (or e.g. a SubLattice using it).
218 explicit RO_LatticeIterator(const Lattice<T>& data, Bool useRef = True);
219
220 // Construct the Iterator with the supplied data, and iteration strategy
221 RO_LatticeIterator(const Lattice<T>& data, const LatticeNavigator& method, Bool useRef = True);
222
223 // Construct the Iterator with the supplied data.
224 // It uses a LatticeStepper with the supplied cursor shape as the
225 // iteration strategy.
227
228 // The copy constructor uses reference semantics (ie. NO real copy is made).
229 // The function <src>copy</src> can be used to make a true copy.
231
232 // Destructor (cleans up dangling references and releases memory)
234
235 // Assignment uses reference semantics (ie. NO real copy is made).
236 // The function <src>copy</src> can be used to make a true copy.
238
239 // Make a copy of the iterator object.
240 // This means that an independent navigator object is created to
241 // be able to iterate independently through the same Lattice.
242 // The position in the copied navigator is the same as the original.
243 // The reset function has to be used to start at the beginning.
244 // <br>Note that if the Lattice uses a cache (e.g. PagedArray), the
245 // cache is shared by the iterators.
247
248 // Is the iterator object empty?
249 Bool isNull() const { return !itsIterPtr; }
250
251 // Return the underlying lattice.
252 Lattice<T>& lattice() const { return itsIterPtr->lattice(); }
253
254 // Increment operator - increment the cursor to the next position. These
255 // functions are forwarded to the current LatticeNavigator and both
256 // postfix and prefix versions will do the same thing.
257 // <br>They return True if the cursor moved (which should always be the
258 // case if the iterator is not at the end).
259 // <group>
262 // </group>
263
264 // Decrement operator - decrement the cursor to the previous
265 // position. These functions are forwarded to the current LatticeNavigator
266 // and both postfix and prefix versions will do the same thing.
267 // <br>They return True if the cursor moved (which should always be the
268 // case if the iterator is not at the start).
269 // <group>
272 // </group>
273
274 // Function which resets the cursor to the beginning of the Lattice and
275 // resets the number of steps taken to zero.
276 void reset();
277
278 // Function which returns a value of "True" if the cursor is at the
279 // beginning of the Lattice, otherwise, returns "False".
280 Bool atStart() const;
281
282 // Function which returns a value of "True" if an attempt has been made
283 // to move the cursor beyond the end of the Lattice.
284 Bool atEnd() const;
285
286 // Function to return the number of steps (increments or decrements) taken
287 // since construction (or since last reset). This is a running count of
288 // all cursor movement, thus doing N increments followed by N decrements
289 // results in 2N steps.
290 uInt nsteps() const;
291
292 // Function which returns the current position of the beginning of the
293 // cursor within the Lattice. The returned IPosition will have the same
294 // number of axes as the underlying Lattice.
296
297 // Function which returns the current position of the end of the
298 // cursor. The returned IPosition will have the same number of axes as the
299 // underlying Lattice.
301
302 // Function which returns the shape of the Lattice being iterated through.
303 // The returned IPosition will always have the same number of axes as the
304 // underlying Lattice.
306
307 // Function which returns the shape of the cursor which is iterating
308 // through the Lattice. The returned IPosition will have the same number
309 // of axes as the underlying Lattice.
311
312 // Functions which returns a window to the data in the Lattice. These are
313 // used to read the data within the Lattice. Use the function that is
314 // appropriate to the current cursor dimension, AFTER REMOVING DEGENERATE
315 // AXES, or use the <src>cursor</src> function which works with any number
316 // of dimensions in the cursor. A call of the function whose return value
317 // is inappropriate with respect to the current cursor dimension will
318 // throw an exception (AipsError).
319 // <group>
320 const Vector<T>& vectorCursor() const;
321 const Matrix<T>& matrixCursor() const;
322 const Cube<T>& cubeCursor() const;
323 const Array<T>& cursor() const;
324 // </group>
325
326 // Function which checks the internals of the class for consistency.
327 // Returns True if everything is fine otherwise returns False.
328 Bool ok() const;
329
330 protected:
331 // The pointer to the Iterator
332 std::shared_ptr<LatticeIterInterface<T>> itsIterPtr;
333};
334
335// <summary>
336// A read/write lattice iterator
337// </summary>
338
339// <use visibility=export>
340
341// <reviewed reviewer="Peter Barnes" date="1999/10/30" tests="tLatticeIterator.cc">
342// </reviewed>
343
344// <prerequisite>
345// <li> <linkto class="RO_LatticeIterator">RO_LatticeIterator</linkto>
346// <li> <linkto class="Lattice">Lattice</linkto>
347// <li> <linkto class="LatticeNavigator">LatticeNavigator</linkto>
348// <li> <linkto class="Array">Array</linkto>
349// </prerequisite>
350
351// <synopsis>
352// LatticeIterator differs from the RO_LatticeIterator class in that
353// the window into the Lattice data which moves with each iterative step may
354// be used to alter the Lattice data itself. The moving "cursor" gives the
355// user the door to reach in and change the basic Lattice before moving to
356// another section of the Lattice.
357// <p>
358// LatticeIterator can be used in 3 ways:
359// <br> - For readonly purposes using the cursor() functions. Note that if
360// the entire iteration is readonly, it is better to use an
361// <linkto class=RO_LatticeIterator>RO_LatticeIterator</linkto> object.
362// <br> - To update (part of)the contents of the lattice (e.g. clip the value
363// of some pixels). For this purpose the <src>rwCursor</src> functions
364// should be used. They read the data (if not read yet) and mark the
365// cursor for write.
366// <br> - To fill the lattice. For this purpose the <src>woCursor</src>
367// functions should be used. They do not read the data, but only mark the
368// cursor for write.
369// <p>
370// When needed, writing the cursor data is done automatically when the
371// cursor position changes or when the iterator is destructed.
372// </synopsis>
373
374// <example>
375// Here's an iterator that runs through a cube, assigning every element
376// of each plane of the cube a value equal to the number of the plane.
377// See <linkto class=LatticeStepper>LatticeStepper</linkto> for an
378// explanation of the navigator used here.
379// <srcblock>
380// PagedArray<Float> pa("someName");
381// IPosition windowShape(2,pa.shape(0), pa.shape(1));
382// LatticeStepper stepper(pa.shape(), windowShape);
383// LatticeIterator<Float> iterator(pa, stepper);
384// Int planeNumber = 0;
385// for (iterator.reset(); !iterator.atEnd(); iterator++) {
386// iterator.woCursor() = planeNumber++;
387// }
388// </srcblock>
389//
390// Here's an iterator that runs through a cube, subtracting the mean from
391// each line of the cube with a mean < 0.
392// See <linkto class=TiledLineStepper>TiledLineStepper</linkto> for an
393// explanation of the navigator used here.
394// <srcblock>
395// PagedArray<Float> pa("someName");
396// TiledLineStepper stepper(pa.shape(), pa.niceCursorShape(), 0);
397// LatticeIterator<Float> iterator(pa, stepper);
398// Int planeNumber = 0;
399// for (iterator.reset(); !iterator.atEnd(); iterator++) {
400// Float meanLine = mean(iterator.cursor());
401// if (meanLine < 0) {
402// iterator.rwCursor() -= meanLine;
403// }
404// }
405// </srcblock>
406// Note that in this last example no more vectors than required are written.
407// This is achieved by using the readonly function <src>cursor</src> in
408// the test and using <src>rwCursor</src> only when data needs to be changed.
409// <br>Note that <src>rwCursor</src> does not read the data again. They are
410// still readily available.
411// </example>
412
413template <class T>
415 public:
416 // The default constructor creates an empty object which is practically
417 // unusable.
418 // It can only be used as the source or target of an assignment. It can
419 // also be used as the source for the copy constructor and the copy function.
420 // Other functions do not check if the object is empty and will usually
421 // give a segmentation fault.
422 // The function isNull() can be used to test if the object is empty.
424
425 // Construct the Iterator with the supplied data.
426 // It uses a TileStepper as the default iteration strategy.
427 // useRef=True means that if possible the cursor arrays returned
428 // reference the data in the underlying lattice. This is only possible
429 // for ArrayLattice objects (or e.g. a SubLattice using it).
430 explicit LatticeIterator(Lattice<T>& data, Bool useRef = True);
431
432 // Construct the Iterator with the supplied data, and iteration strategy
433 LatticeIterator(Lattice<T>& data, const LatticeNavigator& method, Bool useRef = True);
434
435 // Iterate through the data with a LatticeStepper that has uses the
436 // supplied cursorShape.
438
439 // The copy constructor uses reference semantics (ie. NO real copy is made).
440 // The function <src>copy</src> can be used to make a true copy.
442
443 // destructor (cleans up dangling references and releases memory)
445
446 // Assignment uses reference semantics (ie. NO real copy is made).
447 // The function <src>copy</src> can be used to make a true copy.
449
450 // Make a copy of the iterator object.
451 // This means that an independent navigator object is created to
452 // be able to iterate independently through the same Lattice.
453 // The position in the copied navigator is the same as the original.
454 // The reset function has to be used to start at the beginning.
455 // <br>Note that if the Lattice uses a cache (e.g. PagedArray), the
456 // cache is shared by the iterators.
458
459 // Functions to return a window to the data in the Lattice. Use the function
460 // that is appropriate to the current cursor dimension, AFTER REMOVING
461 // DEGENERATE AXES, or use the <src>cursor</src> function which works with
462 // any number of dimensions in the cursor. A call of the function whose
463 // return value is inappropriate with respect to the current cursor
464 // dimension will throw an exception (AipsError) (e.g. VectorCursor
465 // cannot be used when the cursor is 2D).
466 // <br>
467 // When the iterator state changes (e.g. by moving, destruction) the
468 // data are automatically rewritten before the iterator state is changed.
469 // <br>The <src>rw</src> (read/write) versions should be used to read the
470 // data first. They are useful to update a lattice.
471 // The <src>wo</src> (writeonly) versions do not read the data.
472 // They only return a cursor of the correct shape and are useful to
473 // fill a lattice. Note that it sets the state to 'data read'. I.e.,
474 // a subsequent call to, say, <src>cursor()</src> does not read the
475 // data, which would destroy the contents of the cursor which may
476 // just be filled by the user.
477 // <group>
486 //</group>
487
488 // Function which checks the internals of the class for consistency.
489 // Returns True if everything is fine. Otherwise returns False.
490 Bool ok() const;
491
492 // # Make members of parent class known.
493 public:
498
499 protected:
501};
502
503} // namespace casacore
504
505// # See comments in Lattice.h why Lattice.tcc is included here.
506#ifndef CASACORE_NO_AUTO_TEMPLATES
507#include <casacore/lattices/Lattices/Lattice.tcc>
508#include <casacore/lattices/Lattices/LatticeIterator.tcc>
509#endif // # CASACORE_NO_AUTO_TEMPLATES
510#endif
Matrix< T > & woMatrixCursor()
Vector< T > & woVectorCursor()
LatticeIterator(Lattice< T > &data, const LatticeNavigator &method, Bool useRef=True)
Construct the Iterator with the supplied data, and iteration strategy.
LatticeIterator< T > & operator=(const LatticeIterator< T > &other)
Assignment uses reference semantics (ie.
LatticeIterator(Lattice< T > &data, Bool useRef=True)
Construct the Iterator with the supplied data.
Cube< T > & woCubeCursor()
LatticeIterator(const LatticeIterator< T > &other)
The copy constructor uses reference semantics (ie.
Cube< T > & rwCubeCursor()
Vector< T > & rwVectorCursor()
Functions to return a window to the data in the Lattice.
Bool ok() const
Function which checks the internals of the class for consistency.
~LatticeIterator()
destructor (cleans up dangling references and releases memory)
Matrix< T > & rwMatrixCursor()
LatticeIterator()
The default constructor creates an empty object which is practically unusable.
LatticeIterator(Lattice< T > &data, const IPosition &cursorShape, Bool useRef=True)
Iterate through the data with a LatticeStepper that has uses the supplied cursorShape.
LatticeIterator< T > copy() const
Make a copy of the iterator object.
Bool atEnd() const
Function which returns a value of "True" if an attempt has been made to move the cursor beyond the en...
const Matrix< T > & matrixCursor() const
void reset()
Function which resets the cursor to the beginning of the Lattice and resets the number of steps taken...
RO_LatticeIterator(const Lattice< T > &data, Bool useRef=True)
Construct the Iterator with the supplied data.
Bool isNull() const
Is the iterator object empty?
const Cube< T > & cubeCursor() const
Bool atStart() const
Function which returns a value of "True" if the cursor is at the beginning of the Lattice,...
Lattice< T > & lattice() const
Return the underlying lattice.
IPosition endPosition() const
Function which returns the current position of the end of the cursor.
std::shared_ptr< LatticeIterInterface< T > > itsIterPtr
The pointer to the Iterator.
IPosition position() const
Function which returns the current position of the beginning of the cursor within the Lattice.
Bool operator++()
Increment operator - increment the cursor to the next position.
RO_LatticeIterator(const Lattice< T > &data, const IPosition &cursorShape, Bool useRef=True)
Construct the Iterator with the supplied data.
RO_LatticeIterator()
The default constructor creates an empty object which is practically unusable.
const Vector< T > & vectorCursor() const
Functions which returns a window to the data in the Lattice.
RO_LatticeIterator(const RO_LatticeIterator< T > &other)
The copy constructor uses reference semantics (ie.
~RO_LatticeIterator()
Destructor (cleans up dangling references and releases memory).
RO_LatticeIterator< T > copy() const
Make a copy of the iterator object.
RO_LatticeIterator(const Lattice< T > &data, const LatticeNavigator &method, Bool useRef=True)
Construct the Iterator with the supplied data, and iteration strategy.
IPosition cursorShape() const
Function which returns the shape of the cursor which is iterating through the Lattice.
RO_LatticeIterator< T > & operator=(const RO_LatticeIterator< T > &other)
Assignment uses reference semantics (ie.
IPosition latticeShape() const
Function which returns the shape of the Lattice being iterated through.
uInt nsteps() const
Function to return the number of steps (increments or decrements) taken since construction (or since ...
Bool ok() const
Function which checks the internals of the class for consistency.
Bool operator--()
Decrement operator - decrement the cursor to the previous position.
const Array< T > & cursor() const
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
unsigned int uInt
Definition aipstype.h:49
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
const Bool True
Definition aipstype.h:41