casa
$Rev:20696$
|
00001 //# Cube.h: A 3-D Specialization of the Array Class 00002 //# Copyright (C) 1993,1994,1995,1996,1999,2000,2001,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: Cube.h 21130 2011-10-18 07:39:05Z gervandiepen $ 00027 00028 #ifndef CASA_CUBE_H 00029 #define CASA_CUBE_H 00030 00031 00032 //# Includes 00033 #include <casa/Arrays/Array.h> 00034 00035 namespace casa { //#Begin casa namespace 00036 00037 //# Forward Declarations 00038 template<class T> class Matrix; 00039 00040 00041 // <summary> A 3-D Specialization of the Array class </summary> 00042 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00043 // </reviewed> 00044 // 00045 // Cube objects are three-dimensional specializations (e.g., more convenient 00046 // and efficient indexing) of the general Array class. You might also want 00047 // to look at the Array documentation to see inherited functionality. A 00048 // tutorial on using the array classes in general is available in the 00049 // "AIPS++ Programming Manual". 00050 // 00051 // Generally the member functions of Array are also available in 00052 // Cube versions which take a pair of integers where the array 00053 // needs an IPosition. Since the Cube 00054 // is three-dimensional, the IPositions are overkill, although you may 00055 // use those versions if you want to. 00056 // <srcblock> 00057 // Cube<Int> ci(100,100,100); // Shape is 100x100 00058 // ci.resize(50,50,50); // Shape now 50x50 00059 // </srcblock> 00060 // 00061 // Slices may be taken with the Slice class. To take a slice, one "indexes" 00062 // with one Slice(start, length, inc) for each axis, where end and inc 00063 // are optional. Additionally, there is an xyPlane() 00064 // member function which return a Matrix which corresponds to some plane: 00065 // <srcblock> 00066 // Cube<Float> cube(10,20,30); 00067 // for(uInt i=0; i < 30; i++) { 00068 // cube.xyPlane(i) = i; // Set every 10x20 plane to its "height" 00069 // } 00070 // </srcblock> 00071 // 00072 // Element-by-element arithmetic and logical operations are available (in 00073 // aips/ArrayMath.h and aips/ArrayLogical.h). 00074 // 00075 // As with the Arrays, if the preprocessor symbol AIPS_DEBUG is 00076 // defined at compile time invariants will be checked on entry to most 00077 // member functions. Additionally, if AIPS_ARRAY_INDEX_CHECK is defined 00078 // index operations will be bounds-checked. Neither of these should 00079 // be defined for production code. 00080 00081 template<class T> class Cube : public Array<T> 00082 { 00083 public: 00084 00085 // A Cube of length zero in each dimension; zero origin. 00086 Cube(); 00087 00088 // A l1xl2xl3 sized cube. 00089 Cube(uInt l1, uInt l2, uInt l3); 00090 00091 // A l1xl2xl3 sized cube. 00092 // Fill it with the initial value. 00093 Cube(uInt l1, uInt l2, uInt l3, const T &initialValue); 00094 00095 // A Cube where the shape ("len") is defined with IPositions. 00096 Cube(const IPosition &len); 00097 00098 // A Cube where the shape ("len") is defined with IPositions. 00099 // Fill it with the initial value. 00100 Cube(const IPosition &len, const T &initialValue); 00101 00102 // The copy constructor uses reference semantics. 00103 Cube(const Cube<T> &); 00104 00105 // Construct a cube by reference from "other". "other must have 00106 // ndim() of 3 or less. The warning which applies to the copy constructor 00107 // is also valid here. 00108 Cube(const Array<T> &); 00109 00110 // Create an Cube of a given shape from a pointer. 00111 Cube(const IPosition &shape, T *storage, StorageInitPolicy policy = COPY); 00112 // Create an Cube of a given shape from a pointer. Because the pointer 00113 // is const, a copy is always made. 00114 Cube(const IPosition &shape, const T *storage); 00115 00116 // Define a destructor, otherwise the (SUN) compiler makes a static one. 00117 virtual ~Cube(); 00118 00119 // Assign the other array (which must be dimension 3) to this cube. 00120 // If the shapes mismatch, this array is resized. 00121 virtual void assign (const Array<T>& other); 00122 00123 // Make this cube a reference to other. Other must be of dimensionality 00124 // 3 or less. 00125 virtual void reference(const Array<T> &other); 00126 00127 // Resize to the given shape. 00128 // Resize without argument is equal to resize(0,0,0). 00129 // <group> 00130 void resize(uInt nx, uInt ny, uInt nz, Bool copyValues=False); 00131 virtual void resize(); 00132 virtual void resize(const IPosition &newShape, Bool copyValues=False); 00133 // </group> 00134 00135 // Copy the values from other to this cube. If this cube has zero 00136 // elements then it will resize to be the same shape as other; otherwise 00137 // other must conform to this. 00138 // Note that the assign function can be used to assign a 00139 // non-conforming cube. 00140 // <group> 00141 Cube<T> &operator=(const Cube<T> &other); 00142 virtual Array<T> &operator=(const Array<T> &other); 00143 // </group> 00144 00145 // Copy val into every element of this cube; i.e. behaves as if 00146 // val were a constant conformant cube. 00147 Array<T> &operator=(const T &val) 00148 { return Array<T>::operator=(val); } 00149 00150 // Copy to this those values in marray whose corresponding elements 00151 // in marray's mask are True. 00152 Cube<T> &operator= (const MaskedArray<T> &marray) 00153 { Array<T> (*this) = marray; return *this; } 00154 00155 00156 // Single-pixel addressing. If AIPS_ARRAY_INDEX_CHECK is defined, 00157 // bounds checking is performed. 00158 // <group> 00159 T &operator()(const IPosition &i) 00160 { return Array<T>::operator()(i); } 00161 const T &operator()(const IPosition &i) const 00162 { return Array<T>::operator()(i); } 00163 00164 T &operator()(uInt i1, uInt i2, uInt i3) 00165 { 00166 #if defined(AIPS_ARRAY_INDEX_CHECK) 00167 this->validateIndex(i1, i2, i3); // Throws an exception on failure 00168 #endif 00169 return this->begin_p[i1*xinc_p + i2*yinc_p + i3*zinc_p]; 00170 } 00171 00172 const T &operator()(uInt i1, uInt i2, uInt i3) const 00173 { 00174 #if defined(AIPS_ARRAY_INDEX_CHECK) 00175 this->validateIndex(i1, i2, i3); // Throws an exception on failure 00176 #endif 00177 return this->begin_p[i1*xinc_p + i2*yinc_p + i3*zinc_p]; 00178 } 00179 00180 //# Have function at (temporarily) to check if test on contiguous is 00181 //# indeed slower than always using multiplication in operator() 00182 T &at(uInt i1, uInt i2, uInt i3) 00183 { 00184 #if defined(AIPS_ARRAY_INDEX_CHECK) 00185 this->validateIndex(i1, i2, i3); // Throws an exception on failure 00186 #endif 00187 return this->contiguous_p ? this->begin_p[i1 + i2*yinc_p + i3*zinc_p] : 00188 this->begin_p[i1*xinc_p + i2*yinc_p + i3*zinc_p]; 00189 } 00190 00191 const T &at(uInt i1, uInt i2, uInt i3) const 00192 { 00193 #if defined(AIPS_ARRAY_INDEX_CHECK) 00194 this->validateIndex(i1, i2, i3); // Throws an exception on failure 00195 #endif 00196 return this->contiguous_p ? this->begin_p[i1 + i2*yinc_p + i3*zinc_p] : 00197 this->begin_p[i1*xinc_p + i2*yinc_p + i3*zinc_p]; 00198 } 00199 // </group> 00200 00201 // Take a slice of this cube. Slices are always indexed starting 00202 // at zero. This uses reference semantics, i.e. changing a value 00203 // in the slice changes the original. 00204 // <srcblock> 00205 // Cube<Double> vd(100,100,100); 00206 // //... 00207 // vd(Slice(0,10),Slice(10,10,Slice(0,10))) = -1.0; // sub-cube set to -1.0 00208 // </srcblock> 00209 // <group> 00210 Cube<T> operator()(const Slice &sliceX, const Slice &sliceY, 00211 const Slice &sliceZ); 00212 const Cube<T> operator()(const Slice &sliceX, const Slice &sliceY, 00213 const Slice &sliceZ) const; 00214 // </group> 00215 00216 // Slice using IPositions. Required to be defined, otherwise the base 00217 // class versions are hidden. 00218 // <group> 00219 Array<T> operator()(const IPosition &blc, const IPosition &trc, 00220 const IPosition &incr) 00221 { return Array<T>::operator()(blc,trc,incr); } 00222 const Array<T> operator()(const IPosition &blc, const IPosition &trc, 00223 const IPosition &incr) const 00224 { return Array<T>::operator()(blc,trc,incr); } 00225 Array<T> operator()(const IPosition &blc, const IPosition &trc) 00226 { return Array<T>::operator()(blc,trc); } 00227 const Array<T> operator()(const IPosition &blc, const IPosition &trc) const 00228 { return Array<T>::operator()(blc,trc); } 00229 Array<T> operator()(const Slicer& slicer) 00230 { return Array<T>::operator()(slicer); } 00231 const Array<T> operator()(const Slicer& slicer) const 00232 { return Array<T>::operator()(slicer); } 00233 // </group> 00234 00235 00236 // The array is masked by the input LogicalArray. 00237 // This mask must conform to the array. 00238 // <group> 00239 00240 // Return a MaskedArray. 00241 const MaskedArray<T> operator() (const LogicalArray &mask) const 00242 { return Array<T>::operator() (mask); } 00243 00244 // Return a MaskedArray. 00245 MaskedArray<T> operator() (const LogicalArray &mask) 00246 { return Array<T>::operator() (mask); } 00247 00248 // </group> 00249 00250 00251 // The array is masked by the input MaskedLogicalArray. 00252 // The mask is effectively the AND of the internal LogicalArray 00253 // and the internal mask of the MaskedLogicalArray. 00254 // The MaskedLogicalArray must conform to the array. 00255 // <group> 00256 00257 // Return a MaskedArray. 00258 const MaskedArray<T> operator() (const MaskedLogicalArray &mask) const 00259 { return Array<T>::operator() (mask); } 00260 00261 // Return a MaskedArray. 00262 MaskedArray<T> operator() (const MaskedLogicalArray &mask) 00263 { return Array<T>::operator() (mask); } 00264 00265 // </group> 00266 00267 00268 // Extract a plane as a matrix referencing the original data. 00269 // Of course you could also use a Matrix 00270 // iterator on the cube. 00271 // <group> 00272 Matrix<T> xyPlane(uInt zplane); 00273 const Matrix<T> xyPlane(uInt zplane) const; 00274 Matrix<T> xzPlane(uInt yplane); 00275 const Matrix<T> xzPlane(uInt yplane) const; 00276 Matrix<T> yzPlane(uInt xplane); 00277 const Matrix<T> yzPlane(uInt xplane) const; 00278 // </group> 00279 00280 // The length of each axis of the cube. 00281 // <group> 00282 void shape(Int &s1, Int &s2, Int &s3) const 00283 { s1 = this->length_p(0); s2=this->length_p(1); s3=this->length_p(2); } 00284 const IPosition &shape() const 00285 { return this->length_p; } 00286 // </group> 00287 00288 // The number of rows in the Cube, i.e. the length of the first axis. 00289 uInt nrow() const 00290 { return this->length_p(0); } 00291 00292 // The number of columns in the Cube, i.e. the length of the 2nd axis. 00293 uInt ncolumn() const 00294 { return this->length_p(1); } 00295 00296 // The number of planes in the Cube, i.e. the length of the 3rd axis. 00297 uInt nplane() const 00298 { return this->length_p(2); } 00299 00300 // Replace the data values with those in the pointer <src>storage</src>. 00301 // The results are undefined is storage does not point at nelements() or 00302 // more data elements. After takeStorage() is called, <src>unique()</src> 00303 // is True. 00304 // <group> 00305 virtual void takeStorage(const IPosition &shape, T *storage, 00306 StorageInitPolicy policy = COPY); 00307 // Since the pointer is const, a copy is always taken. 00308 virtual void takeStorage(const IPosition &shape, const T *storage); 00309 // </group> 00310 00311 // Checks that the cube is consistent (invariants check out). 00312 virtual Bool ok() const; 00313 00314 protected: 00315 // Remove the degenerate axes from other and store result in this cube. 00316 // An exception is thrown if removing degenerate axes does not result 00317 // in a cube. 00318 virtual void doNonDegenerate(const Array<T> &other, 00319 const IPosition &ignoreAxes); 00320 00321 private: 00322 // Cached constants to improve indexing. 00323 Int xinc_p, yinc_p, zinc_p; 00324 // Helper fn to calculate the indexing constants. 00325 void makeIndexingConstants(); 00326 }; 00327 00328 } //#End casa namespace 00329 #ifndef CASACORE_NO_AUTO_TEMPLATES 00330 #include <casa/Arrays/Cube.tcc> 00331 #endif //# CASACORE_NO_AUTO_TEMPLATES 00332 #endif