1616#include <TCanvas.h>
1717#include <TFile.h>
1818#include <TH2F.h>
19+ #include <TH1F.h>
1920#include <TNtuple.h>
2021#include <TString.h>
2122#include <TTree.h>
2223#include <TLine.h>
2324#include <TStyle.h>
2425
26+ #include <set>
27+
2528#include "IOTOFBase/Segmentation.h"
2629#include "IOTOFBase/IOTOFBaseParam.h"
2730#include "IOTOFBase/GeometryTGeo.h"
31+ #include "IOTOFSimulation/Digitizer.h"
2832#include "DataFormatsIOTOF/Digit.h"
2933#include "ITSMFTSimulation/Hit.h"
3034#include "MathUtils/Utils.h"
3135#include "SimulationDataFormat/ConstMCTruthContainer.h"
3236#include "SimulationDataFormat/IOMCTruthContainerView.h"
3337#include "SimulationDataFormat/MCCompLabel.h"
38+ #include "SimulationDataFormat/MCTrack.h"
39+ #include "SimulationDataFormat/TrackReference.h"
3440#include "DetectorsBase/GeometryManager.h"
3541#include "CCDB/BasicCCDBManager.h"
3642
@@ -75,7 +81,11 @@ void addTLines(float pitch)
7581 gPad -> Update ();
7682}
7783
78- void CheckDigitsIOTOF (std ::string digifile = "tf3digits.root" , std ::string hitfile = "o2sim_HitsTF3.root" , std ::string inputGeom = "o2sim_geometry.root" )
84+ void CheckDigitsIOTOF (std ::string digifile = "tf3digits.root" ,
85+ std ::string hitfile = "o2sim_HitsTF3.root" ,
86+ std ::string kinefile = "o2sim_Kine.root" ,
87+ std ::string inputGeom = "o2sim_geometry.root" ,
88+ std ::string geomCfgStr = "IOTOFBase.segmentedInnerTOF=true;IOTOFBase.segmentedOuterTOF=true;IOTOFBase.enableForwardTOF=false;IOTOFBase.enableBackwardTOF=false;" )
7989{
8090 gStyle -> SetPalette (55 );
8191
@@ -85,7 +95,7 @@ void CheckDigitsIOTOF(std::string digifile = "tf3digits.root", std::string hitfi
8595 using o2 ::iotof ::Digit ;
8696 using o2 ::itsmft ::Hit ;
8797
88- o2 ::conf ::ConfigurableParam ::updateFromString ("IOTOFBase.segmentedInnerTOF=true;IOTOFBase.segmentedOuterTOF=true;IOTOFBase.enableForwardTOF=false;IOTOFBase.enableBackwardTOF=false" );
98+ o2 ::conf ::ConfigurableParam ::updateFromString (geomCfgStr );
8999
90100 auto seg = o2 ::iotof ::Segmentation ::Instance ();
91101
@@ -123,15 +133,48 @@ void CheckDigitsIOTOF(std::string digifile = "tf3digits.root", std::string hitfi
123133
124134 digTree -> GetEntry (0 );
125135
136+ // MC tracks
137+ TFile * kineFile = TFile ::Open (kinefile .data ());
138+ TTree * kineTree = (TTree * )kineFile -> Get ("o2sim" );
139+ std ::vector < std ::vector < o2 ::MCTrack > * > mcTracksPerEvent (nevH , nullptr );
140+ std ::vector < std ::vector < o2 ::TrackReference > * > mcTracksRefsPerEvent (nevH , nullptr );
141+ kineTree -> SetBranchAddress ("MCTrack" , & mcTracksPerEvent [0 ]);
142+ kineTree -> SetBranchAddress ("TrackRefs" , & mcTracksRefsPerEvent [0 ]);
143+
144+ TH1F * hGenHitsEta [2 ][2 ] = {{
145+ new TH1F ("hGenHitsEtaPrmL0" , "hGenHitsEtaPrmL0" , 40 , -2 , 2 ),
146+ new TH1F ("hGenHitsEtaSecL0" , "hGenHitsEtaSecL0" , 40 , -2 , 2 ),
147+ }, {
148+ new TH1F ("hGenHitsEtaPrmL1" , "hGenHitsEtaPrmL1" , 40 , -2 , 2 ),
149+ new TH1F ("hGenHitsEtaSecL1" , "hGenHitsEtaSecL1" , 40 , -2 , 2 ),
150+ }};
151+
126152 // Load all MC hit events upfront and build the hit lookup map.
127153 for (int im = 0 ; im < nevH ; ++ im ) {
128154 hitTree -> SetBranchAddress ("TF3Hit" , & hitArray [im ]);
129155 hitTree -> GetEntry (im );
156+ kineTree -> SetBranchAddress ("MCTrack" , & mcTracksPerEvent [im ]);
157+ kineTree -> SetBranchAddress ("TrackRefs" , & mcTracksRefsPerEvent [im ]);
158+ kineTree -> GetEntry (im );
130159 auto& mc2hit = mc2hitVec [im ];
131160 for (int ih = hitArray [im ]-> size (); ih -- ;) {
132161 const auto& hit = (* hitArray [im ])[ih ];
133162 uint64_t key = (uint64_t (hit .GetTrackID ()) << 32 ) + hit .GetDetectorID ();
134163 mc2hit .emplace (key , ih );
164+
165+ auto & mcTrack = mcTracksPerEvent [im ]-> at (hit .GetTrackID ());
166+ bool isPrimary = mcTrack .isPrimary ();
167+
168+ int layer = gman -> getIOTOFLayer (hit .GetDetectorID ());
169+ if (layer == 0 && isPrimary ) {
170+ hGenHitsEta [0 ][0 ]-> Fill (mcTrack .GetEta ());
171+ } else if (layer == 0 && !isPrimary ) {
172+ hGenHitsEta [0 ][1 ]-> Fill (mcTrack .GetEta ());
173+ } else if (layer == 1 && isPrimary ) {
174+ hGenHitsEta [1 ][0 ]-> Fill (mcTrack .GetEta ());
175+ } else if (layer == 1 && !isPrimary ) {
176+ hGenHitsEta [1 ][1 ]-> Fill (mcTrack .GetEta ());
177+ }
135178 }
136179 }
137180
@@ -142,11 +185,21 @@ void CheckDigitsIOTOF(std::string digifile = "tf3digits.root", std::string hitfi
142185 plabelsArr -> copyandflatten (labels );
143186
144187 // LOOP on : ROFRecord array
188+ TH1F * hRecoDigitEta [2 ][2 ] = {{
189+ new TH1F ("hRecoDigitEtaPrmL0" , "hRecoDigitEtaPrmL0" , 40 , -2 , 2 ),
190+ new TH1F ("hRecoDigitEtaSecL0" , "hRecoDigitEtaSecL0" , 40 , -2 , 2 ),
191+ }, {
192+ new TH1F ("hRecoDigitEtaPrmL1" , "hRecoDigitEtaPrmL1" , 40 , -2 , 2 ),
193+ new TH1F ("hRecoDigitEtaSecL1" , "hRecoDigitEtaSecL1" , 40 , -2 , 2 ),
194+ }};
195+
196+ std ::unordered_map < uint64_t , std ::vector < int >> hitDigitMap ;
145197 for (unsigned int iROF = 0 ; iROF < rofArr .size (); ++ iROF ) {
146198
147199 const unsigned int rofIndex = rofArr [iROF ].getFirstEntry ();
148200 const unsigned int rofNEntries = rofArr [iROF ].getNEntries ();
149201
202+ std ::unordered_map < int , std ::set < uint64_t >> tracksWithDigits ;
150203 // LOOP on : digits array
151204 for (unsigned int iDigit = rofIndex ; iDigit < rofIndex + rofNEntries ; iDigit ++ ) {
152205 if (iDigit % 1000 == 0 ) {
@@ -176,10 +229,11 @@ void CheckDigitsIOTOF(std::string digifile = "tf3digits.root", std::string hitfi
176229 }
177230
178231 int trID = lab .getTrackID ();
232+ int evtID = lab .getEventID ();
179233
180234 const auto gloD = gman -> getMatrixL2G (chipID )(locD ); // convert to global
181235
182- std ::unordered_map < uint64_t , int > * mc2hit = & mc2hitVec [lab . getEventID () ];
236+ std ::unordered_map < uint64_t , int > * mc2hit = & mc2hitVec [evtID ];
183237
184238 // get MC info
185239 uint64_t key = (uint64_t (trID ) << 32 ) + chipID ;
@@ -191,7 +245,7 @@ void CheckDigitsIOTOF(std::string digifile = "tf3digits.root", std::string hitfi
191245 }
192246
193247 ////// HITS
194- Hit & hit = (* hitArray [lab . getEventID () ])[hitEntry -> second ];
248+ Hit & hit = (* hitArray [evtID ])[hitEntry -> second ];
195249
196250 auto xyzLocE = gman -> getMatrixL2G (chipID ) ^ (hit .GetPos ()); // inverse conversion from global to local
197251 auto xyzLocS = gman -> getMatrixL2G (chipID ) ^ (hit .GetPosStart ());
@@ -220,6 +274,21 @@ void CheckDigitsIOTOF(std::string digifile = "tf3digits.root", std::string hitfi
220274 locH .X () - locD .X (), locH .Z () - locD .Z ()); /// difference in x and z between the hit and the digit in the local frame
221275 nt2 -> Fill (chipID , gloD .Z (), locHS .X () - locHE .X (), locHS .Z () - locHE .Z ()); /// differences between local hit start and hit end positions
222276
277+ // Check if key is already in the set of tracks with digits,
278+ // else we double count digits in efficiency calculation
279+ // when using stepping
280+ if (tracksWithDigits [evtID ].find (key ) == tracksWithDigits [evtID ].end ()) {
281+ tracksWithDigits [evtID ].insert (key );
282+ int digitLayer = gman -> getIOTOFLayer (chipID );
283+ auto& mcTrack = mcTracksPerEvent [evtID ]-> at (trID );
284+ bool isPrimary = mcTrack .isPrimary ();
285+ hRecoDigitEta [digitLayer ][isPrimary ? 0 : 1 ]-> Fill (mcTrack .GetEta ());
286+ }
287+
288+ // Fill the hitDigitMap for later analysis
289+ // Hit key from event ID and hit index
290+ uint64_t hitKey = (uint64_t (evtID ) << 32 ) + hitEntry -> second ;
291+ hitDigitMap [hitKey ].push_back (iDigit );
223292 } // end loop on digits array
224293
225294 } // end loop on ROFRecords
@@ -228,35 +297,35 @@ void CheckDigitsIOTOF(std::string digifile = "tf3digits.root", std::string hitfi
228297 auto canvXY = new TCanvas ("canvXY" , "" , 1600 , 800 );
229298 canvXY -> Divide (2 , 1 );
230299 canvXY -> cd (1 );
231- nt -> Draw ("y:x>>h_y_vs_x_IOTOF(1000, -100, 100, 1000, -100, 100)" , "id >= 0 && id < 53568 " , "colz" );
300+ nt -> Draw ("y:x>>h_y_vs_x_IOTOF(1000, -100, 100, 1000, -100, 100)" , "id >= 0 && id < 55488 " , "colz" );
232301 canvXY -> cd (2 );
233- nt -> Draw ("y:z>>h_y_vs_z_IOTOF(1000, -400, 400, 1000, -100, 100)" , "id >= 0 && id < 53568 " , "colz" );
302+ nt -> Draw ("y:z>>h_y_vs_z_IOTOF(1000, -400, 400, 1000, -100, 100)" , "id >= 0 && id < 55488 " , "colz" );
234303 canvXY -> SaveAs ("tf3digits_y_vs_x_vs_z.pdf" );
235304
236305 // z distributions
237306 auto canvZ = new TCanvas ("canvZ" , "" , 800 , 800 );
238307 canvZ -> cd ();
239- nt -> Draw ("z>>h_z_IOTOF(500, -70, 70)" , "id >= 0 && id < 53568 " );
308+ nt -> Draw ("z>>h_z_IOTOF(500, -70, 70)" , "id >= 0 && id < 55488 " );
240309 canvZ -> SaveAs ("tf3digits_z.pdf" );
241310
242311 // dz distributions (difference between local position of digits and hits in x and z)
243312 auto canvdZ = new TCanvas ("canvdZ" , "" , 800 , 800 );
244313 canvdZ -> cd ();
245- nt -> Draw ("dz>>h_dz_ML(500, -0.05, 0.05)" , "id >= 0 && id < 53568 " );
314+ nt -> Draw ("dz>>h_dz_ML(500, -0.05, 0.05)" , "id >= 0 && id < 55488 " );
246315 canvdZ -> SaveAs ("tf3digits_dz.pdf" );
247316 canvdZ -> SaveAs ("tf3digits_dz.root" );
248317
249318 // distributions of differences between local positions of digits and hits in x and z
250319 auto canvdXdZ = new TCanvas ("canvdXdZ" , "" , 1600 , 800 );
251320 canvdXdZ -> Divide (2 , 1 );
252321 canvdXdZ -> cd (1 );
253- nt -> Draw ("dx:dz>>h_dx_vs_dz_ITOF(600 , -0.03 , 0.03, 600 , -0.03 , 0.03 )" , "id >= 0 && id < 1920" , "colz" );
322+ nt -> Draw ("dx:dz>>h_dx_vs_dz_ITOF(1000 , -0.05 , 0.05, 1000 , -0.05 , 0.05 )" , "id >= 0 && id < 1920" , "colz" );
254323 addTLines (0.01 );
255324 auto h = (TH2F * )gPad -> GetPrimitive ("h_dx_vs_dz_ITOF" );
256325 Info ("ITOF" , "RMS(dx)=%.1f mu" , h -> GetRMS (2 ) * 1e4 );
257326 Info ("ITOF" , "RMS(dz)=%.1f mu" , h -> GetRMS (1 ) * 1e4 );
258327 canvdXdZ -> cd (2 );
259- nt -> Draw ("dx:dz>>h_dx_vs_dz_OTOF(600 , -0.03 , 0.03, 600 , -0.03 , 0.03 )" , "id >= 1920 && id < 53568 " , "colz" );
328+ nt -> Draw ("dx:dz>>h_dx_vs_dz_OTOF(1000 , -0.05 , 0.05, 1000 , -0.05 , 0.05 )" , "id >= 1920 && id < 55488 " , "colz" );
260329 addTLines (0.01 );
261330 h = (TH2F * )gPad -> GetPrimitive ("h_dx_vs_dz_OTOF" );
262331 Info ("OTOF" , "RMS(dx)=%.1f mu" , h -> GetRMS (2 ) * 1e4 );
@@ -275,13 +344,80 @@ void CheckDigitsIOTOF(std::string digifile = "tf3digits.root", std::string hitfi
275344 Info ("ITOF" , "RMS(dxH)=%.1f mu" , h -> GetRMS (2 ) * 1e4 );
276345 Info ("ITOF" , "RMS(dzH)=%.1f mu" , h -> GetRMS (1 ) * 1e4 );
277346 canvdXdZHit -> cd (2 );
278- nt2 -> Draw ("dxH:dzH>>h_dxH_vs_dzH_OTOF(300, -0.03, 0.03, 300, -0.03, 0.03)" , "id >= 1920 && id < 53568 " , "colz" );
347+ nt2 -> Draw ("dxH:dzH>>h_dxH_vs_dzH_OTOF(300, -0.03, 0.03, 300, -0.03, 0.03)" , "id >= 1920 && id < 55488 " , "colz" );
279348 addTLines (0.01 );
280349 h = (TH2F * )gPad -> GetPrimitive ("h_dxH_vs_dzH_OTOF" );
281350 Info ("OTOF" , "RMS(dxH)=%.1f mu" , h -> GetRMS (2 ) * 1e4 );
282351 Info ("OTOF" , "RMS(dzH)=%.1f mu" , h -> GetRMS (1 ) * 1e4 );
283352 canvdXdZHit -> SaveAs ("trkdigits_dxH_vs_dzH.pdf" );
284353
285354 f -> Write ();
355+
356+ std ::string trackName [2 ] = {"Prm" , "Sec" };
357+ f -> mkdir ("PrmTrkLayer0" );
358+ f -> mkdir ("SecTrkLayer0" );
359+ f -> mkdir ("PrmTrkLayer1" );
360+ f -> mkdir ("SecTrkLayer1" );
361+ for (int layer = 0 ; layer < 2 ; ++ layer ) {
362+ for (int type = 0 ; type < 2 ; ++ type ) {
363+ f -> cd (Form ("%sTrkLayer%d" , trackName [type ].c_str (), layer ));
364+ hGenHitsEta [layer ][type ]-> Write ();
365+ hRecoDigitEta [layer ][type ]-> Write ();
366+ TH1F * hEffDigitEta = static_cast < TH1F * > (hRecoDigitEta [layer ][type ]-> Clone ("hEffDigitEta" ));
367+ hEffDigitEta -> Divide (hGenHitsEta [layer ][type ]);
368+ // Set errors
369+ for (int bin = 1 ; bin <= hEffDigitEta -> GetNbinsX (); ++ bin ) {
370+ double eff = hEffDigitEta -> GetBinContent (bin );
371+ double nGen = hGenHitsEta [layer ][type ]-> GetBinContent (bin );
372+ double err = 0.0 ;
373+ if (nGen > 0 ) {
374+ err = std ::sqrt (eff * (1 - eff ) / nGen );
375+ }
376+ hEffDigitEta -> SetBinError (bin , err );
377+ }
378+ hEffDigitEta -> SetTitle (";#eta;Digit Efficiency" );
379+ hEffDigitEta -> Write ();
380+ delete hEffDigitEta ;
381+ }
382+ }
383+
384+ // Plot avg fraction of charge collected by digits for
385+ // each hit vs eta, should reflect the digit efficiency
386+ for (int layer = 0 ; layer < 2 ; ++ layer ) {
387+ for (int type = 0 ; type < 2 ; ++ type ) {
388+
389+ f -> cd (Form ("%sTrkLayer%d" , trackName [type ].c_str (), layer ));
390+ TH2F * hFracCharge = new TH2F (Form ("hFracCharge_Layer%d_Type%d" , layer , type ), ";Fraction of charge collected by digits;Entries" , 40 , -2 , 2 , 200 , 0 , 1 );
391+
392+ for (const auto& hitDigitPair : hitDigitMap ) {
393+
394+ uint64_t hitKey = hitDigitPair .first ;
395+ int evtID = static_cast < int > (hitKey >> 32 );
396+ int hitIndex = static_cast < int > (hitKey & 0xFFFFFFFF );
397+ const auto& hit = (* hitArray [evtID ])[hitIndex ];
398+
399+ int hitLayer = gman -> getIOTOFLayer (hit .GetDetectorID ());
400+ if (hitLayer != layer ) continue ;
401+
402+ float energyLoss = hit .GetEnergyLoss (); // in GeV
403+ int charge = static_cast < int > (energyLoss * 2.77778e+08 );
404+
405+ auto& mcTrack = mcTracksPerEvent [evtID ]-> at (hit .GetTrackID ());
406+ bool isPrimary = mcTrack .isPrimary ();
407+ if ((isPrimary ? 0 : 1 ) != type ) continue ;
408+
409+ const auto& digitIndices = hitDigitPair .second ;
410+ float totalDigitCharge = 0.0f ;
411+ for (int digitIndex : digitIndices ) {
412+ totalDigitCharge += (* digArr )[digitIndex ].getCharge ();
413+ }
414+ float fracCharge = totalDigitCharge / charge ;
415+ hFracCharge -> Fill (mcTrack .GetEta (), fracCharge );
416+ }
417+ hFracCharge -> Write ();
418+ delete hFracCharge ;
419+ }
420+ }
421+
286422 f -> Close ();
287423}
0 commit comments