Index: trunk/SophyaLib/HiStats/Makefile
===================================================================
--- trunk/SophyaLib/HiStats/Makefile	(revision 2682)
+++ trunk/SophyaLib/HiStats/Makefile	(revision 2688)
@@ -3,7 +3,7 @@
 all: $(LIB)libHiStats.a
 clean:
-	rm -f $(OBJ)hisprof.o $(OBJ)histerr.o $(OBJ)histinit.o $(OBJ)histos.o $(OBJ)histos2.o $(OBJ)ntupintf.o $(OBJ)ntuple.o $(OBJ)proxtuple.o $(OBJ)xntuple.o
+	rm -f $(OBJ)basedtable.o $(OBJ)datatable.o $(OBJ)hisprof.o $(OBJ)histerr.o $(OBJ)histinit.o $(OBJ)histos.o $(OBJ)histos2.o $(OBJ)ntupintf.o $(OBJ)ntuple.o $(OBJ)proxtuple.o $(OBJ)xntuple.o
 	rm -f $(LIB)libHiStats.a
-$(LIB)libHiStats.a : $(OBJ)hisprof.o $(OBJ)histerr.o $(OBJ)histinit.o $(OBJ)histos.o $(OBJ)histos2.o $(OBJ)ntupintf.o $(OBJ)ntuple.o $(OBJ)proxtuple.o $(OBJ)xntuple.o
+$(LIB)libHiStats.a : $(OBJ)basedtable.o $(OBJ)datatable.o $(OBJ)hisprof.o $(OBJ)histerr.o $(OBJ)histinit.o $(OBJ)histos.o $(OBJ)histos2.o $(OBJ)ntupintf.o $(OBJ)ntuple.o $(OBJ)proxtuple.o $(OBJ)xntuple.o
 	$(ARCXX) $(ARCXXFLAGS) $@ $($(ARARGS))
 ifeq ($(CXX),cxx)
@@ -11,155 +11,195 @@
 endif 
  
