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

Last change on this file since 3066 was 3032, checked in by ansari, 19 years ago

Declaration SwFitsDataTable::AddRow(DataTableRow) dans la classe fille , Reza 17/7/2006

File size: 12.3 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/*! Constructor with the specification of the output swap stream -
73 and optional specification of block (or segment) size
74*/
75SwFitsDataTable::SwFitsDataTable(FitsInOutFile & os, sa_size_t segsz, bool fgcreate)
76 : BaseDataTable(segsz) ,
77 mSwF(os) , mFgCreate(fgcreate)
78{
79 if (!fgcreate) { // Lecture de la table
80 FitsHandler<BaseDataTable> fio(*this);
81 fio.Read(os);
82 }
83}
84//! copy constructor - shares the data
85SwFitsDataTable::SwFitsDataTable(SwFitsDataTable const & a)
86 : BaseDataTable(a.SegmentSize()),
87 mSwF(a.mSwF) , mFgCreate(a.mFgCreate)
88{
89 Share(a);
90}
91//! Destructor - Deletes / closes the input PPF swap stream
92SwFitsDataTable::~SwFitsDataTable()
93{
94 if (mFgCreate) {
95 SwapOutAll();
96 // Ecriture de SegmentSize et autre elements de DVList
97 mSwF.WriteHeaderRecords(Info());
98 MuTyV mtv = SegmentSize();
99 mSwF.WriteKey("SEGMSIZE",mtv," SOPHYA::DataTable SegmentSize");
100 mtv = "SOPHYA::SwFitsDataTable";
101 mSwF.WriteKey("SOPCLSNM",mtv," Object class name ");
102 }
103}
104
105void SwFitsDataTable::Share(SwFitsDataTable const & a)
106{
107 // On recopie la taille de segment
108 mSegSz = a.SegmentSize();
109 if (a.NVar() == 0) return; // Table sans colonne
110
111 // On copie la structure de table
112 CopyStructure(a);
113
114 //
115 // Update nombre d'entree, ...
116 mNEnt = a.mNEnt;
117 mNSeg = a.mNSeg;
118 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
119
120 // mis a jour des tableax min-max
121 mMin = a.mMin;
122 mMax = a.mMax;
123 mMinMaxNEnt = a.mMinMaxNEnt;
124
125 // Et on partage les donnees des colonnes
126 for (size_t kk=0; kk<mNames.size(); kk++) {
127 sa_size_t sk = mNames[kk].ser;
128 sa_size_t ska = a.mNames[kk].ser;
129 switch (mNames[kk].type) {
130 case IntegerField :
131 mICols[sk] = a.mICols[ska];
132 break;
133 case LongField :
134 mLCols[sk] = a.mLCols[ska];
135 break;
136 case FloatField :
137 mFCols[sk] = a.mFCols[ska];
138 break;
139 case DoubleField :
140 case DateTimeField :
141 mDCols[sk] = a.mDCols[ska];
142 break;
143 case ComplexField :
144 mYCols[sk] = a.mYCols[ska];
145 break;
146 case DoubleComplexField :
147 mZCols[sk] = a.mZCols[ska];
148 break;
149 case StringField :
150 mSCols[sk] = a.mSCols[ska];
151 break;
152 default:
153 throw ForbiddenError("SwFitsDataTable::Share() : unknown column type ");
154 break;
155 }
156 }
157}
158void SwFitsDataTable::SwapOutAll() const
159{
160 // Et on vide les buffers de swap
161 for (size_t kk=0; kk<mNames.size(); kk++) {
162 sa_size_t sk = mNames[kk].ser;
163 switch (mNames[kk].type) {
164 case IntegerField :
165 mICols[sk].SwapOutBuffer();
166 break;
167 case LongField :
168 mLCols[sk].SwapOutBuffer();
169 break;
170 case FloatField :
171 mFCols[sk].SwapOutBuffer();
172 break;
173 case DoubleField :
174 case DateTimeField :
175 mDCols[sk].SwapOutBuffer();
176 break;
177 case ComplexField :
178 mYCols[sk].SwapOutBuffer();
179 break;
180 case DoubleComplexField :
181 mZCols[sk].SwapOutBuffer();
182 break;
183 case StringField :
184 mSCols[sk].SwapOutBuffer();
185 break;
186 default:
187 throw ForbiddenError("SwFitsDataTable::Share() : unknown column type ");
188 break;
189 }
190 }
191}
192
193void SwFitsDataTable::Clear()
194{
195 if ( (NVar() == 0) && (NEntry() == 0)) return;
196 mNEnt = 0;
197 mNSeg = 0;
198 if (mVarD) delete[] mVarD;
199 mVarD = NULL;
200 if (mVarMTV) delete[] mVarMTV;
201 mVarMTV = NULL;
202 mNames.clear();
203 if (mInfo) delete mInfo;
204 mInfo = NULL;
205 mMin.clear();
206 mMax.clear();
207 mMinMaxNEnt.clear();
208 mIColsP.clear();
209 mLColsP.clear();
210 mFColsP.clear();
211 mDColsP.clear();
212 mYColsP.clear();
213 mZColsP.clear();
214 mSColsP.clear();
215
216 mIColIdx.clear();
217 mLColIdx.clear();
218 mFColIdx.clear();
219 mDColIdx.clear();
220 mYColIdx.clear();
221 mZColIdx.clear();
222 mSColIdx.clear();
223
224 mICols.clear();
225 mLCols.clear();
226 mFCols.clear();
227 mDCols.clear();
228 mYCols.clear();
229 mZCols.clear();
230 mSCols.clear();
231
232}
233
234
235/*!
236 Implements the action defined in the BaseDataTable interface.
237 In the current implementation, throws an exception (ParmError)
238 if the table contains some data already.
239*/
240sa_size_t SwFitsDataTable::AddColumn(FieldType ft, string const & cnom)
241{
242 return AddColRd(ft, cnom, -1, NULL);
243}
244/*!
245 Adds a column to the table. If swpos != NULL, the swapper is initialized
246 for reading data from the fits file. This method can be called
247 by FitsHandler<BaseDataTable> with non zero swpos.
248*/
249sa_size_t SwFitsDataTable::AddColRd(FieldType ft, string const & cnom,
250 int colidx, vector<int_8> const * swpos)
251{
252 if (NEntry() > 0)
253 throw ParmError("SwFitsDataTable::AddColumn() Table contains already data ");
254 CheckColName(cnom);
255 sa_size_t ser;
256 sa_size_t idx = NVar();
257 if (colidx < 1) colidx = idx+1;
258
259 switch (ft) {
260 case IntegerField :
261 {
262 ser = mICols.size();
263 FITSDataSwapper<int_4> ISwapper(mSwF, colidx);
264 if (swpos)
265 mICols.push_back(SwSegDataBlock<int_4>(ISwapper, *swpos, mSegSz));
266 else
267 mICols.push_back(SwSegDataBlock<int_4>(ISwapper, mSegSz));
268 mIColIdx.push_back(idx);
269 mIColsP.push_back(NULL);
270 for(sa_size_t kk=0; kk<mICols.size(); kk++)
271 mIColsP[kk] = &(mICols[kk]);
272 break;
273 }
274 case LongField :
275 {
276 ser = mLCols.size();
277 FITSDataSwapper<int_8> LSwapper(mSwF, colidx);
278 if (swpos)
279 mLCols.push_back(SwSegDataBlock<int_8>(LSwapper, *swpos, mSegSz));
280 else
281 mLCols.push_back(SwSegDataBlock<int_8>(LSwapper, mSegSz));
282 mLColIdx.push_back(idx);
283 mLColsP.push_back(NULL);
284 for(sa_size_t kk=0; kk<mLCols.size(); kk++)
285 mLColsP[kk] = &(mLCols[kk]);
286 break;
287 }
288 case FloatField :
289 {
290 ser = mFCols.size();
291 FITSDataSwapper<r_4> FSwapper(mSwF, colidx);
292 if (swpos)
293 mFCols.push_back(SwSegDataBlock<r_4>(FSwapper, *swpos, mSegSz));
294 else
295 mFCols.push_back(SwSegDataBlock<r_4>(FSwapper, mSegSz));
296 mFColIdx.push_back(idx);
297 mFColsP.push_back(NULL);
298 for(sa_size_t kk=0; kk<mFCols.size(); kk++)
299 mFColsP[kk] = &(mFCols[kk]);
300 break;
301 }
302 case DoubleField :
303 case DateTimeField :
304 {
305 ser = mDCols.size();
306 FITSDataSwapper<r_8> DSwapper(mSwF, colidx);
307 if (swpos)
308 mDCols.push_back(SwSegDataBlock<r_8>(DSwapper, *swpos, mSegSz));
309 else
310 mDCols.push_back(SwSegDataBlock<r_8>(DSwapper, mSegSz));
311 mDColIdx.push_back(idx);
312 mDColsP.push_back(NULL);
313 for(sa_size_t kk=0; kk<mDCols.size(); kk++)
314 mDColsP[kk] = &(mDCols[kk]);
315 break;
316 }
317 case ComplexField :
318 {
319 ser = mYCols.size();
320 FITSDataSwapper< complex<r_4> > YSwapper(mSwF, colidx);
321 if (swpos)
322 mYCols.push_back(SwSegDataBlock< complex<r_4> >(YSwapper, *swpos, mSegSz));
323 else
324 mYCols.push_back(SwSegDataBlock< complex<r_4> >(YSwapper, mSegSz));
325 mYColIdx.push_back(idx);
326 mYColsP.push_back(NULL);
327 for(sa_size_t kk=0; kk<mYCols.size(); kk++)
328 mYColsP[kk] = &(mYCols[kk]);
329 break;
330 }
331 case DoubleComplexField :
332 {
333 ser = mZCols.size();
334 FITSDataSwapper< complex<r_8> > ZSwapper(mSwF, colidx);
335 if (swpos)
336 mZCols.push_back(SwSegDataBlock< complex<r_8> >(ZSwapper, *swpos, mSegSz));
337 else
338 mZCols.push_back(SwSegDataBlock< complex<r_8> >(ZSwapper, mSegSz));
339 mZColIdx.push_back(idx);
340 mZColsP.push_back(NULL);
341 for(sa_size_t kk=0; kk<mZCols.size(); kk++)
342 mZColsP[kk] = &(mZCols[kk]);
343 break;
344 }
345 case StringField :
346 {
347 ser = mSCols.size();
348 FITSDataSwapper< string > SSwapper(mSwF, colidx);
349 if (swpos)
350 mSCols.push_back(SwSegDataBlock< string >(SSwapper, *swpos, mSegSz));
351 else
352 mSCols.push_back(SwSegDataBlock< string >(SSwapper, mSegSz));
353 mSColIdx.push_back(idx);
354 mSColsP.push_back(NULL);
355 for(sa_size_t kk=0; kk<mSCols.size(); kk++)
356 mSColsP[kk] = &(mSCols[kk]);
357 break;
358 }
359 default:
360 throw ParmError("SwFitsDataTable::AddColumn() unknown field type ");
361 break;
362 }
363 colst col;
364 col.nom = cnom;
365 col.type = ft;
366 col.ser = ser;
367 mNames.push_back(col);
368 // On est oblige de calculer les min-max lors du remplissage
369 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
370 mMin.push_back(9.E39);
371 mMax.push_back(-9.E39);
372 mMinMaxNEnt.push_back(0);
373
374 return NVar();
375}
376
377//! Adds a line (or row to the table) with r_8* input data.
378/*!
379 The min/max values for each column is updated, in addition
380 to the actions performed by the base class AddRow().
381 The table is also created on the FITS file at the first call to AddRow()
382*/
383sa_size_t SwFitsDataTable::AddRow(const r_8* data)
384{
385 if (NRows() == 0) { // On cree la definition de la table FITS au premier appel
386 FitsHandler<BaseDataTable> fio(*this);
387 fio.Write(mSwF);
388 }
389 // On est oblige de calculer les min-max lors du remplissage
390 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
391 for(sa_size_t k=0; k<NVar(); k++) {
392 double x = data[k];
393 if (x < mMin[k]) mMin[k] = x;
394 if (x > mMax[k]) mMax[k] = x;
395 mMinMaxNEnt[k]++;
396 }
397 return BaseDataTable::AddRow(data);
398}
399
400//! Adds a row (or line to the table) with input data as an array of MuTyV
401/*!
402 The min/max values for each column is updated, in addition
403 to the actions performed by the base class AddRow().
404 The table is also created on the FITS file at the first call to AddRow()
405*/
406sa_size_t SwFitsDataTable::AddRow(const MuTyV * data)
407{
408 if (NRows() == 0) { // On cree la definition de la table FITS au premier appel
409 FitsHandler<BaseDataTable> fio(*this);
410 fio.Write(mSwF);
411 }
412 // On est oblige de calculer les min-max lors du remplissage
413 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
414 for(sa_size_t k=0; k<NVar(); k++) {
415 double x = (double)data[k];
416 if (x < mMin[k]) mMin[k] = x;
417 if (x > mMax[k]) mMax[k] = x;
418 mMinMaxNEnt[k]++;
419 }
420 return BaseDataTable::AddRow(data);
421}
422
423//! Adds a row (or line) to the table with input data as DataTableRow object
424/*!
425 The min/max values for each column is updated, in addition
426 to the actions performed by the base class AddRow().
427 The table is also created on the FITS file at the first call to AddRow()
428*/
429sa_size_t SwFitsDataTable::AddRow(DataTableRow const& data)
430{
431 if ( data.Size() != NCols() )
432 throw SzMismatchError(" SwFitsDataTable::AddRow() - data.Size() != NCols() ");
433 return AddRow(data.MTVPtr());
434}
Note: See TracBrowser for help on using the repository browser.