From 32b8056e18665aed94702f85acb8489de7d10b9c Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Fri, 11 Mar 2005 21:25:11 +0000
Subject: [PATCH] From Philippe: This patch implements support for the
 accessing the collection object in TTreeFormula:

//     Accessing collection objects
//     ============================
//
//  TTree::Draw default's handling of collections is to assume that any
//  request on a collection pertain to it content.  For example, if fTracks
//  is a collection of Track objects, the following:
//      tree->Draw("event.fTracks.fPx");
//  will plot the value of fPx for each Track objects inside the collection.
//  Also
//     tree->Draw("event.fTracks.size()");
//  would plot the result of the member function Track::size() for each
//  Track object inside the collection.
//  To access information about the collection itself, TTree::Draw support
//  the '@' notation.  If a variable which points to a collection is
prefixed
//  or postfixed with '@', the next part of the expression will pertain to
//  the collection object.  For example:
//     tree->Draw("event.@fTracks.size()");
//  will plot the size of the collection refered to by fTracks (i.e the
number
//  of Track objects).


git-svn-id: http://root.cern.ch/svn/root/trunk@11309 27541ba8-7e3a-0410-8455-c3a389f83636
---
 cont/src/TEmulatedCollectionProxy.cxx |   4 +-
 hist/src/TFormula.cxx                 |   6 +-
 io/src/TEmulatedCollectionProxy.cxx   |   4 +-
 test/dt_DrawTest.C                    |   8 +-
 test/dt_MakeRef.C                     |   7 +
 test/dt_RunDrawTest.C                 |   2 +-
 tree/src/TTree.cxx                    |  22 +-
 treeplayer/inc/TFormLeafInfo.h        |  25 ++-
 treeplayer/inc/TTreeFormula.h         |  10 +-
 treeplayer/src/TFormLeafInfo.cxx      |  92 ++++++++-
 treeplayer/src/TTreeFormula.cxx       | 277 +++++++++++++++++---------
 treeplayer/src/TTreePlayer.cxx        |  22 +-
 12 files changed, 363 insertions(+), 116 deletions(-)

