@@ -95,9 +95,9 @@ struct OnTheFlyTofPid {
9595 Configurable<float > outerTOFRadius{" outerTOFRadius" , 80 , " barrel outer TOF radius (cm)" };
9696 Configurable<float > innerTOFLength{" innerTOFLength" , 124 , " barrel inner TOF length (cm)" };
9797 Configurable<float > outerTOFLength{" outerTOFLength" , 250 , " barrel outer TOF length (cm)" };
98- Configurable<float > innerTOFPixelArea{ " innerTOFPixelArea " , 1.0 , " barrel inner TOF pixel area (mm^2 )" };
98+ Configurable<std::array< float , 2 >> innerTOFPixelDimension{ " innerTOFPixelDimension " , { 0.1 , 0.1 } , " barrel inner TOF pixel dimension in Z and RPhi (cm )" };
9999 Configurable<float > innerTOFFractionOfInactiveArea{" innerTOFFractionOfInactiveArea" , 0 .f , " barrel inner TOF fraction of inactive area" };
100- Configurable<float > outerTOFPixelArea{ " outerTOFPixelArea " , 25.0 , " barrel outer TOF pixel area (mm^2 )" };
100+ Configurable<std::array< float , 2 >> outerTOFPixelDimension{ " outerTOFPixelDimension " , { 0.1 , 0.1 } , " barrel outer TOF pixel dimension in Z and RPhi (cm )" };
101101 Configurable<float > outerTOFFractionOfInactiveArea{" outerTOFFractionOfInactiveArea" , 0 .f , " barrel outer TOF fraction of inactive area" };
102102 Configurable<float > innerTOFTimeReso{" innerTOFTimeReso" , 20 , " barrel inner TOF time error (ps)" };
103103 Configurable<float > outerTOFTimeReso{" outerTOFTimeReso" , 20 , " barrel outer TOF time error (ps)" };
@@ -189,8 +189,6 @@ struct OnTheFlyTofPid {
189189 histos.add (" h2dEventTimeres" , " h2dEventTimeres" , kTH2F , {axisdNdeta, {300 , 0 , 300 , " resolution" }});
190190 listEfficiency.setObject (new THashList);
191191 listEfficiency->Add (new TEfficiency (" effEventTime" , " effEventTime" , plotsConfig.nBinsMult , 0 .0f , plotsConfig.maxMultRange ));
192- listEfficiency->Add (new TEfficiency (" MapInnerTOF" , " MapInnerTOF" , 100 , -simConfig.innerTOFLength / 2 , simConfig.innerTOFLength / 2 , 100 , 0 , simConfig.innerTOFRadius * M_PI_2));
193- listEfficiency->Add (new TEfficiency (" MapOuterTOF" , " MapOuterTOF" , 100 , -simConfig.outerTOFLength / 2 , simConfig.outerTOFLength / 2 , 100 , 0 , simConfig.outerTOFRadius * M_PI_2));
194192
195193 const AxisSpec axisMomentum{static_cast <int >(plotsConfig.nBinsP ), 0 .0f , +10 .0f , " #it{p} (GeV/#it{c})" };
196194 const AxisSpec axisRigidity{static_cast <int >(plotsConfig.nBinsP ), 0 .0f , +10 .0f , " #it{p} / |#it{z}| (GeV/#it{c})" };
@@ -204,12 +202,14 @@ struct OnTheFlyTofPid {
204202 histos.add (" iTOF/h2dTrackLengthInnerVsPt" , " h2dTrackLengthInnerVsPt" , kTH2F , {axisMomentumSmall, axisTrackLengthInner});
205203 histos.add (" iTOF/h2dTrackLengthInnerRecoVsPt" , " h2dTrackLengthInnerRecoVsPt" , kTH2F , {axisMomentumSmall, axisTrackLengthInner});
206204 histos.add (" iTOF/h2dDeltaTrackLengthInnerVsPt" , " h2dDeltaTrackLengthInnerVsPt" , kTH2F , {axisMomentumSmall, axisTrackDeltaLength});
205+ histos.add (" iTOF/h2HitMap" , " h2HitMap" , kTH2F , {{100 , -simConfig.innerTOFLength / 2 , simConfig.innerTOFLength / 2 }, {100 , 0 , simConfig.innerTOFRadius * 2 * M_PI}});
207206
208207 histos.add (" oTOF/h2dVelocityVsMomentumOuter" , " h2dVelocityVsMomentumOuter" , kTH2F , {axisMomentum, axisVelocity});
209208 histos.add (" oTOF/h2dVelocityVsRigidityOuter" , " h2dVelocityVsRigidityOuter" , kTH2F , {axisRigidity, axisVelocity});
210209 histos.add (" oTOF/h2dTrackLengthOuterVsPt" , " h2dTrackLengthOuterVsPt" , kTH2F , {axisMomentumSmall, axisTrackLengthOuter});
211210 histos.add (" oTOF/h2dTrackLengthOuterRecoVsPt" , " h2dTrackLengthOuterRecoVsPt" , kTH2F , {axisMomentumSmall, axisTrackLengthOuter});
212211 histos.add (" oTOF/h2dDeltaTrackLengthOuterVsPt" , " h2dDeltaTrackLengthOuterVsPt" , kTH2F , {axisMomentumSmall, axisTrackDeltaLength});
212+ histos.add (" oTOF/h2HitMap" , " h2HitMap" , kTH2F , {{100 , -simConfig.outerTOFLength / 2 , simConfig.outerTOFLength / 2 }, {100 , 0 , simConfig.outerTOFRadius * 2 * M_PI}});
213213
214214 const AxisSpec axisPt{static_cast <int >(plotsConfig.nBinsP ), 0 .0f , +4 .0f , " #it{p}_{T} (GeV/#it{c})" };
215215 const AxisSpec axisEta{static_cast <int >(plotsConfig.nBinsEta ), -2 .0f , +2 .0f , " #eta" };
@@ -256,33 +256,39 @@ struct OnTheFlyTofPid {
256256 private:
257257 const float layerRadius;
258258 const float layerLength;
259- const float pixelArea;
259+ const float pixelDimensionZ;
260+ const float pixelDimensionRPhi;
260261 const float fractionInactive;
261262 const float magField;
262263
263- float pixelSize;
264- float circumference;
265- float zLength;
266- int nPixelsPhi;
267- int nPixelsZ;
268- float inactiveBorderPhi;
269- float inactiveBorderZ;
264+ // TH2F* hHitMapInPixel = nullptr;
265+ // TH2F* hHitMap = nullptr;
266+ TAxis* axisZ = nullptr ;
267+ TAxis* axisRPhi = nullptr ;
268+ TAxis* axisInPixelZ = nullptr ;
269+ TAxis* axisInPixelRPhi = nullptr ;
270270
271271 public:
272- TOFLayerEfficiency (float r, float l, float pA , float fIA , float m)
273- : layerRadius(r), layerLength(l), pixelArea(pA ), fractionInactive(fIA ), magField(m)
272+ TOFLayerEfficiency (float r, float l, std::array< float , 2 > pDimensions , float fIA , float m)
273+ : layerRadius(r), layerLength(l), pixelDimensionZ(pDimensions[ 0 ]), pixelDimensionRPhi(pDimensions[ 1 ] ), fractionInactive(fIA ), magField(m)
274274 {
275275 // Assuming square pixels for simplicity
276- pixelSize = std::sqrt (pA);
277- circumference = 2 .0f * M_PI * layerRadius * 10 .0f ; // convert cm to mm
278- zLength = layerLength * 10 .0f ; // convert cm to mm
279- nPixelsPhi = static_cast <int >(circumference / pixelSize);
280- nPixelsZ = static_cast <int >(zLength / pixelSize);
281- inactiveBorderPhi = pixelSize * std::sqrt (fractionInactive);
282- inactiveBorderZ = pixelSize * std::sqrt (fractionInactive);
276+ const float circumference = 2 .0f * M_PI * layerRadius;
277+ axisZ = new TAxis (static_cast <int >(layerLength / pixelDimensionZ), -layerLength / 2 , layerLength);
278+ axisRPhi = new TAxis (static_cast <int >(circumference / pixelDimensionRPhi), 0 .f , circumference);
279+
280+ const float inactiveBorderRPhi = pixelDimensionRPhi * std::sqrt (fractionInactive);
281+ const float inactiveBorderZ = pixelDimensionZ * std::sqrt (fractionInactive);
282+ const double arrayRPhi[4 ] = {0 .f , inactiveBorderRPhi, pixelDimensionRPhi - inactiveBorderRPhi, pixelDimensionRPhi};
283+ axisInPixelRPhi = new TAxis (3 , arrayRPhi);
284+ const double arrayZ[4 ] = {0 .f , inactiveBorderZ, pixelDimensionZ - inactiveBorderZ, pixelDimensionZ};
285+ axisInPixelZ = new TAxis (3 , arrayZ);
286+
287+ // hHitMap = new TH2F(Form("hHitMap_R%.0f", layerRadius), "HitMap;z (cm); r#phi (cm)", 1000, -1000, 1000, 1000, -1000, 1000);
288+ // hHitMapInPixel = new TH2F(Form("hHitMapInPixel_R%.0f", layerRadius), "HitMapInPixel;z (cm); r#phi (cm)", 1000, -10, 10, 1000, -10, 10);
283289 }
284290
285- bool isInTOFActiveArea (std::array<float , 3 > hitPosition = { 0 . 0f , 0 . 0f , 0 . 0f } )
291+ bool isInTOFActiveArea (std::array<float , 3 > hitPosition)
286292 {
287293 if (fractionInactive <= 0 .0f ) {
288294 return true ;
@@ -293,113 +299,92 @@ struct OnTheFlyTofPid {
293299
294300 // Convert 3D position to cylindrical coordinates for area calculation
295301 const float phi = std::atan2 (hitPosition[1 ], hitPosition[0 ]);
302+ const float rphi = phi * layerRadius;
296303 const float z = hitPosition[2 ];
297304 const float r = std::sqrt (hitPosition[0 ] * hitPosition[0 ] + hitPosition[1 ] * hitPosition[1 ]);
298305
299306 // Check if hit is within layer geometric acceptance
300- if (std::abs (z) > layerLength / 2 .0f || r < layerRadius - 1 .0f || r > layerRadius + 1 .0f ) {
307+ if (std::abs (layerRadius - r) > 10 .f ) {
308+ LOG (warning) << " Hit out of TOF layer acceptance: r=" << r << " cm with respect to the layer radius " << layerRadius;
309+ return false ;
310+ }
311+ if (std::abs (z) > layerLength / 2 .0f ) {
312+ LOG (warning) << " Hit out of TOF layer acceptance: z=" << z << " cm with respect to the layer length " << layerLength;
301313 return false ;
302314 }
303315
304- // Convert hit position to pixel coordinates
305- const float phiNorm = (phi + M_PI) / (2 .0f * M_PI); // normalize phi to [0,1]
306- const float zNorm = (z * 10 .0f + zLength / 2 .0f ) / zLength; // normalize z to [0,1]
316+ const int pixelIndexPhi = axisRPhi->FindBin (rphi);
317+ const int pixelIndexZ = axisZ->FindBin (z);
307318
308- const int pixelPhi = static_cast <int >(phiNorm * nPixelsPhi) % nPixelsPhi;
309- const int pixelZ = static_cast <int >(zNorm * nPixelsZ);
319+ // LOG(info) << "Hit pixel " << pixelIndexPhi << "/" << nPixelsRPhi << " and " << pixelIndexZ << "/" << nPixelsZ;
310320
311- // Check if pixel is valid
312- if (pixelZ < 0 || pixelZ >= nPixelsZ) {
313- LOG (fatal) << " Pixel Z index out of bounds: " << pixelZ << " (nPixelsZ: " << nPixelsZ << " )" ;
314- }
315- if (pixelPhi < 0 || pixelPhi >= nPixelsPhi) {
316- LOG (fatal) << " Pixel Phi index out of bounds: " << pixelPhi << " (nPixelsPhi: " << nPixelsPhi << " )" ;
317- }
318- // Determine if the pixel is active based on the fraction of inactive area
319- const float phiPosInPixel = std::abs (phiNorm - pixelPhi);
320- const float zPosInPixel = std::abs (zNorm - pixelZ);
321- if (phiPosInPixel > inactiveBorderPhi) {
322- return false ;
323- }
324- if (zPosInPixel > inactiveBorderZ) {
321+ if (pixelIndexPhi <= 0 || pixelIndexPhi > axisRPhi->GetNbins () || pixelIndexZ <= 0 || pixelIndexZ > axisZ->GetNbins ()) {
322+ // LOG(info) << "Hit out of TOF layer pixel range: pixelIndexPhi=" << pixelIndexPhi << ", pixelIndexZ=" << pixelIndexZ;
325323 return false ;
326324 }
325+ // Calculate local position within the pixel
326+ const float localRPhi = (rphi - axisRPhi->GetBinCenter (pixelIndexPhi));
327+ const float localZ = (z - axisZ->GetBinCenter (pixelIndexZ));
328+
329+ // The difference between the hit and the pixel position cannot be greater than the size of the pixel
330+ if (std::abs (localRPhi - axisRPhi->GetBinCenter (pixelIndexPhi)) > axisRPhi->GetBinWidth (pixelIndexPhi)) {
331+ // LOG(warning) << "Local hit difference in phi is bigger than the pixel size";
332+ }
333+ if (std::abs (localZ - axisZ->GetBinCenter (pixelIndexZ)) > axisZ->GetBinWidth (pixelIndexZ)) {
334+ // LOG(warning) << "Local hit difference in z is bigger than the pixel size";
335+ }
336+ switch (axisInPixelRPhi->FindBin (localRPhi)) {
337+ case 1 :
338+ case 3 :
339+ return false ;
340+ }
341+ switch (axisInPixelZ->FindBin (localZ)) {
342+ case 1 :
343+ case 3 :
344+ return false ;
345+ }
346+ // hHitMap->Fill(z, rphi);
347+ // hHitMapInPixel->Fill(localZ, localRPhi);
348+ // if (static_cast<int>(hHitMapInPixel->GetEntries()) % 100000 == 0) {
349+ // hHitMap->SaveAs(Form("/tmp/%s.png", hHitMap->GetName()));
350+ // hHitMapInPixel->SaveAs(Form("/tmp/%s.png", hHitMapInPixel->GetName()));
351+ // }
327352 return true ;
328353 }
329354
330- // / Utility function to estimate hit position on a TOF layer
331- // / \param track the track parameters
332- // / \param radius the radius of the TOF layer
333- // / \return estimated hit position [x, y, z] in cm
334- std::array<float , 3 > estimateHitPosition (const o2::track::TrackParCov& track)
335- {
336- std::array<float , 3 > hitPosition = {0 .0f , 0 .0f , 0 .0f };
337- // Get the track circle parameters
338- o2::math_utils::CircleXYf_t trcCircle;
339- float sna, csa;
340- track.getCircleParams (magField, trcCircle, sna, csa);
341-
342- // Calculate intersection points with the cylinder of given radius
343- const float centerDistance = std::hypot (trcCircle.xC , trcCircle.yC );
344-
345- if (centerDistance < trcCircle.rC + layerRadius && centerDistance > std::fabs (trcCircle.rC - layerRadius)) {
346- // Calculate intersection point using the same logic as computeTrackLength
347- const float ux = trcCircle.xC / centerDistance;
348- const float uy = trcCircle.yC / centerDistance;
349- const float vx = -uy;
350- const float vy = +ux;
351- const float radical = (centerDistance * centerDistance - trcCircle.rC * trcCircle.rC + layerRadius * layerRadius) / (2 .0f * centerDistance);
352- const float displace = (0 .5f / centerDistance) * std::sqrt (
353- (-centerDistance + trcCircle.rC - layerRadius) *
354- (-centerDistance - trcCircle.rC + layerRadius) *
355- (-centerDistance + trcCircle.rC + layerRadius) *
356- (centerDistance + trcCircle.rC + layerRadius));
357-
358- const float point1[2 ] = {radical * ux + displace * vx, radical * uy + displace * vy};
359- const float point2[2 ] = {radical * ux - displace * vx, radical * uy - displace * vy};
360-
361- // Choose the correct intersection point based on momentum direction
362- std::array<float , 3 > mom;
363- track.getPxPyPzGlo (mom);
364- const float scalarProduct1 = point1[0 ] * mom[0 ] + point1[1 ] * mom[1 ];
365- const float scalarProduct2 = point2[0 ] * mom[0 ] + point2[1 ] * mom[1 ];
366-
367- if (scalarProduct1 > scalarProduct2) {
368- hitPosition[0 ] = point1[0 ];
369- hitPosition[1 ] = point1[1 ];
370- } else {
371- hitPosition[0 ] = point2[0 ];
372- hitPosition[1 ] = point2[1 ];
373- }
374-
375- // Estimate Z position using the track slope
376- float trackLength = computeTrackLength (track, layerRadius, magField);
377- if (trackLength > 0 ) {
378- hitPosition[2 ] = track.getZ () + trackLength * track.getTgl ();
379- }
380- }
381- return hitPosition;
382- }
383-
384355 // / Check if a track hits the active area (convenience function)
385356 // / \param track the track parameters for automatic hit position calculation
386357 // / \return true if the hit is in the active area
387358 bool isTrackInActiveArea (const o2::track::TrackParCov& track)
388359 {
389- auto hitPosition = estimateHitPosition (track);
390- return isInTOFActiveArea (hitPosition);
360+ if (fractionInactive <= 0 .f ) {
361+ return true ;
362+ }
363+ float x, y, z;
364+ if (!track.getXatLabR (layerRadius, x, magField)) {
365+ LOG (warning) << " Could not propagate track to TOF layer at radius " << layerRadius << " cm" ;
366+ return false ;
367+ }
368+ bool b;
369+ ROOT::Math::PositionVector3D hit = track.getXYZGloAt (x, magField, b);
370+ if (!b) {
371+ LOG (warning) << " Could not get hit position at radius " << layerRadius << " cm" ;
372+ return false ;
373+ }
374+ hit.GetCoordinates (x, y, z);
375+ return isInTOFActiveArea (std::array<float , 3 >{x, y, z});
391376 }
392377 };
393378
394379 bool isInInnerTOFActiveArea (const o2::track::TrackParCov& track)
395380 {
396- static TOFLayerEfficiency innerTOFLayer (simConfig.innerTOFRadius , simConfig.innerTOFLength , simConfig.innerTOFPixelArea , simConfig.innerTOFFractionOfInactiveArea , simConfig.magneticField );
381+ static TOFLayerEfficiency innerTOFLayer (simConfig.innerTOFRadius , simConfig.innerTOFLength , simConfig.innerTOFPixelDimension , simConfig.innerTOFFractionOfInactiveArea , simConfig.magneticField );
397382 return innerTOFLayer.isTrackInActiveArea (track);
398383 }
399384
400385 bool isInOuterTOFActiveArea (const o2::track::TrackParCov& track)
401386 {
402- static TOFLayerEfficiency outerTOFLayer (simConfig.outerTOFRadius , simConfig.outerTOFLength , simConfig.outerTOFPixelArea , simConfig.outerTOFFractionOfInactiveArea , simConfig.magneticField );
387+ static TOFLayerEfficiency outerTOFLayer (simConfig.outerTOFRadius , simConfig.outerTOFLength , simConfig.outerTOFPixelDimension , simConfig.outerTOFFractionOfInactiveArea , simConfig.magneticField );
403388 return outerTOFLayer.isTrackInActiveArea (track);
404389 }
405390
@@ -656,18 +641,22 @@ struct OnTheFlyTofPid {
656641 }
657642
658643 // Check if the track hit a sensitive area of the TOF
659- const bool activeInnerTOF = true ; // isInInnerTOFActiveArea(o2track);
660- float x = 0 .f ;
661- o2track.getXatLabR (simConfig.innerTOFRadius , x, simConfig.magneticField .value ); // to get phi at inner TOF radius
662- static_cast <TEfficiency*>(listEfficiency->At (1 ))->Fill (o2track.getZAt (x, simConfig.magneticField .value ), simConfig.innerTOFRadius * o2track.getPhiAt (x, simConfig.magneticField .value ), activeInnerTOF);
644+ const bool activeInnerTOF = isInInnerTOFActiveArea (o2track);
663645 if (!activeInnerTOF) {
664646 trackLengthInnerTOF = -999 .f ;
647+ } else {
648+ float x = 0 .f ;
649+ o2track.getXatLabR (simConfig.innerTOFRadius , x, simConfig.magneticField );
650+ histos.fill (HIST (" iTOF/h2HitMap" ), o2track.getZAt (x, simConfig.magneticField ), simConfig.innerTOFRadius * o2track.getPhiAt (x, simConfig.magneticField ));
665651 }
652+
666653 const bool activeOuterTOF = isInOuterTOFActiveArea (o2track);
667- o2track.getXatLabR (simConfig.outerTOFRadius , x, simConfig.magneticField .value ); // to get phi at outer TOF radius
668- static_cast <TEfficiency*>(listEfficiency->At (2 ))->Fill (o2track.getZAt (x, simConfig.magneticField .value ), simConfig.outerTOFRadius * o2track.getPhiAt (x, simConfig.magneticField .value ), activeOuterTOF);
669654 if (!activeOuterTOF) {
670655 trackLengthOuterTOF = -999 .f ;
656+ } else {
657+ float x = 0 .f ;
658+ o2track.getXatLabR (simConfig.outerTOFRadius , x, simConfig.magneticField );
659+ histos.fill (HIST (" oTOF/h2HitMap" ), o2track.getZAt (x, simConfig.magneticField ), simConfig.outerTOFRadius * o2track.getPhiAt (x, simConfig.magneticField ));
671660 }
672661
673662 // get mass to calculate velocity
0 commit comments