From 275f3f2c3caa17e2df82fcecbc543b6dca087e3b Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Thu, 30 Jan 2003 06:40:33 +0000
Subject: [PATCH] From Philippe: This patch adds systematic test for the
 ability of TTree::Draw to draw TBits objects. It also fixes all the bug
 discovered during the tests. It also adds a test for split level 2.

git-svn-id: http://root.cern.ch/svn/root/trunk@6011 27541ba8-7e3a-0410-8455-c3a389f83636
---
 test/Event.cxx                   | 55 +++++++++++++++++++--
 test/Event.h                     |  5 ++
 test/dt_DrawTest.C               | 84 ++++++++++++++++++++------------
 test/dt_MakeRef.C                | 37 +++++++++++++-
 test/dt_Makefile                 | 10 +++-
 test/dt_RunDrawTest.C            | 13 +++--
 test/dt_RunDrawTest.sh           | 69 ++++++++++++++------------
 treeplayer/inc/TTreeFormula.h    |  4 +-
 treeplayer/src/TSelectorDraw.cxx | 10 +++-
 treeplayer/src/TTreeFormula.cxx  | 35 ++++++++++---
 10 files changed, 235 insertions(+), 87 deletions(-)

diff --git a/test/Event.cxx b/test/Event.cxx
index 1a2dde7a217..d76e45bae0b 100644
--- a/test/Event.cxx
+++ b/test/Event.cxx
@@ -1,4 +1,4 @@
-// @(#)root/test:$Name:  $:$Id: Event.cxx,v 1.18 2002/08/07 13:55:45 brun Exp $
+// @(#)root/test:$Name:  $:$Id: Event.cxx,v 1.19 2002/08/20 15:21:42 brun Exp $
 // Author: Rene Brun   19/08/96
 
 ////////////////////////////////////////////////////////////////////////
@@ -156,7 +156,11 @@ void Event::Build(Int_t ev, Int_t arg5, Float_t ptmin) {
     }
   }
 
-   //  Create and Fill the Track objects
+  fTriggerBits.SetBitNumber((UInt_t)(64*gRandom->Rndm(1)));
+  fTriggerBits.SetBitNumber((UInt_t)(64*gRandom->Rndm(1)));
+  fTriggerBits.SetBitNumber((UInt_t)(64*gRandom->Rndm(1)));
+
+  //  Create and Fill the Track objects
   for (Int_t t = 0; t < ntrack; t++) AddTrack(random,ptmin);
   
   //Restore Object count 
@@ -234,7 +238,47 @@ void Event::SetRandomVertex() {
 }
 
 //______________________________________________________________________________
