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

Last change on this file since 2895 was 2889, checked in by ansari, 20 years ago

Mise au point de la classe SwFitsDataTable - Reza 9/01/2006

File size: 11.7 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*/
382sa_size_t SwFitsDataTable::AddRow(const r_8* data)
383{
384 if (NRows() == 0) { // On cree la definition de la table FITS au premier appel
385 FitsHandler<BaseDataTable> fio(*this);
386 fio.Write(mSwF);
387 }
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 for(sa_size_t k=0; k<NVar(); k++) {
391 double x = data[k];
392 if (x < mMin[k]) mMin[k] = x;
393 if (x > mMax[k]) mMax[k] = x;
394 mMinMaxNEnt[k]++;
395 }
396 return BaseDataTable::AddRow(data);
397}
398
399//! Adds a row (or line to the table) with input data as an array of MuTyV
400/*!
401 The min/max values for each column is updated, in addition
402 to the actions performed by the base class AddRow()
403*/
404sa_size_t SwFitsDataTable::AddRow(const MuTyV * data)
405{
406 if (NRows() == 0) { // On cree la definition de la table FITS au premier appel
407 FitsHandler<BaseDataTable> fio(*this);
408 fio.Write(mSwF);
409 }
410 // On est oblige de calculer les min-max lors du remplissage
411 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
412 for(sa_size_t k=0; k<NVar(); k++) {
413 double x = (double)data[k];
414 if (x < mMin[k]) mMin[k] = x;
415 if (x > mMax[k]) mMax[k] = x;
416 mMinMaxNEnt[k]++;
417 }
418 return BaseDataTable::AddRow(data);
419}
420
Note: See TracBrowser for help on using the repository browser.