casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
CompressFloat.h
Go to the documentation of this file.
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: CompressFloat.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $
00027 
00028 #ifndef TABLES_COMPRESSFLOAT_H
00029 #define TABLES_COMPRESSFLOAT_H
00030 
00031 //# Includes
00032 #include <tables/Tables/BaseMappedArrayEngine.h>
00033 #include <tables/Tables/ScalarColumn.h>
00034 #include <casa/Arrays/Array.h>
00035 
00036 
00037 namespace casa { //# NAMESPACE CASA - BEGIN
00038 
00039 // <summary>
00040 // Virtual column engine to scale a table float array
00041 // </summary>
00042 
00043 // <use visibility=export>
00044 
00045 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tCompressFloat.cc">
00046 // </reviewed>
00047 
00048 // <prerequisite>
00049 //# Classes you should understand before using this one.
00050 //   <li> VirtualColumnEngine
00051 //   <li> VirtualArrayColumn
00052 // </prerequisite>
00053 
00054 // <synopsis> 
00055 // CompressFloat is a virtual column engine which scales an array
00056 // of one type to another type to save disk storage.
00057 // This resembles the classic AIPS compress method which scales the
00058 // data from float to short.
00059 // The scale factor and offset values can be given in two ways:
00060 // <ul>
00061 //  <li> As a fixed values which is used for all arrays in the column.
00062 //       These values have to be given when constructing of the engine.
00063 //  <li> As the name of a column. In this way each array in the
00064 //         column has its own scale and offset value.
00065 //         By default it uses auto-scaling (see below).
00066 //         Otherwise the scale and offset value in a row must be put
00067 //         before the array is put and should not be changed anymore.
00068 // </ul>
00069 // Auto-scaling means that the engine will determine the scale
00070 // and offset value itself when an array (or a slice) is put.
00071 // It does it by mapping the values in the array to the range [-32767,32767].
00072 // At each put the scale/offset values are changed as needed.
00073 // Note that with auto-scaling <src>putSlice</src> can be somewhat
00074 // slower, because the entire array might need to be rescaled.
00075 //
00076 // As in FITS the scale and offset values are used as:
00077 // <br><src> True_value = Stored_value * scale + offset; </src>
00078 //
00079 // An engine object should be used for one column only, because the stored
00080 // column name is part of the engine. If it would be used for more than
00081 // one column, they would all share the same stored column.
00082 // When the engine is bound to a column, it is checked if the name
00083 // of that column matches the given virtual column name.
00084 //
00085 // The engine can be used for a column containing any kind of array
00086 // (thus direct or indirect, fixed or variable shaped)) as long as the
00087 // virtual array can be stored in the stored array. Thus a fixed shaped
00088 // virtual can use a variable shaped stored, but not vice versa.
00089 // A fixed shape indirect virtual can use a stored with direct arrays.
00090 //
00091 // This class can also serve as an example of how to implement
00092 // a virtual column engine.
00093 // </synopsis> 
00094 
00095 // <motivation>
00096 // This class allows to store data in a smaller representation.
00097 // It is needed to resemble the classic AIPS compress option.
00098 //
00099 // Because the engine can serve only one column, it was possible to
00100 // combine the engine and the column functionality in one class.
00101 // </motivation>
00102 
00103 // <example>
00104 // <srcblock>
00105 // // Create the table description and 2 columns with indirect arrays in it.
00106 // // The Int column will be stored, while the double will be
00107 // // used as virtual.
00108 // TableDesc tableDesc ("", TableDesc::Scratch);
00109 // tableDesc.addColumn (ArrayColumnDesc<Short> ("storedArray"));
00110 // tableDesc.addColumn (ArrayColumnDesc<Float> ("virtualArray"));
00111 // tableDesc.addColumn (ScalarColumnDesc<Float> ("scale"));
00112 // tableDesc.addColumn (ScalarColumnDesc<Float> ("offset"));
00113 //
00114 // // Create a new table using the table description.
00115 // SetupNewTable newtab (tableDesc, "tab.data", Table::New);
00116 //
00117 // // Create the array scaling engine (with auto-scale)
00118 // // and bind it to the float column.
00119 // CompressFloat scalingEngine("virtualArray", "storedArray",
00120 //                             "scale", "offset");
00121 // newtab.bindColumn ("virtualArray", scalingEngine);
00122 // // Create the table.
00123 // Table table (newtab);
00124 //
00125 // // Store a 3-D array (with dim. 2,3,4) into each row of the column.
00126 // // The shape of each array in the column is implicitly set by the put
00127 // // function. This will also set the shape of the underlying Int array.
00128 // ArrayColumn data (table, "virtualArray");
00129 // Array<double> someArray(IPosition(4,2,3,4));
00130 // someArray = 0;
00131 // for (uInt i=0, i<10; i++) {          // table will have 10 rows
00132 //     table.addRow();
00133 //     data.put (i, someArray)
00134 // }
00135 // </srcblock>
00136 // </example>
00137 
00138 class CompressFloat : public BaseMappedArrayEngine<Float, Short>
00139 {
00140 public:
00141 
00142   // Construct an engine to scale all arrays in a column with
00143   // the given offset and scale factor.
00144   // StoredColumnName is the name of the column where the scaled
00145   // data will be put and must have data type Short.
00146   // The virtual column using this engine must have data type Float.
00147   CompressFloat (const String& virtualColumnName,
00148                  const String& storedColumnName,
00149                  Float scale,
00150                  Float offset = 0);
00151 
00152   // Construct an engine to scale the arrays in a column.
00153   // The scale and offset values are taken from a column with
00154   // the given names. In that way each array has its own scale factor
00155   // and offset value.
00156   // An exception is thrown if these columns do not exist.
00157   // VirtualColumnName is the name of the virtual column and is used to
00158   // check if the engine gets bound to the correct column.
00159   // StoredColumnName is the name of the column where the scaled
00160   // data will be put and must have data type Short.
00161   // The virtual column using this engine must have data type Float.
00162   CompressFloat (const String& virtualColumnName,
00163                  const String& storedColumnName,
00164                  const String& scaleColumnName,
00165                  const String& offsetColumnName,
00166                  Bool autoScale = True);
00167 
00168   // Construct from a record specification as created by getmanagerSpec().
00169   CompressFloat (const Record& spec);
00170 
00171   // Destructor is mandatory.
00172   ~CompressFloat();
00173 
00174   // Return the type name of the engine (i.e. its class name).
00175   virtual String dataManagerType() const;
00176 
00177   // Get the name given to the engine (is the virtual column name).
00178   virtual String dataManagerName() const;
00179   
00180   // Record a record containing data manager specifications.
00181   virtual Record dataManagerSpec() const;
00182 
00183   // Return the name of the class.
00184   // This includes the names of the template arguments.
00185   static String className();
00186 
00187   // Register the class name and the static makeObject "constructor".
00188   // This will make the engine known to the table system.
00189   static void registerClass();
00190 
00191 private:
00192   // Copy constructor is only used by clone().
00193   // (so it is made private).
00194   CompressFloat (const CompressFloat&);
00195 
00196   // Assignment is not needed and therefore forbidden
00197   // (so it is made private and not implemented).
00198   CompressFloat& operator= (const CompressFloat&);
00199 
00200   // Clone the engine object.
00201   virtual DataManager* clone() const;
00202 
00203   // Initialize the object for a new table.
00204   // It defines the keywords containing the engine parameters.
00205   virtual void create (uInt initialNrrow);
00206 
00207   // Preparing consists of setting the writable switch and
00208   // adding the initial number of rows in case of create.
00209   // Furthermore it reads the keywords containing the engine parameters.
00210   virtual void prepare();
00211 
00212   // Reopen the engine for read/write access.
00213   // It makes the column writable if the underlying column is writable.
00214   virtual void reopenRW();
00215 
00216   // Add rows to the table.
00217   // If auto-scaling, it initializes the scale column with 0
00218   // to indicate that no data has been processed yet.
00219   virtual void addRowInit (uInt startRow, uInt nrrow);
00220 
00221   // Get an array in the given row.
00222   // This will scale and offset from the underlying array.
00223   virtual void getArray (uInt rownr, Array<Float>& array);
00224 
00225   // Put an array in the given row.
00226   // This will scale and offset to the underlying array.
00227   virtual void putArray (uInt rownr, const Array<Float>& array);
00228 
00229   // Get a section of the array in the given row.
00230   // This will scale and offset from the underlying array.
00231   virtual void getSlice (uInt rownr, const Slicer& slicer,
00232                          Array<Float>& array);
00233 
00234   // Put into a section of the array in the given row.
00235   // This will scale and offset to the underlying array.
00236   virtual void putSlice (uInt rownr, const Slicer& slicer,
00237                          const Array<Float>& array);
00238 
00239   // Get an entire column.
00240   // This will scale and offset from the underlying array.
00241   virtual void getArrayColumn (Array<Float>& array);
00242 
00243   // Put an entire column.
00244   // This will scale and offset to the underlying array.
00245   virtual void putArrayColumn (const Array<Float>& array);
00246 
00247   // Get a section of all arrays in the column.
00248   // This will scale and offset from the underlying array.
00249   virtual void getColumnSlice (const Slicer& slicer, Array<Float>& array);
00250 
00251   // Put a section of all arrays in the column.
00252   // This will scale and offset to the underlying array.
00253   virtual void putColumnSlice (const Slicer& slicer, 
00254                                const Array<Float>& array);
00255 
00256   // Scale and/or offset target to array.
00257   // This is meant when reading an array from the stored column.
00258   // It optimizes for scale=1 and/or offset=0.
00259   void scaleOnGet (Float scale, Float offset,
00260                    Array<Float>& array,
00261                    const Array<Short>& target);
00262 
00263   // Scale and/or offset array to target.
00264   // This is meant when writing an array into the stored column.
00265   // It optimizes for scale=1 and/or offset=0.
00266   void scaleOnPut (Float scale, Float offset,
00267                    const Array<Float>& array,
00268                    Array<Short>& target);
00269 
00270   // Scale and/or offset target to array for the entire column.
00271   // When the scale and offset are fixed, it will do the entire array.
00272   // Otherwise it iterates through the array and applies the scale
00273   // and offset per row.
00274   void scaleColumnOnGet (Array<Float>& array,
00275                          const Array<Short>& target);
00276 
00277   // Scale and/or offset array to target for the entire column.
00278   // When the scale and offset are fixed, it will do the entire array.
00279   // Otherwise it iterates through the array and applies the scale
00280   // and offset per row.
00281   void scaleColumnOnPut (const Array<Float>& array,
00282                          Array<Short>& target);
00283 
00284 
00285   //# Now define the data members.
00286   String         scaleName_p;          //# name of scale column
00287   String         offsetName_p;         //# name of offset column
00288   Float          scale_p;              //# fixed scale factor
00289   Float          offset_p;             //# fixed offset value
00290   Bool           fixed_p;              //# scale/offset is fixed
00291   Bool           autoScale_p;          //# determine scale/offset automatically
00292   ROScalarColumn<Float>* scaleColumn_p;  //# column with scale value
00293   ROScalarColumn<Float>* offsetColumn_p; //# column with offset value
00294   ScalarColumn<Float>* rwScaleColumn_p;  //# writable column with scale value
00295   ScalarColumn<Float>* rwOffsetColumn_p; //# writable column with offset value
00296   Array<Short>   buffer_p;             //# buffer to avoid Array constructions
00297 
00298   // Get the scale value for this row.
00299   Float getScale (uInt rownr);
00300 
00301   // Get the offset value for this row.
00302   Float getOffset (uInt rownr);
00303 
00304   // Find minimum and maximum from the array data.
00305   // NaN and infinite values are ignored. If no values are finite,
00306   // minimum and maximum are set to NaN.
00307   void findMinMax (Float& minVal, Float& maxVal,
00308                    const Array<Float>& array) const;
00309 
00310   // Make scale and offset from the minimum and maximum of the array data.
00311   // If minVal is NaN, scale is set to 0.
00312   void makeScaleOffset (Float& scale, Float& offset,
00313                         Float minVal, Float maxVal) const;
00314 
00315   // Put a part of an array in a row using given scale/offset values.
00316   void putPart (uInt rownr, const Slicer& slicer,
00317                 const Array<Float>& array,
00318                 Float scale, Float offset);
00319 
00320   // Fill the array part into the full array and put it using the
00321   // given min/max values.
00322   void putFullPart (uInt rownr, const Slicer& slicer,
00323                     Array<Float>& fullArray,
00324                     const Array<Float>& partArray,
00325                     Float minVal, Float maxVal);
00326 
00327 public:
00328   // Define the "constructor" to construct this engine when a
00329   // table is read back.
00330   // This "constructor" has to be registered by the user of the engine.
00331   // If the engine is commonly used, its registration can be added
00332   // to the registerAllCtor function in DataManager.cc. 
00333   // That function gets automatically invoked by the table system.
00334   static DataManager* makeObject (const String& dataManagerType,
00335                                   const Record& spec);
00336 };
00337 
00338 
00339 inline Float CompressFloat::getScale (uInt rownr)
00340 {
00341   return (fixed_p  ?  scale_p : (*scaleColumn_p)(rownr));
00342 }
00343 inline Float CompressFloat::getOffset (uInt rownr)
00344 {
00345   return (fixed_p  ?  offset_p : (*offsetColumn_p)(rownr));
00346 }
00347 
00348 
00349 
00350 } //# NAMESPACE CASA - END
00351 
00352 #endif