Skip to content

Commit 3c42af7

Browse files
committed
PWGLF: extend UPC timing QA and cuts
1 parent 94d8270 commit 3c42af7

1 file changed

Lines changed: 217 additions & 15 deletions

File tree

PWGLF/Tasks/Strangeness/derivedupcanalysis.cxx

Lines changed: 217 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,17 @@ using NeutronsMC = soa::Join<aod::ZDCNMCCollRefs, aod::ZDCNeutrons>;
6565

6666
using CascMCCoresFull = soa::Join<aod::CascMCCores, aod::CascMCCollRefs>;
6767

68-
using StraCollisonsFull = soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraStamps>;
69-
using StraCollisonFull = soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraStamps>::iterator;
68+
using StraCollisonsFull = soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraEvSelExtras, aod::StraStamps>;
69+
using StraCollisonFull = soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraEvSelExtras, aod::StraStamps>::iterator;
7070

71-
using StraCollisonsFullMC = soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraStamps, aod::StraCollLabels>;
72-
using StraCollisonFullMC = soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraStamps, aod::StraCollLabels>::iterator;
71+
using StraCollisonsFullMC = soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraEvSelExtras, aod::StraStamps, aod::StraCollLabels>;
72+
using StraCollisonFullMC = soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraEvSelExtras, aod::StraStamps, aod::StraCollLabels>::iterator;
7373

7474
using StraMCCollisionsFull = soa::Join<aod::StraMCCollisions, aod::StraMCCollMults>;
7575
using V0MCCoresFull = soa::Join<aod::V0MCCores, aod::V0MCCollRefs>;
7676

7777
struct Derivedupcanalysis {
7878
HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject};
79-
8079
// master analysis switches
8180
Configurable<bool> analyseK0Short{"analyseK0Short", true, "process K0Short-like candidates"};
8281
Configurable<bool> analyseLambda{"analyseLambda", true, "process Lambda-like candidates"};
@@ -168,6 +167,13 @@ struct Derivedupcanalysis {
168167
Configurable<float> ft0a{"ft0a", 100., "FT0A threshold"};
169168
Configurable<float> ft0c{"ft0c", 50., "FT0C threshold"};
170169
Configurable<float> zdc{"zdc", 1., "ZDC threshold"};
170+
Configurable<float> fddaTimeCut{"fddaTimeCut", -1., "FDDA timing cut (ns); negative: no cut"};
171+
Configurable<float> fddcTimeCut{"fddcTimeCut", -1., "FDDC timing cut (ns); negative: no cut"};
172+
Configurable<float> fv0aTimeCut{"fv0aTimeCut", -1., "FV0A timing cut (ns); negative: no cut"};
173+
Configurable<float> ft0aTimeCut{"ft0aTimeCut", -1., "FT0A timing cut (ns); negative: no cut"};
174+
Configurable<float> ft0cTimeCut{"ft0cTimeCut", -1., "FT0C timing cut (ns); negative: no cut"};
175+
Configurable<float> zdcTimeCut{"zdcTimeCut", 2., "ZDC timing cut (ns)"};
176+
Configurable<bool> requireZDCTiming{"requireZDCTiming", true, "require valid ZDC timing for gap-side selection"};
171177
Configurable<int> genGapSide{"genGapSide", 0, "0 -- A, 1 -- C, 2 -- double"};
172178
} upcCuts;
173179

@@ -213,6 +219,8 @@ struct Derivedupcanalysis {
213219
ConfigurableAxis axisFDDCampl{"axisFDDCampl", {100, 0.0f, 2000.0f}, "FDDCamplitude"};
214220
ConfigurableAxis axisZNAampl{"axisZNAampl", {100, 0.0f, 250.0f}, "ZNAamplitude"};
215221
ConfigurableAxis axisZNCampl{"axisZNCampl", {100, 0.0f, 250.0f}, "ZNCamplitude"};
222+
ConfigurableAxis axisFitTime{"axisFitTime", {166, -42.5f, 40.5f}, "FIT time (ns)"};
223+
ConfigurableAxis axisZdcTime{"axisZdcTime", {110, -12.5f, 10.0f}, "ZDC time (ns)"};
216224
} axisDetectors;
217225

