//*-- Author :    Damir Buskulic   20/05/99

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// VFrameChannel                                                        //
//                                                                      //
// Frame data access engine, seeking information from                   //
// a VVirtualFrameInfoDB                                                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "VFrUtil.h"
#include "TStorage.h"
#include "TRegexp.h"
#include "TArrayD.h"
#include "VFrameChannel.h"
#include "VVirtualFrameChannelViewer.h"
#include "VFrameMetaDB.h"
#include "VFileDirectDB.h"

#define SMSSTAMAX 128
#define SMSVALMAX 512
#define MAXCONDITIONS 512

ClassImp(VFrameChannel)

//______________________________________________________________________________
VFrameChannel::VFrameChannel() : VVirtualFrameChannel()
{
//
// Local frame channel constructor
//
   mInfoDBName     = "";
   mCurFrFile      = 0;
   mCurFrFileName  = "";
   mCurMetaData    = new VMetaData();
   mCurVectName    = "";
   mFramesBuffer   = new VFramesBuffer(this);
   mPlayer         = 0;
}

//______________________________________________________________________________
VFrameChannel::VFrameChannel(char* infodb, Option_t* option, char* frameInfoBuild)
           : VVirtualFrameChannel()
{
// Local frame channel constructor
// filename is the name of the info database.
//
   mInfoDBName     = infodb;
   mCurFrFile      = 0;
   mCurFrFileName  = "";
   mCurMetaData    = new VMetaData();
   mCurVectName    = "";
   mFramesBuffer   = new VFramesBuffer(this);
   mPlayer         = 0;
   
   Connect(infodb, option);
}

//______________________________________________________________________________
VFrameChannel::~VFrameChannel()
{
//
// Local frame data base destructor
//

   delete mFramesBuffer;
   if (mCurFrFile) FrFileIEnd(mCurFrFile);
}

//______________________________________________________________________________
 Bool_t VFrameChannel::Connect(char* pathtoDB, Option_t* openopt)
{
// Connect to a new meta info database
   
   VVirtualFrameInfoDB* infodb=0;
   
   if (GetFrameInfoDB()) Disconnect(); // disconnect from an old infoDB
   
   TString metaDBs = pathtoDB;
   char* tmpname = new char[metaDBs.Length()+1];
   if (metaDBs.BeginsWith("metadb:")) {
      metaDBs.Remove(0,7);
      strcpy(tmpname,metaDBs.Data());
      infodb = new VFrameMetaDB(tmpname);
   } else if (metaDBs.BeginsWith("file:")) {
      metaDBs.Remove(0,5);
      strcpy(tmpname,metaDBs.Data());
      infodb = new VFileDirectDB(tmpname);
   } else {
      strcpy(tmpname,metaDBs.Data());
      infodb = new VFrameMetaDB(tmpname);
   }

   SetFrameInfoDB(infodb);
   delete [] tmpname;
   if (infodb) return 1;
   else return 0;
}

//______________________________________________________________________________
 void VFrameChannel::BuildInfoDB(char* nameDB, char* frameFiles, Option_t* opt)
{
// Builds a new meta info database given frame file path and names
   
   VVirtualFrameInfoDB* infodb=0;
   
   if (GetFrameInfoDB()) Disconnect(); // disconnect from an old infoDB
   
   TString metaDBs = nameDB;
   char* tmpname = new char[metaDBs.Length()+1];
   if (metaDBs.BeginsWith("metadb:")) {
      metaDBs.Remove(0,7);
      strcpy(tmpname,metaDBs.Data());
      infodb = new VFrameMetaDB(tmpname,"CREATE",frameFiles);
   } else if (metaDBs.BeginsWith("file:")) {
      Warning("BuildInfoDB","Cannot build info database on direct frame files");
      infodb = 0;
   } else {
      strcpy(tmpname,metaDBs.Data());
      infodb = new VFrameMetaDB(tmpname,"CREATE",frameFiles);
   }
   SetFrameInfoDB(infodb);
   delete [] tmpname;
}

