00001 //# CompressFloat.h: Virtual column engine to scale a table float array 00002 //# Copyright (C) 2001,2002 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 TABLES_COMPRESSFLOAT_H 00029 #define TABLES_COMPRESSFLOAT_H 00030 00031 //# Includes 00032 #include <casacore/casa/aips.h> 00033 #include <casacore/tables/DataMan/BaseMappedArrayEngine.h> 00034 #include <casacore/tables/Tables/ScalarColumn.h> 00035 #include <casacore/casa/Arrays/Array.h> 00036 00037 00038 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00039 00040 // <summary> 00041 // Virtual column engine to scale a table float array 00042 // </summary> 00043 00044 // <use visibility=export> 00045 00046 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tCompressFloat.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 // CompressFloat 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 float to short. 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<Short> ("storedArray")); 00111 // tableDesc.addColumn (ArrayColumnDesc<Float> ("virtualArray")); 00112 // tableDesc.addColumn (ScalarColumnDesc<Float> ("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 float column. 00120 // CompressFloat 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 CompressFloat : public BaseMappedArrayEngine<Float, Short> 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 Short. 00147 // The virtual column using this engine must have data type Float. 00148 CompressFloat (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 Short. 00162 // The virtual column using this engine must have data type Float. 00163 CompressFloat (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 CompressFloat (const Record& spec); 00171 00172 // Destructor is mandatory. 00173 ~CompressFloat(); 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 private: 00193 // Copy constructor is only used by clone(). 00194 // (so it is made private). 00195 CompressFloat (const CompressFloat&); 00196 00197 // Assignment is not needed and therefore forbidden 00198 // (so it is made private and not implemented). 00199 CompressFloat& operator= (const CompressFloat&); 00200 00201 // Clone the engine object. 00202 virtual DataManager* clone() const; 00203 00204 // Initialize the object for a new table. 00205 // It defines the keywords containing the engine parameters. 00206 virtual void create (uInt initialNrrow); 00207 00208 // Preparing consists of setting the writable switch and 00209 // adding the initial number of rows in case of create. 00210 // Furthermore it reads the keywords containing the engine parameters. 00211 virtual void prepare(); 00212 00213 // Reopen the engine for read/write access. 00214 // It makes the column writable if the underlying column is writable. 00215 virtual void reopenRW(); 00216 00217 // Add rows to the table. 00218 // If auto-scaling, it initializes the scale column with 0 00219 // to indicate that no data has been processed yet. 00220 virtual void addRowInit (uInt startRow, uInt nrrow); 00221 00222 // Get an array in the given row. 00223 // This will scale and offset from the underlying array. 00224 virtual void getArray (uInt rownr, Array<Float>& array); 00225 00226 // Put an array in the given row. 00227 // This will scale and offset to the underlying array. 00228 virtual void putArray (uInt rownr, const Array<Float>& array); 00229 00230 // Get a section of the array in the given row. 00231 // This will scale and offset from the underlying array. 00232 virtual void getSlice (uInt rownr, const Slicer& slicer, 00233 Array<Float>& array); 00234 00235 // Put into a section of the array in the given row. 00236 // This will scale and offset to the underlying array. 00237 virtual void putSlice (uInt rownr, const Slicer& slicer, 00238 const Array<Float>& array); 00239 00240 // Get an entire column. 00241 // This will scale and offset from the underlying array. 00242 virtual void getArrayColumn (Array<Float>& array); 00243 00244 // Put an entire column. 00245 // This will scale and offset to the underlying array. 00246 virtual void putArrayColumn (const Array<Float>& array); 00247 00248 // Get some array values in the column. 00249 // This will scale and offset from the underlying array. 00250 virtual void getArrayColumnCells (const RefRows& rownrs, 00251 Array<Float>& data); 00252 00253 // Put some array values in the column. 00254 // This will scale and offset to the underlying array. 00255 virtual void putArrayColumnCells (const RefRows& rownrs, 00256 const Array<Float>& data); 00257 00258 // Get a section of all arrays in the column. 00259 // This will scale and offset from the underlying array. 00260 virtual void getColumnSlice (const Slicer& slicer, Array<Float>& array); 00261 00262 // Put a section of all arrays in the column. 00263 // This will scale and offset to the underlying array. 00264 virtual void putColumnSlice (const Slicer& slicer, 00265 const Array<Float>& array); 00266 00267 // Get a section of some arrays in the column. 00268 // This will scale and offset from the underlying array. 00269 virtual void getColumnSliceCells (const RefRows& rownrs, 00270 const Slicer& slicer, 00271 Array<Float>& data); 00272 00273 // Put into a section of some arrays in the column. 00274 // This will scale and offset to the underlying array. 00275 virtual void putColumnSliceCells (const RefRows& rownrs, 00276 const Slicer& slicer, 00277 const Array<Float>& data); 00278 00279 // Scale and/or offset target to array. 00280 // This is meant when reading an array from the stored column. 00281 // It optimizes for scale=1 and/or offset=0. 00282 void scaleOnGet (Float scale, Float offset, 00283 Array<Float>& array, 00284 const Array<Short>& target); 00285 00286 // Scale and/or offset array to target. 00287 // This is meant when writing an array into the stored column. 00288 // It optimizes for scale=1 and/or offset=0. 00289 void scaleOnPut (Float scale, Float offset, 00290 const Array<Float>& array, 00291 Array<Short>& target); 00292 00293 // Scale and/or offset target to array for the entire column. 00294 // When the scale and offset are fixed, it will do the entire array. 00295 // Otherwise it iterates through the array and applies the scale 00296 // and offset per row. 00297 void scaleColumnOnGet (Array<Float>& array, 00298 const Array<Short>& target); 00299 00300 // Scale and/or offset array to target for the entire column. 00301 // When the scale and offset are fixed, it will do the entire array. 00302 // Otherwise it iterates through the array and applies the scale 00303 // and offset per row. 00304 void scaleColumnOnPut (const Array<Float>& array, 00305 Array<Short>& target); 00306 00307 00308 //# Now define the data members. 00309 String scaleName_p; //# name of scale column 00310 String offsetName_p; //# name of offset column 00311 Float scale_p; //# fixed scale factor 00312 Float offset_p; //# fixed offset value 00313 Bool fixed_p; //# scale/offset is fixed 00314 Bool autoScale_p; //# determine scale/offset automatically 00315 ScalarColumn<Float>* scaleColumn_p; //# column with scale value 00316 ScalarColumn<Float>* offsetColumn_p; //# column with offset value 00317 Array<Short> buffer_p; //# buffer to avoid Array constructions 00318 00319 // Get the scale value for this row. 00320 Float getScale (uInt rownr); 00321 00322 // Get the offset value for this row. 00323 Float getOffset (uInt rownr); 00324 00325 // Find minimum and maximum from the array data. 00326 // NaN and infinite values are ignored. If no values are finite, 00327 // minimum and maximum are set to NaN. 00328 void findMinMax (Float& minVal, Float& maxVal, 00329 const Array<Float>& array) const; 00330 00331 // Make scale and offset from the minimum and maximum of the array data. 00332 // If minVal is NaN, scale is set to 0. 00333 void makeScaleOffset (Float& scale, Float& offset, 00334 Float minVal, Float maxVal) const; 00335 00336 // Put a part of an array in a row using given scale/offset values. 00337 void putPart (uInt rownr, const Slicer& slicer, 00338 const Array<Float>& array, 00339 Float scale, Float offset); 00340 00341 // Fill the array part into the full array and put it using the 00342 // given min/max values. 00343 void putFullPart (uInt rownr, const Slicer& slicer, 00344 Array<Float>& fullArray, 00345 const Array<Float>& partArray, 00346 Float minVal, Float maxVal); 00347 00348 public: 00349 // Define the "constructor" to construct this engine when a 00350 // table is read back. 00351 // This "constructor" has to be registered by the user of the engine. 00352 // If the engine is commonly used, its registration can be added 00353 // to the registerAllCtor function in DataManager.cc. 00354 // That function gets automatically invoked by the table system. 00355 static DataManager* makeObject (const String& dataManagerType, 00356 const Record& spec); 00357 }; 00358 00359 00360 inline Float CompressFloat::getScale (uInt rownr) 00361 { 00362 return (fixed_p ? scale_p : (*scaleColumn_p)(rownr)); 00363 } 00364 inline Float CompressFloat::getOffset (uInt rownr) 00365 { 00366 return (fixed_p ? offset_p : (*offsetColumn_p)(rownr)); 00367 } 00368 00369 00370 00371 } //# NAMESPACE CASACORE - END 00372 00373 #endif