CbmRoot
Loading...
Searching...
No Matches
CbmFastSim.cxx
Go to the documentation of this file.
1/* Copyright (C) 2016 Justus-Liebig-Universitaet Giessen, Giessen
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Julian Book [committer] */
4
6//
7// FastSim
8//
11
12//C++ class headers
13#include <fstream>
14#include <string>
15
16//Fair class headers
17#include "FairRootManager.h"
18#include <Logger.h>
19//#include "FairRunAna.h"
20#include "FairRun.h"
21#include "FairRuntimeDb.h"
22
23//CBM class headers
24#include "CbmMCTrack.h"
25#include "CbmStack.h"
26
27#include "PairAnalysisHelper.h"
28
29//ROOT class headers
30#include "CbmFastSim.h"
31
32#include <TClonesArray.h>
33#include <TDatabasePDG.h>
34#include <TF1.h>
35#include <TH1.h>
36#include <TH2.h>
37#include <TH3.h>
38#include <THnBase.h>
39#include <THnSparse.h>
40#include <TMath.h>
41#include <TMatrixD.h>
42#include <TPDGCode.h>
43#include <TParticle.h>
44#include <TParticlePDG.h>
45#include <TProfile3D.h>
46#include <TRandom3.h>
47#include <TVector3.h>
48#include <TVectorD.h>
49#include <TVirtualMC.h>
50
51
52using std::cout;
53using std::endl;
54using std::ifstream;
55using std::string;
56
57
58// ----- Default constructor -------------------------------------------
60 : FairTask("Cbm Fast Simulation")
61 , fRand(new TRandom3(0))
62 , fdbPdg(TDatabasePDG::Instance())
63{
67 for (Int_t idx = 0; idx < fgkNParts; idx++) {
68 fEFF[idx] = NULL;
69 fEFFdenom[idx] = NULL;
70 for (Int_t j = 0; j < 10; j++)
71 fEFFproj[idx][j] = NULL;
72
73 fRFp[idx] = NULL;
74 }
75}
76// -------------------------------------------------------------------------
77
78// ----- Destructor ----------------------------------------------------
80{
84 FairRootManager* fManager = FairRootManager::Instance();
85 fManager->Write();
86
87 if (fFastTracks) {
88 fFastTracks->Delete();
89 delete fFastTracks;
90 }
91 if (fRand) delete fRand;
92}
93// -------------------------------------------------------------------------
94
95
97{
101 fFastTracks = new TClonesArray("TParticle");
102 FairRootManager::Instance()->Register("FastTrack", "FastSim", fFastTracks, kTRUE);
103}
104
105
106// ----- Public method Init --------------------------------------------
108
109// ----- Public method Init --------------------------------------------
111{
112
114 for (Int_t idx = 0; idx < fgkNParts; idx++) {
115
116 if (fEFF[idx] && fEFFdenom[idx]) {
117 Info("Init", "Prepare efficiency map and projections for index %d and method %d", idx, fMethod);
118 // fEFF[idx]->Print("a");
119
120 // first get projections and calculate integrated effiencies
121 // NOTE: if statistic are bad these are used
122 for (Int_t j = 0; j < fEFF[idx]->GetNdimensions(); j++) {
123
125 switch (fMethod) {
126 case kIgnoreFluct:
128 continue;
129 break;
130 case kLastDim:
132 if (j < (fEFF[idx]->GetNdimensions() - 1)) continue;
133 case kAverage:
135 case kFactorize: {
137 fEFFproj[idx][j] = fEFF[idx]->Projection(j, "E");
138 fEFFproj[idx][j]->SetName(Form("NOMidx%dj%d", idx, j));
139
140 TH1* den = fEFFdenom[idx]->Projection(j, "E");
141 den->SetName(Form("DENidx%dj%d", idx, j));
142 fEFFproj[idx][j]->Divide(den);
143
144 // factoring using last dimension!=1 histograms
145 if (fMethod == kFactorize && j > 0)
146 fEFFproj[idx][j]->Scale(1. / fEFFproj[idx][j]->GetBinContent(fEFFproj[idx][j]->GetMaximumBin()));
147
148 if (den) delete den;
149 } break;
150 case kInterpolate: {
152 if (j > 0) continue;
153 fEFFproj[idx][j] = fEFF[idx]->Projection(j, 1, 2, "E");
154 fEFFproj[idx][j]->SetName(Form("NOMidx%dj%d12", idx, j));
155
156 TH1* den = fEFFdenom[idx]->Projection(j, 1, 2, "E");
157 den->SetName(Form("DENidx%dj%d12", idx, j));
158 fEFFproj[idx][j]->Divide(den);
159
160 if (den) delete den;
161 } break;
162 default: break;
163 }
164 }
165
166 // calculate main effiency map
167 fEFF[idx]->Divide(fEFFdenom[idx]);
168
169 } // endif: nominator
170
171
173 if (fRFp[idx]) {
174 Info("Init", "Momentum smearing map found for index %d", idx);
175 PairAnalysisHelper::CumulateSlicesX(fRFp[idx], kFALSE, kTRUE);
176 }
177
178 } //end: particle species
179
180 // Create and register output array
181 Register();
182
183 return kSUCCESS;
184}
185
187{
188
189 // Get run and runtime database
190 FairRun* run = FairRun::Instance();
191 if (!run) Fatal("SetParContainers", "No analysis run");
192
193 FairRuntimeDb* db = run->GetRuntimeDb();
194 if (!db) Fatal("SetParContainers", "No runtime database");
195}
196// -------------------------------------------------------------------------
197
198void CbmFastSim::SetSeed(unsigned int seed)
199{
203 fRand->SetSeed(seed);
204}
205
206// ----- Public method Finish --------------------------------------------
208{
212}
213// -------------------------------------------------------------------------
214
215// ----- Public method Exec --------------------------------------------
216void CbmFastSim::Exec(Option_t* opt)
217{
221
223 CbmStack* fStack = (CbmStack*) gMC->GetStack();
224 Int_t nTracks = fStack->GetNtrack();
225 // Info("Exec","number of tracks **** %d",Tracks);
226
228 if (fFastTracks->GetEntriesFast() != 0) fFastTracks->Clear("C");
229
231 TClonesArray& chrgCandidates = *fFastTracks; // Charged Candidates
232
233 Int_t iKeep = 0;
234 Int_t iConv = 0;
235
237 Double_t* vals = new Double_t[4]; //fEFF->GetNdimensions()];
238 Int_t* coord = new Int_t[4];
239
241 for (Int_t iTrack = 0; iTrack < nTracks; iTrack++) {
242
244 TParticle* t = fStack->GetParticle(iTrack);
245 int pdg = t->GetPdgCode();
246 // t->Print();
247
249 if (!fdbPdg->GetParticle(pdg)) continue;
250 if (TMath::Abs(fdbPdg->GetParticle(pdg)->Charge()) < 3) continue;
251
254 vals[0] = t->Pt();
255 vals[1] = t->Theta();
256 vals[2] = TVector2::Phi_0_2pi(t->Phi());
257 vals[3] = t->Vz();
258
261 if (TMath::Abs(pdg) == 11 && fStack->GetParticle(t->GetMother(0))
262 && fStack->GetParticle(t->GetMother(0))->GetPdgCode() == 22) {
263 if (!PassEfficiencyFilter(22, vals, coord)) continue;
264 iConv++;
265 }
266 else {
267 if (!PassEfficiencyFilter(pdg, vals, coord)) continue;
268 }
269
271 TLorentzVector p4(t->Px(), t->Py(), t->Pz(), t->Energy());
272
274 // TVector3 stvtx(t->Vx(),t->Vy(),t->Vz());
275
277 if (!Smearing(&p4, pdg)) { /*ERROR*/
278 continue;
279 }
280
283 new ((*fFastTracks)[iKeep]) TParticle(pdg, t->GetStatusCode(), iTrack, 0, 0, 0, p4.Px(), p4.Py(), p4.Pz(),
284 p4.Energy(), t->Vx(), t->Vy(), t->Vz(), 0);
285
286 iKeep++;
287
288 } //trackloop
289
290 // cleanup
291 delete[] vals;
292 delete[] coord;
293
294 Info("Exec", "stack size: \t %d \n", fStack->GetNtrack());
295 Info("Exec", "kept tracks: \t %d \n", iKeep);
296 Info("Exec", "kept converison tracks: \t %d \n", iConv);
297}
298
299Bool_t CbmFastSim::PassEfficiencyFilter(Int_t pdg, Double_t* vals, Int_t* coord)
300{
301 //
302 // check if partilce passed the reconstruction cuts
303 //
304 Int_t idx = -1;
305 switch (TMath::Abs(pdg)) {
306 case kGamma: idx = CbmFastSim::kGam; break;
307 case kElectron: idx = CbmFastSim::kEle; break;
308 case kMuonMinus: idx = CbmFastSim::kMuo; break;
309 case kPiPlus: idx = CbmFastSim::kPio; break;
310 case kKPlus: idx = CbmFastSim::kKao; break;
311 case kProton: idx = CbmFastSim::kPro; break;
312 default: /*Warning("PassEfficiencyFilter","Pdg code %d not supported, particle will not be processed",pdg);*/
313 return kFALSE;
314 }
315
317 if (!fEFF[idx]) {
318 Warning("PassEfficiencyFilter", "No filter for pdg code %d", pdg);
319 return kFALSE;
320 }
321
323 // Info("PassEfficiencyFilter","Efficiency for pt:%.2e theta:%.2e phi:%.2e", vals[0],vals[1],vals[2]);
324
326 Long_t bin = fEFF[idx]->GetBin(vals, kFALSE);
327
329 Double_t eff = 0.0;
330 Double_t err = 0.0;
331 if (bin > 0) {
332 eff = fEFF[idx]->GetBinContent(bin, coord); // write bin coordinates into coord
333
335 if (fMethod != kIgnoreFluct) {
336
337 err = fEFF[idx]->GetBinError(bin);
338 // if (eff>0. && err/eff>=0.60 ) return kFALSE;
339 if (eff > 0. && err / eff >= 0.10) {
340 Double_t effm = GetEfficiency(idx, vals, coord); // vals was NULL
341 // Info("PassEfficiencyFilter","statistical error %f too small (eff:%.2e, new:%.2e)",(eff>0.?err/eff:0.),eff,effm);
342 eff = effm;
343 }
344 }
345 }
346 // else {
347 // eff= GetEfficiency(idx, vals, NULL);
348 // Info("PassEfficiencyFilter","No entry in map, caculate via projections: %.2e (mean eff.)",eff);
349 // }
350
351 Double_t rndm = fRand->Rndm();
352
353 if (rndm > eff) return kFALSE;
354 else
355 return kTRUE;
356}
357
358Bool_t CbmFastSim::Smearing(TLorentzVector* p4, Int_t pdg)
359{
364
365 Int_t idx = -1;
366 switch (TMath::Abs(pdg)) {
367 case kElectron: idx = CbmFastSim::kEle; break;
368 case kMuonMinus: idx = CbmFastSim::kMuo; break;
369 case kPiPlus: idx = CbmFastSim::kPio; break;
370 case kKPlus: idx = CbmFastSim::kKao; break;
371 case kProton: idx = CbmFastSim::kPro; break;
372 default: return kFALSE;
373 }
374
376 Double_t tP = p4->P();
377 Double_t tTheta = p4->Theta();
378 Double_t tPhi = TVector2::Phi_0_2pi(p4->Phi());
379 Double_t mass = fdbPdg->GetParticle(pdg)->Mass();
380
382 Double_t sP = AnalyzeMap(fRFp[idx], tP);
383 Double_t sTheta = tTheta;
384 Double_t sPhi = tPhi;
385
387 Double_t sPx = sP * TMath::Sin(sTheta) * TMath::Cos(sPhi);
388 Double_t sPy = sP * TMath::Sin(sTheta) * TMath::Sin(sPhi);
389 Double_t sPz = sP * TMath::Cos(sTheta);
390
391 Double_t sPt = TMath::Sqrt(sPx * sPx + sPy * sPy);
392 Double_t eta = -TMath::Log(TMath::Tan(sTheta / 2));
393
394
395 // p4->Print();
396 p4->SetPtEtaPhiM(sPt, eta, sPhi, mass);
397 // p4->Print();
398 // printf("\n\n");
399
400 return kTRUE;
401}
402
403Double_t CbmFastSim::AnalyzeMap(TH2F* map, Double_t refValue)
404{
409
411 if (!map) return refValue;
412
414 TAxis* xRec = map->GetXaxis();
415 TAxis* yGen = map->GetYaxis();
416
418 Int_t binGen = yGen->FindBin(refValue);
419
424 if (binGen < 1 || binGen > yGen->GetNbins()) { return (fRand->Gaus(refValue, refValue * 0.02)); }
425
427 Float_t* arrayh = map->GetArray();
428 Int_t offset = (yGen->GetNbins() + 2) * (binGen) + 1;
429
431 Float_t r1 = fRand->Rndm();
432 Int_t binRec = TMath::BinarySearch(xRec->GetNbins() + 2, arrayh + offset - 1, r1);
433
434 Double_t smearedValue = xRec->GetBinLowEdge(binRec + 1);
435 if (r1 > arrayh[offset - 1 + binRec])
436 smearedValue += xRec->GetBinWidth(binRec + 1) * (r1 - arrayh[offset - 1 + binRec])
437 / (arrayh[offset - 1 + binRec + 1] - arrayh[offset - 1 + binRec]);
438
439 // printf("binGen: %d, binRec: %d , offset: %d , \t r1: %f \t in: %f --> out: %f \n",
440 // binGen,binRec,offset, r1,refValue,smearedValue);
441
442 return smearedValue;
443}
444
445
446void CbmFastSim::SetLookupEfficiency(THnBase* nom, THnBase* denom, EParticleType part)
447{
451
452 if (!nom || !denom) Fatal("SetLookupEfficiency", "Either nominator or denominator is NULL ");
453 fEFF[part] = nom;
454 fEFFdenom[part] = denom;
455 /*
456 // first get projections and calculate integrated effiencies
457 // NOTE: if statistic are bad these are used
458 for (Int_t j = 0; j < nom->GetNdimensions(); ++j) {
459
461 switch(fMethod) {
462 case kIgnoreFluct:
464 continue;
465 break;
466 case kLastDim:
468 if( j<(nom->GetNdimensions()-1) ) continue;
469 break;
470 case kAverage:
472 case kFactorize: {
474 fEFFproj[part][j] = nom->Projection(j,"E");
475 fEFFproj[part][j]->SetName(Form("NOMidx%dj%d",part,j));
476
477 TH1 *den=denom->Projection(j,"E");
478 den->SetName(Form("DENidx%dj%d",part,j));
479 fEFFproj[part][j]->Divide( den );
480
481 // factoring using last dimension!=1 histograms
482 if(fMethod==kFactorize && j>0) fEFFproj[part][j]->Scale( 1./fEFFproj[part][j]->GetBinContent( fEFFproj[part][j]->GetMaximumBin() ) );
483
484 if(den) delete den;
485 }
486 break;
487 case kInterpolate: {
489 if(j>0 && j<3) continue;
490 fEFFproj[part][j] = nom->Projection(j,1,2,"E");
491 fEFFproj[part][j]->SetName(Form("NOMidx%dj%d12",part,j));
492
493 TH1 *den=denom->Projection(j,1,2,"E");
494 den->SetName(Form("DENidx%dj%d12",part,j));
495 fEFFproj[part][j]->Divide( den );
496
497 if(den) delete den;
498 }
499 break;
500 default:
501 break;
502 }
503
504
505 }
506
507 // calculate main effiency map
508 nom->Divide(denom);
509 */
510}
511
512Double_t CbmFastSim::GetEfficiency(Int_t idx, Double_t* vals, Int_t* coord)
513{
517
518 if (fMethod == kIgnoreFluct) return 0.;
519
520
521 Int_t ndim = 0;
522 Double_t meanEff = (fMethod == kFactorize ? 1. : 0.);
523 Double_t eff = 0.;
524 // for (Int_t j = 0; j < 10; ++j) {
525 for (Int_t j = 10; j >= 0; j--) {
526
527 if (!fEFFproj[idx][j]) continue;
528
530 if (coord) eff = fEFFproj[idx][j]->GetBinContent(coord[j]);
531 else
532 eff = fEFFproj[idx][j]->GetBinContent(fEFFproj[idx][j]->FindBin(vals[j]));
533 // Info("GetEfficiency","int eff for j:%d and idx:%d and value: %.2e is %.2e!",j,idx,vals[j],eff);
534
536 switch (fMethod) {
537 case kIgnoreFluct: return 0.;
538 case kInterpolate: {
539 if (coord) {
542 for (Int_t c = 0; c < 3; c++) {
543 if (coord[c] == 0) coord[c] += 2;
544 if (coord[c] == 1) coord[c] += 1;
545 if (coord[c] == fEFF[idx]->GetAxis(c)->GetNbins()) coord[c] -= 2;
546 if (coord[c] == fEFF[idx]->GetAxis(c)->GetNbins() - 1) coord[c] -= 1;
547 }
548 eff = fEFFproj[idx][j]->Interpolate(fEFFproj[idx][j]->GetXaxis()->GetBinCenter(coord[0]),
549 fEFFproj[idx][j]->GetYaxis()->GetBinCenter(coord[1]),
550 fEFFproj[idx][j]->GetZaxis()->GetBinCenter(coord[2]));
551 }
552 else
553 eff = fEFFproj[idx][j]->Interpolate(vals[0], vals[1], vals[2]);
554 return eff;
555 } break;
556 case kAverage:
557 case kLastDim:
558 if (eff < 1.e-10) return 0.;
559 meanEff += eff;
560 ndim++;
561 break;
562 case kFactorize:
563 if (eff < 1.e-10) return 0.;
564 meanEff *= eff;
565 ndim = 1; // ndim++;
566 break;
567 }
568 }
569
570 // protect against division by 0
571 if (!ndim) {
572 Error("GetEfficiency", "number of dimensions for idx:%d is zero!", idx);
573 return 0.;
574 }
575
576 // return mean efficiency
577 return (meanEff / ndim);
578}
579
580Bool_t CbmFastSim::IsSelected(TObject* sel, Int_t opt)
581{
582 //
583 // check if partilce passed the cuts
584 //
585
586 Int_t pdg = opt;
587 TVector3* mom = dynamic_cast<TVector3*>(sel);
588
589 // Info("IsSelected","Compare pdg code %d to e(%d),mu(%d),pi(%d),K(%d),p(%d)",
590 // TMath::Abs(pdg),kElectron,kMuonMinus,kPiPlus,kKPlus,kProton);
591
592 Int_t idx = -1;
593 switch (TMath::Abs(pdg)) {
594 case kGamma: idx = CbmFastSim::kGam; break;
595 case kElectron: idx = CbmFastSim::kEle; break;
596 case kMuonMinus: idx = CbmFastSim::kMuo; break;
597 case kPiPlus: idx = CbmFastSim::kPio; break;
598 case kKPlus: idx = CbmFastSim::kKao; break;
599 case kProton: idx = CbmFastSim::kPro; break;
600 default: /*Warning("IsSelected","Pdg code %d not supported, particle will not be processed",pdg);*/ return kFALSE;
601 }
602
603 // Double_t rndm2 = fRand->Rndm();
604 // if(rndm2<0.1) return kTRUE;
605 // else return kFALSE;
606
608 if (!fEFF[idx]) {
609 Warning("IsSelected", "No filter for pdg code %d", pdg);
610 return kTRUE;
611 }
612
614 Double_t* vals = new Double_t[3];
615
618 vals[0] = mom->Pt();
619 vals[1] = mom->Theta();
620 vals[2] = TVector2::Phi_0_2pi(mom->Phi());
621
623 Long_t bin = fEFF[idx]->GetBin(vals, kFALSE);
624
626 delete vals;
627
628 Double_t eff = 0.0;
629 if (bin > 0) eff = fEFF[idx]->GetBinContent(bin);
630 Double_t rndm = fRand->Rndm();
631
632
633 if (rndm > eff) return kFALSE;
634 else
635 return kTRUE;
636}
637
ClassImp(CbmConverterManager)
CbmFastSim(bool persist=true)
Double_t GetEfficiency(Int_t idx, Double_t *vals, Int_t *coord)
void SetLookupEfficiency(THnBase *nom, THnBase *denom, EParticleType part)
TClonesArray * fFastTracks
Definition CbmFastSim.h:95
virtual void Exec(Option_t *opt)
Bool_t Smearing(TLorentzVector *p4, Int_t pdg)
virtual InitStatus Init()
THnBase * fEFFdenom[fgkNParts]
Definition CbmFastSim.h:99
TDatabasePDG * fdbPdg
Definition CbmFastSim.h:81
virtual void SetParContainers()
Bool_t PassEfficiencyFilter(Int_t pdg, Double_t *vals, Int_t *coord)
virtual void InitTask()
static const Int_t fgkNParts
Definition CbmFastSim.h:82
EEfficiencyMethod fMethod
Definition CbmFastSim.h:83
TRandom3 * fRand
Definition CbmFastSim.h:80
THnBase * fEFF[fgkNParts]
Definition CbmFastSim.h:98
void SetSeed(unsigned int seed=65539)
virtual Bool_t IsSelected(TObject *sel, Int_t opt)
void Register()
TH2F * fRFp[fgkNParts]
Definition CbmFastSim.h:102
TH1 * fEFFproj[fgkNParts][10]
Definition CbmFastSim.h:100
virtual void Finish()
Double_t AnalyzeMap(TH2F *map, Double_t refValue)
virtual Int_t GetNtrack() const
Definition CbmStack.h:154
TParticle * GetParticle(Int_t trackId) const
Definition CbmStack.cxx:368
void CumulateSlicesX(TH2 *h, Bool_t reverse=kFALSE, Bool_t norm=kFALSE)