casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
LatticeIterator.h
Go to the documentation of this file.
00001 //# LatticeIterator.h: Iterators for Lattices: readonly or read/write
00002 //# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2003
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: LatticeIterator.h 20229 2008-01-29 15:19:06Z gervandiepen $
00027 
00028 #ifndef LATTICES_LATTICEITERATOR_H
00029 #define LATTICES_LATTICEITERATOR_H
00030 
00031 //# Includes
00032 #include <casa/aips.h>
00033 #include <lattices/Lattices/Lattice.h>
00034 #include <lattices/Lattices/LatticeIterInterface.h>
00035 #include <casa/Utilities/CountedPtr.h>
00036 
00037 namespace casa { //# NAMESPACE CASA - BEGIN
00038 
00039 //# Forward Declarations
00040 class IPosition;
00041 class LatticeNavigator;
00042 template <class T> class Array;
00043 template <class T> class Cube;
00044 template <class T> class Matrix;
00045 template <class T> class Vector;
00046 
00047 
00048 // <summary>
00049 // A readonly iterator for Lattices
00050 // </summary>
00051 
00052 // <use visibility=export>
00053 
00054 // <reviewed reviewer="Peter Barnes" date="1999/10/30" tests="tLatticeIterator.cc">
00055 // </reviewed>
00056 
00057 // <prerequisite>
00058 //   <li> <linkto class="Lattice">Lattice</linkto>
00059 //   <li> <linkto class="LatticeNavigator">LatticeNavigator</linkto>
00060 //   <li> <linkto class="Array">Array</linkto>
00061 // </prerequisite>
00062 
00063 // <etymology>
00064 // The leading "RO" is shorthand for "readonly", which indicates that an
00065 // RO_LatticeIterator is used for traversing a Lattice, examining and 
00066 // possibly extracting its contents, but not for modifying it.
00067 // </etymology>
00068 
00069 // <synopsis> 
00070 // This class provides a convenient way to traverse any class derived from
00071 // Lattice. You can iterate through the Lattice's data from "start" to "end"
00072 // by calling <src>operator++</src>, and reverse direction by calling
00073 // <src>operator--</src>.  You can return immediately to the beginning by
00074 // calling the <src>reset</src> function.  The RO_LatticeIterator gives the
00075 // user the opportunity to methodically walk through the data, in an
00076 // efficient way.
00077 // <p>
00078 // The supplied <linkto class=LatticeNavigator>LatticeNavigator</linkto>
00079 // determines how to step through the Lattice. It can, for instance,
00080 // be line by line, but it can also be in a more complicated way.
00081 // When no navigator is supplied, a default navigator will be used
00082 // which steps in the optimum way.
00083 // <p>
00084 // A cursor (which is an <linkto class=Array>Array</linkto> object) is
00085 // used to return the data for each step in the iteration process.
00086 // Depending on the navigator used the cursor can have a different shape
00087 // for each step of the iteration. This is especially true when the
00088 // end of an axis is reached for a non-integrally fitting cursor shape.
00089 // <br> The cursor() function returns an Array which has the same
00090 // dimensionality as the Lattice. It is, however, also possible to get
00091 // an Array with a lower dimensionality by using the correct function
00092 // in the group <src>vectorCursor()</src>, <src>matrixCursor()</src>, and
00093 // <src>cubeCursor()</src>. Those functions remove (some) degenerated axes
00094 // resulting in a vector, matrix or cube.
00095 // When, for example, a LatticeStepper with shape [64,1,1] is used, the
00096 // <src>vectorCursor()</src> can be used. It will remove the degenerated
00097 // axes (length 1) and return the cursor as a Vector object. Note that
00098 // <src>matrixCursor()</src> cannot be used, because removing the degenerated
00099 // axes results in a 1D array.
00100 // <p>
00101 // Generally iterators should not be long-lived objects - create new ones
00102 // when needed rather than keeping one around for a long time to be
00103 // reused. This is because the cache memory used by the cursor will be
00104 // released when the iterator is destroyed.
00105 // <p>
00106 // The purpose of this class is to hide the possibly complicated
00107 // implementation and structure of the Lattice classes, and allow you to
00108 // iterate through a Lattice with the same ease as one iterates through a
00109 // Fortran or C vector.  For example, and assuming that initialization has
00110 // been done properly, here's a typical 'for' loop:
00111 // <srcblock>
00112 //  // code omitted  which associates Lattice object and the iterator
00113 //  for (iterator.reset(); !iterator.atEnd(); iterator++) {
00114 //    meanValue = mean(iterator.cursor()); 
00115 //  }
00116 // </srcblock>
00117 // The iterator's <src>cursor()</src> member function returns a reference to
00118 // that part of the Lattice data which is presently "seen" by the
00119 // LatticeIterator.
00120 // <p>
00121 // Before explaining the initialization of an iterator, the LatticeNavigator
00122 // class must be further introduced. This is an abstract base class, from which
00123 // concrete navigators are derived. After one of these is created, you
00124 // attach it to the LatticeIterator, and it provides a specific technique
00125 // for navigating through the Lattice. Different navigators deliver
00126 // different traversal schemes.  The most basic is
00127 // <linkto class=LatticeStepper>LatticeStepper</linkto>, which
00128 // moves a specified shape sequentially through the Lattice -- for example,
00129 // by moving one plane at a time, front to back, through a cube.  Another
00130 // (future) navigator might be designed to move a small, 2-dimensional plane
00131 // through a cube, centering each iteration on the brightest pixel of the
00132 // cube's plane, and ignoring the darker regions of the cube.
00133 // <p>
00134 // The performance and memory usage of an iteration through a lattice
00135 // (in particular through a <linkto class=PagedArray>PagedArray</linkto>)
00136 // depends very heavily on the navigator used. Currently there are three
00137 // navigators available:
00138 // <ol>
00139 //  <li> <linkto class=LatticeStepper>LatticeStepper</linkto> steps
00140 // sequentially through a lattice with the given cursor shape.
00141 // This can use a lot of memory for the PagedArray cache.
00142 //  <li> <linkto class=TiledLineStepper>TiledLineStepper</linkto>
00143 // steps line by line through a lattice. However, it is doing that
00144 // in such a way that as few tiles as possible need to kept in the
00145 // PagedArray cache. This reduces memory usage considerably.
00146 //  <li> <linkto class=TileStepper>TileStepper</linkto> steps tile
00147 // by tile through a lattice. This navigator requires a PagedArray cache
00148 // of 1 tile only. However, it can only be used for application in which
00149 // the iteration order is not important (e.g. addition, determining max).
00150 // </ol>
00151 // The class <linkto class=LatticeApply>LatticeApply</linkto> is very useful
00152 // to iterate through a Lattice while applying an algorithm. It makes it
00153 // possible for the user to concentrate on the algorithm.
00154 // <p>
00155 // Here's a typical iterator declaration:
00156 // <srcblock>
00157 // RO_LatticeIterator<Float> iterator(pagedArray, stepper);
00158 // </srcblock>
00159 // The template identifier <src>Float</src> defines the data type of 
00160 // Array object that will be the iterator's cursor. 
00161 //<br>
00162 // The <src>pagedArray</src> constructor argument names a PagedArray object,
00163 // which is what the iterator will traverse.  The <src>stepper</src>
00164 // argument is a LatticeStepper which defines the method of iteration.
00165 
00166 // <example>
00167 // When passed the name of a previously created PagedArray stored on disk,
00168 // this function will traverse the whole array, and report the average value
00169 // of all of the elements. Imagine that the filename contains a PagedArray
00170 // with dimension 64 x 64 x 8.
00171 // <srcblock>
00172 // void demonstrateIterator (const String& filename)
00173 // {
00174 //   PagedArray<Float> pagedArray(filename);
00175 //   IPosition latticeShape = pagedArray.shape();
00176 //   cout << "paged array has shape: " << latticeShape << endl;
00177 // 
00178 //   // Construct the iterator.  since we only want to read the PagedArray,
00179 //   // use the read-only class, which disallows writing back to the cursor.
00180 //   // No navigator is given, so the default TileStepper is used
00181 //   // which ensures optimum performance.
00182 //   RO_LatticeIterator<Float> iterator(pagedArray);
00183 // 
00184 //   // Add for each iteration step the sum of the cursor elements to the sum.
00185 //   // Note that the cursor is an Array object and that the function sum
00186 //   // is defined in ArrayMath.h.
00187 //   Float runningSum = 0.0;
00188 //   for (iterator.reset(); !iterator.atEnd(); iterator++) {
00189 //       runningSum += sum(iterator.cursor());
00190 //   }
00191 //   cout << "average value, from demonstrateIterator: " 
00192 //       << runningSum / latticeShape.product() << endl;
00193 // }
00194 // </srcblock>
00195 // </example>
00196 
00197 // <motivation>
00198 // Iterator classes are a standard feature in C++ libraries -- they
00199 // provide convenience and allow the implementation of the "iteratee"
00200 // to be kept hidden.
00201 // </motivation>
00202 
00203 //# <todo asof="1995/09/12">
00204 //#  <li>
00205 //# </todo>
00206 
00207 
00208 template <class T> class RO_LatticeIterator
00209 {
00210 public:
00211 
00212   // The default constructor creates an empty object which is practically
00213   // unusable.
00214   // It can only be used as the source or target of an assignment. It can
00215   // also be used as the source for the copy constructor and the copy function.
00216   // Other functions do not check if the object is empty and will usually
00217   // give a segmentation fault.
00218   // The function isNull() can be used to test if the object is empty.
00219   RO_LatticeIterator();
00220 
00221   // Construct the Iterator with the supplied data.
00222   // It uses a TileStepper as the default iteration strategy.
00223   // useRef=True means that if possible the cursor arrays returned
00224   // reference the data in the underlying lattice. This is only possible
00225   // for ArrayLattice objects (or e.g. a SubLattice using it).
00226   explicit RO_LatticeIterator (const Lattice<T>& data, Bool useRef=True);
00227 
00228   // Construct the Iterator with the supplied data, and iteration strategy
00229   RO_LatticeIterator (const Lattice<T>& data, const LatticeNavigator& method,
00230                       Bool useRef=True);
00231 
00232   // Construct the Iterator with the supplied data.
00233   // It uses a LatticeStepper with the supplied cursor shape as the
00234   // iteration strategy.
00235   RO_LatticeIterator (const Lattice<T>& data, const IPosition& cursorShape,
00236                       Bool useRef=True);
00237 
00238   // The copy constructor uses reference semantics (ie. NO real copy is made).
00239   // The function <src>copy</src> can be used to make a true copy.
00240   RO_LatticeIterator (const RO_LatticeIterator<T>& other);
00241  
00242   // Destructor (cleans up dangling references and releases memory)
00243   ~RO_LatticeIterator();
00244 
00245   // Assignment uses reference semantics (ie. NO real copy is made).
00246   // The function <src>copy</src> can be used to make a true copy.
00247   RO_LatticeIterator<T>& operator= (const RO_LatticeIterator<T>& other);
00248 
00249   // Make a copy of the iterator object.
00250   // This means that an independent navigator object is created to
00251   // be able to iterate independently through the same Lattice.
00252   // The position in the copied navigator is the same as the original.
00253   // The reset function has to be used to start at the beginning.
00254   // <br>Note that if the Lattice uses a cache (e.g. PagedArray), the
00255   // cache is shared by the iterators.
00256   RO_LatticeIterator<T> copy() const;
00257 
00258   // Is the iterator object empty?
00259   Bool isNull() const
00260     { return itsIterPtr.null(); }
00261 
00262   // Return the underlying lattice.
00263   Lattice<T>& lattice() const
00264     { return itsIterPtr->lattice(); }
00265     
00266   // Increment operator - increment the cursor to the next position.  These
00267   // functions are forwarded to the current LatticeNavigator and both
00268   // postfix and prefix versions will do the same thing.
00269   // <br>They return True if the cursor moved (which should always be the
00270   // case if the iterator is not at the end).
00271   // <group>
00272   Bool operator++();
00273   Bool operator++(int);
00274   // </group>
00275 
00276   // Decrement operator - decrement the cursor to the previous
00277   // position. These functions are forwarded to the current LatticeNavigator
00278   // and both postfix and prefix versions will do the same thing.
00279   // <br>They return True if the cursor moved (which should always be the
00280   // case if the iterator is not at the start).
00281   // <group>
00282   Bool operator--();
00283   Bool operator--(int);
00284   // </group>
00285   
00286   // Function which resets the cursor to the beginning of the Lattice and
00287   // resets the number of steps taken to zero.
00288   void reset();
00289 
00290   // Function which returns a value of "True" if the cursor is at the
00291   // beginning of the Lattice, otherwise, returns "False".
00292   Bool atStart() const;
00293 
00294   // Function which returns a value of "True" if an attempt has been made
00295   // to move the cursor beyond the end of the Lattice.
00296   Bool atEnd() const;
00297   
00298   // Function to return the number of steps (increments or decrements) taken
00299   // since construction (or since last reset).  This is a running count of
00300   // all cursor movement, thus doing N increments followed by N decrements
00301   // results in 2N steps.
00302   uInt nsteps() const;
00303   
00304   // Function which returns the current position of the beginning of the
00305   // cursor within the Lattice. The returned IPosition will have the same
00306   // number of axes as the underlying Lattice.
00307   IPosition position() const;
00308 
00309   // Function which returns the current position of the end of the
00310   // cursor. The returned IPosition will have the same number of axes as the
00311   // underlying Lattice.
00312   IPosition endPosition() const;
00313 
00314   // Function which returns the shape of the Lattice being iterated through.
00315   // The returned IPosition will always have the same number of axes as the
00316   // underlying Lattice.
00317   IPosition latticeShape() const;
00318 
00319   // Function which returns the shape of the cursor which is iterating
00320   // through the Lattice. The returned IPosition will have the same number
00321   // of axes as the underlying Lattice.
00322   IPosition cursorShape() const;
00323 
00324   // Functions which returns a window to the data in the Lattice. These are
00325   // used to read the data within the Lattice.  Use the function that is
00326   // appropriate to the current cursor dimension, AFTER REMOVING DEGENERATE
00327   // AXES, or use the <src>cursor</src> function which works with any number
00328   // of dimensions in the cursor. A call of the function whose return value
00329   // is inappropriate with respect to the current cursor dimension will
00330   // throw an exception (AipsError).
00331   // <group>
00332   const Vector<T>& vectorCursor() const;
00333   const Matrix<T>& matrixCursor() const; 
00334   const Cube<T>& cubeCursor() const; 
00335   const Array<T>& cursor() const; 
00336   // </group>
00337   
00338   // Function which checks the internals of the class for consistency.
00339   // Returns True if everything is fine otherwise returns False.
00340   Bool ok() const;
00341 
00342 protected:
00343   // The pointer to the Iterator
00344   CountedPtr<LatticeIterInterface<T> > itsIterPtr;
00345 };
00346 
00347 
00348 
00349 // <summary>
00350 // A read/write lattice iterator
00351 // </summary>
00352 
00353 // <use visibility=export>
00354 
00355 // <reviewed reviewer="Peter Barnes" date="1999/10/30" tests="tLatticeIterator.cc">
00356 // </reviewed>
00357 
00358 // <prerequisite>
00359 //   <li> <linkto class="RO_LatticeIterator">RO_LatticeIterator</linkto>
00360 //   <li> <linkto class="Lattice">Lattice</linkto>
00361 //   <li> <linkto class="LatticeNavigator">LatticeNavigator</linkto>
00362 //   <li> <linkto class="Array">Array</linkto>
00363 // </prerequisite>
00364 
00365 // <synopsis>
00366 // LatticeIterator differs from the RO_LatticeIterator class in that 
00367 // the window into the Lattice data which moves with each iterative step may
00368 // be used to alter the Lattice data itself.  The moving "cursor" gives the
00369 // user the door to reach in and change the basic Lattice before moving to
00370 // another section of the Lattice.
00371 // <p>
00372 // LatticeIterator can be used in 3 ways:
00373 // <br> - For readonly purposes using the cursor() functions. Note that if
00374 // the entire iteration is readonly, it is better to use an
00375 // <linkto class=RO_LatticeIterator>RO_LatticeIterator</linkto> object.
00376 // <br> - To update (part of)the contents of the lattice (e.g. clip the value
00377 // of some pixels). For this purpose the <src>rwCursor</src> functions
00378 // should be used. They read the data (if not read yet) and mark the
00379 // cursor for write.
00380 // <br> - To fill the lattice. For this purpose the <src>woCursor</src>
00381 // functions should be used. They do not read the data, but only mark the
00382 // cursor for write.
00383 // <p>
00384 // When needed, writing the cursor data is done automatically when the
00385 // cursor position changes or when the iterator is destructed.
00386 // </synopsis>
00387 
00388 // <example>
00389 // Here's an iterator that runs through a cube, assigning every element
00390 // of each plane of the cube a value equal to the number of the plane.
00391 // See <linkto class=LatticeStepper>LatticeStepper</linkto> for an
00392 // explanation of the navigator used here.
00393 // <srcblock>
00394 //      PagedArray<Float> pa("someName");
00395 //      IPosition windowShape(2,pa.shape(0), pa.shape(1));
00396 //      LatticeStepper stepper(pa.shape(), windowShape);
00397 //      LatticeIterator<Float> iterator(pa, stepper);
00398 //      Int planeNumber = 0;
00399 //      for (iterator.reset(); !iterator.atEnd(); iterator++) {
00400 //        iterator.woCursor() = planeNumber++;
00401 //      }
00402 // </srcblock>
00403 //
00404 // Here's an iterator that runs through a cube, subtracting the mean from
00405 // each line of the cube with a mean < 0.
00406 // See <linkto class=TiledLineStepper>TiledLineStepper</linkto> for an
00407 // explanation of the navigator used here.
00408 // <srcblock>
00409 //      PagedArray<Float> pa("someName");
00410 //      TiledLineStepper stepper(pa.shape(), pa.niceCursorShape(), 0);
00411 //      LatticeIterator<Float> iterator(pa, stepper);
00412 //      Int planeNumber = 0;
00413 //      for (iterator.reset(); !iterator.atEnd(); iterator++) {
00414 //        Float meanLine = mean(iterator.cursor());
00415 //        if (meanLine < 0) {
00416 //          iterator.rwCursor() -= meanLine;
00417 //        }
00418 //      }
00419 // </srcblock>
00420 // Note that in this last example no more vectors than required are written.
00421 // This is achieved by using the readonly function <src>cursor</src> in
00422 // the test and using <src>rwCursor</src> only when data needs to be changed.
00423 // <br>Note that <src>rwCursor</src> does not read the data again. They are
00424 // still readily available.
00425 // </example>
00426 
00427 
00428 template <class T> class LatticeIterator : public RO_LatticeIterator<T>
00429 {
00430 public:
00431   
00432   // The default constructor creates an empty object which is practically
00433   // unusable.
00434   // It can only be used as the source or target of an assignment. It can
00435   // also be used as the source for the copy constructor and the copy function.
00436   // Other functions do not check if the object is empty and will usually
00437   // give a segmentation fault.
00438   // The function isNull() can be used to test if the object is empty.
00439   LatticeIterator();
00440 
00441   // Construct the Iterator with the supplied data.
00442   // It uses a TileStepper as the default iteration strategy.
00443   // useRef=True means that if possible the cursor arrays returned
00444   // reference the data in the underlying lattice. This is only possible
00445   // for ArrayLattice objects (or e.g. a SubLattice using it).
00446   explicit LatticeIterator (Lattice<T>& data, Bool useRef=True);
00447 
00448   // Construct the Iterator with the supplied data, and iteration strategy
00449   LatticeIterator (Lattice<T>& data, const LatticeNavigator& method,
00450                    Bool useRef=True);
00451   
00452   // Iterate through the data with a LatticeStepper that has uses the
00453   // supplied cursorShape.
00454   LatticeIterator (Lattice<T>& data, const IPosition& cursorShape,
00455                    Bool useRef=True);
00456   
00457   // The copy constructor uses reference semantics (ie. NO real copy is made).
00458   // The function <src>copy</src> can be used to make a true copy.
00459   LatticeIterator (const LatticeIterator<T>& other);
00460   
00461   // destructor (cleans up dangling references and releases memory)
00462   ~LatticeIterator();
00463   
00464   // Assignment uses reference semantics (ie. NO real copy is made).
00465   // The function <src>copy</src> can be used to make a true copy.
00466   LatticeIterator<T>& operator= (const LatticeIterator<T>& other);  
00467   
00468   // Make a copy of the iterator object.
00469   // This means that an independent navigator object is created to
00470   // be able to iterate independently through the same Lattice.
00471   // The position in the copied navigator is the same as the original.
00472   // The reset function has to be used to start at the beginning.
00473   // <br>Note that if the Lattice uses a cache (e.g. PagedArray), the
00474   // cache is shared by the iterators.
00475   LatticeIterator<T> copy() const;
00476     
00477   // Functions to return a window to the data in the Lattice. Use the function
00478   // that is appropriate to the current cursor dimension, AFTER REMOVING
00479   // DEGENERATE AXES, or use the <src>cursor</src> function which works with
00480   // any number of dimensions in the cursor. A call of the function whose
00481   // return value is inappropriate with respect to the current cursor
00482   // dimension will throw an exception (AipsError) (e.g. VectorCursor
00483   // cannot be used when the cursor is 2D).
00484   // <br>
00485   // When the iterator state changes (e.g. by moving, destruction) the
00486   // data are automatically rewritten before the iterator state is changed.
00487   // <br>The <src>rw</src> (read/write) versions should be used to read the
00488   // data first. They are useful to update a lattice.
00489   // The <src>wo</src> (writeonly) versions do not read the data.
00490   // They only return a cursor of the correct shape and are useful to
00491   // fill a lattice. Note that it sets the state to 'data read'. I.e.,
00492   // a subsequent call to, say, <src>cursor()</src> does not read the
00493   // data, which would destroy the contents of the cursor which may
00494   // just be filled by the user.
00495   // <group>
00496   Vector<T>& rwVectorCursor();
00497   Matrix<T>& rwMatrixCursor();
00498   Cube<T>&   rwCubeCursor();
00499   Array<T>&  rwCursor();
00500   Vector<T>& woVectorCursor();
00501   Matrix<T>& woMatrixCursor();
00502   Cube<T>&   woCubeCursor();
00503   Array<T>&  woCursor();
00504   //</group>
00505   
00506   // Function which checks the internals of the class for consistency.
00507   // Returns True if everything is fine. Otherwise returns False.
00508   Bool ok() const;
00509 
00510   //# Make members of parent class known.
00511 public:
00512   using RO_LatticeIterator<T>::isNull;
00513   using RO_LatticeIterator<T>::position;
00514   using RO_LatticeIterator<T>::endPosition;
00515   using RO_LatticeIterator<T>::cursorShape;
00516 protected:
00517   using RO_LatticeIterator<T>::itsIterPtr;
00518 };
00519 
00520 
00521 
00522 } //# NAMESPACE CASA - END
00523 
00524 //# See comments in Lattice.h why Lattice.tcc is included here.
00525 #ifndef CASACORE_NO_AUTO_TEMPLATES
00526 #include <lattices/Lattices/Lattice.tcc>
00527 #include <lattices/Lattices/LatticeIterator.tcc>
00528 #endif //# CASACORE_NO_AUTO_TEMPLATES
00529 #endif