casa
$Rev:20696$
|
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