]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - STEER/STEERBase/TTreeStream.cxx
SetFlag GetFlag lifted to interface
[u/mrichter/AliRoot.git] / STEER / STEERBase / TTreeStream.cxx
index acd1487ba1db95913a6c29a7e65ee57ec8ddedfd..d53d3fbe5043552a3b0f710db187b4c96ee7e581 100644 (file)
@@ -36,6 +36,9 @@
 #include <TObjArray.h>
 #include <TTree.h>
 #include "TTreeStream.h"
+// includes for test procedures
+#include "TVectorD.h"
+#include "TRandom.h"
 
 ClassImp(TTreeDataElement)
 ClassImp(TTreeStream)
@@ -90,7 +93,53 @@ void TTreeStream::Test()
   //5.) and now see results  in file tteststreamer.root
 }
 
-
+void TTreeSRedirector::Test2()
+{
+  //
+  //Example test function to show functionality of TTreeSRedirector
+  //
+  //
+  //1.)create the  redirector associated with file (testredirector.root)
+  //
+  //
+  TFile* file = new TFile("test.root","recreate");
+  TTreeSRedirector *pmistream= new TTreeSRedirector();
+  TTreeSRedirector &mistream = *pmistream;
+  Char_t ch='s';
+  Float_t f=3.;
+  Float_t f2=1;
+  TObject *po  = new TObject;
+  TObject *po2 = new TObject;
+  for (Int_t i=0;i<100000;i++) {
+    f=i*100;
+    po->SetUniqueID(i);
+    po2->SetUniqueID(i*100);
+    ch=i%120;
+    //
+    //2.) create the tree with identifier specified by first argument
+    //                                layout specified by sequence of arguments
+    //                                Tree identifier has to be specified as first argument !!! 
+    //    if the tree and layout was already defined the consistency if layout is checked
+    //                                if the data are consisten fill given tree 
+    //    the name of branch can be specified using strings with = at the the end
+    //    if string is not specified use automatic convention  B0, B1, ...Bn
+    mistream<<"TreeIdentifier"<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
+    f  = 1./(100.1+i);
+    f2 = -f; 
+    
+    //3.) just another example - we can fill the same tree with different objects
+    //
+    mistream<<"TreeK"<<f<<po<<"\n";
+    mistream<<"TreeK"<<f2<<po2<<"\n";
+  }
+  //
+  //4.) write the streamed tree's to the file and close the corresponding file in destructor
+  //
+  delete pmistream;
+  delete file;
+  //
+  //5.) and now see results in file testredirector.root 
+}
 
 void TTreeSRedirector::Test()
 {
@@ -138,54 +187,143 @@ void TTreeSRedirector::Test()
   //5.) and now see results in file testredirector.root 
 }
 