diff --git a/cont/src/TEmulatedCollectionProxy.cxx b/cont/src/TEmulatedCollectionProxy.cxx
index 39a3d3eaabe..5a494df5922 100644
--- a/cont/src/TEmulatedCollectionProxy.cxx
+++ b/cont/src/TEmulatedCollectionProxy.cxx
@@ -1,4 +1,4 @@
-// @(#)root/cont:$Name:  $:$Id: TEmulatedCollectionProxy.cxx,v 1.7 2005/01/19 18:30:58 brun Exp $
+// @(#)root/cont:$Name:  $:$Id: TEmulatedCollectionProxy.cxx,v 1.8 2005/03/10 22:26:15 rdm Exp $
 // Author: Markus Frank 28/10/04
 
 /*************************************************************************
@@ -301,7 +301,7 @@ void* TEmulatedCollectionProxy::At(UInt_t idx)   {
     if ( idx >= (s/fValDiff) )  {
       return 0;
     }
-    return idx<(c->size()/fValDiff) ? ((char*)&(*c->begin()))+idx*fValDiff : 0;
+    return idx<(s/fValDiff) ? ((char*)&(*c->begin()))+idx*fValDiff : 0;
   }
   Fatal("TEmulatedCollectionProxy","At> Logic error - no proxy object set.");
   return 0;
diff --git a/hist/src/TFormula.cxx b/hist/src/TFormula.cxx
index db8a987d383..6fc6a837ace 100644
--- a/hist/src/TFormula.cxx
+++ b/hist/src/TFormula.cxx
@@ -1,4 +1,4 @@
-// @(#)root/hist:$Name:  $:$Id: TFormula.cxx,v 1.90 2005/03/04 18:38:52 brun Exp $
+// @(#)root/hist:$Name:  $:$Id: TFormula.cxx,v 1.91 2005/03/04 19:37:52 brun Exp $
 // Author: Nicolas Brun   19/08/95
 
 /*************************************************************************
@@ -553,7 +553,7 @@ void TFormula::Analyze(const char *schain, Int_t &err, Int_t offset)
 //*-*    28  : strstr requires two arguments
 //*-*    29  : interpreted or compiled function have to return a numerical type
 //*-*    30  : Bad numerical expression
-//*-*    31  : Variable exist but is not accessible
+//*-*    31  : Part of the variable exist but some of it is not accessible or useable
 //*-*    40  : '(' is expected
 //*-*    41  : ')' is expected
 //*-*    42  : '[' is expected
@@ -1838,7 +1838,7 @@ void TFormula::Analyze(const char *schain, Int_t &err, Int_t offset)
         case 29 : cout<<" TFormula can only call interpreted and compiled functions that return a numerical type: \n"
                       <<chaine_error<<endl; break;
         case 30 : cout<<" Bad numerical expression : \""<<(const char*)chaine_error<<"\""<<endl; break;
-        case 31 : cout<<" The Variable :  \""<<(const char*)chaine_error<<"\" exists but is not accessible"<<endl; break;
+        case 31 : cout<<" Part of the Variable :  \""<<(const char*)chaine_error<<"\" exists but some of it is not accessible or useable"<<endl; break;
         case 40 : cout<<" '(' is expected"<<endl; break;
         case 41 : cout<<" ')' is expected"<<endl; break;
         case 42 : cout<<" '[' is expected"<<endl; break;
diff --git a/io/src/TEmulatedCollectionProxy.cxx b/io/src/TEmulatedCollectionProxy.cxx
index 39a3d3eaabe..5a494df5922 100644
--- a/io/src/TEmulatedCollectionProxy.cxx
+++ b/io/src/TEmulatedCollectionProxy.cxx
@@ -1,4 +1,4 @@
-// @(#)root/cont:$Name:  $:$Id: TEmulatedCollectionProxy.cxx,v 1.7 2005/01/19 18:30:58 brun Exp $
+// @(#)root/cont:$Name:  $:$Id: TEmulatedCollectionProxy.cxx,v 1.8 2005/03/10 22:26:15 rdm Exp $
 // Author: Markus Frank 28/10/04
 
 /*************************************************************************
@@ -301,7 +301,7 @@ void* TEmulatedCollectionProxy::At(UInt_t idx)   {
     if ( idx >= (s/fValDiff) )  {
       return 0;
     }
-    return idx<(c->size()/fValDiff) ? ((char*)&(*c->begin()))+idx*fValDiff : 0;
+    return idx<(s/fValDiff) ? ((char*)&(*c->begin()))+idx*fValDiff : 0;
   }
   Fatal("TEmulatedCollectionProxy","At> Logic error - no proxy object set.");
   return 0;
diff --git a/test/dt_DrawTest.C b/test/dt_DrawTest.C
index 258d0a3f7a8..6ebc43f9f5b 100644
--- a/test/dt_DrawTest.C
+++ b/test/dt_DrawTest.C
@@ -56,7 +56,7 @@ void DrawMarks() {
 
 
 //_______________________________________________________________
-TDirectory* GenerateDrawHist(TTree *tree,int level = 2, int quietLevel = 0)
+TDirectory* GenerateDrawHist(TTree *tree, int quietLevel = 0, int level = 3)
 {
 // Test selections via TreeFormula
 // tree is a TTree when called by stress9
@@ -184,6 +184,12 @@ TDirectory* GenerateDrawHist(TTree *tree,int level = 2, int quietLevel = 0)
                  "",
                  "hAlt", level>1 && gBranchStyle!=0);
 
+   // Test on the @ notation to access the collection object itself
+   DrawSkippable(tree,"event.@fTracks.size()","","hSize",level>2 && !(gBranchStyle==0 && !gHasLibrary));
+   DrawSkippable(tree,"event.fTracks@.size()","","+hSize",level>2 && !(gBranchStyle==0 && !gHasLibrary));
+   DrawSkippable(tree,"@fTracks.size()","","hSize2",level>2 && gBranchStyle!=0);
+   DrawSkippable(tree,"fTracks@.size()","","+hSize2",level>2 && 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 7fc8e3b9a70..79ea35022b0 100644
--- a/test/dt_MakeRef.C
+++ b/test/dt_MakeRef.C
@@ -117,6 +117,9 @@ void MakeHisto(TTree *tree, TDirectory* To) {
 
    TH1F *refAlt = RefClone(where,"hAlt");
 
+   TH1F *refSize  = RefClone(where,"hSize");
+   TH1F *refSize2 = RefClone(where,"hSize2");
+
    // Loop with user code on all events and fill the ref histograms
    // The code below should produce identical results to the tree->Draw above
 
@@ -193,6 +196,10 @@ void MakeHisto(TTree *tree, TDirectory* To) {
       if (bits.TestBitNumber(10)) refFiltTriggerBits->Fill(nbits);
 
       ntracks = event->GetNtrack();
+      refSize->Fill(ntracks);
+      refSize->Fill(ntracks);
+      refSize2->Fill(ntracks);
+      refSize2->Fill(ntracks);
       if ( 5 < ntracks ) {
          t = (Track*)tracks->UncheckedAt(5);
          for(i0=0;i0<4;i0++) {
diff --git a/test/dt_RunDrawTest.C b/test/dt_RunDrawTest.C
index c17d0c9a5ad..ebc38034495 100644
--- a/test/dt_RunDrawTest.C
+++ b/test/dt_RunDrawTest.C
@@ -172,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,2,gQuietLevel);
+   TDirectory* where = GenerateDrawHist(tree,gQuietLevel);
  
    if (gQuietLevel<2) cout << "Comparing histograms" << endl;
    if (Compare(where)>0) {
diff --git a/tree/src/TTree.cxx b/tree/src/TTree.cxx
index fb29f45812b..2cde04804c1 100644
--- a/tree/src/TTree.cxx
+++ b/tree/src/TTree.cxx
@@ -1,4 +1,4 @@
-// @(#)root/tree:$Name:  $:$Id: TTree.cxx,v 1.237 2005/03/07 18:08:25 brun Exp $
+// @(#)root/tree:$Name:  $:$Id: TTree.cxx,v 1.238 2005/03/10 17:57:04 rdm Exp $
 // Author: Rene Brun   12/01/96
 
 /*************************************************************************
@@ -2220,6 +2220,26 @@ Long64_t TTree::Draw(const char *varexp, const char *selection, Option_t *option
 //      will not reset hsqrt, but will continue filling.
 //  This works for 1-D, 2-D and 3-D histograms.
 //
+//     Accessing collection objects
+//     ============================
+//
+//  TTree::Draw default's handling of collections is to assume that any 
+//  request on a collection pertain to it content.  For example, if fTracks
+//  is a collection of Track objects, the following:
+//      tree->Draw("event.fTracks.fPx");
+//  will plot the value of fPx for each Track objects inside the collection.
+//  Also
+//     tree->Draw("event.fTracks.size()");
+//  would plot the result of the member function Track::size() for each
+//  Track object inside the collection.
+//  To access information about the collection itself, TTree::Draw support
+//  the '@' notation.  If a variable which points to a collection is prefixed
+//  or postfixed with '@', the next part of the expression will pertain to
+//  the collection object.  For example:
+//     tree->Draw("event.@fTracks.size()");
+//  will plot the size of the collection refered to by fTracks (i.e the number
+//  of Track objects).
+//
 //     Special functions and variables
 //     ===============================
 //
diff --git a/treeplayer/inc/TFormLeafInfo.h b/treeplayer/inc/TFormLeafInfo.h
index b5d0f6069e3..89479334507 100644
--- a/treeplayer/inc/TFormLeafInfo.h
+++ b/treeplayer/inc/TFormLeafInfo.h
@@ -1,4 +1,4 @@
-// @(#)root/treeplayer:$Name:  $:$Id: TFormLeafInfo.h,v 1.1 2004/06/17 17:37:10 brun Exp $
+// @(#)root/treeplayer:$Name:  $:$Id: TFormLeafInfo.h,v 1.2 2005/02/25 19:13:24 brun Exp $
 // Author: Philippe Canal 01/06/2004
 
 /*************************************************************************
@@ -127,6 +127,29 @@ public:
    virtual Bool_t    Update();
 };
 
+//______________________________________________________________________________
+//
+// TFormLeafInfoCollectionObject
+// This class is used when we are interested by the collection it self and
+// it is split.
+
+class TFormLeafInfoCollectionObject : public TFormLeafInfo {
+public:
+   TFormLeafInfoCollectionObject(TClass* classptr = 0);
+
+   virtual TFormLeafInfo* DeepCopy() const {
+      return new TFormLeafInfoCollectionObject(*this);
+   }
+
+   virtual Int_t     GetCounterValue(TLeaf* leaf);
+   virtual Double_t  ReadValue(char *where, Int_t instance = 0);
+   virtual Double_t  GetValue(TLeaf *leaf, Int_t instance = 0);
+   virtual void     *GetValuePointer(TLeaf *leaf, Int_t instance = 0);
+   virtual void     *GetValuePointer(char  *thisobj, Int_t instance = 0);
+   virtual void     *GetLocalValuePointer(TLeaf *leaf, Int_t instance = 0);
+   virtual void     *GetLocalValuePointer(char  *thisobj, Int_t instance = 0);
+};
+
 //______________________________________________________________________________
 //
 // TFormLeafInfoClones is a small helper class to implement reading a data
diff --git a/treeplayer/inc/TTreeFormula.h b/treeplayer/inc/TTreeFormula.h
index e8ef5eec11f..cb7e48e26f8 100644
--- a/treeplayer/inc/TTreeFormula.h
+++ b/treeplayer/inc/TTreeFormula.h
@@ -1,4 +1,4 @@
-// @(#)root/treeplayer:$Name:  $:$Id: TTreeFormula.h,v 1.41 2005/02/18 09:15:08 rdm Exp $
+// @(#)root/treeplayer:$Name:  $:$Id: TTreeFormula.h,v 1.42 2005/03/08 05:33:30 brun Exp $
 // Author: Rene Brun   19/01/96
 
 /*************************************************************************
@@ -111,12 +111,12 @@ protected:
    Bool_t      BranchHasMethod(TLeaf* leaf, TBranch* branch, const char* method,const char* params, Long64_t readentry) const;
    Int_t       DefineAlternate(const char* expression);
    void        DefineDimensions(Int_t code, Int_t size, TFormLeafInfoMultiVarDim * info, Int_t& virt_dim);
-   Int_t       FindLeafForExpression(const char* expression, TLeaf *&leaf, TString &leftover, Bool_t &final, UInt_t &paran_level, TObjArray &castqueue, std::vector<std::string>&, const char *fullExpression);
+   Int_t       FindLeafForExpression(const char* expression, TLeaf *&leaf, TString &leftover, Bool_t &final, UInt_t &paran_level, TObjArray &castqueue, std::vector<std::string>& aliasUsed, Bool_t &useLeafCollectionObject, const char *fullExpression);
    TLeaf*      GetLeafWithDatamember(const char* topchoice, const char* nextchice, Long64_t readentry) const;
-   Int_t       ParseWithLeaf(TLeaf *leaf, const char *expression, Bool_t final, UInt_t paran_level, TObjArray &castqueue, const char *fullExpression);
-   Int_t       RegisterDimensions(Int_t code, Int_t size, TFormLeafInfoMultiVarDim * multidim = 0);
+   Int_t       ParseWithLeaf(TLeaf *leaf, const char *expression, Bool_t final, UInt_t paran_level, TObjArray &castqueue, Bool_t useLeafCollectionObject, const char *fullExpression);
+   Int_t       RegisterDimensions(Int_t code, Int_t size, TFormLeafInfoMultiVarDim * multidim = 0);
    Int_t       RegisterDimensions(Int_t code, TBranchElement *branch);
-   Int_t       RegisterDimensions(Int_t code, TFormLeafInfo *info);
+   Int_t       RegisterDimensions(Int_t code, TFormLeafInfo *info, Bool_t useCollectionObject);
    Int_t       RegisterDimensions(Int_t code, TLeaf *leaf);
    Int_t       RegisterDimensions(const char *size, Int_t code);
 
diff --git a/treeplayer/src/TFormLeafInfo.cxx b/treeplayer/src/TFormLeafInfo.cxx
index f5218d45f6e..c0152d51e7f 100644
--- a/treeplayer/src/TFormLeafInfo.cxx
+++ b/treeplayer/src/TFormLeafInfo.cxx
@@ -1,4 +1,4 @@
-// @(#)root/treeplayer:$Name:  $:$Id: TFormLeafInfo.cxx,v 1.14 2005/02/25 19:13:24 brun Exp $
+// @(#)root/treeplayer:$Name:  $:$Id: TFormLeafInfo.cxx,v 1.15 2005/02/25 21:49:04 brun Exp $
 // Author: Philippe Canal 01/06/2004
 
 /*************************************************************************
@@ -875,17 +875,17 @@ Bool_t TFormLeafInfoNumerical::Update()
    return kFALSE;
 }
 
-//______________________________________________________________________________
-//
-// TFormLeafInfoClones is a small helper class to implement reading a data member
-// on a TClonesArray object stored in a TTree.
-
 namespace {
    static TStreamerElement gFakeClonesElem("begin","fake",0,
                                            TStreamerInfo::kAny,
                                            "TClonesArray");
 }
 
+//______________________________________________________________________________
+//
+// TFormLeafInfoClones is a small helper class to implement reading a data member
+// on a TClonesArray object stored in a TTree.
+
 //______________________________________________________________________________
 TFormLeafInfoClones::TFormLeafInfoClones(TClass* classptr, Long_t offset) :
    TFormLeafInfo(classptr,offset,&gFakeClonesElem),fTop(kFALSE)
@@ -1032,6 +1032,86 @@ void * TFormLeafInfoClones::GetValuePointer(char *where, Int_t instance) {
    return clones;
 }
 
+//______________________________________________________________________________
+//
+// TFormLeafInfoCollectionObject is a small helper class to implement reading a data member
+// on a TClonesArray object stored in a TTree.
+
+//______________________________________________________________________________
+TFormLeafInfoCollectionObject::TFormLeafInfoCollectionObject(TClass* classptr) :
+   TFormLeafInfo(classptr,0,&gFakeClonesElem)
+{
+}
+
+//______________________________________________________________________________
+Int_t TFormLeafInfoCollectionObject::GetCounterValue(TLeaf* leaf) 
+{
+   // Return the current size of the the TClonesArray
+
+   return 1;
+}
+
+//______________________________________________________________________________
+Double_t TFormLeafInfoCollectionObject::ReadValue(char *where, Int_t instance) 
+{
+   // Return the value of the underlying data member inside the
+   // clones array.
+
+   Assert(0);
+   return 0;
+}
+
+//______________________________________________________________________________
+void* TFormLeafInfoCollectionObject::GetLocalValuePointer(TLeaf *leaf, Int_t /*instance*/)
+{
+   // Return the pointer to the clonesArray
+
+   void* collection;
+   if (leaf->InheritsFrom("TLeafObject") ) {
+      collection = ((TLeafObject*)leaf)->GetObject();
+   } else {
+      collection = ((TBranchElement*)leaf->GetBranch())->GetObject();
+   }
+   return collection;
+}
+
+//______________________________________________________________________________
+void* TFormLeafInfoCollectionObject::GetLocalValuePointer(char *where, Int_t instance) {
+   return TFormLeafInfo::GetLocalValuePointer(where,instance);
+}
+
+//______________________________________________________________________________
+Double_t TFormLeafInfoCollectionObject::GetValue(TLeaf *leaf, Int_t instance) {
+   // Return the value of the underlying data member inside the
+   // clones array.
+
+   char * obj = (char*)GetLocalValuePointer(leaf);
+
+   if (fNext==0) return 0;
+   return fNext->ReadValue(obj,instance);
+}
+
+//______________________________________________________________________________
+void * TFormLeafInfoCollectionObject::GetValuePointer(TLeaf *leaf, Int_t instance) {
+   // Return the pointer to the clonesArray
+
+   void *collection = GetLocalValuePointer(leaf);
+   if (fNext) {
+      return fNext->GetValuePointer((char*)collection,instance);
+   }
+   return collection;
+}
+
+//______________________________________________________________________________
+void * TFormLeafInfoCollectionObject::GetValuePointer(char *where, Int_t instance) {
+   // Return the pointer to the clonesArray
+
+   if (fNext) {
+      return fNext->GetValuePointer(where,instance);
+   }
+   return where;
+}
+
 //______________________________________________________________________________
 //
 // TFormLeafInfoCollection is a small helper class to implement reading a data