-Track::Track(Float_t random) : TObject()
+Track::Track(const Track &orig) : TObject(orig)
+{
+   // Copy a track object
+
+   fPx = orig.fPx;
+   fPy = orig.fPy;
+   fPz = orig.fPx; 
+   fRandom = orig.fRandom;
+   fMass2 = orig.fMass2;
+   fBx = orig.fBx;
+   fBy = orig.fBy;
+   fMeanCharge = orig.fMeanCharge;
+   fXfirst = orig.fXfirst;
+   fXlast  = orig.fXlast;
+   fYfirst = orig.fYfirst;
+   fYlast  = orig.fYlast;
+   fZfirst = orig.fZfirst;
+   fZlast  = orig.fZlast;
+   fCharge = orig.fCharge;
+
+   fVertex[0] = orig.fVertex[0];
+   fVertex[1] = orig.fVertex[1];
+   fVertex[2] = orig.fVertex[2];
+   fNpoint = orig.fNpoint;
+   fNsp = orig.fNsp;
+   if (fNsp) {
+      fPointValue = new Float_t[fNsp];
+      for(int i=0; i<fNsp; i++) {
+         fPointValue[i] = orig.fPointValue[i];
+      }
+   } else {
+      fPointValue = 0;
+   }
+   fValid  = orig.fValid;
+
+   fTriggerBits = orig.fTriggerBits;
+
+}
+
+//______________________________________________________________________________
+Track::Track(Float_t random) : TObject(),fTriggerBits(64)
 {
    // Create a track object.
    // Note that in this example, data members do not have any physical meaning.
@@ -264,6 +308,11 @@ Track::Track(Float_t random) : TObject()
    fZfirst = 50 + 5*a;
    fZlast  = 200 + 10*b;
    fCharge = Float_t(Int_t(3*gRandom->Rndm(1)) - 1);
+
+   fTriggerBits.SetBitNumber((UInt_t)(64*gRandom->Rndm(1)));
+   fTriggerBits.SetBitNumber((UInt_t)(64*gRandom->Rndm(1)));
+   fTriggerBits.SetBitNumber((UInt_t)(64*gRandom->Rndm(1)));
+
    fVertex[0] = gRandom->Gaus(0,0.1);
    fVertex[1] = gRandom->Gaus(0,0.2);
    fVertex[2] = gRandom->Gaus(0,10);
diff --git a/test/Event.h b/test/Event.h
index 0b763fccefb..af894543d3a 100644
--- a/test/Event.h
+++ b/test/Event.h
@@ -42,9 +42,11 @@ private:
    Short_t      fValid;        //Validity criterion
    Int_t        fNsp;          //Number of points for this track with a special value
    Float_t*     fPointValue;   //[fNsp] a special quantity for some point.
+   TBits        fTriggerBits;  //Bits triggered by this track.
 
 public:
    Track() { fPointValue = 0; }
+   Track(const Track& orig);
    Track(Float_t random);
    virtual ~Track() {Clear();}
    void          Clear(Option_t *option="") { delete [] fPointValue; fPointValue=0; }
@@ -66,6 +68,7 @@ public:
    Float_t       GetCharge() const { return fCharge; }
    Float_t       GetVertex(Int_t i=0) {return (i<3)?fVertex[i]:0;}
    Int_t         GetNpoint() const { return fNpoint; }
+   TBits&        GetTriggerBits() { return fTriggerBits; }
    Short_t       GetValid()  const { return fValid; }
    virtual void  SetValid(Int_t valid=1) { fValid = valid; }
    Int_t         GetN() const { return fNsp; }
@@ -113,6 +116,7 @@ private:
    TRef           fLastTrack;         //reference pointer to last track
    TRef           fWebHistogram;      //EXEC:GetWebHistogram reference to an histogram in a TWebFile
    TH1F          *fH;                 //->
+   TBits          fTriggerBits;       //Bits triggered by this event.
 
    static TClonesArray *fgTracks;
    static TH1F         *fgHist;
@@ -152,6 +156,7 @@ public:
    TH1          *GetWebHistogram()  const {return (TH1*)fWebHistogram.GetObject();}
    Int_t         GetMeasure(UChar_t which) { return (which<10)?fMeasures[which]:0; }
    Float_t       GetMatrix(UChar_t x, UChar_t y) { return (x<4&&y<4)?fMatrix[x][y]:0; }
+   TBits&        GetTriggerBits() { return fTriggerBits; }
 
    ClassDef(Event,1)  //Event structure
 };
diff --git a/test/dt_DrawTest.C b/test/dt_DrawTest.C
index 9adc93994df..3625cc5c6f0 100644
--- a/test/dt_DrawTest.C
+++ b/test/dt_DrawTest.C
@@ -7,27 +7,31 @@ int gHasLibrary = kFALSE;
 int gBranchStyle = 1;
 TList gSkipped;
 
