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