Skip to content

Commit fc27b45

Browse files
authored
[Common] configs for special checks for light ion runs (#12494)
1 parent 41780c4 commit fc27b45

File tree

1 file changed

+183
-27
lines changed

1 file changed

+183
-27
lines changed

Common/Tools/EventSelectionTools.h

Lines changed: 183 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ struct evselConfigurables : o2::framework::ConfigurableGroup {
106106
o2::framework::Configurable<float> confEpsilonVzDiffVetoInROF{"EpsilonVzDiffVetoInROF", 0.3, "Minumum distance to nearby collisions along z inside this ITS ROF, cm"}; // o2-linter: disable=name/configurable (temporary fix)
107107
o2::framework::Configurable<bool> confUseWeightsForOccupancyVariable{"UseWeightsForOccupancyEstimator", 1, "Use or not the delta-time weights for the occupancy estimator"}; // o2-linter: disable=name/configurable (temporary fix)
108108
o2::framework::Configurable<int> confNumberOfOrbitsPerTF{"NumberOfOrbitsPerTF", -1, "Number of orbits per Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix)
109+
110+
// configurables for light-ion event selection (testing mode)
111+
o2::framework::Configurable<int> confLightIonsAlternativeBcMatching{"TestAlternativeBcMatching", 0, "0 - use standard matching, 1 - try alternative for light ions"}; // o2-linter: disable=name/configurable (temporary fix)
112+
o2::framework::Configurable<int> confLightIonsModifyTimeVetoOnNearbyColl{"TestModifyTimeVetoOnNearbyColl", 0, "0 - use standard time veto, 1 - modify time range"}; // o2-linter: disable=name/configurable (temporary fix)
113+
o2::framework::Configurable<int> confLightIonsVetoOnTRDinPast{"TestVetoOnTRDinPast", 0, "0 - use standard time veto, 1 - use veto on TRD in the past events"}; // o2-linter: disable=name/configurable (temporary fix)
114+
o2::framework::Configurable<float> confLightIonsNsigmaOnVzDiff{"TestVzDiffNsigma", 3.0, "+/- nSigma on vZ difference by FT0 and by tracks"}; // o2-linter: disable=name/configurable (temporary fix)
115+
o2::framework::Configurable<float> confLightIonsMarginVzDiff{"TestVzDiffMargin", 0.2, "margin for +/- nSigma on vZ difference by FT0 and by tracks"}; // o2-linter: disable=name/configurable (temporary fix)
109116
};
110117

111118
// luminosity configurables
@@ -602,13 +609,20 @@ class EventSelectionModule
602609
int run3min = 500000;
603610
int lastRun = -1; // last run number (needed to access ccdb only if run!=lastRun)
604611
std::bitset<nBCsPerOrbit> bcPatternB; // bc pattern of colliding bunches
612+
std::vector<int> bcsPattern; // pattern of colliding BCs
605613

606614
int64_t bcSOR = -1; // global bc of the start of the first orbit
607615
int64_t nBCsPerTF = -1; // duration of TF in bcs, should be 128*3564 or 32*3564
608616
int rofOffset = -1; // ITS ROF offset, in bc
609617
int rofLength = -1; // ITS ROF length, in bc
610618
std::string strLPMProductionTag = ""; // MC production tag to be retrieved from AO2D metadata
611619

620+
// temporary (?) parameterizations for light ion runs
621+
int runLightIons = -1;
622+
int runListLightIons[11] = {564356, 564359, 564373, 564374, 564387, 564400, 564414, 564430, 564445, 564468, 564472};
623+
std::vector<float> diffVzParMean; // parameterization for mean of diff vZ by FT0 vs by tracks
624+
std::vector<float> diffVzParSigma; // parameterization for stddev of diff vZ by FT0 vs by tracks
625+
612626
int32_t findClosest(int64_t globalBC, std::map<int64_t, int32_t>& bcs)
613627
{
614628
auto it = bcs.lower_bound(globalBC);
@@ -718,12 +732,38 @@ class EventSelectionModule
718732
// avoids crash related to specific run number
719733
auto grplhcif = ccdb->template getSpecific<o2::parameters::GRPLHCIFData>("GLO/Config/GRPLHCIF", ts);
720734
bcPatternB = grplhcif->getBunchFilling().getBCPattern();
735+
bcsPattern = grplhcif->getBunchFilling().getFilledBCs();
721736

722737
// extract ITS ROF parameters
723738
auto alppar = ccdb->template getForTimeStamp<o2::itsmft::DPLAlpideParam<0>>("ITS/Config/AlpideParam", ts);
724739
rofOffset = alppar->roFrameBiasInBC;
725740
rofLength = alppar->roFrameLengthInBC;
726741
LOGP(debug, "ITS ROF Offset={} ITS ROF Length={}", rofOffset, rofLength);
742+
if (evselOpts.confLightIonsAlternativeBcMatching) {
743+
for (unsigned long i = 0; i < bcsPattern.size(); i++)
744+
LOGP(info, "bcsPattern: i={} bc={}", i, bcsPattern.at(i));
745+
}
746+
747+
// special treatment of light ion runs
748+
if (lastRun >= 564356 && lastRun <= 564472) {
749+
for (unsigned long i = 0; i < sizeof(runListLightIons) / sizeof(*runListLightIons); i++) {
750+
if (runListLightIons[i] == lastRun) {
751+
runLightIons = lastRun;
752+
// extract parameterization for diff of vZ by FT0 vs by tracks
753+
auto parMeans = ccdb->template getForTimeStamp<std::vector<float>>("Users/a/altsybee/diffVzCollVsFTOmeanPar", ts);
754+
auto parSigmas = ccdb->template getForTimeStamp<std::vector<float>>("Users/a/altsybee/diffVzCollVsFTOsigmaPar", ts);
755+
diffVzParMean = *parMeans;
756+
diffVzParSigma = *parSigmas;
757+
LOGP(info, ">>> special treatment for diffVz for light ion run {}", runLightIons);
758+
for (int i = 0; i < 5; i++)
759+
LOGP(info, " mean par {} = {}", i, diffVzParMean[i]);
760+
for (int i = 0; i < 5; i++)
761+
LOGP(info, " sigma par {} = {}", i, diffVzParSigma[i]);
762+
break;
763+
}
764+
}
765+
}
766+
727767
} // if run != lastRun
728768
return true;
729769
}
@@ -824,13 +864,19 @@ class EventSelectionModule
824864
// create maps from globalBC to bc index for TVX-fired bcs
825865
// to be used for closest TVX searches
826866
std::map<int64_t, int32_t> mapGlobalBcWithTVX;
867+
std::map<int64_t, int32_t> mapGlobalBcWithOrInFT0;
827868
std::map<int64_t, float> mapGlobalBcVtxZ;
828869
for (const auto& bc : bcs) {
829870
int64_t globalBC = bc.globalBC();
830871
// skip non-colliding bcs for data and anchored runs
831872
if (run >= run3min && bcPatternB[globalBC % nBCsPerOrbit] == 0) {
832873
continue;
833874
}
875+
876+
if (bc.has_ft0()) {
877+
mapGlobalBcWithOrInFT0[globalBC] = bc.globalIndex();
878+
}
879+
834880
auto selection = bcselbuffer[bc.globalIndex()].selection;
835881
if (bitcheck64(selection, aod::evsel::kIsTriggerTVX)) {
836882
mapGlobalBcWithTVX[globalBC] = bc.globalIndex();
@@ -863,9 +909,11 @@ class EventSelectionModule
863909
std::vector<bool> vIsVertexTOFmatched(cols.size(), 0); // at least one of vertex contributors is matched to TOF
864910
std::vector<bool> vIsVertexTRDmatched(cols.size(), 0); // at least one of vertex contributors is matched to TRD
865911

866-
std::vector<int> vCollisionsPerBc(bcs.size(), 0); // counter of collisions per found bc for pileup checks
867-
std::vector<int> vFoundBCindex(cols.size(), -1); // indices of found bcs
868-
std::vector<int64_t> vFoundGlobalBC(cols.size(), 0); // global BCs for collisions
912+
std::vector<int> vCollisionsPerBc(bcs.size(), 0); // counter of collisions per found bc for pileup checks
913+
std::vector<int> vCollisionsPileupPerColl(cols.size(), 0); // counter of pileup in the same bc as a given collision
914+
std::vector<int64_t> vBCinPatternPerColl(cols.size(), 0); // found nominal BCs for collisions
915+
std::vector<int> vFoundBCindex(cols.size(), -1); // indices of found bcs
916+
std::vector<int64_t> vFoundGlobalBC(cols.size(), 0); // global BCs for collisions
869917

870918
std::vector<bool> vIsVertexTOF(cols.size(), 0);
871919
std::vector<bool> vIsVertexTRD(cols.size(), 0);
@@ -937,7 +985,67 @@ class EventSelectionModule
937985
int64_t foundGlobalBC = 0;
938986
int32_t foundBCindex = -1;
939987

940-
if (nPvTracksTOF > 0) {
988+
// alternative collision-BC matching (currently: test mode, the aim is to improve pileup rejection)
989+
if (evselOpts.confLightIonsAlternativeBcMatching) {
990+
foundGlobalBC = globalBC;
991+
// find closest nominal bc in pattern
992+
for (unsigned long i = 0; i < bcsPattern.size(); i++) {
993+
int32_t localBC = globalBC % nBCsPerOrbit;
994+
int32_t bcFromPattern = bcsPattern.at(i);
995+
int64_t bcDiff = bcFromPattern - localBC;
996+
if (std::abs(bcDiff) <= 20) {
997+
foundGlobalBC = (globalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPattern;
998+
break; // the bc in pattern is found
999+
}
1000+
}
1001+
1002+
// matched with TOF --> precise time, match to TVX, but keep the nominal foundGlobalBC from pattern
1003+
if (vIsVertexTOFmatched[colIndex]) {
1004+
std::map<int64_t, int32_t>::iterator it = mapGlobalBcWithTVX.find(foundGlobalBC);
1005+
if (it != mapGlobalBcWithTVX.end()) {
1006+
foundBCindex = it->second; // TVX at foundGlobalBC is found
1007+
} else { // check if TVX is in nearby bcs
1008+
it = mapGlobalBcWithTVX.find(foundGlobalBC + 1); // next bc
1009+
if (it != mapGlobalBcWithTVX.end()) {
1010+
// foundGlobalBC += 1;
1011+
foundBCindex = it->second;
1012+
} else {
1013+
it = mapGlobalBcWithTVX.find(foundGlobalBC - 1); // previous bc
1014+
if (it != mapGlobalBcWithTVX.end()) {
1015+
// foundGlobalBC -= 1;
1016+
foundBCindex = it->second;
1017+
} else {
1018+
foundBCindex = bc.globalIndex(); // keep original BC index
1019+
}
1020+
}
1021+
}
1022+
} // end of if TOF-matched vertex
1023+
else { // for non-TOF and low-mult vertices, consider nearby nominal bcs
1024+
int64_t meanBC = globalBC + TMath::Nint(sumHighPtTime / sumHighPtW / bcNS);
1025+
int64_t bestGlobalBC = findBestGlobalBC(meanBC, evselOpts.confSigmaBCforHighPtTracks, vNcontributors[colIndex], col.posZ(), mapGlobalBcVtxZ);
1026+
if (bestGlobalBC > 0) {
1027+
foundGlobalBC = bestGlobalBC;
1028+
// find closest nominal bc in pattern
1029+
for (unsigned long j = 0; j < bcsPattern.size(); j++) {
1030+
int32_t bcFromPatternBest = bcsPattern.at(j);
1031+
int64_t bcDiff = bcFromPatternBest - (bestGlobalBC % nBCsPerOrbit);
1032+
if (std::abs(bcDiff) <= 20) {
1033+
foundGlobalBC = (bestGlobalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPatternBest;
1034+
break; // the bc in pattern is found
1035+
}
1036+
}
1037+
foundBCindex = mapGlobalBcWithTVX[bestGlobalBC];
1038+
} else { // failed to find a proper TVX with small vZ difference
1039+
foundBCindex = bc.globalIndex(); // keep original BC index
1040+
}
1041+
} // end of non-TOF matched vertices
1042+
// sanitity check: if BC was not found
1043+
if (foundBCindex == -1) {
1044+
foundBCindex = bc.globalIndex();
1045+
}
1046+
vBCinPatternPerColl[colIndex] = foundGlobalBC;
1047+
// end of alternative coll-BC matching (test)
1048+
} else if (nPvTracksTOF > 0) { // "standard matching":
9411049
// for collisions with TOF tracks:
9421050
// take bc corresponding to TOF track with median time
9431051
int64_t tofGlobalBC = globalBC + TMath::Nint(getMedian(vTrackTimesTOF) / bcNS);
@@ -975,23 +1083,34 @@ class EventSelectionModule
9751083
if (foundBCindex >= 0)
9761084
mapGlobalBcVtxZ.erase(foundGlobalBC);
9771085
}
978-
979-
// second loop to match remaining low-pt TPCnoTOFnoTRD collisions
980-
for (const auto& col : cols) {
981-
int32_t colIndex = col.globalIndex();
982-
if (vIsVertexTPC[colIndex] > 0 && vIsVertexTOF[colIndex] == 0 && vIsVertexHighPtTPC[colIndex] == 0) {
983-
float weightedTime = vWeightedTimesTPCnoTOFnoTRD[colIndex];
984-
float weightedSigma = vWeightedSigmaTPCnoTOFnoTRD[colIndex];
985-
auto bc = col.template bc_as<soa::Join<aod::BCs, aod::Run3MatchedToBCSparse>>();
986-
int64_t globalBC = bc.globalBC();
987-
int64_t meanBC = globalBC + TMath::Nint(weightedTime / bcNS);
988-
int64_t sigmaBC = TMath::CeilNint(weightedSigma / bcNS);
989-
int64_t bestGlobalBC = findBestGlobalBC(meanBC, sigmaBC, vNcontributors[colIndex], col.posZ(), mapGlobalBcVtxZ);
990-
vFoundGlobalBC[colIndex] = bestGlobalBC > 0 ? bestGlobalBC : globalBC;
991-
vFoundBCindex[colIndex] = bestGlobalBC > 0 ? mapGlobalBcWithTVX[bestGlobalBC] : bc.globalIndex();
1086+
// alternative matching: looking for collisions with the same nominal BC
1087+
if (evselOpts.confLightIonsAlternativeBcMatching) {
1088+
for (unsigned long iCol = 0; iCol < vBCinPatternPerColl.size(); iCol++) {
1089+
int64_t foundNominalBC = vBCinPatternPerColl[iCol];
1090+
for (unsigned long jCol = 0; jCol < vBCinPatternPerColl.size(); jCol++) {
1091+
int64_t foundNominalBC2 = vBCinPatternPerColl[jCol];
1092+
if (foundNominalBC2 == foundNominalBC) {
1093+
vCollisionsPileupPerColl[iCol]++;
1094+
}
1095+
}
1096+
}
1097+
} else { // continue standard matching: second loop to match remaining low-pt TPCnoTOFnoTRD collisions
1098+
for (const auto& col : cols) {
1099+
int32_t colIndex = col.globalIndex();
1100+
if (vIsVertexTPC[colIndex] > 0 && vIsVertexTOF[colIndex] == 0 && vIsVertexHighPtTPC[colIndex] == 0) {
1101+
float weightedTime = vWeightedTimesTPCnoTOFnoTRD[colIndex];
1102+
float weightedSigma = vWeightedSigmaTPCnoTOFnoTRD[colIndex];
1103+
auto bc = col.template bc_as<soa::Join<aod::BCs, aod::Run3MatchedToBCSparse>>();
1104+
int64_t globalBC = bc.globalBC();
1105+
int64_t meanBC = globalBC + TMath::Nint(weightedTime / bcNS);
1106+
int64_t sigmaBC = TMath::CeilNint(weightedSigma / bcNS);
1107+
int64_t bestGlobalBC = findBestGlobalBC(meanBC, sigmaBC, vNcontributors[colIndex], col.posZ(), mapGlobalBcVtxZ);
1108+
vFoundGlobalBC[colIndex] = bestGlobalBC > 0 ? bestGlobalBC : globalBC;
1109+
vFoundBCindex[colIndex] = bestGlobalBC > 0 ? mapGlobalBcWithTVX[bestGlobalBC] : bc.globalIndex();
1110+
}
1111+
// fill pileup counter
1112+
vCollisionsPerBc[vFoundBCindex[colIndex]]++;
9921113
}
993-
// fill pileup counter
994-
vCollisionsPerBc[vFoundBCindex[colIndex]]++;
9951114
}
9961115

9971116
// save indices of collisions for occupancy calculation (both in ROF and in time range)
@@ -1188,10 +1307,24 @@ class EventSelectionModule
11881307
sumAmpFT0CInFullTimeWindow += wOccup * vAmpFT0CperColl[thisColIndex];
11891308

11901309
// counting tracks from other collisions in fixed time windows
1191-
if (std::fabs(dt) < evselOpts.confTimeRangeVetoOnCollNarrow)
1192-
nITS567tracksForVetoNarrow += vTracksITS567perColl[thisColIndex];
1193-
if (std::fabs(dt) < evselOpts.confTimeRangeVetoOnCollStandard)
1194-
nITS567tracksForVetoStrict += vTracksITS567perColl[thisColIndex];
1310+
if (!evselOpts.confLightIonsModifyTimeVetoOnNearbyColl) {
1311+
if (std::fabs(dt) < evselOpts.confTimeRangeVetoOnCollNarrow)
1312+
nITS567tracksForVetoNarrow += vTracksITS567perColl[thisColIndex];
1313+
if (std::fabs(dt) < evselOpts.confTimeRangeVetoOnCollStandard)
1314+
nITS567tracksForVetoStrict += vTracksITS567perColl[thisColIndex];
1315+
} else { // special veto ranges (tests for light ion runs)
1316+
if (dt > -4.5 && dt < 2.5) // avoid TOF- and TRD-related structures, with 0.5 us margin
1317+
nITS567tracksForVetoNarrow += vTracksITS567perColl[thisColIndex];
1318+
1319+
if (!evselOpts.confLightIonsVetoOnTRDinPast) {
1320+
if (dt > -25.5 && dt < 2.5) // test effect from TRD triggers in the past
1321+
nITS567tracksForVetoStrict += vTracksITS567perColl[thisColIndex];
1322+
} else {
1323+
// counting TRD-matched vertices in a long time interval in the past
1324+
if (dt > -25.5 && dt < 2.5)
1325+
nITS567tracksForVetoStrict += vIsVertexTRDmatched[thisColIndex];
1326+
}
1327+
}
11951328

11961329
// standard cut on other collisions vs delta-times
11971330
const float driftV = 2.5; // drift velocity in cm/us, TPC drift_length / drift_time = 250 cm / 100 us
@@ -1210,7 +1343,11 @@ class EventSelectionModule
12101343
vSumAmpFT0CinFullTimeWin[colIndex] = sumAmpFT0CInFullTimeWindow; // occupancy by a sum of FT0C amplitudes (without a current collision)
12111344
// occupancy flags based on nearby collisions
12121345
vNoCollInTimeRangeNarrow[colIndex] = (nITS567tracksForVetoNarrow == 0);
1213-
vNoCollInTimeRangeStrict[colIndex] = (nITS567tracksForVetoStrict == 0);
1346+
if (!evselOpts.confLightIonsVetoOnTRDinPast)
1347+
vNoCollInTimeRangeStrict[colIndex] = (nITS567tracksForVetoStrict == 0);
1348+
else
1349+
vNoCollInTimeRangeStrict[colIndex] = (nITS567tracksForVetoStrict == 0 && nITS567tracksForVetoNarrow == 0);
1350+
12141351
vNoHighMultCollInTimeRange[colIndex] = (nCollsWithFT0CAboveVetoStandard == 0);
12151352
}
12161353

@@ -1228,15 +1365,34 @@ class EventSelectionModule
12281365
bool isGoodZvtxFT0vsPV = 0;
12291366
if (bcselEntry.foundFT0Id > -1) {
12301367
auto foundFT0 = ft0s.rawIteratorAt(bcselEntry.foundFT0Id);
1231-
isGoodZvtxFT0vsPV = std::fabs(foundFT0.posZ() - col.posZ()) < evselOpts.maxDiffZvtxFT0vsPV;
1368+
float diffVz = foundFT0.posZ() - col.posZ();
1369+
if (runLightIons == -1)
1370+
isGoodZvtxFT0vsPV = std::fabs(diffVz) < evselOpts.maxDiffZvtxFT0vsPV;
1371+
else { // special treatment of light ion runs
1372+
float multT0A = bc.ft0().sumAmpA();
1373+
float multT0C = bc.ft0().sumAmpC();
1374+
float T0M = multT0A + multT0C;
1375+
// calc mean at this T0 ampl.
1376+
float x = (T0M < 50 ? 50 : T0M);
1377+
double diffMean = diffVzParMean[0] + diffVzParMean[1] * pow(x, diffVzParMean[2]) + diffVzParMean[3] * pow(x, diffVzParMean[4]);
1378+
// calc sigma at this T0 ampl.
1379+
x = (T0M < 20 ? 20 : (T0M > 1.2e4 ? 1.2e4 : T0M));
1380+
double diffSigma = diffVzParSigma[0] + diffVzParSigma[1] * pow(x, diffVzParSigma[2]) + diffVzParSigma[3] * pow(x, diffVzParSigma[4]);
1381+
float nSigma = evselOpts.confLightIonsNsigmaOnVzDiff;
1382+
float margin = evselOpts.confLightIonsMarginVzDiff;
1383+
isGoodZvtxFT0vsPV = (diffVz > diffMean - nSigma * diffSigma - margin && diffVz < diffMean + nSigma * diffSigma + margin);
1384+
}
12321385
}
12331386

12341387
// copy alias decisions from bcsel table
12351388
uint32_t alias = bcselEntry.alias;
12361389

12371390
// copy selection decisions from bcsel table
12381391
uint64_t selection = bcselbuffer[bc.globalIndex()].selection;
1239-
selection |= vCollisionsPerBc[foundBC] <= 1 ? BIT(aod::evsel::kNoSameBunchPileup) : 0;
1392+
if (evselOpts.confLightIonsAlternativeBcMatching)
1393+
selection |= vCollisionsPileupPerColl[colIndex] <= 1 ? BIT(aod::evsel::kNoSameBunchPileup) : 0;
1394+
else
1395+
selection |= vCollisionsPerBc[foundBC] <= 1 ? BIT(aod::evsel::kNoSameBunchPileup) : 0;
12401396
selection |= vIsVertexITSTPC[colIndex] ? BIT(aod::evsel::kIsVertexITSTPC) : 0;
12411397
selection |= vIsVertexTOFmatched[colIndex] ? BIT(aod::evsel::kIsVertexTOFmatched) : 0;
12421398
selection |= vIsVertexTRDmatched[colIndex] ? BIT(aod::evsel::kIsVertexTRDmatched) : 0;

0 commit comments

Comments
 (0)