#include "swfitsdtable.h" #include "fitshdtable.h" #include "sopnamsp.h" #include "pexceptions.h" /*! \class SOPHYA::SwFitsDataTable \ingroup FitsIOServer This class can be used to organize data in table (row-column) form. Each column holds homogeneous data (same data type), while different columns can be used for different data types (integer, float, string ...). A Fits file binary table is used as swap space. \warning - When creating a table, the output fits file (FitsInOutFile) must not be closed (destroyed) before the SwFitsDataTable object is destroyed. The destructor writes out any pending buffer to the fits file. - It is not possible to make a complete (deep) copy of a SwFitsDataTable Copy constructor and equal operator shares the data. - The min/max values for column data are not updated when reading from a fits file. In this case, the Show() method (or ostream& << operator) will compute min/max values. This operation will take some time for large tables. \sa SOPHYA::MuTyV \sa SOPHYA::DataTableRow \sa SOPHYA::DataTable \sa SOPHYA::SwSegDataBlock SOPHYA::FitsDataSwapper \code #include "swfitsdtable.h" // ... { // ---- Creation of the table // Create the swap stream FitsInOutFile so("myswtable.fits", FitsInOutFile::Fits_Create); SwFitsDataTable dt(so, 16); // define table columns dt.AddFloatColumn("X0_f"); dt.AddFloatColumn("X1_f"); dt.AddDoubleColumn("X0X0pX1X1_d"); // Fill the table r_8 x[5]; for(int i=0; i<63; i++) { x[0] = (i%9)-4.; x[1] = (i/9)-3.; x[2] = x[0]*x[0]+x[1]*x[1]; dt.AddLine(x); } // Printing table info cout << dt ; // The destructor will Swap out data still in memory } { // ---- Accessing information from a previously created table SwFitsDataTable dt; FitsInOutFile si("myswtable.fits", FitsInOutFile::Fits_ReadOnly); // Position the fits file on the first extension (BinTable) si.MoveAbsToHDU(2); // Reading in the table (initialisation) si >> dt; // Printing table info cout << dt ; } \endcode */ //! Default constructor with optional specification of block (or segment) size SwFitsDataTable::SwFitsDataTable(sa_size_t segsz) : BaseDataTable(segsz) { mFgCreate = false; } /*! Constructor with the specification of the output swap stream - and optional specification of block (or segment) size */ SwFitsDataTable::SwFitsDataTable(FitsInOutFile & os, sa_size_t segsz, bool fgcreate) : BaseDataTable(segsz) , mSwF(os) , mFgCreate(fgcreate) { if (!fgcreate) { // Lecture de la table FitsHandler fio(*this); fio.Read(os); } } //! copy constructor - shares the data SwFitsDataTable::SwFitsDataTable(SwFitsDataTable const & a) : BaseDataTable(a.SegmentSize()), mSwF(a.mSwF) , mFgCreate(a.mFgCreate) { Share(a); } //! Destructor - Deletes / closes the input PPF swap stream SwFitsDataTable::~SwFitsDataTable() { if (mFgCreate) { SwapOutAll(); // Ecriture de SegmentSize et autre elements de DVList mSwF.WriteHeaderRecords(Info()); MuTyV mtv = SegmentSize(); mSwF.WriteKey("SEGMSIZE",mtv," SOPHYA::DataTable SegmentSize"); mtv = "SOPHYA::SwFitsDataTable"; mSwF.WriteKey("SOPCLSNM",mtv," Object class name "); } } void SwFitsDataTable::Share(SwFitsDataTable const & a) { // On recopie la taille de segment mSegSz = a.SegmentSize(); if (a.NVar() == 0) return; // Table sans colonne // On copie la structure de table CopyStructure(a); // // Update nombre d'entree, ... mNEnt = a.mNEnt; mNSeg = a.mNSeg; if (a.mInfo) mInfo = new DVList(*(a.mInfo)); // mis a jour des tableax min-max mMin = a.mMin; mMax = a.mMax; mMinMaxNEnt = a.mMinMaxNEnt; // Et on partage les donnees des colonnes for (size_t kk=0; kk with non zero swpos. */ sa_size_t SwFitsDataTable::AddColRd(FieldType ft, string const & cnom, int colidx, vector const * swpos) { if (NEntry() > 0) throw ParmError("SwFitsDataTable::AddColumn() Table contains already data "); CheckColName(cnom); sa_size_t ser; sa_size_t idx = NVar(); if (colidx < 1) colidx = idx+1; switch (ft) { case IntegerField : { ser = mICols.size(); FITSDataSwapper ISwapper(mSwF, colidx); if (swpos) mICols.push_back(SwSegDataBlock(ISwapper, *swpos, mSegSz)); else mICols.push_back(SwSegDataBlock(ISwapper, mSegSz)); mIColIdx.push_back(idx); mIColsP.push_back(NULL); for(sa_size_t kk=0; kk LSwapper(mSwF, colidx); if (swpos) mLCols.push_back(SwSegDataBlock(LSwapper, *swpos, mSegSz)); else mLCols.push_back(SwSegDataBlock(LSwapper, mSegSz)); mLColIdx.push_back(idx); mLColsP.push_back(NULL); for(sa_size_t kk=0; kk FSwapper(mSwF, colidx); if (swpos) mFCols.push_back(SwSegDataBlock(FSwapper, *swpos, mSegSz)); else mFCols.push_back(SwSegDataBlock(FSwapper, mSegSz)); mFColIdx.push_back(idx); mFColsP.push_back(NULL); for(sa_size_t kk=0; kk DSwapper(mSwF, colidx); if (swpos) mDCols.push_back(SwSegDataBlock(DSwapper, *swpos, mSegSz)); else mDCols.push_back(SwSegDataBlock(DSwapper, mSegSz)); mDColIdx.push_back(idx); mDColsP.push_back(NULL); for(sa_size_t kk=0; kk > YSwapper(mSwF, colidx); if (swpos) mYCols.push_back(SwSegDataBlock< complex >(YSwapper, *swpos, mSegSz)); else mYCols.push_back(SwSegDataBlock< complex >(YSwapper, mSegSz)); mYColIdx.push_back(idx); mYColsP.push_back(NULL); for(sa_size_t kk=0; kk > ZSwapper(mSwF, colidx); if (swpos) mZCols.push_back(SwSegDataBlock< complex >(ZSwapper, *swpos, mSegSz)); else mZCols.push_back(SwSegDataBlock< complex >(ZSwapper, mSegSz)); mZColIdx.push_back(idx); mZColsP.push_back(NULL); for(sa_size_t kk=0; kk SSwapper(mSwF, colidx); if (swpos) mSCols.push_back(SwSegDataBlock< string >(SSwapper, *swpos, mSegSz)); else mSCols.push_back(SwSegDataBlock< string >(SSwapper, mSegSz)); mSColIdx.push_back(idx); mSColsP.push_back(NULL); for(sa_size_t kk=0; kk fio(*this); fio.Write(mSwF); } // On est oblige de calculer les min-max lors du remplissage // On ne peut pas en effet 'relire' le swap pendant l'ecriture for(sa_size_t k=0; k mMax[k]) mMax[k] = x; mMinMaxNEnt[k]++; } return BaseDataTable::AddRow(data); } //! Adds a row (or line to the table) with input data as an array of MuTyV /*! The min/max values for each column is updated, in addition to the actions performed by the base class AddRow() */ sa_size_t SwFitsDataTable::AddRow(const MuTyV * data) { if (NRows() == 0) { // On cree la definition de la table FITS au premier appel FitsHandler fio(*this); fio.Write(mSwF); } // On est oblige de calculer les min-max lors du remplissage // On ne peut pas en effet 'relire' le swap pendant l'ecriture for(sa_size_t k=0; k mMax[k]) mMax[k] = x; mMinMaxNEnt[k]++; } return BaseDataTable::AddRow(data); }