218226
// for MC
@@ -268,7 +276,7 @@ struct Derivedupcanalysis {
268276
ConfigurableAxis axisOccupancy{"axisOccupancy", {VARIABLE_WIDTH, 0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 4500.0f, 6000.0f, 8000.0f, 10000.0f, 50000.0f}, "Occupancy"};
269277

270278
// UPC axes
271-
ConfigurableAxis axisSelGap{"axisSelGap", {4, -1.5, 2.5}, "Gap side"};
279+
ConfigurableAxis axisSelGap{"axisSelGap", {7, -1.5, 5.5}, "Gap side"};
272280

273281
// AP plot axes
274282
ConfigurableAxis axisAPAlpha{"axisAPAlpha", {220, -1.1f, 1.1f}, "V0 AP alpha"};
@@ -297,6 +305,8 @@ struct Derivedupcanalysis {
297305
ConfigurableAxis axisCtau{"axisCtau", {200, 0.0f, 20.0f}, "c x tau (cm)"};
298306

299307
static constexpr std::string_view kParticlenames[] = {"K0Short", "Lambda", "AntiLambda", "Xi", "AntiXi", "Omega", "AntiOmega"};
308+
static constexpr uint8_t kFT0TriggerBitIsActiveA = 5;
309+
static constexpr uint8_t kFT0TriggerBitIsActiveC = 6;
300310

301311
void setBits(std::bitset<kSelNum>& mask, std::initializer_list<int> selections)
302312
{
@@ -931,6 +941,22 @@ struct Derivedupcanalysis {
931941
histos.add("eventQA/hFT0", "hFT0", kTH3D, {axisDetectors.axisFT0Aampl, axisDetectors.axisFT0Campl, axisSelGap});
932942
histos.add("eventQA/hFDD", "hFDD", kTH3D, {axisDetectors.axisFDDAampl, axisDetectors.axisFDDCampl, axisSelGap});
933943
histos.add("eventQA/hZN", "hZN", kTH3D, {axisDetectors.axisZNAampl, axisDetectors.axisZNCampl, axisSelGap});
944+
histos.add("eventQA/hTimeFT0A", "hTimeFT0A", kTH2D, {axisDetectors.axisFitTime, axisSelGap});
945+
histos.add("eventQA/hTimeFT0C", "hTimeFT0C", kTH2D, {axisDetectors.axisFitTime, axisSelGap});
946+
histos.add("eventQA/hTimeFV0A", "hTimeFV0A", kTH2D, {axisDetectors.axisFitTime, axisSelGap});
947+
histos.add("eventQA/hTimeFDDA", "hTimeFDDA", kTH2D, {axisDetectors.axisFitTime, axisSelGap});
948+
histos.add("eventQA/hTimeFDDC", "hTimeFDDC", kTH2D, {axisDetectors.axisFitTime, axisSelGap});
949+
histos.add("eventQA/hTimeFT0APreSel", "hTimeFT0APreSel", kTH1D, {axisDetectors.axisFitTime});
950+
histos.add("eventQA/hTimeFT0CPreSel", "hTimeFT0CPreSel", kTH1D, {axisDetectors.axisFitTime});
951+
histos.add("eventQA/hTimeFV0APreSel", "hTimeFV0APreSel", kTH1D, {axisDetectors.axisFitTime});
952+
histos.add("eventQA/hTimeFDDAPreSel", "hTimeFDDAPreSel", kTH1D, {axisDetectors.axisFitTime});
953+
histos.add("eventQA/hTimeFDDCPreSel", "hTimeFDDCPreSel", kTH1D, {axisDetectors.axisFitTime});
954+
histos.add("eventQA/hFT0Time", "hFT0Time", kTH3D, {axisDetectors.axisFitTime, axisDetectors.axisFitTime, axisSelGap});
955+
histos.add("eventQA/hFDDTime", "hFDDTime", kTH3D, {axisDetectors.axisFitTime, axisDetectors.axisFitTime, axisSelGap});
956+
histos.add("eventQA/hZNTime", "hZNTime", kTH3D, {axisDetectors.axisZdcTime, axisDetectors.axisZdcTime, axisSelGap});
957+
histos.add("eventQA/hFT0TimePreSel", "hFT0TimePreSel", kTH2D, {axisDetectors.axisFitTime, axisDetectors.axisFitTime});
958+
histos.add("eventQA/hFDDTimePreSel", "hFDDTimePreSel", kTH2D, {axisDetectors.axisFitTime, axisDetectors.axisFitTime});
959+
histos.add("eventQA/hZNTimePreSel", "hZNTimePreSel", kTH2D, {axisDetectors.axisZdcTime, axisDetectors.axisZdcTime});
934960

935961
if (doprocessGenerated) {
936962
histos.add("eventQA/mc/hEventSelectionMC", "hEventSelectionMC", kTH3D, {{3, -0.5, 2.5}, axisNTracksPVeta1, axisGeneratorIds});
@@ -955,7 +981,7 @@ struct Derivedupcanalysis {
955981
histos.add("eventQA/mc/hNTracksPVeta1vsMCNParticlesEta10rec", "hNTracksPVeta1vsMCNParticlesEta10rec", kTH2D, {axisNTracksPVeta1, axisNTracksPVeta1});
956982
histos.add("eventQA/mc/hNTracksGlobalvstotalMultMCParticles", "hNTracksGlobalvstotalMultMCParticles", kTH2D, {axisNTracksGlobal, axisNchInvMass});
957983
histos.add("eventQA/mc/hNTracksPVeta1vstotalMultMCParticles", "hNTracksPVeta1vstotalMultMCParticles", kTH2D, {axisNTracksPVeta1, axisNchInvMass});
958-
histos.add("eventQA/hSelGapSideNoNeutrons", "Selected gap side (no n); Entries", kTH1D, {{5, -0.5, 4.5}});
984+
histos.add("eventQA/hSelGapSideNoNeutrons", "Selected gap side (no n); Entries", kTH1D, {axisSelGap});
959985
}
960986

961987
if (doprocessV0sMC) {
@@ -1050,12 +1076,164 @@ struct Derivedupcanalysis {
10501076
}
10511077

10521078
template <typename TCollision>
1053-
int getGapSide(TCollision const& collision)
1079+
int applyZDCTiming(int selGapSide, TCollision const& collision)
1080+
{
1081+
if (!upcCuts.requireZDCTiming) {
1082+
return selGapSide;
1083+
}
1084+
if (selGapSide == o2::aod::sgselector::SingleGapA ||
1085+
selGapSide == o2::aod::sgselector::SingleGapC ||
1086+
selGapSide == o2::aod::sgselector::DoubleGap) {
1087+
1088+
const float timeZNA = collision.timeZNA();
1089+
const float timeZNC = collision.timeZNC();
1090+
const float cut = upcCuts.zdcTimeCut;
1091+
1092+
auto isInvalidTime = [](float time) {
1093+
return !std::isfinite(time) || (std::abs(time) == 999.f);
1094+
};
1095+
1096+
const bool gapA = isInvalidTime(timeZNA) || (std::abs(timeZNA) > cut);
1097+
const bool gapC = isInvalidTime(timeZNC) || (std::abs(timeZNC) > cut);
1098+
const bool neutronA = !isInvalidTime(timeZNA) && (std::abs(timeZNA) < cut);
1099+
const bool neutronC = !isInvalidTime(timeZNC) && (std::abs(timeZNC) < cut);
1100+
1101+
if (selGapSide == o2::aod::sgselector::SingleGapA) { // 0nXn
1102+
if (!(gapA && neutronC)) {
1103+
selGapSide = o2::aod::sgselector::NoGap;
1104+
}
1105+
} else if (selGapSide == o2::aod::sgselector::SingleGapC) { // Xn0n
1106+
if (!(neutronA && gapC)) {
1107+
selGapSide = o2::aod::sgselector::NoGap;
1108+
}
1109+
} else if (selGapSide == o2::aod::sgselector::DoubleGap) {
1110+
if (!(gapA && gapC)) {
1111+
selGapSide = o2::aod::sgselector::NoGap;
1112+
}
1113+
}
1114+
}
1115+
1116+
return selGapSide;
1117+
}
1118+
1119+
bool isInvalidTime(float time) const
1120+
{
1121+
return !std::isfinite(time) || (std::abs(time) >= 998.f);
1122+
}
1123+
1124+
bool isTimingCutEnabled(float cut) const
1125+
{
1126+
return cut >= 0.f;
1127+
}
1128+
1129+
bool isTimingGap(float time, float cut) const
1130+
{
1131+
return isInvalidTime(time) || (std::abs(time) > cut);
1132+
}
1133+
1134+
bool isTimingActivity(float time, float cut) const
1135+
{
1136+
return !isInvalidTime(time) && (std::abs(time) < cut);
1137+
}
1138+
1139+
bool hasFT0Activity(uint8_t triggerMask, uint8_t bit) const
10541140
{
1055-
int selGapSide = sgSelector.trueGap(collision, upcCuts.fv0a, upcCuts.ft0a, upcCuts.ft0c, upcCuts.zdc);
1141+
return (triggerMask & (static_cast<uint8_t>(1u) << bit)) != 0;
1142+
}
1143+
1144+
template <typename TCollision>
1145+
int applyFITTiming(int selGapSide, TCollision const& collision)
1146+
{
1147+
if (selGapSide != o2::aod::sgselector::SingleGapA &&
1148+
selGapSide != o2::aod::sgselector::SingleGapC &&
1149+
selGapSide != o2::aod::sgselector::DoubleGap) {
1150+
return selGapSide;
1151+
}
1152+
1153+
const bool useFDDA = isTimingCutEnabled(upcCuts.fddaTimeCut);
1154+
const bool useFDDC = isTimingCutEnabled(upcCuts.fddcTimeCut);
1155+
const bool useFV0A = isTimingCutEnabled(upcCuts.fv0aTimeCut);
1156+
const bool useFT0A = isTimingCutEnabled(upcCuts.ft0aTimeCut);
1157+
const bool useFT0C = isTimingCutEnabled(upcCuts.ft0cTimeCut);
1158+
1159+
if (!(useFDDA || useFDDC || useFV0A || useFT0A || useFT0C)) {
1160+
return selGapSide;
1161+
}
1162+
1163+
const bool ft0ActiveA = hasFT0Activity(collision.triggerMaskFT0(), kFT0TriggerBitIsActiveA);
1164+
const bool ft0ActiveC = hasFT0Activity(collision.triggerMaskFT0(), kFT0TriggerBitIsActiveC);
1165+
1166+
const bool gapFDDA = !useFDDA || isTimingGap(collision.timeFDDA(), upcCuts.fddaTimeCut);
1167+
const bool actFDDA = !useFDDA || isTimingActivity(collision.timeFDDA(), upcCuts.fddaTimeCut);
1168+
const bool gapFDDC = !useFDDC || isTimingGap(collision.timeFDDC(), upcCuts.fddcTimeCut);
1169+
const bool actFDDC = !useFDDC || isTimingActivity(collision.timeFDDC(), upcCuts.fddcTimeCut);
1170+
const bool gapFV0A = !useFV0A || isTimingGap(collision.timeFV0A(), upcCuts.fv0aTimeCut);
1171+
const bool actFV0A = !useFV0A || isTimingActivity(collision.timeFV0A(), upcCuts.fv0aTimeCut);
1172+
const bool gapFT0A = !useFT0A || !ft0ActiveA || isTimingGap(collision.timeFT0A(), upcCuts.ft0aTimeCut);
1173+
const bool actFT0A = !useFT0A || (ft0ActiveA && isTimingActivity(collision.timeFT0A(), upcCuts.ft0aTimeCut));
1174+
const bool gapFT0C = !useFT0C || !ft0ActiveC || isTimingGap(collision.timeFT0C(), upcCuts.ft0cTimeCut);
1175+
const bool actFT0C = !useFT0C || (ft0ActiveC && isTimingActivity(collision.timeFT0C(), upcCuts.ft0cTimeCut));
1176+
1177+
if (selGapSide == o2::aod::sgselector::SingleGapA) {
1178+
if (!(gapFV0A && gapFDDA && gapFT0A && actFDDC && actFT0C)) {
1179+
selGapSide = o2::aod::sgselector::NoGap;
1180+
}
1181+
} else if (selGapSide == o2::aod::sgselector::SingleGapC) {
1182+
if (!(actFV0A && actFDDA && actFT0A && gapFDDC && gapFT0C)) {
1183+
selGapSide = o2::aod::sgselector::NoGap;
1184+
}
1185+
} else if (selGapSide == o2::aod::sgselector::DoubleGap) {
1186+
if (!(gapFV0A && gapFDDA && gapFT0A && gapFDDC && gapFT0C)) {
1187+
selGapSide = o2::aod::sgselector::NoGap;
1188+
}
1189+
}
1190+
10561191
return selGapSide;
10571192
}
10581193

1194+
template <typename TCollision>
1195+
int getGapSide(TCollision const& collision)
1196+
{
1197+
int selGapSide = o2::aod::sgselector::NoGap;
1198+
selGapSide = sgSelector.trueGap(collision, upcCuts.fv0a, upcCuts.ft0a, upcCuts.ft0c, upcCuts.zdc);
1199+
selGapSide = applyZDCTiming(selGapSide, collision);
1200+
return applyFITTiming(selGapSide, collision);
1201+
}
1202+
float sanitizeZdcTime(float time) const
1203+
{
1204+
if (!std::isfinite(time)) {
1205+
return -12.f;
1206+
}
1207+
if (std::abs(time) >= 998.f) {
1208+
return -11.f;
1209+
}
1210+
return time;
1211+
}
1212+
1213+
float sanitizeFITTime(float time) const
1214+
{
1215+
if (!std::isfinite(time)) {
1216+
return -42.f;
1217+
}
1218+
if (std::abs(time) >= 998.f) {
1219+
return -41.f;
1220+
}
1221+
return time;
1222+
}
1223+
1224+
template <typename TCollision>
1225+
void fillPreSelTimingHistograms(TCollision const& collision)
1226+
{
1227+
histos.fill(HIST("eventQA/hFT0TimePreSel"), sanitizeFITTime(collision.timeFT0A()), sanitizeFITTime(collision.timeFT0C()));
1228+
histos.fill(HIST("eventQA/hFDDTimePreSel"), sanitizeFITTime(collision.timeFDDA()), sanitizeFITTime(collision.timeFDDC()));
1229+
histos.fill(HIST("eventQA/hZNTimePreSel"), sanitizeZdcTime(collision.timeZNA()), sanitizeZdcTime(collision.timeZNC()));
1230+
histos.fill(HIST("eventQA/hTimeFT0APreSel"), sanitizeFITTime(collision.timeFT0A()));
1231+
histos.fill(HIST("eventQA/hTimeFT0CPreSel"), sanitizeFITTime(collision.timeFT0C()));
1232+
histos.fill(HIST("eventQA/hTimeFV0APreSel"), sanitizeFITTime(collision.timeFV0A()));
1233+
histos.fill(HIST("eventQA/hTimeFDDAPreSel"), sanitizeFITTime(collision.timeFDDA()));
1234+
histos.fill(HIST("eventQA/hTimeFDDCPreSel"), sanitizeFITTime(collision.timeFDDC()));
1235+
}
1236+
10591237
template <typename TCollision>
10601238
void fillHistogramsQA(TCollision const& collision, int const& gap)
10611239
{
@@ -1099,6 +1277,18 @@ struct Derivedupcanalysis {
10991277
histos.fill(HIST("eventQA/hZN"), -2, -2, gap);
11001278
else if (zna == -999 || znc == -999)
11011279
LOG(warning) << "Only one ZDC signal is -999";
1280+
else {
1281+
histos.fill(HIST("eventQA/hZN"), zna, znc, gap);
1282+
}
1283+
1284+
histos.fill(HIST("eventQA/hFT0Time"), sanitizeFITTime(collision.timeFT0A()), sanitizeFITTime(collision.timeFT0C()), gap);
1285+
histos.fill(HIST("eventQA/hFDDTime"), sanitizeFITTime(collision.timeFDDA()), sanitizeFITTime(collision.timeFDDC()), gap);
1286+
histos.fill(HIST("eventQA/hZNTime"), sanitizeZdcTime(collision.timeZNA()), sanitizeZdcTime(collision.timeZNC()), gap);
1287+
histos.fill(HIST("eventQA/hTimeFT0A"), sanitizeFITTime(collision.timeFT0A()), gap);
1288+
histos.fill(HIST("eventQA/hTimeFT0C"), sanitizeFITTime(collision.timeFT0C()), gap);
1289+
histos.fill(HIST("eventQA/hTimeFV0A"), sanitizeFITTime(collision.timeFV0A()), gap);
1290+
histos.fill(HIST("eventQA/hTimeFDDA"), sanitizeFITTime(collision.timeFDDA()), gap);
1291+
histos.fill(HIST("eventQA/hTimeFDDC"), sanitizeFITTime(collision.timeFDDC()), gap);
11021292
}
11031293

11041294
template <typename TCollision>
@@ -1868,13 +2058,13 @@ struct Derivedupcanalysis {
18682058
}
18692059
}
18702060

1871-
if (evSels.studyUPConly && (selGapSide != static_cast<int>(upcCuts.genGapSide)))
1872-
continue;
1873-
1874-
++nCollisions;
1875-
atLeastOne = true;
2061+
const bool passStd = !evSels.studyUPConly || (selGapSide == static_cast<int>(upcCuts.genGapSide));
2062+
if (passStd) {
2063+
++nCollisions;
2064+
atLeastOne = true;
2065+
}
18762066

1877-
if (biggestNContribs < collision.multPVTotalContributors()) {
2067+
if (passStd && biggestNContribs < collision.multPVTotalContributors()) {
18782068
biggestNContribs = collision.multPVTotalContributors();
18792069
if (static_cast<int>(upcCuts.genGapSide) == 0) {
18802070
ft0ampl = collision.totalFT0AmplitudeC();
@@ -1946,6 +2136,9 @@ struct Derivedupcanalysis {
19462136
continue;
19472137
} // event is accepted
19482138

2139+
if (collision.isUPC()) {
2140+
fillPreSelTimingHistograms(collision);
2141+
}
19492142
histos.fill(HIST("eventQA/hRawGapSide"), collision.gapSide());
19502143

19512144
int selGapSide = collision.isUPC() ? getGapSide(collision) : -1;
@@ -2002,6 +2195,9 @@ struct Derivedupcanalysis {
20022195
continue;
20032196
} // event is accepted
20042197

2198+
if (collision.isUPC()) {
2199+
fillPreSelTimingHistograms(collision);
2200+
}
20052201
histos.fill(HIST("eventQA/hRawGapSide"), collision.gapSide());
20062202

20072203
int selGapSide = collision.isUPC() ? getGapSide(collision) : -1;
@@ -2087,6 +2283,9 @@ struct Derivedupcanalysis {
20872283
continue;
20882284
} // event is accepted
20892285

2286+
if (collision.isUPC()) {
2287+
fillPreSelTimingHistograms(collision);
2288+
}
20902289
histos.fill(HIST("eventQA/hRawGapSide"), collision.gapSide());
20912290

20922291
int selGapSide = collision.isUPC() ? getGapSide(collision) : -1;
@@ -2139,6 +2338,9 @@ struct Derivedupcanalysis {
21392338
continue;
21402339
} // event is accepted
21412340

2341+
if (collision.isUPC()) {
2342+
fillPreSelTimingHistograms(collision);
2343+
}
21422344
histos.fill(HIST("eventQA/hRawGapSide"), collision.gapSide());
21432345

21442346
int selGapSide = collision.isUPC() ? getGapSide(collision) : -1;

0 commit comments

Comments
 (0)