casacore
Loading...
Searching...
No Matches
TiledDataStMan.h
Go to the documentation of this file.
1// # TiledDataStMan.h: Tiled Data Storage Manager
2// # Copyright (C) 1995,1996,1997,1999,2001
3// # Associated Universities, Inc. Washington DC, USA.
4// #
5// # This library is free software; you can redistribute it and/or modify it
6// # under the terms of the GNU Library General Public License as published by
7// # the Free Software Foundation; either version 2 of the License, or (at your
8// # option) any later version.
9// #
10// # This library is distributed in the hope that it will be useful, but WITHOUT
11// # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12// # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13// # License for more details.
14// #
15// # You should have received a copy of the GNU Library General Public License
16// # along with this library; if not, write to the Free Software Foundation,
17// # Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18// #
19// # Correspondence concerning AIPS++ should be addressed as follows:
20// # Internet email: casa-feedback@nrao.edu.
21// # Postal address: AIPS++ Project Office
22// # National Radio Astronomy Observatory
23// # 520 Edgemont Road
24// # Charlottesville, VA 22903-2475 USA
25
26#ifndef TABLES_TILEDDATASTMAN_H
27#define TABLES_TILEDDATASTMAN_H
28
29// # Includes
30#include <casacore/casa/aips.h>
31#include <casacore/tables/DataMan/TiledStMan.h>
32#include <casacore/casa/Containers/Block.h>
33#include <casacore/casa/BasicSL/String.h>
34#include <vector>
35
36namespace casacore { // # NAMESPACE CASACORE - BEGIN
37
38// # Forward Declarations
39
40// <summary>
41// Tiled Data Storage Manager.
42// </summary>
43
44// <use visibility=export>
45
46// <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="">
47// </reviewed>
48
49// <prerequisite>
50// # Classes you should understand before using this one.
51// <li> <linkto class=TiledStMan>TiledStMan</linkto>
52// <li> <linkto class=TSMCube>TSMCube</linkto>
53// <li> <linkto class=ROTiledStManAccessor>ROTiledStManAccessor</linkto>
54// for a discussion of the maximum cache size
55// <li> <linkto class=Record>Record</linkto>
56// </prerequisite>
57
58// <etymology>
59// TiledDataStMan is the Tiled Storage Manager for general
60// data arrays.
61// </etymology>
62
63// <synopsis>
64// TiledDataStMan is a derivation from TiledStMan, the abstract
65// tiled storage manager class. A description of the basics
66// of tiled storage managers is given in the
67// <linkto module=Tables:TiledStMan>Tables module</linkto> description.
68// <p>
69// TiledDataStMan allows the user explicit control over the
70// definition and extension of hypercubes by means of the accessor
71// class <linkto class=TiledDataStManAccessor>TiledDataStManAccessor</linkto>.
72// The user can determine which row should be put in which hypercube,
73// so it is possible to put row 0-9 in hypercube A, row 10-29 in B,
74// row 30-39 in A again, etc.. This makes it possible to use a tiled
75// storage manager for a data column containing data with
76// different shapes (e.g. line and continuum data). Actually,
77// this storage manager is developed for irregularly shaped
78// UV-data, but can be used for any purpose.
79// <br>
80// Each extensible hypercube uses a file of its own. This means that there
81// shouldn't be too many of them, otherwise the number of files may
82// get too high.
83// <p>
84// The TiledDataStMan has the following (extra) properties:
85// <ul>
86// <li> When multiple hypercubes are used, one or more id columns have
87// to be used to differentiate between them. The id values must
88// be defined when the hypercube gets added; they cannot be put
89// explicitly.
90// <li> A hypercube can be extensible in its last dimension by setting
91// its last dimension to zero. In that case extendHypercube can
92// be used to extend the hypercube when needed.
93// All fixed sized hypercubes are stored in one file, while there
94// is one file per extensible hypercube.
95// <li> The table must be large enough to accommodate the addition
96// or extension of a hypercube. This means that a sufficient
97// number of rows must be added to the table before a hypercube
98// can be added or extended. It is the responsibility of the user
99// to "synchronize" addition of rows and hypercubes.
100// <li> It is possible to define coordinates for the hypercube axes
101// in several ways:
102// <ul>
103// <li> Use the TiledDataStMan storage manager to hold their values
104// and define the coordinates when adding or extending the
105// hypercube. This is the preferred way.
106// <li> As above, but use explicit puts to write their values.
107// This has to be used when coordinates are defined after
108// the hypercube has been added or extended.
109// Note that several rows may share the same value, so
110// overwriting a value may affect multiple rows.
111// <li> Use another storage manager to hold their values.
112// This is useful when their values depend on other axes,
113// because that cannot be handled by TiledDataStMan.
114// </ul>
115// Note that it is possible to store one coordinate column with
116// TiledDataStMan and another with another storage manager.
117// </ul>
118// </synopsis>
119
120// <motivation>
121// This tiled storage manager allows one to create and extend hypercubes
122// as needed. One has complete control over which row is stored in which
123// hypercube.
124// </motivation>
125
126// <example>
127// The following example shows how to create a TiledDataStMan tiled
128// storage manager using the hypercolumn as defined in the table description.
129// Furthermore it shows how to use TiledDataStManAccessor
130// to add a hypercube, while defining its tile shape, coordinates,
131// and id-value.
132// The example shows that reading the data back does not require any knowledge
133// of the data manager. It's exactly the same if another data manager was used.
134// <br>
135// The table created contains the equally shaped data columns "Data" and
136// "Weight".
137// Each cell in those columns contains a 2D array with shape [12,20]. The
138// coordinates of those arrays are "Pol" and "Freq".
139// The tiled storage manager superimposes two more axes ("Baseline"and "Time")
140// on the data resulting in a 4D hypercube with shape [12,20,30,42].
141// The table contains 42*30 rows (which has to be equal to the number of
142// elements in the superimposed axes).
143// <br>
144// The tile shape of the hypercube is (arbitrarily) set to [4,5,6,7].
145// Of course, any tile shape could be chosen. This tile shape results
146// in a tile size of 6720 bytes (4*5*6*7 *(4+4) bytes), which is not
147// that large (32768 as tile size is very reasonable). The number of tiles
148// is integral in each dimension, so no space is wasted.
149// Finally it makes access along the various axes about equally efficient.
150// <br>
151// Although in this example only one hypercube is added, multiple hypercubes
152// are possible, because an id column has been defined.
153// <note role=caution>
154// The example uses the global Array function indgen to fill the data
155// and coordinate arrays with arbitrary values.
156// </note>
157// Note that the description of class
158// <linkto class=ROTiledStManAccessor>ROTiledStManAccessor</linkto>
159// contains a discussion about the effect of setting the maximum cache size.
160//
161// <srcblock>
162// // Define the table description and the columns in it.
163// TableDesc td ("", "1", TableDesc::Scratch);
164// td.addColumn (ScalarColumnDesc<float> ("Time"));
165// td.addColumn (ScalarColumnDesc<float> ("Baseline"));
166// td.addColumn (ArrayColumnDesc<float> ("Pol", 1));
167// td.addColumn (ArrayColumnDesc<float> ("Freq", 1));
168// td.addColumn (ScalarColumnDesc<String> ("Id"));
169// td.addColumn (ArrayColumnDesc<float> ("Data", 2));
170// td.addColumn (ArrayColumnDesc<float> ("Weight", 2));
171// // Define the 4-dim hypercolumn with its data, coordinate and id columns.
172// td.defineHypercolumn ("TSMExample",
173// 4,
174// stringToVector ("Data,Weight"),
175// stringToVector ("Pol,Freq,Baseline,Time"),
176// stringToVector ("Id"));
177//
178// // Now create a new table from the description.
179// SetupNewTable newtab("tTiledDataStMan_tmp.data", td, Table::New);
180// // Create a TiledDataStMan storage manager for the hypercolumn
181// // and bind the columns to it.
182// TiledDataStMan sm1 ("TSMExample");
183// newtab.bindAll (sm1);
184// // Create the table with 42*30 rows.
185// Table table(newtab, 42*30);
186// // Create the accessor to be able to add a hypercube to this
187// // storage manager.
188// TiledDataStManAccessor accessor(table, "TSMExample");
189// // Define the values for the coordinates of the hypercube
190// // and put them into the record.
191// Vector<float> timeValues(42);
192// Vector<float> baselineValues(30);
193// Vector<float> freqValues(20);
194// Vector<float> polValues(12);
195// indgen (timeValues);
196// indgen (baselineValues, float(100));
197// indgen (freqValues, float(200));
198// indgen (polValues, float(300));
199// Record hyperDef;
200// hyperDef.define ("Time", timeValues);
201// hyperDef.define ("Baseline", baselineValues);
202// hyperDef.define ("Freq", freqValues);
203// hyperDef.define ("Pol", polValues);
204// // Define the id value as well.
205// hyperDef.define ("Id", "");
206// // Now add the hypercube with the given shape, tile shape,
207// // and coordinate and id values.
208// accessor.addHypercube (IPosition(4,12,20,30,42),
209// IPosition(4,4,5,6,7), hyperDef);
210// ArrayColumn<float> data (table, "Data");
211// ArrayColumn<float> weight (table, "Weight");
212// Matrix<float> array(IPosition(2,12,20));
213// indgen (array);
214// // Write some data into the data columns.
215// for (uInt i=0; i<30*42; i++) {
216// data.put (i, array);
217// weight.put (i, array+float(100));
218// array += float(200);
219// }
220// // Prepare for reading the data back.
221// // Note that time and baseline are in fact scalar columns. They are
222// // superimposed dimensions on the hypercube.
223// ScalarColumn<float> time (table, "Time");
224// ScalarColumn<float> baseline (table, "Baseline");
225// ArrayColumn<float> freq (table, "Freq");
226// ArrayColumn<float> pol (table, "Pol");
227// ScalarColumn<String> id (table, "Id");
228// float fValue;
229// String sValue;
230// for (rownr_t i=0; i<table.nrow(); i++) {
231// data.get (i, array);
232// weight.get (i, array);
233// pol.get (i, polValues);
234// freq.get (i, freqValues);
235// baseline.get (i, fValue);
236// time.get (i, fValue);
237// id.get (i, sValue);
238// }
239// </srcblock>
240// Note that in this example an id column was not necessary, because
241// there is only one hypercube.
242// <p>
243// The following example is more advanced. Two (extensible) hypercubes
244// are used for line and continuum data. Writing such a data set
245// could be done as shown. Reading it back is the same as above.
246// <br>
247// In this example the data columns contain line and continuum data.
248// So there are two types of data, each with their own shape and
249// stored in their own (extensible) hypercube. Note that the last
250// dimension of the hypercube shape is set to zero (to make extensible),
251// but the last tile shape dimension has been filled in,
252// because the exact tile shape must be known.
253// <br>
254// Before each put of the data the appropriate hypercube is extended.
255// Also the time has to be put, which is done (as an example) in
256// two different ways (using an explicit put and using the extendHypercube).
257//
258// <srcblock>
259// // Defining TableDesc and storage manager is same as in first example.
260// // Create the table.
261// Table table(newtab);
262// // Create the accessor to be able to add the hypercubes to this
263// // storage manager.
264// TiledDataStManAccessor accessor(table, "TSMExample");
265// // Fill the coordinate values.
266// // Note that the time axis of the hypercube will have length 0 to
267// // make it extensible. Therefore the time coordinate can only be
268// // filled in when the hypercube is extended.
269// Vector<float> baselineValues(30);
270// Vector<float> freqValuesCont(1);
271// Vector<float> freqValuesLine(20);
272// Vector<float> polValues(4);
273// indgen (baselineValues, float(100));
274// indgen (freqValuesLine, float(200));
275// indgen (freqValuesCont, float(200));
276// indgen (polValues, float(300));
277// Record hyperDefLine;
278// hyperDefLine.define ("Baseline", baselineValues);
279// hyperDefLine.define ("Pol", polValues);
280// // Make similar record for line data.
281// // Fill the correct id and frequency values for each type.
282// // Add the 2 hypercubes.
283// Record hyperDefCont (hyperDefLine);
284// hyperDefLine.define ("Id", "L");
285// hyperDefLine.define ("Freq", freqValuesLine);
286// hyperDefCont.define ("Id", "C");
287// hyperDefCont.define ("Freq", freqValuesCont);
288// // Add the hypercubes.
289// // Define their last dimension as zero to make them extensible.
290// accessor.addHypercube (IPosition(4,4,20,30,0),
291// IPosition(4,4,5,6,7), hyperDefLine);
292// accessor.addHypercube (IPosition(4,4,1,30,0),
293// IPosition(4,4,1,6,7), hyperDefCont);
294// ScalarColumn<float> time (table, "Time");
295// ScalarColumn<float> baseline (table, "Baseline");
296// ArrayColumn<float> freq (table, "Freq");
297// ArrayColumn<float> pol (table, "Pol");
298// ArrayColumn<float> data (table, "Data");
299// ArrayColumn<float> weight (table, "Weight");
300// Matrix<float> arrayLine(IPosition(2,4,20));
301// Matrix<float> arrayCont(IPosition(2,4,1));
302// indgen (arrayLine);
303// indgen (arrayCont);
304// // Write some data into the data columns.
305// // Alternately line and continuum is written.
306// // Each hypercube requires 30 rows to be added (i.e. nr of baselines).
307// // The last dimension of each hypercube is extended with 1.
308// rownr_t rownr = 0;
309// for (uInt i=0; i<42; i++) {
310// if (i%2 == 0) {
311// table.addRow (30);
312// accessor.extendHypercube (1, hyperDefLine);
313// time.put (rownr, float(i));
314// for (uInt j=0; j<30; j++) {
315// data.put (rownr, arrayLine);
316// weight.put (rownr, arrayLine);
317// rownr++;
318// }
319// }else{
320// table.addRow (30);
321// Vector<float> timeValue(1);
322// timeValue(0) = float(i);
323// hyperDefCont.define ("Time", timeValue);
324// accessor.extendHypercube (1, hyperDefCont);
325// time.put (rownr, float(i));
326// for (uInt j=0; j<30; j++) {
327// data.put (rownr, arrayCont);
328// weight.put (rownr, arrayCont);
329// rownr++;
330// }
331// }
332// }
333// </srcblock>
334// Note that in this example the time is defined in 2 different ways.
335// The first one by an explicit put, the second one as a record in
336// the extendHypercube call. The second way if the preferred one,
337// although it requires a bit more coding.
338// </example>
339
340// # <todo asof="$DATE:$">
341// # A List of bugs, limitations, extensions or planned refinements.
342// # </todo>
343
346
347 public:
348 // Create a TiledDataStMan storage manager for the hypercolumn
349 // with the given name.
350 // The hypercolumn name is also the name of the storage manager.
351 // The given maximum cache size (default is unlimited) is persistent,
352 // thus will be reused when the table is read back. Note that the class
353 // <linkto class=ROTiledStManAccessor>ROTiledStManAccessor</linkto>
354 // allows one to overwrite the maximum cache size temporarily.
355 // <br>The constructor taking a Record expects fields in the record with
356 // the name of the arguments in uppercase. If not defined, their
357 // default value is used.
358 // <group>
359 TiledDataStMan(const String& hypercolumnName, uInt64 maximumCacheSize = 0);
360 TiledDataStMan(const String& hypercolumnName, const Record& spec);
361 // </group>
362
364
365 // Forbid copy constructor.
367
368 // Forbid assignment.
370
371 // Clone this object.
372 // It does not clone TSMColumn objects possibly used.
374
375 // Get the type name of the data manager (i.e. TiledDataStMan).
377
378 // Make the object from the type name string.
379 // This function gets registered in the DataManager "constructor" map.
380 static DataManager* makeObject(const String& dataManagerType, const Record& spec);
381
382 private:
383 // Create a TiledDataStMan.
384 // This constructor is private, because it should only be used
385 // by makeObject.
387
388 // Add rows to the storage manager.
389 // This will only increase the number of rows. When a hypercube is
390 // added or extended, it will be checked whether the number of rows
391 // is sufficient.
392 void addRow64(rownr_t nrrow);
393
394 // Add a hypercube.
395 // The number of rows in the table must be large enough to
396 // accommodate this hypercube.
397 // The possible id values must be given in the record, while
398 // coordinate values are optional. The field names in the record
399 // should match the coordinate and id column names.
400 // The last dimension in the cube shape can be zero, indicating that
401 // the hypercube is extensible.
402 void addHypercube(const IPosition& cubeShape, const IPosition& tileShape, const Record& values);
403
404 // Extend the hypercube with the given number of elements in
405 // the last dimension.
406 // The record should contain the id values (to get the correct
407 // hypercube) and optionally coordinate values for the elements added.
408 void extendHypercube(uInt64 incrInLastDim, const Record& values);
409
410 // Get the hypercube in which the given row is stored.
411 virtual TSMCube* getHypercube(rownr_t rownr);
412
413 // Get the hypercube in which the given row is stored.
414 // It also returns the position of the row in that hypercube.
415 virtual TSMCube* getHypercube(rownr_t rownr, IPosition& position);
416
417 // Flush and optionally fsync the data.
418 // It returns a True status if it had to flush (i.e. if data have changed).
419 virtual Bool flush(AipsIO&, Bool fsync);
420
421 // Let the storage manager create files as needed for a new table.
422 // This allows a column with an indirect array to create its file.
423 virtual void create64(rownr_t nrrow);
424
425 // Read the header info.
426 virtual void readHeader(rownr_t nrrow, Bool firstTime);
427
428 // Update the map of row numbers to cube number plus offset.
429 void updateRowMap(uInt cubeNr, uInt64 incrInLastDim);
430
431 // Check if the table is large enough to hold this
432 // hypercube extension.
433 void checkNrrow(const IPosition& cubeShape, uInt64 incrInLastDim) const;
434
435 // # Declare the data members.
436 // The map of row number to cube and position in cube.
437 std::vector<rownr_t> rowMap_p;
438 std::vector<uInt> cubeMap_p;
439 std::vector<uInt> posMap_p;
440 // The row number since the last hypercube extension.
442};
443
444} // namespace casacore
445
446#endif
Abstract base class for a data manager.
String: the storage and methods of handling collections of characters.
Definition String.h:355
friend class TiledDataStManAccessor
virtual TSMCube * getHypercube(rownr_t rownr, IPosition &position)
Get the hypercube in which the given row is stored.
std::vector< uInt > cubeMap_p
TiledDataStMan(const String &hypercolumnName, uInt64 maximumCacheSize=0)
Create a TiledDataStMan storage manager for the hypercolumn with the given name.
TiledDataStMan()
Create a TiledDataStMan.
void checkNrrow(const IPosition &cubeShape, uInt64 incrInLastDim) const
Check if the table is large enough to hold this hypercube extension.
DataManager * clone() const
Clone this object.
virtual void readHeader(rownr_t nrrow, Bool firstTime)
Read the header info.
static DataManager * makeObject(const String &dataManagerType, const Record &spec)
Make the object from the type name string.
std::vector< rownr_t > rowMap_p
The map of row number to cube and position in cube.
std::vector< uInt > posMap_p
virtual TSMCube * getHypercube(rownr_t rownr)
Get the hypercube in which the given row is stored.
virtual Bool flush(AipsIO &, Bool fsync)
Flush and optionally fsync the data.
void addHypercube(const IPosition &cubeShape, const IPosition &tileShape, const Record &values)
Add a hypercube.
String dataManagerType() const
Get the type name of the data manager (i.e.
void updateRowMap(uInt cubeNr, uInt64 incrInLastDim)
Update the map of row numbers to cube number plus offset.
TiledDataStMan(const TiledDataStMan &)=delete
Forbid copy constructor.
TiledDataStMan & operator=(const TiledDataStMan &)=delete
Forbid assignment.
TiledDataStMan(const String &hypercolumnName, const Record &spec)
void addRow64(rownr_t nrrow)
Add rows to the storage manager.
void extendHypercube(uInt64 incrInLastDim, const Record &values)
Extend the hypercube with the given number of elements in the last dimension.
virtual void create64(rownr_t nrrow)
Let the storage manager create files as needed for a new table.
rownr_t nrrowLast_p
The row number since the last hypercube extension.
TiledStMan()
Create a TiledStMan.
const IPosition & tileShape(rownr_t rownr) const
Get the tile shape of the data in the given row.
uInt maximumCacheSize() const
Get the current maximum cache size (in MiB (MibiByte)).
Definition TiledStMan.h:499
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
unsigned int uInt
Definition aipstype.h:49
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
uInt64 rownr_t
Define the type of a row number in a table.
Definition aipsxtype.h:44
unsigned long long uInt64
Definition aipsxtype.h:37