| [2688] | 1 | #include "datatable.h"
 | 
|---|
 | 2 | #include "strutil.h"
 | 
|---|
 | 3 | #include "pexceptions.h"
 | 
|---|
 | 4 | #include "fiosegdb.h"
 | 
|---|
| [3392] | 5 | #include "thsafeop.h"
 | 
|---|
| [2688] | 6 | 
 | 
|---|
| [3392] | 7 | namespace SOPHYA { 
 | 
|---|
| [2688] | 8 | 
 | 
|---|
 | 9 | /*!
 | 
|---|
| [3392] | 10 |    \class DataTable
 | 
|---|
| [2688] | 11 |    \ingroup HiStats
 | 
|---|
 | 12 |    This class can be used to organize data in table (row-column) form.
 | 
|---|
 | 13 |    Each column holds homogeneous data (same data type), while different
 | 
|---|
| [2808] | 14 |    columns can be used for different data types 
 | 
|---|
 | 15 |    (integer, float, string ...).
 | 
|---|
 | 16 |    The whole data set is kept in memory.
 | 
|---|
| [2688] | 17 |    \sa SOPHYA::MuTyV
 | 
|---|
| [2849] | 18 |    \sa SOPHYA::DataTableRow
 | 
|---|
| [2688] | 19 |    \sa SOPHYA::BaseDataTable
 | 
|---|
| [2808] | 20 |    \sa SOPHYA::SegDataBlock
 | 
|---|
| [2688] | 21 | 
 | 
|---|
 | 22 |    \code
 | 
|---|
 | 23 |    #include "datatable.h"
 | 
|---|
 | 24 |    // ...
 | 
|---|
 | 25 |    DataTable dt(64);
 | 
|---|
 | 26 |    dt.AddFloatColumn("X0_f");
 | 
|---|
 | 27 |    dt.AddFloatColumn("X1_f");
 | 
|---|
 | 28 |    dt.AddDoubleColumn("X0X0pX1X1_d");
 | 
|---|
 | 29 |    double x[5];
 | 
|---|
 | 30 |    for(int i=0; i<63; i++) {
 | 
|---|
 | 31 |      x[0] = (i%9)-4.;  x[1] = (i/9)-3.;  x[2] = x[0]*x[0]+x[1]*x[1];
 | 
|---|
| [2849] | 32 |      dt.AddRow(x);
 | 
|---|
| [2688] | 33 |    }
 | 
|---|
 | 34 |    // Printing table info
 | 
|---|
 | 35 |    cout << dt ;
 | 
|---|
 | 36 |    // Saving object into a PPF file
 | 
|---|
 | 37 |    POutPersist po("dtable.ppf");
 | 
|---|
 | 38 |    po << dt ;
 | 
|---|
 | 39 |    \endcode
 | 
|---|
| [2849] | 40 | 
 | 
|---|
 | 41 |   DataTableRow objects can also be used to fill the table, or access the data, as
 | 
|---|
 | 42 |   shown in the example below:
 | 
|---|
 | 43 |   \code
 | 
|---|
 | 44 |   // We use the same table as in the example above:
 | 
|---|
 | 45 |   DataTableRow row = dt.EmptyRow();
 | 
|---|
 | 46 |   row[0] = 83.3; row[1] = 20.;   row[2] = 83.3*83.3+20.*20.;
 | 
|---|
 | 47 |   dt.AddRow(row);
 | 
|---|
 | 48 |   row["X0_f"] = 7.5; row["X1_f"] = 6.;  row["X0X0pX1X1_d"] = 7.5*7.5+6.*6.;
 | 
|---|
 | 49 |   dt.AddRow(row);  
 | 
|---|
 | 50 |   \endcode
 | 
|---|
| [2688] | 51 | */
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 | 
 | 
|---|
 | 54 | //! Default constructor - optional specification of block (or segment) size
 | 
|---|
 | 55 | DataTable::DataTable(sa_size_t segsz)
 | 
|---|
 | 56 |   : BaseDataTable(segsz)
 | 
|---|
 | 57 | {
 | 
|---|
 | 58 | }
 | 
|---|
 | 59 | 
 | 
|---|
| [2808] | 60 | //! copy constructor 
 | 
|---|
 | 61 | /*!
 | 
|---|
 | 62 |   The copy constructur shares the data if \b share=true. 
 | 
|---|
 | 63 |   Otherwise, the Clone() method is called to make a complete copy.
 | 
|---|
| [3392] | 64 |   This constructor copies also the thread safety state from \b a .
 | 
|---|
| [2808] | 65 | */
 | 
|---|
| [2688] | 66 | DataTable::DataTable(DataTable const & a, bool share)
 | 
|---|
 | 67 |   : BaseDataTable(a.SegmentSize())
 | 
|---|
 | 68 | {
 | 
|---|
 | 69 |   if (share) Share(a);
 | 
|---|
 | 70 |   else Clone(a);
 | 
|---|
 | 71 |   mNEnt = a.mNEnt;
 | 
|---|
 | 72 |   mNSeg = a.mNSeg;
 | 
|---|
 | 73 |   if (a.mInfo)  mInfo = new DVList(*(a.mInfo));
 | 
|---|
 | 74 | }
 | 
|---|
| [3392] | 75 | /*! 
 | 
|---|
 | 76 |   Copy the table structure from \b a and shares the data (columns content).
 | 
|---|
 | 77 |   The tread-safety state is copied from \b a .
 | 
|---|
 | 78 | */
 | 
|---|
| [2688] | 79 | void DataTable::Share(DataTable const & a)
 | 
|---|
 | 80 | {
 | 
|---|
 | 81 |   // On copie la structure de table 
 | 
|---|
 | 82 |   CopyStructure(a);
 | 
|---|
| [3392] | 83 |   if (a.IsThreadSafe())  SetThreadSafe(true);
 | 
|---|
 | 84 |   else SetThreadSafe(false);
 | 
|---|
| [2688] | 85 |   // Et on partage les donnees des colonnes 
 | 
|---|
 | 86 |   for (size_t kk=0; kk<mNames.size(); kk++) {
 | 
|---|
 | 87 |     sa_size_t sk = mNames[kk].ser;
 | 
|---|
 | 88 |     sa_size_t ska = a.mNames[kk].ser;
 | 
|---|
 | 89 |     switch (mNames[kk].type) {
 | 
|---|
 | 90 |     case IntegerField :
 | 
|---|
 | 91 |       mICols[sk].Share(a.mICols[ska]); 
 | 
|---|
 | 92 |     break;
 | 
|---|
 | 93 |     case LongField :
 | 
|---|
 | 94 |       mLCols[sk].Share(a.mLCols[ska]); 
 | 
|---|
 | 95 |       break;
 | 
|---|
 | 96 |     case FloatField :
 | 
|---|
 | 97 |       mFCols[sk].Share(a.mFCols[ska]); 
 | 
|---|
 | 98 |       break;
 | 
|---|
 | 99 |     case DoubleField :
 | 
|---|
| [2831] | 100 |     case DateTimeField :
 | 
|---|
| [2688] | 101 |       mDCols[sk].Share(a.mDCols[ska]); 
 | 
|---|
 | 102 |       break;
 | 
|---|
| [2827] | 103 |     case ComplexField :
 | 
|---|
 | 104 |       mYCols[sk].Share(a.mYCols[ska]); 
 | 
|---|
 | 105 |       break;
 | 
|---|
 | 106 |     case DoubleComplexField :
 | 
|---|
 | 107 |       mZCols[sk].Share(a.mZCols[ska]); 
 | 
|---|
 | 108 |       break;
 | 
|---|
| [2688] | 109 |     case StringField :
 | 
|---|
 | 110 |       mSCols[sk].Share(a.mSCols[ska]); 
 | 
|---|
 | 111 |       break;
 | 
|---|
 | 112 |     default:
 | 
|---|
 | 113 |       throw ForbiddenError("DataTable::Share() : unknown column type ");
 | 
|---|
 | 114 |     break;
 | 
|---|
 | 115 |     }
 | 
|---|
 | 116 |   }  
 | 
|---|
 | 117 | }
 | 
|---|
 | 118 | 
 | 
|---|
| [2808] | 119 | //! Copy the table structure from \b a and duplicate (copy) the data (columns content)
 | 
|---|
| [2688] | 120 | void DataTable::Clone(DataTable const & a)
 | 
|---|
 | 121 | {
 | 
|---|
 | 122 |   // On copie la structure de table 
 | 
|---|
 | 123 |   CopyStructure(a);
 | 
|---|
| [3392] | 124 |   if (a.IsThreadSafe())  SetThreadSafe(true);
 | 
|---|
 | 125 |   else SetThreadSafe(false);
 | 
|---|
 | 126 |   // Et on copie les donnees des colonnes 
 | 
|---|
| [2688] | 127 |   for (size_t kk=0; kk<mNames.size(); kk++) {
 | 
|---|
 | 128 |     sa_size_t sk = mNames[kk].ser;
 | 
|---|
 | 129 |     sa_size_t ska = a.mNames[kk].ser;
 | 
|---|
 | 130 |     switch (mNames[kk].type) {
 | 
|---|
 | 131 |     case IntegerField :
 | 
|---|
 | 132 |       mICols[sk].Clone(a.mICols[ska], true); 
 | 
|---|
 | 133 |     break;
 | 
|---|
 | 134 |     case LongField :
 | 
|---|
 | 135 |       mLCols[sk].Clone(a.mLCols[ska], true); 
 | 
|---|
 | 136 |       break;
 | 
|---|
 | 137 |     case FloatField :
 | 
|---|
 | 138 |       mFCols[sk].Clone(a.mFCols[ska], true); 
 | 
|---|
 | 139 |       break;
 | 
|---|
 | 140 |     case DoubleField :
 | 
|---|
| [2831] | 141 |     case DateTimeField :
 | 
|---|
| [2688] | 142 |       mDCols[sk].Clone(a.mDCols[ska], true); 
 | 
|---|
 | 143 |       break;
 | 
|---|
| [2827] | 144 |     case ComplexField :
 | 
|---|
 | 145 |       mYCols[sk].Clone(a.mYCols[ska], true); 
 | 
|---|
 | 146 |       break;
 | 
|---|
 | 147 |     case DoubleComplexField :
 | 
|---|
 | 148 |       mZCols[sk].Clone(a.mZCols[ska], true); 
 | 
|---|
 | 149 |       break;
 | 
|---|
| [2688] | 150 |     case StringField :
 | 
|---|
 | 151 |       mSCols[sk].Clone(a.mSCols[ska], true); 
 | 
|---|
 | 152 |       break;
 | 
|---|
 | 153 |     default:
 | 
|---|
 | 154 |       throw ForbiddenError("DataTable::Clone() : unknown column type ");
 | 
|---|
 | 155 |     break;
 | 
|---|
 | 156 |     }
 | 
|---|
 | 157 |   }  
 | 
|---|
 | 158 | }
 | 
|---|
| [2808] | 159 | //! Reset (/clear) the table content and structure
 | 
|---|
| [2688] | 160 | void DataTable::Clear()
 | 
|---|
 | 161 | {
 | 
|---|
 | 162 |   if ( (NVar() == 0) && (NEntry() == 0)) return;
 | 
|---|
 | 163 |   mNEnt = 0;
 | 
|---|
 | 164 |   mNSeg = 0;
 | 
|---|
 | 165 |   if (mVarD) delete[] mVarD;
 | 
|---|
 | 166 |   mVarD = NULL;
 | 
|---|
 | 167 |   if (mVarMTV) delete[] mVarMTV;
 | 
|---|
 | 168 |   mVarMTV = NULL;
 | 
|---|
 | 169 |   mNames.clear();
 | 
|---|
 | 170 |   if (mInfo) delete mInfo;
 | 
|---|
 | 171 |   mInfo = NULL;
 | 
|---|
| [3392] | 172 |   if (mThS) delete mThS;
 | 
|---|
 | 173 |   mThS = NULL;
 | 
|---|
| [2688] | 174 |   mMin.clear();
 | 
|---|
 | 175 |   mMax.clear();
 | 
|---|
 | 176 |   mMinMaxNEnt.clear();
 | 
|---|
 | 177 |   mIColsP.clear();
 | 
|---|
 | 178 |   mLColsP.clear();
 | 
|---|
 | 179 |   mFColsP.clear();
 | 
|---|
 | 180 |   mDColsP.clear();
 | 
|---|
| [2827] | 181 |   mYColsP.clear();
 | 
|---|
 | 182 |   mZColsP.clear();
 | 
|---|
| [2688] | 183 |   mSColsP.clear();
 | 
|---|
 | 184 | 
 | 
|---|
 | 185 |   mIColIdx.clear();
 | 
|---|
 | 186 |   mLColIdx.clear();
 | 
|---|
 | 187 |   mFColIdx.clear();
 | 
|---|
 | 188 |   mDColIdx.clear();
 | 
|---|
| [2827] | 189 |   mYColIdx.clear();
 | 
|---|
 | 190 |   mZColIdx.clear();
 | 
|---|
| [2688] | 191 |   mSColIdx.clear();
 | 
|---|
 | 192 | 
 | 
|---|
 | 193 |   mICols.clear();
 | 
|---|
 | 194 |   mLCols.clear();
 | 
|---|
 | 195 |   mFCols.clear();
 | 
|---|
 | 196 |   mDCols.clear();
 | 
|---|
| [2827] | 197 |   mYCols.clear();
 | 
|---|
 | 198 |   mZCols.clear();
 | 
|---|
| [2688] | 199 |   mSCols.clear();
 | 
|---|
 | 200 | }
 | 
|---|
 | 201 | 
 | 
|---|
 | 202 | 
 | 
|---|
| [2808] | 203 | /*! 
 | 
|---|
 | 204 |   Implements the action defined in the BaseDataTable interface.
 | 
|---|
 | 205 |   In the current implementation, throws an exception (ParmError) 
 | 
|---|
 | 206 |   if the table contains some data already.
 | 
|---|
 | 207 | */
 | 
|---|
| [2688] | 208 | sa_size_t DataTable::AddColumn(FieldType ft, string const & cnom)
 | 
|---|
 | 209 | {
 | 
|---|
 | 210 |   if (NEntry() > 0) 
 | 
|---|
 | 211 |     throw ParmError("DataTable::AddColumn() Table contains already data ");
 | 
|---|
 | 212 |   CheckColName(cnom);
 | 
|---|
 | 213 |   sa_size_t ser; 
 | 
|---|
 | 214 |   sa_size_t idx = NVar(); 
 | 
|---|
 | 215 |   switch (ft) {
 | 
|---|
 | 216 |   case IntegerField :
 | 
|---|
 | 217 |     ser = mICols.size();
 | 
|---|
 | 218 |     mICols.push_back(SegDataBlock<int_4>(mSegSz));
 | 
|---|
 | 219 |     mIColIdx.push_back(idx);
 | 
|---|
 | 220 |     mIColsP.push_back(NULL);
 | 
|---|
 | 221 |     for(sa_size_t kk=0; kk<mICols.size(); kk++)
 | 
|---|
 | 222 |       mIColsP[kk] = &(mICols[kk]);
 | 
|---|
 | 223 |     break;
 | 
|---|
 | 224 |   case LongField :
 | 
|---|
 | 225 |     ser = mLCols.size();
 | 
|---|
 | 226 |     mLCols.push_back(SegDataBlock<int_8>(mSegSz));
 | 
|---|
 | 227 |     mLColIdx.push_back(idx);
 | 
|---|
 | 228 |     mLColsP.push_back(NULL);
 | 
|---|
 | 229 |     for(sa_size_t kk=0; kk<mLCols.size(); kk++)
 | 
|---|
 | 230 |       mLColsP[kk] = &(mLCols[kk]);
 | 
|---|
 | 231 |     break;
 | 
|---|
 | 232 |   case FloatField :
 | 
|---|
 | 233 |     ser = mFCols.size();
 | 
|---|
 | 234 |     mFCols.push_back(SegDataBlock<r_4>(mSegSz));
 | 
|---|
 | 235 |     mFColIdx.push_back(idx);
 | 
|---|
 | 236 |     mFColsP.push_back(NULL);
 | 
|---|
 | 237 |     for(sa_size_t kk=0; kk<mFCols.size(); kk++)
 | 
|---|
 | 238 |       mFColsP[kk] = &(mFCols[kk]);
 | 
|---|
 | 239 |     break;
 | 
|---|
 | 240 |   case DoubleField :
 | 
|---|
| [2831] | 241 |   case DateTimeField :
 | 
|---|
| [2688] | 242 |     ser = mDCols.size();
 | 
|---|
 | 243 |     mDCols.push_back(SegDataBlock<r_8>(mSegSz));
 | 
|---|
 | 244 |     mDColIdx.push_back(idx);
 | 
|---|
 | 245 |     mDColsP.push_back(NULL);
 | 
|---|
 | 246 |     for(sa_size_t kk=0; kk<mDCols.size(); kk++)
 | 
|---|
 | 247 |       mDColsP[kk] = &(mDCols[kk]);
 | 
|---|
 | 248 |     break;
 | 
|---|
| [2827] | 249 |   case ComplexField :
 | 
|---|
 | 250 |     ser = mYCols.size();
 | 
|---|
 | 251 |     mYCols.push_back(SegDataBlock< complex<r_4> >(mSegSz));
 | 
|---|
 | 252 |     mYColIdx.push_back(idx);
 | 
|---|
 | 253 |     mYColsP.push_back(NULL);
 | 
|---|
 | 254 |     for(sa_size_t kk=0; kk<mYCols.size(); kk++)
 | 
|---|
 | 255 |       mYColsP[kk] = &(mYCols[kk]);
 | 
|---|
 | 256 |     break;
 | 
|---|
 | 257 |   case DoubleComplexField :
 | 
|---|
 | 258 |     ser = mZCols.size();
 | 
|---|
 | 259 |     mZCols.push_back(SegDataBlock< complex<r_8> >(mSegSz));
 | 
|---|
 | 260 |     mZColIdx.push_back(idx);
 | 
|---|
 | 261 |     mZColsP.push_back(NULL);
 | 
|---|
 | 262 |     for(sa_size_t kk=0; kk<mZCols.size(); kk++)
 | 
|---|
 | 263 |       mZColsP[kk] = &(mZCols[kk]);
 | 
|---|
 | 264 |     break;
 | 
|---|
| [2688] | 265 |   case StringField :
 | 
|---|
| [2847] | 266 |     ser = mSCols.size();
 | 
|---|
| [2688] | 267 |     mSCols.push_back(SegDataBlock<string>(mSegSz));
 | 
|---|
 | 268 |     mSColIdx.push_back(idx);
 | 
|---|
 | 269 |     mSColsP.push_back(NULL);
 | 
|---|
 | 270 |     for(sa_size_t kk=0; kk<mSCols.size(); kk++)
 | 
|---|
 | 271 |       mSColsP[kk] = &(mSCols[kk]);
 | 
|---|
 | 272 |     break;
 | 
|---|
 | 273 |   default:
 | 
|---|
 | 274 |     throw ParmError("DataTable::AddColumn() unknown field type ");
 | 
|---|
 | 275 |     break;
 | 
|---|
 | 276 |   }
 | 
|---|
 | 277 |   colst col;
 | 
|---|
 | 278 |   col.nom = cnom;
 | 
|---|
 | 279 |   col.type = ft;
 | 
|---|
 | 280 |   col.ser = ser;
 | 
|---|
 | 281 |   mNames.push_back(col);
 | 
|---|
| [2696] | 282 | 
 | 
|---|
 | 283 |   // Tableaux de calcul min-max
 | 
|---|
 | 284 |   mMin.push_back(0.);
 | 
|---|
 | 285 |   mMax.push_back(0.);
 | 
|---|
 | 286 |   mMinMaxNEnt.push_back(0);
 | 
|---|
 | 287 | 
 | 
|---|
| [2688] | 288 |   return NVar();
 | 
|---|
 | 289 | }
 | 
|---|
 | 290 | 
 | 
|---|
| [3392] | 291 | } // FIN namespace SOPHYA 
 | 
|---|