casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
CompressComplex.h
Go to the documentation of this file.
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