+void TTreeSRedirector::UnitTest(){
+  //
+  //
+  //
+  UnitTestSparse(0.5);
+  UnitTestSparse(0.1);
+  UnitTestSparse(0.01);
+}
+
+void TTreeSRedirector::UnitTestSparse(Double_t scale){
+  //
+  // Unit test for the TTreeSRedirector
+  // 1.) Test TTreeRedirector 
+  //      a.) Fill tree with random vectors
+  //      b.) Fill downscaled version of vectors
+  //      c.) The same skipping first entry
+  // 2.) Check results wtitten to terminale
+  //     a.) Disk consumption 
+  //             skip data should be scale time smaller than full
+  //             zerro replaced  ata should be compresed time smaller than full
+  //     b.) Test invariants
+  // Input parameter scale => downscaling of sprse element 
+  //            
+  if (scale<=0) scale=1;
+  if (scale>1) scale=1;
+  TTreeSRedirector *pcstream = new TTreeSRedirector("testpcstreamSparse.root","recreate");
+  for (Int_t ientry=0; ientry<20000; ientry++){
+    TVectorD vecRandom(50);
+    TVectorD vecZerro(50);   // zerro vector
+    for (Int_t j=0; j<50; j++) vecRandom[j]=ientry+gRandom->Rndm();
+    Bool_t isSelected= (gRandom->Rndm()<scale);
+    TVectorD *pvecFull   = &vecRandom;
+    TVectorD *pvecSparse = isSelected ? &vecRandom:0;
+    TVectorD *pvecSparse0 = isSelected ? &vecRandom:0;
+    TVectorD *pvecSparse1 = isSelected ? &vecRandom:&vecZerro;
+
+    if (ientry==0) {
+      pvecSparse0=0;
+      pvecSparse=&vecRandom;
+    }
+    (*pcstream)<<"Full"<<                  // stored all vectors
+      "ientry="<<ientry<<
+      "vec.="<<pvecFull<<                  
+      "\n";
+    (*pcstream)<<"SparseSkip"<<                // fraction of vectors stored
+      "ientry="<<ientry<<
+      "vec.="<<pvecSparse<<                
+      "\n";
+    (*pcstream)<<"SparseSkip0"<<               // fraction with -pointer
+      "ientry="<<ientry<<
+      "vec.="<<pvecSparse0<<
+      "\n";
+    (*pcstream)<<"SparseZerro"<<               // all vectors filled, franction filled with 0
+      "ientry="<<ientry<<
+      "vec.="<<pvecSparse1<<
+      "\n";
+  }
+  delete pcstream;
+  //
+  // 2.) check results
+  //
+  TFile* f = TFile::Open("testpcstreamSparse.root");
+  TTree * treeFull = (TTree*)f->Get("Full");
+  TTree * treeSparseSkip = (TTree*)f->Get("SparseSkip");
+  TTree * treeSparseSkip0 = (TTree*)f->Get("SparseSkip0");
+  TTree * treeSparseZerro = (TTree*)f->Get("SparseZerro");
+  //    a.) data volume
+  //
+  Double_t ratio=(1./scale)*treeSparseSkip->GetZipBytes()/Double_t(treeFull->GetZipBytes());
+  Double_t ratio0=(1./scale)*treeSparseSkip0->GetZipBytes()/Double_t(treeFull->GetZipBytes());
+  Double_t ratio1=(1./scale)*treeSparseZerro->GetZipBytes()/Double_t(treeFull->GetZipBytes());
+  printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tRatioSkip\t%f\n",scale,ratio);
+  printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tRatioSkip0\t%f\n",scale,ratio0);
+  printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tRatioZerro\t%f\n",scale,ratio1);
+  //    b.) Integrity 
+  Int_t outlyersSparseSkip=treeSparseSkip->Draw("1","(vec.fElements-ientry-0.5)>0.5","goff");
+  Int_t outlyersSparseSkip0=treeSparseSkip0->Draw("1","(vec.fElements-ientry-0.5)>0.5","goff");
+  printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tOutlyersSkip\t%d\n",scale,outlyersSparseSkip);
+  printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tOutlyersSkip0\t%d\n",scale,outlyersSparseSkip);
+
+  Bool_t isOK=(ratio<1.2)&&(outlyersSparseSkip0);
+  printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tisOk\t%d\n",scale,isOK);  
+}
 
 TTreeSRedirector::TTreeSRedirector(const char *fname,const char * option) :
