Fork me on GitHub

source: git/examples/geometry.C@ 7f66dc0

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

integration of event display ongoing

Not functionnal so far. geometry.C still only displays the geometry in a
eve window.

  • Property mode set to 100644
File size: 32.6 KB
Line 
1#include <set>
2#include <map>
3#include <utility>
4#include <vector>
5#include <algorithm>
6#include <sstream>
7#include "TGeoManager.h"
8#include "TGeoVolume.h"
9#include "TGeoMedium.h"
10#include "TGeoNode.h"
11#include "TGeoCompositeShape.h"
12#include "TGeoMatrix.h"
13#include "TGeoTube.h"
14#include "TGeoCone.h"
15#include "TGeoArb8.h"
16//#include "../external/ExRootAnalysis/ExRootConfReader.h"
17#include "TF2.h"
18#include "TH1F.h"
19#include "TMath.h"
20#include "TSystem.h"
21
22/*
23 * alice_esd.C : GUI complete
24 * assembly.C: sauvegarde as shape-extract -> implement in the geometry class (read/write)
25 * histobrowser.C: intégration d'histogrammes dans le display (on pourrait avoir Pt, eta, phi pour les principales collections)
26 * also from alice_esd: summary html table
27 *
28 */
29using namespace std;
30
31// Forward declarations.
32class Delphes3DGeometry;
33class ExRootTreeReader;
34class DelphesCaloData;
35class DelphesDisplay;
36void make_gui();
37void load_event();
38void delphes_read();
39
40// Configuration and global variables.
41Int_t event_id = 0; // Current event id.
42Double_t gRadius = 1.29;
43Double_t gHalfLength = 3.0;
44Double_t gBz = 3.8;
45
46TAxis *gEtaAxis = 0;
47TAxis *gPhiAxis = 0;
48
49TChain gChain("Delphes");
50
51ExRootTreeReader *gTreeReader = 0;
52
53TClonesArray *gBranchTower = 0;
54TClonesArray *gBranchTrack = 0;
55TClonesArray *gBranchJet = 0;
56
57DelphesCaloData *gCaloData = 0;
58TEveElementList *gJetList = 0;
59TEveTrackList *gTrackList = 0;
60
61DelphesDisplay *gDelphesDisplay = 0;
62
63/******************************************************************************/
64// Construction of the geometry
65/******************************************************************************/
66
67// TODO: asymmetric detector
68
69class Delphes3DGeometry {
70 public:
71 Delphes3DGeometry(TGeoManager *geom = NULL);
72 ~Delphes3DGeometry() {}
73
74 void readFile(const char* filename, const char* ParticlePropagator="ParticlePropagator",
75 const char* TrackingEfficiency="ChargedHadronTrackingEfficiency",
76 const char* MuonEfficiency="MuonEfficiency",
77 const char* Calorimeters="Calorimeter");
78
79 void setContingency(Double_t contingency) { contingency_ = contingency; }
80 void setCaloBarrelThickness(Double_t thickness) { calo_barrel_thickness_ = thickness; }
81 void setCaloEndcapThickness(Double_t thickness) { calo_endcap_thickness_ = thickness; }
82 void setMuonSystemThickness(Double_t thickness) { muonSystem_thickn_ = thickness; }
83
84 TGeoVolume* getDetector(bool withTowers = true);
85
86 private:
87 std::pair<Double_t, Double_t> addTracker(TGeoVolume *top);
88 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);
89 std::pair<Double_t, Double_t> addMuonDets(TGeoVolume *top, const char* name, Double_t innerBarrelRadius, Double_t innerBarrelLength);
90 void addCaloTowers(TGeoVolume *top, const char* name, Double_t innerBarrelRadius, Double_t innerBarrelLength, set< pair<Double_t, Int_t> >& caloBinning);
91
92 private:
93
94 TGeoManager *geom_;
95
96 TGeoMedium *vacuum_;
97 TGeoMedium *tkmed_;
98 TGeoMedium *calomed_;
99 TGeoMedium *mudetmed_;
100
101 Double_t contingency_;
102 Double_t calo_barrel_thickness_;
103 Double_t calo_endcap_thickness_;
104 Double_t muonSystem_thickn_;
105 Double_t tk_radius_;
106 Double_t tk_length_;
107 Double_t tk_etamax_;
108
109 std::vector<std::string> calorimeters_;
110 std::vector<std::string> muondets_;
111
112 std::map<std::string, Double_t> muonSystem_etamax_;
113 std::map<std::string, set< pair<Double_t, Int_t> > > caloBinning_;
114
115};
116
117Delphes3DGeometry::Delphes3DGeometry(TGeoManager *geom) {
118
119 //--- the geometry manager
120 geom_ = geom==NULL? gGeoManager : geom;
121
122 //--- define some materials
123 TGeoMaterial *matVacuum = new TGeoMaterial("Vacuum", 0,0,0);
124 TGeoMaterial *matAl = new TGeoMaterial("Al", 26.98,13,2.7); // placeholder
125
126 //--- define some media
127 TGeoMedium *Vacuum = new TGeoMedium("Vacuum",1, matVacuum);
128 TGeoMedium *Al = new TGeoMedium("Root Material",2, matAl);
129 vacuum_ = Vacuum;
130 tkmed_ = Vacuum; // placeholder
131 calomed_ = Al; // placeholder
132 mudetmed_ = Al; // placeholder
133
134 // custom parameters
135 contingency_ = 10.;
136 calo_barrel_thickness_ = 50.;
137 calo_endcap_thickness_ = 75.;
138 muonSystem_thickn_ = 10.;
139
140 // read these parameters from the Delphes Card (with default values)
141 tk_radius_ = 120.;
142 tk_length_ = 150.;
143 tk_etamax_ = 3.0;
144}
145
146void Delphes3DGeometry::readFile(const char *configFile,
147 const char* ParticlePropagator, const char* TrackingEfficiency,
148 const char* MuonEfficiency, const char* Calorimeters) {
149
150 ExRootConfReader *confReader = new ExRootConfReader;
151 confReader->ReadFile(configFile);
152
153 tk_radius_ = confReader->GetDouble(Form("%s::Radius",ParticlePropagator), 1.0)*100; // tk_radius
154 tk_length_ = confReader->GetDouble(Form("%s::HalfLength",ParticlePropagator), 3.0)*100; // tk_length
155
156 {
157 TString tkEffFormula = confReader->GetString(Form("%s::EfficiencyFormula",TrackingEfficiency),"abs(eta)<3.0");
158 tkEffFormula.ReplaceAll("pt","x");
159 tkEffFormula.ReplaceAll("eta","y");
160 tkEffFormula.ReplaceAll("phi","0.");
161 TF2* tkEffFunction = new TF2("tkEff",tkEffFormula,0,1000,-10,10);
162 TH1F etaHisto("eta","eta",100,5.,-5.);
163 Double_t pt,eta;
164 for(int i=0;i<1000;++i) {
165 tkEffFunction->GetRandom2(pt,eta);
166 etaHisto.Fill(eta);
167 }
168 Int_t bin = -1;
169 bin = etaHisto.FindFirstBinAbove(0.5);
170 Double_t etamin = (bin>-1) ? etaHisto.GetBinLowEdge(bin) : -10.;
171 bin = etaHisto.FindLastBinAbove(0.5);
172 Double_t etamax = (bin>-1) ? etaHisto.GetBinLowEdge(bin+1) : -10.;
173 tk_etamax_ = TMath::Max(fabs(etamin),fabs(etamax)); // tk_etamax
174 delete tkEffFunction;
175 }
176
177 {
178 muondets_.push_back("muons");
179 TString muonEffFormula = confReader->GetString(Form("%s::EfficiencyFormula",MuonEfficiency),"abs(eta)<2.0");
180 muonEffFormula.ReplaceAll("pt","x");
181 muonEffFormula.ReplaceAll("eta","y");
182 muonEffFormula.ReplaceAll("phi","0.");
183 TF2* muEffFunction = new TF2("muEff",muonEffFormula,0,1000,-10,10);
184 TH1F etaHisto("eta2","eta2",100,5.,-5.);
185 Double_t pt,eta;
186 for(int i=0;i<1000;++i) {
187 muEffFunction->GetRandom2(pt,eta);
188 etaHisto.Fill(eta);
189 }
190 Int_t bin = -1;
191 bin = etaHisto.FindFirstBinAbove(0.5);
192 Double_t etamin = (bin>-1) ? etaHisto.GetBinLowEdge(bin) : -10.;
193 bin = etaHisto.FindLastBinAbove(0.5);
194 Double_t etamax = (bin>-1) ? etaHisto.GetBinLowEdge(bin+1) : -10.;
195 muonSystem_etamax_["muons"] = TMath::Max(fabs(etamin),fabs(etamax)); // muonSystem_etamax
196 delete muEffFunction;
197 }
198
199 std::string s(Calorimeters);
200 std::replace( s.begin(), s.end(), ',', ' ' );
201 std::istringstream stream( s );
202 std::string word;
203 while (stream >> word) calorimeters_.push_back(word);
204
205 caloBinning_.clear(); // calo binning
206 for(std::vector<std::string>::const_iterator calo=calorimeters_.begin();calo!=calorimeters_.end(); ++calo) {
207 set< pair<Double_t, Int_t> > caloBinning;
208 ExRootConfParam paramEtaBins, paramPhiBins;
209 ExRootConfParam param = confReader->GetParam(Form("%s::EtaPhiBins",calo->c_str()));
210 Int_t size = param.GetSize();
211 for(int i = 0; i < size/2; ++i) {
212 paramEtaBins = param[i*2];
213 paramPhiBins = param[i*2+1];
214 assert(paramEtaBins.GetSize()==1);
215 caloBinning.insert(std::make_pair(paramEtaBins[0].GetDouble(),paramPhiBins.GetSize()-1));
216 }
217 caloBinning_[*calo] = caloBinning;
218 }
219
220 delete confReader;
221
222}
223
224TGeoVolume* Delphes3DGeometry::getDetector(bool withTowers) {
225 // compute the envelope
226 Double_t system_radius = tk_radius_+calo_barrel_thickness_+3*contingency_;
227 Double_t system_length = tk_length_+contingency_+(contingency_+calo_endcap_thickness_)*calorimeters_.size()+contingency_;
228 // the detector volume
229 TGeoVolume *top = geom_->MakeBox("Delphes3DGeometry", vacuum_, system_radius, system_radius, system_length);
230 // build the detector
231 std::pair<Double_t, Double_t> limits = addTracker(top);
232 Double_t radius = limits.first;
233 Double_t length = limits.second;
234 for(std::vector<std::string>::const_iterator calo = calorimeters_.begin(); calo != calorimeters_.end(); ++calo) {
235 limits = addCalorimeter(top,calo->c_str(),radius,length,caloBinning_[*calo]);
236 if (withTowers) {
237 addCaloTowers(top,calo->c_str(),radius,length,caloBinning_[*calo]);
238 }
239 radius = limits.first;
240 length = limits.second;
241 }
242 for(std::vector<std::string>::const_iterator muon = muondets_.begin(); muon != muondets_.end(); ++muon) {
243 limits = addMuonDets(top, muon->c_str(), radius, length);
244 radius = limits.first;
245 length = limits.second;
246 }
247 // return the result
248 return top;
249}
250
251std::pair<Double_t, Double_t> Delphes3DGeometry::addTracker(TGeoVolume *top) {
252 // tracker: a cylinder with two cones substracted
253 new TGeoCone("forwardTkAcceptance",(tk_length_/2.+0.05),0.,tk_radius_,(tk_length_)*2.*exp(-tk_etamax_)/(1-exp(-2.*tk_etamax_)),tk_radius_);
254 TGeoTranslation *tr1 = new TGeoTranslation("tkacc1",0., 0., tk_length_/2.);
255 tr1->RegisterYourself();
256 TGeoRotation *negz = new TGeoRotation("tknegz",0,180,0);
257 negz->RegisterYourself();
258 TGeoCombiTrans *tr2 = new TGeoCombiTrans("tkacc2",0.,0.,-tk_length_/2.,negz);
259 tr2->RegisterYourself();
260 TGeoCompositeShape* tracker_cs = new TGeoCompositeShape("tracker_cs","forwardTkAcceptance:tkacc1+forwardTkAcceptance:tkacc2");
261 TGeoVolume *tracker = new TGeoVolume("tracker",tracker_cs,tkmed_);
262 tracker->SetLineColor(kYellow);
263 top->AddNode(tracker,1);
264 return std::make_pair(tk_radius_,tk_length_);
265}
266
267std::pair<Double_t, Double_t> Delphes3DGeometry::addCalorimeter(TGeoVolume *top, const char* name,
268 Double_t innerBarrelRadius, Double_t innerBarrelLength, set< pair<Double_t, Int_t> >& caloBinning) {
269 // parameters derived from the inputs
270 Double_t calo_endcap_etamax = TMath::Max(fabs(caloBinning.begin()->first),fabs(caloBinning.rbegin()->first));
271 Double_t calo_barrel_innerRadius = innerBarrelRadius+contingency_;
272 Double_t calo_barrel_length = innerBarrelLength + calo_barrel_thickness_;
273 Double_t calo_endcap_etamin = -log(innerBarrelRadius/(2*innerBarrelLength));
274 Double_t calo_endcap_innerRadius1 = innerBarrelLength*2.*exp(-calo_endcap_etamax)/(1-exp(-2.*calo_endcap_etamax));
275 Double_t calo_endcap_innerRadius2 = (innerBarrelLength+calo_endcap_thickness_)*2.*exp(-calo_endcap_etamax)/(1-exp(-2.*calo_endcap_etamax));
276 Double_t calo_endcap_outerRadius1 = innerBarrelRadius;
277 Double_t calo_endcap_outerRadius2 = innerBarrelRadius+calo_barrel_thickness_;
278 Double_t calo_endcap_coneThickness = TMath::Min(calo_barrel_thickness_ * (1-exp(-2.*calo_endcap_etamin)) / (2.*exp(-calo_endcap_etamin)), calo_endcap_thickness_);
279 Double_t calo_endcap_diskThickness = TMath::Max(0.,calo_endcap_thickness_-calo_endcap_coneThickness);
280
281 // calorimeters: tube truncated in eta + cones
282 new TGeoTube(Form("%s_barrel_cylinder",name),calo_barrel_innerRadius,calo_barrel_innerRadius+calo_barrel_thickness_,calo_barrel_length);
283 new TGeoCone(Form("%s_endcap_cone",name),calo_endcap_coneThickness/2.,calo_endcap_innerRadius1,calo_endcap_outerRadius1,calo_endcap_innerRadius2,calo_endcap_outerRadius2);
284 new TGeoTube(Form("%s_endcap_disk",name),calo_endcap_innerRadius2,tk_radius_+calo_barrel_thickness_,calo_endcap_diskThickness/2.);
285 TGeoTranslation *tr1 = new TGeoTranslation(Form("%s_tr1",name),0., 0., (calo_endcap_coneThickness+calo_endcap_diskThickness)/2.);
286 tr1->RegisterYourself();
287 TGeoCompositeShape *calo_endcap_cs = new TGeoCompositeShape(Form("%s_endcap_cs",name),Form("%s_endcap_cone+%s_endcap_disk:%s_tr1",name,name,name));
288 TGeoTranslation *trc1 = new TGeoTranslation(Form("%s_endcap1_position",name),0.,0., innerBarrelLength+calo_endcap_coneThickness/2.);
289 trc1->RegisterYourself();
290 TGeoRotation *negz = new TGeoRotation(Form("%s_negz",name),0,180,0);
291 TGeoCombiTrans *trc2 = new TGeoCombiTrans(Form("%s_endcap2_position",name),0.,0.,-(innerBarrelLength+calo_endcap_coneThickness/2.),negz);
292 trc2->RegisterYourself();
293 TGeoTranslation *trc1c = new TGeoTranslation(Form("%s_endcap1_position_cont",name),0.,0., innerBarrelLength+calo_endcap_coneThickness/2.+contingency_);
294 trc1c->RegisterYourself();
295 TGeoCombiTrans *trc2c = new TGeoCombiTrans(Form("%s_endcap2_position_cont",name),0.,0.,-(innerBarrelLength+calo_endcap_coneThickness/2.)-contingency_,negz);
296 trc2c->RegisterYourself();
297 TGeoVolume *calo_endcap = new TGeoVolume(Form("%s_endcap",name),calo_endcap_cs,calomed_);
298 TGeoCompositeShape *calo_barrel_cs = new TGeoCompositeShape(Form("%s_barrel_cs",name),
299 Form("%s_barrel_cylinder-%s_endcap_cs:%s_endcap1_position-%s_endcap_cs:%s_endcap2_position",name,name,name,name,name));
300 TGeoVolume *calo_barrel = new TGeoVolume(Form("%s_barrel",name),calo_barrel_cs,calomed_);
301 calo_endcap->SetLineColor(kViolet);
302 calo_endcap->SetFillColor(kViolet);
303 calo_barrel->SetLineColor(kRed);
304 top->AddNode(calo_endcap,1,trc1c);
305 top->AddNode(calo_endcap,2,trc2c);
306 top->AddNode(calo_barrel,1);
307 return std::make_pair(calo_barrel_innerRadius+calo_barrel_thickness_,innerBarrelLength+calo_endcap_thickness_+contingency_);
308}
309
310std::pair<Double_t, Double_t> Delphes3DGeometry::addMuonDets(TGeoVolume *top, const char* name, Double_t innerBarrelRadius, Double_t innerBarrelLength) {
311 // muon system: tube + disks
312 Double_t muonSystem_radius = innerBarrelRadius + contingency_;
313 Double_t muonSystem_length = innerBarrelLength + contingency_;
314 Double_t muonSystem_rmin = muonSystem_length*2.*exp(-muonSystem_etamax_[name])/(1-exp(-2.*muonSystem_etamax_[name]));
315 TGeoVolume *muon_barrel = geom_->MakeTube(Form("%s_barrel",name),mudetmed_,muonSystem_radius,muonSystem_radius+muonSystem_thickn_,muonSystem_length);
316 muon_barrel->SetLineColor(kBlue);
317 top->AddNode(muon_barrel,1);
318 TGeoVolume *muon_endcap = geom_->MakeTube(Form("%s_endcap",name),mudetmed_,muonSystem_rmin,muonSystem_radius+muonSystem_thickn_,muonSystem_thickn_/2.);
319 muon_endcap->SetLineColor(kBlue);
320 TGeoTranslation *trm1 = new TGeoTranslation(Form("%sEndcap1_position",name),0.,0.,muonSystem_length);
321 trm1->RegisterYourself();
322 TGeoTranslation *trm2 = new TGeoTranslation(Form("%sEndcap2_position",name),0.,0.,-muonSystem_length);
323 trm1->RegisterYourself();
324 top->AddNode(muon_endcap,1,trm1);
325 top->AddNode(muon_endcap,2,trm2);
326 return std::make_pair(muonSystem_radius,muonSystem_length);
327}
328
329void Delphes3DGeometry::addCaloTowers(TGeoVolume *top, const char* name,
330 Double_t innerBarrelRadius, Double_t innerBarrelLength, set< pair<Double_t, Int_t> >& caloBinning) {
331
332 TGeoVolume* calo_endcap = top->GetNode(Form("%s_endcap_1",name))->GetVolume();
333 TGeoVolume* calo_barrel = top->GetNode(Form("%s_barrel_1",name))->GetVolume();
334 Double_t calo_endcap_etamin = -log(innerBarrelRadius/(2*innerBarrelLength));
335 Double_t calo_endcap_coneThickness = TMath::Min(calo_barrel_thickness_ * (1-exp(-2.*calo_endcap_etamin)) / (2.*exp(-calo_endcap_etamin)), calo_endcap_thickness_);
336
337 // calo towers in the barrel
338 Double_t vertices[16] = {0.,0.,0.,0.,0.,0.,0.,0.}; // summit of the pyramid
339 Double_t R = tk_radius_ + contingency_+(contingency_+calo_barrel_thickness_)*calorimeters_.size(); // radius of the muons system = height of the pyramid
340 Int_t nEtaBins = caloBinning.size();
341 // this rotation is to make the tower point "up"
342 TGeoRotation* initTowerRot = new TGeoRotation(Form("%s_initTowerRot",name),0.,90.,0.);
343 TGeoCombiTrans* initTower = new TGeoCombiTrans(Form("%s_initTower",name),0.,-R/2.,0.,initTowerRot);
344 initTower->RegisterYourself();
345 // eta bins... we build one pyramid per eta slice and then translate it nphi times.
346 // phi bins represented by rotations around z
347 Double_t *y = new Double_t[nEtaBins];
348 Double_t *dx = new Double_t[nEtaBins];
349 Int_t *nphi = new Int_t[nEtaBins];
350 Int_t etaslice = 0;
351 std::map<std::pair<int,int>, TGeoRotation*> phirotations;
352 for(set< pair<Double_t, Int_t> >::const_iterator bin=caloBinning.begin(); bin!=caloBinning.end();++bin) {
353 if(abs(bin->first)>calo_endcap_etamin) continue; // only in the barrel
354 nphi[etaslice] = bin->second;
355 y[etaslice] = 0.5*R*(1-exp(-2*bin->first))/exp(-bin->first);
356 Double_t phiRotationAngle = 360./nphi[etaslice];
357 dx[etaslice] = R*tan(TMath::Pi()*phiRotationAngle/360.);
358 for(int phislice=0;phislice<nphi[etaslice];++phislice) {
359 phirotations[make_pair(etaslice,phislice)] = new TGeoRotation(Form("%s_phi%d_%d",name,etaslice,phislice),phiRotationAngle*phislice,0.,0.);
360 phirotations[make_pair(etaslice,phislice)]->RegisterYourself();
361 }
362 ++etaslice;
363 }
364 nEtaBins = etaslice;
365 for(int i=0;i<nEtaBins-1;++i) { // loop on the eta slices
366 vertices[8] = -dx[i]; vertices[9] = y[i];
367 vertices[10] = -dx[i]; vertices[11] = y[i+1];
368 vertices[12] = dx[i]; vertices[13] = y[i+1];
369 vertices[14] = dx[i]; vertices[15] = y[i];
370 new TGeoArb8(Form("%s_tower%d",name,i),R/2., vertices); // tower in the proper eta slice, at phi=0
371 // intersection between the tower and the calo_barrel
372 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));
373 TGeoVolume *finaltower = new TGeoVolume(Form("%s_ftower%d",name,i),finaltower_cs,calomed_);
374 finaltower->SetLineColor(kRed);
375 for(int j=0;j<nphi[i];++j) { // loop on the phi slices
376 calo_barrel->AddNode(finaltower,j,phirotations[make_pair(i,j)]);
377 }
378 }
379 delete[] y;
380 delete[] dx;
381 delete[] nphi;
382 //the towers in the forward region
383 R = tk_length_+contingency_+(contingency_+calo_endcap_thickness_)*calorimeters_.size(); // Z of the muons system = height of the pyramid
384 nEtaBins = caloBinning.size();
385 // translation to bring the origin of the tower to (0,0,0) (well, not really as the endcap is not yet in place)
386 TGeoTranslation* towerdz = new TGeoTranslation(Form("%s_towerdz",name),0.,0.,R/2.-(innerBarrelLength+calo_endcap_coneThickness/2.));
387 towerdz->RegisterYourself();
388 // eta bins... we build one pyramid per eta slice and then translate it nphi times.
389 Double_t *r = new Double_t[nEtaBins];
390 nphi = new Int_t[nEtaBins];
391 etaslice = 0;
392 phirotations.clear();
393 for(set< pair<Double_t, Int_t> >::const_iterator bin=caloBinning.begin(); bin!=caloBinning.end();++bin) {
394 if(bin->first<calo_endcap_etamin) continue; // only in the + endcap
395 r[etaslice] = R*2*exp(-bin->first)/(1-exp(-2*bin->first));
396 nphi[etaslice] = bin->second;
397 Double_t phiRotationAngle = 360./nphi[etaslice];
398 for(int phislice=0;phislice<nphi[etaslice];++phislice) {
399 phirotations[make_pair(etaslice,phislice)] = new TGeoRotation(Form("%s_forward_phi%d_%d",name,etaslice,phislice),phiRotationAngle*phislice,0.,0.);
400 phirotations[make_pair(etaslice,phislice)]->RegisterYourself();
401 }
402 ++etaslice;
403 }
404 nEtaBins = etaslice;
405 for(int i=0;i<nEtaBins-1;++i) { // loop on the eta slices
406 vertices[8] = -r[i+1]*sin(TMath::Pi()/nphi[i]); vertices[9] = r[i+1]*cos(TMath::Pi()/nphi[i]);
407 vertices[10] = -r[i]*sin(TMath::Pi()/nphi[i]); vertices[11] = r[i]*cos(TMath::Pi()/nphi[i]);
408 vertices[12] = r[i]*sin(TMath::Pi()/nphi[i]); vertices[13] = r[i]*cos(TMath::Pi()/nphi[i]);
409 vertices[14] = r[i+1]*sin(TMath::Pi()/nphi[i]); vertices[15] = r[i+1]*cos(TMath::Pi()/nphi[i]);
410 new TGeoArb8(Form("%sfwdtower%d",name,i),R/2., vertices); // tower in the proper eta slice, at phi=0
411 // intersection between the tower and the calo_endcap
412 TGeoCompositeShape *finalfwdtower_cs = new TGeoCompositeShape(Form("%sffwdtower%d_cs",name,i),Form("%sfwdtower%d:%s_towerdz*%s_endcap_cs",name,i,name,name));
413 TGeoVolume *finalfwdtower = new TGeoVolume(Form("%sffwdtower%d",name,i),finalfwdtower_cs,calomed_);
414 finalfwdtower->SetLineColor(kViolet);
415 for(int j=0;j<nphi[i];++j) { // loop on the phi slices
416 calo_endcap->AddNode(finalfwdtower,j,phirotations[make_pair(i,j)]);
417 }
418 }
419 delete[] r;
420 delete[] nphi;
421}
422
423/******************************************************************************/
424// Initialization and steering functions
425/******************************************************************************/
426
427void delphes_event_display(const char *configFile, const char *inputFile)
428{
429 // to be the main function, initializes the application.
430
431 gSystem->Load("libDelphesDisplay");
432
433 TEveManager::Create(kTRUE, "IV");
434
435//------------------------------------ TODO: this should be moved to the geometry class
436 ExRootConfParam param, paramEtaBins;
437 Long_t i, j, size, sizeEtaBins;
438 set< Double_t > etaSet;
439 set< Double_t >::iterator itEtaSet;
440
441 Double_t *etaBins;
442
443 ExRootConfReader *confReader = new ExRootConfReader;
444 confReader->ReadFile(configFile);
445
446 gRadius = confReader->GetDouble("ParticlePropagator::Radius", 1.0);
447 gHalfLength = confReader->GetDouble("ParticlePropagator::HalfLength", 3.0);
448 gBz = confReader->GetDouble("ParticlePropagator::Bz", 0.0);
449
450
451 // read eta and phi bins
452 param = confReader->GetParam("Calorimeter::EtaPhiBins");
453 size = param.GetSize();
454 etaSet.clear();
455 for(i = 0; i < size/2; ++i)
456 {
457 paramEtaBins = param[i*2];
458 sizeEtaBins = paramEtaBins.GetSize();
459
460 for(j = 0; j < sizeEtaBins; ++j)
461 {
462 etaSet.insert(paramEtaBins[j].GetDouble());
463 }
464 }
465
466 delete confReader;
467
468 etaBins = new Double_t[etaSet.size()];
469 i = 0;
470
471 for(itEtaSet = etaSet.begin(); itEtaSet != etaSet.end(); ++itEtaSet)
472 {
473 etaBins[i] = *itEtaSet;
474 ++i;
475 }
476
477 gEtaAxis = new TAxis(etaSet.size() - 1, etaBins);
478 gPhiAxis = 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
479//-----------------------------------------------------------------------
480
481 // Create chain of root trees
482 gChain.Add(inputFile);
483
484 // Create object of class ExRootTreeReader
485 printf("*** Opening Delphes data file ***\n");
486 gTreeReader = new ExRootTreeReader(&gChain);
487
488 // Get pointers to branches
489 //TODO make it configurable, for more objects (or can we guess from the config?)
490 gBranchTower = gTreeReader->UseBranch("Tower");
491 gBranchTrack = gTreeReader->UseBranch("Track");
492 gBranchJet = gTreeReader->UseBranch("Jet");
493
494// idea: for pf objects, we could use the TEveCompound to show track + cluster ??? (nice display but little meaning)
495// for MET and SHT, show an arrow (tooltip = title)
496// for electrons and muons, create additional track collections
497// for photons, use TEveStraightLineSet
498
499/*
500 add Branch Calorimeter/eflowTracks EFlowTrack Track
501 add Branch Calorimeter/eflowPhotons EFlowPhoton Tower
502 add Branch Calorimeter/eflowNeutralHadrons EFlowNeutralHadron Tower
503
504 add Branch GenJetFinder/jets GenJet Jet
505
506 add Branch UniqueObjectFinder/jets Jet Jet
507
508 add Branch UniqueObjectFinder/electrons Electron Electron
509 add Branch UniqueObjectFinder/photons Photon Photon
510 add Branch UniqueObjectFinder/muons Muon Muon
511
512 add Branch MissingET/momentum MissingET MissingET
513 add Branch ScalarHT/energy ScalarHT ScalarHT
514*/
515
516 // data
517 gCaloData = new DelphesCaloData(2);
518 gCaloData->RefSliceInfo(0).Setup("ECAL", 0.1, kRed);
519 gCaloData->RefSliceInfo(1).Setup("HCAL", 0.1, kBlue);
520 gCaloData->SetEtaBins(gEtaAxis);
521 gCaloData->SetPhiBins(gPhiAxis);
522 gCaloData->IncDenyDestroy();
523
524 gJetList = new TEveElementList("Jets");
525 gEve->AddElement(gJetList);
526
527 gTrackList = new TEveTrackList("Tracks");
528 gTrackList->SetMainColor(kBlue);
529 gTrackList->SetMarkerColor(kRed);
530 gTrackList->SetMarkerStyle(kCircle);
531 gTrackList->SetMarkerSize(0.5);
532 gEve->AddElement(gTrackList);
533
534 TEveTrackPropagator *trkProp = gTrackList->GetPropagator();
535 trkProp->SetMagField(0.0, 0.0, -gBz);
536 trkProp->SetMaxR(gRadius*100.0);
537 trkProp->SetMaxZ(gHalfLength*100.0);
538
539 // viewers and scenes
540
541 TEveCalo3D *calo = new TEveCalo3D(gCaloData);
542 calo->SetBarrelRadius(gRadius*100.0); //TODO get it from geometry class
543 calo->SetEndCapPos(gHalfLength*100.0); //TODO get it from geometry class
544
545 gStyle->SetPalette(1, 0);
546 TEveCaloLego *lego = new TEveCaloLego(gCaloData);
547 lego->InitMainTrans();
548 lego->RefMainTrans().SetScale(TMath::TwoPi(), TMath::TwoPi(), TMath::Pi());
549 lego->SetAutoRebin(kFALSE);
550 lego->Set2DMode(TEveCaloLego::kValSizeOutline);
551
552 gDelphesDisplay = new DelphesDisplay;
553 gEve->AddGlobalElement(geometry);
554 gEve->AddGlobalElement(calo);
555 gDelphesDisplay->ImportGeomRPhi(geometry);
556 gDelphesDisplay->ImportCaloRPhi(calo);
557 gDelphesDisplay->ImportGeomRhoZ(geometry);
558 gDelphesDisplay->ImportCaloRhoZ(calo);
559 gDelphesDisplay->ImportCaloLego(lego);
560 gEve->Redraw3D(kTRUE);
561
562}
563
564//______________________________________________________________________________
565void load_event()
566{
567 // Load event specified in global event_id.
568 // The contents of previous event are removed.
569
570 printf("Loading event %d.\n", event_id);
571
572 gEve->GetViewers()->DeleteAnnotations();
573
574 if(gCaloData) gCaloData->ClearTowers();
575 if(gJetList) gJetList->DestroyElements();
576 if(gTrackList) gTrackList->DestroyElements();
577
578 delphes_read();
579
580 TEveElement* top = gEve->GetCurrentEvent();
581 gDelphesDisplay->DestroyEventRPhi();
582 gDelphesDisplay->ImportEventRPhi(top);
583 gDelphesDisplay->DestroyEventRhoZ();
584 gDelphesDisplay->ImportEventRhoZ(top);
585
586 //update_html_summary();
587
588 gEve->Redraw3D(kFALSE, kTRUE);
589}
590
591void delphes_read()
592{
593
594 TIter itTower(gBranchTower);
595 TIter itTrack(gBranchTrack);
596 TIter itJet(gBranchJet);
597
598 Tower *tower;
599 Track *track;
600 Jet *jet;
601
602 TEveJetCone *eveJetCone;
603 TEveTrack *eveTrack;
604
605 Int_t counter;
606
607 TEveTrackPropagator *trkProp = gTrackList->GetPropagator();
608 if(event >= gTreeReader->GetEntries()) return;
609
610 // Load selected branches with data from specified event
611 gTreeReader->ReadEntry(event_id);
612 // Loop over all towers
613 itTower.Reset();
614 while((tower = (Tower *) itTower.Next()))
615 {
616 gCaloData->AddTower(tower->Edges[0], tower->Edges[1], tower->Edges[2], tower->Edges[3]);
617 gCaloData->FillSlice(0, tower->Eem);
618 gCaloData->FillSlice(1, tower->Ehad);
619 }
620 gCaloData->DataChanged();
621 // Loop over all tracks
622 itTrack.Reset();
623 counter = 0;
624 while((track = (Track *) itTrack.Next()))
625 {
626 TParticle pb(track->PID, 1, 0, 0, 0, 0,
627 track->P4().Px(), track->P4().Py(),
628 track->P4().Pz(), track->P4().E(),
629 track->X, track->Y, track->Z, 0.0);
630
631 eveTrack = new TEveTrack(&pb, counter, trkProp);
632 eveTrack->SetName(Form("%s [%d]", pb.GetName(), counter++));
633 eveTrack->SetStdTitle();
634 eveTrack->SetAttLineAttMarker(gTrackList);
635
636 switch(TMath::Abs(track->PID))
637 {
638 case 11:
639 eveTrack->SetLineColor(kRed);
640 break;
641 case 13:
642 eveTrack->SetLineColor(kGreen);
643 break;
644 default:
645 eveTrack->SetLineColor(kBlue);
646 }
647 gTrackList->AddElement(eveTrack);
648 eveTrack->MakeTrack();
649 }
650 // Loop over all jets
651 itJet.Reset();
652 counter = 0;
653 while((jet = (Jet *) itJet.Next()))
654 {
655 eveJetCone = new TEveJetCone();
656 eveJetCone->SetName(Form("jet [%d]", counter++));
657 eveJetCone->SetMainTransparency(60);
658 eveJetCone->SetLineColor(kYellow);
659 eveJetCone->SetCylinder(gRadius*100.0 - 10, gHalfLength*100.0 - 10);
660 eveJetCone->SetPickable(kTRUE);
661 eveJetCone->AddEllipticCone(jet->Eta, jet->Phi, jet->DeltaEta, jet->DeltaPhi);
662 gJetList->AddElement(eveJetCone);
663 }
664}
665
666
667/******************************************************************************/
668// GUI
669/******************************************************************************/
670
671//______________________________________________________________________________
672//
673// EvNavHandler class is needed to connect GUI signals.
674
675class EvNavHandler
676{
677public:
678 void Fwd()
679 {
680 if (event_id < tree->GetEntries() - 1) {
681 ++event_id;
682 load_event();
683 } else {
684 printf("Already at last event.\n");
685 }
686 }
687 void Bck()
688 {
689 if (event_id > 0) {
690 --event_id;
691 load_event();
692 } else {
693 printf("Already at first event.\n");
694 }
695 }
696};
697
698//______________________________________________________________________________
699void make_gui()
700{
701 // Create minimal GUI for event navigation.
702 // TODO: better GUI could be made based on the ch15 of the manual (Writing a GUI)
703
704 // add a tab on the left
705 TEveBrowser* browser = gEve->GetBrowser();
706 browser->StartEmbedding(TRootBrowser::kLeft);
707
708 // set the main title
709 TGMainFrame* frmMain = new TGMainFrame(gClient->GetRoot(), 1000, 600);
710 frmMain->SetWindowName("Delphes Event Display");
711 frmMain->SetCleanup(kDeepCleanup);
712
713 // build the navigation menu
714 TGHorizontalFrame* hf = new TGHorizontalFrame(frmMain);
715 {
716 TString icondir;
717 if(gSystem->Getenv("ROOTSYS"))
718 icondir = Form("%s/icons/", gSystem->Getenv("ROOTSYS"));
719 if(!gSystem->OpenDirectory(icondir))
720 icondir = Form("%s/icons/", (const char*)gSystem->GetFromPipe("root-config --etcdir") );
721 TGPictureButton* b = 0;
722 EvNavHandler *fh = new EvNavHandler;
723
724 b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoBack.gif"));
725 hf->AddFrame(b);
726 b->Connect("Clicked()", "EvNavHandler", fh, "Bck()");
727
728 b = new TGPictureButton(hf, gClient->GetPicture(icondir+"GoForward.gif"));
729 hf->AddFrame(b);
730 b->Connect("Clicked()", "EvNavHandler", fh, "Fwd()");
731 }
732 frmMain->AddFrame(hf);
733 frmMain->MapSubwindows();
734 frmMain->Resize();
735 frmMain->MapWindow();
736 browser->StopEmbedding();
737 browser->SetTabTitle("Event Control", 0);
738}
739
740/******************************************************************************/
741// MAIN
742/******************************************************************************/
743
744void geometry(const char* filename = "delphes_card_CMS.tcl", const char* ParticlePropagator="ParticlePropagator",
745 const char* TrackingEfficiency="ChargedHadronTrackingEfficiency",
746 const char* MuonEfficiency="MuonEfficiency",
747 const char* Calorimeters="Calorimeter")
748{
749 gSystem->Load("libGeom");
750 gSystem->Load("../libDelphes");
751 TGeoManager *geom = new TGeoManager("delphes", "Delphes geometry");
752
753 // make the top container volume -> designed to contain a "big" detector (ATLAS)
754 TGeoVolume *top = geom->MakeBox("TOP", 0, 1500, 1500, 2300);
755 geom->SetTopVolume(top);
756
757 // build the detector
758 Delphes3DGeometry det3D;
759 det3D.readFile(filename,ParticlePropagator, TrackingEfficiency, MuonEfficiency, Calorimeters);
760 top->AddNode(det3D.getDetector(true),1);
761
762 // draw it
763 geom->CloseGeometry();
764 //top->Draw();
765 //TFile* file = new TFile("DelpheGeom.root","RECREATE");
766 //top->Write("DelphesGeometry");
767 //file->Close();
768
769 TEveManager::Create(kTRUE, "IV");
770
771
772 //TFile::SetCacheFileDir(".");
773 //gGeoManager = gEve->GetGeometry("DelpheGeom.root");
774 gGeoManager->DefaultColors();
775
776 TGeoVolume* top = gGeoManager->GetTopVolume()->FindNode("Delphes3DGeometry_1")->GetVolume();
777
778 TEveGeoTopNode* trk = new TEveGeoTopNode(gGeoManager, top->FindNode("tracker_1"));
779 trk->SetVisLevel(6);
780 gEve->AddGlobalElement(trk);
781
782 TEveGeoTopNode* calo = new TEveGeoTopNode(gGeoManager, top->FindNode("Calorimeter_barrel_1"));
783 calo->SetVisLevel(3);
784 gEve->AddGlobalElement(calo);
785 calo = new TEveGeoTopNode(gGeoManager, top->FindNode("Calorimeter_endcap_1"));
786 calo->SetVisLevel(3);
787 calo->UseNodeTrans();
788 gEve->AddGlobalElement(calo);
789 calo = new TEveGeoTopNode(gGeoManager, top->FindNode("Calorimeter_endcap_2"));
790 calo->SetVisLevel(3);
791 calo->UseNodeTrans();
792 gEve->AddGlobalElement(calo);
793
794 TEveGeoTopNode* muon = new TEveGeoTopNode(gGeoManager, top->FindNode("muons_barrel_1"));
795 muon->SetVisLevel(4);
796 gEve->AddGlobalElement(muon);
797 muon = new TEveGeoTopNode(gGeoManager, top->FindNode("muons_endcap_1"));
798 muon->SetVisLevel(4);
799 muon->UseNodeTrans();
800 gEve->AddGlobalElement(muon);
801 muon = new TEveGeoTopNode(gGeoManager, top->FindNode("muons_endcap_2"));
802 muon->SetVisLevel(4);
803 muon->UseNodeTrans();
804 gEve->AddGlobalElement(muon);
805
806 gEve->FullRedraw3D(kTRUE);
807
808 // EClipType not exported to CINT (see TGLUtil.h):
809 // 0 - no clip, 1 - clip plane, 2 - clip box
810 TGLViewer *v = gEve->GetDefaultGLViewer();
811 v->GetClipSet()->SetClipType(1);
812 v->ColorSet().Background().SetColor(kMagenta+4);
813 v->SetGuideState(TGLUtil::kAxesEdge, kTRUE, kFALSE, 0);
814 v->RefreshPadEditor(v);
815
816 v->CurrentCamera().RotateRad(-1.2, 0.5);
817 v->DoDraw();
818
819 make_gui();
820 // load_event();
821 // gEve->Redraw3D(kTRUE); // Reset camera after the first event has been shown.
822}
823
Note: See TracBrowser for help on using the repository browser.