Index: examples/geometry.C
===================================================================
--- examples/geometry.C	(revision a844c077208c72984dbdaeb188751d762d6bcf17)
+++ examples/geometry.C	(revision ffd01cb8b6b9ef622e7701fff0f9ca794365bccc)
@@ -5,4 +5,5 @@
 #include <algorithm>
 #include <sstream>
+#include <exception>
 #include "TGeoManager.h"
 #include "TGeoVolume.h"
@@ -40,4 +41,5 @@
 #include "TClonesArray.h"
 #include "TGLClip.h"
+#include "TEveArrow.h"
 
 /*
@@ -54,7 +56,10 @@
 class DelphesCaloData;
 class DelphesDisplay;
+class DelphesBranchBase;
+template<typename EveContainer> class DelphesBranchElement;
 void make_gui();
 void load_event();
 void delphes_read();
+void readConfig(const char *configFile, const Delphes3DGeometry& det3D, std::vector<DelphesBranchBase*>& elements, std::vector<TClonesArray*>& arrays);
 
 // Configuration and global variables.
@@ -84,5 +89,5 @@
 TEveElementList *gJetList = 0;
 TEveElementList *gGenJetList = 0;
-TEveArrow *gMet = 0;
+TEveElementList *gMetList = 0;
 TEveTrackList *gTrackList = 0;
 TEveTrackList *gElectronList = 0;
@@ -121,4 +126,5 @@
      Double_t getDetectorRadius() const { return muonSystem_radius_; }
      Double_t getTrackerHalfLength() const { return tk_length_; }
+     Double_t getDetectorHalfLength() const { return muonSystem_length_; }
      Double_t getBField() const { return tk_Bz_; }
      std::pair<TAxis*, TAxis*> getCaloAxes() { return std::make_pair(etaAxis_,phiAxis_); }
@@ -147,4 +153,5 @@
      Double_t muonSystem_thickn_;
      Double_t muonSystem_radius_;
+     Double_t muonSystem_length_;
      Double_t tk_radius_;
      Double_t tk_length_;
@@ -282,4 +289,5 @@
 
    muonSystem_radius_ = tk_radius_ + contingency_ + (contingency_+calo_barrel_thickness_)*calorimeters_.size() + muonSystem_thickn_;
+   muonSystem_length_ = tk_length_ + contingency_ + (contingency_+calo_endcap_thickness_)*calorimeters_.size() + muonSystem_thickn_;
 
    delete confReader;
@@ -490,5 +498,5 @@
 /******************************************************************************/
 
-void delphes_event_display(const char *configFile, const char *inputFile, const Delphes3DGeometry& det3D)
+void delphes_event_display(const char *configFile, const char *inputFile, Delphes3DGeometry& det3D)
 {
 
@@ -505,5 +513,5 @@
    gPhiAxis = det3D.getCaloAxes().second;
 
-   TGeoVolume* top = det3D.getDetector(false); //TODO: can this be set in the GUI?
+   TGeoVolume* top = det3D.getDetector(false);
    geom->SetTopVolume(top);
    TEveElementList *geometry = new TEveElementList("Geometry");
@@ -542,4 +550,8 @@
    gTreeReader = new ExRootTreeReader(&gChain);
 
+   // prepare data collections
+   std::vector<DelphesBranchBase*> elements;
+   std::vector<TClonesArray*> arrays;
+   //readConfig(configFile, det3D, elements, arrays);
    // Get pointers to branches
 //TODO make it configurable, for more objects (or can we guess from the config?)
@@ -571,10 +583,13 @@
    gEve->AddElement(gGenJetList);
 
-   gMet = new TEveArrow(1., 0., 0., 0., 0., 0.);
-   gMet->SetMainColor(kViolet);
-   gMet->SetTubeR(0.02);
-   gMet->SetPickable(kTRUE);
-   gMet->SetName("Missing Et");
-   gEve->GetCurrentEvent()->AddElement(gMet);
+   gMetList = new TEveElementList("Missing Et");
+   gMetList->SetMainColor(kViolet);
+   gEve->AddElement(gMetList);
+//   gMet = new TEveArrow(1., 0., 0., 0., 0., 0.);
+//   gMet->SetMainColor(kViolet);
+//   gMet->SetTubeR(0.02);
+//   gMet->SetPickable(kTRUE);
+//   gMet->SetName("Missing Et");
+//   gEve->GetCurrentEvent()->AddElement(gMet);
 
    TEveTrackPropagator *trkProp;
@@ -662,4 +677,5 @@
    if(gCaloData) gCaloData->ClearTowers();
    if(gJetList) gJetList->DestroyElements();
+   if(gMetList) gMetList->DestroyElements();
    if(gGenJetList) gGenJetList->DestroyElements();
    if(gTrackList) gTrackList->DestroyElements();
@@ -703,4 +719,5 @@
   TEveJetCone *eveJetCone;
   TEveTrack *eveTrack;
+  TEveArrow *eveMet;
 
   Int_t counter;
@@ -839,15 +856,13 @@
   itMet.Reset();
   while((MET = (MissingET*) itMet.Next())) {
-    delete gMet;
-    gMet = new TEveArrow((gRadius * MET->MET/maxPt)*cos(MET->Phi), (gRadius * MET->MET/maxPt)*sin(MET->Phi), 0., 0., 0., 0.);
-    gMet->SetMainColor(kViolet);
-    gMet->SetTubeR(0.04);
-    gMet->SetConeR(0.08);
-    gMet->SetConeL(0.10);
-    gMet->SetPickable(kTRUE);
-    gMet->SetName("Missing Et");
-    gMet->SetTitle(Form("Missing Et (%.1f GeV)",MET->MET));
-    gMet->ProjectAllChildren();
-    gEve->GetCurrentEvent()->AddElement(gMet);
+    eveMet = new TEveArrow((gRadius * MET->MET/maxPt)*cos(MET->Phi), (gRadius * MET->MET/maxPt)*sin(MET->Phi), 0., 0., 0., 0.);
+    eveMet->SetMainColor(kViolet);
+    eveMet->SetTubeR(0.04);
+    eveMet->SetConeR(0.08);
+    eveMet->SetConeL(0.10);
+    eveMet->SetPickable(kTRUE);
+    eveMet->SetName("Missing Et");
+    eveMet->SetTitle(Form("Missing Et (%.1f GeV)",MET->MET));
+    gMetList->AddElement(eveMet);
   }
 }
