// Author: Andrew M. Rogers, NSCL 07/01/2006
// Original Design: Daniel Bazin, NSCL
//* Copyright (C) 2006-2008 Andrew M. Rogers

#include <fstream>
#include <stdio.h>
#include <iostream>

#include <TChain.h>
#include <TTree.h>
#include <TFile.h>
#include <TEventList.h>
#include <TNamed.h>
#include <time.h>
#include <sys/stat.h>

#ifndef __PACKETID_H
#define __PACKETID_H
#include "packetID.h"
#endif

#include "TTarget.h"
#include "TExperiment.h"


ClassImp(TExperiment);
ClassImp(TBufferHeader);

////////////////////////////////////////////////////////////////////////////////
/* BEGIN_HTML
<p> The TExperiment provides the structure for holding a typical           
 experiment at the NSCL.  For each device a class is constructed.       
 For example there is a class that represents HiRA (THiRA) and the      
 S800 (TS800).  An instance of  these classes is then instanciated in   
 TExperiment.</p>
                                                          
 <p>TExperiment is then a contruct that describes the entire experiment.   </p
                                                                        
 <p>Run information can be displayed using the command,                    
             tree->GetUserInfo()->Print()                               
 This information can also be stored and used in any processing         
 scripts written for this tree.  For example, to get the number of times 
 the run was paused we could do,                                        
   Char_t *ch;                                                          
   ch = (Char_t*)tree->GetUserInfo->FindObject("Pauses")->GetTitle();   
 </p>                                                                    
<h3><a name="unpack">I. Unpacking</a></h3>

<h3><a name="vars">II. Important Data Members</a></h3>

<h3><a name="examples">III. Examples</a></h3>


END_HTML */
////////////////////////////////////////////////////////////////////////////////


//______________________________________________________________________________
TExperiment::TExperiment(const char *name) {
  // -- Default constructor.
  // If a sub-class inherits from TObject and you do not want the fBits and 
  // fUniqueID to be streamed out to the root file then it is advisable to 
  // add the line,
  //              MyClass::Class()->IgnoreTObjectStreamer();
  // This will save, in some cases, a significant amount of disk space when 
  // writing a root file.

  fName = name;

  TBufferHeader::Class()->IgnoreTObjectStreamer();
  #ifdef EXPERIMENT_03045
  TNamed::Class()->IgnoreTObjectStreamer();
  #endif
  #ifdef MCPCLASS_FLAG
  TMcp::Class()->IgnoreTObjectStreamer();
  TMcpDet::Class()->IgnoreTObjectStreamer();
  mcp    = new TMcp();
  #endif
  #ifdef HIRACLASS_FLAG
  THiRA::Class()->IgnoreTObjectStreamer();
  TTele::Class()->IgnoreTObjectStreamer();
  THiRASiDet::Class()->IgnoreTObjectStreamer();
  TDelta::Class()->IgnoreTObjectStreamer();
  TFront::Class()->IgnoreTObjectStreamer();
  TBack::Class()->IgnoreTObjectStreamer();
  TCsI::Class()->IgnoreTObjectStreamer();
  THiRAPixel::Class()->IgnoreTObjectStreamer();
  hira   = new THiRA();
  #endif
  #ifdef S800CLASS_FLAG
  TS800::Class()->IgnoreTObjectStreamer();
  TS800Scintillator::Class()->IgnoreTObjectStreamer();
  TS800Crdc::Class()->IgnoreTObjectStreamer();
  TS800CrdcPads::Class()->IgnoreTObjectStreamer();
  TS800CrdcCalc::Class()->IgnoreTObjectStreamer();
  TS800FpTrack::Class()->IgnoreTObjectStreamer();
  TS800ImTrack::Class()->IgnoreTObjectStreamer();
  TS800Map::Class()->IgnoreTObjectStreamer();
  TS800IonChamber::Class()->IgnoreTObjectStreamer();
  TS800Tppac::Class()->IgnoreTObjectStreamer();
  TS800Trigger::Class()->IgnoreTObjectStreamer();
  TS800TimeOfFlight::Class()->IgnoreTObjectStreamer();
  s800   = new TS800();
  #endif
  #ifdef FOURPICLASS_FLAG
  TFourPi::Class()->IgnoreTObjectStreamer();
  fourpi = new TFourPi();
  #endif
  #ifdef EPICSCLASS_FLAG
  TEpics::Class()->IgnoreTObjectStreamer();
  epics  = new TEpics();
  #endif
  #ifdef SCALERCLASS_FLAG
  TScaler::Class()->IgnoreTObjectStreamer();
  TScalerCh::Class()->IgnoreTObjectStreamer();
  scalers = new TScaler();
  #endif

  // Allocate memory for objects that will be written to UserInfo list.
  analysisState = new TNamed("Analysis State","-1");
  expNumber     = new TNamed("Experiment Number","unknown");
  runTitle      = new TNamed("Run Title","");
  runNumber     = new TNamed("Run Number","");
  elapsedTime   = new TNamed("Elapsed Run Time","");
  dateCreated   = new TNamed("Run Creation Date","");
  dateEnded     = new TNamed("Run End Date","");
  timeCreated   = new TNamed("Run Creation Time","");
  timeEnded     = new TNamed("Run End Time","");
  nPauses       = new TNamed("Pauses","");
  nResumes      = new TNamed("Resumes","");
  nBuffers      = new TNamed("Number of buffers read","");

  nTotalEntities      = new TNamed("Total Entity Count","");
  nTotalType1Entities = new TNamed("Total Type1 (Data) Entity Count","");
  nTotalWords         = new TNamed("Total Word Count","");
  nTotalType1Words    = new TNamed("Total Type1 (Data) Word Count","");
  avgEventRate        = new TNamed("Average Event Rate","");
  avgType1EventRate   = new TNamed("Average Type1 (Data) Event Rate","");
  avgWordRate         = new TNamed("Average Word Rate","");
  avgType1WordRate    = new TNamed("Average Type1 (Data) Word Rate","");
  evtSize             = new TNamed("Event File Size","");
  rootSize            = new TNamed("ROOT File Size","");


  evtFilePath  = "./";
  rootFilePath = "./";

  // Allocate memory for detector classes.
  header = new TBufferHeader();
  // Initialize the target object array.
  fTargets = new TObjArray(10);



  // By default do not fill anything.
  kHiraFill    = kFALSE;
  kHiraCsIFill = kFALSE;
  kMcpFill     = kFALSE;
  kS800Fill    = kFALSE;
  kFourPiFill  = kFALSE;
  kEpicsFill   = kFALSE;
  kScalerFill  = kFALSE;
  kElogFill    = kFALSE;

  fGManager = new TGeoManager("expManager","NSCL Experiment Geometry Manager");

}

