3131#include "SimulationDataFormat/MCEventHeader.h"
3232#include "DetectorsBase/Propagator.h"
3333#include "SimulationDataFormat/TrackReference.h"
34+ #include "SimulationDataFormat/O2DatabasePDG.h"
3435#include "SimulationDataFormat/MCTrack.h"
3536#include "SimulationDataFormat/MCCompLabel.h"
3637#include "SimulationDataFormat/MCTruthContainer.h"
@@ -60,11 +61,15 @@ struct ParticleInfo {
6061 bool isPrimary = 0u ;
6162 unsigned char storedStatus = 2 ; /// not stored = 2, fake = 1, good = 0
6263 o2 ::its ::TrackITS track ;
64+ o2 ::MCTrack mcTrack ;
6365};
6466
6567#pragma link C++ class ParticleInfo + ;
6668
67- void CheckTracksCA (bool doFakeClStud = false,
69+ void CheckTracksCA (bool doEffStud = false,
70+ bool doFakeClStud = false,
71+ bool doPullStud = true,
72+ bool createOutput = false,
6873 std ::string tracfile = "o2trac_its.root" ,
6974 std ::string magfile = "o2sim_grp.root" ,
7075 std ::string clusfile = "o2clus_its.root" ,
@@ -124,7 +129,10 @@ void CheckTracksCA(bool doFakeClStud = false,
124129 info [n ].resize (mcArr -> size ());
125130 hZvertex -> Fill (mcEvent -> GetZ ());
126131 for (unsigned int mcI {0 }; mcI < mcArr -> size (); ++ mcI ) {
127- auto part = mcArr -> at (mcI );
132+ const auto part = mcArr -> at (mcI );
133+ if (!o2 ::O2DatabasePDG ::Instance ()-> GetParticle (part .GetPdgCode ())) {
134+ continue ;
135+ }
128136 info [n ][mcI ].event = n ;
129137 info [n ][mcI ].pdg = part .GetPdgCode ();
130138 info [n ][mcI ].pvx = mcEvent -> GetX ();
@@ -134,6 +142,7 @@ void CheckTracksCA(bool doFakeClStud = false,
134142 info [n ][mcI ].phi = part .GetPhi ();
135143 info [n ][mcI ].eta = part .GetEta ();
136144 info [n ][mcI ].isPrimary = part .isPrimary ();
145+ info [n ][mcI ].mcTrack = part ;
137146 }
138147 }
139148 std ::cout << "done." << std ::endl ;
@@ -214,117 +223,108 @@ void CheckTracksCA(bool doFakeClStud = false,
214223 std ::cout << "\t- Total number of fakes: " << fakes << " (" << fakes * 100. / total << "%)" << std ::endl ;
215224 std ::cout << "\t- Total number of good: " << good << " (" << good * 100. / total << "%)" << std ::endl ;
216225
217- int nb = 100 ;
218- double xbins [nb + 1 ], ptcutl = 0.01 , ptcuth = 10. ;
219- double a = std ::log (ptcuth / ptcutl ) / nb ;
220- for (int i = 0 ; i <= nb ; i ++ )
221- xbins [i ] = ptcutl * std ::exp (i * a );
222- TH1D * num = new TH1D ("num" , ";#it{p}_{T} (GeV/#it{c});Efficiency (fake-track rate)" , nb , xbins );
223- num -> Sumw2 ();
224- TH1D * numEta = new TH1D ("numEta" , ";#eta;Number of tracks" , 60 , -3 , 3 );
225- numEta -> Sumw2 ();
226- TH1D * numChi2 = new TH1D ("numChi2" , ";#it{p}_{T} (GeV/#it{c});Efficiency (fake-track rate)" , 200 , 0 , 100 );
227-
228- TH1D * fak = new TH1D ("fak" , ";#it{p}_{T} (GeV/#it{c});Fak" , nb , xbins );
229- fak -> Sumw2 ();
230- TH1D * multiFak = new TH1D ("multiFak" , ";#it{p}_{T} (GeV/#it{c});Fak" , nb , xbins );
231- multiFak -> Sumw2 ();
232- TH1D * fakChi2 = new TH1D ("fakChi2" , ";#it{p}_{T} (GeV/#it{c});Fak" , 200 , 0 , 100 );
233-
234- TH1D * clone = new TH1D ("clone" , ";#it{p}_{T} (GeV/#it{c});Clone" , nb , xbins );
235- clone -> Sumw2 ();
236-
237- TH1D * den = new TH1D ("den" , ";#it{p}_{T} (GeV/#it{c});Den" , nb , xbins );
238- den -> Sumw2 ();
239-
240- for (auto& evInfo : info ) {
241- for (auto& part : evInfo ) {
242- if ((part .clusters & 0x7f ) != 0x7f ) {
243- // part.clusters != 0x3f && part.clusters != 0x3f << 1 &&
244- // part.clusters != 0x1f && part.clusters != 0x1f << 1 && part.clusters != 0x1f << 2 &&
245- // part.clusters != 0x0f && part.clusters != 0x0f << 1 && part.clusters != 0x0f << 2 && part.clusters != 0x0f << 3) {
246- continue ;
247- }
248- if (!part .isPrimary ) {
249- continue ;
250- }
251- den -> Fill (part .pt );
252- if (part .isReco ) {
253- num -> Fill (part .pt );
254- numEta -> Fill (part .eta );
255- if (part .isReco > 1 ) {
256- for (int _i {0 }; _i < part .isReco - 1 ; ++ _i ) {
257- clone -> Fill (part .pt );
226+ TFile * file {nullptr };
227+ if (createOutput ) {
228+ file = TFile ::Open ("CheckTracksCA.root" , "recreate" );
229+ }
230+
231+ if (doEffStud ) {
232+ std ::cout << "Calculating efficiencies... " ;
233+ const int nb = 100 ;
234+ double xbins [nb + 1 ], ptcutl = 0.01 , ptcuth = 10. ;
235+ double a = std ::log (ptcuth / ptcutl ) / nb ;
236+ for (int i = 0 ; i <= nb ; i ++ )
237+ xbins [i ] = ptcutl * std ::exp (i * a );
238+ TH1D * num = new TH1D ("num" , ";#it{p}_{T} (GeV/#it{c});Efficiency (fake-track rate)" , nb , xbins );
239+ num -> Sumw2 ();
240+ TH1D * numEta = new TH1D ("numEta" , ";#eta;Number of tracks" , 60 , -3 , 3 );
241+ numEta -> Sumw2 ();
242+ TH1D * numChi2 = new TH1D ("numChi2" , ";#it{p}_{T} (GeV/#it{c});Efficiency (fake-track rate)" , 200 , 0 , 100 );
243+
244+ TH1D * fak = new TH1D ("fak" , ";#it{p}_{T} (GeV/#it{c});Fak" , nb , xbins );
245+ fak -> Sumw2 ();
246+ TH1D * multiFak = new TH1D ("multiFak" , ";#it{p}_{T} (GeV/#it{c});Fak" , nb , xbins );
247+ multiFak -> Sumw2 ();
248+ TH1D * fakChi2 = new TH1D ("fakChi2" , ";#it{p}_{T} (GeV/#it{c});Fak" , 200 , 0 , 100 );
249+
250+ TH1D * clone = new TH1D ("clone" , ";#it{p}_{T} (GeV/#it{c});Clone" , nb , xbins );
251+ clone -> Sumw2 ();
252+
253+ TH1D * den = new TH1D ("den" , ";#it{p}_{T} (GeV/#it{c});Den" , nb , xbins );
254+ den -> Sumw2 ();
255+
256+ for (auto& evInfo : info ) {
257+ for (auto& part : evInfo ) {
258+ if ((part .clusters & 0x7f ) != 0x7f ) {
259+ // part.clusters != 0x3f && part.clusters != 0x3f << 1 &&
260+ // part.clusters != 0x1f && part.clusters != 0x1f << 1 && part.clusters != 0x1f << 2 &&
261+ // part.clusters != 0x0f && part.clusters != 0x0f << 1 && part.clusters != 0x0f << 2 && part.clusters != 0x0f << 3) {
262+ continue ;
263+ }
264+ if (!part .isPrimary ) {
265+ continue ;
266+ }
267+ den -> Fill (part .pt );
268+ if (part .isReco ) {
269+ num -> Fill (part .pt );
270+ numEta -> Fill (part .eta );
271+ if (part .isReco > 1 ) {
272+ for (int _i {0 }; _i < part .isReco - 1 ; ++ _i ) {
273+ clone -> Fill (part .pt );
274+ }
258275 }
259276 }
260- }
261- if (part .isFake ) {
262- fak -> Fill (part .pt );
263- if ( part .isFake > 1 ) {
264- for ( int _i { 0 }; _i < part .isFake - 1 ; ++ _i ) {
265- multiFak -> Fill ( part . pt );
277+ if ( part . isFake ) {
278+ fak -> Fill (part .pt );
279+ if (part .isFake > 1 ) {
280+ for ( int _i { 0 }; _i < part .isFake - 1 ; ++ _i ) {
281+ multiFak -> Fill ( part .pt );
282+ }
266283 }
267284 }
268285 }
269286 }
270- }
271287
272- TCanvas * c1 = new TCanvas ;
273- c1 -> SetLogx ();
274- c1 -> SetGridx ();
275- c1 -> SetGridy ();
276- TH1 * sum = (TH1 * )num -> Clone ("sum" );
277- sum -> Add (fak );
278- sum -> Divide (sum , den , 1 , 1 );
279- sum -> SetLineColor (kBlack );
280- sum -> Draw ("hist" );
281- num -> Divide (num , den , 1 , 1 , "b" );
282- num -> Draw ("histesame" );
283- fak -> Divide (fak , den , 1 , 1 , "b" );
284- fak -> SetLineColor (2 );
285- fak -> Draw ("histesame" );
286- multiFak -> Divide (multiFak , den , 1 , 1 , "b" );
287- multiFak -> SetLineColor (kRed + 1 );
288- multiFak -> Draw ("histsame" );
289- clone -> Divide (clone , den , 1 , 1 , "b" );
290- clone -> SetLineColor (3 );
291- clone -> Draw ("histesame" );
292- TCanvas * c2 = new TCanvas ;
293- c2 -> SetGridx ();
294- c2 -> SetGridy ();
295- hZvertex -> DrawClone ();
296-
297- std ::cout << "** Streaming output TTree to file ... " << std ::flush ;
298- TFile file ("CheckTracksCA.root" , "recreate" );
299- TTree tree ("ParticleInfo" , "ParticleInfo" );
300- ParticleInfo pInfo ;
301- tree .Branch ("particle" , & pInfo );
302- for (auto& event : info ) {
303- for (auto& part : event ) {
304- int nCl {0 };
305- for (unsigned int bit {0 }; bit < sizeof (pInfo .clusters ) * 8 ; ++ bit ) {
306- nCl += bool (part .clusters & (1 << bit ));
307- }
308- if (nCl < 3 ) {
309- continue ;
310- }
311- pInfo = part ;
312- tree .Fill ();
288+ TCanvas * c1 = new TCanvas ;
289+ c1 -> SetLogx ();
290+ c1 -> SetGridx ();
291+ c1 -> SetGridy ();
292+ TH1 * sum = (TH1 * )num -> Clone ("sum" );
293+ sum -> Add (fak );
294+ sum -> Divide (sum , den , 1 , 1 );
295+ sum -> SetLineColor (kBlack );
296+ sum -> Draw ("hist" );
297+ num -> Divide (num , den , 1 , 1 , "b" );
298+ num -> Draw ("histesame" );
299+ fak -> Divide (fak , den , 1 , 1 , "b" );
300+ fak -> SetLineColor (2 );
301+ fak -> Draw ("histesame" );
302+ multiFak -> Divide (multiFak , den , 1 , 1 , "b" );
303+ multiFak -> SetLineColor (kRed + 1 );
304+ multiFak -> Draw ("histsame" );
305+ clone -> Divide (clone , den , 1 , 1 , "b" );
306+ clone -> SetLineColor (3 );
307+ clone -> Draw ("histesame" );
308+ TCanvas * c2 = new TCanvas ;
309+ c2 -> SetGridx ();
310+ c2 -> SetGridy ();
311+ hZvertex -> DrawClone ();
312+
313+ if (createOutput ) {
314+ sum -> Write ("total" );
315+ fak -> Write ("singleFake" );
316+ num -> Write ("efficiency" );
317+ numEta -> Write ("etaDist" );
318+ multiFak -> Write ("multiFake" );
319+ clone -> Write ("clones" );
313320 }
321+ std ::cout << " done." << std ::endl ;
314322 }
315- tree .Write ();
316- sum -> Write ("total" );
317- fak -> Write ("singleFake" );
318- num -> Write ("efficiency" );
319- numEta -> Write ("etaDist" );
320- multiFak -> Write ("multiFake" );
321- clone -> Write ("clones" );
322- file .Close ();
323- std ::cout << " done." << std ::endl ;
324323
325324 //////////////////////
326325 // Fake clusters study
327326 if (doFakeClStud ) {
327+ std ::cout << "Creating fake cluster study... " ;
328328 std ::vector < TH1I * > histLength , histLength1Fake , histLengthNoCl , histLength1FakeNoCl ;
329329 std ::vector < THStack * > stackLength , stackLength1Fake ;
330330 std ::vector < TLegend * > legends , legends1Fake ;
@@ -364,10 +364,10 @@ void CheckTracksCA(bool doFakeClStud = false,
364364 stackLength1Fake [iH - 4 ]-> Add (histLength1FakeNoCl [iH - 4 ]);
365365 }
366366
367- for (auto& event : info ) {
368- for (auto& part : event ) {
367+ for (const auto& event : info ) {
368+ for (const auto& part : event ) {
369369 int nCl {0 };
370- for (unsigned int bit {0 }; bit < sizeof (pInfo .clusters ) * 8 ; ++ bit ) {
370+ for (unsigned int bit {0 }; bit < sizeof (part .clusters ) * 8 ; ++ bit ) {
371371 nCl += bool (part .clusters & (1 << bit ));
372372 }
373373 if (nCl < 3 ) {
@@ -409,5 +409,93 @@ void CheckTracksCA(bool doFakeClStud = false,
409409 gPad -> BuildLegend ();
410410 }
411411 canvas -> SaveAs ("fakeClusters.png" , "recreate" );
412+ std ::cout << " done\n" ;
413+ }
414+
415+ if (doPullStud ) {
416+ std ::cout << "Creating pull study... " ;
417+ const int nBins {30 };
418+ const float xWidth {10 };
419+ // Pulls
420+ auto hYPull = new TH1F ("hYPull" , "Pull Y" , nBins , - xWidth , xWidth );
421+ auto hZPull = new TH1F ("hZPull" , "Pull Z" , nBins , - xWidth , xWidth );
422+ auto hSPhiPull = new TH1F ("hSPhiPull" , "Pull Sin(Phi)" , nBins , - xWidth , xWidth );
423+ auto hTglPull = new TH1F ("hTglPull" , "Pull Tg(Lambda)" , nBins , - xWidth , xWidth );
424+ auto hQoPtPull = new TH1F ("hQoPtPull" , "Pull Q/Pt" , nBins , - xWidth , xWidth );
425+ // Correlation
426+ auto hCorYZ = new TH2F ("hCorYZ" , ";#sigma_{Z}^{2};#sigma_{Y}^{2}" , nBins , 0 , 5e-5 , nBins , 0 , 5e-5 );
427+ auto hCorYSPhi = new TH2F ("hCorYSPhi" , ";#sigma_{snp}^{2};#sigma_{Y}^{2}" , nBins , 0 , 5e-5 , nBins , 0 , 5e-5 );
428+
429+ for (const auto & event : info ) {
430+ for (const auto & part : event ) {
431+ if (((part .clusters & 0x7f ) != 0x7f ) && !part .isPrimary ) {
432+ continue ;
433+ }
434+
435+ // prepare mc truth parameters
436+ std ::array < float , 3 > xyz {(float )part .mcTrack .GetStartVertexCoordinatesX (), (float )part .mcTrack .GetStartVertexCoordinatesY (), (float )part .mcTrack .GetStartVertexCoordinatesZ ()};
437+ std ::array < float , 3 > pxyz {(float )part .mcTrack .GetStartVertexMomentumX (), (float )part .mcTrack .GetStartVertexMomentumY (), (float )part .mcTrack .GetStartVertexMomentumZ ()};
438+ o2 ::track ::TrackPar mcTrack (xyz , pxyz , TMath ::Nint (o2 ::O2DatabasePDG ::Instance ()-> GetParticle (part .mcTrack .GetPdgCode ())-> Charge () / 3 ), false);
439+ if (!mcTrack .rotate (part .track .getAlpha ()) &&
440+ o2 ::base ::Propagator ::Instance ()-> propagateTo (mcTrack , part .track .getX ())) {
441+ continue ;
442+ }
443+
444+ hYPull -> Fill ((part .track .getY () - mcTrack .getY ()) / std ::sqrt (part .track .getSigmaY2 ()));
445+ hZPull -> Fill ((part .track .getZ () - mcTrack .getZ ()) / std ::sqrt (part .track .getSigmaZ2 ()));
446+ hSPhiPull -> Fill ((part .track .getSnp () - mcTrack .getSnp ()) / std ::sqrt (part .track .getSigmaSnp2 ()));
447+ hTglPull -> Fill ((part .track .getTgl () - mcTrack .getTgl ()) / std ::sqrt (part .track .getSigmaTgl2 ()));
448+ hQoPtPull -> Fill ((part .track .getQ2Pt () - mcTrack .getQ2Pt ()) / std ::sqrt (part .track .getSigma1Pt2 ()));
449+
450+ hCorYZ -> Fill (part .track .getSigmaZ2 (), part .track .getSigmaY2 ());
451+ hCorYSPhi -> Fill (part .track .getSigmaZ2 (), part .track .getSigmaSnp2 ());
452+ }
453+ }
454+
455+ // normalise, set axis, fit and draw
456+ auto doPullCalc = [ ](TH1F * h ) {
457+ h -> Scale (1. / h -> Integral ("width" ));
458+ h -> GetYaxis ()-> SetRangeUser (1e-5 , 1. );
459+ h -> Fit ("gaus" , "" , "2QMR" );
460+ gPad -> SetLogy ();
461+ h -> Draw ("hist" );
462+ };
463+
464+ auto c = new TCanvas ("cPull ", "" , 1000 , 1000 );
465+ c -> Divide (5 , 5 );
466+ c -> cd (1 );
467+ doPullCalc (hYPull );
468+ c -> cd (2 );
469+ hCorYZ -> Draw ("colz" );
470+ c -> cd (3 );
471+ hCorYSPhi -> Draw ("colz" );
472+ c -> cd (1 + 6 );
473+ doPullCalc (hZPull );
474+ c -> cd (1 + 12 );
475+ doPullCalc (hSPhiPull );
476+ c -> cd (1 + 18 );
477+ doPullCalc (hTglPull );
478+ c -> cd (1 + 24 );
479+ doPullCalc (hQoPtPull );
480+ c -> Draw ();
481+ std ::cout << " done\n" ;
482+ }
483+
484+ if (createOutput ) {
485+ std ::cout << "** Streaming output TTree to file ... " << std ::flush ;
486+ TTree tree ("ParticleInfo" , "ParticleInfo" );
487+ ParticleInfo pInfo ;
488+ tree .Branch ("particle" , & pInfo );
489+ for (const auto& event : info ) {
490+ for (const auto& part : event ) {
491+ if ( ((part .clusters & 0x7f ) != 0x7f ) && !part .isPrimary ) {
492+ continue ;
493+ }
494+ pInfo = part ;
495+ tree .Fill ();
496+ }
497+ }
498+ tree .Write ();
499+ file -> Close ();
412500 }
413501}
0 commit comments