1 | // ESAF : Euso Simulation and Analysis Framework |
---|
2 | // $Id: EShowerPainter.cc 2795 2008-02-11 12:50:20Z naumov $ |
---|
3 | // Naumov Dmitry created Jun, 28 2004 |
---|
4 | |
---|
5 | #include "EShowerPainter.hh" |
---|
6 | #include "ESystemOfUnits.hh" |
---|
7 | #include "EShower.hh" |
---|
8 | #include "EShowerStep.hh" |
---|
9 | #include "Etypes.hh" |
---|
10 | |
---|
11 | #include "Riostream.h" |
---|
12 | |
---|
13 | #include <TGeoBBox.h> |
---|
14 | #include <TGeoVolume.h> |
---|
15 | #include <TGeoMatrix.h> |
---|
16 | #include <TVector3.h> |
---|
17 | #include <TGeoManager.h> |
---|
18 | #include <TGeoTube.h> |
---|
19 | #include <TPad.h> |
---|
20 | #include <TTimer.h> |
---|
21 | #include <TSeqCollection.h> |
---|
22 | #include <TH2F.h> |
---|
23 | #include <TH3F.h> |
---|
24 | #include <TMath.h> |
---|
25 | #include <TList.h> |
---|
26 | |
---|
27 | using namespace TMath; |
---|
28 | using namespace sou; |
---|
29 | |
---|
30 | ClassImp(EShowerPainter) |
---|
31 | |
---|
32 | //_____________________________________________________________________________ |
---|
33 | EShowerPainter::EShowerPainter( EShower *sh ) { |
---|
34 | // |
---|
35 | // Constructor |
---|
36 | // |
---|
37 | |
---|
38 | fShower = sh; |
---|
39 | |
---|
40 | fNumFrames = 100; |
---|
41 | fFrame = -1; |
---|
42 | fWorldBuild = kFALSE; |
---|
43 | fBoxDefined = kFALSE; |
---|
44 | fHistoContainer = new TList(); |
---|
45 | fThreshold = 1.e-3; |
---|
46 | |
---|
47 | if ( !fShower || fShower->GetNumSteps() <= 0 ) { |
---|
48 | Info("Build()","Empty Shower ( NumSteps = 0 ). Painter made zombie."); |
---|
49 | MakeZombie(); |
---|
50 | return; |
---|
51 | } |
---|
52 | |
---|
53 | } |
---|
54 | |
---|
55 | //_____________________________________________________________________________ |
---|
56 | EShowerPainter::~EShowerPainter() { |
---|
57 | // |
---|
58 | // Destructor |
---|
59 | // |
---|
60 | fHistoContainer->Delete(); |
---|
61 | |
---|
62 | } |
---|
63 | //______________________________________________________________________________ |
---|
64 | void EShowerPainter::DefineBox() { |
---|
65 | |
---|
66 | if (IsBoxDefined()) return; |
---|
67 | Int_t n = fShower->GetNumSteps(); |
---|
68 | Double_t Xmin(kHuge), Xmax(-kHuge), Ymin(kHuge), Ymax(-kHuge), Zmin(kHuge), Zmax(-kHuge), Nmax(1); |
---|
69 | |
---|
70 | for (Int_t i=0; i<n; i++) { |
---|
71 | if (Nmax < fShower->GetStep(i)->GetNumElectrons() ) |
---|
72 | Nmax = fShower->GetStep(i)->GetNumElectrons(); |
---|
73 | } |
---|
74 | |
---|
75 | for (Int_t i=0; i<n; i++) { |
---|
76 | Double_t xmean = (fShower->GetStep(i)->GetPosi().X() + fShower->GetStep(i)->GetPosf().X())/2/km; |
---|
77 | Double_t ymean = (fShower->GetStep(i)->GetPosi().Y() + fShower->GetStep(i)->GetPosf().Y())/2/km; |
---|
78 | Double_t zmean = (fShower->GetStep(i)->GetPosi().Z() + fShower->GetStep(i)->GetPosf().Z())/2/km; |
---|
79 | Double_t ne = fShower->GetStep(i)->GetNumElectrons(); |
---|
80 | if (ne/Nmax > fThreshold) { |
---|
81 | Xmin = (Xmin < xmean ? Xmin : xmean); |
---|
82 | Xmax = (Xmax > xmean ? Xmax : xmean); |
---|
83 | Ymin = (Ymin < ymean ? Ymin : ymean); |
---|
84 | Ymax = (Ymax > ymean ? Ymax : ymean); |
---|
85 | Zmin = (Zmin < zmean ? Zmin : zmean); |
---|
86 | Zmax = (Zmax > zmean ? Zmax : zmean); |
---|
87 | } |
---|
88 | } |
---|
89 | |
---|
90 | fXmin = Xmin; |
---|
91 | fXmax = Xmax; |
---|
92 | fYmin = Ymin; |
---|
93 | fYmax = Ymax; |
---|
94 | fZmin = Zmin; |
---|
95 | fZmax = Zmax; |
---|
96 | fNmax = Nmax; |
---|
97 | fBoxDefined = kTRUE; |
---|
98 | } |
---|
99 | //______________________________________________________________________________ |
---|
100 | void EShowerPainter::Build() { |
---|
101 | // |
---|
102 | // Find the size of the box that contains the shower |
---|
103 | // |
---|
104 | |
---|
105 | if ( IsZombie() ) return; |
---|
106 | |
---|
107 | DefineBox(); |
---|
108 | Int_t n = fShower->GetNumSteps(); |
---|
109 | |
---|
110 | |
---|
111 | fDx = 1.; |
---|
112 | fDy = 1.; |
---|
113 | fDz = (fShower->GetStep(0)->GetPosi() - fShower->GetStep(n-1)->GetPosf()).Mag()/2/km; |
---|
114 | |
---|
115 | TVector3 initPos = (fShower->GetStep(0)->GetPosi() + fShower->GetStep(0)->GetPosf())*0.5; |
---|
116 | TVector3 lastPos = (fShower->GetStep(n-1)->GetPosi() + fShower->GetStep(n-1)->GetPosf())*0.5; |
---|
117 | fCenter = (initPos + lastPos)*0.5*(1/km); |
---|
118 | // build the shower track |
---|
119 | Double_t kScale = 1./fNmax; |
---|
120 | fShowerVolume = gGeoManager->MakeBox("fShowerVolume",fVacuum,fDx,fDy,fDz); |
---|
121 | Double_t dz_shift = 0; |
---|
122 | |
---|
123 | for (Int_t i=0; i<n; i++) { |
---|
124 | TVector3 stepCenter = (fShower->GetStep(i)->GetPosi() + fShower->GetStep(i)->GetPosf())*0.5; |
---|
125 | double dz = (fShower->GetStep(i)->GetPosi() - fShower->GetStep(i)->GetPosf()).Mag()/2/km; |
---|
126 | double rmax = fShower->GetStep(i)->GetNumElectrons()*kScale; |
---|
127 | |
---|
128 | if (fShower->GetStep(i)->GetNumElectrons()/fNmax > fThreshold) { |
---|
129 | rmax = rmax < 0.001 ? 0.001 : rmax; |
---|
130 | TString name = Form("tube_%d",i); |
---|
131 | dz_shift = (stepCenter-initPos).Mag()/km-fDz; |
---|
132 | TGeoVolume *s = gGeoManager->MakeTube(name, fVacuum, 0.9*rmax, rmax, dz); |
---|
133 | s->SetLineColor(50+(Int_t)(50.*log(fShower->GetStep(i)->GetNumElectrons()/fNmax))); |
---|
134 | fShowerVolume->AddNode(s,1, new TGeoTranslation(0,0,-dz_shift)); |
---|
135 | } |
---|
136 | } |
---|
137 | |
---|
138 | } |
---|
139 | |
---|
140 | //______________________________________________________________________________ |
---|
141 | void EShowerPainter::BuildWorld() { |
---|
142 | // |
---|
143 | // Build World based on the shower geometry |
---|
144 | // |
---|
145 | |
---|
146 | if ( IsZombie() ) return; |
---|
147 | |
---|
148 | if( IsWorldBuilt() ) return; |
---|
149 | |
---|
150 | new TGeoManager("ShowerViewer","Shower Viewer"); |
---|
151 | TGeoMaterial *matVacuum = new TGeoMaterial("Al", 26.98,13,2.7); |
---|
152 | fVacuum = new TGeoMedium("Al", 1, matVacuum); |
---|
153 | fTOP = gGeoManager->MakeBox("fTOP",fVacuum,230,230,20); |
---|
154 | gGeoManager->SetTopVolume(fTOP); |
---|
155 | Build(); |
---|
156 | Double_t OffSet = 1.1; |
---|
157 | Double_t x1(-5),x2(5),y1(-5),y2(5); // make 10x10x30 kms box for default |
---|
158 | if (fXmin < x1) x1 = fXmin*OffSet; |
---|
159 | if (fXmax > x2) x2 = fXmax*OffSet; |
---|
160 | if (fYmin < y1) y1 = fYmin*OffSet; |
---|
161 | if (fYmax > y2) y2 = fYmax*OffSet; |
---|
162 | fFoVVolume = gGeoManager->MakeBox("fFoVVolume",fVacuum,(x2-x1)/2,(y2-y1)/2,15); |
---|
163 | Double_t fTheta = fShower->GetTheta()*RadToDeg(); |
---|
164 | Double_t fPhi = fShower->GetPhi()*RadToDeg(); |
---|
165 | TGeoTranslation tr; |
---|
166 | TGeoRotation rot; |
---|
167 | tr.SetTranslation(fCenter.X(),fCenter.Y(),fCenter.Z()); |
---|
168 | rot.SetAngles(fTheta,Min(fPhi,360-fPhi),0); |
---|
169 | TGeoHMatrix h = tr*rot; |
---|
170 | fShowerVolume->SetLineColor(kGreen); |
---|
171 | fFoVVolume->SetLineColor(kBlue); |
---|
172 | fTOP->AddNode(fShowerVolume,1,new TGeoHMatrix(h)); |
---|
173 | fTOP->AddNode(fFoVVolume,1, new TGeoTranslation((x1+x2)/2,(y1+y2)/2,15)); |
---|
174 | gGeoManager->CloseGeometry(); |
---|
175 | } |
---|
176 | |
---|
177 | //______________________________________________________________________________ |
---|
178 | void EShowerPainter::UpdateVisibility( Option_t *opt ) { |
---|
179 | // |
---|
180 | // Fast update ov fisibility status of the objects |
---|
181 | // |
---|
182 | |
---|
183 | if ( !gGeoManager ) return; |
---|
184 | |
---|
185 | TGeoVolume *top; |
---|
186 | if ( !(top = gGeoManager->GetTopVolume()) ) return; |
---|
187 | TGeoVolume *shower = top->FindNode("fShowerVolume_1")->GetVolume(); |
---|
188 | if ( !shower ) return; |
---|
189 | |
---|
190 | Int_t n; |
---|
191 | if ( fFrame == -1) |
---|
192 | n = shower->GetNdaughters(); |
---|
193 | else |
---|
194 | n = (Int_t)(((Float_t)shower->GetNdaughters()/fNumFrames)*fFrame); |
---|
195 | shower->SetVisibility(kFALSE); |
---|
196 | shower->VisibleDaughters(kFALSE); |
---|
197 | for (Int_t i=0; i<shower->GetNdaughters(); i++) { |
---|
198 | Bool_t vis = ( i <= n ); |
---|
199 | if ( shower->GetNode(i)->GetVolume()->IsVisible() != vis ) { |
---|
200 | shower->GetNode(i)->GetVolume()->SetVisibility(vis); |
---|
201 | } |
---|
202 | } |
---|
203 | shower->SetVisibility(kTRUE); |
---|
204 | shower->VisibleDaughters(kTRUE); |
---|
205 | return; |
---|
206 | } |
---|
207 | |
---|
208 | //______________________________________________________________________________ |
---|
209 | void EShowerPainter::Draw( Option_t* ) { |
---|
210 | // |
---|
211 | // Draw the shower in its world volume |
---|
212 | // |
---|
213 | BuildWorld(); |
---|
214 | UpdateVisibility(); |
---|
215 | |
---|
216 | if ( !IsZombie() ) { |
---|
217 | fTOP->Draw(); |
---|
218 | } |
---|
219 | } |
---|
220 | |
---|
221 | //______________________________________________________________________________ |
---|
222 | void EShowerPainter::DrawXY() { |
---|
223 | // Draw the shower projection on XY Earth surface |
---|
224 | |
---|
225 | // build histograms |
---|
226 | TH2F *th0 = GetShowerHisto2D("ShowerXY", "XY projection"); |
---|
227 | for (Int_t i=0; i<fShower->GetNumSteps(); i++) { |
---|
228 | double xmean = (fShower->GetStep(i)->GetPosi().X() + fShower->GetStep(i)->GetPosf().X())/2/km; |
---|
229 | double ymean = (fShower->GetStep(i)->GetPosi().Y() + fShower->GetStep(i)->GetPosf().Y())/2/km; |
---|
230 | double Ne = fShower->GetStep(i)->GetNumElectrons(); |
---|
231 | th0->Fill(xmean,ymean,Ne); |
---|
232 | } |
---|
233 | th0->Draw("colz"); |
---|
234 | } |
---|
235 | |
---|
236 | //______________________________________________________________________________ |
---|
237 | void EShowerPainter::DrawXYZ() { |
---|
238 | // Draw the shower track in XYZ |
---|
239 | |
---|
240 | // build histograms |
---|
241 | TH3F *th0 = GetShowerHisto3D("ShowerXYZ", "XYZ development"); |
---|
242 | for (Int_t i=0; i<fShower->GetNumSteps(); i++) { |
---|
243 | double xmean = (fShower->GetStep(i)->GetPosi().X() + fShower->GetStep(i)->GetPosf().X())/2/km; |
---|
244 | double ymean = (fShower->GetStep(i)->GetPosi().Y() + fShower->GetStep(i)->GetPosf().Y())/2/km; |
---|
245 | double zmean = (fShower->GetStep(i)->GetPosi().Z() + fShower->GetStep(i)->GetPosf().Z())/2/km; |
---|
246 | double Ne = fShower->GetStep(i)->GetNumElectrons(); |
---|
247 | th0->Fill(xmean,ymean,zmean,Ne/fNmax); |
---|
248 | } |
---|
249 | th0->Draw("box"); |
---|
250 | } |
---|
251 | |
---|
252 | //_____________________________________________________________________________ |
---|
253 | void EShowerPainter::Animate() { |
---|
254 | // |
---|
255 | // Move to next animation step and increase the counter |
---|
256 | // |
---|
257 | |
---|
258 | if ( IsEnded() ) { |
---|
259 | // leave the last frame to be painted |
---|
260 | fFrame = fNumFrames-1; |
---|
261 | Stop(); |
---|
262 | return; |
---|
263 | } |
---|
264 | |
---|
265 | NextFrame(); |
---|
266 | } |
---|
267 | |
---|
268 | //_____________________________________________________________________________ |
---|
269 | void EShowerPainter::NextFrame() { |
---|
270 | // |
---|
271 | // Move to the next animation frame |
---|
272 | // |
---|
273 | |
---|
274 | if ( !gGeoManager ) return; |
---|
275 | |
---|
276 | TGeoVolume *top = gGeoManager->GetTopVolume(); |
---|
277 | TGeoVolume *shower = top->FindNode("fShowerVolume_1")->GetVolume(); |
---|
278 | |
---|
279 | Int_t n = (Int_t)(((Float_t)shower->GetNdaughters()/fNumFrames)*fFrame); |
---|
280 | |
---|
281 | for (Int_t i=0; i<shower->GetNdaughters(); i++) { |
---|
282 | Bool_t vis = ( i <= n ); |
---|
283 | if ( shower->GetNode(i)->GetVolume()->IsVisible() != vis ) { |
---|
284 | shower->GetNode(i)->GetVolume()->SetVisibility(vis); |
---|
285 | } |
---|
286 | } |
---|
287 | fFrame++; |
---|
288 | } |
---|
289 | |
---|
290 | //_____________________________________________________________________________ |
---|
291 | TH2F *EShowerPainter::GetShowerHisto2D(const char *name, const char *title) { |
---|
292 | // Draw XY shower track projection. X and Y of the histogram have always center |
---|
293 | // at zero for a better display |
---|
294 | // |
---|
295 | DefineBox(); |
---|
296 | |
---|
297 | if ( title == 0 ) title = name; |
---|
298 | |
---|
299 | |
---|
300 | TH2F* th = (TH2F*)fHistoContainer->FindObject(name); |
---|
301 | |
---|
302 | if (!th) { |
---|
303 | Double_t OffSet = 1.1; |
---|
304 | Double_t x1(-5),x2(5),y1(-5),y2(5); // make 5 kms box for default |
---|
305 | if (fXmin < x1) x1 = fXmin*OffSet; |
---|
306 | if (fXmax > x2) x2 = fXmax*OffSet; |
---|
307 | if (fYmin < y1) y1 = fYmin*OffSet; |
---|
308 | if (fYmax > y2) y2 = fYmax*OffSet; |
---|
309 | // define number of steps |
---|
310 | Int_t nx = (Int_t)(x2-x1); |
---|
311 | Int_t ny = (Int_t)(y2-y1); |
---|
312 | |
---|
313 | th = new TH2F( name, title,nx,x1,x2,ny,y1,y2); |
---|
314 | fHistoContainer->Add(th); |
---|
315 | th->SetStats(0); |
---|
316 | th->SetXTitle("X [km]"); |
---|
317 | th->SetYTitle("Y [km]"); |
---|
318 | } |
---|
319 | |
---|
320 | return th; |
---|
321 | } |
---|
322 | //_____________________________________________________________________________ |
---|
323 | TH3F *EShowerPainter::GetShowerHisto3D(const char *name, const char *title) { |
---|
324 | // |
---|
325 | // |
---|
326 | // |
---|
327 | DefineBox(); |
---|
328 | |
---|
329 | if ( title == 0 ) title = name; |
---|
330 | |
---|
331 | TH3F* th = (TH3F*)fHistoContainer->FindObject(name); |
---|
332 | |
---|
333 | if (!th) { |
---|
334 | Double_t OffSet = 1.1; |
---|
335 | Double_t x1(-5),x2(5),y1(-5),y2(5),z1(0),z2(30); // make 10x10x30 kms box for default |
---|
336 | if (fXmin < x1) x1 = fXmin*OffSet; |
---|
337 | if (fXmax > x2) x2 = fXmax*OffSet; |
---|
338 | if (fYmin < y1) y1 = fYmin*OffSet; |
---|
339 | if (fYmax > y2) y2 = fYmax*OffSet; |
---|
340 | th = new TH3F( name, title, 30,x1,x2,30,y1,y2,30,z1,z2); |
---|
341 | fHistoContainer->Add(th); |
---|
342 | th->SetStats(0); |
---|
343 | th->SetXTitle("X [km]"); |
---|
344 | th->SetYTitle("Y [km]"); |
---|
345 | th->SetZTitle("Z [km]"); |
---|
346 | } |
---|
347 | |
---|
348 | return th; |
---|
349 | } |
---|