casa
$Rev:20696$
|
00001 //# CompressComplex.h: Virtual column engine to scale a table Complex array 00002 //# Copyright (C) 2001,2002,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: CompressComplex.h 20739 2009-09-29 01:15:15Z Malte.Marquarding $ 00027 00028 #ifndef TABLES_COMPRESSCOMPLEX_H 00029 #define TABLES_COMPRESSCOMPLEX_H 00030 00031 //# Includes 00032 #include <tables/Tables/BaseMappedArrayEngine.h> 00033 #include <tables/Tables/ScalarColumn.h> 00034 #include <casa/Arrays/Array.h> 00035 #include <casa/BasicSL/Complex.h> 00036 00037 00038 namespace casa { //# NAMESPACE CASA - BEGIN 00039 00040 // <summary> 00041 // Virtual column engine to scale a table Complex array 00042 // </summary> 00043 00044 // <use visibility=export> 00045 00046 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tCompressComplex.cc"> 00047 // </reviewed> 00048 00049 // <prerequisite> 00050 //# Classes you should understand before using this one. 00051 // <li> VirtualColumnEngine 00052 // <li> VirtualArrayColumn 00053 // </prerequisite> 00054 00055 // <synopsis> 00056 // CompressComplex is a virtual column engine which scales an array 00057 // of one type to another type to save disk storage. 00058 // This resembles the classic AIPS compress method which scales the 00059 // data from Complex to int. 00060 // The scale factor and offset values can be given in two ways: 00061 // <ul> 00062 // <li> As a fixed values which is used for all arrays in the column. 00063 // These values have to be given when constructing of the engine. 00064 // <li> As the name of a column. In this way each array in the 00065 // column has its own scale and offset value. 00066 // By default it uses auto-scaling (see below). 00067 // Otherwise the scale and offset value in a row must be put 00068 // before the array is put and should not be changed anymore. 00069 // </ul> 00070 // Auto-scaling means that the engine will determine the scale 00071 // and offset value itself when an array (or a slice) is put. 00072 // It does it by mapping the values in the array to the range [-32767,32767]. 00073 // At each put the scale/offset values are changed as needed. 00074 // Note that with auto-scaling <src>putSlice</src> can be somewhat 00075 // slower, because the entire array might need to be rescaled. 00076 // 00077 // As in FITS the scale and offset values are used as: 00078 // <br><src> True_value = Stored_value * scale + offset; </src> 00079 // 00080 // An engine object should be used for one column only, because the stored 00081 // column name is part of the engine. If it would be used for more than 00082 // one column, they would all share the same stored column. 00083 // When the engine is bound to a column, it is checked if the name 00084 // of that column matches the given virtual column name. 00085 // 00086 // The engine can be used for a column containing any kind of array 00087 // (thus direct or indirect, fixed or variable shaped)) as long as the 00088 // virtual array can be stored in the stored array. Thus a fixed shaped 00089 // virtual can use a variable shaped stored, but not vice versa. 00090 // A fixed shape indirect virtual can use a stored with direct arrays. 00091 // 00092 // This class can also serve as an example of how to implement 00093 // a virtual column engine. 00094 // </synopsis> 00095 00096 // <motivation> 00097 // This class allows to store data in a smaller representation. 00098 // It is needed to resemble the classic AIPS compress option. 00099 // 00100 // Because the engine can serve only one column, it was possible to 00101 // combine the engine and the column functionality in one class. 00102 // </motivation> 00103 00104 // <example> 00105 // <srcblock> 00106 // // Create the table description and 2 columns with indirect arrays in it. 00107 // // The Int column will be stored, while the double will be 00108 // // used as virtual. 00109 // TableDesc tableDesc ("", TableDesc::Scratch); 00110 // tableDesc.addColumn (ArrayColumnDesc<Int> ("storedArray")); 00111 // tableDesc.addColumn (ArrayColumnDesc<Complex> ("virtualArray")); 00112 // tableDesc.addColumn (ScalarColumnDesc<Complex> ("scale")); 00113 // tableDesc.addColumn (ScalarColumnDesc<Float> ("offset")); 00114 // 00115 // // Create a new table using the table description. 00116 // SetupNewTable newtab (tableDesc, "tab.data", Table::New); 00117 // 00118 // // Create the array scaling engine (with auto-scale) 00119 // // and bind it to the Complex column. 00120 // CompressComplex scalingEngine("virtualArray", "storedArray", 00121 // "scale", "offset"); 00122 // newtab.bindColumn ("virtualArray", scalingEngine); 00123 // // Create the table. 00124 // Table table (newtab); 00125 // 00126 // // Store a 3-D array (with dim. 2,3,4) into each row of the column. 00127 // // The shape of each array in the column is implicitly set by the put 00128 // // function. This will also set the shape of the underlying Int array. 00129 // ArrayColumn data (table, "virtualArray"); 00130 // Array<double> someArray(IPosition(4,2,3,4)); 00131 // someArray = 0; 00132 // for (uInt i=0, i<10; i++) { // table will have 10 rows 00133 // table.addRow(); 00134 // data.put (i, someArray) 00135 // } 00136 // </srcblock> 00137 // </example> 00138 00139 class CompressComplex : public BaseMappedArrayEngine<Complex, Int> 00140 { 00141 public: 00142 00143 // Construct an engine to scale all arrays in a column with 00144 // the given offset and scale factor. 00145 // StoredColumnName is the name of the column where the scaled 00146 // data will be put and must have data type Int. 00147 // The virtual column using this engine must have data type Complex. 00148 CompressComplex (const String& virtualColumnName, 00149 const String& storedColumnName, 00150 Float scale, 00151 Float offset = 0); 00152 00153 // Construct an engine to scale the arrays in a column. 00154 // The scale and offset values are taken from a column with 00155 // the given names. In that way each array has its own scale factor 00156 // and offset value. 00157 // An exception is thrown if these columns do not exist. 00158 // VirtualColumnName is the name of the virtual column and is used to 00159 // check if the engine gets bound to the correct column. 00160 // StoredColumnName is the name of the column where the scaled 00161 // data will be put and must have data type Int. 00162 // The virtual column using this engine must have data type Complex. 00163 CompressComplex (const String& virtualColumnName, 00164 const String& storedColumnName, 00165 const String& scaleColumnName, 00166 const String& offsetColumnName, 00167 Bool autoScale = True); 00168 00169 // Construct from a record specification as created by getmanagerSpec(). 00170 CompressComplex (const Record& spec); 00171 00172 // Destructor is mandatory. 00173 ~CompressComplex(); 00174 00175 // Return the type name of the engine (i.e. its class name). 00176 virtual String dataManagerType() const; 00177 00178 // Get the name given to the engine (is the virtual column name). 00179 virtual String dataManagerName() const; 00180 00181 // Record a record containing data manager specifications. 00182 virtual Record dataManagerSpec() const; 00183 00184 // Return the name of the class. 00185 // This includes the names of the template arguments. 00186 static String className(); 00187 00188 // Register the class name and the static makeObject "constructor". 00189 // This will make the engine known to the table system. 00190 static void registerClass(); 00191 00192 protected: 00193 // Copy constructor is only used by clone() and derived class. 00194 // (so it is made private). 00195 CompressComplex (const CompressComplex&); 00196 00197 private: 00198 // Assignment is not needed and therefore forbidden 00199 // (so it is made private and not implemented). 00200 CompressComplex& operator= (const CompressComplex&); 00201 00202 // Clone the engine object. 00203 virtual DataManager* clone() const; 00204 00205 protected: 00206 // Initialize the object for a new table. 00207 // It defines the keywords containing the engine parameters. 00208 virtual void create (uInt initialNrrow); 00209 00210 private: 00211 // Preparing consists of setting the writable switch and 00212 // adding the initial number of rows in case of create. 00213 // Furthermore it reads the keywords containing the engine parameters. 00214 virtual void prepare(); 00215 00216 // Reopen the engine for read/write access. 00217 // It makes the column writable if the underlying column is writable. 00218 virtual void reopenRW(); 00219 00220 // Add rows to the table. 00221 // If auto-scaling, it initializes the scale column with 0 00222 // to indicate that no data has been processed yet. 00223 virtual void addRowInit (uInt startRow, uInt nrrow); 00224 00225 // Get an array in the given row. 00226 // This will scale and offset from the underlying array. 00227 virtual void getArray (uInt rownr, Array<Complex>& array); 00228 00229 // Put an array in the given row. 00230 // This will scale and offset to the underlying array. 00231 virtual void putArray (uInt rownr, const Array<Complex>& array); 00232 00233 // Get a section of the array in the given row. 00234 // This will scale and offset from the underlying array. 00235 virtual void getSlice (uInt rownr, const Slicer& slicer, 00236 Array<Complex>& array); 00237 00238 // Put into a section of the array in the given row. 00239 // This will scale and offset to the underlying array. 00240 virtual void putSlice (uInt rownr, const Slicer& slicer, 00241 const Array<Complex>& array); 00242 00243 // Get an entire column. 00244 // This will scale and offset from the underlying array. 00245 virtual void getArrayColumn (Array<Complex>& array); 00246 00247 // Put an entire column. 00248 // This will scale and offset to the underlying array. 00249 virtual void putArrayColumn (const Array<Complex>& array); 00250 00251 // Get a section of all arrays in the column. 00252 // This will scale and offset from the underlying array. 00253 virtual void getColumnSlice (const Slicer& slicer, Array<Complex>& array); 00254 00255 // Put a section of all arrays in the column. 00256 // This will scale and offset to the underlying array. 00257 virtual void putColumnSlice (const Slicer& slicer, 00258 const Array<Complex>& array); 00259 00260 // Scale and/or offset target to array. 00261 // This is meant when reading an array from the stored column. 00262 // It optimizes for scale=1 and/or offset=0. 00263 virtual void scaleOnGet (Float scale, Float offset, 00264 Array<Complex>& array, 00265 const Array<Int>& target); 00266 00267 // Scale and/or offset array to target. 00268 // This is meant when writing an array into the stored column. 00269 // It optimizes for scale=1 and/or offset=0. 00270 virtual void scaleOnPut (Float scale, Float offset, 00271 const Array<Complex>& array, 00272 Array<Int>& target); 00273 00274 // Scale and/or offset target to array for the entire column. 00275 // When the scale and offset are fixed, it will do the entire array. 00276 // Otherwise it iterates through the array and applies the scale 00277 // and offset per row. 00278 void scaleColumnOnGet (Array<Complex>& array, 00279 const Array<Int>& target); 00280 00281 // Scale and/or offset array to target for the entire column. 00282 // When the scale and offset are fixed, it will do the entire array. 00283 // Otherwise it iterates through the array and applies the scale 00284 // and offset per row. 00285 void scaleColumnOnPut (const Array<Complex>& array, 00286 Array<Int>& target); 00287 00288 protected: 00289 //# Now define the data members. 00290 String scaleName_p; //# name of scale column 00291 String offsetName_p; //# name of offset column 00292 Float scale_p; //# fixed scale factor 00293 Float offset_p; //# fixed offset value 00294 Bool fixed_p; //# scale/offset is fixed 00295 Bool autoScale_p; //# determine scale/offset automatically 00296 ROScalarColumn<Float>* scaleColumn_p; //# column with scale value 00297 ROScalarColumn<Float>* offsetColumn_p; //# column with offset value 00298 ScalarColumn<Float>* rwScaleColumn_p; //# writable column with scale value 00299 ScalarColumn<Float>* rwOffsetColumn_p; //# writable column with offset value 00300 Array<Int> buffer_p; //# buffer to avoid Array constructions 00301 //# (makes multi-threading harder) 00302 00303 // Get the scale value for this row. 00304 Float getScale (uInt rownr); 00305 00306 // Get the offset value for this row. 00307 Float getOffset (uInt rownr); 00308 00309 // Find minimum and maximum from the array data. 00310 // NaN and infinite values are ignored. If no values are finite, 00311 // minimum and maximum are set to NaN. 00312 virtual void findMinMax (Float& minVal, Float& maxVal, 00313 const Array<Complex>& array) const; 00314 00315 // Make scale and offset from the minimum and maximum of the array data. 00316 // If minVal is NaN, scale is set to 0. 00317 void makeScaleOffset (Float& scale, Float& offset, 00318 Float minVal, Float maxVal) const; 00319 00320 // Put a part of an array in a row using given scale/offset values. 00321 void putPart (uInt rownr, const Slicer& slicer, 00322 const Array<Complex>& array, 00323 Float scale, Float offset); 00324 00325 // Fill the array part into the full array and put it using the 00326 // given min/max values. 00327 void putFullPart (uInt rownr, const Slicer& slicer, 00328 Array<Complex>& fullArray, 00329 const Array<Complex>& partArray, 00330 Float minVal, Float maxVal); 00331 00332 public: 00333 // Define the "constructor" to construct this engine when a 00334 // table is read back. 00335 // This "constructor" has to be registered by the user of the engine. 00336 // If the engine is commonly used, its registration can be added 00337 // to the registerAllCtor function in DataManager.cc. 00338 // That function gets automatically invoked by the table system. 00339 static DataManager* makeObject (const String& dataManagerType, 00340 const Record& spec); 00341 }; 00342 00343 00344 00345 00346 // <summary> 00347 // Virtual column engine to scale a table Complex array for Single Dish data 00348 // </summary> 00349 00350 // <use visibility=export> 00351 00352 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tCompressComplex.cc"> 00353 // </reviewed> 00354 00355 // <prerequisite> 00356 //# Classes you should understand before using this one. 00357 // <li> CompressComplex 00358 // </prerequisite> 00359 00360 // <synopsis> 00361 // CompressComplexSD is similar to CompressComplex, but compresses 00362 // in a slighty different way optimized for single dish data. 00363 // Usually the imaginary part of single dish data is 0, so the scaling 00364 // is optimized for it. 00365 // <br>If the imaginary part is 0, the real part is scaled with 15 bits 00366 // extra to get a higher precision. The least significant bit is set to 0 00367 // indicating the imag==0. 00368 // <br>If the imaginary part is not 0, the real part is scaled normally. 00369 // The imaginary part is scaled with 1 bit less. The least significant bit 00370 // is set to 1 indicating that imag!=0. 00371 // </synopsis> 00372 00373 // <motivation> 00374 // This class is created on top of CompressComplex to cope with SD data 00375 // in a better way. Using CompressComplex often makes the imag part non-zero 00376 // if it is scaled as 0. 00377 // </motivation> 00378 00379 // <example> 00380 // <srcblock> 00381 // // Create the table description and 2 columns with indirect arrays in it. 00382 // // The Int column will be stored, while the double will be 00383 // // used as virtual. 00384 // TableDesc tableDesc ("", TableDesc::Scratch); 00385 // tableDesc.addColumn (ArrayColumnDesc<Int> ("storedArray")); 00386 // tableDesc.addColumn (ArrayColumnDesc<Complex> ("virtualArray")); 00387 // tableDesc.addColumn (ScalarColumnDesc<Complex> ("scale")); 00388 // tableDesc.addColumn (ScalarColumnDesc<Float> ("offset")); 00389 // 00390 // // Create a new table using the table description. 00391 // SetupNewTable newtab (tableDesc, "tab.data", Table::New); 00392 // 00393 // // Create the array scaling engine (with auto-scale) 00394 // // and bind it to the Complex column. 00395 // CompressComplexSD scalingEngine("virtualArray", "storedArray", 00396 // "scale", "offset"); 00397 // newtab.bindColumn ("virtualArray", scalingEngine); 00398 // // Create the table. 00399 // Table table (newtab); 00400 // 00401 // // Store a 3-D array (with dim. 2,3,4) into each row of the column. 00402 // // The shape of each array in the column is implicitly set by the put 00403 // // function. This will also set the shape of the underlying Int array. 00404 // ArrayColumn data (table, "virtualArray"); 00405 // Array<double> someArray(IPosition(4,2,3,4)); 00406 // someArray = 0; 00407 // for (uInt i=0, i<10; i++) { // table will have 10 rows 00408 // table.addRow(); 00409 // data.put (i, someArray) 00410 // } 00411 // </srcblock> 00412 // </example> 00413 00414 class CompressComplexSD : public CompressComplex 00415 { 00416 public: 00417 00418 // Construct an engine to scale all arrays in a column with 00419 // the given offset and scale factor. 00420 // StoredColumnName is the name of the column where the scaled 00421 // data will be put and must have data type Int. 00422 // The virtual column using this engine must have data type Complex. 00423 CompressComplexSD (const String& virtualColumnName, 00424 const String& storedColumnName, 00425 Float scale, 00426 Float offset = 0); 00427 00428 // Construct an engine to scale the arrays in a column. 00429 // The scale and offset values are taken from a column with 00430 // the given names. In that way each array has its own scale factor 00431 // and offset value. 00432 // An exception is thrown if these columns do not exist. 00433 // VirtualColumnName is the name of the virtual column and is used to 00434 // check if the engine gets bound to the correct column. 00435 // StoredColumnName is the name of the column where the scaled 00436 // data will be put and must have data type Int. 00437 // The virtual column using this engine must have data type Complex. 00438 CompressComplexSD (const String& virtualColumnName, 00439 const String& storedColumnName, 00440 const String& scaleColumnName, 00441 const String& offsetColumnName, 00442 Bool autoScale = True); 00443 00444 // Construct from a record specification as created by getmanagerSpec(). 00445 CompressComplexSD (const Record& spec); 00446 00447 // Destructor is mandatory. 00448 ~CompressComplexSD(); 00449 00450 // Return the type name of the engine (i.e. its class name). 00451 virtual String dataManagerType() const; 00452 00453 // Return the name of the class. 00454 // This includes the names of the template arguments. 00455 static String className(); 00456 00457 // Register the class name and the static makeObject "constructor". 00458 // This will make the engine known to the table system. 00459 static void registerClass(); 00460 00461 private: 00462 // Copy constructor is only used by clone(). 00463 // (so it is made private). 00464 CompressComplexSD (const CompressComplexSD&); 00465 00466 // Assignment is not needed and therefore forbidden 00467 // (so it is made private and not implemented). 00468 CompressComplexSD& operator= (const CompressComplexSD&); 00469 00470 // Clone the engine object. 00471 virtual DataManager* clone() const; 00472 00473 // Initialize the object for a new table. 00474 // It defines the keywords containing the engine parameters. 00475 virtual void create (uInt initialNrrow); 00476 00477 // Scale and/or offset target to array. 00478 // This is meant when reading an array from the stored column. 00479 // It optimizes for scale=1 and/or offset=0. 00480 virtual void scaleOnGet (Float scale, Float offset, 00481 Array<Complex>& array, 00482 const Array<Int>& target); 00483 00484 // Scale and/or offset array to target. 00485 // This is meant when writing an array into the stored column. 00486 // It optimizes for scale=1 and/or offset=0. 00487 virtual void scaleOnPut (Float scale, Float offset, 00488 const Array<Complex>& array, 00489 Array<Int>& target); 00490 00491 // Find minimum and maximum from the array data. 00492 // NaN and infinite values and zero imaginary parts are ignored. 00493 // If no values are finite, minimum and maximum are set to NaN. 00494 virtual void findMinMax (Float& minVal, Float& maxVal, 00495 const Array<Complex>& array) const; 00496 00497 public: 00498 // Define the "constructor" to construct this engine when a 00499 // table is read back. 00500 // This "constructor" has to be registered by the user of the engine. 00501 // If the engine is commonly used, its registration can be added 00502 // to the registerAllCtor function in DataManager.cc. 00503 // That function gets automatically invoked by the table system. 00504 static DataManager* makeObject (const String& dataManagerType, 00505 const Record& spec); 00506 }; 00507 00508 00509 00510 00511 inline Float CompressComplex::getScale (uInt rownr) 00512 { 00513 return (fixed_p ? scale_p : (*scaleColumn_p)(rownr)); 00514 } 00515 inline Float CompressComplex::getOffset (uInt rownr) 00516 { 00517 return (fixed_p ? offset_p : (*offsetColumn_p)(rownr)); 00518 } 00519 00520 00521 00522 } //# NAMESPACE CASA - END 00523 00524 #endif