diff --git a/treeplayer/src/TTreeFormula.cxx b/treeplayer/src/TTreeFormula.cxx
index 090b9af76f6..dafded656e3 100644
--- a/treeplayer/src/TTreeFormula.cxx
+++ b/treeplayer/src/TTreeFormula.cxx
@@ -1,4 +1,4 @@
-// @(#)root/treeplayer:$Name:  $:$Id: TTreeFormula.cxx,v 1.168 2005/03/07 17:00:17 brun Exp $
+// @(#)root/treeplayer:$Name:  $:$Id: TTreeFormula.cxx,v 1.169 2005/03/08 05:33:30 brun Exp $
 // Author: Rene Brun   19/01/96
 
 /*************************************************************************
@@ -395,7 +395,8 @@ Int_t TTreeFormula::RegisterDimensions(Int_t code, Int_t size, TFormLeafInfoMult
 }
 
 //______________________________________________________________________________
-Int_t TTreeFormula::RegisterDimensions(Int_t code, TFormLeafInfo *leafinfo) {
+Int_t TTreeFormula::RegisterDimensions(Int_t code, TFormLeafInfo *leafinfo,
+                                       Bool_t useCollectionObject) {
    // This method is used internally to decode the dimensions of the variables
 
    Int_t ndim, size, current, vardim;
@@ -428,7 +429,7 @@ Int_t TTreeFormula::RegisterDimensions(Int_t code, TFormLeafInfo *leafinfo) {
       TStreamerElement* counter = cl->GetStreamerInfo()->GetStreamerElement(array->GetCountName(),offset);
       leafinfo->fCounter = new TFormLeafInfo(cl,offset,counter);
 
-   } else if (elem->GetClassPointer() == TClonesArray::Class() ) {
+   } else if (!useCollectionObject && elem->GetClassPointer() == TClonesArray::Class() ) {
 
       ndim = 1;
       size = -1;
@@ -438,7 +439,7 @@ Int_t TTreeFormula::RegisterDimensions(Int_t code, TFormLeafInfo *leafinfo) {
       TStreamerElement *counter = ClonesClass->GetStreamerInfo()->GetStreamerElement("fLast",c_offset);
       leafinfo->fCounter = new TFormLeafInfo(ClonesClass,c_offset,counter);
 
-   } else if (elem->GetClassPointer() && elem->GetClassPointer()->GetCollectionProxy() ) {
+   } else if (!useCollectionObject && elem->GetClassPointer() && elem->GetClassPointer()->GetCollectionProxy() ) {
 
       if ( typeid(*leafinfo) == typeid(TFormLeafInfoCollection) ) {
          ndim = 1;
@@ -647,8 +648,9 @@ Int_t TTreeFormula::DefineAlternate(const char *expression)
 //______________________________________________________________________________
 Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression, 
                                   Bool_t final, UInt_t paran_level,
-                                   TObjArray &castqueue, 
-                                   const char* fullExpression) 
+                                  TObjArray &castqueue, 
+                                  Bool_t useLeafCollectionObject,
+                                  const char* fullExpression) 
 {
    // Decompose 'expression' as pointing to something inside the leaf
    // Returns:
@@ -874,69 +876,87 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
             unwindCollection = kTRUE;
          }
 
-      } else if (BranchEl->GetType()==3) {
-
-         TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, kTRUE);
-         // The dimension needs to be handled!
-         numberOfVarDim += RegisterDimensions(code,clonesinfo);
+      } else if ( BranchEl->GetType()==3) {
+         TFormLeafInfo* clonesinfo;
+         if (useLeafCollectionObject) {
+            clonesinfo = new TFormLeafInfoCollectionObject(cl);
+         } else {
+            clonesinfo = new TFormLeafInfoClones(cl, 0, kTRUE);
+            // The dimension needs to be handled!
+            numberOfVarDim += RegisterDimensions(code,clonesinfo,useLeafCollectionObject);
 
+         }
          maininfo = clonesinfo;
          previnfo = maininfo;
 
-      } else if (BranchEl->GetType()==4) {
+      } else if (!useLeafCollectionObject && BranchEl->GetType()==4) {
 
-         TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE);
-         // The dimension needs to be handled!
-         numberOfVarDim += RegisterDimensions(code,collectioninfo);
+         TFormLeafInfo* collectioninfo;
+         if (useLeafCollectionObject) {
+             collectioninfo = new TFormLeafInfoCollectionObject(cl);
+         } else {
+             collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE);
+             // The dimension needs to be handled!
+             numberOfVarDim += RegisterDimensions(code,collectioninfo,useLeafCollectionObject);
+         }
 
          maininfo = collectioninfo;
          previnfo = maininfo;
 
       } else if (BranchEl->GetStreamerType()==-1 && cl && cl->GetCollectionProxy()) {
 
-         TFormLeafInfo *collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE);
-         // The dimension needs to be handled!
-         numberOfVarDim += RegisterDimensions(code,collectioninfo);
+         if (useLeafCollectionObject) {
 
-         maininfo = collectioninfo;
-         previnfo = collectioninfo;
-         
-         if (cl->GetCollectionProxy()->GetValueClass()!=0 &&
-             cl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()!=0) {
+            TFormLeafInfo *collectioninfo = new TFormLeafInfoCollectionObject(cl);
+            maininfo = collectioninfo;
+            previnfo = collectioninfo;
 
-            TFormLeafInfo *multi = new TFormLeafInfoMultiVarDimCollection(cl,0,
-               cl->GetCollectionProxy()->GetValueClass(),collectioninfo);
+         } else {
+            TFormLeafInfo *collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE);
+            // The dimension needs to be handled!
+            numberOfVarDim += RegisterDimensions(code,collectioninfo,kFALSE);
 
-            fHasMultipleVarDim[code] = kTRUE;
-            numberOfVarDim += RegisterDimensions(code,multi);
-            previnfo->fNext = multi;
-            cl = cl->GetCollectionProxy()->GetValueClass();
-            multi->fNext =  new TFormLeafInfoCollection(cl, 0, cl, false);
-            previnfo = multi->fNext;
+            maininfo = collectioninfo;
+            previnfo = collectioninfo;
 
-         } 
-         if (cl->GetCollectionProxy()->GetValueClass()==0 &&
-               cl->GetCollectionProxy()->GetType()>0) {
+            if (cl->GetCollectionProxy()->GetValueClass()!=0 &&
+                cl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()!=0) {
 
-            previnfo->fNext = 
-               new TFormLeafInfoNumerical(cl->GetCollectionProxy()->GetType());
-            previnfo = previnfo->fNext;
-         } else {
-            // nothing to do
+               TFormLeafInfo *multi = new TFormLeafInfoMultiVarDimCollection(cl,0,
+                     cl->GetCollectionProxy()->GetValueClass(),collectioninfo);
+
+               fHasMultipleVarDim[code] = kTRUE;
+               numberOfVarDim += RegisterDimensions(code,multi, kFALSE);
+               previnfo->fNext = multi;
+               cl = cl->GetCollectionProxy()->GetValueClass();
+               multi->fNext =  new TFormLeafInfoCollection(cl, 0, cl, false);
+               previnfo = multi->fNext;
+
+            } 
+            if (cl->GetCollectionProxy()->GetValueClass()==0 &&
+                cl->GetCollectionProxy()->GetType()>0) {
+
+               previnfo->fNext = 
+                        new TFormLeafInfoNumerical(cl->GetCollectionProxy()->GetType());
+               previnfo = previnfo->fNext;
+            } else {
+               // nothing to do
+            }
          }
 
       } else if (strlen(right)==0 && cl && element && final) {
 
          TClass *elemCl = element->GetClassPointer();
-         if (elemCl && elemCl->GetCollectionProxy()
-               && elemCl->GetCollectionProxy()->GetValueClass()
-               && elemCl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()) {
+         if (!useLeafCollectionObject 
+             && elemCl && elemCl->GetCollectionProxy()
+             && elemCl->GetCollectionProxy()->GetValueClass()
+             && elemCl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()) {
 
             TFormLeafInfo *collectioninfo = 
                new TFormLeafInfoCollection(cl, 0, elemCl);
 
             // The dimension needs to be handled!
-            numberOfVarDim += RegisterDimensions(code,collectioninfo);
+            numberOfVarDim += RegisterDimensions(code,collectioninfo,kFALSE);
 
             maininfo = collectioninfo;
             previnfo = collectioninfo;
@@ -947,7 +967,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                                                       collectioninfo);
 
             fHasMultipleVarDim[code] = kTRUE;
-            numberOfVarDim += RegisterDimensions(code,multi);
+            numberOfVarDim += RegisterDimensions(code,multi,kFALSE);
             previnfo->fNext = multi;
             cl = elemCl->GetCollectionProxy()->GetValueClass();
             multi->fNext =  new TFormLeafInfoCollection(cl, 0, cl, false);
@@ -961,7 +981,8 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                previnfo = previnfo->fNext;
             } 
 
-         } else if (elemCl && elemCl->GetCollectionProxy()
+         } else if (!useLeafCollectionObject 
+               && elemCl && elemCl->GetCollectionProxy()
                && elemCl->GetCollectionProxy()->GetValueClass()==0
                && elemCl->GetCollectionProxy()->GetType()>0) {
 
@@ -974,7 +995,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                new TFormLeafInfoCollection(cl, 0, elemCl);
 
             // The dimension needs to be handled!
-            numberOfVarDim += RegisterDimensions(code,collectioninfo);
+            numberOfVarDim += RegisterDimensions(code,collectioninfo, kFALSE);
 
             collectioninfo->fNext = 
                new TFormLeafInfoNumerical(elemCl->GetCollectionProxy()->GetType());
@@ -1001,11 +1022,11 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
          // directly a collection.
          Assert(numberOfVarDim==1 && maininfo);
 
-         if (cl && cl->GetCollectionProxy()) {
+         if (!useLeafCollectionObject && cl && cl->GetCollectionProxy()) {
             TFormLeafInfo *multi = 
                new TFormLeafInfoMultiVarDimCollection(cl, 0, cl, maininfo);
             fHasMultipleVarDim[code] = kTRUE;
-            numberOfVarDim += RegisterDimensions(code,multi);
+            numberOfVarDim += RegisterDimensions(code,multi,kFALSE);
             previnfo->fNext = multi;
 
             multi->fNext =  new TFormLeafInfoCollection(cl, 0, cl, false);
@@ -1057,6 +1078,8 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
       }
 
       Int_t i;
+      Bool_t prevUseCollectionObject = useLeafCollectionObject;
+      Bool_t useCollectionObject = useLeafCollectionObject;
       for (i=0, current = &(work[0]); i<=nchname;i++ ) {
          // We will treated the terminator as a token.
          if (right[i] == '(') {
@@ -1078,8 +1101,8 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                Error("DefinedVariable","Class probably unavailable:%s",cl->GetName());
                return -2;
             }
-            if (cl == TClonesArray::Class()) {
-               // We are NEVER interested in the ClonesArray object but only
+            if (!useCollectionObject && cl == TClonesArray::Class()) {
+               // We are not interested in the ClonesArray object but only
                // in its contents.
                // We need to retrieve the class of its content.
 
@@ -1100,7 +1123,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                   TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0, top);
 
                   // The dimension needs to be handled!
-                  numberOfVarDim += RegisterDimensions(code,clonesinfo);
+                  numberOfVarDim += RegisterDimensions(code,clonesinfo, kFALSE);
 
                   previnfo = clonesinfo;
                   maininfo = clonesinfo;
@@ -1110,7 +1133,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                TClass * inside_cl = clones->GetClass();
                if (1 || inside_cl) cl = inside_cl;
 
-            } else if (cl && cl->GetCollectionProxy() ) {
+            } else if (!useCollectionObject && cl && cl->GetCollectionProxy() ) {
 
                // We are NEVER (for now!) interested in the ClonesArray object but only
                // in its contents.
@@ -1132,7 +1155,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                   TFormLeafInfo* collectioninfo = 
                      new TFormLeafInfoCollection(mother_cl, 0,cl,top);
                   // The dimension needs to be handled!
-                  numberOfVarDim += RegisterDimensions(code,collectioninfo);
+                  numberOfVarDim += RegisterDimensions(code,collectioninfo, kFALSE);
 
                   previnfo = collectioninfo;
                   maininfo = collectioninfo;
@@ -1147,34 +1170,46 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                }
             }
 
-            TMethodCall *method;
-            if (cl->GetClassInfo()==0) {
+            TMethodCall *method  = 0;
+            if (cl==0) {
                Error("DefinedVariable",
-                     "Can not call method %s on class without dictionary (%s)!",
-                     right,cl->GetName());
+                     "Could not discover the TClass corresponding to (%s)!",
+                     right);
                return -2;
+            } else if (cl==TClonesArray::Class() && strcmp(work,"size")==0) {
+               method = new TMethodCall(cl, "GetEntriesFast", "");
+            } else if (cl->GetCollectionProxy() && strcmp(work,"size")==0) {
+               leafinfo = new TFormLeafInfoCollectionSize(cl);
+            } else {
+               if (cl->GetClassInfo()==0) {
+                  Error("DefinedVariable",
+                        "Can not call method %s on class without dictionary (%s)!",
+                        right,cl->GetName());
+                  return -2;
+               }
+               method = new TMethodCall(cl, work, params);
             }
-            method = new TMethodCall(cl, work, params);
-            if (!method->GetMethod()) {
-               Error("DefinedVariable","Unknown method:%s",right);
-               return -1;
-            }
-            switch(method->ReturnType()) {
-               case TMethodCall::kLong:
+            if (method) {
+               if (!method->GetMethod()) {
+                  Error("DefinedVariable","Unknown method:%s in %s",right,cl->GetName());
+                  return -1;
+               }
+               switch(method->ReturnType()) {
+                  case TMethodCall::kLong:
                      leafinfo = new TFormLeafInfoMethod(cl,method);
                      cl = 0;
                      break;
-               case TMethodCall::kDouble:
+                  case TMethodCall::kDouble:
                      leafinfo = new TFormLeafInfoMethod(cl,method);
                      cl = 0;
                      break;
-               case TMethodCall::kString:
+                  case TMethodCall::kString:
                      leafinfo = new TFormLeafInfoMethod(cl,method);
                      // 1 will be replaced by -1 when we know how to use strlen
                      numberOfVarDim += RegisterDimensions(code,1); //NOTE: changed from 0
                      cl = 0;
                      break;
-               case TMethodCall::kOther:
+                  case TMethodCall::kOther:
                      {
                         TString return_type = 
                            gInterpreter->TypeName(method->GetMethod()->GetReturnTypeName());
@@ -1185,10 +1220,11 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                            cl = 0;
                         }
                      };    break;
-               default:
-               Error("DefineVariable","Method %s from %s has an impossible return type %d",
-                     work,cl->GetName(),method->ReturnType());
-               return -2;
+                  default:
+                     Error("DefineVariable","Method %s from %s has an impossible return type %d",
+                        work,cl->GetName(),method->ReturnType());
+                     return -2;
+               }
             }
             if (maininfo==0) {
                maininfo = leafinfo;
@@ -1202,6 +1238,8 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
             leafinfo = 0;
             current = &(work[0]);
             *current = 0;
+            prevUseCollectionObject = kFALSE;
+            useCollectionObject = kFALSE;
             continue;
          } else if (right[i] == ')') {
             // We should have the end of a cast operator.  Let's introduce a TFormLeafCast
@@ -1236,9 +1274,22 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
             // skip it all if there is nothing to look at
             if (strlen(work)==0) continue;
 
+            prevUseCollectionObject = useCollectionObject;
+            if (work[0]=='@') {
+               useCollectionObject = kTRUE;
+               Int_t l = 0;
+               for(l=0;work[l+1]!=0;++l) work[l] = work[l+1];
+               work[l] = '\0';
+            } else if (work[strlen(work)-1]=='@') {
+               useCollectionObject = kTRUE;
+               work[strlen(work)-1] = '\0';
+            } else {
+               useCollectionObject = kFALSE;
+            }
+
             Bool_t mustderef = kFALSE;
-            if (cl == TClonesArray::Class()) {
-               // We are NEVER interested in the ClonesArray object but only
+            if (!prevUseCollectionObject && cl == TClonesArray::Class()) {
+               // We are not interested in the ClonesArray object but only
                // in its contents.
                // We need to retrieve the class of its content.
 
@@ -1261,7 +1312,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
 
                   TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0);
                   // The dimension needs to be handled!
-                  numberOfVarDim += RegisterDimensions(code,clonesinfo);
+                  numberOfVarDim += RegisterDimensions(code,clonesinfo, kFALSE);
 
                   mustderef = kTRUE;
                   previnfo = clonesinfo;
@@ -1292,7 +1343,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                   // so let get the number of objects
                   //strcpy(work,"fLast");
                }
-            } else if (cl && cl->GetCollectionProxy() ) {
+            } else if (!prevUseCollectionObject && cl && cl->GetCollectionProxy() ) {
 
                // We are NEVER interested in the Collection object but only
                // in its contents.
@@ -1317,7 +1368,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                   TFormLeafInfo* collectioninfo = 
                      new TFormLeafInfoCollection(mother_cl, 0, cl);
                   // The dimension needs to be handled!
-                  numberOfVarDim += RegisterDimensions(code,collectioninfo);
+                  numberOfVarDim += RegisterDimensions(code,collectioninfo, kFALSE);
 
                   mustderef = kTRUE;
                   previnfo = collectioninfo;
@@ -1343,7 +1394,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                element = cl->GetStreamerInfo()->GetStreamerElement(work,offset);
             }
 
-            if (!element) {
+            if (!element && !prevUseCollectionObject) {
                // We allow for looking for a data member inside a class inside
                // a TClonesArray without mentioning the TClonesArrays variable name
                TIter next( cl->GetStreamerInfo()->GetElements() );
@@ -1366,12 +1417,12 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                      }
 
                      TClass *sub_cl = clones->GetClass();
-                     element = sub_cl->GetStreamerInfo()->GetStreamerElement(work,offset);
+                     if (sub_cl) element = sub_cl->GetStreamerInfo()->GetStreamerElement(work,offset);
                      delete clonesinfo;
 
                      if (element) {
                         leafinfo = new TFormLeafInfoClones(cl,clones_offset,curelem);
-                        numberOfVarDim += RegisterDimensions(code,leafinfo);
+                        numberOfVarDim += RegisterDimensions(code,leafinfo, kFALSE);
                         if (maininfo==0) maininfo = leafinfo;
                         if (previnfo==0) previnfo = leafinfo;
                         else {
@@ -1402,10 +1453,10 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                                                                      curelem,maininfo);
                            fHasMultipleVarDim[code] = kTRUE;
                            leafinfo->fNext = new TFormLeafInfoCollection(cl,coll_offset,curelem);
-                           numberOfVarDim += RegisterDimensions(code,leafinfo);
+                           numberOfVarDim += RegisterDimensions(code,leafinfo, kFALSE);
                         } else {
                            leafinfo = new TFormLeafInfoCollection(cl,coll_offset,curelem);
-                           numberOfVarDim += RegisterDimensions(code,leafinfo);
+                           numberOfVarDim += RegisterDimensions(code,leafinfo, kFALSE);
                         }
                         if (maininfo==0) maininfo = leafinfo;
                         if (previnfo==0) previnfo = leafinfo;
@@ -1497,12 +1548,12 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                      mustderef = kTRUE;
                   } else {
 
-                     if (element->GetClassPointer() ==  TClonesArray::Class()) {
+                     if (!useCollectionObject && element->GetClassPointer() ==  TClonesArray::Class()) {
 
                         leafinfo = new TFormLeafInfoClones(cl,offset,element);
                         mustderef = kTRUE;
 
-                     } else if (element->GetClassPointer() 
+                     } else if (!useCollectionObject &&  element->GetClassPointer() 
                         && element->GetClassPointer()->GetCollectionProxy()) {
 
                         mustderef = kTRUE;
@@ -1539,7 +1590,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
  
                            if (valueCl!=0 && valueCl->GetCollectionProxy()!=0) {
 
-                              numberOfVarDim += RegisterDimensions(code,leafinfo);
+                              numberOfVarDim += RegisterDimensions(code,leafinfo, kFALSE);
                               if (previnfo==0) previnfo = leafinfo;
                               else {
                                  previnfo->fNext = leafinfo;
@@ -1578,7 +1629,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
                return -1;
             }
 
-            numberOfVarDim += RegisterDimensions(code,leafinfo);
+            numberOfVarDim += RegisterDimensions(code,leafinfo, useCollectionObject); // Note or useCollectionObject||prevUseColectionObject
             if (maininfo==0) {
                maininfo = leafinfo;
             }
@@ -1598,7 +1649,7 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression,
             *current = 0;
 
             Assert(right[i] != '[');  // We are supposed to have removed all dimensions already!
-            
+
          } else
             *current++ = right[i];
       }
@@ -1656,7 +1707,8 @@ Int_t TTreeFormula::FindLeafForExpression(const char* expression,
                                           TLeaf *&leaf,
                                           TString &leftover, Bool_t &final, 
                                           UInt_t &paran_level, TObjArray &castqueue, 
-                                          std::vector<std::string>& aliasUsed, 
+                                          std::vector<std::string>& aliasUsed,
+                                          Bool_t &useLeafCollectionObject,
                                           const char *fullExpression)
 {
    // Look for the leaf corresponding to the start of expression.
@@ -1690,6 +1742,7 @@ Int_t TTreeFormula::FindLeafForExpression(const char* expression,
 
    Int_t nchname = strlen(cname);
    Int_t i;
+   Bool_t foundAtSign = kFALSE;
 
    for (i=0, current = &(work[0]); i<=nchname && !final;i++ ) {
       // We will treated the terminator as a token.
@@ -1789,6 +1842,21 @@ Int_t TTreeFormula::FindLeafForExpression(const char* expression,
          // so far does point to a leaf.
          *current = '\0';
 
+         if (work[0]=='@') {
+            foundAtSign = kTRUE;
+            Int_t l = 0;
+            for(l=0;work[l+1]!=0;++l) work[l] = work[l+1];
+            work[l] = '\0';
+            --current;
+         } else if (work[strlen(work)-2]=='@') {
+            foundAtSign = kTRUE;
+            work[strlen(work)-2] = cname[i];
+            work[strlen(work)-1] = '\0';
+            --current;
+         } else {
+            foundAtSign = kFALSE;
+         }
+
          if (left[0]==0) strcpy(left,work);
          if (!leaf && !branch) {
             // So far, we have not found a matching leaf or branch.
@@ -1803,7 +1871,7 @@ Int_t TTreeFormula::FindLeafForExpression(const char* expression,
             if (!branch) branch = fTree->FindBranch(first);
             if (!leaf) leaf = fTree->FindLeaf(first);
 
-            if (branch && cname[i] != 0) {
+            if (branch && (foundAtSign || cname[i] != 0)  ) {
                // Since we found a branch and there is more information in the name,
                // we do NOT look at the 'IsOnTerminalBranch' status of the leaf
                // we found ... yet!
@@ -1816,11 +1884,21 @@ Int_t TTreeFormula::FindLeafForExpression(const char* expression,
                      if ( type == 3 || type ==4) {
                         // We have a Collection branch.
                         leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
+                        if (foundAtSign) {
+                           useLeafCollectionObject = foundAtSign;
+                           foundAtSign = kFALSE;
+                           current = &(work[0]);
+                           *current = 0;
+                           ++i;
+                           break;
+                        }
                      }
                   }
                }
 
                // we reset work
+               useLeafCollectionObject = foundAtSign;
+               foundAtSign = kFALSE;
                current = &(work[0]);
                *current = 0;
             } else if (leaf || branch) {
@@ -1851,6 +1929,7 @@ Int_t TTreeFormula::FindLeafForExpression(const char* expression,
                      final = kTRUE;
                      strcpy(right,first);
                      //We need to put the delimiter back!
+                     if (foundAtSign) strcat(right,"@");
                      if (cname[i]=='.') strcat(right,".");
 
                      // We reset work
@@ -1927,14 +2006,24 @@ Int_t TTreeFormula::FindLeafForExpression(const char* expression,
                if (second[0]) strcat(second,".");
                strcat(second,work);
                leaf = tmp_leaf;
+               useLeafCollectionObject = foundAtSign;
+               foundAtSign = kFALSE;
 
                // we reset work
                current = &(work[0]);
                *current = 0;
             } else {
                //We need to put the delimiter back!
-               if (strlen(work)) work[strlen(work)] = cname[i];
-               else --current;
+               if (strlen(work)) {
+                  if (foundAtSign) {
+                     Int_t where = strlen(work);
+                     work[where] = '@';
+                     work[where+1] = cname[i];
+                     ++current;
+                  } else {
+                     work[strlen(work)] = cname[i];
+                  }
+               } else --current;
             }
          }
       }
@@ -1987,7 +2076,8 @@ Int_t TTreeFormula::FindLeafForExpression(const char* expression,
          aliasUsed.push_back(left);
          TString newExpression = aliasValue;
          newExpression += (cname+strlen(left));
-         Int_t res = FindLeafForExpression(newExpression, leaf, leftover, final, paran_level, castqueue, aliasUsed, fullExpression);
+         Int_t res = FindLeafForExpression(newExpression, leaf, leftover, final, paran_level, 
+                                           castqueue, aliasUsed, useLeafCollectionObject, fullExpression);
          if (res<0) {
             Error("DefinedVariable",
                   "The substitution of the alias \"%s\" by \"%s\" failed.",left,aliasValue);
@@ -2125,11 +2215,12 @@ Int_t TTreeFormula::DefinedVariable(TString &name, Int_t &action)
    }
    cname[k]='\0';
 
+   Bool_t useLeafCollectionObject = kFALSE;
    TString leftover;
    TLeaf *leaf = 0;
    {  
       std::vector<std::string> aliasSofar = fAliasesUsed;
-      res = FindLeafForExpression(cname, leaf, leftover, final, paran_level, castqueue, aliasSofar, name);
+      res = FindLeafForExpression(cname, leaf, leftover, final, paran_level, castqueue, aliasSofar, useLeafCollectionObject, name);
    }
    if (res<0) return res;
 
@@ -2230,7 +2321,7 @@ Int_t TTreeFormula::DefinedVariable(TString &name, Int_t &action)
       // Now that we have clean-up the expression, let's compare it to the content
       // of the leaf!
 
-      Int_t res = ParseWithLeaf(leaf,leftover,final,paran_level,castqueue,name);
+      Int_t res = ParseWithLeaf(leaf,leftover,final,paran_level,castqueue,useLeafCollectionObject,name);
       if (res<0) return res;
       if (res>0) action = res;
       return code;
diff --git a/treeplayer/src/TTreePlayer.cxx b/treeplayer/src/TTreePlayer.cxx
index bd59441e186..de407167806 100644
--- a/treeplayer/src/TTreePlayer.cxx
+++ b/treeplayer/src/TTreePlayer.cxx
@@ -1,4 +1,4 @@
-// @(#)root/treeplayer:$Name:  $:$Id: TTreePlayer.cxx,v 1.182 2005/03/04 17:46:50 brun Exp $
+// @(#)root/treeplayer:$Name:  $:$Id: TTreePlayer.cxx,v 1.183 2005/03/07 18:48:27 brun Exp $
 // Author: Rene Brun   12/01/96
 
 /*************************************************************************
@@ -663,6 +663,26 @@ Long64_t TTreePlayer::DrawSelect(const char *varexp0, const char *selection, Opt
 //      will not reset hsqrt, but will continue filling.
 //  This works for 1-D, 2-D and 3-D histograms.
 //
+//     Accessing collection objects
+//     ============================
+//
+//  TTree::Draw default's handling of collections is to assume that any 
+//  request on a collection pertain to it content.  For example, if fTracks
+//  is a collection of Track objects, the following:
+//      tree->Draw("event.fTracks.fPx");
+//  will plot the value of fPx for each Track objects inside the collection.
+//  Also
+//     tree->Draw("event.fTracks.size()");
+//  would plot the result of the member function Track::size() for each
+//  Track object inside the collection.
+//  To access information about the collection itself, TTree::Draw support
+//  the '@' notation.  If a variable which points to a collection is prefixed
+//  or postfixed with '@', the next part of the expression will pertain to
+//  the collection object.  For example:
+//     tree->Draw("event.@fTracks.size()");
+//  will plot the size of the collection refered to by fTracks (i.e the number
+//  of Track objects).
+//
 //     Special functions and variables
 //     ===============================
 //
-- 
GitLab