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$ 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 T &operator()(uInt i1, uInt i2, uInt i3) 00164 { 00165 #if defined(AIPS_ARRAY_INDEX_CHECK) 00166 IPosition index(3); 00167 index(0) = i1; index(1) = i2; index(2) = i3; 00168 this->validateIndex(index); // Throws an exception on failure 00169 #endif 00170 return this->contiguous_p ? this->begin_p[i1 + i2*yinc_p + i3*zinc_p] : 00171 this->begin_p[i1*xinc_p + i2*yinc_p + i3*zinc_p]; 00172 } 00173 00174 const T &operator()(uInt i1, uInt i2, uInt i3) const 00175 { 00176 #if defined(AIPS_ARRAY_INDEX_CHECK) 00177 IPosition index(3); 00178 index(0) = i1; index(1) = i2; index(2) = i3; 00179 this->validateIndex(index); // Throws an exception on failure 00180 #endif 00181 return this->contiguous_p ? this->begin_p[i1 + i2*yinc_p + i3*zinc_p] : 00182 this->begin_p[i1*xinc_p + i2*yinc_p + i3*zinc_p]; 00183 } 00184 // </group> 00185 00186 // Take a slice of this cube. Slices are always indexed starting 00187 // at zero. This uses reference semantics, i.e. changing a value 00188 // in the slice changes the original. 00189 // <srcblock> 00190 // Cube<Double> vd(100,100,100); 00191 // //... 00192 // vd(Slice(0,10),Slice(10,10,Slice(0,10))) = -1.0; // sub-cube set to -1.0 00193 // </srcblock> 00194 Cube<T> operator()(const Slice &sliceX, const Slice &sliceY, 00195 const Slice &sliceZ); 00196 00197 // Slice using IPositions. Required to be defined, otherwise the base 00198 // class versions are hidden. 00199 // <group> 00200 Array<T> operator()(const IPosition &blc, const IPosition &trc, 00201 const IPosition &incr) 00202 { return Array<T>::operator()(blc,trc,incr); } 00203 Array<T> operator()(const IPosition &blc, const IPosition &trc) 00204 { return Array<T>::operator()(blc,trc); } 00205 Array<T> operator()(const Slicer& slicer) 00206 { return Array<T>::operator()(slicer); } 00207 // </group> 00208 00209 00210 // The array is masked by the input LogicalArray. 00211 // This mask must conform to the array. 00212 // <group> 00213 00214 // Return a MaskedArray. 00215 MaskedArray<T> operator() (const LogicalArray &mask) const 00216 { return Array<T>::operator() (mask); } 00217 00218 // Return a MaskedArray. 00219 MaskedArray<T> operator() (const LogicalArray &mask) 00220 { return Array<T>::operator() (mask); } 00221 00222 // </group> 00223 00224 00225 // The array is masked by the input MaskedLogicalArray. 00226 // The mask is effectively the AND of the internal LogicalArray 00227 // and the internal mask of the MaskedLogicalArray. 00228 // The MaskedLogicalArray must conform to the array. 00229 // <group> 00230 00231 // Return a MaskedArray. 00232 MaskedArray<T> operator() (const MaskedLogicalArray &mask) const 00233 { return Array<T>::operator() (mask); } 00234 00235 // Return a MaskedArray. 00236 MaskedArray<T> operator() (const MaskedLogicalArray &mask) 00237 { return Array<T>::operator() (mask); } 00238 00239 // </group> 00240 00241 00242 // Extract a plane as a cube. We could have xzPlane, etc also if that 00243 // would be of use to anyone. Of course you could also use a Matrix 00244 // iterator on the cube. 00245 // <group> 00246 Matrix<T> xyPlane(uInt zplane); 00247 const Matrix<T> xyPlane(uInt zplane) const; 00248 // </group> 00249 00250 // The length of each axis of the cube. 00251 // <group> 00252 void shape(Int &s1, Int &s2, Int &s3) const 00253 { s1 = this->length_p(0); s2=this->length_p(1); s3=this->length_p(2); } 00254 const IPosition &shape() const 00255 { return this->length_p; } 00256 // </group> 00257 00258 // The number of rows in the Cube, i.e. the length of the first axis. 00259 uInt nrow() const 00260 { return this->length_p(0); } 00261 00262 // The number of columns in the Cube, i.e. the length of the 2nd axis. 00263 uInt ncolumn() const 00264 { return this->length_p(1); } 00265 00266 // The number of planes in the Cube, i.e. the length of the 3rd axis. 00267 uInt nplane() const 00268 { return this->length_p(2); } 00269 00270 // Replace the data values with those in the pointer <src>storage</src>. 00271 // The results are undefined is storage does not point at nelements() or 00272 // more data elements. After takeStorage() is called, <src>unique()</src> 00273 // is True. 00274 // <group> 00275 virtual void takeStorage(const IPosition &shape, T *storage, 00276 StorageInitPolicy policy = COPY); 00277 // Since the pointer is const, a copy is always taken. 00278 virtual void takeStorage(const IPosition &shape, const T *storage); 00279 // </group> 00280 00281 // Checks that the cube is consistent (invariants check out). 00282 virtual Bool ok() const; 00283 00284 protected: 00285 // Remove the degenerate axes from other and store result in this cube. 00286 // An exception is thrown if removing degenerate axes does not result 00287 // in a cube. 00288 virtual void doNonDegenerate(Array<T> &other, const IPosition &ignoreAxes); 00289 00290 private: 00291 // Cached constants to improve indexing. 00292 Int xinc_p, yinc_p, zinc_p; 00293 // Helper fn to calculate the indexing constants. 00294 void makeIndexingConstants(); 00295 }; 00296 00297 } //#End casa namespace 00298 #ifndef AIPS_NO_TEMPLATE_SRC 00299 #include <casa/Arrays/Cube.cc> 00300 #endif //# AIPS_NO_TEMPLATE_SRC 00301 #endif
1.5.1