//______________________________________________________________________________
TExperiment::~TExperiment()
{
  // --  Destructor
  //

  delete header;
  delete fTargets;
  #ifdef MCPCLASS_FLAG
  delete mcp;
  #endif
  #ifdef HIRACLASS_FLAG
  delete hira;
  #endif
  #ifdef S800CLASS_FLAG
  delete s800;
  #endif
  #ifdef FOURPICLASS_FLAG
  delete fourpi;
  #endif
  #ifdef EPICSCLASS_FLAG
  delete epics;
  #endif
  #ifdef SCALERCLASS_FLAG
  delete scalers;
  #endif
}

//______________________________________________________________________________
void TExperiment::AddTarget(const char *name, const char *title, 
			    Int_t ladder, Int_t ladderPos, Double_t thickness,
			    Int_t Z, Int_t A)
{
  // -- Add a target to the experimental setup.
  //

  TTarget *tmpTarget = new TTarget(name,title,fGManager,ladder,ladderPos,thickness,Z,A);
  //  tmpTarget->fGeomTar = fGManager;
  //  tmpTarget->Print();
  fTargets->Add(tmpTarget);
  //  fTargets->Add(new TTarget(name,title,ladder,ladderPos,thickness,Z,A));
  printf("* Added Target %s to ladder %i at position %i.\n",tmpTarget->GetName(),
	 tmpTarget->GetLadder(),tmpTarget->GetLadderPos());
  
}


//______________________________________________________________________________
void TExperiment::Calculate() 
{
  // -- Call to all Calculate methods.
  //

  #ifdef MCP_CLASS_FLAG
  if(kMcpFill)    mcp->Calculate();
  #endif
  #ifdef HIRACLASS_FLAG
  if(kHiraFill)   hira->Calculate();
  #endif
  #ifdef S800CLASS_FLAG
  if(kS800Fill)   s800->Calculate();
  #endif
  #ifdef FOURPICLASS_FLAG
  if(kFourPiFill) fourpi->Calculate();
  #endif
  #ifdef EPICSCLASS_FLAG
  if(kEpicsFill)  epics->Calculate();
  #endif
  #ifdef SCALERCLASS_FLAG
  #endif
}

//______________________________________________________________________________
void TExperiment::Calibrate() 
{
  // -- Calls all Calibrate methods.
  //

  #ifdef MCP_CLASS_FLAG
  if(kMcpFill)    mcp->Calibrate();
  #endif
  #ifdef HIRACLASS_FLAG
  if(kHiraFill)   hira->Calibrate();
  #endif
  #ifdef S800CLASS_FLAG
  if(kS800Fill)   s800->Calibrate();
  #endif
  #ifdef FOURPICLASS_FLAG
  if(kFourPiFill) fourpi->Calibrate();
  #endif
  #ifdef EPICSCLASS_FLAG
  if(kEpicsFill)  epics->Calibrate();
  #endif  
  #ifdef SCALERCLASS_FLAG
  #endif
}

//______________________________________________________________________________
void TExperiment::Clear(Option_t *) 
{
  // -- Clear all member classes.
  //

  header->Clear();
  #ifdef MCPCLASS_FLAG
  if(kMcpFill)    mcp->Clear();
  #endif
  #ifdef HIRACLASS_FLAG
  if(kHiraFill)   hira->Clear();
  #endif
  #ifdef S800CLASS_FLAG
  if(kS800Fill)   s800->Clear();
  #endif
  #ifdef FOURPICLASS_FLAG
  if(kFourPiFill) fourpi->Clear();
  #endif
  #ifdef EPICSCLASS_FLAG
  if(kEpicsFill)  epics->Clear();
  #endif
  #ifdef SCALERCLASS_FLAG
  if(kScalerFill) scalers->Clear();
  #endif
}