//______________________________________________________________________________
 VConditionSet* VFrameChannel::CreateConditionSet(const char* condfs, const char* selfs)
{
// Creates a condition set adapted to the current Frame Info DB
   if (!GetFrameInfoDB()) {
     Warning("CreateConditionSet","Info database not opened, cannot create a condition set");
     return 0;
  }
  return GetFrameInfoDB()->CreateConditionSet(condfs,selfs);
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetFrameR(Double_t gpstime)
{
// Gets the frame that contains data for time "gpstime"
// The time is a GPS time expressed as a double : seconds.nanoseconds
// If the reference time of this database is set, it will be
// added to gpstime
   
   return GetFrame(gpstime + GetRefTime());
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetFrame(Double_t gpstime)
{
// Gets the frame that contains data for time "gpstime"
// The time is a GPS time expressed as a double : seconds.nanoseconds
// gpstime is the absolute time, no reference included
   
   FrameH* frame;
   VMetaData* meta = new VMetaData();

   if (!GetFrameInfoDB()) {
      Warning("GetFrame","Info database not opened");
      return 0;
   }

// Finds the index of the frame meta in the metadata tree
// returns also the begin and end time of the frame
   GetFrameInfoDB()->GetMetaData(meta,gpstime);
   if (!meta->IsValid()) return 0;
   
   meta->Copy(*mCurMetaData);
      
// ---- Access the frame found ----

   frame = mFramesBuffer->GetFrameCopy(meta);
   delete meta;
   return frame;
}   

//______________________________________________________________________________
 FrameH* VFrameChannel::GetNextFrameR(Double_t gpstime, VConditionSet* conds)
{
// Gets the frame that contains data for time "gpstime" or the frame that
// is the nearest next one and that satisfies the condition set "conds".
// The time is a GPS time expressed as a double : seconds.nanoseconds
// If the reference time of this database is set, it will be
// added to gpstime
// If the pointer to condition is null, suppose no condition asked, will return
// the next nearest frame.
   
   return GetNextFrame(gpstime + GetRefTime(),conds);
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetNextFrameB(Double_t gpstime, VConditionSet* conds)
{
// Gets the frame that contains data for time "gpstime" or the frame that
// is the nearest next one and that satisfies the condition set "conds".
// The time is a GPS time expressed as a double : seconds.nanoseconds
// If the pointer to condition is null, suppose no condition asked, will return
// the next nearest frame.
   
   FrameH* frame;
   VMetaData* nearestmeta = new VMetaData();
   
   if (!GetFrameInfoDB()) {
      Warning("GetNextFrameB","Data base not opened");
      return 0;
   }

   GetFrameInfoDB()->NextMetaData(nearestmeta, gpstime, conds);
   if (!nearestmeta->IsValid()) return 0;

   nearestmeta->Copy(*mCurMetaData);

// ---- Access the frame found ----

// Read the meta-data
   frame = mFramesBuffer->GetFrame(nearestmeta);
   delete nearestmeta;
   return frame;
}   

//______________________________________________________________________________
 FrVect* VFrameChannel::GetNextVectB(Double_t gpstime, char* vectname, VConditionSet* conds)
{
// Gets the vector named "vectname that contains data for time "gpstime"
// or the vector that is the nearest next one and that satisfies
// the selection formula "condf".
// The time is a GPS time expressed as a double : seconds.nanoseconds
// If the pointer to condition is null, suppose no condition asked, will return
// the next nearest frame.
   
   FrVect* vect;
   VMetaData* nearestmeta = new VMetaData();
   
   if (!GetFrameInfoDB()) {
      Warning("GetNextVectB","Data base not opened");
      return 0;
   }

   GetFrameInfoDB()->NextMetaData(nearestmeta, gpstime, conds);
   if (!nearestmeta->IsValid()) return 0;

   nearestmeta->Copy(*mCurMetaData);
   mCurVectName = vectname;
   
// ---- Access the frame found ----

// Read the meta-data
   vect = mFramesBuffer->GetVect(nearestmeta,vectname);
   delete nearestmeta;
   return vect;
}   

//______________________________________________________________________________
 FrameH* VFrameChannel::GetNextFrame(Double_t gpstime, VConditionSet* conds)
{
// Gets the frame that contains data for time "gpstime" or the frame that
// is the nearest next one and that satisfies the condition set "conds".
// The time is a GPS time expressed as a double : seconds.nanoseconds
// If the pointer to condition is null, suppose no condition asked, will return
// the next nearest frame.
// Uses buffered method, and then copies the frame

   FrameH* frame, *frcopy;
   
   frame = GetNextFrameB(gpstime,conds);
   if (frame) {
      frcopy = FrameCopy(frame);
   } else {
      frcopy = 0;
   }
   return frcopy;
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetNextFrame(Double_t gpstime, const char* selection)
{
// Gets the frame that contains data for time "gpstime" or the frame that
// is the nearest next one and that satisfies the selection formula "selection".
// The time is a GPS time expressed as a double : seconds.nanoseconds
// If the pointer to char is null, suppose no condition asked, will return
// the next nearest frame.
// Uses buffered method, and then copies the frame

   VConditionSet* conds;
   FrameH* frame;
   
   if (!selection || strlen(selection)==0) return GetNextFrame(gpstime, (VConditionSet*)0);
   
   conds = GetFrameInfoDB()->CreateConditionSet(selection);
   frame = GetNextFrame(gpstime,conds);
   delete conds;
   return frame;
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetNextFrameR(Double_t gpstime, const char* selection)
{
// Gets the frame that contains data for time "gpstime" or the frame that
// is the nearest next one and that satisfies the selection formula "selection".
// The time is a GPS time expressed as a double : seconds.nanoseconds
// If the reference time of this database is set, it will be
// added to gpstime
// If the pointer to condition is null, suppose no condition asked, will return
// the next nearest frame.
   
   return GetNextFrame(gpstime + GetRefTime(),selection);
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetFrameDirectB(VMetaData* meta, Option_t* opt)
{
// Gets the frame that is described by meta data "meta"
// This should normally not be called directly, but only after
// finding the right position from the index tree.
// BE CAREFULL ! the output of this routine is managed by the buffer,
// You should not delete it.
   
   return GetFrameDirectB("",meta,opt);
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetFrameDirectB(char* vectname, VMetaData* meta, Option_t* opt)
{
// Gets the frame that is described by meta data "meta"
// This should normally not be called directly, but only after
// finding the right position from the index tree.
// BE CAREFULL ! the output of this routine is managed by the buffer,
// You should not delete it.
   
   char* tmpfilename;
   TString frpathname;
   FrameH* frame;
   Int_t vecttype;
   TString slash="/";
   TString opts = opt;
   opts.ToLower();
   char* vectnamer = vectname;

   if (strlen(vectname)) {
      vecttype = VGetVectType(vectname);
      switch (vecttype) {
         case 1: vectnamer = vectname+4; break;
         case 2: vectnamer = vectname+5; break;
         case 3: vectnamer = vectname+4; break;
         default: break;
      }
   } else vecttype = -1;
   
   if (!GetFrameInfoDB()) {
      Warning("GetFrameDirectB","Data base not opened");
      return 0;
   }
   if (!meta) {
      Warning("GetFrameDirectB","Null meta data, no frame loaded");
      return 0;
   }
      
// ---- Access the frame ----

// Read the meta-data
   
   TRegexp* reg = new TRegexp("^[ ]*[/]",kFALSE); // regexp for any number of spaces + a slash

   TString metafilename = meta->GetFileName();
   if (metafilename.Index(*reg) != kNPOS) { // file path begins with a slash
      frpathname = metafilename;
   } else if (strlen(GetFrameInfoDB()->GetPathToDB())==0) {
      frpathname = metafilename;
   } else {
      frpathname = GetFrameInfoDB()->GetPathToDB() + slash + metafilename;
   }
   delete reg;
   
   if (FrLibVersion(0)>=3.79) {
// Direct access to the frame in the file
      if ( (mCurFrFileName != frpathname.Data()) ) {
         if (mCurFrFile) FrFileIEnd(mCurFrFile);
         mCurFrFileName = frpathname.Data();
         tmpfilename = new char[strlen(frpathname.Data())+1];
         strcpy(tmpfilename,frpathname.Data());
         mCurFrFile = FrFileINew(tmpfilename);
         delete [] tmpfilename;
      }
      
      frame = 0;
      if (opts=="empty") {
         frame = FrameHReadT(mCurFrFile,meta->GetStartTime().GetTimeD()+1e-4);
      } else if (vecttype==-1){
         frame = FrameReadT(mCurFrFile,meta->GetStartTime().GetTimeD()+1e-4);
     // Protect against overflow in timeOffsetN. Do it for all frames read
     // before September 22 2002. Arbitrary date, hope the bug in Framelib will
     // be cured until then
         if (frame->rawData && frame->rawData->firstAdc && frame->GTimeS < 716724657) {
            FrAdcData* adctoclear = frame->rawData->firstAdc;
            while (adctoclear) {
#if FR_VERS<6000
               adctoclear->timeOffsetN = 0;
               adctoclear->timeOffsetS = 0;
#else
               adctoclear->timeOffset = 0;
#endif
               adctoclear = adctoclear->next;
            }
         }
      } else {
         if (vecttype == 1 || !vecttype) {
            frame = FrameHNew("vegatemp");
            FrRawDataNew(frame);
            if (frame->rawData) {
               frame->rawData->firstAdc = FrAdcDataReadT(mCurFrFile,
                                   vectnamer,meta->GetStartTime().GetTimeD()+1e-4);
         // Protect against overflow in timeOffsetN. Do it for all frames read
         // before September 22 2002. Arbitrary date, hope the bug in Framelib will
         // be cured until then
               if (frame->rawData->firstAdc && frame->GTimeS < 716724657) {
                  FrAdcData* adctoclear = frame->rawData->firstAdc;
                  while (adctoclear) {
#if FR_VERS<6000
                     adctoclear->timeOffsetN = 0;
                     adctoclear->timeOffsetS = 0;
#else
                     adctoclear->timeOffset = 0;
#endif
                     adctoclear = adctoclear->next;
                  }
               }
            }
         }
         if (vecttype == 2 || (!vecttype && !frame)) {
            frame = FrameHNew("vegatemp");
            if (frame) frame->procData = FrProcDataReadT(mCurFrFile,
                                   vectnamer,meta->GetStartTime().GetTimeD()+1e-4);
         }
         if (vecttype == 3 || (!vecttype && !frame)) {
            frame = FrameHNew("vegatemp");
            if (frame) frame->simData = FrSimDataReadT(mCurFrFile,
                                   vectnamer,meta->GetStartTime().GetTimeD()+1e-4);
         }
      } 
      if (frame) return frame;
   }
   
   Error("GetFrameDirectB","Inconsistency, cannot read frame in file %s",frpathname.Data());
   return 0;
}   

//______________________________________________________________________________
 FrAdcData* VFrameChannel::GetAdcDirectB(VMetaData* meta, char* vectname)
{
// Gets the adc "vectname" that is in frame defined by meta information "meta"
// This should normally not be called directly, but only after
// finding the right meta information.
// BE CAREFULL ! the output of this routine is managed by the buffer,
// You should not delete it.

   FrAdcData* adc=0;
   FrameH* frame = GetFrameDirectB(vectname,meta);
   if (frame) {
      if (frame->rawData) {
         adc = frame->rawData->firstAdc;
         frame->rawData->firstAdc = 0;
      }
      FrameFree(frame);
   }
   return adc;
}

//______________________________________________________________________________
 FrProcData* VFrameChannel::GetProcDirectB(VMetaData* meta, char* vectname)
{
// Gets the proc "vectname" that is in frame defined by meta information "meta"
// This should normally not be called directly, but only after
// finding the right meta information.
// BE CAREFULL ! the output of this routine is managed by the buffer,
// You should not delete it.

   FrProcData* proc=0;
   FrameH* frame = GetFrameDirectB(vectname,meta);
   if (frame) {
      proc = frame->procData;
      frame->procData = 0;
      FrameFree(frame);
   }
   return proc;
}

//______________________________________________________________________________
 FrSimData* VFrameChannel::GetSimDirectB(VMetaData* meta, char* vectname)
{
// Gets the proc "vectname" that is in frame defined by meta information "meta"
// This should normally not be called directly, but only after
// finding the right meta information.
// BE CAREFULL ! the output of this routine is managed by the buffer,
// You should not delete it.

   FrSimData* sim=0;
   FrameH* frame = GetFrameDirectB(vectname,meta);
   if (frame) {
      sim = frame->simData;
      frame->simData = 0;
      FrameFree(frame);
   }
   return sim;
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetNextFrameB()
{
// Returns the frame following in time the last returned one (uses buffer)
   
   if (!GetFrameInfoDB()) {
      Warning("GetNextFrameB","Data base not opened");
      return 0;
   }
   if (mCurMetaData) {
      return GetNextFrameB(mCurMetaData->GetEndTime()+1e-4);
   } else {
      return GetNextFrameB(0.);
   }
}

// //______________________________________________________________________________
// FrVect* VFrameChannel::GetNextVectB()
// {
// // Returns the vector following in time the last returned one (uses buffer)
// 
//    Double_t beginf, endf;
//    char* vectname0;
//    FrVect* vect;
//    
//    if (!mIsOpened || !mOption.CompareTo("update", TString::kIgnoreCase)) {
//       Warning("GetNextFrameB","Data base not opened or in update mode");
//       return 0;
//    }
//    
//    vectname0 = new char[mCurVectName.Length()+1];
//    strcpy(vectname0,mCurVectName.());
// 
//    vect = GetNextVectB(mCurMetaData->GetEndTime()+1e-4, vectname0);
//    delete [] vectname0;
//    return vect;
// }

//______________________________________________________________________________
 FrameH* VFrameChannel::GetNextFrameB(VConditionSet* condset)
{
// Returns the first frame satisfying the next selection
// region of the condition set "condset". (uses buffer)
// Returns a a buffered frame pointer. User does not have to take care
// (delete) the frame. But the frame may be deleted at any time.

   FrameH* frame;
   VMetaData* nearestmeta = new VMetaData();
   
   if (!GetFrameInfoDB()) {
      Warning("GetNextFrameB","Data base not opened");
      return 0;
   }
   
   if (!condset) {
      Warning("GetNextFrameB","No condition set defined");
      return 0;
   }

   GetFrameInfoDB()->NextMetaData(nearestmeta, condset);
   if (!nearestmeta->IsValid()) return 0;

   nearestmeta->Copy(*mCurMetaData);

// ---- Access the frame found ----

// Read the meta-data
   frame = mFramesBuffer->GetFrame(nearestmeta);
   delete nearestmeta;
   return frame;
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetNextFrame()
{
// Returns the frame following in time the last returned one
// Uses buffered method, and then copies the frame

   FrameH* frame, *frcopy;
   
   frame = GetNextFrameB();
   if (frame) {
      frcopy = FrameCopy(frame);
   } else {
      frcopy = 0;
   }
   return frcopy;
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetNextFrame(VConditionSet* condset)
{
// Returns the first frame satisfying the next selection
// region of the condition set "condset".
// Returns a frame copy. User has to take care (delete) it if necessary.

   FrameH* frame, *frcopy;
   
   frame = GetNextFrameB(condset);
   if (frame) {
      frcopy = FrameCopy(frame);
   } else {
      frcopy = 0;
   }
   return frcopy;
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetPreviousFrameB()
{
// Returns the frame preceeding in time the last returned one

   FrameH* frame;
   VMetaData* nearestmeta = new VMetaData();
   
   if (!GetFrameInfoDB()) {
      Warning("GetPreviousFrameB","Data base not opened");
      return 0;
   }
   if (!mCurMetaData) {
      Warning("GetPreviousFrameB","No current meta data");
      return 0;
   }

   mCurMetaData->Copy(*nearestmeta);
   GetFrameInfoDB()->PreviousMetaData(nearestmeta);
   if (!nearestmeta->IsValid()) return 0;

   nearestmeta->Copy(*mCurMetaData);

// ---- Access the frame found ----

// Read the meta-data
   frame = mFramesBuffer->GetFrame(mCurMetaData);
   return frame;
}

//______________________________________________________________________________
 FrameH* VFrameChannel::GetPreviousFrame()
{
// Returns the frame preceeding in time the last returned one
// Uses buffered method, and then copies the frame

   FrameH* frame, *frcopy;
   
   frame = GetPreviousFrameB();
   if (frame) {
      frcopy = FrameCopy(frame);
   } else {
      frcopy = 0;
   }
   return frcopy;
}

//______________________________________________________________________________
 FrVect* VFrameChannel::GetNextVect(char* nameofvect, Double_t gpstime, const char* selection, Option_t* opt)
{
//   Extracts a vector FrVect given it's name and type. 
// The vector is satisfying the selection expression, i.e. it begins at the
// start of the ConditionSet defined by the selection and has a length defined
// by the length of this condition set. The search for the vector begins at
// time gps time.
// Vectors extracted from the database will be concatenated as needed
// to obtain the desired vector.
//   The string nameofvect indicates the type (adc, proc, sim) and
// the name of the series to be extracted. The convention for the format
// is "type.name".
//   For example "adc.IFO_DMRO" is a good format.
//   If only the name is given, the groups of series in the frame
// will be searched in the order adc, proc, sim for that name.
//   If more than one identical name was defined in the frame, the first
// found series with that name will be used.
// if the selection string is empty, will return 0

   Double_t vstart, vlength;
   Int_t cok;
   VConditionSet* condset;
   
   if (!selection) {
      Warning("GetNextVect","No selection expression");
      return 0;
   }
   if (!strlen(selection)) {
      Warning("GetNextVect","Empty selection expression");
      return 0;
   }
   
   condset = GetFrameInfoDB()->CreateConditionSet(selection);
   cok = condset->NearestGEFormSet(gpstime);
   if (!cok) {delete condset; return 0;}
   vstart = condset->GetIntersectionStart();
   vlength = condset->GetIntersectionEnd() - vstart;
   delete condset;
   return GetVect(nameofvect, vstart, vlength,opt);
}

//______________________________________________________________________________
 FrVect* VFrameChannel::GetNextVectR(char* nameofvect, Double_t gpstime, const char* selection, Option_t* opt)
{
//   Extracts a vector FrVect given it's name and type. 
// The vector is satisfying the selection expression, i.e. it begins at the
// start of the ConditionSet defined by the selection and has a length defined
// by the length of this condition set. The search for the vector begins at
// time gpstime, which is considered relative to the reference time.
// Vectors extracted from the database will be concatenated as needed
// to obtain the desired vector.
//   The string nameofvect indicates the type (adc, proc, sim) and
// the name of the series to be extracted. The convention for the format
// is "type.name".
//   For example "adc.IFO_DMRO" is a good format.
//   If only the name is given, the groups of series in the frame
// will be searched in the order adc, proc, sim for that name.
//   If more than one identical name was defined in the frame, the first
// found series with that name will be used.
// if the selection string is empty, will return 0

   return GetNextVect(nameofvect, gpstime + GetRefTime(), selection);
}

//______________________________________________________________________________
 FrVect* VFrameChannel::GetNextVect(char* nameofvect, VConditionSet* condset, Option_t* opt)
{
//   Extracts a vector FrVect given it's name and type. 
// The vector is satisfying the condition set condset, i.e. it begins at the
// start of the ConditionSet "condset" and has a length defined by the length
// of this condition set.
// Vectors extracted from the database will be concatenated as needed
// to obtain the desired vector.
//   The string nameofvect indicates the type (adc, proc, sim) and
// the name of the series to be extracted. The convention for the format
// is "type.name".
//   For example "adc.IFO_DMRO" is a good format.
//   If only the name is given, the groups of series in the frame
// will be searched in the order adc, proc, sim for that name.
//   If more than one identical name was defined in the frame, the first
// found series with that name will be used.

   Int_t cok;
   Double_t vstart, vlength;
   
   if (!condset) {
      Warning("GetNextVect","No condition set");
      return 0;
   }
   
   cok = condset->NextFormSet();
   if (!cok) return 0;
   vstart = condset->GetIntersectionStart();
   vlength = condset->GetIntersectionEnd() - vstart;
   return GetVect(nameofvect, vstart, vlength, opt);
}

//______________________________________________________________________________
 VFrVectObject* VFrameChannel::GetNextSignal(char* nameofvect,  VConditionSet* condset, Option_t* opt)
{
// Retrieve the next vector, encapsulate it in an object. Used with signal library
// See VFrameChannel::GetNextVect() for the meaning of variables

   FrVect* vect;
   vect = GetNextVect(nameofvect, condset,opt);
   VFrVectObject* frvo = new VFrVectObject(vect);
   return frvo;
}

//______________________________________________________________________________
 FrVect* VFrameChannel::GetVectR(char* nameofvect, Double_t start, Double_t length, Option_t* opt)
{
//   Extracts a vector FrVect given it's name and type. The vector starts
// at time "start" and has a length "length". "start" is considered with
// respect to the reference time. Vectors extracted from
// the database will be concatenated as needed to obtain the desired vector
//   The string nameofvect indicates the type (adc, proc, sim) and
// the name of the series to be extracted. The convention for the format
// is "type.name".
//   For example "adc.IFO_DMRO" is a good format.
//   If only the name is given, the groups of series in the frame
// will be searched in the order adc, proc, sim for that name.
//   If more than one identical name was defined in the frame, the first
// found series with that name will be used.

   return GetVect(nameofvect, start + GetRefTime(), length, opt);
}
//______________________________________________________________________________
 FrVect* VFrameChannel::GetVect(char* nameofvect, Double_t start, Double_t length, Option_t* opt)
{
//   Extracts a vector FrVect given it's name and type. The vector starts
// at time "start" and has a length "length". Vectors extracted from
// the database will be concatenated as needed to obtain the desired vector
//   The string nameofvect indicates the type (adc, proc, sim) and
// the name of the series to be extracted. The convention for the format
// is "type.name".
//   For example "adc.IFO_DMRO" is a good format.
//   If only the name is given, the groups of series in the frame
// will be searched in the order adc, proc, sim for that name.
//   If more than one identical name was defined in the frame, the first
// found series with that name will be used.
// All data will be casted to double, except if opt = "nocast" is given,
// in which case, the result vector will have the same type as the original
// ones

   FrVect* vect, * vectresult;
   Int_t ndataresult;
   Double_t dstep;
   VGPSTime framestart, frameend, oldframestart, oldframeend;
   char* dataresult;
   unsigned short* dataresultUS;
   short* dataresultS;
   unsigned int* dataresultUI;
   int* dataresultI;
   float* dataresultF;
   double* dataresultD;
   Int_t inputvindex;
   Int_t typevect, typeresult;
   char*   tdata;
   unsigned short* tdataUS;
   short* tdataS;
   unsigned int* tdataUI;
   int* tdataI;
   float* tdataF;
   double* tdataD;
   
   TString opts = opt;
   opts.ToLower();
   
   if (!GetFrameInfoDB()) {
      Warning("GetVect","Data base not opened");
      return 0;
   }
   
// Get the first vector to see it's parameters
   vect = GetNextVectB(start,nameofvect);
   if (!vect) {
      Warning("GetVect","Requested vector not present in the frame");
      return 0;
   }

// No dealing with 2D vectors yet
   if (vect->nDim >1) {
      Warning("GetVect","No extraction of 2D vectors yet");
      return 0;
   }
   
   tdata= vect->data;
   tdataUS= vect->dataUS;
   tdataS= vect->dataS;
   tdataUI= vect->dataUI;
   tdataI= vect->dataI;
   tdataF= vect->dataF;
   tdataD= vect->dataD;
   
   if (vect->dx[0] == 0) {dstep = 1;} else {dstep = vect->dx[0];}
// The Minimal requested length is the time step
   if (dstep>length) length = dstep;
   ndataresult = (Int_t)(length/dstep+0.5); // correct for possible rounding pbs

// Create a new vector according to these parameters
   char* unitxname;
   if (vect->unitX) {
      unitxname = new char[strlen(vect->unitX[0])+1];
      strcpy(unitxname,vect->unitX[0]);
   } else {
      unitxname = new char[9];
      strcpy(unitxname,"time (s)");
   }
   
   if (opts.Contains("nocast")) {
      typeresult = vect->type;
   } else {
      typeresult = FR_VECT_8R;
   }
   vectresult = FrVectNew1D(vect->name, typeresult, ndataresult,
                            dstep, unitxname,vect->unitY);
   delete [] unitxname;
   
#if FR_VERS<6000
   framestart.SetSec(vect->GTimeS);
   framestart.SetNsec(vect->GTimeN);
#else
   framestart.SetTimeD(vect->GTime);
#endif
   frameend = framestart + vect->nx[0]*dstep;
// Correct the start time to be on the boundary of a clock tick
// ============================================================================
// BE CAREFUL, THIS MAY LEAD TO ERRORS AND PROBLEMS IN THE FUTURE
// ============================================================================
//
// Also add dstep/100 to avoid rounding errors
   double corstart = dstep/100;
   if (start-framestart.GetTimeD() < -1e-4) corstart = -corstart;
   start = (Int_t)((start-framestart.GetTimeD()+corstart)/dstep)*dstep + framestart.GetTimeD();
   Double_t ftmpindex = (start - framestart.GetTimeD())/dstep;
   if (ftmpindex<0) inputvindex = (Int_t)(ftmpindex-0.5);
   else inputvindex = (Int_t)(ftmpindex+0.5);
   typevect = vect->type;

// Sets the supplementary variables of the new vector
#if FR_VERS<6000
   vectresult->GTimeS = (long)(floor(start));
//   CAUTION, the last two digits of nanoseconds are set to 0
//    thus the precision is limited to 100 ns
//    this is to avoid rounding errors
   vectresult->GTimeN = (long)((start-vectresult->GTimeS)*1e7+0.5)*100;
#else
   long startStemp = (long)(floor(start));
//   CAUTION, the last two digits of nanoseconds are set to 0
//    thus the precision is limited to 100 ns
//    this is to avoid rounding errors
   long startNtemp = (long)((start-startStemp)*1e7+0.5)*100;
   vectresult->GTime = startStemp + startNtemp * 1e-9;
#endif
   vectresult->startX[0] = 0;
   vectresult->ULeapS = vect->ULeapS;
   vectresult->localTime = vect->localTime;
   
// Copy the relevant data into the newly created vector
   Int_t dataindex = 0;
   dataresult = vectresult->data; // pointer to the data area of the result vector
   dataresultUS = vectresult->dataUS; // pointer to the data area of the result vector
   dataresultS = vectresult->dataS; // pointer to the data area of the result vector
   dataresultUI = vectresult->dataUI; // pointer to the data area of the result vector
   dataresultI = vectresult->dataI; // pointer to the data area of the result vector
   dataresultF = vectresult->dataF; // pointer to the data area of the result vector
   dataresultD = vectresult->dataD; // pointer to the data area of the result vector

   while (dataindex < ndataresult) {
      if (inputvindex<0) {
         switch (typeresult) {
            case FR_VECT_C :  dataresult[dataindex]   = 0; break;
            case FR_VECT_2U : dataresultUS[dataindex] = 0; break;
            case FR_VECT_2S : dataresultS[dataindex]  = 0; break;
            case FR_VECT_4U : dataresultUI[dataindex] = 0; break;
            case FR_VECT_4S : dataresultI[dataindex]  = 0; break;
            case FR_VECT_4R : dataresultF[dataindex]  = 0; break;
            case FR_VECT_8R : dataresultD[dataindex]  = 0; break;
            default : 
               Warning("GetVect","Type of data not valid in the input vector");
               FrVectFree(vectresult);
               return 0;
               break;
         }
         dataindex++;
         inputvindex++;
      } else {
         if (opts.Contains("nocast")) {
            switch (typevect) {
               case FR_VECT_C :  dataresult[dataindex]   = tdata[inputvindex]; break;
               case FR_VECT_2U : dataresultUS[dataindex] = tdataUS[inputvindex]; break;
               case FR_VECT_2S : dataresultS[dataindex]  = tdataS[inputvindex]; break;
               case FR_VECT_4U : dataresultUI[dataindex] = tdataUI[inputvindex]; break;
               case FR_VECT_4S : dataresultI[dataindex]  = tdataI[inputvindex]; break;
               case FR_VECT_4R : dataresultF[dataindex]  = tdataF[inputvindex]; break;
               case FR_VECT_8R : dataresultD[dataindex]  = tdataD[inputvindex]; break;
               default : 
                  Warning("GetVect","Type of data not valid in the input vector");
                  FrVectFree(vectresult);
                  return 0;
                  break;
            }
         } else {
            switch (typevect) {
               case FR_VECT_C :  dataresultD[dataindex] = (double)(tdata[inputvindex]); break;
               case FR_VECT_2U : dataresultD[dataindex] = (double)(tdataUS[inputvindex]); break;
               case FR_VECT_2S : dataresultD[dataindex] = (double)(tdataS[inputvindex]); break;
               case FR_VECT_4U : dataresultD[dataindex] = (double)(tdataUI[inputvindex]); break;
               case FR_VECT_4S : dataresultD[dataindex] = (double)(tdataI[inputvindex]); break;
               case FR_VECT_4R : dataresultD[dataindex] = (double)(tdataF[inputvindex]); break;
               case FR_VECT_8R : dataresultD[dataindex] = tdataD[inputvindex]; break;
               default : 
                  Warning("GetVect","Type of data not valid in the input vector");
                  FrVectFree(vectresult);
                  return 0;
                  break;
            }
         }
         dataindex++;
         inputvindex++;
 //     If necessary, load the next vector
         if ( inputvindex >= (Int_t)(vect->nx[0])) {

//        Loading next frame
            oldframestart = framestart;
            oldframeend = frameend;
            vect = GetNextVectB(mCurMetaData->GetEndTime()+1e-4, nameofvect);
            if (!vect) {
               inputvindex = -99999999;
            } else {
               tdata= vect->data;
               tdataUS= vect->dataUS;
               tdataS= vect->dataS;
               tdataUI= vect->dataUI;
               tdataI= vect->dataI;
               tdataF= vect->dataF;
               tdataD= vect->dataD;
#if FR_VERS<6000
               framestart.SetSec(vect->GTimeS);
               framestart.SetNsec(vect->GTimeN);
#else
               framestart.SetTimeD(vect->GTime);
#endif
               frameend = framestart + vect->nx[0]*dstep;
               if ((vect->dx[0] != dstep) || (vect->dx[0]==0 && dstep!=1)) {
                  Error("GetVect","Change of step size in read vectors");
                  FrVectFree(vectresult);
                  return 0;
               }
//          In case there is a hole between the two vectors,
//          fill it with zeros. It is assumed the hole is an integer number
//          of steps
               int numholes = (int)((framestart.GetTimeD() - oldframeend.GetTimeD())/dstep);
               if (numholes) {
//              dataindex contains the current index+1=the number of filled bins
                  if (dataindex+numholes > ndataresult)
                     numholes = ndataresult - dataindex;
                  for (int i = 0; i<numholes; i++) {
                     switch (typeresult) {
                        case FR_VECT_C :  dataresult[dataindex]   = 0; break;
                        case FR_VECT_2U : dataresultUS[dataindex] = 0; break;
                        case FR_VECT_2S : dataresultS[dataindex]  = 0; break;
                        case FR_VECT_4U : dataresultUI[dataindex] = 0; break;
                        case FR_VECT_4S : dataresultI[dataindex]  = 0; break;
                        case FR_VECT_4R : dataresultF[dataindex]  = 0; break;
                        case FR_VECT_8R : dataresultD[dataindex]  = 0; break;
                        default : 
                           Warning("GetVect","Type of data not valid in the input vector");
                           FrVectFree(vectresult);
                           return 0;
                           break;
                     }
                     dataindex++;
                  }
               }
               inputvindex = 0;
            }
         }
      }
   }
         
   return vectresult;            
}

//______________________________________________________________________________
 VFrVectObject* VFrameChannel::GetSignal(char* nameofvect, Double_t start, Double_t length, Option_t* opt)
{
// Retrieve a vector encapsulated in an object. Used with signal library
// See VFrameChannel::GetVect() for the meaning of variables

   FrVect* vect;
   vect = GetVect(nameofvect, start,length,opt);
   VFrVectObject* frvo = new VFrVectObject(vect);
   return frvo;
}

//______________________________________________________________________________
 VFrVectObject* VFrameChannel::GetSignalR(char* nameofvect, Double_t start, Double_t length, Option_t* opt)
{
// Retrieve a vector encapsulated in an object. Used with signal library
// See VFrameChannel::GetVectR() for the meaning of variables

   return GetSignal(nameofvect, start + GetRefTime(), length, opt);
}

//______________________________________________________________________________
 VFrVectObject* VFrameChannel::GetNextSignal(char* nameofvect, Double_t gpstime, const char* selection, Option_t* opt)
{
// Retrieve the next vector, encapsulate it in an object. Used with signal library
// See VFrameChannel::GetNextVect() for the meaning of variables

   FrVect* vect;
   vect = GetNextVect(nameofvect, gpstime, selection,opt);
   VFrVectObject* frvo = new VFrVectObject(vect);
   return frvo;
}

//______________________________________________________________________________
 VFrVectObject* VFrameChannel::GetNextSignalR(char* nameofvect, Double_t gpstime, const char* selection, Option_t* opt)
{
// Retrieve the next vector, encapsulate it in an object. Used with signal library
// See VFrameChannel::GetNextVectR() for the meaning of variables

   return GetNextSignal(nameofvect, gpstime + GetRefTime(), selection, opt);
}

//______________________________________________________________________________
 Double_t VFrameChannel::GetStart()
{
// Returns the start time of the first frame in the metadatabase
   return GetFrameInfoDB()->GetStart();
}

//______________________________________________________________________________
 Double_t VFrameChannel::GetEnd()
{
// Returns the end time of the last frame in the metadatabase
   return GetFrameInfoDB()->GetEnd();
}

//______________________________________________________________________________
 VNtuple* VFrameChannel::ExtractSMSR(char* ntname, char* listofnames0, Double_t start, Double_t length)
{
//   Builds a new NTuple and fills it with SMS data from the database
//   The NTuple that is build is a VNtuple.
//   If one wants to have this ntuple on disk rather than in memory,
//   one should open a file in "RECREATE" or "UPDATE" mode first.
//   On closing this file, the ntuple will automatically be saved on disk
//   (AND THE NTUPLE DELETED).
//   The SMS data starts at time "start" and has a length "length".
//   start time is considered by reference to the reference time
//   ntname is the name of the created ntuple
//   listofnames is the list of names of the SMS stations/values one needs
//   to include in the ntuple. The format is 
//   "name1:name2:name3:...." where namei is of the form "stationname.valuename",
   
   return ExtractSMS(ntname,listofnames0,start + GetRefTime(),length);
}

//______________________________________________________________________________
 VNtuple* VFrameChannel::ExtractSMS(char* ntname, char* listofnames0, Double_t start, Double_t length)
{
//   Builds a new NTuple and fills it with SMS data from the database
//   The NTuple that is build is a VNtuple.
//   If one wants to have this ntuple on disk rather than in memory,
//   one should open a file in "RECREATE" or "UPDATE" mode first.
//   On closing this file, the ntuple will automatically be saved on disk
//   (AND THE NTUPLE DELETED).
//   The SMS data starts at time "start" and has a length "length".
//   ntname is the name of the created ntuple
//   listofnames is the list of names of the SMS stations/values one needs
//   to include in the ntuple. The format is 
//   "name1:name2:name3:...." where namei is of the form "stationname.valuename",

   char** smsstaname;
   char** smsvalname;
   char** smsstaname1;
   char** smsvalname1;
   char* listofnames;
   TString ntlist;
   Int_t ll, numnames, numnames0, numnames1;
   Int_t i, inames, ismsval, ivar;
   char* begp, *endp, *valp;
   FrameH* frame;
   FrSerData* serdata;
   Long_t sererr;
   Double_t smsval;
   char* namepointer;
   char tmpname[100];
   Int_t serlength;
   Int_t ntlistlength;
   VNtuple* vnt;
   
   TString point = ".";
   TString colon = ":";

// The lowest frame time and step are determined for the VNTuple
   VGPSTime reftime(0,0);
   Double_t loweststep = 100000000000.;
   Double_t oldstarttime = 0.;

   if (!GetFrameInfoDB()) {
      Warning("ExtractSMS","Data base not opened or in update mode");
      return 0;
   }
   
// Extracts the desired names of stations/values

   ntlistlength = 0;
   ntlist = "";
   ll = strlen(listofnames0);
   listofnames = new char[ll+1];
   strcpy(listofnames, listofnames0);
// Number of names in the list
   numnames = 0; i=0;
   while (listofnames[i]) { if (listofnames[i]==':') numnames++; i++; }
   if (listofnames[i-1] != ':') numnames++;
   smsstaname = new char*[numnames+1];
   smsvalname = new char*[numnames+1];
   begp = listofnames;
   endp = listofnames;
   numnames0 = 0;
   for (inames = 0; inames < numnames; inames++) {
//   Station and value name
      endp = strstr(begp,":");
      if (!endp) endp=begp+strlen(begp); // in case there is no more ":"
      endp[0] = 0;
      smsstaname[inames] = begp;
//   separate station and value
      valp = strstr(begp,".");
      if (valp) {
         valp[0] = 0;
         smsvalname[inames] = valp+1;
         numnames0++;
//     Build the ntuple var list
         if (!ntlist.IsNull()) ntlist += colon;
         ntlist += smsstaname[inames] + point + smsvalname[inames];
      } else {
         smsvalname[inames] = 0; // in case there is no "."
      }
      begp = endp+1;
         
   }
//   Supplementary station and value names if complete sms asked for
   smsstaname1 = new char*[SMSSTAMAX * SMSVALMAX];
   smsvalname1 = new char*[SMSSTAMAX * SMSVALMAX];
   
// Get the first vector to see it's parameters
   frame = GetNextFrameB(start);
   if (!frame) return 0;
   
// Test the names to see if they are present in the first frame
   numnames1 = 0;
   for (ismsval = 0; ismsval < numnames; ismsval++) {
      if (!smsvalname[ismsval]) {   // if search for ALL values in the station
#if FR_VERS >= 4040
         serdata = FrSerDataFind(frame, smsstaname[ismsval],0);
#else
         serdata = FrSerDataFind(frame, smsstaname[ismsval]);
#endif
         if (!serdata) {
            Error("ExtractSMS","The SMS station : %s is not in the first extracted frame", smsstaname[ismsval]);
            Error("ExtractSMS","Trying to extract all values from a non existing SMS, no output");
            return 0;
         }
//      Serial data ok, add all the names of the parameters to the list
         namepointer = serdata->data;
         serlength = strlen(serdata->data);
//      Skip the first 6 parameters in serial data (meaningless in our case)
#if FR_VERS < 4040
         for (i=0;i<6;i++) {
            while(*namepointer==' ' || *namepointer=='\n') namepointer++;
            sscanf(namepointer,"%s",tmpname);
            namepointer += strlen(tmpname)+1;
         }
#endif
         while (namepointer - serdata->data < serlength) {
//         Get the name of the parameter
            while(*namepointer==' ' || *namepointer=='n') namepointer++;
            sscanf(namepointer,"%s",tmpname);
            smsstaname1[numnames1] = new char[strlen(smsstaname[ismsval])+1];
            strcpy(smsstaname1[numnames1], smsstaname[ismsval]);
            smsvalname1[numnames1] = new char[strlen(tmpname)+1];
            strcpy(smsvalname1[numnames1], tmpname);
            
//        Continue to build the ntuple var list
            if (!ntlist.IsNull()) ntlist += colon;
            ntlist += smsstaname1[numnames1] + point + smsvalname1[numnames1];

            numnames1++;
            namepointer += strlen(tmpname)+1;
//         Skip the value
            while(*namepointer==' ' || *namepointer=='n') namepointer++;
            sscanf(namepointer,"%s",tmpname);
            namepointer += strlen(tmpname)+1;
         }
      } else {
         sererr = FrSerDataGet(frame, smsstaname[ismsval], smsvalname[ismsval], &smsval);
         if (sererr == -2) {
            Warning("ExtractSMS","The SMS station : %s is not in the first extracted frame", smsstaname[ismsval]);
         } else if (sererr == -1) {
            Warning("ExtractSMS","The SMS parameter : %s is not in the first extracted frame", smsvalname[ismsval]);
         }
      }
   }
   
// Nevertheless, try to load all the frames. The SMS parameters may be present elsewhere
   
   if (ntlist.IsNull()) ntlist = "t";
   else ntlist = "t:"+ntlist;
   
// First, build a new ntuple.
   vnt = new VNtuple(ntname,ntname,ntlist.Data());
   Float_t* ntparam = new Float_t[numnames0 + numnames1 + 1]; // +1 because of first var = time
   reftime.SetSec(frame->GTimeS);
   reftime.SetNsec(frame->GTimeN);
   vnt->SetLocalTime(0);
   vnt->SetLeapS(frame->ULeapS);
   
// Fill the ntuple
   
   int nframesread=1;
   while (frame) {
      ivar = 0;
//   First, the time;
      ntparam[ivar] = (Float_t)((Double_t)(frame->GTimeS) + 1.e-9 * frame->GTimeN - reftime.GetTimeD());
      ivar++;
//   Next, the strictly defined parameters
      for (i=0; i<numnames; i++) {
         if (smsvalname[i]) {
            sererr = FrSerDataGet(frame, smsstaname[i], smsvalname[i], &smsval);
            if (sererr != 0) {
               ntparam[ivar] = 0;
            } else {
               ntparam[ivar] = smsval;
            }
            ivar++;
         }
      }
//   Next, the case where all the vars of an SMS are taken
      for (i=0; i<numnames1; i++) {
         sererr = FrSerDataGet(frame, smsstaname1[i], smsvalname1[i], &smsval);
         if (sererr != 0) {
            ntparam[ivar] = 0;
         } else {
            ntparam[ivar] = smsval;
         }
         ivar++;
      }
      
      vnt->Fill(ntparam);
      if (!(nframesread%1000)) printf("Extract SMS : %d frames readn",nframesread);

// See if the time step between frames is the lowest one. There must be at least
// some order in the frames to make it work.
      double currentstep = (double)(frame->GTimeS + 1e-9*(double)(frame->GTimeN)) - oldstarttime;
      if (currentstep < loweststep) loweststep = currentstep;
      oldstarttime = (double)(frame->GTimeS + 1e-9*(double)(frame->GTimeN));
      
// Load next frame and process it;
      frame = GetNextFrameB();
      nframesread++;
      if (frame) {
         Double_t tmpstart = (Double_t)(frame->GTimeS) + 1.e-9 * frame->GTimeN;
         if (tmpstart > start + length) frame = 0;
      }
   }
   
// Update the VNTuple parameters
   vnt->SetGPSStart(reftime.GetSec(),reftime.GetNsec());
   vnt->SetStep(loweststep);
   
   delete [] listofnames;
   delete [] smsstaname;
   delete [] smsvalname;
   for (i=0; i<numnames1; i++) {
      if (smsstaname1[i]) delete [] smsstaname1[i];
      if (smsvalname1[i]) delete [] smsvalname1[i];
   }
   delete [] smsstaname1;
   delete [] smsvalname1;
   delete [] ntparam;
   return vnt;
}

//______________________________________________________________________________
 FrVect* VFrameChannel::ExtractSMSVectR(char* name0, Double_t start, Double_t length)
{
//   Builds a new FrVect and fills it with SMS data from the database
//   The SMS data starts at time "start" and has a length "length".
//   start time is considered by reference to the reference time
//   listofnames is the name of the SMS station/value one needs
//   to extract. The format is "stationname.valuename", for example
//   TiServer.rtt2 (value of round trip time 2 for timing server)
   
   return ExtractSMSVect(name0,start + GetRefTime(),length);
}

//______________________________________________________________________________
 FrVect* VFrameChannel::ExtractSMSVect(char* name0, Double_t start, Double_t length)
{
//   Builds a new FrVect and fills it with SMS data from the database
//   The SMS data starts at time "start" and has a length "length".
//   listofnames is the name of the SMS station/value one needs
//   to extract. The format is "stationname.valuename", for example
//   TiServer.rtt2 (value of round trip time 2 for timing server)

   char* smsstaname;
   char* smsvalname;
   char* names;
   Int_t ll;
   Int_t i;
   char* valp;
   FrameH* frame;
   Long_t sererr;
   Double_t smsval;
   FrVect* vect;
   double timax;

   TString point = ".";

// The lowest frame time and step are determined for the vector
   VGPSTime reftime(0,0);  // reference time = time of the first frame after start
   Double_t loweststep = 100000000000.;
   Double_t oldstarttime = 0.;

   if (!GetFrameInfoDB()) {
      Warning("ExtractSMSVect","Data base not opened");
      return 0;
   }
   
// Extracts the desired name of station/value

   ll = strlen(name0);
   names = new char[ll+1];
   strcpy(names, name0);
   smsstaname = names;
   smsvalname = 0;
//   separate station and value
   valp = strstr(names,".");
   if (valp) {
      valp[0] = 0;
      smsvalname = valp+1;
   }

// Prepare the temporary arrays
   int arraysize=10000;    // start size of array. will be expanded if necessary
   TArrayD valarray(arraysize);
   TArrayD timearray(arraysize);
   
// Get the first vector
   frame = GetNextFrameB(start);
   if (!frame) return 0;
   
   reftime.SetSec(frame->GTimeS);
   reftime.SetNsec(frame->GTimeN);
   
// Read the frames
   timax = 0;   // no need for timin since it is always 0
   int nframesread=0;
   while (frame) {
//   First, the time;
      timearray[nframesread] = (Double_t)(frame->GTimeS) + 1.e-9 * frame->GTimeN - reftime.GetTimeD();
      if (timearray[nframesread] > timax) timax = timearray[nframesread];
//   Next, value of station asked for
      sererr = FrSerDataGet(frame, smsstaname, smsvalname, &smsval);
      if (sererr != 0) {
         valarray[nframesread] = 0;
      } else {
         valarray[nframesread] = smsval;
      }
      
      if (!(nframesread%1000)) printf("Extract SMS vect: %d frames readn",nframesread);

// See if the time step between frames is the lowest one. There must be at least
// some order in the frames to make it work.
      double currentstep = (double)(frame->GTimeS + 1e-9*(double)(frame->GTimeN)) - oldstarttime;
      if (currentstep < loweststep) loweststep = currentstep;
      oldstarttime = (double)(frame->GTimeS + 1e-9*(double)(frame->GTimeN));
      
// Load next frame and process it;
      frame = GetNextFrameB();
      nframesread++;
      if (frame) {
         Double_t tmpstart = (Double_t)(frame->GTimeS) + 1.e-9 * frame->GTimeN;
         if (tmpstart > start + length) frame = 0;
      }
      
// Grow arrays if necessary
      if (nframesread>arraysize) {
         arraysize *=2;   // double the array size
         valarray.Set(arraysize);
         timearray.Set(arraysize);  // this is non destructive
      }
   }

// Build the FrVect and fill it with the extracted values
   int nsteps = (int)(timax/loweststep)+1; // timin is always 0
   vect = FrVectNew1D(name0, FR_VECT_8R, nsteps, loweststep, "time [s]", "");
#if FR_VERS<6000
   vect->GTimeS = reftime.GetSec();
   vect->GTimeN = reftime.GetNsec();
#else
   vect->GTime = reftime.GetTimeD();
#endif
   
   for (i=0;i<nframesread;i++) {
      int istep = (int)((timearray[i] + loweststep/2)/loweststep);
      vect->dataD[istep] = valarray[i];
   }
      
   delete [] names;
   return vect;
}

//______________________________________________________________________________
 void VFrameChannel::Print(Option_t* opt)
{
// Prints information about the database and it's contents
// option :
//     "full" : prints all the database info. VERY LONG. mainly for test
//     "conditions" : prints only conditions names

   FrameH* firstframe;
   TString sopt = opt;
   sopt.ToLower();
   printf("  ___________________________  n");
   printf(" |                           | n");
   printf(" | Frame channel information | n");
   printf(" |___________________________| n");
   if (GetFrameInfoDB()) {
      
//    Gets the first frame
      printf("n  First frame in Info DB start time (GPS) : %14.4fn",GetStart());
      printf("n  Last frame in Info DB end time (GPS)    : %14.4fn",GetEnd());
      printf("  ===================================================n");
      GetFrameInfoDB()->Print(opt);
      printf("n\n Dump of the first frame n");
      printf(    " _______________________n\n");

      firstframe = GetNextFrameB(GetStart());
      FrameDump(firstframe, stdout,2);
   } else {
      printf("nNo connected information databasen\n");
   }
}

//______________________________________________________________________________
 void VFrameChannel::DrawCondition(const char* selexp, const char* selection, Option_t* option, Double_t start, Double_t length)
{
//   Draws expression selexp for conditions defined in the info database
//   with respect to time.
//
//   selexp is an expression (formula) referencing a combination of conditions
//   Example:
//      selexp = trig.amp   simplest case: draw a plot of amplitude of 
//                                          condition named trig
//             = sqrt(trig.p)            : draw distribution of sqrt(trig.p)
//             = x*y/z                   : where x, y and z are conditions
//                                         defined in the database
//   Note that selexp may contain a selection.
//   example, if selexp= x*(y<0), the value plotted will be x if y<0
//   and will be 0 otherwise.
// 
//   selection is an expression with a combination of the conditions.
//   In a selection all the C++ operators are authorized.
//   The value corresponding to the selection expression is used as a veto 
//   to plot the points. If it is not 0, the point is plotted.
//   The value returned is not relevant, only relevant is
//   (selection==0) -> point skipped or (selection!=0) -> point plotted
//
//   Examples:
//       selection1 = "x<y && sqrt(z)>3.2"
//       selection2 = "(x+y)*(sqrt(z)>3.2"
//   selection1 returns a value = 0 or 1
//   selection2 returns a value  = x+y if sqrt(z)>3.2
//              returns a value  = 0 otherwise.
//   Warning : if there is no selection (selection=""), selexp itself
//             will be taken as selection expression, i.e. only points where
//             selexp != 0 will be plotted
// 
//   option is the drawing option
//       see TGraph::Draw for the list of all drawing options.
// 
//   start is the start time of the first conditions to process
//      (default is beginning of database values)
//   length is the length in time of the data to process (default is all data)
// Draws a condition with respect to time
   
   if (GetFrameInfoDB()) GetFrameInfoDB()->Draw(selexp, selection, option, start, length);
}

//______________________________________________________________________________
 VVirtualFrameChannelPlayer* VFrameChannel::GetPlayer()
{
// Load the VFrameChannelPlayer (if not already done)

   if (mPlayer) return mPlayer;
   mPlayer = VVirtualFrameChannelPlayer::FrameChannelPlayer(this);
   return mPlayer;
}

//______________________________________________________________________________
 Int_t VFrameChannel::MakeSelector(const char *selector)
{
//*-*-*-*-*-*-*Generate skeleton selector class for this Frame Channel*-*-*-*-*-*-*
//*-*          =======================================================
//
//   The following files are produced: selector.h and selector.C
//   if selector is NULL, selector will be "MyFrameAnalysis".
//
//   The generated code in selector.h includes the following:
//      - Identification of the original frame channel and Input info database
//      - Definition of selector class (data and functions)
//      - the following class functions:
//         - constructor and destructor
//         - void    Begin(VFrameChannel *fc)
//         - void    Init(VFrameChannel *fc)
//         - Bool_t  ProcessCut(FrameH* frame);
//         - Bool_t  ProcessFrame(FrameH* frame);
//         - Bool_t  ProcessVect(int nbvect, FrVect** invects, FrVect* ouvect);
//         - void    Terminate
//
//   The class selector derives from VSelector.
//   The generated code in selector.C includes empty functions defined above:
//
//      - connect your frame channel (eg: fc = new VFrameChannel("infoDB.root");)
//      - fc->MakeClass("MyClass");
//    Where MyClass.h, MyClass.C the name of the files created by this function.
//   In a vega session, you can do:
//      vega > fc->Process("select.C")
//

   return MakeClass(selector,"","selector");
}

//______________________________________________________________________________
 Int_t VFrameChannel::MakeClass(const char *classname, const char* cond, Option_t *option)
{
//*-*-*-*-*-*-*Generate skeleton analysis class for this Frame Channel*-*-*-*-*-*-*
//*-*          =======================================================
//
//   The following files are produced: classname.h and classname.C
//   if classname is NULL, classname will be "MyFrameAnalysis".
//
//   When the option "selector" is specified, the function generates the
//   selector class described in VFrameChannel::MakeSelector.
//
//   The generated code in classname.h includes the following:
//      - Identification of the original frame channel and input conditions
//      - Definition of analysis class (data and functions)
//      - the following class functions:
//         -constructor (connecting by default the frame channel)
//         -Init(VFrameChannel *fc) to initialize a new VFrameChannel
//
//   The generated code in classname.C includes only the main
//   analysis function Loop.
//
//   To use this function:
//      - connect your frame channel (eg: fc = new VFrameChannel("infoDB.root");)
//      - fc->MakeClass("MyClass");
//    Where MyClass.h, MyClass.C the name of the files created by this function.
//   In a vega session, you can do:
//      Root > .L MyClass.C
//      Root > MyClass t
//      Root > t.Loop();       // Loop on the frames in the frame channel
//

   GetPlayer();
   if (!mPlayer) return 0;
   return mPlayer->MakeClass(classname,cond,option);
}

//______________________________________________________________________________
 const char* VFrameChannel::GetProcessList()
{
// Get list of channels/vectors to be processed
   GetPlayer();
   if (!mPlayer) return 0;
   return mPlayer->GetProcessList();
}

//______________________________________________________________________________
 Double_t VFrameChannel::GetProcessStart()
{
// Get start time of processing
   GetPlayer();
   if (!mPlayer) return 0;
   return mPlayer->GetProcessStart();
}

//______________________________________________________________________________
 Double_t VFrameChannel::GetProcessLength()
{
// Get length (in time) for the processing
   GetPlayer();
   if (!mPlayer) return 0;
   return mPlayer->GetProcessLength();
}

//______________________________________________________________________________
 Double_t VFrameChannel::GetProcessStep()
{
// Get time step of the processing
   GetPlayer();
   if (!mPlayer) return 0;
   return mPlayer->GetProcessStep();
}

//______________________________________________________________________________
 void VFrameChannel::SetProcessList(const char* list)
{
// Set list of channels/vectors to be processed
   GetPlayer();
   if (!mPlayer) return;
   mPlayer->SetProcessList(list);
}

//______________________________________________________________________________
 void VFrameChannel::SetProcessStart(Double_t start)
{
// Set start time of processing
   GetPlayer();
   if (!mPlayer) return;
   mPlayer->SetProcessStart(start);
}

//______________________________________________________________________________
 void VFrameChannel::SetProcessLength(Double_t length)
{
// Set length (in time) for the processing
   GetPlayer();
   if (!mPlayer) return;
   mPlayer->SetProcessLength(length);
}

//______________________________________________________________________________
 void VFrameChannel::SetProcessStep(Double_t step)
{
// Set time step of the processing
   GetPlayer();
   if (!mPlayer) return;
   mPlayer->SetProcessStep(step);
}

//______________________________________________________________________________
 Int_t VFrameChannel::Process(const char *filename, const char* cond,Option_t *option)
{
//*-*-*-*-*-*-* Process data provided by this Frame Channel *-*-*-*-*-*-*
//              ===========================================
   GetPlayer();
   if (mPlayer) return mPlayer->Process(filename,0,1e20,cond,option);
   else         return -1;
}

//______________________________________________________________________________
 Int_t VFrameChannel::Process(VSelector *selector, const char* cond,Option_t *option)
{
//*-*-*-*-*-*-* Process data provided by this Frame Channel *-*-*-*-*-*-*
//              ===========================================
   GetPlayer();
   if (mPlayer) return mPlayer->Process(selector,0,1e20,cond,option);
   else         return -1;
}

//______________________________________________________________________________
 Int_t VFrameChannel::Process(const char *filename, double starttime, double length, const char* cond,Option_t *option)
{
   GetPlayer();
   if (mPlayer) {
      SetProcessStart(starttime);
      SetProcessLength(length);
      return mPlayer->Process(filename,starttime,length,cond,option);
   }
   else         return -1;
}

//______________________________________________________________________________
 Int_t VFrameChannel::Process(VSelector *selector, double starttime, double length, const char* cond,Option_t *option)
{
   GetPlayer();
   if (mPlayer) {
      SetProcessStart(starttime);
      SetProcessLength(length);
      return mPlayer->Process(selector,starttime,length,cond,option);
   }
   else         return -1;
}

//______________________________________________________________________________
 Int_t VFrameChannel::ProcessVect(const char *filename,const char* vectlist, const char* cond,Option_t *option)
{
   GetPlayer();
   if (mPlayer) {
      SetProcessList(vectlist);
      return mPlayer->Process(filename,0,1e20,cond,option);
   }
   else         return -1;
}

//______________________________________________________________________________
 Int_t VFrameChannel::ProcessVect(VSelector *selector,const char* vectlist, const char* cond,Option_t *option)
{
   GetPlayer();
   if (mPlayer) {
      SetProcessList(vectlist);
      return mPlayer->Process(selector,0,1e20,cond,option);
   }
   else         return -1;
}

//______________________________________________________________________________
 Int_t VFrameChannel::ProcessVect(const char *filename, double starttime, double length, const char* vectlist, const char* cond,Option_t *option)
{
   GetPlayer();
   if (mPlayer) {
      SetProcessList(vectlist);
      SetProcessStart(starttime);
      SetProcessLength(length);
      return mPlayer->Process(filename,starttime,length,cond,option);
   }
   else         return -1;
}

//______________________________________________________________________________
 Int_t VFrameChannel::ProcessVect(VSelector *selector, double starttime, double length,const char* vectlist, const char* cond,Option_t *option)
{
   GetPlayer();
   if (mPlayer) {
      SetProcessList(vectlist);
      SetProcessStart(starttime);
      SetProcessLength(length);
      return mPlayer->Process(selector,starttime,length,cond,option);
   }
   else         return -1;
}

//______________________________________________________________________________
 void VFrameChannel::StartViewer(int mode)
{
   GetPlayer();
   if (mPlayer) mPlayer->StartViewer(mode);
}

//______________________________________________________________________________
 double VFrameChannel::GetViewerTime() {
   if (gDataViewer) return gDataViewer->GetCurrentTime();
   return 0;
}


- ROOT page - VEGA page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to , or contact with any questions or problems regarding ROOT or VEGA.