-  fFile(new TFile(fname,option)),
-  fDataLayouts(0)
+  fDirectory(NULL),
+  fDirectoryOwner(kTRUE),
+  fDataLayouts(NULL)
 {
   //
   // Constructor
   //
-  if (!fFile){
-    fFile = new TFile(fname,option);
+  TString name(fname);
+  if (!name.IsNull()){
+    fDirectory = new TFile(fname,option);
+  }
+  else
+  {
+    fDirectory = gDirectory;
+    fDirectoryOwner = kFALSE;
   }
 }
 
-
-
 TTreeSRedirector::~TTreeSRedirector()
 {
   //
   // Destructor
   //
   Close();       //write the tree to the selected file
-  fFile->Close();
-  delete fFile;
+  if (fDirectoryOwner)
+  {
+    fDirectory->Close();
+    delete fDirectory;
+  }
 }
 void TTreeSRedirector::StoreObject(TObject* object){
   //
   //
   //
   TDirectory * backup = gDirectory;
-  fFile->cd();
+  fDirectory->cd();
   object->Write();
   if (backup) backup->cd();
 }
 
-
-void  TTreeSRedirector::SetFile(TFile *sfile){
+void  TTreeSRedirector::SetDirectory(TDirectory *sfile){
   //
   // Set the external file 
   // In case other file already attached old file is closed before
   // Redirector will be the owner of file ?
-  if (fFile) {
-    fFile->Close();
-    delete fFile;
+  if (fDirectory && fDirectoryOwner) {
+    fDirectory->Close();
+    delete fDirectory;
   }
-  fFile=sfile;
+  fDirectory=sfile;
 }
 
-
 TTreeStream  & TTreeSRedirector::operator<<(Int_t id)
 {
   //
@@ -204,7 +342,7 @@ TTreeStream  & TTreeSRedirector::operator<<(Int_t id)
   }
   if (!clayout){
     TDirectory * backup = gDirectory;
-    fFile->cd();
+    fDirectory->cd();
     char chname[100];
     snprintf(chname,100,"Tree%d",id);
     clayout = new TTreeStream(chname);
@@ -215,6 +353,24 @@ TTreeStream  & TTreeSRedirector::operator<<(Int_t id)
   return *clayout;
 }
 
+void TTreeSRedirector::SetExternalTree(const char* name, TTree* externalTree)
+{
+  TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
+
+  if (!clayout){
+    TDirectory * backup = gDirectory;
+    fDirectory->cd();
+    clayout = new TTreeStream(name,externalTree);
+    clayout->fId=-1;
+    clayout->SetName(name);
+    Int_t entries = fDataLayouts->GetEntriesFast();
+    fDataLayouts->AddAt(clayout,entries);
+    if (backup) backup->cd();
+  }
+  //else
+  //  AliError(Form("identifier %s already associated",name));
+}
+
 
 TTreeStream  & TTreeSRedirector::operator<<(const char* name)
 {
@@ -227,7 +383,7 @@ TTreeStream  & TTreeSRedirector::operator<<(const char* name)
 
   if (!clayout){
     TDirectory * backup = gDirectory;
-    fFile->cd();
+    fDirectory->cd();
     clayout = new TTreeStream(name);
     clayout->fId=-1;
     clayout->SetName(name);
@@ -244,7 +400,7 @@ void TTreeSRedirector::Close(){
   //
   //
   TDirectory * backup = gDirectory;
-  fFile->cd();
+  fDirectory->cd();
   if (fDataLayouts){
     Int_t entries = fDataLayouts->GetEntriesFast();
     for (Int_t i=0;i<entries;i++){
@@ -259,8 +415,6 @@ void TTreeSRedirector::Close(){
   if (backup) backup->cd();
 }
 
-
-
 //-------------------------------------------------------------
 TTreeDataElement:: TTreeDataElement(Char_t type) :
   TNamed(),
@@ -299,11 +453,11 @@ TTreeDataElement:: TTreeDataElement(TClass* cl) :
 }
 
 //-------------------------------------------------------------------
-TTreeStream::TTreeStream(const char *treename):
+TTreeStream::TTreeStream(const char *treename, TTree* externalTree):
   TNamed(treename,treename),
   fElements(0),
   fBranches(0),
-  fTree(new TTree(treename, treename)),
+  fTree(externalTree),
   fCurrentIndex(0),
   fId(0),
   fNextName(),
@@ -313,6 +467,7 @@ TTreeStream::TTreeStream(const char *treename):
   //
   // Standard ctor
   //
+  if (!fTree) fTree = new TTree(treename, treename);
 }
 
 TTreeStream::~TTreeStream()
@@ -373,15 +528,16 @@ Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
   return 0;
 }
 
-Int_t TTreeStream::CheckIn(TObject *o){
+Int_t TTreeStream::CheckIn(TObject *pObject){
   //
   // Insert TObject
   //
-  if (!o) return 0;
+  TClass *pClass = 0;
+  if (pObject) pClass=pObject->IsA();
   if (!fElements) fElements = new TObjArray(1000);
   TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
   if (!element) {
-    element = new TTreeDataElement(o->IsA());
+    element = new TTreeDataElement(pClass);
     //
     char name[1000];
     if (fNextName.Length()>0){
@@ -396,17 +552,21 @@ Int_t TTreeStream::CheckIn(TObject *o){
       snprintf(name,1000,"B%d",fCurrentIndex);
     }
     element->SetName(name);
-
-    element->SetPointer(o);
+    
+    element->SetPointer(pObject);
     fElements->AddAt(element,fCurrentIndex);
     fCurrentIndex++;
     return 0; //new element added
   }
-  if (element->fClass!=o->IsA()){
-    fStatus++;
-    return 1; //mismatched data element
+  if (element->fClass==0) {
+    element->fClass=pClass;
+  }else{
+    if (element->fClass!=pClass){
+      fStatus++;
+      return 1; //mismatched data element
+    }
   }
-  element->SetPointer(o);
+  element->SetPointer(pObject);
   fCurrentIndex++;
   return 0;  
 }
@@ -415,14 +575,15 @@ void TTreeStream::BuildTree(){
   //
   // Build the Tree
   //
-  if (fTree && fTree->GetEntries()>0) return;
+  //if (fTree && fTree->GetEntries()>0) return;
   if (!fTree)  fTree = new TTree(GetName(),GetName());
   Int_t entries = fElements->GetEntriesFast();  
-  fBranches = new TObjArray(entries);
+  if (!fBranches) fBranches = new TObjArray(entries);
   
   for (Int_t i=0;i<entries;i++){
     //
     TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
+    if (fBranches->At(i)) continue;
     char bname1[1000];
     if (element->GetName()[0]==0){
       snprintf(bname1,1000,"B%d",i);