-void DrawSkippable(TTree* tree, const char* what, const char* where, Bool_t skip) {
+void DrawSkippable(TTree* tree, const char* what, const char* where, Bool_t draw) {
   //cerr << "Doing " << what << " which is " << skip << endl;
-  if (skip) gSkipped.Add(new TNamed(where,where));
-  else {
+  if (draw) {
     TString cut = what;
     cut.Append(">>");
     cut.Append(where);
     tree->Draw(cut.Data(),"","goff");
+
+  } else {
+    gSkipped.Add(new TNamed(where,where));
   }
+  
 };
 
 void DrawSkippable(TTree* tree, const char* what, const char* cond,
-                   const char* where, Bool_t skip) {
-  //cerr << "Doing " << what << " which is " << skip << endl;
-  if (skip) gSkipped.Add(new TNamed(where,where));
-  else {
-    TString cut = what;
-    cut.Append(">>");
-    cut.Append(where);
-    tree->Draw(cut.Data(),cond,"goff");
-  }
+                   const char* where, Bool_t draw) {
+   //cerr << "Doing " << what << " which is " << skip << endl;
+   if (draw) { 
+      TString cut = what;
+      cut.Append(">>");
+      cut.Append(where);
+      tree->Draw(cut.Data(),cond,"goff");
+   } else {
+     gSkipped.Add(new TNamed(where,where));
+   }
 };
 
 // Rootmarks for fcdflnx1 is 153.4
@@ -50,7 +54,7 @@ void DrawMarks() {
 
 
 //_______________________________________________________________
-TDirectory* GenerateDrawHist(TTree *tree,int level = 1, int quietLevel = 0)
+TDirectory* GenerateDrawHist(TTree *tree,int level = 2, int quietLevel = 0)
 {
 // Test selections via TreeFormula
 // tree is a TTree when called by stress9
@@ -66,7 +70,7 @@ TDirectory* GenerateDrawHist(TTree *tree,int level = 1, int quietLevel = 0)
    gBenchmark->Start("DrawTest");
    
    // Each tree->Draw generates an histogram
-   DrawSkippable(tree,"GetNtrack()","hGetNtrack",!(level>0 && gHasLibrary));
+   DrawSkippable(tree,"GetNtrack()","hGetNtrack",(level>0 && gHasLibrary));
 
    //gBenchmark->Show("DrawTest");  gBenchmark->Start("DrawTest");
 
@@ -77,12 +81,12 @@ TDirectory* GenerateDrawHist(TTree *tree,int level = 1, int quietLevel = 0)
    tree->Draw("fH.GetMean()>>hHmean","","goff");
    if (level>0) tree->Draw("fH.fXaxis.fXmax>>hHAxisMax","","goff");
    if (level>0) tree->Draw("fH.fXaxis.GetXmax()>>hHAxisGetMax","","goff");
-   DrawSkippable(tree,"fH.GetXaxis().GetXmax()","hHGetAxisGetMax",!(level>0));
-   DrawSkippable(tree,"fH.GetXaxis().fXmax","hHGetAxisMax",!(level>0));
+   DrawSkippable(tree,"fH.GetXaxis().GetXmax()","hHGetAxisGetMax",(level>0));
+   DrawSkippable(tree,"fH.GetXaxis().fXmax","hHGetAxisMax",(level>0));
    DrawSkippable(tree,"GetHistogram().GetXaxis().GetXmax()","hGetHGetAxisMax",
-                 !(level>0&&gHasLibrary));
+                 (level>0&&gHasLibrary));
    DrawSkippable(tree,"event.GetHistogram().GetXaxis().GetXmax()",
-                 "hGetRefHGetAxisMax",!(level>0&&gHasLibrary));
+                 "hGetRefHGetAxisMax",(level>0&&gHasLibrary));
 
    tree->Draw("fTracks.fPx>>hPx","fEvtHdr.fEvtNum%10 == 0","goff");
    tree->Draw("fTracks.fPy>>hPy","fEvtHdr.fEvtNum%10 == 0","goff");
@@ -100,7 +104,7 @@ TDirectory* GenerateDrawHist(TTree *tree,int level = 1, int quietLevel = 0)
    tree->Draw("fCharge>>hCharge","fPx < 0","goff");
    tree->Draw("fNpoint>>hNpoint","fPx < 0","goff");
    tree->Draw("fValid>>hValid",  "fPx < 0","goff");
-   DrawSkippable(tree,"fPointValue","hPointValue", gBranchStyle==0);
+   DrawSkippable(tree,"fPointValue","hPointValue", gBranchStyle!=0);
 
    tree->Draw("fMatrix>>hFullMatrix","","goff");
    tree->Draw("fMatrix[][0]>>hColMatrix","","goff");
@@ -124,28 +128,44 @@ TDirectory* GenerateDrawHist(TTree *tree,int level = 1, int quietLevel = 0)
 
    // Test variable indexing
    DrawSkippable(tree,"fClosestDistance[fNvertex/2]","hClosestDistanceIndex",
-                 !(level>0));
-   DrawSkippable(tree,"fPx:fPy[fNpoint/6]","fPy[fNpoint/6]>0","hPxInd",!(level>0));
+                 (level>0));
+   DrawSkippable(tree,"fPx:fPy[fNpoint/6]","fPy[fNpoint/6]>0","hPxInd",(level>0));
 
    // Test of simple function calls
-   DrawSkippable(tree,"sqrt(fNtrack)","hSqrtNtrack",!(level>0));   
+   DrawSkippable(tree,"sqrt(fNtrack)","hSqrtNtrack",(level>0));   
 
    // Test string operations
-   DrawSkippable(tree,"fEvtHdr.fEvtNum","fType==\"type1\" ","hString",!(level>0));
-   DrawSkippable(tree,"fEvtHdr.fEvtNum","strstr(fType,\"1\") ","+hString",!(level>0));
+   DrawSkippable(tree,"fEvtHdr.fEvtNum","fType==\"type1\" ","hString",(level>0));
+   DrawSkippable(tree,"fEvtHdr.fEvtNum","strstr(fType,\"1\") ","+hString",(level>0));
 
    // Test binary operators
-   DrawSkippable(tree,"fValid<<4","hShiftValid",!(level>0));
-   DrawSkippable(tree,"((fValid<<4)>>2)","+hShiftValid",!(level>0));
+   DrawSkippable(tree,"fValid<<4","hShiftValid",(level>0));
+   DrawSkippable(tree,"((fValid<<4)>>2)","+hShiftValid",(level>0));
    DrawSkippable(tree,"fValid&0x1","(fNvertex>10) && (fNseg<=6000)"
-                 ,"hAndValid",!(level>0));
+                 ,"hAndValid",(level>0));
 
    // Test weight
