00001 //# BitFlagsEngine.h: Templated virtual column engine to map bit flags to a Bool 00002 //# Copyright (C) 2009 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_BITFLAGSENGINE_H 00029 #define TABLES_BITFLAGSENGINE_H 00030 00031 //# Includes 00032 #include <casacore/casa/aips.h> 00033 #include <casacore/tables/DataMan/BaseMappedArrayEngine.h> 00034 00035 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00036 00037 00038 // <summary> Non-templated Helper class to handle the mask. </summary> 00039 // <use visibility=local> 00040 class BFEngineMask 00041 { 00042 public: 00043 // Form the mask as given. 00044 explicit BFEngineMask (uInt mask=0xffffffff); 00045 00046 // Form the mask from the given keywords defining the bits. 00047 BFEngineMask (const Array<String>& keys, uInt defaultMask); 00048 00049 // Make the mask from the given keywords defining the bits. 00050 void makeMask (const TableColumn& column); 00051 00052 // Form the read mask from the specification. 00053 // If keywords are given, the mask is formed from them. 00054 void fromRecord (const RecordInterface& spec, const TableColumn& column, 00055 const String& prefix); 00056 00057 // Store the info in a Record. 00058 void toRecord (RecordInterface& spec, const String& prefix) const; 00059 00060 // Get the mask. 00061 uInt getMask() const 00062 { return itsMask; } 00063 00064 // Get the mask keywords. 00065 const Array<String>& getKeys() const 00066 { return itsMaskKeys; } 00067 00068 private: 00069 Array<String> itsMaskKeys; 00070 uInt itsMask; 00071 }; 00072 00073 00074 // <summary> 00075 // Templated virtual column engine to map bit flags to a Bool. 00076 // </summary> 00077 00078 // <use visibility=export> 00079 00080 // <reviewed reviewer="Gareth Hunt" date="94Nov17" tests=""> 00081 // </reviewed> 00082 00083 // <prerequisite> 00084 //# Classes you should understand before using this one. 00085 // <li> VirtualColumnEngine 00086 // <li> VirtualArrayColumn 00087 // </prerequisite> 00088 00089 // <synopsis> 00090 // BitFlagsEngine is a virtual column engine which maps an integer column 00091 // containing flag bits to a Bool column. It can be used in a MeasurementSet 00092 // to have multiple flag categories, yet use all existing software that 00093 // deals with the Bool FLAG column. 00094 // 00095 // The engine support read as well as write access. 00096 // For both cases a mask can be defined telling which bits have to be taken 00097 // into account. For example, when writing to the Bool FLAG column, the data 00098 // in the bitflags column twill be or-ed with the bits as defined in the 00099 // writemask. Similary when reading FLAG, only the bits of the readmask are 00100 // taken into account. 00101 // 00102 // The masks can be defined in two ways: 00103 // <ul> 00104 // <li> The mask can be given directly as an integer value. 00105 // The default write mask is 1 (thus only bit 0), while the default 00106 // read mask is all bits. 00107 // <li> Symbolic names for mask bits can be defined as keywords in the 00108 // flagbits column. They define the bit value, not the bit number. 00109 // It makes it possible to combine bits in a keyword. 00110 // The keywords are stored in a subrecord of keyword FLAGSETS. 00111 // Example of keyword and their values could be: 00112 // <br>RFI=1, CAL=2, CLIP=4, OTHER=8, RFICAL=3 00113 // <br>Note that in this example RFICAL is defined such that it 00114 // contains RFI and CAL. 00115 // </ul> 00116 // A mask can be set at construction time, but it can be changed at runtime 00117 // using the <src>setProperties</src> function. 00118 // The masks are kept in special keywords (which are different from the 00119 // keywords defining the flag bits), so it is possible to change a mask 00120 // by changing those keywords before opening a table. However, that is 00121 // not recommended. 00122 // 00123 // BitFlagsEngine is known to the table system for data types uChar, Short, 00124 // and Int. 00125 // </synopsis> 00126 00127 // <motivation> 00128 // The FLAG_CATEGORY defined the Measurement does not work because adding 00129 // an extra flag means resizing the entire array which is slow. 00130 // This class makes it possible to use an integer column to store flags 00131 // and map it directly to a Bool column. 00132 // </motivation> 00133 00134 // <example> 00135 // <srcblock> 00136 // // Create the table description and 2 columns with indirect arrays in it. 00137 // // The Int column will be stored, while the Bool will be used as virtual. 00138 // TableDesc tableDesc ("", TableDesc::Scratch); 00139 // tableDesc.addColumn (ArrayColumnDesc<Int> ("BitBlags")); 00140 // tableDesc.addColumn (ArrayColumnDesc<Bool> ("FLAG")); 00141 // 00142 // // Create a new table using the table description. 00143 // SetupNewTable newtab (tableDesc, "tab.data", Table::New); 00144 // 00145 // // Create the engine and bind the FLAG column to it. 00146 // BitFlagsEngine<Int> flagsEngine("FLAG", "BitFlags"); 00147 // newtab.bindColumn ("FLAG", flagsEngine); 00148 // // Create the table. 00149 // Table table (newtab); 00150 // 00151 // // Store a 3-D array (with dim. 2,3,4) into each row of the column. 00152 // // The shape of each array in the column is implicitly set by the put 00153 // // function. This will also set the shape of the underlying Int array. 00154 // ArrayColumn data (table, "virtualArray"); 00155 // Array<Bool> someArray(IPosition(4,2,3,4)); 00156 // someArray = True; 00157 // for (uInt i=0, i<10; i++) { // table will have 10 rows 00158 // table.addRow(); 00159 // data.put (i, someArray) 00160 // } 00161 // </srcblock> 00162 // The underlying integer array will be stored according to the writemask 00163 // which defaults to 1. 00164 // </example> 00165 00166 // <templating arg=StoredType> 00167 // <li> only suited for built-in integer data types 00168 // </templating> 00169 00170 template<typename StoredType> class BitFlagsEngine : public BaseMappedArrayEngine<Bool, StoredType> 00171 { 00172 //# Make members of parent class known. 00173 public: 00174 using BaseMappedArrayEngine<Bool,StoredType>::virtualName; 00175 protected: 00176 using BaseMappedArrayEngine<Bool,StoredType>::storedName; 00177 using BaseMappedArrayEngine<Bool,StoredType>::table; 00178 using BaseMappedArrayEngine<Bool,StoredType>::column; 00179 using BaseMappedArrayEngine<Bool,StoredType>::setNames; 00180 00181 public: 00182 // Construct an engine to map integer arrays in a column to Bool arrays. 00183 // StoredColumnName is the name of the column where the integer 00184 // data will be put and must have data type StoredType. 00185 // The virtual column using this engine must have data type Bool. 00186 // <br>A mask can be given that specifies which bits to use in the mapping 00187 // from StoredType to Bool. Similarly a mask can be given defining which 00188 // bits to set when mapping from Bool to StoredType. 00189 BitFlagsEngine (const String& virtualColumnName, 00190 const String& storedColumnName, 00191 StoredType readMask=StoredType(0xffffffff), 00192 StoredType writeMask=1); 00193 00194 // Construct an engine to map integer arrays in a column to Bool arrays. 00195 // StoredColumnName is the name of the column where the scaled 00196 // data will be put and must have data type StoredType. 00197 // The virtual column using this engine must have data type Bool. 00198 // <br>A mask can be given that specifies which bits to use in the mapping 00199 // from StoredType to Bool. Similarly a mask can be given defining which 00200 // bits to set when mapping from Bool to StoredType. 00201 // The masks are given using the values of keywords in the stored column. 00202 // Each keyword should be an integer defining one or more bits and can be 00203 // seen as a symbolic name. The keyword values are or-ed to form the mask. 00204 // The keywords are stored in a subrecord of keyword FLAGSETS. 00205 BitFlagsEngine (const String& virtualColumnName, 00206 const String& storedColumnName, 00207 const Array<String>& readMaskKeys, 00208 const Array<String>& writeMaskKeys); 00209 00210 // Construct from a record specification as created by dataManagerSpec(). 00211 BitFlagsEngine (const Record& spec); 00212 00213 // Destructor is mandatory. 00214 ~BitFlagsEngine(); 00215 00216 // Return the type name of the engine (i.e. its class name). 00217 virtual String dataManagerType() const; 00218 00219 // Get the name given to the engine (is the virtual column name). 00220 virtual String dataManagerName() const; 00221 00222 // Record a record containing data manager specifications. 00223 virtual Record dataManagerSpec() const; 00224 00225 // Get data manager properties that can be modified. 00226 // These are ReadMask, WriteMask, ReadMaskKeys, and WriteMaskKeys. 00227 // It is a subset of the data manager specification. 00228 virtual Record getProperties() const; 00229 00230 // Modify data manager properties. 00231 // These are ReadMask, WriteMask, ReadMaskKeys, and/or WriteMaskKeys. 00232 // Mask keys should be given as an array of strings giving the keyword 00233 // names defining mask bits (similar to the constructor). Mask keys are 00234 // only used if not empty. 00235 virtual void setProperties (const Record& spec); 00236 00237 // Return the name of the class. 00238 // This includes the names of the template arguments. 00239 static String className(); 00240 00241 // Register the class name and the static makeObject "constructor". 00242 // This will make the engine known to the table system. 00243 // The automatically invoked registration function in DataManReg.cc 00244 // contains BitFlagsEngine<Int>. 00245 // Any other instantiation of this class must be registered "manually" 00246 // (or added to DataManReg.cc). 00247 static void registerClass(); 00248 00249 private: 00250 // Copy constructor is only used by clone(). 00251 // (so it is made private). 00252 BitFlagsEngine (const BitFlagsEngine<StoredType>&); 00253 00254 // Assignment is not needed and therefore forbidden 00255 // (so it is made private and not implemented). 00256 BitFlagsEngine<StoredType>& operator= (const BitFlagsEngine<StoredType>&); 00257 00258 // Clone the engine object. 00259 DataManager* clone() const; 00260 00261 // Initialize the object for a new table. 00262 // It defines the keywords containing the engine parameters. 00263 void create (uInt initialNrrow); 00264 00265 // Preparing consists of setting the writable switch and 00266 // adding the initial number of rows in case of create. 00267 // Furthermore it reads the keywords containing the engine parameters. 00268 void prepare(); 00269 00270 // Get an array in the given row. 00271 // This will scale and offset from the underlying array. 00272 void getArray (uInt rownr, Array<Bool>& array); 00273 00274 // Put an array in the given row. 00275 // This will scale and offset to the underlying array. 00276 void putArray (uInt rownr, const Array<Bool>& array); 00277 00278 // Get a section of the array in the given row. 00279 // This will scale and offset from the underlying array. 00280 void getSlice (uInt rownr, const Slicer& slicer, Array<Bool>& array); 00281 00282 // Put into a section of the array in the given row. 00283 // This will scale and offset to the underlying array. 00284 void putSlice (uInt rownr, const Slicer& slicer, 00285 const Array<Bool>& array); 00286 00287 // Get an entire column. 00288 // This will scale and offset from the underlying array. 00289 void getArrayColumn (Array<Bool>& array); 00290 00291 // Put an entire column. 00292 // This will scale and offset to the underlying array. 00293 void putArrayColumn (const Array<Bool>& array); 00294 00295 // Get some array values in the column. 00296 // This will scale and offset from the underlying array. 00297 virtual void getArrayColumnCells (const RefRows& rownrs, 00298 Array<Bool>& data); 00299 00300 // Put some array values in the column. 00301 // This will scale and offset to the underlying array. 00302 virtual void putArrayColumnCells (const RefRows& rownrs, 00303 const Array<Bool>& data); 00304 00305 // Get a section of all arrays in the column. 00306 // This will scale and offset from the underlying array. 00307 void getColumnSlice (const Slicer& slicer, Array<Bool>& array); 00308 00309 // Put a section of all arrays in the column. 00310 // This will scale and offset to the underlying array. 00311 void putColumnSlice (const Slicer& slicer, const Array<Bool>& array); 00312 00313 // Get a section of some arrays in the column. 00314 // This will scale and offset from the underlying array. 00315 virtual void getColumnSliceCells (const RefRows& rownrs, 00316 const Slicer& slicer, 00317 Array<Bool>& data); 00318 00319 // Put into a section of some arrays in the column. 00320 // This will scale and offset to the underlying array. 00321 virtual void putColumnSliceCells (const RefRows& rownrs, 00322 const Slicer& slicer, 00323 const Array<Bool>& data); 00324 00325 // Map bit flags array to Bool array. 00326 // This is meant when reading an array from the stored column. 00327 void mapOnGet (Array<Bool>& array, 00328 const Array<StoredType>& stored); 00329 00330 // Map Bool array to bit flags array. 00331 // This is meant when writing an array into the stored column. 00332 void mapOnPut (const Array<Bool>& array, 00333 Array<StoredType>& stored); 00334 00335 // Functor to and an array and mask and convert to Bool. 00336 struct FlagsToBool : public std::unary_function<StoredType,Bool> 00337 { 00338 explicit FlagsToBool(StoredType readMask) : itsMask(readMask) {} 00339 Bool operator() (StoredType value) const 00340 { return (value & itsMask) != 0; } 00341 private: 00342 StoredType itsMask; 00343 }; 00344 // Functor to convert Bools to flags using a mask. 00345 // By default only bit 0 is set. 00346 // Flag bits not affected are kept. 00347 struct BoolToFlags : public std::binary_function<Bool,StoredType,StoredType> 00348 { 00349 explicit BoolToFlags(StoredType writeMask) : itsMask(writeMask) {} 00350 StoredType operator() (Bool flag, StoredType value) const 00351 { return (flag ? value&itsMask : value); } 00352 private: 00353 StoredType itsMask; 00354 }; 00355 00356 public: 00357 // Define the "constructor" to construct this engine when a 00358 // table is read back. 00359 // This "constructor" has to be registered by the user of the engine. 00360 // If the engine is commonly used, its registration can be added 00361 // to the registerAllCtor function in DataManReg.cc. 00362 // That function gets automatically invoked by the table system. 00363 static DataManager* makeObject (const String& dataManagerType, 00364 const Record& spec); 00365 00366 private: 00367 BFEngineMask itsBFEReadMask; 00368 BFEngineMask itsBFEWriteMask; 00369 StoredType itsReadMask; 00370 StoredType itsWriteMask; 00371 Bool itsIsNew; //# True = new table 00372 }; 00373 00374 00375 } //# NAMESPACE CASACORE - END 00376 00377 #ifndef CASACORE_NO_AUTO_TEMPLATES 00378 #include <casacore/tables/DataMan/BitFlagsEngine.tcc> 00379 #endif //# CASACORE_NO_AUTO_TEMPLATES 00380 #endif