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;
40class LatticeNavigator;
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
201
202template <class T> class RO_LatticeIterator
203{
204public:
205
206 // The default constructor creates an empty object which is practically
207 // unusable.
208 // It can only be used as the source or target of an assignment. It can
209 // also be used as the source for the copy constructor and the copy function.
210 // Other functions do not check if the object is empty and will usually
211 // give a segmentation fault.
212 // The function isNull() can be used to test if the object is empty.
214
215 // Construct the Iterator with the supplied data.
216 // It uses a TileStepper as the default iteration strategy.
217 // useRef=True means that if possible the cursor arrays returned
218 // reference the data in the underlying lattice. This is only possible
219 // for ArrayLattice objects (or e.g. a SubLattice using it).
220 explicit RO_LatticeIterator (const Lattice<T>& data, Bool useRef=True);
221
222 // Construct the Iterator with the supplied data, and iteration strategy
223 RO_LatticeIterator (const Lattice<T>& data, const LatticeNavigator& method,
224 Bool useRef=True);
225
226 // Construct the Iterator with the supplied data.
227 // It uses a LatticeStepper with the supplied cursor shape as the
228 // iteration strategy.
230 Bool useRef=True);
231
232 // The copy constructor uses reference semantics (ie. NO real copy is made).
233 // The function <src>copy</src> can be used to make a true copy.
235
236 // Destructor (cleans up dangling references and releases memory)
238
239 // Assignment uses reference semantics (ie. NO real copy is made).
240 // The function <src>copy</src> can be used to make a true copy.
242
243 // Make a copy of the iterator object.
244 // This means that an independent navigator object is created to
245 // be able to iterate independently through the same Lattice.
246 // The position in the copied navigator is the same as the original.
247 // The reset function has to be used to start at the beginning.
248 // <br>Note that if the Lattice uses a cache (e.g. PagedArray), the
249 // cache is shared by the iterators.
251
252 // Is the iterator object empty?
253 Bool isNull() const
254 { return !itsIterPtr; }
255
256 // Return the underlying lattice.
258 { return itsIterPtr->lattice(); }
259
260 // Increment operator - increment the cursor to the next position. These
261 // functions are forwarded to the current LatticeNavigator and both
262 // postfix and prefix versions will do the same thing.
263 // <br>They return True if the cursor moved (which should always be the
264 // case if the iterator is not at the end).
265 // <group>
268 // </group>
269
270 // Decrement operator - decrement the cursor to the previous
271 // position. These functions are forwarded to the current LatticeNavigator
272 // and both postfix and prefix versions will do the same thing.
273 // <br>They return True if the cursor moved (which should always be the
274 // case if the iterator is not at the start).
275 // <group>
278 // </group>
279
280 // Function which resets the cursor to the beginning of the Lattice and
281 // resets the number of steps taken to zero.
282 void reset();
283
284 // Function which returns a value of "True" if the cursor is at the
285 // beginning of the Lattice, otherwise, returns "False".
286 Bool atStart() const;
287
288 // Function which returns a value of "True" if an attempt has been made
289 // to move the cursor beyond the end of the Lattice.
290 Bool atEnd() const;
291
292 // Function to return the number of steps (increments or decrements) taken
293 // since construction (or since last reset). This is a running count of
294 // all cursor movement, thus doing N increments followed by N decrements
295 // results in 2N steps.
296 uInt nsteps() const;
297
298 // Function which returns the current position of the beginning of the
299 // cursor within the Lattice. The returned IPosition will have the same
300 // number of axes as the underlying Lattice.
302
303 // Function which returns the current position of the end of the
304 // cursor. The returned IPosition will have the same number of axes as the
305 // underlying Lattice.
307
308 // Function which returns the shape of the Lattice being iterated through.
309 // The returned IPosition will always have the same number of axes as the
310 // underlying Lattice.
312
313 // Function which returns the shape of the cursor which is iterating
314 // through the Lattice. The returned IPosition will have the same number
315 // of axes as the underlying Lattice.
317
318 // Functions which returns a window to the data in the Lattice. These are
319 // used to read the data within the Lattice. Use the function that is
320 // appropriate to the current cursor dimension, AFTER REMOVING DEGENERATE
321 // AXES, or use the <src>cursor</src> function which works with any number
322 // of dimensions in the cursor. A call of the function whose return value
323 // is inappropriate with respect to the current cursor dimension will
324 // throw an exception (AipsError).
325 // <group>
326 const Vector<T>& vectorCursor() const;
327 const Matrix<T>& matrixCursor() const;
328 const Cube<T>& cubeCursor() const;
329 const Array<T>& cursor() const;
330 // </group>
331
332 // Function which checks the internals of the class for consistency.
333 // Returns True if everything is fine otherwise returns False.
334 Bool ok() const;
335
336protected:
337 // The pointer to the Iterator
338 std::shared_ptr<LatticeIterInterface<T>> itsIterPtr;
339};
340
341
342
343// <summary>
344// A read/write lattice iterator
345// </summary>
346
347// <use visibility=export>
348
349// <reviewed reviewer="Peter Barnes" date="1999/10/30" tests="tLatticeIterator.cc">
350// </reviewed>
351
352// <prerequisite>
353// <li> <linkto class="RO_LatticeIterator">RO_LatticeIterator</linkto>
354// <li> <linkto class="Lattice">Lattice</linkto>
355// <li> <linkto class="LatticeNavigator">LatticeNavigator</linkto>
356// <li> <linkto class="Array">Array</linkto>
357// </prerequisite>
358
359// <synopsis>
360// LatticeIterator differs from the RO_LatticeIterator class in that
361// the window into the Lattice data which moves with each iterative step may
362// be used to alter the Lattice data itself. The moving "cursor" gives the
363// user the door to reach in and change the basic Lattice before moving to
364// another section of the Lattice.
365// <p>
366// LatticeIterator can be used in 3 ways:
367// <br> - For readonly purposes using the cursor() functions. Note that if
368// the entire iteration is readonly, it is better to use an
369// <linkto class=RO_LatticeIterator>RO_LatticeIterator</linkto> object.
370// <br> - To update (part of)the contents of the lattice (e.g. clip the value
371// of some pixels). For this purpose the <src>rwCursor</src> functions
372// should be used. They read the data (if not read yet) and mark the
373// cursor for write.
374// <br> - To fill the lattice. For this purpose the <src>woCursor</src>
375// functions should be used. They do not read the data, but only mark the
376// cursor for write.
377// <p>
378// When needed, writing the cursor data is done automatically when the
379// cursor position changes or when the iterator is destructed.
380// </synopsis>
381
382// <example>
383// Here's an iterator that runs through a cube, assigning every element
384// of each plane of the cube a value equal to the number of the plane.
385// See <linkto class=LatticeStepper>LatticeStepper</linkto> for an
386// explanation of the navigator used here.
387// <srcblock>
388// PagedArray<Float> pa("someName");
389// IPosition windowShape(2,pa.shape(0), pa.shape(1));
390// LatticeStepper stepper(pa.shape(), windowShape);
391// LatticeIterator<Float> iterator(pa, stepper);
392// Int planeNumber = 0;
393// for (iterator.reset(); !iterator.atEnd(); iterator++) {
394// iterator.woCursor() = planeNumber++;
395// }
396// </srcblock>
397//
398// Here's an iterator that runs through a cube, subtracting the mean from
399// each line of the cube with a mean < 0.
400// See <linkto class=TiledLineStepper>TiledLineStepper</linkto> for an
401// explanation of the navigator used here.
402// <srcblock>
403// PagedArray<Float> pa("someName");
404// TiledLineStepper stepper(pa.shape(), pa.niceCursorShape(), 0);
405// LatticeIterator<Float> iterator(pa, stepper);
406// Int planeNumber = 0;
407// for (iterator.reset(); !iterator.atEnd(); iterator++) {
408// Float meanLine = mean(iterator.cursor());
409// if (meanLine < 0) {
410// iterator.rwCursor() -= meanLine;
411// }
412// }
413// </srcblock>
414// Note that in this last example no more vectors than required are written.
415// This is achieved by using the readonly function <src>cursor</src> in
416// the test and using <src>rwCursor</src> only when data needs to be changed.
417// <br>Note that <src>rwCursor</src> does not read the data again. They are
418// still readily available.
419// </example>
420
421
422template <class T> class LatticeIterator : public RO_LatticeIterator<T>
423{
424public:
425
426 // The default constructor creates an empty object which is practically
427 // unusable.
428 // It can only be used as the source or target of an assignment. It can
429 // also be used as the source for the copy constructor and the copy function.
430 // Other functions do not check if the object is empty and will usually
431 // give a segmentation fault.
432 // The function isNull() can be used to test if the object is empty.
434
435 // Construct the Iterator with the supplied data.
436 // It uses a TileStepper as the default iteration strategy.
437 // useRef=True means that if possible the cursor arrays returned
438 // reference the data in the underlying lattice. This is only possible
439 // for ArrayLattice objects (or e.g. a SubLattice using it).
440 explicit LatticeIterator (Lattice<T>& data, Bool useRef=True);
441
442 // Construct the Iterator with the supplied data, and iteration strategy
444 Bool useRef=True);
445
446 // Iterate through the data with a LatticeStepper that has uses the
447 // supplied cursorShape.
449 Bool useRef=True);
450
451 // The copy constructor uses reference semantics (ie. NO real copy is made).
452 // The function <src>copy</src> can be used to make a true copy.
454
455 // destructor (cleans up dangling references and releases memory)
457
458 // Assignment uses reference semantics (ie. NO real copy is made).
459 // The function <src>copy</src> can be used to make a true copy.
461
462 // Make a copy of the iterator object.
463 // This means that an independent navigator object is created to
464 // be able to iterate independently through the same Lattice.
465 // The position in the copied navigator is the same as the original.
466 // The reset function has to be used to start at the beginning.
467 // <br>Note that if the Lattice uses a cache (e.g. PagedArray), the
468 // cache is shared by the iterators.
470
471 // Functions to return a window to the data in the Lattice. Use the function
472 // that is appropriate to the current cursor dimension, AFTER REMOVING
473 // DEGENERATE AXES, or use the <src>cursor</src> function which works with
474 // any number of dimensions in the cursor. A call of the function whose
475 // return value is inappropriate with respect to the current cursor
476 // dimension will throw an exception (AipsError) (e.g. VectorCursor
477 // cannot be used when the cursor is 2D).
478 // <br>
479 // When the iterator state changes (e.g. by moving, destruction) the
480 // data are automatically rewritten before the iterator state is changed.
481 // <br>The <src>rw</src> (read/write) versions should be used to read the
482 // data first. They are useful to update a lattice.
483 // The <src>wo</src> (writeonly) versions do not read the data.
484 // They only return a cursor of the correct shape and are useful to
485 // fill a lattice. Note that it sets the state to 'data read'. I.e.,
486 // a subsequent call to, say, <src>cursor()</src> does not read the
487 // data, which would destroy the contents of the cursor which may
488 // just be filled by the user.
489 // <group>
498 //</group>
499
500 // Function which checks the internals of the class for consistency.
501 // Returns True if everything is fine. Otherwise returns False.
502 Bool ok() const;
503
504 //# Make members of parent class known.
505public:
510protected:
512};
513
514
515
516} //# NAMESPACE CASACORE - END
517
518//# See comments in Lattice.h why Lattice.tcc is included here.
519#ifndef CASACORE_NO_AUTO_TEMPLATES
520#include <casacore/lattices/Lattices/Lattice.tcc>
521#include <casacore/lattices/Lattices/LatticeIterator.tcc>
522#endif //# CASACORE_NO_AUTO_TEMPLATES
523#endif
A read/write lattice iterator.
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
this file contains all the compiler specific defines
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