-   DrawSkippable(tree,"fPx","(fBx>.25) || (fBy<=-.25)","hPxBx",!(level>0));
-   DrawSkippable(tree,"fPx","fBx*fBx*(fBx>.25) + fBy*fBy*(fBy<=-.25)",
-                 "hPxBxWeight",!(level>0));
-  
-   if (quietLevel<2) gBenchmark->Show("DrawTest");  
+   DrawSkippable(tree,"fPx","(fBx>.15) || (fBy<=-.15)","hPxBx",(level>0));
+   DrawSkippable(tree,"fPx","fBx*fBx*(fBx>.15) + fBy*fBy*(fBy<=-.15)",
+                 "hPxBxWeight",(level>0));
+
+   DrawSkippable(tree,"event.fTriggerBits",
+                 "hTriggerBits",level>1 && gBranchStyle!=0);
+   DrawSkippable(tree,"event.fTriggerBits.fNbits",
+                 "event.fTriggerBits.TestBitNumber(10)",
+                 "hFiltTriggerBits",level>1 && gBranchStyle!=0);
+
+   DrawSkippable(tree,"event.GetTriggerBits()",
+                 "hTriggerBitsFunc",level>1 && gBranchStyle!=0 && gHasLibrary );
+
+   DrawSkippable(tree,"fTracks.fTriggerBits",
+                 "hTrackTrigger", level>1 && gBranchStyle!=0);
+   DrawSkippable(tree,"fPx",
+                 "fTracks.fTriggerBits.TestBitNumber(5)",
+                 "hFiltTrackTrigger", level>1 && gBranchStyle!=0);
+
+
+   if (quietLevel<2) gBenchmark->Show("DrawTest");   
    else gBenchmark->Stop("DrawTest");  
    gBenchmark->Start("DrawTest");
 
