source: Sophya/trunk/SophyaExt/FitsIOServer/swfitsdtable.cc@ 3076

Last change on this file since 3076 was 3069, checked in by ansari, 19 years ago

Correction plusieurs bugs lies a SwFitsDataTable - Reza 08/09/2006

File size: 12.9 KB
Line 
1#include "swfitsdtable.h"
2#include "fitshdtable.h"
3#include "sopnamsp.h"
4#include "pexceptions.h"
5
6
7/*!
8 \class SOPHYA::SwFitsDataTable
9 \ingroup FitsIOServer
10 This class can be used to organize data in table (row-column) form.
11 Each column holds homogeneous data (same data type), while different
12 columns can be used for different data types
13 (integer, float, string ...).
14 A Fits file binary table is used as swap space.
15
16 \warning
17 - When creating a table, the output fits file (FitsInOutFile) must not be closed
18 (destroyed) before the SwFitsDataTable object is destroyed. The destructor writes
19 out any pending buffer to the fits file.
20 - It is not possible to make a complete (deep) copy of a SwFitsDataTable
21 Copy constructor and equal operator shares the data.
22 - The min/max values for column data are not updated when reading from a fits file.
23 In this case, the Show() method (or ostream& << operator) will compute min/max
24 values. This operation will take some time for large tables.
25
26 \sa SOPHYA::MuTyV
27 \sa SOPHYA::DataTableRow
28 \sa SOPHYA::DataTable
29 \sa SOPHYA::SwSegDataBlock SOPHYA::FitsDataSwapper
30
31 \code
32 #include "swfitsdtable.h"
33 // ...
34 {
35 // ---- Creation of the table
36 // Create the swap stream
37 FitsInOutFile so("myswtable.fits", FitsInOutFile::Fits_Create);
38 SwFitsDataTable dt(so, 16);
39 // define table columns
40 dt.AddFloatColumn("X0_f");
41 dt.AddFloatColumn("X1_f");
42 dt.AddDoubleColumn("X0X0pX1X1_d");
43 // Fill the table
44 r_8 x[5];
45 for(int i=0; i<63; i++) {
46 x[0] = (i%9)-4.; x[1] = (i/9)-3.; x[2] = x[0]*x[0]+x[1]*x[1];
47 dt.AddLine(x);
48 }
49 // Printing table info
50 cout << dt ;
51 // The destructor will Swap out data still in memory
52 }
53 {
54 // ---- Accessing information from a previously created table
55 SwFitsDataTable dt;
56 FitsInOutFile si("myswtable.fits", FitsInOutFile::Fits_ReadOnly);
57 // Position the fits file on the first extension (BinTable)
58 si.MoveAbsToHDU(2);
59 // Reading in the table (initialisation)
60 si >> dt;
61 // Printing table info
62 cout << dt ;
63 }
64 \endcode
65*/
66//! Default constructor with optional specification of block (or segment) size
67SwFitsDataTable::SwFitsDataTable(sa_size_t segsz)
68 : BaseDataTable(segsz)
69{
70 mFgCreate = false;
71}
72/*!
73 \brief Construcor with specification of the \b FitsInOutFile swap stream.
74 if fgcreate == true, creates an empty table (the fits file should then be
75 opened for writing).
76 if fgcreate == false , the table is initialized (read in) from the current HDU.
77*/
78SwFitsDataTable::SwFitsDataTable(FitsInOutFile & os, sa_size_t segsz, bool fgcreate)
79 : BaseDataTable(segsz) ,
80 mSwF(os) , mFgCreate(fgcreate)
81{
82 if (!fgcreate) { // Lecture de la table
83 FitsHandler<BaseDataTable> fio(*this);
84 fio.Read(os);
85 }
86}
87
88/*!
89 \brief Construcor with specification of the FITS file name.
90 if fgcreate == false , the FITS file is opened and the table is
91 initialized (read in) from HDU \b hdunum
92*/
93SwFitsDataTable::SwFitsDataTable(string fitsname, int hdunum, sa_size_t segsz)
94 : BaseDataTable(segsz) ,
95 mSwF(fitsname, FitsInOutFile::Fits_RO)
96{
97 // Lecture de la table
98 FitsHandler<BaseDataTable> fio(*this);
99 mSwF.MoveAbsToHDU(hdunum);
100 fio.Read(mSwF);
101}
102
103//! copy constructor - shares the data
104SwFitsDataTable::SwFitsDataTable(SwFitsDataTable const & a)
105 : BaseDataTable(a.SegmentSize()),
106 mSwF(a.mSwF) , mFgCreate(a.mFgCreate)
107{
108 Share(a);
109}
110//! Destructor - Deletes / closes the input PPF swap stream
111SwFitsDataTable::~SwFitsDataTable()
112{
113 if (mFgCreate) {
114 SwapOutAll();
115 // Ecriture de SegmentSize et autre elements de DVList
116 mSwF.WriteHeaderRecords(Info());
117 MuTyV mtv = SegmentSize();
118 mSwF.WriteKey("SEGMSIZE",mtv," SOPHYA::DataTable SegmentSize");
119 mtv = "SOPHYA::SwFitsDataTable";
120 mSwF.WriteKey("SOPCLSNM",mtv," Object class name ");
121 }
122}
123
124void SwFitsDataTable::Share(SwFitsDataTable const & a)
125{
126 // On recopie la taille de segment
127 mSegSz = a.SegmentSize();
128 if (a.NVar() == 0) return; // Table sans colonne
129
130 // On copie la structure de table
131 CopyStructure(a);
132
133 //
134 // Update nombre d'entree, ...
135 mNEnt = a.mNEnt;
136 mNSeg = a.mNSeg;
137 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
138
139 // mis a jour des tableax min-max
140 mMin = a.mMin;
141 mMax = a.mMax;
142 mMinMaxNEnt = a.mMinMaxNEnt;
143
144 // Et on partage les donnees des colonnes
145 for (size_t kk=0; kk<mNames.size(); kk++) {
146 sa_size_t sk = mNames[kk].ser;
147 sa_size_t ska = a.mNames[kk].ser;
148 switch (mNames[kk].type) {
149 case IntegerField :
150 mICols[sk] = a.mICols[ska];
151 break;
152 case LongField :
153 mLCols[sk] = a.mLCols[ska];
154 break;
155 case FloatField :
156 mFCols[sk] = a.mFCols[ska];
157 break;
158 case DoubleField :
159 case DateTimeField :
160 mDCols[sk] = a.mDCols[ska];
161 break;
162 case ComplexField :
163 mYCols[sk] = a.mYCols[ska];
164 break;
165 case DoubleComplexField :
166 mZCols[sk] = a.mZCols[ska];
167 break;
168 case StringField :
169 mSCols[sk] = a.mSCols[ska];
170 break;
171 default:
172 throw ForbiddenError("SwFitsDataTable::Share() : unknown column type ");
173 break;
174 }
175 }
176}
177void SwFitsDataTable::SwapOutAll() const
178{
179 if (NRows() < 1) return;
180 // Et on vide les buffers de swap
181 for (size_t kk=0; kk<mNames.size(); kk++) {
182 sa_size_t sk = mNames[kk].ser;
183 switch (mNames[kk].type) {
184 case IntegerField :
185 mICols[sk].SwapOutBuffer();
186 break;
187 case LongField :
188 mLCols[sk].SwapOutBuffer();
189 break;
190 case FloatField :
191 mFCols[sk].SwapOutBuffer();
192 break;
193 case DoubleField :
194 case DateTimeField :
195 mDCols[sk].SwapOutBuffer();
196 break;
197 case ComplexField :
198 mYCols[sk].SwapOutBuffer();
199 break;
200 case DoubleComplexField :
201 mZCols[sk].SwapOutBuffer();
202 break;
203 case StringField :
204 mSCols[sk].SwapOutBuffer();
205 break;
206 default:
207 throw ForbiddenError("SwFitsDataTable::SwapOutAll() : unknown column type ");
208 break;
209 }
210 }
211}
212
213void SwFitsDataTable::Clear()
214{
215 if ( (NVar() == 0) && (NEntry() == 0)) return;
216 mNEnt = 0;
217 mNSeg = 0;
218 if (mVarD) delete[] mVarD;
219 mVarD = NULL;
220 if (mVarMTV) delete[] mVarMTV;
221 mVarMTV = NULL;
222 mNames.clear();
223 if (mInfo) delete mInfo;
224 mInfo = NULL;
225 mMin.clear();
226 mMax.clear();
227 mMinMaxNEnt.clear();
228 mIColsP.clear();
229 mLColsP.clear();
230 mFColsP.clear();
231 mDColsP.clear();
232 mYColsP.clear();
233 mZColsP.clear();
234 mSColsP.clear();
235
236 mIColIdx.clear();
237 mLColIdx.clear();
238 mFColIdx.clear();
239 mDColIdx.clear();
240 mYColIdx.clear();
241 mZColIdx.clear();
242 mSColIdx.clear();
243
244 mICols.clear();
245 mLCols.clear();
246 mFCols.clear();
247 mDCols.clear();
248 mYCols.clear();
249 mZCols.clear();
250 mSCols.clear();
251
252}
253
254
255/*!
256 Implements the action defined in the BaseDataTable interface.
257 In the current implementation, throws an exception (ParmError)
258 if the table contains some data already.
259*/
260sa_size_t SwFitsDataTable::AddColumn(FieldType ft, string const & cnom)
261{
262 return AddColRd(ft, cnom, -1, NULL);
263}
264/*!
265 Adds a column to the table. If swpos != NULL, the swapper is initialized
266 for reading data from the fits file. This method can be called
267 by FitsHandler<BaseDataTable> with non zero swpos.
268*/
269sa_size_t SwFitsDataTable::AddColRd(FieldType ft, string const & cnom,
270 int colidx, vector<int_8> const * swpos)
271{
272 if (NEntry() > 0)
273 throw ParmError("SwFitsDataTable::AddColumn() Table contains already data ");
274 CheckColName(cnom);
275 sa_size_t ser;
276 sa_size_t idx = NVar();
277 if (colidx < 1) colidx = idx+1;
278
279 switch (ft) {
280 case IntegerField :
281 {
282 ser = mICols.size();
283 FITSDataSwapper<int_4> ISwapper(mSwF, colidx, this);
284 if (swpos)
285 mICols.push_back(SwSegDataBlock<int_4>(ISwapper, *swpos, mSegSz));
286 else
287 mICols.push_back(SwSegDataBlock<int_4>(ISwapper, mSegSz));
288 mIColIdx.push_back(idx);
289 mIColsP.push_back(NULL);
290 for(sa_size_t kk=0; kk<mICols.size(); kk++)
291 mIColsP[kk] = &(mICols[kk]);
292 break;
293 }
294 case LongField :
295 {
296 ser = mLCols.size();
297 FITSDataSwapper<int_8> LSwapper(mSwF, colidx, this);
298 if (swpos)
299 mLCols.push_back(SwSegDataBlock<int_8>(LSwapper, *swpos, mSegSz));
300 else
301 mLCols.push_back(SwSegDataBlock<int_8>(LSwapper, mSegSz));
302 mLColIdx.push_back(idx);
303 mLColsP.push_back(NULL);
304 for(sa_size_t kk=0; kk<mLCols.size(); kk++)
305 mLColsP[kk] = &(mLCols[kk]);
306 break;
307 }
308 case FloatField :
309 {
310 ser = mFCols.size();
311 FITSDataSwapper<r_4> FSwapper(mSwF, colidx, this);
312 if (swpos)
313 mFCols.push_back(SwSegDataBlock<r_4>(FSwapper, *swpos, mSegSz));
314 else
315 mFCols.push_back(SwSegDataBlock<r_4>(FSwapper, mSegSz));
316 mFColIdx.push_back(idx);
317 mFColsP.push_back(NULL);
318 for(sa_size_t kk=0; kk<mFCols.size(); kk++)
319 mFColsP[kk] = &(mFCols[kk]);
320 break;
321 }
322 case DoubleField :
323 case DateTimeField :
324 {
325 ser = mDCols.size();
326 FITSDataSwapper<r_8> DSwapper(mSwF, colidx, this);
327 if (swpos)
328 mDCols.push_back(SwSegDataBlock<r_8>(DSwapper, *swpos, mSegSz));
329 else
330 mDCols.push_back(SwSegDataBlock<r_8>(DSwapper, mSegSz));
331 mDColIdx.push_back(idx);
332 mDColsP.push_back(NULL);
333 for(sa_size_t kk=0; kk<mDCols.size(); kk++)
334 mDColsP[kk] = &(mDCols[kk]);
335 break;
336 }
337 case ComplexField :
338 {
339 ser = mYCols.size();
340 FITSDataSwapper< complex<r_4> > YSwapper(mSwF, colidx, this);
341 if (swpos)
342 mYCols.push_back(SwSegDataBlock< complex<r_4> >(YSwapper, *swpos, mSegSz));
343 else
344 mYCols.push_back(SwSegDataBlock< complex<r_4> >(YSwapper, mSegSz));
345 mYColIdx.push_back(idx);
346 mYColsP.push_back(NULL);
347 for(sa_size_t kk=0; kk<mYCols.size(); kk++)
348 mYColsP[kk] = &(mYCols[kk]);
349 break;
350 }
351 case DoubleComplexField :
352 {
353 ser = mZCols.size();
354 FITSDataSwapper< complex<r_8> > ZSwapper(mSwF, colidx, this);
355 if (swpos)
356 mZCols.push_back(SwSegDataBlock< complex<r_8> >(ZSwapper, *swpos, mSegSz));
357 else
358 mZCols.push_back(SwSegDataBlock< complex<r_8> >(ZSwapper, mSegSz));
359 mZColIdx.push_back(idx);
360 mZColsP.push_back(NULL);
361 for(sa_size_t kk=0; kk<mZCols.size(); kk++)
362 mZColsP[kk] = &(mZCols[kk]);
363 break;
364 }
365 case StringField :
366 {
367 ser = mSCols.size();
368 FITSDataSwapper< string > SSwapper(mSwF, colidx, this);
369 if (swpos)
370 mSCols.push_back(SwSegDataBlock< string >(SSwapper, *swpos, mSegSz));
371 else
372 mSCols.push_back(SwSegDataBlock< string >(SSwapper, mSegSz));
373 mSColIdx.push_back(idx);
374 mSColsP.push_back(NULL);
375 for(sa_size_t kk=0; kk<mSCols.size(); kk++)
376 mSColsP[kk] = &(mSCols[kk]);
377 break;
378 }
379 default:
380 throw ParmError("SwFitsDataTable::AddColumn() unknown field type ");
381 break;
382 }
383 colst col;
384 col.nom = cnom;
385 col.type = ft;
386 col.ser = ser;
387 mNames.push_back(col);
388 // On est oblige de calculer les min-max lors du remplissage
389 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
390 mMin.push_back(9.E39);
391 mMax.push_back(-9.E39);
392 mMinMaxNEnt.push_back(0);
393
394 return NVar();
395}
396
397//! Adds a line (or row to the table) with r_8* input data.
398/*!
399 The min/max values for each column is updated, in addition
400 to the actions performed by the base class AddRow().
401 The table is also created on the FITS file at the first call to AddRow()
402*/
403sa_size_t SwFitsDataTable::AddRow(const r_8* data)
404{
405 if (NRows() == 0) { // On cree la definition de la table FITS au premier appel
406 FitsHandler<BaseDataTable> fio(*this);
407 fio.Write(mSwF);
408 }
409 // On est oblige de calculer les min-max lors du remplissage
410 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
411 for(sa_size_t k=0; k<NVar(); k++) {
412 double x = data[k];
413 if (x < mMin[k]) mMin[k] = x;
414 if (x > mMax[k]) mMax[k] = x;
415 mMinMaxNEnt[k]++;
416 }
417 return BaseDataTable::AddRow(data);
418}
419
420//! Adds a row (or line to the table) with input data as an array of MuTyV
421/*!
422 The min/max values for each column is updated, in addition
423 to the actions performed by the base class AddRow().
424 The table is also created on the FITS file at the first call to AddRow()
425*/
426sa_size_t SwFitsDataTable::AddRow(const MuTyV * data)
427{
428 if (NRows() == 0) { // On cree la definition de la table FITS au premier appel
429 FitsHandler<BaseDataTable> fio(*this);
430 fio.Write(mSwF);
431 }
432 // On est oblige de calculer les min-max lors du remplissage
433 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
434 for(sa_size_t k=0; k<NVar(); k++) {
435 double x = (double)data[k];
436 if (x < mMin[k]) mMin[k] = x;
437 if (x > mMax[k]) mMax[k] = x;
438 mMinMaxNEnt[k]++;
439 }
440 return BaseDataTable::AddRow(data);
441}
442
443//! Adds a row (or line) to the table with input data as DataTableRow object
444/*!
445 The min/max values for each column is updated, in addition
446 to the actions performed by the base class AddRow().
447 The table is also created on the FITS file at the first call to AddRow()
448*/
449sa_size_t SwFitsDataTable::AddRow(DataTableRow const& data)
450{
451 if ( data.Size() != NCols() )
452 throw SzMismatchError(" SwFitsDataTable::AddRow() - data.Size() != NCols() ");
453 return AddRow(data.MTVPtr());
454}
Note: See TracBrowser for help on using the repository browser.