#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(). The table is also created on the FITS file at the first call to 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); } //! Adds a row (or line) to the table with input data as DataTableRow object /*! The min/max values for each column is updated, in addition to the actions performed by the base class AddRow(). The table is also created on the FITS file at the first call to AddRow() */ sa_size_t SwFitsDataTable::AddRow(DataTableRow const& data) { if ( data.Size() != NCols() ) throw SzMismatchError(" SwFitsDataTable::AddRow() - data.Size() != NCols() "); return AddRow(data.MTVPtr()); }