@@ -955,5 +970,5 @@
    // 0 - no clip, 1 - clip plane, 2 - clip box
    TGLViewer *v = gEve->GetDefaultGLViewer();
-   Double_t plane[4] = { 0., 1., 0., 0. };
+   //Double_t plane[4] = { 0., 1., 0., 0. };
    //v->GetClipSet()->SetClipState(1,plane);
    //v->GetClipSet()->SetClipType(1);
@@ -966,2 +981,163 @@
 }
 
+// virtual class to represent objects from a Delphes-tree branch
+class DelphesBranchBase
+{
+  public:
+    DelphesBranchBase(const char* name, const char*type, const enum EColor color):name_(name),type_(type),color_(color) {}
+    virtual ~DelphesBranchBase() {};
+    const char* GetName() const { return (const char*)name_; }
+    const char* GetType() const { return (const char*)type_; }
+    enum EColor GetColor() const { return color_; }
+    virtual const char* GetClassName() = 0;
+    virtual void Reset() = 0;
+
+  private:
+    TString name_;
+    TString type_; // needed for parsing the branch later on
+    const enum EColor color_;
+};
+// concrete implementations. EveContainer can be a TrackList, ElementList or CaloData.
+template<typename EveContainer> class DelphesBranchElement: public DelphesBranchBase
+{
+  public:
+    DelphesBranchElement(const char* name, const char*type, const enum EColor color):DelphesBranchBase(name, type, color) {
+      throw std::exception();
+    }
+
+    // destructor
+    virtual ~DelphesBranchElement() {
+      delete data_;
+    }
+ 
+    // get the container (ElementList, TrackList, or CaloData)
+    EveContainer* GetContainer() { return data_; }
+
+    // resets the collection (before moving to the next event)
+    // making it pure virtual implies that only the specializations below will compile
+    virtual void Reset() {};
+
+    // template class name
+    virtual const char* GetClassName() { return data_->ClassName(); }
+
+  private:
+    EveContainer* data_;
+};
+// special case for calo towers
+template<> DelphesBranchElement<DelphesCaloData>::DelphesBranchElement(const char* name, const char*type, const enum EColor color):DelphesBranchBase(name, type, color) {
+      if(TString(type)=="tower") {
+        data_ = new DelphesCaloData(2); 
+        data_->RefSliceInfo(0).Setup("ECAL", 0.1, kRed);
+        data_->RefSliceInfo(1).Setup("HCAL", 0.1, kBlue);
+        data_->IncDenyDestroy();
+      } else {
+        throw std::exception();
+      }
+    }
+template<> void DelphesBranchElement<DelphesCaloData>::Reset() { data_->ClearTowers(); }
+// special case for element lists
+template<> DelphesBranchElement<TEveElementList>::DelphesBranchElement(const char* name, const char*type, const enum EColor color):DelphesBranchBase(name, type, color) {
+      if(TString(type)=="vector" || TString(type)=="jet") {
+        data_ = new TEveElementList(name);
+        data_->SetMainColor(color_);
+      } else {
+        throw std::exception();
+      }
+    }
+template<> void DelphesBranchElement<TEveElementList>::Reset() { data_->DestroyElements(); }
+// special case for track lists
+template<> DelphesBranchElement<TEveTrackList>::DelphesBranchElement(const char* name, const char*type, const enum EColor color):DelphesBranchBase(name, type, color) {
+      if(TString(type)=="track") {
+        data_ = new TEveTrackList(name);
+        data_->SetMainColor(color_);
+        data_->SetMarkerColor(color_);
+        data_->SetMarkerStyle(kCircle);
+        data_->SetMarkerSize(0.5);
+      } else if(TString(type)=="photon") {
+        data_ = new TEveTrackList(name);
+        data_->SetMainColor(color_);
+        data_->SetMarkerColor(color_);
+        data_->SetMarkerStyle(kCircle);
+        data_->SetMarkerSize(0.5);
+      } else {
+        throw std::exception();
+      }
+    }
+template<> void DelphesBranchElement<TEveTrackList>::Reset() { data_->DestroyElements(); }
+
+// function that parses the config to extract the branches of interest and prepare containers
+void readConfig(const char *configFile, Delphes3DGeometry& det3D, std::vector<DelphesBranchBase*>& elements, std::vector<TClonesArray*>& arrays) {
+   ExRootConfReader *confReader = new ExRootConfReader;
+   confReader->ReadFile(configFile);
+   Double_t tk_radius = det3D.getTrackerRadius();
+   Double_t tk_length = det3D.getTrackerHalfLength();
+   Double_t tk_Bz     = det3D.getBField();
+   Double_t mu_radius = det3D.getDetectorRadius();
+   Double_t mu_length = det3D.getDetectorHalfLength();
+   TAxis*   etaAxis   = det3D.getCaloAxes().first;
+   TAxis*   phiAxis   = det3D.getCaloAxes().second;
+   ExRootConfParam branches = confReader->GetParam("TreeWriter::Branch");
+   Int_t nBranches = branches.GetSize()/3;
+   for(Int_t b = 0; b<nBranches; ++b) {
+     TString input = branches[b*3].GetString();
+     TString name = branches[b*3+1].GetString();
+     TString className = branches[b*3+2].GetString();
+     if(className=="Track") {
+       if(input.Contains("eflow",TString::kIgnoreCase) || name.Contains("eflow",TString::kIgnoreCase)) continue; //no eflow
+       DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"track",kBlue);
+       elements.push_back(list);
+       TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
+       trkProp->SetMagField(0., 0., -tk_Bz);
+       trkProp->SetMaxR(tk_radius);
+       trkProp->SetMaxZ(tk_length);
+     } else if(className=="Tower") {
+       if(input.Contains("eflow",TString::kIgnoreCase) || name.Contains("eflow",TString::kIgnoreCase)) continue; //no eflow
+       DelphesBranchElement<DelphesCaloData>* list = new DelphesBranchElement<DelphesCaloData>(name,"tower",kBlack);
+       list->GetContainer()->SetEtaBins(etaAxis);
+       list->GetContainer()->SetPhiBins(phiAxis);
+       elements.push_back(list);
+     } else if(className=="Jet") {
+       if(input.Contains("GenJetFinder")) {
+         DelphesBranchElement<TEveElementList>* list = new DelphesBranchElement<TEveElementList>(name,"jet",kCyan);
+         list->GetContainer()->SetRnrSelf(false);
+         list->GetContainer()->SetRnrChildren(false);
+         elements.push_back(list);
+       } else {
+         elements.push_back(new DelphesBranchElement<TEveElementList>(name,"jet",kYellow));
+       }
+     } else if(className=="Electron") {
+       DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"track",kRed);
+       elements.push_back(list);
+       TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
+       trkProp->SetMagField(0., 0., -tk_Bz);
+       trkProp->SetMaxR(tk_radius);
+       trkProp->SetMaxZ(tk_length);
+     } else if(className=="Photon") {
+       DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"photon",kYellow);
+       elements.push_back(list);
+       TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
+       trkProp->SetMagField(0., 0., 0.);
+       trkProp->SetMaxR(tk_radius);
+       trkProp->SetMaxZ(tk_length);
+     } else if(className=="Muon") {
+       DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"track",kGreen);
+       elements.push_back(list);
+       TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
+       trkProp->SetMagField(0., 0., -tk_Bz);
+       trkProp->SetMaxR(mu_radius);
+       trkProp->SetMaxZ(mu_length);
+     } else if(className=="MissingET") {
+       elements.push_back(new DelphesBranchElement<TEveElementList>(name,"vector",kViolet));
+     } else if(className=="GenParticle") {
+       DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"track",kCyan);
+       elements.push_back(list);
+       list->GetContainer()->SetRnrSelf(false);
+       list->GetContainer()->SetRnrChildren(false);
+       TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
+       trkProp->SetMagField(0., 0., -tk_Bz);
+       trkProp->SetMaxR(tk_radius);
+       trkProp->SetMaxZ(tk_length);
+     }
+     arrays.push_back(gTreeReader->UseBranch(name));
+   }
+}