//______________________________________________________________________________
void TExperiment::CreateFolders()
{
  // -- Create all initial folders.
  // Folders can be useful for storing global constants, calibration file data,
  // run information . . . among other things.
  //
  // This method should call all sub-class CreateFolders methods.

  f_constants.SetNameTitle("Constants","CONSTANTS");
  
  f_constants.Write();
  
  #ifdef MCPCLASS_FLAG
  //  mcp->CreateFolders();
  #endif
  #ifdef HIRACLASS_FLAG
  hira->CreateFolders();
  #endif
}


//______________________________________________________________________________
void TExperiment::DumpClassInfo()
{
  // -- Output of currently built and fillable classes.
  //

  printf("**********************DUMPING CLASS MEMBERS INFO*****************************\n");
  
  Bool_t kBuilt=kFALSE;


  #ifdef HIRACLASS_FLAG 
  kBuilt=kTRUE;
  #endif
  printf("* THiRA Class Built . . .      [%u] \t Filled . . . [%u]\n",kBuilt,kHiraFill);
  kBuilt=kFALSE;
  #ifdef HIRACSICLASS_FLAG 
  kBuilt=kTRUE;
  #endif
  printf("* THiRACsI Class Built . . .   [%u] \t Filled . . . [%u]\n",kBuilt,kHiraCsIFill);
  kBuilt=kFALSE;
  #ifdef MCPCLASS_FLAG 
  kBuilt=kTRUE;
  #endif
  printf("* TMcp Class Built . . .       [%u] \t Filled . . . [%u]\n",kBuilt,kMcpFill);
  kBuilt=kFALSE;
  #ifdef S800CLASS_FLAG 
  kBuilt=kTRUE;
  #endif
  printf("* TS800 Class Built . . .      [%u] \t Filled . . . [%u]\n",kBuilt,kS800Fill);
  kBuilt=kFALSE;
  #ifdef FOURPICLASS_FLAG 
  kBuilt=kTRUE;
  #endif
  printf("* TFourPi Class Built . . .    [%u] \t Filled . . . [%u]\n",kBuilt,kFourPiFill);
  kBuilt=kFALSE;
  #ifdef EPICSCLASS_FLAG 
  kBuilt=kTRUE;
  #endif
  printf("* TEpics Class Built . . .     [%u] \t Filled . . . [%u]\n",kBuilt,kEpicsFill);
  kBuilt=kFALSE;
  #ifdef SCALERCLASS_FLAG 
  kBuilt=kTRUE;
  #endif
  printf("* TScaler Class Built . . .    [%u] \t Filled . . . [%u]\n",kBuilt,kScalerFill);
  kBuilt=kFALSE;
  #ifdef ELOGCLASS_FLAG 
  kBuilt=kTRUE;
  #endif
  printf("* TElog Class Built . . .      [%u] \t Filled . . . [%u]\n",kBuilt,kElogFill);
  kBuilt=kFALSE;

}


//______________________________________________________________________________
void TExperiment::DumpInfo()
{
  // -- Output all run information.
  // This output should include all information in the UserInfoList of the current TTree.
  // In addition scaler values are output along with any quantities calculated with these
  // values.

  ofstream dumpFile("RUNDUMP.dat",ios::out);
  Char_t outC[2000];

  printf("***************************DUMPING RUN INFO**********************************\n");
  
  // Dump UserInfo
  fChain->GetUserInfo()->Print();
  TNamed *namedTmp = (TNamed*)fChain->GetUserInfo()->FindObject("Elapsed Run Time");
  Double_t eTime   = atof(namedTmp->GetTitle());
  TNamed *dumpN;
  TIter next(fChain->GetUserInfo());
  while((dumpN = (TNamed *)next())){
    sprintf(outC,"%-35.35s \t%s\n",dumpN->GetName(),dumpN->GetTitle());
    dumpFile << outC;
  }
  dumpFile.close();

  #ifdef SCALERCLASS_FLAG
  if(kScalerFill) scalers->DumpScalers("RUNDUMP.dat","UPDATE");
  #endif
  #ifdef HIRACLASS_FLAG
  
  

  #endif


}


//______________________________________________________________________________
void TExperiment::InitClass() 
{
  // -- Initialize the class and sub-classes.
  // The InitClass method of all member classes should be called here.  This
  // method is responsible for setting all the defaults of the member classes.

  #ifdef MCPCLASS_FLAG
  mcp->InitClass();
  #endif
  #ifdef HIRACLASS_FLAG
  hira->InitClass();
  #endif
  #ifdef S800CLASS_FLAG
  s800->InitClass();
  #endif
  #ifdef FOURPICLASS_FLAG
  fourpi->InitClass();
  #endif
  #ifdef EPICSCLASS_FLAG
  epics->InitClass();
  #endif
  #ifdef SCALERCLASS_FLAG
  scalers->InitClass();
  #endif
}


