#include <TObjArray.h>
#include <TTree.h>
#include "TTreeStream.h"
+// includes for test procedures
+#include "TVectorD.h"
+#include "TRandom.h"
ClassImp(TTreeDataElement)
ClassImp(TTreeStream)
//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()
{
//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) :
- fFile(new TFile(fname,"recreate")),
- fDataLayouts(0)
+TTreeSRedirector::TTreeSRedirector(const char *fname,const char * option) :
+ fDirectory(NULL),
+ fDirectoryOwner(kTRUE),
+ fDataLayouts(NULL)
{
//
// Constructor
//
- if (!fFile){
- fFile = new TFile(fname,"new");
+ TString name(fname);
+ if (!name.IsNull()){
+ fDirectory = new TFile(fname,option);
+ }
+ else
+ {
+ fDirectory = gDirectory;
+ fDirectoryOwner = kFALSE;
}
}
// 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::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 (fDirectory && fDirectoryOwner) {
+ fDirectory->Close();
+ delete fDirectory;
+ }
+ fDirectory=sfile;
+}
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);
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)
{
if (!clayout){
TDirectory * backup = gDirectory;
- fFile->cd();
+ fDirectory->cd();
clayout = new TTreeStream(name);
clayout->fId=-1;
clayout->SetName(name);
//
//
TDirectory * backup = gDirectory;
- fFile->cd();
+ fDirectory->cd();
if (fDataLayouts){
Int_t entries = fDataLayouts->GetEntriesFast();
for (Int_t i=0;i<entries;i++){
if (backup) backup->cd();
}
-
-
//-------------------------------------------------------------
TTreeDataElement:: TTreeDataElement(Char_t type) :
TNamed(),
}
//-------------------------------------------------------------------
-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(),
//
// Standard ctor
//
+ if (!fTree) fTree = new TTree(treename, treename);
}
TTreeStream::~TTreeStream()
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){
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;
}
//
// 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);
}
else{
- snprintf(bname1,1000,element->GetName());
+ snprintf(bname1,1000,"%s",element->GetName());
}
if (element->fClass){
if (element->fClass->GetBaseClass("TClonesArray")){