Skip to content

Commit 0b941a6

Browse files
committed
Introduce minimalistic barrel UPC candidate producer
1 parent e7fe139 commit 0b941a6

2 files changed

Lines changed: 391 additions & 0 deletions

File tree

‎PWGUD/TableProducer/CMakeLists.txt‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,8 @@ o2physics_add_dpl_workflow(upc-cand-producer-semi-fwd
8080
SOURCES upcCandProducerSemiFwd.cxx
8181
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking
8282
COMPONENT_NAME Analysis)
83+
84+
o2physics_add_dpl_workflow(upc-cand-producer-barrel
85+
SOURCES upcCandProducerBarrel.cxx
86+
PUBLIC_LINK_LIBRARIES O2::Framework O2::CCDB O2::DataFormatsParameters O2Physics::AnalysisCore
87+
COMPONENT_NAME Analysis)
Lines changed: 386 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file dgTwoTrackCandProducer.cxx
13+
/// \brief Compact two-track double-gap candidate table producer for exclusive diffraction and UPC studies.
14+
/// Requires: event selection, propagation, TPC PID and TOF PID services
15+
/// \author Nazar Burmasov (JINR), Evgeny Kryshen (JINR)
16+
17+
#include "Common/CCDB/EventSelectionParams.h"
18+
#include "Common/CCDB/RCTSelectionFlags.h"
19+
#include "Common/Core/TableHelper.h"
20+
#include "Common/DataModel/EventSelection.h"
21+
#include "Common/DataModel/PIDResponseTOF.h"
22+
#include "Common/DataModel/PIDResponseTPC.h"
23+
24+
#include <CCDB/BasicCCDBManager.h>
25+
#include <CommonConstants/LHCConstants.h>
26+
#include <DataFormatsFIT/Triggers.h>
27+
#include <DataFormatsParameters/AggregatedRunInfo.h>
28+
#include <DataFormatsParameters/GRPLHCIFData.h>
29+
#include <Framework/AnalysisTask.h>
30+
#include <Framework/Configurable.h>
31+
#include <Framework/HistogramRegistry.h>
32+
#include <Framework/InitContext.h>
33+
#include <Framework/Logger.h>
34+
#include <Framework/runDataProcessing.h>
35+
36+
#include <TH1.h>
37+
#include <TH2.h>
38+
39+
#include <algorithm>
40+
#include <bitset>
41+
#include <cmath>
42+
#include <cstddef>
43+
#include <cstdint>
44+
#include <memory>
45+
#include <vector>
46+
47+
using namespace o2;
48+
using namespace o2::framework;
49+
using namespace o2::aod::rctsel;
50+
51+
namespace
52+
{
53+
constexpr int NBCsPerOrbit = o2::constants::lhc::LHCMaxBunches;
54+
constexpr int MaxStoredDistance = 15;
55+
constexpr float MaxFITTime = 30.f;
56+
57+
using DistanceMap = std::vector<std::vector<uint32_t>>;
58+
59+
DistanceMap buildMinimumDistanceMap(std::vector<uint32_t> const& tfIDs,
60+
int64_t bcSOR, int64_t nBCsPerTF,
61+
std::vector<int64_t>& activeBCs, uint32_t maxDistance)
62+
{
63+
const uint32_t overflowDistance = maxDistance + 1;
64+
DistanceMap distances(tfIDs.size(), std::vector<uint32_t>(nBCsPerTF, overflowDistance));
65+
if (activeBCs.empty()) {
66+
return distances;
67+
}
68+
std::sort(activeBCs.begin(), activeBCs.end());
69+
activeBCs.erase(std::unique(activeBCs.begin(), activeBCs.end()), activeBCs.end());
70+
size_t nextIndex = 0;
71+
for (size_t iTF = 0; iTF < tfIDs.size(); ++iTF) {
72+
const int64_t tfStartBC = bcSOR + tfIDs[iTF] * nBCsPerTF;
73+
for (int64_t bcInTF = 0; bcInTF < nBCsPerTF; ++bcInTF) {
74+
const int64_t currentBC = tfStartBC + bcInTF;
75+
while (nextIndex < activeBCs.size() && activeBCs[nextIndex] < currentBC) {
76+
++nextIndex;
77+
}
78+
int64_t distance = overflowDistance;
79+
if (nextIndex < activeBCs.size()) {
80+
distance = std::min(distance, activeBCs[nextIndex] - currentBC);
81+
}
82+
if (nextIndex > 0) {
83+
distance = std::min(distance, currentBC - activeBCs[nextIndex - 1]);
84+
}
85+
distances[iTF][bcInTF] = static_cast<uint32_t>(distance);
86+
}
87+
}
88+
return distances;
89+
}
90+
91+
void fillVetoHistograms(std::shared_ptr<TH2> const& hVetoT00, std::shared_ptr<TH2> const& hVetoTV0,
92+
std::shared_ptr<TH2> const& hVetoTVD, int bcInOrbit,
93+
uint32_t distanceFT0, uint32_t distanceFV0, uint32_t distanceFDD)
94+
{
95+
hVetoT00->Fill(bcInOrbit, -1);
96+
hVetoTV0->Fill(bcInOrbit, -1);
97+
hVetoTVD->Fill(bcInOrbit, -1);
98+
for (uint32_t threshold = 0; threshold <= MaxStoredDistance; ++threshold) {
99+
if (distanceFT0 <= threshold) {
100+
continue;
101+
}
102+
hVetoT00->Fill(bcInOrbit, threshold);
103+
if (distanceFV0 <= threshold) {
104+
continue;
105+
}
106+
hVetoTV0->Fill(bcInOrbit, threshold);
107+
if (distanceFDD > threshold) {
108+
hVetoTVD->Fill(bcInOrbit, threshold);
109+
}
110+
}
111+
}
112+
} // namespace
113+
114+
namespace o2::aod::upc_cand_prod_bar
115+
{
116+
DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t);
117+
DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t);
118+
DECLARE_SOA_COLUMN(TFId, tfId, uint32_t);
119+
DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t);
120+
DECLARE_SOA_COLUMN(PosX, posX, float);
121+
DECLARE_SOA_COLUMN(PosY, posY, float);
122+
DECLARE_SOA_COLUMN(PosZ, posZ, float);
123+
DECLARE_SOA_COLUMN(Px, px, std::vector<float>);
124+
DECLARE_SOA_COLUMN(Py, py, std::vector<float>);
125+
DECLARE_SOA_COLUMN(Pz, pz, std::vector<float>);
126+
DECLARE_SOA_COLUMN(TpcSignal, tpcSignal, std::vector<float>);
127+
DECLARE_SOA_COLUMN(TpcNSigmaEl, tpcNSigmaEl, std::vector<float>);
128+
DECLARE_SOA_COLUMN(TpcNSigmaPi, tpcNSigmaPi, std::vector<float>);
129+
DECLARE_SOA_COLUMN(TpcNSigmaKa, tpcNSigmaKa, std::vector<float>);
130+
DECLARE_SOA_COLUMN(TpcNSigmaPr, tpcNSigmaPr, std::vector<float>);
131+
DECLARE_SOA_COLUMN(TofNSigmaEl, tofNSigmaEl, std::vector<float>);
132+
DECLARE_SOA_COLUMN(TofNSigmaPi, tofNSigmaPi, std::vector<float>);
133+
DECLARE_SOA_COLUMN(TofNSigmaKa, tofNSigmaKa, std::vector<float>);
134+
DECLARE_SOA_COLUMN(TofNSigmaPr, tofNSigmaPr, std::vector<float>);
135+
DECLARE_SOA_COLUMN(ItsClusterMap, itsClusterMap, std::vector<uint8_t>);
136+
DECLARE_SOA_COLUMN(NClusters, nClusters, std::vector<uint8_t>);
137+
DECLARE_SOA_COLUMN(Sign, sign, std::vector<int8_t>);
138+
DECLARE_SOA_COLUMN(MinimumDistanceFT0, minimumDistanceFT0, int8_t);
139+
DECLARE_SOA_COLUMN(MinimumDistanceFV0, minimumDistanceFV0, int8_t);
140+
DECLARE_SOA_COLUMN(MinimumDistanceFDD, minimumDistanceFDD, int8_t);
141+
} // namespace o2::aod::upc_cand_prod_bar
142+
143+
namespace o2::aod
144+
{
145+
DECLARE_SOA_TABLE(UPCBarrelCands, "AOD", "UPCBARRELCANDS",
146+
upc_cand_prod_bar::RunNumber,
147+
upc_cand_prod_bar::GlobalBC,
148+
upc_cand_prod_bar::TFId,
149+
upc_cand_prod_bar::Timestamp,
150+
upc_cand_prod_bar::PosX,
151+
upc_cand_prod_bar::PosY,
152+
upc_cand_prod_bar::PosZ,
153+
upc_cand_prod_bar::Px,
154+
upc_cand_prod_bar::Py,
155+
upc_cand_prod_bar::Pz,
156+
upc_cand_prod_bar::TpcSignal,
157+
upc_cand_prod_bar::TpcNSigmaEl,
158+
upc_cand_prod_bar::TpcNSigmaPi,
159+
upc_cand_prod_bar::TpcNSigmaKa,
160+
upc_cand_prod_bar::TpcNSigmaPr,
161+
upc_cand_prod_bar::TofNSigmaEl,
162+
upc_cand_prod_bar::TofNSigmaPi,
163+
upc_cand_prod_bar::TofNSigmaKa,
164+
upc_cand_prod_bar::TofNSigmaPr,
165+
upc_cand_prod_bar::ItsClusterMap,
166+
upc_cand_prod_bar::NClusters,
167+
upc_cand_prod_bar::Sign,
168+
upc_cand_prod_bar::MinimumDistanceFT0,
169+
upc_cand_prod_bar::MinimumDistanceFV0,
170+
upc_cand_prod_bar::MinimumDistanceFDD);
171+
} // namespace o2::aod
172+
173+
struct UpcCandProducerBarrel {
174+
Produces<aod::UPCBarrelCands> selectedCandidates;
175+
HistogramRegistry registry{"registry", {}};
176+
Service<o2::ccdb::BasicCCDBManager> ccdb;
177+
178+
int cachedRunNumber = -1;
179+
int64_t bcSOR = 0;
180+
int64_t nBCsPerTF = 0;
181+
int configuredOrbitsPerTF = -1;
182+
int configuredTFStartBorder = -1;
183+
int configuredTFEndBorder = -1;
184+
int tfStartBorder = 0;
185+
int tfEndBorder = 0;
186+
std::bitset<NBCsPerOrbit> collidingBCs;
187+
188+
Configurable<size_t> candidateTrackCount{"candidateTrackCount", 2, "Required N tracks in selected collisions"};
189+
Configurable<float> maxAbsEta{"maxAbsEta", 0.8f, "Maximum |eta| of selected tracks"};
190+
Configurable<float> minPt{"minPt", 0.2f, "Minimum pT of selected tracks (GeV/c)"};
191+
Configurable<int> vetoBCWindow{"vetoBCWindow", 0, "FIT veto half-window in BC; <0 disables"};
192+
Configurable<int> vetoFT0{"vetoFT0", 1, "FT0 veto: 0=off, 1=on"};
193+
Configurable<int> vetoFV0{"vetoFV0", 0, "FV0 veto: 0=off, 1=on"};
194+
Configurable<int> vetoFDD{"vetoFDD", 0, "FDD veto: 0=off, 1=on"};
195+
196+
using CollisionsWithSels = soa::Join<aod::Collisions, aod::EvSels>;
197+
using BCsWithSels = soa::Join<aod::BCsWithTimestamps, aod::BcSels>;
198+
using TracksWithPID = soa::Join<aod::Tracks, aod::TracksExtra,
199+
aod::pidTPCEl, aod::pidTPCPi, aod::pidTPCKa, aod::pidTPCPr,
200+
aod::pidTOFEl, aod::pidTOFPi, aod::pidTOFKa, aod::pidTOFPr>;
201+
Preslice<TracksWithPID> tracksPerCollision = aod::track::collisionId;
202+
203+
RCTFlagsChecker rctChecker{kFDDBad, kFT0Bad, kFV0Bad, kITSBad, kITSLimAccMCRepr, kTPCBadTracking, kTPCLimAccMCRepr, kTPCBadPID, kTOFBad, kTOFLimAccMCRepr, kCcdbObjectLoaded};
204+
205+
void init(InitContext& initContext)
206+
{
207+
ccdb->setLocalObjectValidityChecking();
208+
auto inheritEventSelectionOption = [&](char const* name, int& value) {
209+
if (!o2::common::core::getTaskOptionValue(initContext, "eventselection-run3", name, value, false)) {
210+
LOGF(fatal, "Could not inherit option %s from eventselection-run3", name);
211+
}
212+
};
213+
inheritEventSelectionOption("bcselOpts.NumberOfOrbitsPerTF", configuredOrbitsPerTF);
214+
inheritEventSelectionOption("bcselOpts.TimeFrameStartBorderMargin", configuredTFStartBorder);
215+
inheritEventSelectionOption("bcselOpts.TimeFrameEndBorderMargin", configuredTFEndBorder);
216+
registry.add("hProcessedTFs", "Processed TFs;;TFs", HistType::kTH1D, {{1, 0., 1.}});
217+
registry.add("hTVX", "TVX counts per run;run;TVX BCs", HistType::kTH1D, {{NBCsPerOrbit, 0., NBCsPerOrbit}});
218+
registry.add("hTVXRCT", "TVX counts per run;run;TVX BCs", HistType::kTH1D, {{NBCsPerOrbit, 0., NBCsPerOrbit}});
219+
registry.add("hVetoT00", ";BC in orbit;veto range (BC);colliding BC count, no RCT mask", HistType::kTH2D, {{NBCsPerOrbit, 0., NBCsPerOrbit}, {17, -1.5, 15.5}});
220+
registry.add("hVetoTV0", ";BC in orbit;veto range (BC);colliding BC count, no RCT mask", HistType::kTH2D, {{NBCsPerOrbit, 0., NBCsPerOrbit}, {17, -1.5, 15.5}});
221+
registry.add("hVetoTVD", ";BC in orbit;veto range (BC);colliding BC count, no RCT mask", HistType::kTH2D, {{NBCsPerOrbit, 0., NBCsPerOrbit}, {17, -1.5, 15.5}});
222+
registry.add("hVetoT00RCT", ";BC in orbit;veto range (BC);colliding BC count, RCT mask", HistType::kTH2D, {{NBCsPerOrbit, 0., NBCsPerOrbit}, {17, -1.5, 15.5}});
223+
registry.add("hVetoTV0RCT", ";BC in orbit;veto range (BC);colliding BC count, RCT mask", HistType::kTH2D, {{NBCsPerOrbit, 0., NBCsPerOrbit}, {17, -1.5, 15.5}});
224+
registry.add("hVetoTVDRCT", ";BC in orbit;veto range (BC);colliding BC count, RCT mask", HistType::kTH2D, {{NBCsPerOrbit, 0., NBCsPerOrbit}, {17, -1.5, 15.5}});
225+
LOGF(info, "Veto config: window=%d FT0=%d FV0=%d FDD=%d", vetoBCWindow.value, vetoFT0.value, vetoFV0.value, vetoFDD.value);
226+
}
227+
228+
void updateRunInfo(int runNumber)
229+
{
230+
if (runNumber == cachedRunNumber) {
231+
return;
232+
}
233+
const auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(ccdb->instance(), runNumber);
234+
const int64_t orbitsPerTF = configuredOrbitsPerTF < 0 ? runInfo.orbitsPerTF : configuredOrbitsPerTF;
235+
const bool needsEventSelectionParams = configuredTFStartBorder < 0 || configuredTFEndBorder < 0;
236+
const auto* eventSelectionParams = needsEventSelectionParams ? ccdb->getForTimeStamp<EventSelectionParams>("EventSelection/EventSelectionParams", runInfo.sor / 2 + runInfo.eor / 2) : nullptr;
237+
if (orbitsPerTF <= 0 || !runInfo.grpLHC || (needsEventSelectionParams && !eventSelectionParams)) {
238+
LOGF(fatal, "Incomplete run information for run %d", runNumber);
239+
}
240+
bcSOR = runInfo.orbitSOR * NBCsPerOrbit;
241+
nBCsPerTF = orbitsPerTF * NBCsPerOrbit;
242+
tfStartBorder = configuredTFStartBorder < 0 ? eventSelectionParams->fTimeFrameStartBorderMargin : configuredTFStartBorder;
243+
tfEndBorder = configuredTFEndBorder < 0 ? eventSelectionParams->fTimeFrameEndBorderMargin : configuredTFEndBorder;
244+
collidingBCs = runInfo.grpLHC->getBunchFilling().getBCPattern();
245+
cachedRunNumber = runNumber;
246+
}
247+
248+
void process(CollisionsWithSels const& collisions, TracksWithPID const& tracks, BCsWithSels const& bcs, aod::FT0s const& ft0s, aod::FV0As const& fv0s, aod::FDDs const& fdds)
249+
{
250+
updateRunInfo(bcs.begin().runNumber());
251+
std::vector<uint32_t> tfIDs;
252+
std::vector<uint8_t> tfPassesRCT;
253+
std::vector<size_t> localTFIndex;
254+
localTFIndex.reserve(bcs.size());
255+
const auto bcOffset = bcs.begin().globalIndex();
256+
for (const auto& bc : bcs) {
257+
const auto tfID = static_cast<uint32_t>((static_cast<int64_t>(bc.globalBC()) - bcSOR) / nBCsPerTF);
258+
if (tfIDs.empty() || tfID != tfIDs.back()) {
259+
tfIDs.push_back(tfID);
260+
tfPassesRCT.push_back(static_cast<uint8_t>(rctChecker(bc)));
261+
}
262+
localTFIndex.push_back(tfIDs.size() - 1);
263+
}
264+
registry.fill(HIST("hProcessedTFs"), 0.5, static_cast<double>(tfIDs.size()));
265+
266+
auto hTVX = registry.get<TH1>(HIST("hTVX"));
267+
auto hTVXRCT = registry.get<TH1>(HIST("hTVXRCT"));
268+
269+
std::vector<int64_t> bcsWithFT0;
270+
std::vector<int64_t> bcsWithFV0;
271+
std::vector<int64_t> bcsWithFDD;
272+
bcsWithFT0.reserve(ft0s.size());
273+
bcsWithFV0.reserve(fv0s.size());
274+
bcsWithFDD.reserve(fdds.size());
275+
276+
for (const auto& ft0 : ft0s) {
277+
const auto bc = ft0.bc_as<BCsWithSels>();
278+
const auto gbc = bc.globalBC();
279+
const auto bcInOrbit = gbc % NBCsPerOrbit;
280+
if (ft0.timeA() < MaxFITTime || ft0.timeC() < MaxFITTime) {
281+
bcsWithFT0.push_back(gbc);
282+
}
283+
if (!collidingBCs[bcInOrbit] || !TESTBIT(ft0.triggerMask(), o2::fit::Triggers::bitVertex)) {
284+
continue;
285+
}
286+
hTVX->Fill(bcInOrbit);
287+
if (!bc.selection_bit(aod::evsel::kNoTimeFrameBorder) || !rctChecker(bc)) {
288+
continue;
289+
}
290+
hTVXRCT->Fill(bcInOrbit);
291+
}
292+
for (const auto& fv0 : fv0s) {
293+
if (fv0.time() < MaxFITTime) {
294+
bcsWithFV0.push_back(fv0.bc_as<BCsWithSels>().globalBC());
295+
}
296+
}
297+
for (const auto& fdd : fdds) {
298+
if (fdd.timeA() < MaxFITTime || fdd.timeC() < MaxFITTime) {
299+
bcsWithFDD.push_back(fdd.bc_as<BCsWithSels>().globalBC());
300+
}
301+
}
302+
303+
const uint32_t scanDistance = std::max(MaxStoredDistance, vetoBCWindow.value);
304+
const DistanceMap minDistanceFT0 = buildMinimumDistanceMap(tfIDs, bcSOR, nBCsPerTF, bcsWithFT0, scanDistance);
305+
const DistanceMap minDistanceFV0 = buildMinimumDistanceMap(tfIDs, bcSOR, nBCsPerTF, bcsWithFV0, scanDistance);
306+
const DistanceMap minDistanceFDD = buildMinimumDistanceMap(tfIDs, bcSOR, nBCsPerTF, bcsWithFDD, scanDistance);
307+
308+
auto hVetoT00 = registry.get<TH2>(HIST("hVetoT00"));
309+
auto hVetoTV0 = registry.get<TH2>(HIST("hVetoTV0"));
310+
auto hVetoTVD = registry.get<TH2>(HIST("hVetoTVD"));
311+
auto hVetoT00RCT = registry.get<TH2>(HIST("hVetoT00RCT"));
312+
auto hVetoTV0RCT = registry.get<TH2>(HIST("hVetoTV0RCT"));
313+
auto hVetoTVDRCT = registry.get<TH2>(HIST("hVetoTVDRCT"));
314+
for (size_t iTF = 0; iTF < tfIDs.size(); ++iTF) {
315+
const int64_t tfStartBC = bcSOR + static_cast<int64_t>(tfIDs[iTF]) * nBCsPerTF;
316+
for (int64_t bcInTF = tfStartBorder + 1; bcInTF < nBCsPerTF - tfEndBorder; ++bcInTF) {
317+
const int64_t globalBC = tfStartBC + bcInTF;
318+
const int bcInOrbit = globalBC % NBCsPerOrbit;
319+
if (!collidingBCs[bcInOrbit]) {
320+
continue;
321+
}
322+
const auto distanceFT0 = minDistanceFT0[iTF][bcInTF];
323+
const auto distanceFV0 = minDistanceFV0[iTF][bcInTF];
324+
const auto distanceFDD = minDistanceFDD[iTF][bcInTF];
325+
fillVetoHistograms(hVetoT00, hVetoTV0, hVetoTVD, bcInOrbit, distanceFT0, distanceFV0, distanceFDD);
326+
if (tfPassesRCT[iTF] != 0u) {
327+
fillVetoHistograms(hVetoT00RCT, hVetoTV0RCT, hVetoTVDRCT, bcInOrbit, distanceFT0, distanceFV0, distanceFDD);
328+
}
329+
}
330+
}
331+
332+
for (const auto& collision : collisions) {
333+
if (collision.numContrib() != candidateTrackCount || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !rctChecker(collision)) {
334+
continue;
335+
}
336+
auto bc = collision.bc_as<BCsWithSels>();
337+
auto gbc = bc.globalBC();
338+
const auto iTF = localTFIndex[bc.globalIndex() - bcOffset];
339+
const int64_t bcInTF = (static_cast<int64_t>(gbc) - bcSOR) % nBCsPerTF;
340+
const auto distFT0 = minDistanceFT0[iTF][bcInTF];
341+
const auto distFV0 = minDistanceFV0[iTF][bcInTF];
342+
const auto distFDD = minDistanceFDD[iTF][bcInTF];
343+
const auto vetoWindow = static_cast<uint32_t>(vetoBCWindow.value);
344+
if (vetoBCWindow.value >= 0 && (((vetoFT0.value != 0) && distFT0 <= vetoWindow) || ((vetoFV0.value != 0) && distFV0 <= vetoWindow) || ((vetoFDD.value != 0) && distFDD <= vetoWindow))) {
345+
continue;
346+
}
347+
std::vector<float> px, py, pz;
348+
std::vector<float> tpcSignal, tpcNSigmaEl, tpcNSigmaPi, tpcNSigmaKa, tpcNSigmaPr;
349+
std::vector<float> tofNSigmaEl, tofNSigmaPi, tofNSigmaKa, tofNSigmaPr;
350+
std::vector<uint8_t> itsClusterMap;
351+
std::vector<uint8_t> nClusters;
352+
std::vector<int8_t> sign;
353+
for (const auto& track : tracks.sliceBy(tracksPerCollision, collision.globalIndex())) {
354+
if (!track.isPVContributor() || !track.hasITS() || !track.hasTPC() || std::abs(track.eta()) > maxAbsEta.value || track.pt() < minPt.value) {
355+
continue;
356+
}
357+
px.push_back(track.px());
358+
py.push_back(track.py());
359+
pz.push_back(track.pz());
360+
tpcSignal.push_back(track.tpcSignal());
361+
tpcNSigmaEl.push_back(track.tpcNSigmaEl());
362+
tpcNSigmaPi.push_back(track.tpcNSigmaPi());
363+
tpcNSigmaKa.push_back(track.tpcNSigmaKa());
364+
tpcNSigmaPr.push_back(track.tpcNSigmaPr());
365+
tofNSigmaEl.push_back(track.tofNSigmaEl());
366+
tofNSigmaPi.push_back(track.tofNSigmaPi());
367+
tofNSigmaKa.push_back(track.tofNSigmaKa());
368+
tofNSigmaPr.push_back(track.tofNSigmaPr());
369+
itsClusterMap.push_back(track.itsClusterMap());
370+
nClusters.push_back(track.tpcNClsFound());
371+
sign.push_back(track.sign());
372+
}
373+
if (px.size() != candidateTrackCount) {
374+
continue;
375+
}
376+
selectedCandidates(bc.runNumber(), gbc, tfIDs[iTF], bc.timestamp(), collision.posX(), collision.posY(), collision.posZ(),
377+
px, py, pz, tpcSignal, tpcNSigmaEl, tpcNSigmaPi, tpcNSigmaKa, tpcNSigmaPr,
378+
tofNSigmaEl, tofNSigmaPi, tofNSigmaKa, tofNSigmaPr, itsClusterMap, nClusters, sign,
379+
std::min<uint32_t>(distFT0, MaxStoredDistance + 1),
380+
std::min<uint32_t>(distFV0, MaxStoredDistance + 1),
381+
std::min<uint32_t>(distFDD, MaxStoredDistance + 1));
382+
}
383+
}
384+
};
385+
386+
WorkflowSpec defineDataProcessing(ConfigContext const& context) { return WorkflowSpec{adaptAnalysisTask<UpcCandProducerBarrel>(context)}; }

0 commit comments

Comments
 (0)