diff --git a/test/dt_MakeRef.C b/test/dt_MakeRef.C
index faf044a2123..c389b0bd6df 100644
--- a/test/dt_MakeRef.C
+++ b/test/dt_MakeRef.C
@@ -101,6 +101,13 @@ void MakeHisto(TTree *tree, TDirectory* To) {
    TH1F *refPxBx = RefClone(where,"hPxBx");
    TH1F *refPxBxWeight =  RefClone(where,"hPxBxWeight");
 
+   TH1F *refTriggerBits = RefClone(where,"hTriggerBits");
+   TH1F *refTriggerBitsFunc = RefClone(where,"hTriggerBitsFunc");
+   TH1F *refFiltTriggerBits = RefClone(where,"hFiltTriggerBits");
+
+   TH1F *refTrackTrigger = RefClone(where,"hTrackTrigger");
+   TH1F *refFiltTrackTrigger = RefClone(where,"hFiltTrackTrigger");
+
    // Loop with user code on all events and fill the ref histograms
    // The code below should produce identical results to the tree->Draw above
 
@@ -151,6 +158,20 @@ void MakeHisto(TTree *tree, TDirectory* To) {
       }
       refCellMatrix->Fill(event->GetMatrix(2,2));
 
+      TBits bits = event->GetTriggerBits();
+      Int_t nbits = bits.GetNbits();
+      Int_t ncx = refTriggerBits->GetXaxis()->GetNbins();
+      Int_t nextbit = -1;
+      while(1) {
+         nextbit = bits->FirstSetBit(nextbit+1);
+         if (nextbit >= nbits) break;
+         if (nextbit > ncx) refTriggerBits->Fill(ncx+1);
+         else               refTriggerBits->Fill(nextbit);
+         if (nextbit > ncx) refTriggerBitsFunc->Fill(ncx+1);
+         else               refTriggerBitsFunc->Fill(nextbit);
+      }
+      if (bits.TestBitNumber(10)) refFiltTriggerBits->Fill(nbits);
+
       ntracks = event->GetNtrack();
       if ( 5 < ntracks ) {
          t = (Track*)tracks->UncheckedAt(5);
@@ -200,8 +221,8 @@ void MakeHisto(TTree *tree, TDirectory* To) {
          float Bx,By;
          Bx = t->GetBx();
          By = t->GetBy();
-         if ((Bx>.25) || (By<=-.25)) refPxBx->Fill(t->GetPx());
-         double weight = Bx*Bx*(Bx>.25) + By*By*(By<=-.25);
+         if ((Bx>.15) || (By<=-.15)) refPxBx->Fill(t->GetPx());
+         double weight = Bx*Bx*(Bx>.15) + By*By*(By<=-.15);
          if (weight) refPxBxWeight->Fill(t->GetPx(),weight);
 
          if (i<4) {
@@ -215,6 +236,18 @@ void MakeHisto(TTree *tree, TDirectory* To) {
          for(i1=0; i1<t->GetN(); i1++) {
             refPointValue->Fill( t->GetPointValue(i1) );
          }
+         TBits bits = t->GetTriggerBits();
+         Int_t nbits = bits.GetNbits();
+         Int_t ncx = refTrackTrigger->GetXaxis()->GetNbins();
+         Int_t nextbit = -1;
+         while(1) {
+            nextbit = bits->FirstSetBit(nextbit+1);
+            if (nextbit >= nbits) break;
+            if (nextbit > ncx) refTrackTrigger->Fill(ncx+1);
+            else               refTrackTrigger->Fill(nextbit);
+         }
+         if (bits.TestBitNumber(5)) refFiltTrackTrigger->Fill(t->GetPx());
+
       }
    }
 
diff --git a/test/dt_Makefile b/test/dt_Makefile
index 6efa81da9c4..90962e01aa4 100644
--- a/test/dt_Makefile
+++ b/test/dt_Makefile
@@ -8,7 +8,8 @@ action=1
 
 include ./Makefile
 
-DATAFILES = Event.new.split0.root Event.new.split1.root Event.new.split9.root \
+DATAFILES = Event.new.split0.root Event.new.split1.root \
+	Event.new.split2.root  Event.new.split9.root \
 	Event.old.streamed.root Event.old.split.root
 
 REFFILE=dt_reference.root
@@ -27,6 +28,11 @@ Event.new.split1.root : Event$(ExeSuf) libEvent.$(DllSuf)
 	mv Event.root Event.new.split1.root && \
 	echo  "$@ made"
 
+Event.new.split2.root : Event$(ExeSuf) libEvent.$(DllSuf)
+	@./Event $(size) $(comp) 2 $(action) $(tracks) $(OUTPUT)  && \
+	mv Event.root Event.new.split2.root && \
+	echo  "$@ made"
+
 Event.new.split9.root : Event$(ExeSuf) libEvent.$(DllSuf)
 	@./Event $(size) $(comp) 9 $(action) $(tracks) $(OUTPUT) && \
 	mv Event.root Event.new.split9.root && \
@@ -52,7 +58,7 @@ Streamer="Event::Streamer not available,"
 
 
 dt_RunDrawTest_C.$(DllSuf) : dt_RunDrawTest.C dt_DrawTest.C
-	@root -l -b -q 'gSystem->Exit(!gSystem->CompileMacro("dt_RunDrawTest.C","kf"));' |  $(OUTPUT) && \
+	@root -l -b -q dt_build.C $(OUTPUT) && \
 	echo "$@ made"
 
 #Windows does not like piping 
diff --git a/test/dt_RunDrawTest.C b/test/dt_RunDrawTest.C
index 03ee0d33139..16bef0dddf7 100644
--- a/test/dt_RunDrawTest.C
+++ b/test/dt_RunDrawTest.C
@@ -21,7 +21,8 @@ Int_t HistCompare(TH1 *ref, TH1 *comp)
 // Compare histograms h1 and h2
 // Check number of entries, mean and rms
 // if means differ by more than 1/1000 of the range return -1
-// if rms differs in percent by more than 1/1000 return -2
+// if means differ by more than 1/100 of the original mean return -2
+// if rms differs in percent by more than 1/1000 return -3
 // Otherwise return difference of number of entries
 
    Int_t n1       = (Int_t)ref->GetEntries();
@@ -38,9 +39,10 @@ Int_t HistCompare(TH1 *ref, TH1 *comp)
    }
 
    Float_t xrange = ref->GetXaxis()->GetXmax() - ref->GetXaxis()->GetXmin();
-   if (xrange==0) fprintf(stderr,"no range for %s\n",ref->GetName());
-   if (TMath::Abs((mean1-mean2)/xrange) > 0.001*xrange) return -1;
-   if (rms1 && TMath::Abs((rms1-rms2)/rms1) > 0.001)    return -2;
+   if (xrange==0) { fprintf(stderr,"no range for %s\n",ref->GetName()); return -4; }
+   if (xrange>0.0001 && TMath::Abs((mean1-mean2)/xrange) > 0.001)  return -1;
+   if (mean2> 0.0001 && TMath::Abs((mean1-mean2)/mean2) > 0.01)    return -2;
+   if (rms1 > 0.0001 && TMath::Abs((rms1-rms2)/rms1) > 0.0001)     return -3;
    return n1*factor-n2;
 }
 
@@ -53,6 +55,7 @@ Int_t Compare(TDirectory* from) {
    Int_t comp;
    Int_t fail = 0;
    TKey* key;
+
    while ((key=(TKey*)next())) {
       if (strcmp(key->GetClassName(),"TH1F")
           && strcmp(key->GetClassName(),"TH2F") ) 
@@ -169,7 +172,7 @@ bool dt_RunDrawTest(const char* from, Int_t mode = 0, Int_t verboseLevel = 0) {
    // cerr << "Branch style is " << gBranchStyle << endl;
 
    if (gQuietLevel<2) cout << "Generating histograms from TTree::Draw" << endl;
-   TDirectory* where = GenerateDrawHist(tree,1,gQuietLevel);
+   TDirectory* where = GenerateDrawHist(tree,2,gQuietLevel);
  
    if (gQuietLevel<2) cout << "Comparing histograms" << endl;
    if (Compare(where)>0) {
diff --git a/test/dt_RunDrawTest.sh b/test/dt_RunDrawTest.sh
index 7ac0ee598ed..f4ad43d9032 100755
--- a/test/dt_RunDrawTest.sh
+++ b/test/dt_RunDrawTest.sh
@@ -1,48 +1,55 @@
-#!/bin/sh
+#!/bin/sh 
 
 # Previous step is to do something like
 # root -l -q 'MakeRef.C("Event.old.split.root");'
 
 ClassWarning='Warning in <TClass::TClass>: no dictionary for class'
 RootPrompt='root \[0\]'
+EmptyLine='^$'
 Streamer="Event::Streamer not available,"
 
 # launch replace
 # root.exe -l -b 'dt_RunDrawTest.C+("Event.new.split9.root",0)'
 launch () {
-  echo test $1 level $2 
+#  echo test $1 level $2 
 #  (echo 'gROOT->ProcessLine(".L dt_RunDrawTest.C+");gSystem->Exit(!dt_RunDrawTest("'$1'",'$2'));' | root.exe -l -b 2>&1; return $?;) | grep -v "$3";
 # (root.exe -l -b -q 'gROOT->ProcessLine(".L dt_RunDrawTest.C+");gSystem->Exit(!dt_RunDrawTest("'$1'",'$2'));' 2>&1; return $?;) | grep -v "$3";
   (root.exe -l -b -q 'dt_wrap.C("'$1'",'$2')' 2>&1; return $?;) | grep -v "$3";
 }
 
 
-launch "Event.old.split.root" 0 "$ClassWarning\|$RootPrompt" && \
-launch "Event.old.split.root" 1 "$RootPrompt" && \
-launch "Event.old.split.root" 2 "$ClassWarning\|$RootPrompt" && \
-launch "Event.old.split.root" 3 "$RootPrompt" && \
-launch "Event.old.split.root" 4 "$RootPrompt"
-
-launch "Event.old.streamed.root" 0 "$Streamer\|$ClassWarning\|$RootPrompt" && \
-launch "Event.old.streamed.root" 1 "$RootPrompt" && \
-launch "Event.old.streamed.root" 2 "$ClassWarning\|$RootPrompt" && \
-launch "Event.old.streamed.root" 3 "$RootPrompt" && \
-launch "Event.old.streamed.root" 4 "$RootPrompt"
-
-launch "Event.new.split9.root" 0 "$ClassWarning\|$RootPrompt" && \
-launch "Event.new.split9.root" 1 "$RootPrompt" && \
-launch "Event.new.split9.root" 2 "$ClassWarning\|$RootPrompt" && \
-launch "Event.new.split9.root" 3 "$RootPrompt" && \
-launch "Event.new.split9.root" 4 "$RootPrompt"
-
-launch "Event.new.split1.root" 0 "$ClassWarning\|$RootPrompt" && \
-launch "Event.new.split1.root" 1 "$RootPrompt" && \
-launch "Event.new.split1.root" 2 "$ClassWarning\|$RootPrompt" && \
-launch "Event.new.split1.root" 3 "$RootPrompt" && \
-launch "Event.new.split1.root" 4 "$RootPrompt"
-
-launch "Event.new.split0.root" 0 "$Streamer\|$ClassWarning\|$RootPrompt" && \
-launch "Event.new.split0.root" 1 "$RootPrompt" && \
-launch "Event.new.split0.root" 2 "$ClassWarning\|$RootPrompt" && \
-launch "Event.new.split0.root" 3 "$RootPrompt" && \
-launch "Event.new.split0.root" 4 "$RootPrompt"
+launch "Event.old.split.root" 0 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.old.split.root" 1 "$RootPrompt\|$EmptyLine" && \
+launch "Event.old.split.root" 2 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.old.split.root" 3 "$RootPrompt\|$EmptyLine" && \
+launch "Event.old.split.root" 4 "$RootPrompt\|$EmptyLine"
+
+launch "Event.old.streamed.root" 0 "$Streamer\|$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.old.streamed.root" 1 "$RootPrompt\|$EmptyLine" && \
+launch "Event.old.streamed.root" 2 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.old.streamed.root" 3 "$RootPrompt\|$EmptyLine" && \
+launch "Event.old.streamed.root" 4 "$RootPrompt\|$EmptyLine"
+
+launch "Event.new.split9.root" 0 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split9.root" 1 "$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split9.root" 2 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split9.root" 3 "$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split9.root" 4 "$RootPrompt\|$EmptyLine"
+
+launch "Event.new.split2.root" 0 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split2.root" 1 "$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split2.root" 2 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split2.root" 3 "$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split2.root" 4 "$RootPrompt\|$EmptyLine"
+
+launch "Event.new.split1.root" 0 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split1.root" 1 "$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split1.root" 2 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split1.root" 3 "$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split1.root" 4 "$RootPrompt\|$EmptyLine"
+
+launch "Event.new.split0.root" 0 "$Streamer\|$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split0.root" 1 "$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split0.root" 2 "$ClassWarning\|$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split0.root" 3 "$RootPrompt\|$EmptyLine" && \
+launch "Event.new.split0.root" 4 "$RootPrompt\|$EmptyLine"
diff --git a/treeplayer/inc/TTreeFormula.h b/treeplayer/inc/TTreeFormula.h
index df5d6011883..801e19dec72 100644
--- a/treeplayer/inc/TTreeFormula.h
+++ b/treeplayer/inc/TTreeFormula.h
@@ -1,4 +1,4 @@
-// @(#)root/treeplayer:$Name:  $:$Id: TTreeFormula.h,v 1.25 2002/08/01 21:33:48 brun Exp $
+// @(#)root/treeplayer:$Name:  $:$Id: TTreeFormula.h,v 1.26 2003/01/24 07:04:29 brun Exp $
 // Author: Rene Brun   19/01/96
 
 /*************************************************************************
@@ -110,7 +110,7 @@ public:
              TTreeFormula(const char *name,const char *formula, TTree *tree);
    virtual   ~TTreeFormula();
    virtual Int_t      DefinedVariable(TString &variable);
-   virtual TClass*    EvalClass();
+   virtual TClass*    EvalClass() const;
    virtual Double_t   EvalInstance(Int_t i=0);
    virtual void*      EvalObject(Int_t i=0);
    // EvalInstance should be const.  See comment on GetNdata()
diff --git a/treeplayer/src/TSelectorDraw.cxx b/treeplayer/src/TSelectorDraw.cxx
index 234e25335aa..7fb65cea2e9 100644
--- a/treeplayer/src/TSelectorDraw.cxx
+++ b/treeplayer/src/TSelectorDraw.cxx
@@ -1,4 +1,4 @@
-// @(#)root/treeplayer:$Name:  $:$Id: TSelectorDraw.cxx,v 1.5 2003/01/17 17:48:09 brun Exp $
+// @(#)root/treeplayer:$Name:  $:$Id: TSelectorDraw.cxx,v 1.6 2003/01/24 07:04:29 brun Exp $
 // Author: Rene Brun   08/01/2003
 
 /*************************************************************************
@@ -926,7 +926,7 @@ void TSelectorDraw::ProcessFillObject(Int_t /*entry*/)
          TClass *cl = fVar1->EvalClass();
          if (cl==TBits::Class()) {
 
-            void *obj = fVar1->EvalObject();
+            void *obj = fVar1->EvalObject(i);
 
             TBits *bits = (TBits*)obj;
             Int_t nbits = bits->GetNbits();
@@ -940,6 +940,12 @@ void TSelectorDraw::ProcessFillObject(Int_t /*entry*/)
                fNfill++;
             }
             
+         } else {
+
+           Warning("ProcessFillObject",
+                   "Not implemented for %s",
+                   cl?cl->GetName():"unknown class");
+
          }
       }
    }
diff --git a/treeplayer/src/TTreeFormula.cxx b/treeplayer/src/TTreeFormula.cxx
index 8c3b97511ca..eca2cd1f008 100644
--- a/treeplayer/src/TTreeFormula.cxx
+++ b/treeplayer/src/TTreeFormula.cxx
@@ -1,4 +1,4 @@
-// @(#)root/treeplayer:$Name:  $:$Id: TTreeFormula.cxx,v 1.107 2003/01/17 17:48:09 brun Exp $
+// @(#)root/treeplayer:$Name:  $:$Id: TTreeFormula.cxx,v 1.108 2003/01/24 07:04:29 brun Exp $
 // Author: Rene Brun   19/01/96
 
 /*************************************************************************
@@ -1973,7 +1973,7 @@ Int_t TTreeFormula::DefinedVariable(TString &name)
       strcat(right,&cname[i]);
    }
 
-   if (!final && branch) { // NOTE: should we add && !leaf ???
+   if (!final && branch && !leaf) { // NOTE: should we add && !leaf ???
       leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(0);
       if (!leaf) return -1;
       final = leaf->IsOnTerminalBranch();
@@ -2114,8 +2114,8 @@ Int_t TTreeFormula::DefinedVariable(TString &name)
             }
             break;
          }
-         // If we have a got a class object, we need to verify whether it is on a split TClonesArray
-         // sub branch.
+         // If we got a class object, we need to verify whether it is on a
+         // split TClonesArray sub branch.
          if (cl && BranchEl->GetBranchCount()) {
            if (BranchEl->GetType()==31) {
               // This is inside a TClonesArray.
@@ -2144,6 +2144,20 @@ Int_t TTreeFormula::DefinedVariable(TString &name)
               maininfo->fNext = previnfo;
 
            }
+         } else if (BranchEl->GetType()==3) {
+
+            TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, &gFakeClonesElem, kTRUE);
+            // The dimension needs to be handled!
+            numberOfVarDim += RegisterDimensions(code,clonesinfo);
+              
+            maininfo = clonesinfo;
+            previnfo = maininfo;
+
+         } else if (strlen(right)==0 && cl && element && !element->IsaPointer() && final) {
+           
+            maininfo = new TFormLeafInfoDirect(BranchEl); 
+            previnfo = maininfo;
+
          }
       }
       if (cl) {
@@ -3021,7 +3035,7 @@ Int_t TTreeFormula::GetRealInstance(Int_t instance, Int_t codeindex) {
 }
 
 //______________________________________________________________________________
-TClass* TTreeFormula::EvalClass()
+TClass* TTreeFormula::EvalClass() const
 {
 //*-*-*-*-*-*-*-*-*-*-*Evaluate the class of this treeformula*-*-*-*-*-*-*-*-*-*
 //*-*                  ======================================
@@ -3037,8 +3051,11 @@ TClass* TTreeFormula::EvalClass()
          if (leaf->IsA()==TLeafObject::Class()) {
             return ((TLeafObject*)leaf)->GetClass();
          } else if ( leaf->IsA()==TLeafElement::Class()) {
-            TBranchElement * br = (TBranchElement*)((TLeafElement*)leaf)->GetBranch();
-            return gROOT->GetClass( br->GetTypeName() );
+            TBranchElement * branch = (TBranchElement*)((TLeafElement*)leaf)->GetBranch();
+            TStreamerInfo * info = branch->GetInfo();
+            Int_t id = branch->GetID();
+            TStreamerElement* elem = (TStreamerElement*)info->GetElements()->At(id);
+            return gROOT->GetClass( elem->GetTypeName() );
          } else {
             return 0;
          }
@@ -3086,7 +3103,7 @@ void* TTreeFormula::EvalObject(int instance)
    switch(fLookupType[0]) {
       case kDirect: {
         if (real_instance) {
-          Warning("EvalObject","Not yet implement for kDirect and arrays.\nPlease contact the developers (%s)\n",GetName());
+          Warning("EvalObject","Not yet implement for kDirect and arrays (for %s).\nPlease contact the developers \n",GetName());
         }
         return leaf->GetValuePointer();
       }
@@ -3494,6 +3511,8 @@ Bool_t TTreeFormula::IsInteger(Int_t code) const
            return kFALSE;
       }
    }
+   
+   if (EvalClass()==TBits::Class()) return kTRUE;
 
    TLeaf *leaf = (TLeaf*)fLeaves.At(code);
    if (!leaf) return kFALSE;
-- 
GitLab