//______________________________________________________________________________
void TExperiment::InitTree(TTree *itree) 
{
  // -- Initialze a tree.
  // Set the branch addresses for all members of all classes.
  //
  // IMPORTANT:  This method assumes that classes are created using the object oriented
  //             method described in the ROOT Users Manual or that the corresponding 
  //             class has a valid InitTree method.

  fChain = itree;
  
  #ifdef MCPCLASS_FLAG
  //  if(kMcpFill)    {fChain->SetBranchAddress("mcp",&mcp); mcp->InitTree(fChain);}
  if(kMcpFill)    mcp->InitTree(fChain);
  #endif
  #ifdef HIRACLASS_FLAG
  //  if(kHiraFill)  {b_hira->SetAddress(&hira); hira->InitTree(fChain);}
  if(kHiraFill)   hira->InitTree(fChain);
  #endif
  #ifdef S800CLASS_FLAG
  //  if(kS800Fill)   {fChain->SetBranchAddress("s800",&s800); s800->InitTree(fChain);}
  if(kS800Fill)   s800->InitTree(fChain);
  #endif
  #ifdef FOURPICLASS_FLAG
  if(kFourPiFill) {fChain->SetBranchAddress("fourpi",&fourpi); fourpi->InitTree(fChain);
  #endif
  #ifdef EPICSCLASS_FLAG
  if(kEpicsFill){
    if(strcmp(fChain->ClassName(),"TChain")!=0){
      epics->InitTree((TTree*)fChain->GetDirectory()->FindObjectAny("stateVarT"));
    }
  }
  #endif
  #ifdef SCALERCLASS_FLAG
  if(kScalerFill){
    if(strcmp(fChain->ClassName(),"TChain")!=0){
      scalers->InitTree((TTree*)fChain->GetDirectory()->FindObjectAny("scalerT"));
    }
    scalers->fEChain = fChain;
  }
  #endif
}

//______________________________________________________________________________
Bool_t TExperiment::ConvertEvtFile(Char_t *evtFile, Char_t *rootFile,Option_t *nBufs)
{
  // -- Convert an event file to a ROOT file.
  // An event file is opened for reading and a root file created for writing.
  // A buffer is read and each entitiy in the buffer is looped over.  The buffer
  // header is read and the buffer type is determined.
  //
  // NOTE:  If the root file already exist it will be overwritten!!!
  // 
  // For additional information on the buffer structure please see,
  // http://docs.nscl.msu.edu
  //
  
  UShort_t *p;                             // This is the pointer to the buffer.
  UShort_t buffer[4096],
    packetTag;

  Long64_t fileSize;                       // Size of the evt file in bytes.
  Long64_t nBuf2Read;                      // Number of buffers to unpack.
  Int_t    counter = 0 ;                   // Counter for updating progress.
  Float_t  cent;                           // Percent done.
  time_t   start;                          // Start conversion time.
  time_t   now;                            // Current time.
  Char_t   tempChar[500],
    pathE[500],
    pathR[500];

  Int_t    fPauses  = 0,                   // Number of times run was paused.
           fResumes = 0;                   // Number of times run was resumed.
  Bool_t   fRunEnd  = kFALSE;              // Did we find an end run buffer?
  Char_t   cBuf[200];


  // Set the number of buffers to unpack.
  nBuf2Read = (Long64_t)atoi(nBufs);

  // Set the full path for the evt file.
  memset(tempChar,'\0',500);
  memset(pathE,'\0',500);
  strcat(pathE,evtFilePath);
  strcat(pathE,evtFile);
  memset(pathR,'\0',500);
  strcat(pathR,rootFilePath);
  strcat(pathR,rootFile);

  // Start the counter.
  time(&start);
  
  // Open evt file for reading.
  ifstream file(pathE,ios::in | ios::binary);
  if(!file.is_open()){ printf("File could not be opened!\n"); return kFALSE;}

  file.seekg(0,ios::end);
  fileSize = file.tellg();
  cout << "Evt File size:        " << fileSize << " bytes" << endl;

  file.seekg(0,ios::beg);
  cout << "At beginning of file: " << pathE << endl;

  // Open ROOT file for writing.
   TFile *f = new TFile(pathR,"RECREATE");

  if (f->IsZombie()) {
    cout << "Error opening file " << pathR << endl;
    exit(-1);
  }

  // We must be careful here.  The file must be open before we create the tree.
  sprintf(tempChar,"E%s",expNumber->GetTitle());
  TTree *type0Tree = new TTree("headerT",  "Buffer Header Tree",2);
  TTree *type1Tree = new TTree(tempChar,   "Event Data Type:  TExperiment Tree",2);
  TTree *type2Tree = new TTree("scalerT",  "Scaler Type Tree",2);
  TTree *type3Tree = new TTree("snapshotT","Snapshot Type Tree",2);
  TTree *type4Tree = new TTree("stateVarT","Documentation:  State Variables Tree",2);
  TTree *type5Tree = new TTree("runVarT",  "Documentation:  Run Variables Tree",2);
  TTree *type6Tree = new TTree("packetT",  "Documentation:  Packet Types Tree",2);

  // Set the trees to compatability mode.
  //   type0Tree->SetMakeClass(1);
  //   type1Tree->SetMakeClass(1);
  //   type2Tree->SetMakeClass(1);
  //   type3Tree->SetMakeClass(1);
  //   type5Tree->SetMakeClass(1);
  //   type6Tree->SetMakeClass(1);


  // Create the branches.
  type0Tree->Branch("Header","TBufferHeader",&header,32000);
  //   type1Tree->Branch("Header","TBufferHeader",&header,32000);
  //   type2Tree->Branch("Header","TBufferHeader",&header,32000);
  //   type3Tree->Branch("Header","TBufferHeader",&header,32000);
  //   type4Tree->Branch("Header","TBufferHeader",&header,32000);
  //   type5Tree->Branch("Header","TBufferHeader",&header,32000);
  //   type6Tree->Branch("Header","TBufferHeader",&header,32000);
  #ifdef MCPCLASS_FLAG
  if(kMcpFill)    type1Tree->Branch("mcp","TMcp",&mcp); mcp->InitBranch(type1Tree,"Raw");
  #endif
  #ifdef HIRACLASS_FLAG
  if(kHiraFill)   hira->InitBranch(type1Tree,"Raw"); //hira->ClearErr();
  #endif
  #ifdef S800CLASS_FLAG
  if(kS800Fill)   type1Tree->Branch("s800","TS800",&s800);
    #if TS800_OP_TPPAC==0
    type1Tree->SetBranchStatus("tppac*",0);
    #endif
    #if TS800_OP_TCRDC==0
    type1Tree->SetBranchStatus("tcrdc*",0);
    #endif
    #if (TS800_OP_TPPAC==0 && TS800_OP_TCRDC==0)
    type1Tree->SetBranchStatus("imTrack*",0);
    #endif
  #endif
  #ifdef FOURPICLASS_FLAG
  if(kFourPiFill) fourpi->InitBranch(type1Tree,TFOURPI_OP_CDISABLE);
  #endif
  #ifdef EPICSCLASS_FLAG
  if(kEpicsFill)  type4Tree->Branch("epics","TEpics",&epics);
  #endif
  #ifdef SCALERCLASS_FLAG
  if(kScalerFill) type2Tree->Branch("scalers","TScaler",&scalers);
  #endif

  type1Tree->SetAutoSave(50000000);

  CreateFolders();

  
  UShort_t nWords,                 // Number of used words in the buffer.
    type,                          // Type of data in the buffer.
    checksum,                      // Buffer checksum.
    runNum,                        // Run number of active run.
    sequence[2],                   // Buffer sequence number.
    nEntities,                     // Number of entities or events in the buffer.
    format,                        // Buffer format version.
    entitySize,                    // Entity size word (self-inclusive).
    subEvtSize;                    // Event size word (self-inclusive).

  UShort_t nReadWords,             // Number of read words in the buffer.
    subEvtLength;                  // Number of words in an event.

  ULong64_t fBuffers,              // Number of read buffers.
    nTotEntities,                  // Total number of entities of events in the run.
    nTotType1Entities,             // Total number of data entities of events in the run.
    nTotWords,                     // Total number of words in run.
    nTotType1Words;                // Total number of data words in run. 

  analysisState->SetTitle("0");    // Set the analysis state to 0=RAW data TTree.
  
  fBuffers          = 0;
  nTotEntities      = 0;
  nTotType1Entities = 0;
  nTotWords         = 0;
  nTotType1Words    = 0;
  nBuffers->SetTitle("0");
  nTotalEntities->SetTitle("0");
  nTotalType1Entities->SetTitle("0");
  nTotalWords->SetTitle("0");
  nTotalType1Words->SetTitle("0");


  // Unpack the event file.
  while (!file.eof()) {                                    // Read event file
    file.read((Char_t*)buffer,sizeof(buffer));             // Read buffer
    
    // Unpack the header              // Set the BufferHeader data members
    nWords      = buffer[0];          header->nwds = nWords;                   
    type        = buffer[1];          header->type = type;
    checksum    = buffer[2];       
    runNum      = buffer[3]; 
    sequence[0] = buffer[4];          
    sequence[1] = buffer[5];          header->sequence  = (Long64_t)(sequence[1]<<16|sequence[0]);
    nEntities   = buffer[6];          header->nEntities = nEntities;
    format      = buffer[10];

    nReadWords    = 1;
    nTotEntities += nEntities;
    nTotWords    += nWords;
    if(type==1){
      nTotType1Entities += nEntities;
      nTotType1Words    += nWords;
    }
    #ifdef DEBUG
    cout << "Found nWords: " << nWords
	 << " \t type: "     << type << " " << header->type
	 << " \t checksum: " << checksum
	 << " \t runNum: "      << runNum 
	 << " \t sequence[0]: " << sequence[0]
	 << " \t sequence[1]: " << sequence[1]
	 << " \t nEntities: "   << nEntities << endl;
    #endif

    // Output progress to stdout.
    #ifndef DEBUG
    if(counter == 50){
      time(&now);
      cent = 100 * ((Long64_t)(fBuffers * 8192))/(fileSize);
      sprintf(tempChar,"%02.2f",cent);
      cout << "Processing Buffer: " << fBuffers << "  " << tempChar << "%" 
	   << "   " << difftime(now, start) << " s" << "\r";
      cout.flush();
      counter=0;
    }
    counter++;
    #endif

    type0Tree->Fill();

    //######################################################################
    // Event Data Type
    //######################################################################
    if (type == 1){                                // type = 1 is event data.
      p = &buffer[16];                             // Point p toward the first word after buffer header.

      for (Long64_t jj=0; jj<nEntities; jj++){     // Loop through all entities in the buffer.
	entitySize  = *p++;                        // First word in the buffer, it's the entity size.
	entitySize--;                              // The word count is self inclusive.
	nReadWords++;
	Bool_t foundEvents = kFALSE;
	
	while (entitySize>0) {                     // Loop through single events in the buffer.
	  subEvtSize       = *p++;	           // Sub-Event length.
	  subEvtLength     = subEvtSize; 
	  nReadWords++;

	  packetTag = *p++;

	  switch(packetTag){
	  case VMEADC_PACKET:
	    nReadWords++;
	    foundEvents = kTRUE;
	    break;

	  case FOURPI_PACKET:
	    nReadWords++;
	    foundEvents = kTRUE;
	    #ifdef FOURPICLASS_FLAG
	    if(kFourPiFill) fourpi->Unpack(p);
	    #endif
	    break;
	      
	  case HIRA_PACKET:
	    nReadWords++;
	    foundEvents = kTRUE;
            #ifdef HIRACLASS_FLAG
	    if(kHiraFill) hira->Unpack(p);
            #endif
	    break;

	  case CSI_PACK:
	    nReadWords++;
	    foundEvents = kTRUE;
	    #ifdef HIRACSICLASS_FLAG
	    if(kHiraCsIFill) hira->UnpackCsI(p);
	    #endif
	    break;

	  case MCP_PACK:
	    nReadWords++;
	    foundEvents = kTRUE;
	    #ifdef MCPCLASS_FLAG
	    if(kMcpFill) mcp->Unpack(p);
	    #endif
	    break;

	  case S800_PACKET:
	    nReadWords++;
	    foundEvents = kTRUE;
	    #ifdef S800CLASS_FLAG
	    if(kS800Fill) s800->Unpack(p);
	    #endif
	    break;	    

	  default:
	    cout << "Uknown Packet:  " << *p <<endl;
	    break;
	  }

	  entitySize -= subEvtLength;
	  p          += subEvtLength - 2;
	  if (foundEvents == kFALSE) return kTRUE;           // Give up.
	}
	// END OF EVENT

      	type1Tree->Fill();
	// Clear all classes for next event.
	Clear();
      }
    }
    //######################################################################
    // Scaler Data Type
    //######################################################################
    else if (type == 2){ // Scaler data buffers
      // Point p toward nEntities.  This is the number of scalers read out.
      p = &buffer[6];                             
      #ifdef SCALERCLASS_FLAG
      if(kScalerFill) {scalers->Unpack(p); type2Tree->Fill();}
      #endif
      // END OF EVENT
      Clear();

    }else if (type == 3){ // Snapshot Scaler data buffers
      type3Tree->Fill();
      Clear();
    }else if (type == 4){ 
      type4Tree->Fill();
      Clear();
    }
    //######################################################################
    // Documentation Data Type:  Run State Variables
    //######################################################################
    else if (type == 5){ // Documentation Buffer
      // Point p toward nEntities.  This is the number of items read out.
      p = &buffer[6];                             
      #ifdef EPICSCLASS_FLAG
      if(kEpicsFill) {epics->Unpack(p); type5Tree->Fill();}
      #endif
      // END OF EVENT
      Clear();

    }else if (type == 6){
      type6Tree->Fill();
      Clear();
    }else if (type == 10){
      Clear();
    } 
    //######################################################################
    // BEGIN RUN BUFFER
    //######################################################################
    else if (type == 11){ cout << "BEGIN RUN"  << endl;
      sprintf(cBuf,"%u",buffer[3]);
      runNumber->SetTitle(cBuf);

      Char_t runTitleA[200];
      Char_t *runT;
      memset(runTitleA,'\0',200);

      // Get the run title (80 bytes of 8bit char with \0 termination)
      for(Int_t i=16,j=0; i<56; i++){
	runTitleA[j]   = (Char_t)(buffer[i]&0x00ff);
	runTitleA[j+1] = (Char_t)(buffer[i]>>8);
	if(runTitleA[j+1] == '\0') break;
	
	j = j + 2;	
      }
      runT = runTitleA;
      printf("Run Title:         %s\n",runT);

      sprintf(cBuf,"%s",runTitleA);
      runTitle->SetTitle(cBuf);
      sprintf(cBuf,"%02u/%02u/%u",buffer[58],buffer[59],buffer[60]);
      dateCreated->SetTitle(cBuf);
      sprintf(cBuf,"%02u:%02u:%02u",buffer[61],buffer[62],buffer[63]);
      timeCreated->SetTitle(cBuf);

      type1Tree->GetUserInfo()->Add(runNumber);
      type1Tree->GetUserInfo()->Add(runTitle);
      type1Tree->GetUserInfo()->Add(expNumber);
      type1Tree->GetUserInfo()->Add(analysisState);
      type1Tree->GetUserInfo()->Add(dateCreated);
      type1Tree->GetUserInfo()->Add(timeCreated);

      Clear();
    }
    //######################################################################
    // END RUN BUFFER
    //######################################################################    
    else if (type == 12){ cout << endl << "END RUN"  << endl;
      // Write run info to the tree.
      if(!fRunEnd){
	// Get the elapsed runtime.
	ULong64_t  upper,lower,eTime;
	Double_t eVal;
	lower = (ULong64_t)buffer[56];
	upper = (ULong64_t)buffer[57];
	eTime = (ULong64_t)(upper<<16|lower);
	eVal  = (Double_t) eTime/10.00;                     // Convert from 10ths of seconds.
	sprintf(cBuf,"%.2lf",eVal);
	elapsedTime->SetTitle(cBuf);

	sprintf(cBuf,"%02u/%02u/%u",buffer[58],buffer[59],buffer[60]);
	dateEnded->SetTitle(cBuf);
	sprintf(cBuf,"%02u:%02u:%02u",buffer[61],buffer[62],buffer[63]);
	timeEnded->SetTitle(cBuf);
	sprintf(cBuf,"%u",fPauses);
	nPauses->SetTitle(cBuf);
	sprintf(cBuf,"%u",fResumes);
	nResumes->SetTitle(cBuf);

	type1Tree->GetUserInfo()->Add(elapsedTime);
	type1Tree->GetUserInfo()->Add(dateEnded);
	type1Tree->GetUserInfo()->Add(timeEnded);
	type1Tree->GetUserInfo()->Add(nPauses);
	type1Tree->GetUserInfo()->Add(nResumes);
       }
      //      type1Tree->Fill();
      Clear();

      if(fRunEnd) break;
      
      fRunEnd = kTRUE;   

    }else if (type == 13){ cout << "PAUSE RUN"  << endl;
      fPauses++;
      Clear();
    }else if (type == 14){ cout << "RESUME RUN" << endl;
      fResumes++;
      Clear();
    }else{
      cout << "Buffer corrupted.  No valid data type." <<endl;
      break;
    }
    fBuffers++;
    
    // If nBufs is given then stop conversion.
    if(nBuf2Read==(Long64_t)fBuffers) break;
  }

  // If run did not end correctly.
  if(!fRunEnd){
    printf("WARNING!!!  END RUN BUFFER NOT FOUND.  Run may be corrupt.\n");
    type1Tree->GetUserInfo()->Add(elapsedTime);
    type1Tree->GetUserInfo()->Add(dateEnded);
    type1Tree->GetUserInfo()->Add(timeEnded);
    type1Tree->GetUserInfo()->Add(nPauses);
    type1Tree->GetUserInfo()->Add(nResumes);
  }

  cout << "Read " << fBuffers << " buffers." << endl;

  sprintf(cBuf,"%llu",fBuffers);
  nBuffers->SetTitle(cBuf);
  type1Tree->GetUserInfo()->Add(nBuffers);

  Double_t timeTmp = atof(type1Tree->GetUserInfo()->FindObject("Elapsed Run Time")->GetTitle());
  sprintf(cBuf,"%llu",nTotEntities);
  nTotalEntities->SetTitle(cBuf);
  sprintf(cBuf,"%llu",nTotType1Entities);
  nTotalType1Entities->SetTitle(cBuf);
  sprintf(cBuf,"%llu",nTotWords);
  nTotalWords->SetTitle(cBuf);
  sprintf(cBuf,"%llu",nTotType1Words);
  nTotalType1Words->SetTitle(cBuf);
  sprintf(cBuf,"%.2f",(Double_t)nTotEntities/timeTmp);
  avgEventRate->SetTitle(cBuf);
  sprintf(cBuf,"%.2f",(Double_t)nTotType1Entities/timeTmp);
  avgType1EventRate->SetTitle(cBuf);
  sprintf(cBuf,"%.2f",(Double_t)nTotWords/timeTmp);
  avgWordRate->SetTitle(cBuf);
  sprintf(cBuf,"%.2f",(Double_t)nTotType1Words/timeTmp);
  avgType1WordRate->SetTitle(cBuf);
  sprintf(cBuf,"%lli",(Long64_t)fileSize);
  evtSize->SetTitle(cBuf);
  sprintf(cBuf,"%lli",(Long64_t)f->GetSize());
  rootSize->SetTitle(cBuf);
  type1Tree->GetUserInfo()->Add(nTotalEntities);

  type1Tree->GetUserInfo()->Add(nTotalWords);
  type1Tree->GetUserInfo()->Add(avgEventRate);
  type1Tree->GetUserInfo()->Add(avgWordRate);
  type1Tree->GetUserInfo()->Add(nTotalType1Entities);
  type1Tree->GetUserInfo()->Add(nTotalType1Words);
  type1Tree->GetUserInfo()->Add(avgType1EventRate);
  type1Tree->GetUserInfo()->Add(avgType1WordRate);
  type1Tree->GetUserInfo()->Add(evtSize);
  type1Tree->GetUserInfo()->Add(rootSize);


  type1Tree->SetBranchStatus("*",1);
  type0Tree->AutoSave();
  type1Tree->AutoSave();
  type2Tree->AutoSave();
  type3Tree->AutoSave();
  type4Tree->AutoSave();
  type5Tree->AutoSave();
  type6Tree->AutoSave();
  
  file.close();

  // Must call GetUserInfo()->Clear() since deleting the tree will attempt
  // to delete the objects associated with the GetUserInfo TList.
  type0Tree->GetUserInfo()->Clear();
  type1Tree->GetUserInfo()->Clear();
  type2Tree->GetUserInfo()->Clear();
  type3Tree->GetUserInfo()->Clear();
  type4Tree->GetUserInfo()->Clear();
  type5Tree->GetUserInfo()->Clear();
  type6Tree->GetUserInfo()->Clear();
  type0Tree->Delete();
  type1Tree->Delete();
  type2Tree->Delete();
  type3Tree->Delete();
  type4Tree->Delete();
  type5Tree->Delete();
  type6Tree->Delete();

  f->Close();
  delete f;

  return kTRUE;
}

//______________________________________________________________________________
Bool_t TExperiment::ConvertEvtFile(Char_t *evtFileList) 
{
  // -- Convert multiple event files to ROOT files.
  // Note that the argument of this method is the name of a file containing the
  // names of the event files to be converted.  IT SHOULD NOT CONTAIN THE FULL
  // PATH!!!  The location of the event files is set by calling the method
  // SetEventFilePath().

  Char_t evtFile[200];
  Char_t rootFile[200];
  
  ifstream listFile(evtFileList,ios::in);

  cout << "#################################################################" << endl;
  while(!listFile.eof()){
    memset(evtFile,'\0',200);
    memset(rootFile,'\0',200);
    listFile.getline(evtFile,200);

    for(Int_t i=0; i<200; i++){
      if(evtFile[i]=='.') break;
      rootFile[i] = evtFile[i];
    }
    strcat(rootFile,".root");
    cout << evtFile << " " << rootFile << endl;

    if(ConvertEvtFile(evtFile,rootFile)){
      cout << "SUCCESS!!!" << endl;
      cout << "#################################################################" << endl;
    }else{
      cout << "FAILED!!!" << endl;
      cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << endl;
    }
   }

  listFile.close();

  return kTRUE;
}


//______________________________________________________________________________
Long64_t TExperiment::LoadTree(Long64_t entry)
{
  // -- Load an entry for a TChain.
  //

  // Set the environment to read one entry
  if (!fChain) return -5;
  Long64_t centry = fChain->LoadTree(entry);
  //   hira->fChain->LoadTree(entry);
  //   for(Int_t i=0; i<16; i++) hira->tele[i].fChain->LoadTree(entry);
  //   for(Int_t i=0; i<16; i++) hira->tele[i].EF.fChain->LoadTree(entry);

  if (centry < 0) return centry;
  if (!fChain->InheritsFrom(TChain::Class()))  return centry;
  TChain *chain = (TChain*)fChain;
  if (chain->GetTreeNumber() != fCurrent) {
    fCurrent = chain->GetTreeNumber();
  }
  return centry;
}


//______________________________________________________________________________
void TExperiment::SetTarget(const char *targetName)
{
  // -- Set the current target for this run.
  //

  fTarget = (TTarget*)fTargets->FindObject(targetName);
  printf ("Looking for %s\n",targetName);
  #ifdef HIRACLASS_FLAG
  hira->SetTarget(fTarget);
  #endif
}


//______________________________________________________________________________
Bool_t TExperiment::SetEventFilePath(Char_t *path) 
{
  // -- Sets the event file source path.  
  // This is the location from which event files will be read.
  evtFilePath = path;
  return kTRUE;
}


//______________________________________________________________________________
Bool_t TExperiment::SetExperimentNumber(Char_t *number) 
{
  // -- Sets the experiment number of this instance of TExperiment.
  expNumber->SetTitle(number);  
  return kTRUE;
}


//______________________________________________________________________________
Bool_t TExperiment::SetRootFilePath(Char_t *path) 
{
  // -- Sets the root file destination path.  
  // Any root file generated from an event file will be written to this directory.

  rootFilePath = path;

  return kTRUE;
}


// //______________________________________________________________________________
// void TExperiment::SetName(const Char_t *name)
// {
//   // -- Change (i.e. set) the name of the TExperiment.
//   //

//   fName = name;
// }


// //______________________________________________________________________________
// void TExperiment::SetNameTitle(const Char_t *name, const Char_t *title)
// {
//   // -- Change (i.e. set) all the TExperiment parameters (name and title).
//   //

//   fName  = name;
//   fTitle = title;
// }


// //______________________________________________________________________________
// void TExperiment::SetTitle(const Char_t *title)
// {
//   // -- Change (i.e. set) the title of the TExperiment.
//   //

//   fTitle = title;
// }

Last change: Tue Dec 16 22:01:05 2008
Last generated: 2008-12-16 22:01

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