-$(OBJ)hisprof.o: hisprof.cc $(INC)machdefs.h \
- hisprof.h $(INC)peida.h \
- $(INC)utils.h \
- $(INC)perrors.h \
- $(INC)pexceptions.h \
- $(INC)fmath.h \
- $(INC)tvector.h \
- $(INC)tmatrix.h \
- $(INC)tarray.h \
- $(INC)basarr.h \
- $(INC)anydataobj.h \
- $(INC)mutyv.h \
- $(INC)dvlist.h \
- $(INC)objfio.h \
- $(INC)ppersist.h \
- $(INC)gnumd5.h \
- $(INC)ppfbinstream.h \
- $(INC)rawstream.h \
- $(INC)ppfnametag.h \
- $(INC)ndatablock.h \
- $(INC)utilarr.h histos.h
-$(OBJ)histerr.o: histerr.cc $(INC)machdefs.h \
- histinit.h $(INC)ntoolsinit.h \
- $(INC)tarrinit.h \
- $(INC)sophyainit.h histerr.h \
- $(INC)objfio.h \
- $(INC)anydataobj.h \
- $(INC)ppersist.h \
- $(INC)pexceptions.h \
- $(INC)gnumd5.h \
- $(INC)ppfbinstream.h \
- $(INC)rawstream.h \
- $(INC)ppfnametag.h histos.h \
- $(INC)peida.h \
- $(INC)utils.h \
- $(INC)perrors.h \
- $(INC)fmath.h \
- $(INC)tvector.h \
- $(INC)tmatrix.h \
- $(INC)tarray.h \
- $(INC)basarr.h \
- $(INC)mutyv.h \
- $(INC)dvlist.h \
- $(INC)ndatablock.h \
- $(INC)utilarr.h
-$(OBJ)histinit.o: histinit.cc $(INC)machdefs.h \
- histinit.h $(INC)ntoolsinit.h \
- $(INC)tarrinit.h \
- $(INC)sophyainit.h histos.h \
- $(INC)objfio.h \
- $(INC)anydataobj.h \
- $(INC)ppersist.h \
- $(INC)pexceptions.h \
- $(INC)gnumd5.h \
- $(INC)ppfbinstream.h \
- $(INC)rawstream.h \
- $(INC)ppfnametag.h \
- $(INC)peida.h \
- $(INC)utils.h \
- $(INC)perrors.h \
- $(INC)fmath.h \
- $(INC)tvector.h \
- $(INC)tmatrix.h \
- $(INC)tarray.h \
- $(INC)basarr.h \
- $(INC)mutyv.h \
- $(INC)dvlist.h \
- $(INC)ndatablock.h \
- $(INC)utilarr.h histos2.h hisprof.h \
- histerr.h ntuple.h ntupintf.h xntuple.h
-$(OBJ)histos.o: histos.cc $(INC)machdefs.h histos.h \
- $(INC)objfio.h \
- $(INC)anydataobj.h \
- $(INC)ppersist.h \
- $(INC)pexceptions.h \
- $(INC)gnumd5.h \
- $(INC)ppfbinstream.h \
- $(INC)rawstream.h \
- $(INC)ppfnametag.h \
- $(INC)peida.h \
- $(INC)utils.h \
- $(INC)perrors.h \
- $(INC)fmath.h \
- $(INC)tvector.h \
- $(INC)tmatrix.h \
- $(INC)tarray.h \
- $(INC)basarr.h \
- $(INC)mutyv.h \
- $(INC)dvlist.h \
- $(INC)ndatablock.h \
- $(INC)utilarr.h \
- $(INC)poly.h \
- $(INC)strutil.h
-$(OBJ)histos2.o: histos2.cc $(INC)machdefs.h \
- histos2.h $(INC)peida.h \
- $(INC)utils.h \
- $(INC)perrors.h \
- $(INC)pexceptions.h \
- $(INC)fmath.h histos.h \
- $(INC)objfio.h \
- $(INC)anydataobj.h \
- $(INC)ppersist.h \
- $(INC)gnumd5.h \
- $(INC)ppfbinstream.h \
- $(INC)rawstream.h \
- $(INC)ppfnametag.h \
- $(INC)tvector.h \
- $(INC)tmatrix.h \
- $(INC)tarray.h \
- $(INC)basarr.h \
- $(INC)mutyv.h \
- $(INC)dvlist.h \
- $(INC)ndatablock.h \
- $(INC)utilarr.h
-$(OBJ)ntupintf.o: ntupintf.cc ntupintf.h \
- $(INC)machdefs.h
-$(OBJ)ntuple.o: ntuple.cc $(INC)strutil.h \
- $(INC)perrors.h \
- $(INC)pexceptions.h \
- $(INC)machdefs.h ntuple.h \
- $(INC)objfio.h \
- $(INC)anydataobj.h \
- $(INC)ppersist.h \
- $(INC)gnumd5.h \
- $(INC)ppfbinstream.h \
- $(INC)rawstream.h \
- $(INC)ppfnametag.h ntupintf.h \
- $(INC)dvlist.h \
- $(INC)mutyv.h
-$(OBJ)proxtuple.o: proxtuple.cc proxtuple.h ntuple.h \
- $(INC)objfio.h \
- $(INC)machdefs.h \
- $(INC)anydataobj.h \
- $(INC)ppersist.h \
- $(INC)pexceptions.h \
- $(INC)gnumd5.h \
- $(INC)ppfbinstream.h \
- $(INC)rawstream.h \
- $(INC)ppfnametag.h ntupintf.h \
- $(INC)dvlist.h \
- $(INC)mutyv.h
-$(OBJ)xntuple.o: xntuple.cc $(INC)ppersist.h \
- $(INC)machdefs.h \
- $(INC)pexceptions.h \
- $(INC)gnumd5.h \
- $(INC)ppfbinstream.h \
- $(INC)rawstream.h \
- $(INC)ppfnametag.h \
- $(INC)perrors.h xntuple.h ntupintf.h \
- $(INC)dvlist.h \
- $(INC)objfio.h \
- $(INC)anydataobj.h \
- $(INC)mutyv.h
+$(OBJ)basedtable.o: basedtable.cc basedtable.h \
+  $(INC)machdefs.h ntupintf.h \
+  $(INC)dvlist.h \
+  $(INC)objfio.h \
+  $(INC)anydataobj.h \
+  $(INC)ppersist.h \
+  $(INC)pexceptions.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h \
+  $(INC)mutyv.h \
+  $(INC)segdatablock.h \
+  $(INC)sopnamsp.h
+$(OBJ)datatable.o: datatable.cc datatable.h basedtable.h \
+  $(INC)machdefs.h ntupintf.h \
+  $(INC)dvlist.h \
+  $(INC)objfio.h \
+  $(INC)anydataobj.h \
+  $(INC)ppersist.h \
+  $(INC)pexceptions.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h \
+  $(INC)mutyv.h \
+  $(INC)segdatablock.h \
+  $(INC)sopnamsp.h \
+  $(INC)strutil.h \
+  $(INC)fiosegdb.h \
+  $(INC)ppftpointerio.h
+$(OBJ)hisprof.o: hisprof.cc $(INC)sopnamsp.h \
+  $(INC)machdefs.h hisprof.h \
+  $(INC)peida.h \
+  $(INC)utils.h \
+  $(INC)perrors.h \
+  $(INC)pexceptions.h \
+  $(INC)fmath.h \
+  $(INC)tvector.h \
+  $(INC)tmatrix.h \
+  $(INC)tarray.h \
+  $(INC)basarr.h \
+  $(INC)anydataobj.h \
+  $(INC)mutyv.h \
+  $(INC)dvlist.h \
+  $(INC)objfio.h \
+  $(INC)ppersist.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h \
+  $(INC)ndatablock.h \
+  $(INC)utilarr.h histos.h
+$(OBJ)histerr.o: histerr.cc $(INC)sopnamsp.h \
+  $(INC)machdefs.h histinit.h \
+  $(INC)ntoolsinit.h \
+  $(INC)tarrinit.h \
+  $(INC)sophyainit.h histerr.h \
+  $(INC)objfio.h \
+  $(INC)anydataobj.h \
+  $(INC)ppersist.h \
+  $(INC)pexceptions.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h histos.h \
+  $(INC)peida.h \
+  $(INC)utils.h \
+  $(INC)perrors.h \
+  $(INC)fmath.h \
+  $(INC)tvector.h \
+  $(INC)tmatrix.h \
+  $(INC)tarray.h \
+  $(INC)basarr.h \
+  $(INC)mutyv.h \
+  $(INC)dvlist.h \
+  $(INC)ndatablock.h \
+  $(INC)utilarr.h
+$(OBJ)histinit.o: histinit.cc $(INC)sopnamsp.h \
+  $(INC)machdefs.h histinit.h \
+  $(INC)ntoolsinit.h \
+  $(INC)tarrinit.h \
+  $(INC)sophyainit.h histos.h \
+  $(INC)objfio.h \
+  $(INC)anydataobj.h \
+  $(INC)ppersist.h \
+  $(INC)pexceptions.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h \
+  $(INC)peida.h \
+  $(INC)utils.h \
+  $(INC)perrors.h \
+  $(INC)fmath.h \
+  $(INC)tvector.h \
+  $(INC)tmatrix.h \
+  $(INC)tarray.h \
+  $(INC)basarr.h \
+  $(INC)mutyv.h \
+  $(INC)dvlist.h \
+  $(INC)ndatablock.h \
+  $(INC)utilarr.h histos2.h hisprof.h histerr.h \
+  ntuple.h ntupintf.h xntuple.h datatable.h basedtable.h \
+  $(INC)segdatablock.h
+$(OBJ)histos.o: histos.cc $(INC)sopnamsp.h \
+  $(INC)machdefs.h histos.h \
+  $(INC)objfio.h \
+  $(INC)anydataobj.h \
+  $(INC)ppersist.h \
+  $(INC)pexceptions.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h \
+  $(INC)peida.h \
+  $(INC)utils.h \
+  $(INC)perrors.h \
+  $(INC)fmath.h \
+  $(INC)tvector.h \
+  $(INC)tmatrix.h \
+  $(INC)tarray.h \
+  $(INC)basarr.h \
+  $(INC)mutyv.h \
+  $(INC)dvlist.h \
+  $(INC)ndatablock.h \
+  $(INC)utilarr.h \
+  $(INC)poly.h \
+  $(INC)strutil.h
+$(OBJ)histos2.o: histos2.cc $(INC)sopnamsp.h \
+  $(INC)machdefs.h histos2.h \
+  $(INC)peida.h \
+  $(INC)utils.h \
+  $(INC)perrors.h \
+  $(INC)pexceptions.h \
+  $(INC)fmath.h histos.h \
+  $(INC)objfio.h \
+  $(INC)anydataobj.h \
+  $(INC)ppersist.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h \
+  $(INC)tvector.h \
+  $(INC)tmatrix.h \
+  $(INC)tarray.h \
+  $(INC)basarr.h \
+  $(INC)mutyv.h \
+  $(INC)dvlist.h \
+  $(INC)ndatablock.h \
+  $(INC)utilarr.h
+$(OBJ)ntupintf.o: ntupintf.cc $(INC)sopnamsp.h \
+  ntupintf.h $(INC)machdefs.h \
+  $(INC)pexceptions.h
+$(OBJ)ntuple.o: ntuple.cc $(INC)sopnamsp.h \
+  $(INC)strutil.h \
+  $(INC)perrors.h \
+  $(INC)pexceptions.h \
+  $(INC)machdefs.h ntuple.h \
+  $(INC)objfio.h \
+  $(INC)anydataobj.h \
+  $(INC)ppersist.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h ntupintf.h \
+  $(INC)dvlist.h \
+  $(INC)mutyv.h
+$(OBJ)proxtuple.o: proxtuple.cc $(INC)sopnamsp.h \
+  proxtuple.h ntuple.h $(INC)objfio.h \
+  $(INC)machdefs.h \
+  $(INC)anydataobj.h \
+  $(INC)ppersist.h \
+  $(INC)pexceptions.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h ntupintf.h \
+  $(INC)dvlist.h \
+  $(INC)mutyv.h
+$(OBJ)xntuple.o: xntuple.cc $(INC)sopnamsp.h \
+  $(INC)ppersist.h \
+  $(INC)machdefs.h \
+  $(INC)pexceptions.h \
+  $(INC)gnumd5.h \
+  $(INC)ppfbinstream.h \
+  $(INC)rawstream.h \
+  $(INC)ppfnametag.h \
+  $(INC)perrors.h xntuple.h ntupintf.h \
+  $(INC)dvlist.h \
+  $(INC)objfio.h \
+  $(INC)anydataobj.h \
+  $(INC)mutyv.h
Index: trunk/SophyaLib/HiStats/basedtable.cc
===================================================================
--- trunk/SophyaLib/HiStats/basedtable.cc	(revision 2688)
+++ trunk/SophyaLib/HiStats/basedtable.cc	(revision 2688)
@@ -0,0 +1,572 @@
+#include "basedtable.h"
+#include <ctype.h>
+#include "sopnamsp.h"
+#include "pexceptions.h"
+
+/*!
+   \class SOPHYA::BaseDataTable
+   \ingroup HiStats
+   Base class for data tables. Each line represent a record
+   and the column contains a given data type.
+*/
+
+string BaseDataTable::ColTypeToString(FieldType ft, bool fgl)
+{
+  string rs;
+  switch (ft) {
+  case IntegerField :
+    if (fgl) rs = "Integer";
+    else rs = "I";
+    break;
+  case LongField :
+    if (fgl) rs = "Long Integer";
+    else rs = "L";
+    break;
+  case FloatField :
+    if (fgl) rs = "Float";
+    else rs = "F";
+    break;
+  case DoubleField :
+    if (fgl) rs = "Double";
+    else rs = "D";
+    break;
+  case ComplexField :
+    if (fgl) rs = "Complex";
+    else rs = "Zx4";    
+    break;
+  case DoubleComplexField :
+    if (fgl) rs = "DoubleComplex";
+    else rs = "Zx8";
+    break;    
+  case StringField :
+    if (fgl) rs = "String";
+    else rs = "S";
+    break;
+  case DateField :
+    if (fgl) rs = "Date";
+    else rs = "Date";
+    break;
+  default:
+    rs = "??";
+    break;
+  }
+  return rs;
+}
+
+/* Constructeur */
+BaseDataTable::BaseDataTable(sa_size_t segsz)
+{
+  mNEnt = 0;
+  mSegSz = (segsz > 0) ? segsz : 16;
+  mNSeg = 0;
+  mVarD = NULL;
+  mVarMTV = NULL;
+  mInfo = NULL;
+}
+
+BaseDataTable::~BaseDataTable()
+{
+  if (mVarD) delete[] mVarD;
+  if (mVarMTV) delete[] mVarMTV;
+  if (mInfo) delete mInfo;
+}
+
+sa_size_t BaseDataTable::CopyStructure(BaseDataTable const & a)
+{
+  if (NVar() > 0) 
+    throw ParmError("BaseDataTable::CopyStructure() Table already has columns");
+  if (a.NVar() == 0) {
+    cout << "BaseDataTable::CopyStructure(a)/Warning Table a is not initialized" << endl;
+    return 0;
+  }
+  for (size_t kk=0; kk<a.mNames.size(); kk++) 
+    AddColumn(a.mNames[kk].type, a.mNames[kk].nom);
+  return NVar();
+}
+
+//! return true is same structure
+bool BaseDataTable::CompareStructure(BaseDataTable const & a)
+{
+  if (NVar() != a.NVar())  return false;
+  for (size_t kk=0; kk<mNames.size(); kk++) 
+    if ( (mNames[kk].type != a.mNames[kk].type) || 
+	 (mNames[kk].nom != a.mNames[kk].nom) ) return false;
+  return true;
+}
+
+bool BaseDataTable::CheckColName(string const & cnom)
+{
+  size_t l,k;
+  l = cnom.length();
+  if (l < 1)  
+    throw ParmError("BaseDataTable::CheckColName() zero length column name");
+  if (!isalpha(cnom[0]))  
+    throw ParmError("BaseDataTable::CheckColName() first character not alphabetical");
+  for(k=1; k<l; k++) 
+    if ((!isalnum(cnom[k])) && (cnom[k] != '_'))  
+      throw ParmError("BaseDataTable::CheckColName() Non alphanumeric char in name");
+  for(k=0; k<mNames.size(); k++)
+    if (cnom == mNames[k].nom) 
+      throw ParmError("BaseDataTable::CheckColName() already existing name");
+  return true;
+}
+
+// 
+// A quel index correspond mon nom ? 
+// 
+sa_size_t BaseDataTable::IndexNom(char const* nom) const 
+{
+  for(sa_size_t k=0; k<NVar(); k++)
+    if ( mNames[k].nom == nom )  return k;
+  throw NotFoundExc("BaseDataTable::IndexNom() : column name not found ");
+}
+
+string BaseDataTable::NomIndex(sa_size_t k) const 
+{
+  if ((k < 0) || (k >= NVar())) 
+    throw RangeCheckError("BaseDataTable::NomIndex() out of range column index k");
+  return mNames[k].nom ; 
+}
+
+
+sa_size_t BaseDataTable::AddLine(const r_8* data)
+{
+  if (NVar() == 0) 
+    throw ParmError("BaseDataTable::AddLine(const r_8*) Table has no column !");
+  if (NEntry() == SegmentSize()*NbSegments())  Extend();
+  sa_size_t n = NEntry();
+  sa_size_t bid = n/mSegSz;
+  sa_size_t off = n%mSegSz;
+  for(sa_size_t k=0; k<mIColsP.size(); k++) 
+    mIColsP[k]->GetSegment(bid)[off] = (int_4)data[mIColIdx[k]];
+  for(sa_size_t k=0; k<mLColsP.size(); k++) 
+    mLColsP[k]->GetSegment(bid)[off] = (int_8)data[mLColIdx[k]];
+  for(sa_size_t k=0; k<mFColsP.size(); k++) 
+    mFColsP[k]->GetSegment(bid)[off] = (r_4)data[mFColIdx[k]];
+  for(sa_size_t k=0; k<mDColsP.size(); k++) 
+    mDColsP[k]->GetSegment(bid)[off] = data[mDColIdx[k]];
+  for(sa_size_t k=0; k<mSColsP.size(); k++) 
+    mSColsP[k]->GetSegment(bid)[off] = (string)MuTyV(data[mSColIdx[k]]);
+
+  mNEnt++;
+  return mNEnt;
+}
+
+sa_size_t BaseDataTable::AddLine(const MuTyV* data)
+{
+  if (NVar() == 0) 
+    throw ParmError("BaseDataTable::AddLine(const MuTyV*) Table has no column !");
+  if (NEntry() == SegmentSize()*NbSegments())  Extend();
+  sa_size_t n = NEntry();
+  sa_size_t bid = n/mSegSz;
+  sa_size_t off = n%mSegSz;
+  for(sa_size_t k=0; k<mIColsP.size(); k++) 
+    mIColsP[k]->GetSegment(bid)[off] = (int_4)data[mIColIdx[k]];
+  for(sa_size_t k=0; k<mLColsP.size(); k++) 
+    mLColsP[k]->GetSegment(bid)[off] = (int_8)data[mLColIdx[k]];
+  for(sa_size_t k=0; k<mSColsP.size(); k++) 
+    mSColsP[k]->GetSegment(bid)[off] = (string)data[mSColIdx[k]];
+  for(sa_size_t k=0; k<mFColsP.size(); k++) 
+    mFColsP[k]->GetSegment(bid)[off] = (r_4)data[mFColIdx[k]];
+  for(sa_size_t k=0; k<mDColsP.size(); k++) 
+    mDColsP[k]->GetSegment(bid)[off] = (r_8)data[mDColIdx[k]];
+
+  mNEnt++;
+  return mNEnt;
+}
+
+sa_size_t BaseDataTable::Extend()
+{
+  for(sa_size_t k=0; k<mIColsP.size(); k++) 
+    mIColsP[k]->Extend();
+  for(sa_size_t k=0; k<mLColsP.size(); k++) 
+    mLColsP[k]->Extend();
+  for(sa_size_t k=0; k<mFColsP.size(); k++) 
+    mFColsP[k]->Extend();
+  for(sa_size_t k=0; k<mDColsP.size(); k++)     
+    mDColsP[k]->Extend();
+  for(sa_size_t k=0; k<mSColsP.size(); k++) 
+    mSColsP[k]->Extend();
+  mNSeg++;
+  return mNSeg;
+}
+
+
+MuTyV* BaseDataTable::GetLine(sa_size_t n) const 
+{
+  if ((n < 0) || (n >= NEntry())) 
+    throw RangeCheckError("BaseDataTable::GetLine() out of range line index n");
+  if (mVarMTV == NULL) mVarMTV = new MuTyV[NVar()];
+
+  sa_size_t bid = n/mSegSz;
+  sa_size_t off = n%mSegSz;
+  for(sa_size_t k=0; k<mIColsP.size(); k++) 
+    mVarMTV[mIColIdx[k]] = mIColsP[k]->GetSegment(bid)[off];
+  for(sa_size_t k=0; k<mLColsP.size(); k++) 
+    mVarMTV[mLColIdx[k]] = mLColsP[k]->GetSegment(bid)[off];
+  for(sa_size_t k=0; k<mFColsP.size(); k++) 
+    mVarMTV[mFColIdx[k]] = mFColsP[k]->GetSegment(bid)[off];
+  for(sa_size_t k=0; k<mDColsP.size(); k++) 
+    mVarMTV[mDColIdx[k]] = mDColsP[k]->GetSegment(bid)[off];
+  for(sa_size_t k=0; k<mSColsP.size(); k++) 
+    mVarMTV[mSColIdx[k]] = atof(mSColsP[k]->GetSegment(bid)[off].c_str());
+
+  return mVarMTV;
+}
+
+void BaseDataTable::CopyMerge(BaseDataTable const& a, bool cp)
+{
+  if (cp && (NEntry() > 0) )
+    throw ParmError("BaseDataTable::CopyMerge(a) Table has entries already");
+  if (a.NVar() == 0)  throw ParmError("BaseDataTable::CopyMerge(a) Table a has no column");
+  if (NVar() == 0) CopyStructure(a);
+  else if (!CompareStructure(a)) 
+    throw SzMismatchError("BaseDataTable::CopyMerge(a) (this,a) have different table structure");
+  if (a.NEntry() == 0) {
+    cout << " BaseDataTable::CopyMerge(a)/Warning : table a has zero (0) entry ! " << endl;
+    return;
+  }
+  for(sa_size_t kk=0; kk<a.NEntry(); kk++) 
+    AddLine(a.GetLine(kk));
+}
+
+
+//! Returns the associated DVList object
+DVList&  BaseDataTable::Info() const
+{
+  if (mInfo == NULL)  mInfo = new DVList;
+  return(*mInfo);
+}
+
+void BaseDataTable::Print(int num, int nmax) const 
+{
+  // A faire
+  return;
+}
+
+
+//! Prints table definition and number of entries 
+void   BaseDataTable::Show(ostream& os) const 
+{
+  os << "BaseDataTable: NVar= " << NVar() << " NEnt= " << NEntry() 
+     << " ( SegSize= " << SegmentSize() << "  NbSegments= " 
+     << NbSegments() << " )" << endl;
+  os << "--------------------------------------------------------------------" << endl;
+  os << setw(3) << "i" << ":" << setw(20) << " Name" << " ("  
+     << setw(4) << "Type" << ") | " 
+     << setw(15) << " Min " << " | " << setw(15) << " Max " << endl;
+  os << "--------------------------------------------------------------------" << endl;
+  r_8 min, max ;
+  for(sa_size_t i = 0 ; i < NVar() ; i++) {
+    GetMinMax(i, min, max) ;
+    string nom;
+    if (mNames[i].nom.length() > 20) 
+      nom = mNames[i].nom.substr(20);
+    else nom = mNames[i].nom;
+    os << setw(3) << i << ":" << setw(20) << nom << " (" 
+       << setw(4) << ColTypeToString(mNames[i].type) << ") | " 
+       << setw(15) << min << " | " << setw(15) << max << endl;
+  }
+  os << "--------------------------------------------------------------------" << endl;
+  return;
+}
+
+//! NOT YET IMPLEMENTED ! - Fills table from an ascii file
+int    BaseDataTable::FillFromASCIIFile(string const& fn)
+//	Remplit le ntuple a partir d'un fichier ASCII.
+//	Renvoie le nombre de lignes ajoutees.
+{
+// a faire
+return(0);
+}
+
+
+
+// 
+// ------------------------------------
+// ------- Interface NTuple -----------
+// ------------------------------------
+// 
+sa_size_t BaseDataTable::NbLines() const
+{
+  return(NEntry());
+}
+
+sa_size_t BaseDataTable::NbColumns() const
+{
+  return(NVar());
+}
+
+r_8* BaseDataTable::GetLineD(sa_size_t n) const 
+{
+  if ((n < 0) || (n >= NEntry())) 
+    throw RangeCheckError("BaseDataTable::GetLineD() out of range line index n");
+  if (mVarD == NULL) mVarD = new r_8[NVar()];
+
+  sa_size_t bid = n/mSegSz;
+  sa_size_t off = n%mSegSz;
+  for(sa_size_t k=0; k<mIColsP.size(); k++) 
+    mVarD[mIColIdx[k]] = mIColsP[k]->GetSegment(bid)[off];
+  for(sa_size_t k=0; k<mLColsP.size(); k++) 
+    mVarD[mLColIdx[k]] = mLColsP[k]->GetSegment(bid)[off];
+  for(sa_size_t k=0; k<mFColsP.size(); k++) 
+    mVarD[mFColIdx[k]] = mFColsP[k]->GetSegment(bid)[off];
+  for(sa_size_t k=0; k<mDColsP.size(); k++) 
+    mVarD[mDColIdx[k]] = mDColsP[k]->GetSegment(bid)[off];
+  for(sa_size_t k=0; k<mSColsP.size(); k++) 
+    mVarD[mSColIdx[k]] = atof(mSColsP[k]->GetSegment(bid)[off].c_str());
+
+  return mVarD;
+}
+
+#define BADVAL -1.e39
+
+r_8  BaseDataTable::GetCell(sa_size_t n, sa_size_t k) const 
+{
+  if ((n < 0) || (n >= NEntry())) 
+    throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
+  if ((k < 0) || (n >= NVar())) 
+    throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
+  double rv = BADVAL;
+  sa_size_t sk = mNames[k].ser;
+  sa_size_t bid = n/mSegSz;
+  sa_size_t off = n%mSegSz;
+  switch (mNames[k].type) {
+  case IntegerField :
+    rv = mIColsP[sk]->GetSegment(bid)[off];
+    break;
+  case LongField :
+    rv = mLColsP[sk]->GetSegment(bid)[off];
+    break;
+  case FloatField :
+    rv = mFColsP[sk]->GetSegment(bid)[off];
+    break;
+  case DoubleField :
+    rv = mDColsP[sk]->GetSegment(bid)[off];
+    break;
+  case StringField :
+    rv = atof(mSColsP[sk]->GetSegment(bid)[off].c_str());
+    break;
+  default:
+    rv = BADVAL;
+    break;
+  }
+  return rv ; 
+}
+
+
+r_8  BaseDataTable::GetCell(sa_size_t n, string const& nom) const 
+{
+  return GetCell(n, IndexNom(nom));
+}
+
+string   BaseDataTable::GetCelltoString(sa_size_t n, sa_size_t k) const
+{
+  if ((n < 0) || (n >= NEntry())) 
+    throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
+  if ((k < 0) || (n >= NVar())) 
+    throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
+  MuTyV rv;;
+  sa_size_t sk = mNames[k].ser;
+  sa_size_t bid = n/mSegSz;
+  sa_size_t off = n%mSegSz;
+  switch (mNames[k].type) {
+  case IntegerField :
+    rv = mIColsP[sk]->GetSegment(bid)[off];
+    break;
+  case LongField :
+    rv = mLColsP[sk]->GetSegment(bid)[off];
+    break;
+  case FloatField :
+    rv = mFColsP[sk]->GetSegment(bid)[off];
+    break;
+  case DoubleField :
+    rv = mDColsP[sk]->GetSegment(bid)[off];
+    break;
+  case StringField :
+    rv = atof(mSColsP[sk]->GetSegment(bid)[off].c_str());
+    break;
+  default:
+    rv = " ";
+    break;
+  }
+  return (string)rv ; 
+}
+
+void BaseDataTable::GetMinMax(sa_size_t k, double& min, double& max)  const
+{
+  min = 9E39 ; max = -9E39 ; 
+  if ((k < 0) || (k >= NVar())) 
+    throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
+  if (mMinMaxNEnt.size() < NVar()) {
+    mMin.clear();
+    mMax.clear();
+    mMinMaxNEnt.clear();
+    for(size_t kk=0; kk<NVar(); kk++) {
+      mMin.push_back(0.);
+      mMax.push_back(0.);
+      mMinMaxNEnt.push_back(0);
+    }
+  }
+  if (mMinMaxNEnt[k] == mNEnt) {
+    min = mMin[k];
+    max = mMax[k];
+    return;
+  }
+  sa_size_t sk = mNames[k].ser;
+
+  sa_size_t cnt = 0;
+  switch (mNames[k].type) {
+  case IntegerField :
+    for(size_t is=0; is<mIColsP[sk]->NbSegments(); is++) {
+      int_4* sp = mIColsP[sk]->GetSegment(is);
+      for(size_t n=0; n<mIColsP[sk]->SegmentSize(); n++) {
+	if (cnt >= NEntry())  break;
+	if (sp[n] > max) max = sp[n];
+	if (sp[n] < min) min = sp[n];
+	cnt++;
+      }
+    }
+    
+    break;
+  case LongField :
+    for(size_t is=0; is<mLColsP[sk]->NbSegments(); is++) {
+      int_8* sp = mLColsP[sk]->GetSegment(is);
+      for(size_t n=0; n<mLColsP[sk]->SegmentSize(); n++) {
+	if (cnt >= NEntry())  break;
+	if (sp[n] > max) max = sp[n];
+	if (sp[n] < min) min = sp[n];
+	cnt++;
+      }
+    }
+    break;
+  case FloatField :
+    for(size_t is=0; is<mFColsP[sk]->NbSegments(); is++) {
+      r_4* sp = mFColsP[sk]->GetSegment(is);
+      for(size_t n=0; n<mFColsP[sk]->SegmentSize(); n++) {
+	if (cnt >= NEntry())  break;
+	if (sp[n] > max) max = sp[n];
+	if (sp[n] < min) min = sp[n];
+	cnt++;
+      }
+    }
+    break;
+  case DoubleField :
+    for(size_t is=0; is<mDColsP[sk]->NbSegments(); is++) {
+      r_8* sp = mDColsP[sk]->GetSegment(is);
+      for(size_t n=0; n<mDColsP[sk]->SegmentSize(); n++) {
+	if (cnt >= NEntry())  break;
+	if (sp[n] > max) max = sp[n];
+	if (sp[n] < min) min = sp[n];
+	cnt++;
+      }
+    }
+    break;
+  case StringField :
+    return;
+    break;
+  default:
+    return;
+    break;
+  }  
+
+  mMinMaxNEnt[k] = cnt; 
+  mMin[k] = min;
+  mMax[k] = max;
+  return ; 
+}
+
+
+void BaseDataTable::GetMinMax(string const & nom, double& min, double& max)   const
+{
+  GetMinMax(IndexNom(nom), min, max) ; 
+}
+
+
+sa_size_t BaseDataTable::ColumnIndex(string const& nom) const 
+{
+  return IndexNom(nom) ; 
+}
+
+
+string BaseDataTable::ColumnName(sa_size_t k) const 
+{
+  return NomIndex(k) ; 
+}
+
+
+string BaseDataTable::VarList_C(const char* nomx) const 
+{
+  string rets="";
+  sa_size_t i;
+  for(i=0; i<NVar(); i++) {
+    if ( (i%5 == 0) && (i > 0) )  rets += ";";  
+    if (i%5 == 0)   rets += "\ndouble "; 
+    else rets += ",";
+    rets += mNames[i].nom;
+  }
+  rets += "; \n";
+  if (nomx) { 
+    char buff[256];
+    for(i=0; i<NVar(); i++) {
+      rets += mNames[i].nom;
+      rets += '=';
+      
+      sprintf(buff,"%s[%ld]; ",  nomx, i);
+      rets += buff;
+      if ( (i%3 == 0) && (i > 0) )  rets += "\n"; 
+    }
+  }
+  return(rets);
+}
+
+
+string BaseDataTable::LineHeaderToString() const 
+{
+  char buff[32];
+  string rets=" Num    ";
+  for(int i=0; i<NVar(); i++) {
+    sprintf(buff, "%8s ", NomIndex(i).c_str() );
+    rets += buff;
+  }
+  rets += '\n';
+  return(rets);  
+}
+
+
+string BaseDataTable::LineToString(sa_size_t n) const 
+{
+  if ((n < 0) || (n >= NEntry())) 
+    throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
+  string rs;
+  MuTyV rv;;
+  sa_size_t bid = n/mSegSz;
+  sa_size_t off = n%mSegSz;
+  for(sa_size_t k=0; k<NVar(); k++) {
+    sa_size_t sk = mNames[k].ser;
+    switch (mNames[k].type) {
+    case IntegerField :
+      rv = mIColsP[sk]->GetSegment(bid)[off];
+      break;
+    case LongField :
+      rv = mLColsP[sk]->GetSegment(bid)[off];
+      break;
+    case FloatField :
+      rv = mFColsP[sk]->GetSegment(bid)[off];
+      break;
+    case DoubleField :
+      rv = mDColsP[sk]->GetSegment(bid)[off];
+      break;
+    case StringField :
+      rv = atof(mSColsP[sk]->GetSegment(bid)[off].c_str());
+    break;
+    default:
+      rv = " ";
+      break;
+    }
+    rs += " ";
+    rs += (string)rv;
+  }
+  return rs;
+}
+
Index: trunk/SophyaLib/HiStats/basedtable.h
===================================================================
--- trunk/SophyaLib/HiStats/basedtable.h	(revision 2688)
+++ trunk/SophyaLib/HiStats/basedtable.h	(revision 2688)
@@ -0,0 +1,158 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Class BaseDataTable 
+//   R. Ansari -  Avril 2005
+//   (C)  LAL-IN2P3/CNRS    CEA-DAPNIA  
+
+#ifndef BASEDTABLE_H_SEEN
+#define BASEDTABLE_H_SEEN
+
+#include "machdefs.h"
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "ntupintf.h"
+#include "dvlist.h"
+#include "segdatablock.h"
+
+namespace SOPHYA {
+class BaseDataTable : public AnyDataObj , public NTupleInterface {
+public:
+  // ===> DO NOT CHANGE EXISTING enum type VALUES !!! 
+  enum FieldType {IntegerField=1, LongField=2, 
+		  FloatField=3, DoubleField=4,
+		  ComplexField=5, DoubleComplexField=6,
+		  StringField=7, DateField=8};
+  // <=====================================================> 
+
+  static string     ColTypeToString(FieldType ft, bool fgl=false);
+
+  // constructeur , destructeur 
+  BaseDataTable(sa_size_t segsz=512);
+  virtual           ~BaseDataTable();
+  
+  inline sa_size_t  AddIntegerColumn(const char * cnom) 
+  { return AddColumn(IntegerField, cnom); }
+  inline sa_size_t  AddIntegerColumn(string const & cnom) 
+  { return AddColumn(IntegerField, cnom); }
+  inline sa_size_t  AddFloatColumn(const char * cnom) 
+  { return AddColumn(FloatField, cnom); }
+  inline sa_size_t  AddFloatColumn(string const & cnom) 
+  { return AddColumn(FloatField, cnom); }
+  inline sa_size_t  AddDoubleColumn(const char * cnom) 
+  { return AddColumn(DoubleField, cnom); }
+  inline sa_size_t  AddDoubleColumn(string const & cnom) 
+  { return AddColumn(DoubleField, cnom); }
+  
+  inline sa_size_t  AddColumn(FieldType ft, const char * cnom)
+  { string nom = cnom;  return AddColumn(ft, nom); }
+  
+  //! Pure virtual method for adding a new column to the Data Table
+  virtual sa_size_t AddColumn(FieldType ft, string const & cnom) = 0;
+  //! Duplicate the data table structure from the source Table
+  virtual sa_size_t CopyStructure(BaseDataTable const & a);
+  //! Checks if the two table have the same column structure
+  virtual bool      CompareStructure(BaseDataTable const & a);
+
+  // Verifie la validite du nom de colonne:envoie une exception
+  // si nom en double ou non valide
+  virtual bool      CheckColName(string const & cnom);
+
+  // Acces to various counts and parameters
+  inline sa_size_t  NEntry() const { return mNEnt ; }
+  inline sa_size_t  NVar() const   { return mNames.size() ; } 
+  inline sa_size_t  NVars() const   { return mNames.size() ; } 
+  inline sa_size_t  SegmentSize() const   { return mSegSz ; } 
+  inline sa_size_t  NbSegments() const   { return mNSeg ; } 
+
+  // Filling data structures (adding lines)
+  virtual sa_size_t AddLine(const r_8* data);
+  virtual sa_size_t AddLine(const MuTyV * data);
+  
+  inline sa_size_t  Fill(const r_8* data)
+  { return AddLine(data); }
+  inline sa_size_t  Fill(const MuTyV * data);
+     
+  virtual sa_size_t Extend();
+
+  // Getting a given line (record) information 
+  virtual MuTyV *   GetLine(sa_size_t n) const ;
+  
+  sa_size_t         IndexNom(char const* nom) const ; 
+  inline sa_size_t  IndexNom(string const & nom) const 
+  { return IndexNom(nom.c_str()); }
+  string            NomIndex(sa_size_t k) const ; 
+  
+  //! Copy or merges  the data from \b a into the data table (cp=true -> copy)
+  virtual void      CopyMerge(BaseDataTable const& a, bool cp=false) ; 
+  //! Equal (copy) operator
+  inline BaseDataTable&  operator = (BaseDataTable const& a) 
+  { CopyMerge(a, true) ; return *this ; } 
+   
+  void              Print(int num, int nmax=1) const ;
+  
+  void              Show(ostream& os) const ; 
+  inline void       Show() const { Show(cout) ; } 
+  
+  DVList&           Info() const ; 
+  
+  // Remplissage depuis fichier ASCII 
+  int		    FillFromASCIIFile(string const& fn);
+  
+  // Declaration de l interface NTuple
+  virtual sa_size_t NbLines() const ;
+  virtual sa_size_t NbColumns() const ;
+  virtual r_8 *     GetLineD(sa_size_t n) const ;
+  virtual r_8	    GetCell(sa_size_t n, sa_size_t k) const ;
+  virtual r_8	    GetCell(sa_size_t n, string const & nom) const ;
+  virtual string    GetCelltoString(sa_size_t n, sa_size_t k) const ;
+  virtual void      GetMinMax(sa_size_t k, double& min, double& max)   const ; 
+  virtual void      GetMinMax(string const & nom, double& min, double& max)   const ; 
+  virtual sa_size_t ColumnIndex(string const & nom)  const ;
+  virtual string    ColumnName(sa_size_t k) const;
+  virtual string    VarList_C(const char* nomx=NULL) const ;
+  virtual string    LineHeaderToString() const;
+  virtual string    LineToString(sa_size_t n) const;  
+  
+protected:
+  uint_8   mNEnt ;   // nb total d'entrees 
+  uint_8   mSegSz ;  // taille bloc/segment 
+  uint_8   mNSeg;    // Nb total de segments
+  mutable r_8 *  mVarD;    // Pour retourner une ligne de la table
+  mutable MuTyV *  mVarMTV;    // Pour retourner une ligne de la table en MuTyV
+  
+  typedef struct { 
+    string nom; 
+    FieldType type;
+    sa_size_t ser;
+  } colst;
+  std::vector<colst> mNames;
+
+  mutable DVList* mInfo;        // Infos (variables) attachees au NTuple
+
+  // Pour calculer et garder le min/max   
+  mutable std::vector<r_8> mMin;
+  mutable std::vector<r_8> mMax;
+  mutable std::vector<uint_8> mMinMaxNEnt;
+  
+  // Les pointeurs des SegDataBlock ...  
+  std::vector< SegDBInterface<int_4> * > mIColsP; 
+  std::vector< sa_size_t > mIColIdx;
+  std::vector< SegDBInterface<int_8> * > mLColsP; 
+  std::vector< sa_size_t > mLColIdx;
+  std::vector< SegDBInterface<r_4> * > mFColsP;
+  std::vector< sa_size_t > mFColIdx; 
+  std::vector< SegDBInterface<r_8> * > mDColsP; 
+  std::vector< sa_size_t > mDColIdx;
+  std::vector< SegDBInterface<string> * > mSColsP; 
+  std::vector< sa_size_t > mSColIdx;
+  
+}; 
+/*! Prints table information (Column name and type, min/max) on stream \b s (bd.Show(s)) */
+inline ostream& operator << (ostream& s, BaseDataTable const & bd)
+  {  bd.Show(s);  return(s);  }
+  
+} // namespace SOPHYA
+
+#endif
Index: trunk/SophyaLib/HiStats/datatable.cc
===================================================================
--- trunk/SophyaLib/HiStats/datatable.cc	(revision 2688)
+++ trunk/SophyaLib/HiStats/datatable.cc	(revision 2688)
@@ -0,0 +1,353 @@
+#include "datatable.h"
+#include "sopnamsp.h"
+#include "strutil.h"
+#include "pexceptions.h"
+#include "fiosegdb.h"
+
+
+/*!
+   \class SOPHYA::DataTable
+   \ingroup HiStats
+   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 ...)
+   \sa SOPHYA::MuTyV
+   \sa SOPHYA::BaseDataTable
+   \sa SOPHYA::ObjFileIO<DataTable>
+
+   \code
+   #include "datatable.h"
+   // ...
+   DataTable dt(64);
+   dt.AddFloatColumn("X0_f");
+   dt.AddFloatColumn("X1_f");
+   dt.AddDoubleColumn("X0X0pX1X1_d");
+   double 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 ;
+   // Saving object into a PPF file
+   POutPersist po("dtable.ppf");
+   po << dt ;
+   \endcode
+*/
+
+
+//! Default constructor - optional specification of block (or segment) size
+DataTable::DataTable(sa_size_t segsz)
+  : BaseDataTable(segsz)
+{
+}
+
+//! copy constructor - shares the data
+DataTable::DataTable(DataTable const & a, bool share)
+  : BaseDataTable(a.SegmentSize())
+{
+  if (share) Share(a);
+  else Clone(a);
+  mNEnt = a.mNEnt;
+  mNSeg = a.mNSeg;
+  if (a.mInfo)  mInfo = new DVList(*(a.mInfo));
+}
+
+void DataTable::Share(DataTable const & a)
+{
+  // On copie la structure de table 
+  CopyStructure(a);
+  // Et on partage les donnees des colonnes 
+  for (size_t kk=0; kk<mNames.size(); kk++) {
+    sa_size_t sk = mNames[kk].ser;
+    sa_size_t ska = a.mNames[kk].ser;
+    switch (mNames[kk].type) {
+    case IntegerField :
+      mICols[sk].Share(a.mICols[ska]); 
+    break;
+    case LongField :
+      mLCols[sk].Share(a.mLCols[ska]); 
+      break;
+    case FloatField :
+      mFCols[sk].Share(a.mFCols[ska]); 
+      break;
+    case DoubleField :
+      mDCols[sk].Share(a.mDCols[ska]); 
+      break;
+    case StringField :
+      mSCols[sk].Share(a.mSCols[ska]); 
+      break;
+    default:
+      throw ForbiddenError("DataTable::Share() : unknown column type ");
+    break;
+    }
+  }  
+}
+
+void DataTable::Clone(DataTable const & a)
+{
+  // On copie la structure de table 
+  CopyStructure(a);
+  // Et on partage les donnees des colonnes 
+  for (size_t kk=0; kk<mNames.size(); kk++) {
+    sa_size_t sk = mNames[kk].ser;
+    sa_size_t ska = a.mNames[kk].ser;
+    switch (mNames[kk].type) {
+    case IntegerField :
+      mICols[sk].Clone(a.mICols[ska], true); 
+    break;
+    case LongField :
+      mLCols[sk].Clone(a.mLCols[ska], true); 
+      break;
+    case FloatField :
+      mFCols[sk].Clone(a.mFCols[ska], true); 
+      break;
+    case DoubleField :
+      mDCols[sk].Clone(a.mDCols[ska], true); 
+      break;
+    case StringField :
+      mSCols[sk].Clone(a.mSCols[ska], true); 
+      break;
+    default:
+      throw ForbiddenError("DataTable::Clone() : unknown column type ");
+    break;
+    }
+  }  
+}
+
+void DataTable::Clear()
+{
+  if ( (NVar() == 0) && (NEntry() == 0)) return;
+  mNEnt = 0;
+  mNSeg = 0;
+  if (mVarD) delete[] mVarD;
+  mVarD = NULL;
+  if (mVarMTV) delete[] mVarMTV;
+  mVarMTV = NULL;
+  mNames.clear();
+  if (mInfo) delete mInfo;
+  mInfo = NULL;
+  mMin.clear();
+  mMax.clear();
+  mMinMaxNEnt.clear();
+  mIColsP.clear();
+  mLColsP.clear();
+  mFColsP.clear();
+  mDColsP.clear();
+  mSColsP.clear();
+
+  mIColIdx.clear();
+  mLColIdx.clear();
+  mFColIdx.clear();
+  mDColIdx.clear();
+  mSColIdx.clear();
+
+  mICols.clear();
+  mLCols.clear();
+  mFCols.clear();
+  mDCols.clear();
+  mSCols.clear();
+}
+
+
+sa_size_t DataTable::AddColumn(FieldType ft, string const & cnom)
+{
+  if (NEntry() > 0) 
+    throw ParmError("DataTable::AddColumn() Table contains already data ");
+  CheckColName(cnom);
+  sa_size_t ser; 
+  sa_size_t idx = NVar(); 
+  switch (ft) {
+  case IntegerField :
+    ser = mICols.size();
+    mICols.push_back(SegDataBlock<int_4>(mSegSz));
+    mIColIdx.push_back(idx);
+    mIColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mICols.size(); kk++)
+      mIColsP[kk] = &(mICols[kk]);
+    break;
+  case LongField :
+    ser = mLCols.size();
+    mLCols.push_back(SegDataBlock<int_8>(mSegSz));
+    mLColIdx.push_back(idx);
+    mLColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mLCols.size(); kk++)
+      mLColsP[kk] = &(mLCols[kk]);
+    break;
+  case FloatField :
+    ser = mFCols.size();
+    mFCols.push_back(SegDataBlock<r_4>(mSegSz));
+    mFColIdx.push_back(idx);
+    mFColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mFCols.size(); kk++)
+      mFColsP[kk] = &(mFCols[kk]);
+    break;
+  case DoubleField :
+    ser = mDCols.size();
+    mDCols.push_back(SegDataBlock<r_8>(mSegSz));
+    mDColIdx.push_back(idx);
+    mDColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mDCols.size(); kk++)
+      mDColsP[kk] = &(mDCols[kk]);
+    break;
+  case StringField :
+    ser = mDCols.size();
+    mSCols.push_back(SegDataBlock<string>(mSegSz));
+    mSColIdx.push_back(idx);
+    mSColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mSCols.size(); kk++)
+      mSColsP[kk] = &(mSCols[kk]);
+    break;
+  default:
+    throw ParmError("DataTable::AddColumn() unknown field type ");
+    break;
+  }
+  colst col;
+  col.nom = cnom;
+  col.type = ft;
+  col.ser = ser;
+  mNames.push_back(col);
+  return NVar();
+}
+
+/*!
+   \class SOPHYA::ObjFileIO<DataTable>
+   \ingroup HiStats
+   Persistence (serialisation) handler for class DataTable
+*/
+/* --Methode-- */ 
+DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
+void   ObjFileIO<DataTable>::WriteSelf(POutPersist& s)  const
+//	Serialisation en ecriture du DataTable sur stream PPF
+{
+  if (dobj == NULL)   
+    throw NullPtrError("ObjFileIO<DataTable>::WriteSelf() NULL dobj pointer ");
+  //-------  On ecrit 3 uint_4 .... 
+  //  [0]: Numero de version ;
+  //  [1] : bit1 non nul -> has info  
+  //  [2] : reserve
+  uint_4 itab[3];
+  itab[0] = 1;  // Numero de version a 1
+  itab[1] = itab[2] = 0;
+  if (dobj->mInfo)  itab[1] = 1;
+  s.Put(itab, 3);
+
+  //-------- Ecriture de segment size, nb de colonnes, nb de lignes ...  
+  // [0] : SegmentSize()        [1] : NVar()
+  // [2] : NEntry()             [3] : NbSegments()
+  uint_8 ltab[5];
+  ltab[0] = dobj->SegmentSize();
+  ltab[1] = dobj->NVar();
+  ltab[2] = dobj->NEntry();
+  ltab[3] = dobj->NbSegments();
+  ltab[4] = 0;
+  s.Put(ltab, 5);
+
+  //------ Ecriture du nom et type des colonnes
+  for(sa_size_t k=0; k<dobj->NVar(); k++) { 
+    uint_2 typ = dobj->mNames[k].type;
+    s.Put(typ);
+    s.Put(dobj->mNames[k].nom);
+  }
+  //------- Ecriture du DVList Info() associe, si existant
+  if (dobj->mInfo)  s << (*(dobj->mInfo));
+
+  //------- Ecriture des SegDataBlock<T> 
+  for (size_t kk=0; kk<dobj->mNames.size(); kk++) {
+    sa_size_t sk = dobj->mNames[kk].ser;
+    switch (dobj->mNames[kk].type) {
+    case BaseDataTable::IntegerField :
+      s << dobj->mICols[sk]; 
+    break;
+    case BaseDataTable::LongField :
+      s << dobj->mLCols[sk]; 
+      break;
+    case BaseDataTable::FloatField :
+      s << dobj->mFCols[sk]; 
+      break;
+    case BaseDataTable::DoubleField :
+      s << dobj->mDCols[sk]; 
+      break;
+    case BaseDataTable::StringField :
+      s << dobj->mSCols[sk]; 
+      break;
+    default:
+      throw ForbiddenError("ObjFileIO<DataTable>::WriteSelf() : unknown column type ");
+    break;
+    }
+  }    
+  return;
+}
+
+/* --Methode-- */
+DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
+void  ObjFileIO<DataTable>::ReadSelf(PInPersist& s)
+//	Serialisation en lecture du DataTable sur stream PPF
+{
+  // ------- On lit les 3 premiers uint_4
+  //  [0]: Numero de version ;
+  //  [1] : bit1 non nul -> has info  
+  //  [2] : reserve
+  uint_4 itab[3] = {0,0,0};
+  s.Get(itab, 3);
+  bool hadinfo = false;
+  if ((itab[1]&1) == 1)  hadinfo = true;
+
+  // -------- Lecture de segment size, nb de colonnes, nb de lignes ...  
+  // [0] : SegmentSize()        [1] : NVar()
+  // [2] : NEntry()             [3] : NbSegments()
+  uint_8 ltab[5] = {0,0,0,0,0};
+  s.Get(ltab, 5);
+  if (dobj == NULL) dobj = new DataTable(ltab[0]);
+  else { dobj->Clear();  dobj->mSegSz = ltab[0]; }
+  // -------- Lecture nom/type colonnes et allocation des colonnes
+  uint_2 typ; 
+  string cnom;
+  for(uint_8 k=0; k<ltab[1]; k++) { 
+    s.Get(typ);
+    s.Get(cnom);
+    BaseDataTable::FieldType ft = (BaseDataTable::FieldType)typ;
+    dobj->AddColumn(ft, cnom);
+  }
+  // ------- Lecture du DVList Info() associe, si necessaire
+  if (hadinfo) {    // Lecture eventuelle du DVList Info
+    if (dobj->mInfo == NULL)  dobj->mInfo = new DVList;
+    s >> (*(dobj->mInfo));
+  }
+  // ------- Mise a jour des champs Nb d'entrees, nb segments ...
+  dobj->mNEnt = ltab[2];
+  dobj->mNSeg = ltab[3];
+  // ------- Lecture des SegDataBlock<T> 
+  for (size_t kk=0; kk<dobj->mNames.size(); kk++) {
+    sa_size_t sk = dobj->mNames[kk].ser;
+    switch (dobj->mNames[kk].type) {
+    case BaseDataTable::IntegerField :
+      s >> dobj->mICols[sk]; 
+    break;
+    case BaseDataTable::LongField :
+      s >> dobj->mLCols[sk]; 
+      break;
+    case BaseDataTable::FloatField :
+      s >> dobj->mFCols[sk]; 
+      break;
+    case BaseDataTable::DoubleField :
+      s >> dobj->mDCols[sk]; 
+      break;
+    case BaseDataTable::StringField :
+      s >> dobj->mSCols[sk]; 
+      break;
+    default:
+      throw ForbiddenError("ObjFileIO<DataTable>::ReadSelf() : unknown column type ");
+    break;
+    }
+  }    
+return;
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<DataTable>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<DataTable>;
+#endif
Index: trunk/SophyaLib/HiStats/datatable.h
===================================================================
--- trunk/SophyaLib/HiStats/datatable.h	(revision 2688)
+++ trunk/SophyaLib/HiStats/datatable.h	(revision 2688)
@@ -0,0 +1,55 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Class DataTable  (Row-Column data table in memory) 
+//   R. Ansari -  Avril 2005
+//   (C)  LAL-IN2P3/CNRS    CEA-DAPNIA  
+
+#ifndef DATATABLE_H_SEEN
+#define DATATABLE_H_SEEN
+
+#include "basedtable.h"
+#include "objfio.h"
+
+
+namespace SOPHYA {
+
+//  Forward class declaration for Fits handler
+class FITS_DataTable;
+
+class DataTable : public BaseDataTable {
+public:
+  DataTable(sa_size_t segsz=512); 
+  DataTable(DataTable const& a, bool share=true); 
+  
+  virtual sa_size_t AddColumn(FieldType ft, string const & cnom);
+
+  //  Pour la gestion de persistance PPF
+  friend class ObjFileIO<DataTable> ;
+  // pour fichiers FITS
+  friend class FITS_DataTable;
+  
+  //! Reset the table content and structure
+  void Clear();
+protected:
+  void Share(DataTable const & a);
+  void Clone(DataTable const & a);
+
+  // Donnees en memoire
+  std::vector< SegDataBlock<int_4> > mICols; 
+  std::vector< SegDataBlock<int_8> > mLCols; 
+  std::vector< SegDataBlock<r_4> > mFCols;
+  std::vector< SegDataBlock<r_8> > mDCols; 
+  std::vector< SegDataBlock<string> > mSCols;     
+}; 
+  
+/*! Writes the object in the POutPersist stream \b os */
+inline POutPersist& operator << (POutPersist& os, DataTable & obj)
+{ ObjFileIO<DataTable> fio(&obj);  fio.Write(os);  return(os); }
+/*! Reads the object from the PInPersist stream \b is */
+inline PInPersist& operator >> (PInPersist& is, DataTable & obj)
+{ ObjFileIO<DataTable> fio(&obj); is.SkipToNextObject(); fio.Read(is); return(is); }
+// Classe pour la gestion de persistance
+// ObjFileIO<DataTable>
+} // namespace SOPHYA
+
+#endif
+
Index: trunk/SophyaLib/HiStats/histats.h
===================================================================
--- trunk/SophyaLib/HiStats/histats.h	(revision 2682)
+++ trunk/SophyaLib/HiStats/histats.h	(revision 2688)
@@ -9,4 +9,5 @@
 #include "ntuple.h"
 #include "xntuple.h"
+#include "datatable.h"
 
 #endif // HISTATS_SEEN
Index: trunk/SophyaLib/HiStats/histinit.cc
===================================================================
--- trunk/SophyaLib/HiStats/histinit.cc	(revision 2682)
+++ trunk/SophyaLib/HiStats/histinit.cc	(revision 2688)
@@ -12,4 +12,5 @@
 #include "ntuple.h"
 #include "xntuple.h"
+#include "datatable.h"
 
 /*!
@@ -47,4 +48,7 @@
   DObjRegister(ObjFileIO<XNTuple>, XNTuple);
 
+  PPRegister(ObjFileIO<DataTable>);
+  DObjRegister(ObjFileIO<DataTable>, DataTable);
+
 }
 
Index: trunk/SophyaLib/HiStats/objlist.list
===================================================================
--- trunk/SophyaLib/HiStats/objlist.list	(revision 2682)
+++ trunk/SophyaLib/HiStats/objlist.list	(revision 2688)
@@ -1,2 +1,4 @@
+basedtable.o
+datatable.o
 hisprof.o
 histerr.o
