Fork me on GitHub

source: git/examples/geometry.C@ ffd01cb

ImprovedOutputFile Timing dual_readout llp
Last change on this file since ffd01cb was ffd01cb, checked in by Christophe Delaere <christophe.delaere@…>, 10 years ago

Tentative code to automatize config parsing

As it is, the code is useless. It gets too complicated for the
interpreter and the auto dict generation fails. The new classes have to
be compiled separately. The idea is to move the code to the display
directory.

  • Property mode set to 100644
File size: 46.8 KB
Line 
1#include <set>
2#include <map>
3#include <utility>
4#include <vector>
5#include <algorithm>
6#include <sstream>
7#include <exception>
8#include "TGeoManager.h"
9#include "TGeoVolume.h"
10#include "TGeoMedium.h"
11#include "TGeoNode.h"
12#include "TGeoCompositeShape.h"
13#include "TGeoMatrix.h"
14#include "TGeoTube.h"
15#include "TGeoCone.h"
16#include "TGeoArb8.h"
17//#include "external/ExRootAnalysis/ExRootConfReader.h"
18//#include "external/ExRootAnalysis/ExRootTreeReader.h"
19//#include "display/DelphesCaloData.h"
20//#include "display/DelphesDisplay.h"
21//#include "classes/DelphesClasses.h"
22#include "TF2.h"
23#include "TH1F.h"
24#include "TChain.h"
25#include "TEveElement.h"
26#include "TEveJetCone.h"
27#include "TEveTrack.h"
28#include "TEveTrackPropagator.h"
29#include "TEveCalo.h"
30#include "TMath.h"
31#include "TSystem.h"
32#include "TEveManager.h"
33#include "TEveGeoNode.h"
34#include "TEveTrans.h"
35#include "TEveViewer.h"
36#include "TEveBrowser.h"
37#include "TRootBrowser.h"
38#include "TGLViewer.h"
39#include "TGButton.h"
40#include "TCollection.h"
41#include "TClonesArray.h"
42#include "TGLClip.h"
43#include "TEveArrow.h"
44
45/*
46 * assembly.C: sauvegarde as shape-extract -> implement in the geometry class (read/write)
47 * histobrowser.C: intégration d'histogrammes dans le display (on pourrait avoir Pt, eta, phi pour les principales collections)
48 * also from alice_esd: summary html table
49 *
50 */
51using namespace std;
52
53// Forward declarations.
54class Delphes3DGeometry;
55class ExRootTreeReader;
56class DelphesCaloData;
57class DelphesDisplay;
58class DelphesBranchBase;
59template<typename EveContainer> class DelphesBranchElement;
60void make_gui();
61void load_event();
62void delphes_read();
63void readConfig(const char *configFile, const Delphes3DGeometry& det3D, std::vector<DelphesBranchBase*>& elements, std::vector<TClonesArray*>& arrays);
64
65// Configuration and global variables.
66Int_t event_id = 0; // Current event id.
67Double_t gRadius = 1.29;
68Double_t gTotRadius = 2.0;
69Double_t gHalfLength = 3.0;
70Double_t gBz = 3.8;
71
72TAxis *gEtaAxis = 0;
73TAxis *gPhiAxis = 0;
74
75TChain gChain("Delphes");
76
77ExRootTreeReader *gTreeReader = 0;
78
79TClonesArray *gBranchTower = 0;
80TClonesArray *gBranchTrack = 0;
81TClonesArray *gBranchEle = 0;
82TClonesArray *gBranchMuon = 0;
83TClonesArray *gBranchPhoton = 0;
84TClonesArray *gBranchJet = 0;
85TClonesArray *gBranchGenJet = 0;
86TClonesArray *gBranchMet = 0;
87
88DelphesCaloData *gCaloData = 0;
89TEveElementList *gJetList = 0;
90TEveElementList *gGenJetList = 0;
91TEveElementList *gMetList = 0;
92TEveTrackList *gTrackList = 0;
93TEveTrackList *gElectronList = 0;
94TEveTrackList *gMuonList = 0;
95TEveTrackList *gPhotonList = 0;
96
97DelphesDisplay *gDelphesDisplay = 0;
98
99/******************************************************************************/
100// Construction of the geometry
101/******************************************************************************/
102
103// TODO: asymmetric detector
104
105class Delphes3DGeometry {
106 public:
107 Delphes3DGeometry(TGeoManager *geom = NULL);
108 ~Delphes3DGeometry() {}
109
110 void readFile(const char* filename, const char* ParticlePropagator="ParticlePropagator",
111 const char* TrackingEfficiency="ChargedHadronTrackingEfficiency",
112 const char* MuonEfficiency="MuonEfficiency",
113 const char* Calorimeters="Calorimeter");
114
115 void loadFromFile(const char* filename, const char* name="DelphesGeometry");
116 void save(const char* filename, const char* name="DelphesGeometry");
117
118 void setContingency(Double_t contingency) { contingency_ = contingency; }
119 void setCaloBarrelThickness(Double_t thickness) { calo_barrel_thickness_ = thickness; }
120 void setCaloEndcapThickness(Double_t thickness) { calo_endcap_thickness_ = thickness; }
121 void setMuonSystemThickness(Double_t thickness) { muonSystem_thickn_ = thickness; }
122
123 TGeoVolume* getDetector(bool withTowers = true);
124
125 Double_t getTrackerRadius() const { return tk_radius_; }
126 Double_t getDetectorRadius() const { return muonSystem_radius_; }
127 Double_t getTrackerHalfLength() const { return tk_length_; }
128 Double_t getDetectorHalfLength() const { return muonSystem_length_; }
129 Double_t getBField() const { return tk_Bz_; }
130 std::pair<TAxis*, TAxis*> getCaloAxes() { return std::make_pair(etaAxis_,phiAxis_); }
131
132 private:
133 std::pair<Double_t, Double_t> addTracker(TGeoVolume *top);
134 std::pair<Double_t, Double_t> addCalorimeter(TGeoVolume *top, const char* name, Double_t innerBarrelRadius, Double_t innerBarrelLength, set< pair<Double_t, Int_t> >& caloBinning);
135 std::pair<Double_t, Double_t> addMuonDets(TGeoVolume *top, const char* name, Double_t innerBarrelRadius, Double_t innerBarrelLength);
136 void addCaloTowers(TGeoVolume *top, const char* name, Double_t innerBarrelRadius, Double_t innerBarrelLength, set< pair<Double_t, Int_t> >& caloBinning);
137
138 private:
139
140 TGeoManager *geom_;
141
142 TGeoMedium *vacuum_;
143 TGeoMedium *tkmed_;
144 TGeoMedium *calomed_;
145 TGeoMedium *mudetmed_;
146
147 TAxis* etaAxis_;
148 TAxis* phiAxis_;
149
150 Double_t contingency_;
151 Double_t calo_barrel_thickness_;
152 Double_t calo_endcap_thickness_;
153 Double_t muonSystem_thickn_;
154 Double_t muonSystem_radius_;
155 Double_t muonSystem_length_;
156 Double_t tk_radius_;
157 Double_t tk_length_;
158 Double_t tk_etamax_;
159 Double_t tk_Bz_;
160
161 std::vector<std::string> calorimeters_;
162 std::vector<std::string> muondets_;
163
164 std::map<std::string, Double_t> muonSystem_etamax_;
165 std::map<std::string, set< pair<Double_t, Int_t> > > caloBinning_;
166
167};
168
169Delphes3DGeometry::Delphes3DGeometry(TGeoManager *geom) {
170
171 //--- the geometry manager
172 geom_ = geom==NULL? gGeoManager : geom;
173 //gGeoManager->DefaultColors();
174
175 //--- define some materials
176 TGeoMaterial *matVacuum = new TGeoMaterial("Vacuum", 0,0,0);
177 TGeoMaterial *matAl = new TGeoMaterial("Al", 26.98,13,2.7); // placeholder
178 //TODO: create different materials for different subdetectors???
179 matVacuum->SetTransparency(85); //TODO: tune
180 matAl->SetTransparency(85); //TODO: tune
181
182 //--- define some media
183 TGeoMedium *Vacuum = new TGeoMedium("Vacuum",1, matVacuum);
184 TGeoMedium *Al = new TGeoMedium("Root Material",2, matAl);
185 vacuum_ = Vacuum;
186 tkmed_ = Vacuum; // placeholder
187 calomed_ = Al; // placeholder
188 mudetmed_ = Al; // placeholder
189
190 // custom parameters
191 contingency_ = 10.;
192 calo_barrel_thickness_ = 50.;
193 calo_endcap_thickness_ = 75.;
194 muonSystem_thickn_ = 10.;
195
196 // read these parameters from the Delphes Card (with default values)
197 etaAxis_ = NULL;
198 phiAxis_ = NULL;
199 tk_radius_ = 120.;
200 tk_length_ = 150.;
201 tk_etamax_ = 3.0;
202 tk_Bz_ = 1.;
203 muonSystem_radius_ = 200.;
204}
205
206void Delphes3DGeometry::readFile(const char *configFile,
207 const char* ParticlePropagator, const char* TrackingEfficiency,
208 const char* MuonEfficiency, const char* Calorimeters) {
209
210 ExRootConfReader *confReader = new ExRootConfReader;
211 confReader->ReadFile(configFile);
212
213 tk_radius_ = confReader->GetDouble(Form("%s::Radius",ParticlePropagator), 1.0)*100.; // tk_radius
214 tk_length_ = confReader->GetDouble(Form("%s::HalfLength",ParticlePropagator), 3.0)*100.; // tk_length
215 tk_Bz_ = confReader->GetDouble("ParticlePropagator::Bz", 0.0); // tk_Bz
216
217 {
218 TString tkEffFormula = confReader->GetString(Form("%s::EfficiencyFormula",TrackingEfficiency),"abs(eta)<3.0");
219 tkEffFormula.ReplaceAll("pt","x");
220 tkEffFormula.ReplaceAll("eta","y");
221 tkEffFormula.ReplaceAll("phi","0.");
222 TF2* tkEffFunction = new TF2("tkEff",tkEffFormula,0,1000,-10,10);
223 TH1F etaHisto("eta","eta",100,5.,-5.);
224 Double_t pt,eta;
225 for(int i=0;i<1000;++i) {
226 tkEffFunction->GetRandom2(pt,eta);
227 etaHisto.Fill(eta);
228 }
229 Int_t bin = -1;
230 bin = etaHisto.FindFirstBinAbove(0.5);
231 Double_t etamin = (bin>-1) ? etaHisto.GetBinLowEdge(bin) : -10.;
232 bin = etaHisto.FindLastBinAbove(0.5);
233 Double_t etamax = (bin>-1) ? etaHisto.GetBinLowEdge(bin+1) : -10.;
234 tk_etamax_ = TMath::Max(fabs(etamin),fabs(etamax)); // tk_etamax
235 delete tkEffFunction;
236 }
237
238 {
239 muondets_.push_back("muons");
240 TString muonEffFormula = confReader->GetString(Form("%s::EfficiencyFormula",MuonEfficiency),"abs(eta)<2.0");
241 muonEffFormula.ReplaceAll("pt","x");
242 muonEffFormula.ReplaceAll("eta","y");
243 muonEffFormula.ReplaceAll("phi","0.");
244 TF2* muEffFunction = new TF2("muEff",muonEffFormula,0,1000,-10,10);
245 TH1F etaHisto("eta2","eta2",100,5.,-5.);
246 Double_t pt,eta;
247 for(int i=0;i<1000;++i) {
248 muEffFunction->GetRandom2(pt,eta);
249 etaHisto.Fill(eta);
250 }
251 Int_t bin = -1;
252 bin = etaHisto.FindFirstBinAbove(0.5);
253 Double_t etamin = (bin>-1) ? etaHisto.GetBinLowEdge(bin) : -10.;
254 bin = etaHisto.FindLastBinAbove(0.5);
255 Double_t etamax = (bin>-1) ? etaHisto.GetBinLowEdge(bin+1) : -10.;
256 muonSystem_etamax_["muons"] = TMath::Max(fabs(etamin),fabs(etamax)); // muonSystem_etamax
257 delete muEffFunction;
258 }
259
260 std::string s(Calorimeters);
261 std::replace( s.begin(), s.end(), ',', ' ' );
262 std::istringstream stream( s );
263 std::string word;
264 while (stream >> word) calorimeters_.push_back(word);
265
266 caloBinning_.clear(); // calo binning
267 for(std::vector<std::string>::const_iterator calo=calorimeters_.begin();calo!=calorimeters_.end(); ++calo) {
268 set< pair<Double_t, Int_t> > caloBinning;
269 ExRootConfParam paramEtaBins, paramPhiBins;
270 ExRootConfParam param = confReader->GetParam(Form("%s::EtaPhiBins",calo->c_str()));
271 Int_t size = param.GetSize();
272 for(int i = 0; i < size/2; ++i) {
273 paramEtaBins = param[i*2];
274 paramPhiBins = param[i*2+1];
275 assert(paramEtaBins.GetSize()==1);
276 caloBinning.insert(std::make_pair(paramEtaBins[0].GetDouble(),paramPhiBins.GetSize()-1));
277 }
278 caloBinning_[*calo] = caloBinning;
279 }
280
281 set< pair<Double_t, Int_t> > caloBinning = caloBinning_[*calorimeters_.begin()];
282 Double_t *etaBins = new Double_t[caloBinning.size()]; // note that this is the eta binning of the first calo
283 unsigned int ii = 0;
284 for(set< pair<Double_t, Int_t> >::const_iterator itEtaSet = caloBinning.begin(); itEtaSet != caloBinning.end(); ++itEtaSet) {
285 etaBins[ii++] = itEtaSet->first;
286 }
287 etaAxis_ = new TAxis(caloBinning.size() - 1, etaBins);
288 phiAxis_ = new TAxis(72, -TMath::Pi(), TMath::Pi()); // note that this is fixed while #phibins could vary, also with eta, which doesn't seem possible in ROOT
289
290 muonSystem_radius_ = tk_radius_ + contingency_ + (contingency_+calo_barrel_thickness_)*calorimeters_.size() + muonSystem_thickn_;
291 muonSystem_length_ = tk_length_ + contingency_ + (contingency_+calo_endcap_thickness_)*calorimeters_.size() + muonSystem_thickn_;
292
293 delete confReader;
294
295}
296
297TGeoVolume* Delphes3DGeometry::getDetector(bool withTowers) {
298 // compute the envelope
299 Double_t system_radius = tk_radius_+calo_barrel_thickness_+3*contingency_;
300 Double_t system_length = tk_length_+contingency_+(contingency_+calo_endcap_thickness_)*calorimeters_.size()+contingency_;
301 // the detector volume
302 TGeoVolume *top = geom_->MakeBox("Delphes3DGeometry", vacuum_, system_radius, system_radius, system_length);
303 // build the detector
304 std::pair<Double_t, Double_t> limits = addTracker(top);
305 Double_t radius = limits.first;
306 Double_t length = limits.second;
307 for(std::vector<std::string>::const_iterator calo = calorimeters_.begin(); calo != calorimeters_.end(); ++calo) {
308 limits = addCalorimeter(top,calo->c_str(),radius,length,caloBinning_[*calo]);
309 if (withTowers) {
310 addCaloTowers(top,calo->c_str(),radius,length,caloBinning_[*calo]);
311 }
312 radius = limits.first;
313 length = limits.second;
314 }
315 for(std::vector<std::string>::const_iterator muon = muondets_.begin(); muon != muondets_.end(); ++muon) {
316 limits = addMuonDets(top, muon->c_str(), radius, length);
317 radius = limits.first;
318 length = limits.second;
319 }
320 // return the result
321 return top;
322}
323
324std::pair<Double_t, Double_t> Delphes3DGeometry::addTracker(TGeoVolume *top) {
325 // tracker: a cylinder with two cones substracted
326 new TGeoCone("forwardTkAcceptance",(tk_length_/2.+0.05),0.,tk_radius_,(tk_length_)*2.*exp(-tk_etamax_)/(1-exp(-2.*tk_etamax_)),tk_radius_);
327 TGeoTranslation *tr1 = new TGeoTranslation("tkacc1",0., 0., tk_length_/2.);
328 tr1->RegisterYourself();
329 TGeoRotation *negz = new TGeoRotation("tknegz",0,180,0);
330 negz->RegisterYourself();
331 TGeoCombiTrans *tr2 = new TGeoCombiTrans("tkacc2",0.,0.,-tk_length_/2.,negz);
332 tr2->RegisterYourself();
333 TGeoCompositeShape* tracker_cs = new TGeoCompositeShape("tracker_cs","forwardTkAcceptance:tkacc1+forwardTkAcceptance:tkacc2");
334 TGeoVolume *tracker = new TGeoVolume("tracker",tracker_cs,tkmed_);
335 tracker->SetLineColor(kYellow);
336 top->AddNode(tracker,1);
337 return std::make_pair(tk_radius_,tk_length_);
338}
339
340std::pair<Double_t, Double_t> Delphes3DGeometry::addCalorimeter(TGeoVolume *top, const char* name,
341 Double_t innerBarrelRadius, Double_t innerBarrelLength, set< pair<Double_t, Int_t> >& caloBinning) {
342 // parameters derived from the inputs
343 Double_t calo_endcap_etamax = TMath::Max(fabs(caloBinning.begin()->first),fabs(caloBinning.rbegin()->first));
344 Double_t calo_barrel_innerRadius = innerBarrelRadius+contingency_;
345 Double_t calo_barrel_length = innerBarrelLength + calo_barrel_thickness_;
346 Double_t calo_endcap_etamin = -log(innerBarrelRadius/(2*innerBarrelLength));
347 Double_t calo_endcap_innerRadius1 = innerBarrelLength*2.*exp(-calo_endcap_etamax)/(1-exp(-2.*calo_endcap_etamax));
348 Double_t calo_endcap_innerRadius2 = (innerBarrelLength+calo_endcap_thickness_)*2.*exp(-calo_endcap_etamax)/(1-exp(-2.*calo_endcap_etamax));
349 Double_t calo_endcap_outerRadius1 = innerBarrelRadius;
350 Double_t calo_endcap_outerRadius2 = innerBarrelRadius+calo_barrel_thickness_;
351 Double_t calo_endcap_coneThickness = TMath::Min(calo_barrel_thickness_ * (1-exp(-2.*calo_endcap_etamin)) / (2.*exp(-calo_endcap_etamin)), calo_endcap_thickness_);
352 Double_t calo_endcap_diskThickness = TMath::Max(0.,calo_endcap_thickness_-calo_endcap_coneThickness);
353
354 // calorimeters: tube truncated in eta + cones
355 new TGeoTube(Form("%s_barrel_cylinder",name),calo_barrel_innerRadius,calo_barrel_innerRadius+calo_barrel_thickness_,calo_barrel_length);
356 new TGeoCone(Form("%s_endcap_cone",name),calo_endcap_coneThickness/2.,calo_endcap_innerRadius1,calo_endcap_outerRadius1,calo_endcap_innerRadius2,calo_endcap_outerRadius2);
357 new TGeoTube(Form("%s_endcap_disk",name),calo_endcap_innerRadius2,tk_radius_+calo_barrel_thickness_,calo_endcap_diskThickness/2.);
358 TGeoTranslation *tr1 = new TGeoTranslation(Form("%s_tr1",name),0., 0., (calo_endcap_coneThickness+calo_endcap_diskThickness)/2.);
359 tr1->RegisterYourself();
360 TGeoCompositeShape *calo_endcap_cs = new TGeoCompositeShape(Form("%s_endcap_cs",name),Form("%s_endcap_cone+%s_endcap_disk:%s_tr1",name,name,name));
361 TGeoTranslation *trc1 = new TGeoTranslation(Form("%s_endcap1_position",name),0.,0., innerBarrelLength+calo_endcap_coneThickness/2.);
362 trc1->RegisterYourself();
363 TGeoRotation *negz = new TGeoRotation(Form("%s_negz",name),0,180,0);
364 TGeoCombiTrans *trc2 = new TGeoCombiTrans(Form("%s_endcap2_position",name),0.,0.,-(innerBarrelLength+calo_endcap_coneThickness/2.),negz);
365 trc2->RegisterYourself();
366 TGeoTranslation *trc1c = new TGeoTranslation(Form("%s_endcap1_position_cont",name),0.,0., innerBarrelLength+calo_endcap_coneThickness/2.+contingency_);
367 trc1c->RegisterYourself();
368 TGeoCombiTrans *trc2c = new TGeoCombiTrans(Form("%s_endcap2_position_cont",name),0.,0.,-(innerBarrelLength+calo_endcap_coneThickness/2.)-contingency_,negz);
369 trc2c->RegisterYourself();
370 TGeoVolume *calo_endcap = new TGeoVolume(Form("%s_endcap",name),calo_endcap_cs,calomed_);
371 TGeoCompositeShape *calo_barrel_cs = new TGeoCompositeShape(Form("%s_barrel_cs",name),
372 Form("%s_barrel_cylinder-%s_endcap_cs:%s_endcap1_position-%s_endcap_cs:%s_endcap2_position",name,name,name,name,name));
373 TGeoVolume *calo_barrel = new TGeoVolume(Form("%s_barrel",name),calo_barrel_cs,calomed_);
374 calo_endcap->SetLineColor(kViolet);
375 calo_endcap->SetFillColor(kViolet);
376 calo_barrel->SetLineColor(kRed);
377 top->AddNode(calo_endcap,1,trc1c);
378 top->AddNode(calo_endcap,2,trc2c);
379 top->AddNode(calo_barrel,1);
380 return std::make_pair(calo_barrel_innerRadius+calo_barrel_thickness_,innerBarrelLength+calo_endcap_thickness_+contingency_);
381}
382
383std::pair<Double_t, Double_t> Delphes3DGeometry::addMuonDets(TGeoVolume *top, const char* name, Double_t innerBarrelRadius, Double_t innerBarrelLength) {
384 // muon system: tube + disks
385 Double_t muonSystem_radius = innerBarrelRadius + contingency_;
386 Double_t muonSystem_length = innerBarrelLength + contingency_;
387 Double_t muonSystem_rmin = muonSystem_length*2.*exp(-muonSystem_etamax_[name])/(1-exp(-2.*muonSystem_etamax_[name]));
388 TGeoVolume *muon_barrel = geom_->MakeTube(Form("%s_barrel",name),mudetmed_,muonSystem_radius,muonSystem_radius+muonSystem_thickn_,muonSystem_length);
389 muon_barrel->SetLineColor(kBlue);
390 top->AddNode(muon_barrel,1);
391 TGeoVolume *muon_endcap = geom_->MakeTube(Form("%s_endcap",name),mudetmed_,muonSystem_rmin,muonSystem_radius+muonSystem_thickn_,muonSystem_thickn_/2.);
392 muon_endcap->SetLineColor(kBlue);
393 TGeoTranslation *trm1 = new TGeoTranslation(Form("%sEndcap1_position",name),0.,0.,muonSystem_length);
394 trm1->RegisterYourself();
395 TGeoTranslation *trm2 = new TGeoTranslation(Form("%sEndcap2_position",name),0.,0.,-muonSystem_length);
396 trm1->RegisterYourself();
397 top->AddNode(muon_endcap,1,trm1);
398 top->AddNode(muon_endcap,2,trm2);
399 return std::make_pair(muonSystem_radius,muonSystem_length);
400}
401
402void Delphes3DGeometry::addCaloTowers(TGeoVolume *top, const char* name,
403 Double_t innerBarrelRadius, Double_t innerBarrelLength, set< pair<Double_t, Int_t> >& caloBinning) {
404
405 TGeoVolume* calo_endcap = top->GetNode(Form("%s_endcap_1",name))->GetVolume();
406 TGeoVolume* calo_barrel = top->GetNode(Form("%s_barrel_1",name))->GetVolume();
407 Double_t calo_endcap_etamin = -log(innerBarrelRadius/(2*innerBarrelLength));
408 Double_t calo_endcap_coneThickness = TMath::Min(calo_barrel_thickness_ * (1-exp(-2.*calo_endcap_etamin)) / (2.*exp(-calo_endcap_etamin)), calo_endcap_thickness_);
409
410 // calo towers in the barrel
411 Double_t vertices[16] = {0.,0.,0.,0.,0.,0.,0.,0.}; // summit of the pyramid
412 Double_t R = tk_radius_ + contingency_+(contingency_+calo_barrel_thickness_)*calorimeters_.size(); // radius of the muons system = height of the pyramid
413 Int_t nEtaBins = caloBinning.size();
414 // this rotation is to make the tower point "up"
415 TGeoRotation* initTowerRot = new TGeoRotation(Form("%s_initTowerRot",name),0.,90.,0.);
416 TGeoCombiTrans* initTower = new TGeoCombiTrans(Form("%s_initTower",name),0.,-R/2.,0.,initTowerRot);
417 initTower->RegisterYourself();
418 // eta bins... we build one pyramid per eta slice and then translate it nphi times.
419 // phi bins represented by rotations around z
420 Double_t *y = new Double_t[nEtaBins];
421 Double_t *dx = new Double_t[nEtaBins];
422 Int_t *nphi = new Int_t[nEtaBins];
423 Int_t etaslice = 0;
424 std::map<std::pair<int,int>, TGeoRotation*> phirotations;
425 for(set< pair<Double_t, Int_t> >::const_iterator bin=caloBinning.begin(); bin!=caloBinning.end();++bin) {
426 if(abs(bin->first)>calo_endcap_etamin) continue; // only in the barrel
427 nphi[etaslice] = bin->second;
428 y[etaslice] = 0.5*R*(1-exp(-2*bin->first))/exp(-bin->first);
429 Double_t phiRotationAngle = 360./nphi[etaslice];
430 dx[etaslice] = R*tan(TMath::Pi()*phiRotationAngle/360.);
431 for(int phislice=0;phislice<nphi[etaslice];++phislice) {
432 phirotations[make_pair(etaslice,phislice)] = new TGeoRotation(Form("%s_phi%d_%d",name,etaslice,phislice),phiRotationAngle*phislice,0.,0.);
433 phirotations[make_pair(etaslice,phislice)]->RegisterYourself();
434 }
435 ++etaslice;
436 }
437 nEtaBins = etaslice;
438 for(int i=0;i<nEtaBins-1;++i) { // loop on the eta slices
439 vertices[8] = -dx[i]; vertices[9] = y[i];
440 vertices[10] = -dx[i]; vertices[11] = y[i+1];
441 vertices[12] = dx[i]; vertices[13] = y[i+1];
442 vertices[14] = dx[i]; vertices[15] = y[i];
443 new TGeoArb8(Form("%s_tower%d",name,i),R/2., vertices); // tower in the proper eta slice, at phi=0
444 // intersection between the tower and the calo_barrel
445 TGeoCompositeShape *finaltower_cs = new TGeoCompositeShape(Form("%s_ftower%d_cs",name,i),Form("%s_tower%d:%s_initTower*%s_barrel_cs",name,i,name,name));
446 TGeoVolume *finaltower = new TGeoVolume(Form("%s_ftower%d",name,i),finaltower_cs,calomed_);
447 finaltower->SetLineColor(kRed);
448 for(int j=0;j<nphi[i];++j) { // loop on the phi slices
449 calo_barrel->AddNode(finaltower,j,phirotations[make_pair(i,j)]);
450 }
451 }
452 delete[] y;
453 delete[] dx;
454 delete[] nphi;
455 //the towers in the forward region
456 R = tk_length_+contingency_+(contingency_+calo_endcap_thickness_)*calorimeters_.size(); // Z of the muons system = height of the pyramid
457 nEtaBins = caloBinning.size();
458 // translation to bring the origin of the tower to (0,0,0) (well, not really as the endcap is not yet in place)
459 TGeoTranslation* towerdz = new TGeoTranslation(Form("%s_towerdz",name),0.,0.,R/2.-(innerBarrelLength+calo_endcap_coneThickness/2.));
460 towerdz->RegisterYourself();
461 // eta bins... we build one pyramid per eta slice and then translate it nphi times.
462 Double_t *r = new Double_t[nEtaBins];
463 nphi = new Int_t[nEtaBins];
464 etaslice = 0;
465 phirotations.clear();
466 for(set< pair<Double_t, Int_t> >::const_iterator bin=caloBinning.begin(); bin!=caloBinning.end();++bin) {
467 if(bin->first<calo_endcap_etamin) continue; // only in the + endcap
468 r[etaslice] = R*2*exp(-bin->first)/(1-exp(-2*bin->first));
469 nphi[etaslice] = bin->second;
470 Double_t phiRotationAngle = 360./nphi[etaslice];
471 for(int phislice=0;phislice<nphi[etaslice];++phislice) {
472 phirotations[make_pair(etaslice,phislice)] = new TGeoRotation(Form("%s_forward_phi%d_%d",name,etaslice,phislice),phiRotationAngle*phislice,0.,0.);
473 phirotations[make_pair(etaslice,phislice)]->RegisterYourself();
474 }
475 ++etaslice;
476 }
477 nEtaBins = etaslice;
478 for(int i=0;i<nEtaBins-1;++i) { // loop on the eta slices
479 vertices[8] = -r[i+1]*sin(TMath::Pi()/nphi[i]); vertices[9] = r[i+1]*cos(TMath::Pi()/nphi[i]);
480 vertices[10] = -r[i]*sin(TMath::Pi()/nphi[i]); vertices[11] = r[i]*cos(TMath::Pi()/nphi[i]);
481 vertices[12] = r[i]*sin(TMath::Pi()/nphi[i]); vertices[13] = r[i]*cos(TMath::Pi()/nphi[i]);
482 vertices[14] = r[i+1]*sin(TMath::Pi()/nphi[i]); vertices[15] = r[i+1]*cos(TMath::Pi()/nphi[i]);
483 new TGeoArb8(Form("%sfwdtower%d",name,i),R/2., vertices); // tower in the proper eta slice, at phi=0
484 // intersection between the tower and the calo_endcap
485 TGeoCompositeShape *finalfwdtower_cs = new TGeoCompositeShape(Form("%sffwdtower%d_cs",name,i),Form("%sfwdtower%d:%s_towerdz*%s_endcap_cs",name,i,name,name));
486 TGeoVolume *finalfwdtower = new TGeoVolume(Form("%sffwdtower%d",name,i),finalfwdtower_cs,calomed_);
487 finalfwdtower->SetLineColor(kViolet);
488 for(int j=0;j<nphi[i];++j) { // loop on the phi slices
489 calo_endcap->AddNode(finalfwdtower,j,phirotations[make_pair(i,j)]);
490 }
491 }
492 delete[] r;
493 delete[] nphi;
494}
495
496/******************************************************************************/
497// Initialization and steering functions
498/******************************************************************************/
499
500void delphes_event_display(const char *configFile, const char *inputFile, Delphes3DGeometry& det3D)
501{
502
503 // initialize the application
504 TEveManager::Create(kTRUE, "IV");
505 TGeoManager* geom = gGeoManager;
506
507 // build the detector
508 gRadius = det3D.getTrackerRadius();
509 gTotRadius = det3D.getDetectorRadius();
510 gHalfLength = det3D.getTrackerHalfLength();
511 gBz = det3D.getBField();
512 gEtaAxis = det3D.getCaloAxes().first;
513 gPhiAxis = det3D.getCaloAxes().second;
514
515 TGeoVolume* top = det3D.getDetector(false);
516 geom->SetTopVolume(top);
517 TEveElementList *geometry = new TEveElementList("Geometry");
518 TEveGeoTopNode* trk = new TEveGeoTopNode(gGeoManager, top->FindNode("tracker_1"));
519 trk->SetVisLevel(6);
520 geometry->AddElement(trk);
521 TEveGeoTopNode* calo = new TEveGeoTopNode(gGeoManager, top->FindNode("Calorimeter_barrel_1"));
522 calo->SetVisLevel(3);
523 geometry->AddElement(calo);
524 calo = new TEveGeoTopNode(gGeoManager, top->FindNode("Calorimeter_endcap_1"));
525 calo->SetVisLevel(3);
526 calo->UseNodeTrans();
527 geometry->AddElement(calo);
528 calo = new TEveGeoTopNode(gGeoManager, top->FindNode("Calorimeter_endcap_2"));
529 calo->SetVisLevel(3);
530 calo->UseNodeTrans();
531 geometry->AddElement(calo);
532 TEveGeoTopNode* muon = new TEveGeoTopNode(gGeoManager, top->FindNode("muons_barrel_1"));
533 muon->SetVisLevel(4);
534 geometry->AddElement(muon);
535 muon = new TEveGeoTopNode(gGeoManager, top->FindNode("muons_endcap_1"));
536 muon->SetVisLevel(4);
537 muon->UseNodeTrans();
538 geometry->AddElement(muon);
539 muon = new TEveGeoTopNode(gGeoManager, top->FindNode("muons_endcap_2"));
540 muon->SetVisLevel(4);
541 muon->UseNodeTrans();
542 geometry->AddElement(muon);
543 //gGeoManager->DefaultColors();
544
545 // Create chain of root trees
546 gChain.Add(inputFile);
547
548 // Create object of class ExRootTreeReader
549 printf("*** Opening Delphes data file ***\n");
550 gTreeReader = new ExRootTreeReader(&gChain);
551
552 // prepare data collections
553 std::vector<DelphesBranchBase*> elements;
554 std::vector<TClonesArray*> arrays;
555 //readConfig(configFile, det3D, elements, arrays);
556 // Get pointers to branches
557//TODO make it configurable, for more objects (or can we guess from the config?)
558 gBranchTower = gTreeReader->UseBranch("Tower");
559 gBranchTrack = gTreeReader->UseBranch("Track");
560 gBranchEle = gTreeReader->UseBranch("Electron");
561 gBranchMuon = gTreeReader->UseBranch("Muon");
562 gBranchPhoton = gTreeReader->UseBranch("Photon");
563 gBranchJet = gTreeReader->UseBranch("Jet");
564 gBranchGenJet = gTreeReader->UseBranch("GenJet");
565 gBranchMet = gTreeReader->UseBranch("MissingET");
566
567 // data
568 gCaloData = new DelphesCaloData(2);
569 gCaloData->RefSliceInfo(0).Setup("ECAL", 0.1, kRed);
570 gCaloData->RefSliceInfo(1).Setup("HCAL", 0.1, kBlue);
571 gCaloData->SetEtaBins(gEtaAxis);
572 gCaloData->SetPhiBins(gPhiAxis);
573 gCaloData->IncDenyDestroy();
574
575 gJetList = new TEveElementList("Jets");
576 gJetList->SetMainColor(kYellow);
577 gEve->AddElement(gJetList);
578
579 gGenJetList = new TEveElementList("GenJets");
580 gGenJetList->SetMainColor(kCyan);
581 gGenJetList->SetRnrSelf(false);
582 gGenJetList->SetRnrChildren(false);
583 gEve->AddElement(gGenJetList);
584
585 gMetList = new TEveElementList("Missing Et");
586 gMetList->SetMainColor(kViolet);
587 gEve->AddElement(gMetList);
588// gMet = new TEveArrow(1., 0., 0., 0., 0., 0.);
589// gMet->SetMainColor(kViolet);
590// gMet->SetTubeR(0.02);
591// gMet->SetPickable(kTRUE);
592// gMet->SetName("Missing Et");
593// gEve->GetCurrentEvent()->AddElement(gMet);
594
595 TEveTrackPropagator *trkProp;
596
597 gElectronList = new TEveTrackList("Electrons");
598 gElectronList->SetMainColor(kRed);
599 gElectronList->SetMarkerColor(kViolet);
600 gElectronList->SetMarkerStyle(kCircle);
601 gElectronList->SetMarkerSize(0.5);
602 gEve->AddElement(gElectronList);
603 trkProp = gElectronList->GetPropagator();
604 trkProp->SetMagField(0.0, 0.0, -gBz);
605 trkProp->SetMaxR(gRadius);
606 trkProp->SetMaxZ(gHalfLength);
607
608 gMuonList = new TEveTrackList("Muons");
609 gMuonList->SetMainColor(kGreen);
610 gMuonList->SetMarkerColor(kViolet);
611 gMuonList->SetMarkerStyle(kCircle);
612 gMuonList->SetMarkerSize(0.5);
613 gEve->AddElement(gMuonList);
614 trkProp = gMuonList->GetPropagator();
615 trkProp->SetMagField(0.0, 0.0, -gBz);
616 trkProp->SetMaxR(gTotRadius);
617 trkProp->SetMaxZ(gHalfLength);
618
619 gTrackList = new TEveTrackList("Tracks");
620 gTrackList->SetMainColor(kBlue);
621 gTrackList->SetMarkerColor(kRed);
622 gTrackList->SetMarkerStyle(kCircle);
623 gTrackList->SetMarkerSize(0.5);
624 gEve->AddElement(gTrackList);
625 trkProp = gTrackList->GetPropagator();
626 trkProp->SetMagField(0.0, 0.0, -gBz);
627 trkProp->SetMaxR(gRadius);
628 trkProp->SetMaxZ(gHalfLength);
629
630 gPhotonList= new TEveTrackList("Photons");
631 gPhotonList->SetMainColor(kYellow);
632 gPhotonList->SetLineStyle(7);
633 gPhotonList->SetMarkerColor(kViolet);
634 gPhotonList->SetMarkerStyle(kCircle);
635 gPhotonList->SetMarkerSize(0.5);
636 gEve->AddElement(gPhotonList);
637 trkProp = gPhotonList->GetPropagator();
638 trkProp->SetMagField(0.0, 0.0, 0.0);
639 trkProp->SetMaxR(gRadius);
640 trkProp->SetMaxZ(gHalfLength);
641
642 // viewers and scenes
643
644 TEveCalo3D *calo3d = new TEveCalo3D(gCaloData);
645 calo3d->SetBarrelRadius(gRadius);
646 calo3d->SetEndCapPos(gHalfLength);
647
648 //gStyle->SetPalette(1, 0);
649 TEveCaloLego *lego = new TEveCaloLego(gCaloData);
650 lego->InitMainTrans();
651 lego->RefMainTrans().SetScale(TMath::TwoPi(), TMath::TwoPi(), TMath::Pi());
652 lego->SetAutoRebin(kFALSE);
653 lego->Set2DMode(TEveCaloLego::kValSizeOutline);
654
655 gDelphesDisplay = new DelphesDisplay;
656 gEve->AddGlobalElement(geometry);
657 gEve->AddGlobalElement(calo3d);
658 gDelphesDisplay->ImportGeomRPhi(geometry);
659 gDelphesDisplay->ImportCaloRPhi(calo3d);
660 gDelphesDisplay->ImportGeomRhoZ(geometry);
661 gDelphesDisplay->ImportCaloRhoZ(calo3d);
662 gDelphesDisplay->ImportCaloLego(lego);
663 gEve->Redraw3D(kTRUE);
664
665}
666
667//______________________________________________________________________________
668void load_event()
669{
670 // Load event specified in global event_id.
671 // The contents of previous event are removed.
672
673 printf("Loading event %d.\n", event_id);
674
675 gEve->GetViewers()->DeleteAnnotations();
676
677 if(gCaloData) gCaloData->ClearTowers();
678 if(gJetList) gJetList->DestroyElements();
679 if(gMetList) gMetList->DestroyElements();
680 if(gGenJetList) gGenJetList->DestroyElements();
681 if(gTrackList) gTrackList->DestroyElements();
682 if(gElectronList) gElectronList->DestroyElements();
683 if(gMuonList) gMuonList->DestroyElements();
684 if(gPhotonList) gPhotonList->DestroyElements();
685
686 delphes_read();
687
688 TEveElement* top = (TEveElement*)gEve->GetCurrentEvent();
689 gDelphesDisplay->DestroyEventRPhi();
690 gDelphesDisplay->ImportEventRPhi(top);
691 gDelphesDisplay->DestroyEventRhoZ();
692 gDelphesDisplay->ImportEventRhoZ(top);
693
694 //update_html_summary();
695
696 gEve->Redraw3D(kFALSE, kTRUE);
697}
698
699void delphes_read()
700{
701
702 TIter itTower(gBranchTower);
703 TIter itTrack(gBranchTrack);
704 TIter itElectron(gBranchEle);
705 TIter itPhoton(gBranchPhoton);
706 TIter itMuon(gBranchMuon);
707 TIter itJet(gBranchJet);
708 TIter itGenJet(gBranchGenJet);
709 TIter itMet(gBranchMet);
710
711 Tower *tower;
712 Track *track;
713 Electron *electron;
714 Muon *muon;
715 Photon *photon;
716 Jet *jet;
717 MissingET *MET;
718
719 TEveJetCone *eveJetCone;
720 TEveTrack *eveTrack;
721 TEveArrow *eveMet;
722
723 Int_t counter;
724 Float_t maxPt = 0.;
725
726 TEveTrackPropagator *trkProp = gTrackList->GetPropagator();
727 TEveTrackPropagator *photProp = gPhotonList->GetPropagator();
728 if(event_id >= gTreeReader->GetEntries()) return;
729
730 // Load selected branches with data from specified event
731 gTreeReader->ReadEntry(event_id);
732
733 // Loop over all towers
734 itTower.Reset();
735 while((tower = (Tower *) itTower.Next()))
736 {
737 gCaloData->AddTower(tower->Edges[0], tower->Edges[1], tower->Edges[2], tower->Edges[3]);
738 gCaloData->FillSlice(0, tower->Eem);
739 gCaloData->FillSlice(1, tower->Ehad);
740 }
741 gCaloData->DataChanged();
742
743 // Loop over all tracks
744 itTrack.Reset();
745 counter = 0;
746 while((track = (Track *) itTrack.Next())) {
747 TParticle pb(track->PID, 1, 0, 0, 0, 0,
748 track->P4().Px(), track->P4().Py(),
749 track->P4().Pz(), track->P4().E(),
750 track->X, track->Y, track->Z, 0.0);
751
752 eveTrack = new TEveTrack(&pb, counter, trkProp);
753 eveTrack->SetName(Form("%s [%d]", pb.GetName(), counter++));
754 eveTrack->SetStdTitle();
755 eveTrack->SetAttLineAttMarker(gTrackList);
756 gTrackList->AddElement(eveTrack);
757 eveTrack->SetLineColor(kBlue);
758 eveTrack->MakeTrack();
759 maxPt = maxPt > track->PT ? maxPt : track->PT;
760 }
761
762 // Loop over all electrons
763 itElectron.Reset();
764 counter = 0;
765 while((electron = (Electron *) itElectron.Next())) {
766 TParticle pb(electron->Charge<0?11:-11, 1, 0, 0, 0, 0,
767 electron->P4().Px(), electron->P4().Py(),
768 electron->P4().Pz(), electron->P4().E(),
769 0., 0., 0., 0.);
770
771 eveTrack = new TEveTrack(&pb, counter, trkProp);
772 eveTrack->SetName(Form("%s [%d]", pb.GetName(), counter++));
773 eveTrack->SetStdTitle();
774 eveTrack->SetAttLineAttMarker(gElectronList);
775 gElectronList->AddElement(eveTrack);
776 eveTrack->SetLineColor(kRed);
777 eveTrack->MakeTrack();
778 maxPt = maxPt > electron->PT ? maxPt : electron->PT;
779 }
780
781 // Loop over all photons
782 itPhoton.Reset();
783 counter = 0;
784 while((photon = (Photon *) itPhoton.Next())) {
785 TParticle pb(22, 1, 0, 0, 0, 0,
786 photon->P4().Px(), photon->P4().Py(),
787 photon->P4().Pz(), photon->P4().E(),
788 0., 0., 0., 0.);
789
790 eveTrack = new TEveTrack(&pb, counter, photProp);
791 eveTrack->SetName(Form("%s [%d]", pb.GetName(), counter++));
792 eveTrack->SetStdTitle();
793 eveTrack->SetAttLineAttMarker(gPhotonList);
794 gPhotonList->AddElement(eveTrack);
795 eveTrack->SetLineColor(kYellow);
796 eveTrack->MakeTrack();
797 maxPt = maxPt > photon->PT ? maxPt : photon->PT;
798 }
799
800 // Loop over all muons
801 itMuon.Reset();
802 counter = 0;
803 while((muon = (Muon *) itMuon.Next())) {
804 TParticle pb(muon->Charge<0?13:-13, 1, 0, 0, 0, 0,
805 muon->P4().Px(), muon->P4().Py(),
806 muon->P4().Pz(), muon->P4().E(),
807 0., 0., 0., 0.);
808
809 eveTrack = new TEveTrack(&pb, counter, trkProp);
810 eveTrack->SetName(Form("%s [%d]", pb.GetName(), counter++));
811 eveTrack->SetStdTitle();
812 eveTrack->SetAttLineAttMarker(gMuonList);
813 gMuonList->AddElement(eveTrack);
814 eveTrack->SetLineColor(kGreen);
815 eveTrack->MakeTrack();
816 maxPt = maxPt > muon->PT ? maxPt : muon->PT;
817 }
818
819 // Loop over all jets
820 itJet.Reset();
821 counter = 0;
822 while((jet = (Jet *) itJet.Next()))
823 {
824 eveJetCone = new TEveJetCone();
825 eveJetCone->SetTitle(Form("jet [%d]: Pt=%f, Eta=%f, \nPhi=%f, M=%f",counter,jet->PT, jet->Eta, jet->Phi, jet->Mass));
826 eveJetCone->SetName(Form("jet [%d]", counter++));
827 eveJetCone->SetMainTransparency(60);
828 eveJetCone->SetLineColor(kYellow);
829 eveJetCone->SetFillColor(kYellow);
830 eveJetCone->SetCylinder(gRadius - 10, gHalfLength - 10);
831 eveJetCone->SetPickable(kTRUE);
832 eveJetCone->AddEllipticCone(jet->Eta, jet->Phi, jet->DeltaEta, jet->DeltaPhi);
833 gJetList->AddElement(eveJetCone);
834 maxPt = maxPt > jet->PT ? maxPt : jet->PT;
835 }
836
837 // Loop over all genjets
838 itJet.Reset();
839 counter = 0;
840 while((jet = (Jet *) itGenJet.Next()))
841 {
842 eveJetCone = new TEveJetCone();
843 eveJetCone->SetTitle(Form("jet [%d]: Pt=%f, Eta=%f, \nPhi=%f, M=%f",counter,jet->PT, jet->Eta, jet->Phi, jet->Mass));
844 eveJetCone->SetName(Form("jet [%d]", counter++));
845 eveJetCone->SetMainTransparency(60);
846 eveJetCone->SetLineColor(kCyan);
847 eveJetCone->SetFillColor(kCyan);
848 eveJetCone->SetCylinder(gRadius - 10, gHalfLength - 10);
849 eveJetCone->SetPickable(kTRUE);
850 eveJetCone->AddEllipticCone(jet->Eta, jet->Phi, jet->DeltaEta, jet->DeltaPhi);
851 gGenJetList->AddElement(eveJetCone);
852 }
853
854 // Missing Et
855 // recipe: gRadius * MET/maxpt(tracks, jets)
856 itMet.Reset();
857 while((MET = (MissingET*) itMet.Next())) {
858 eveMet = new TEveArrow((gRadius * MET->MET/maxPt)*cos(MET->Phi), (gRadius * MET->MET/maxPt)*sin(MET->Phi), 0., 0., 0., 0.);
859 eveMet->SetMainColor(kViolet);
860 eveMet->SetTubeR(0.04);
861 eveMet->SetConeR(0.08);
862 eveMet->SetConeL(0.10);
863 eveMet->SetPickable(kTRUE);
864 eveMet->SetName("Missing Et");
865 eveMet->SetTitle(Form("Missing Et (%.1f GeV)",MET->MET));
866 gMetList->AddElement(eveMet);
867 }
868}
869
870
871/******************************************************************************/
872// GUI
873/******************************************************************************/
874
875//______________________________________________________________________________
876//
877// EvNavHandler class is needed to connect GUI signals.
878
879class EvNavHandler
880{
881public:
882 void Fwd()
883 {
884 if (event_id < gTreeReader->GetEntries() - 1) {
885 ++event_id;
886 load_event();
887 } else {
888 printf("Already at last event.\n");
889 }
890 }
891 void Bck()
892 {
893 if (event_id > 0) {
894 --event_id;
895 load_event();
896 } else {
897 printf("Already at first event.\n");
898 }
899 }
900};
901
902//______________________________________________________________________________
903void make_gui()
904{
905 // Create minimal GUI for event navigation.
906 // TODO: better GUI could be made based on the ch15 of the manual (Writing a GUI)
907
908 // add a tab on the left
909 TEveBrowser* browser = gEve->GetBrowser();
910 browser->StartEmbedding(TRootBrowser::kLeft);
911
912 // set the main title
913 TGMainFrame* frmMain = new TGMainFrame(gClient->GetRoot(), 1000, 600);
914 frmMain->SetWindowName("Delphes Event Display");
915 frmMain->SetCleanup(kDeepCleanup);
916
917 // build the navigation menu
918 TGHorizontalFrame* hf = new TGHorizontalFrame(frmMain);
919 {
920 TString icondir;
921 if(gSystem->Getenv("ROOTSYS"))
922 icondir = Form("%s/icons/", gSystem->Getenv("ROOTSYS"));
923 if(!gSystem->OpenDirectory(icondir))
924 icondir = Form("%s/icons/", (const char*)gSystem->GetFromPipe("root-config --etcdir") );
925 TGPictureButton* b = 0;
926 EvNavHandler *fh = new EvNavHandler;
927
928 b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoBack.gif"));
929 hf->AddFrame(b);
930 b->Connect("Clicked()", "EvNavHandler", fh, "Bck()");
931
932 b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoForward.gif"));
933 hf->AddFrame(b);
934 b->Connect("Clicked()", "EvNavHandler", fh, "Fwd()");
935 }
936 frmMain->AddFrame(hf);
937 frmMain->MapSubwindows();
938 frmMain->Resize();
939 frmMain->MapWindow();
940 browser->StopEmbedding();
941 browser->SetTabTitle("Event Control", 0);
942}
943
944/******************************************************************************/
945// MAIN
946/******************************************************************************/
947
948void geometry(const char* filename = "delphes_card_CMS.tcl", const char* ParticlePropagator="ParticlePropagator",
949 const char* TrackingEfficiency="ChargedHadronTrackingEfficiency",
950 const char* MuonEfficiency="MuonEfficiency",
951 const char* Calorimeters="Calorimeter")
952{
953
954 // load the libraries
955 gSystem->Load("libGeom");
956 gSystem->Load("../libDelphes");
957 gSystem->Load("../libDelphesDisplay");
958
959 // create the detector representation
960 Delphes3DGeometry det3D(new TGeoManager("delphes", "Delphes geometry"));
961 det3D.readFile(filename, ParticlePropagator, TrackingEfficiency, MuonEfficiency, Calorimeters);
962
963 // create the application items
964 delphes_event_display("delphes_card_CMS.tcl", "../delphes_output.root", det3D);
965 make_gui();
966 load_event();
967 gEve->Redraw3D(kTRUE); // Reset camera after the first event has been shown.
968
969 // EClipType not exported to CINT (see TGLUtil.h):
970 // 0 - no clip, 1 - clip plane, 2 - clip box
971 TGLViewer *v = gEve->GetDefaultGLViewer();
972 //Double_t plane[4] = { 0., 1., 0., 0. };
973 //v->GetClipSet()->SetClipState(1,plane);
974 //v->GetClipSet()->SetClipType(1);
975 //v->ColorSet().Background().SetColor(kMagenta+4);
976 //v->SetGuideState(TGLUtil::kAxesEdge, kTRUE, kFALSE, 0);
977 v->RefreshPadEditor(v);
978 v->CurrentCamera().RotateRad(-1.2, 0.5);
979 v->DoDraw();
980
981}
982
983// virtual class to represent objects from a Delphes-tree branch
984class DelphesBranchBase
985{
986 public:
987 DelphesBranchBase(const char* name, const char*type, const enum EColor color):name_(name),type_(type),color_(color) {}
988 virtual ~DelphesBranchBase() {};
989 const char* GetName() const { return (const char*)name_; }
990 const char* GetType() const { return (const char*)type_; }
991 enum EColor GetColor() const { return color_; }
992 virtual const char* GetClassName() = 0;
993 virtual void Reset() = 0;
994
995 private:
996 TString name_;
997 TString type_; // needed for parsing the branch later on
998 const enum EColor color_;
999};
1000// concrete implementations. EveContainer can be a TrackList, ElementList or CaloData.
1001template<typename EveContainer> class DelphesBranchElement: public DelphesBranchBase
1002{
1003 public:
1004 DelphesBranchElement(const char* name, const char*type, const enum EColor color):DelphesBranchBase(name, type, color) {
1005 throw std::exception();
1006 }
1007
1008 // destructor
1009 virtual ~DelphesBranchElement() {
1010 delete data_;
1011 }
1012
1013 // get the container (ElementList, TrackList, or CaloData)
1014 EveContainer* GetContainer() { return data_; }
1015
1016 // resets the collection (before moving to the next event)
1017 // making it pure virtual implies that only the specializations below will compile
1018 virtual void Reset() {};
1019
1020 // template class name
1021 virtual const char* GetClassName() { return data_->ClassName(); }
1022
1023 private:
1024 EveContainer* data_;
1025};
1026// special case for calo towers
1027template<> DelphesBranchElement<DelphesCaloData>::DelphesBranchElement(const char* name, const char*type, const enum EColor color):DelphesBranchBase(name, type, color) {
1028 if(TString(type)=="tower") {
1029 data_ = new DelphesCaloData(2);
1030 data_->RefSliceInfo(0).Setup("ECAL", 0.1, kRed);
1031 data_->RefSliceInfo(1).Setup("HCAL", 0.1, kBlue);
1032 data_->IncDenyDestroy();
1033 } else {
1034 throw std::exception();
1035 }
1036 }
1037template<> void DelphesBranchElement<DelphesCaloData>::Reset() { data_->ClearTowers(); }
1038// special case for element lists
1039template<> DelphesBranchElement<TEveElementList>::DelphesBranchElement(const char* name, const char*type, const enum EColor color):DelphesBranchBase(name, type, color) {
1040 if(TString(type)=="vector" || TString(type)=="jet") {
1041 data_ = new TEveElementList(name);
1042 data_->SetMainColor(color_);
1043 } else {
1044 throw std::exception();
1045 }
1046 }
1047template<> void DelphesBranchElement<TEveElementList>::Reset() { data_->DestroyElements(); }
1048// special case for track lists
1049template<> DelphesBranchElement<TEveTrackList>::DelphesBranchElement(const char* name, const char*type, const enum EColor color):DelphesBranchBase(name, type, color) {
1050 if(TString(type)=="track") {
1051 data_ = new TEveTrackList(name);
1052 data_->SetMainColor(color_);
1053 data_->SetMarkerColor(color_);
1054 data_->SetMarkerStyle(kCircle);
1055 data_->SetMarkerSize(0.5);
1056 } else if(TString(type)=="photon") {
1057 data_ = new TEveTrackList(name);
1058 data_->SetMainColor(color_);
1059 data_->SetMarkerColor(color_);
1060 data_->SetMarkerStyle(kCircle);
1061 data_->SetMarkerSize(0.5);
1062 } else {
1063 throw std::exception();
1064 }
1065 }
1066template<> void DelphesBranchElement<TEveTrackList>::Reset() { data_->DestroyElements(); }
1067
1068// function that parses the config to extract the branches of interest and prepare containers
1069void readConfig(const char *configFile, Delphes3DGeometry& det3D, std::vector<DelphesBranchBase*>& elements, std::vector<TClonesArray*>& arrays) {
1070 ExRootConfReader *confReader = new ExRootConfReader;
1071 confReader->ReadFile(configFile);
1072 Double_t tk_radius = det3D.getTrackerRadius();
1073 Double_t tk_length = det3D.getTrackerHalfLength();
1074 Double_t tk_Bz = det3D.getBField();
1075 Double_t mu_radius = det3D.getDetectorRadius();
1076 Double_t mu_length = det3D.getDetectorHalfLength();
1077 TAxis* etaAxis = det3D.getCaloAxes().first;
1078 TAxis* phiAxis = det3D.getCaloAxes().second;
1079 ExRootConfParam branches = confReader->GetParam("TreeWriter::Branch");
1080 Int_t nBranches = branches.GetSize()/3;
1081 for(Int_t b = 0; b<nBranches; ++b) {
1082 TString input = branches[b*3].GetString();
1083 TString name = branches[b*3+1].GetString();
1084 TString className = branches[b*3+2].GetString();
1085 if(className=="Track") {
1086 if(input.Contains("eflow",TString::kIgnoreCase) || name.Contains("eflow",TString::kIgnoreCase)) continue; //no eflow
1087 DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"track",kBlue);
1088 elements.push_back(list);
1089 TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
1090 trkProp->SetMagField(0., 0., -tk_Bz);
1091 trkProp->SetMaxR(tk_radius);
1092 trkProp->SetMaxZ(tk_length);
1093 } else if(className=="Tower") {
1094 if(input.Contains("eflow",TString::kIgnoreCase) || name.Contains("eflow",TString::kIgnoreCase)) continue; //no eflow
1095 DelphesBranchElement<DelphesCaloData>* list = new DelphesBranchElement<DelphesCaloData>(name,"tower",kBlack);
1096 list->GetContainer()->SetEtaBins(etaAxis);
1097 list->GetContainer()->SetPhiBins(phiAxis);
1098 elements.push_back(list);
1099 } else if(className=="Jet") {
1100 if(input.Contains("GenJetFinder")) {
1101 DelphesBranchElement<TEveElementList>* list = new DelphesBranchElement<TEveElementList>(name,"jet",kCyan);
1102 list->GetContainer()->SetRnrSelf(false);
1103 list->GetContainer()->SetRnrChildren(false);
1104 elements.push_back(list);
1105 } else {
1106 elements.push_back(new DelphesBranchElement<TEveElementList>(name,"jet",kYellow));
1107 }
1108 } else if(className=="Electron") {
1109 DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"track",kRed);
1110 elements.push_back(list);
1111 TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
1112 trkProp->SetMagField(0., 0., -tk_Bz);
1113 trkProp->SetMaxR(tk_radius);
1114 trkProp->SetMaxZ(tk_length);
1115 } else if(className=="Photon") {
1116 DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"photon",kYellow);
1117 elements.push_back(list);
1118 TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
1119 trkProp->SetMagField(0., 0., 0.);
1120 trkProp->SetMaxR(tk_radius);
1121 trkProp->SetMaxZ(tk_length);
1122 } else if(className=="Muon") {
1123 DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"track",kGreen);
1124 elements.push_back(list);
1125 TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
1126 trkProp->SetMagField(0., 0., -tk_Bz);
1127 trkProp->SetMaxR(mu_radius);
1128 trkProp->SetMaxZ(mu_length);
1129 } else if(className=="MissingET") {
1130 elements.push_back(new DelphesBranchElement<TEveElementList>(name,"vector",kViolet));
1131 } else if(className=="GenParticle") {
1132 DelphesBranchElement<TEveTrackList>* list = new DelphesBranchElement<TEveTrackList>(name,"track",kCyan);
1133 elements.push_back(list);
1134 list->GetContainer()->SetRnrSelf(false);
1135 list->GetContainer()->SetRnrChildren(false);
1136 TEveTrackPropagator *trkProp = list->GetContainer()->GetPropagator();
1137 trkProp->SetMagField(0., 0., -tk_Bz);
1138 trkProp->SetMaxR(tk_radius);
1139 trkProp->SetMaxZ(tk_length);
1140 }
1141 arrays.push_back(gTreeReader->UseBranch(name));
1142 }
1143}
Note: See TracBrowser for help on using the repository browser.