Project
Loading...
Searching...
No Matches
TPCDataFilter.cxx
Go to the documentation of this file.
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#include <vector>
13#include <TStopwatch.h>
32
33namespace o2::global
34{
35
36using namespace o2::framework;
39
45
47
48class TPCDataFilter : public Task
49{
50 public:
51 enum TrackDecision : char { NA,
55
56 TPCDataFilter(std::shared_ptr<DataRequest> dr, GTrackID::mask_t src, bool useMC)
57 : mDataRequest(dr), mTracksSrc(src), mUseMC(useMC)
58 {
59 }
60 ~TPCDataFilter() final = default;
61 void init(InitContext& ic) final;
62 void run(ProcessingContext& pc) final;
63 void finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) final;
64 void process(o2::globaltracking::RecoContainer& recoData);
66
67 private:
68 void updateTimeDependentParams(ProcessingContext& pc){};
69 std::shared_ptr<DataRequest> mDataRequest;
70 bool mUseMC{false};
71 char mRemMode = TrackDecision::KEEP;
72 GTrackID::mask_t mTracksSrc{};
73 o2::steer::MCKinematicsReader mcReader; // reader of MC information
74 //
75 // TPC data
76 std::vector<o2::tpc::ClusterNative> mClustersLinearFiltered;
77 std::vector<unsigned int> mClustersLinearStatus;
78 std::vector<char> mTrackStatus;
79 std::vector<o2::tpc::TrackTPC> mTracksFiltered;
80 std::vector<o2::tpc::TPCClRefElem> mTrackClusIdxFiltered;
81 std::vector<o2::MCCompLabel> mTPCTrkLabelsFiltered;
82 o2::tpc::ClusterNativeAccess mClusFiltered;
83 GTrackID::mask_t mAccTrackSources;
84 float mMinAbsTgl = 0.;
85 int mMinTPCClusters = 0;
86};
87
89{
90 mRemMode = ic.options().get<bool>("suppress-rejected") ? TrackDecision::REMOVE : TrackDecision::REDUCE;
91 GTrackID::mask_t acceptSourcesTrc = GTrackID::getSourcesMask("ITS,TPC,ITS-TPC,TPC-TOF,TPC-TRD,ITS-TPC-TRD,TPC-TRD-TOF,ITS-TPC-TOF,ITS-TPC-TRD-TOF");
92 mAccTrackSources = acceptSourcesTrc & GTrackID::getSourcesMask(ic.options().get<std::string>("accept-track-sources"));
93 mMinAbsTgl = ic.options().get<float>("min-abs-tgl");
94 mMinTPCClusters = ic.options().get<int>("min-tpc-clusters");
95}
96
98{
100 recoData.collectData(pc, *mDataRequest.get()); // select tracks of needed type, with minimal cuts, the real selected will be done in the vertexer
101 updateTimeDependentParams(pc); // Make sure this is called after recoData.collectData, which may load some conditions
102 process(recoData);
103
104 sendOutput(pc);
105}
106
108{
109
110 pc.outputs().snapshot(Output{"TPC", "TRACKSF", 0}, mTracksFiltered);
111 pc.outputs().snapshot(Output{"TPC", "CLUSREFSF", 0}, mTrackClusIdxFiltered);
112 if (mUseMC) {
113 pc.outputs().snapshot(Output{"TPC", "TRACKSMCLBLF", 0}, mTPCTrkLabelsFiltered);
114 }
115
116 o2::tpc::TPCSectorHeader clusterOutputSectorHeader{0};
117 clusterOutputSectorHeader.activeSectors = (1ul << o2::tpc::constants::MAXSECTOR) - 1;
118 for (int i = 0; i < o2::tpc::constants::MAXSECTOR; i++) {
119 clusterOutputSectorHeader.sectorBits = (1ul << i);
121 char* buffer = pc.outputs().make<char>({o2::header::gDataOriginTPC, "CLUSTERNATIVEF", subspec, {clusterOutputSectorHeader}},
122 mClusFiltered.nClustersSector[i] * sizeof(*mClusFiltered.clustersLinear) + sizeof(o2::tpc::ClusterCountIndex))
123 .data();
124 o2::tpc::ClusterCountIndex* outIndex = reinterpret_cast<o2::tpc::ClusterCountIndex*>(buffer);
125 memset(outIndex, 0, sizeof(*outIndex));
126 for (int j = 0; j < o2::tpc::constants::MAXGLOBALPADROW; j++) {
127 outIndex->nClusters[i][j] = mClusFiltered.nClusters[i][j];
128 }
129 memcpy(buffer + sizeof(*outIndex), mClusFiltered.clusters[i][0], mClusFiltered.nClustersSector[i] * sizeof(*mClusFiltered.clustersLinear));
130
131 if (mUseMC && mClusFiltered.clustersMCTruth) {
133 for (unsigned int j = 0; j < mClusFiltered.nClustersSector[i]; j++) {
134 const auto& labels = mClusFiltered.clustersMCTruth->getLabels(mClusFiltered.clusterOffset[i][0] + j);
135 for (const auto& label : labels) {
136 cont.addElement(j, label);
137 }
138 }
140 cont.flatten_to(contflat);
141 pc.outputs().snapshot({o2::header::gDataOriginTPC, "CLNATIVEMCLBLF", subspec, {clusterOutputSectorHeader}}, contflat);
142 }
143 }
144}
145
147{
148 auto tpcTracks = recoData.getTPCTracks();
149 auto tpcTrackClusIdx = recoData.getTPCTracksClusterRefs();
150 auto tpcClusterIdxStruct = &recoData.inputsTPCclusters->clusterIndex;
151 gsl::span<const o2::MCCompLabel> tpcTrkLabels;
152 if (mUseMC) {
153 tpcTrkLabels = recoData.getTPCTracksMCLabels();
154 mTPCTrkLabelsFiltered.clear();
155 }
156 const unsigned int DISCARD = -1U;
157
158 mTracksFiltered.clear();
159 mTrackClusIdxFiltered.clear();
160 mClustersLinearFiltered.clear();
161 mTrackStatus.clear();
162 mTrackStatus.resize(tpcTracks.size());
163 mClustersLinearStatus.clear();
164 mClustersLinearStatus.resize(tpcClusterIdxStruct->nClustersTotal, DISCARD);
165
166 size_t nSelTracks = 0;
167 auto selTPCTrack = [this, tpcTracks, tpcTrackClusIdx, tpcClusterIdxStruct, &nSelTracks](int itpc, char stat) {
168 this->mTrackStatus[itpc] = stat;
169 if (stat != TrackDecision::KEEP) {
170 return;
171 }
172 nSelTracks++;
173 const auto& trc = tpcTracks[itpc];
174 int count = trc.getNClusters();
175 const o2::tpc::ClusterNative* cl = nullptr;
176 for (int ic = count; ic--;) {
177 const auto cl = &trc.getCluster(tpcTrackClusIdx, ic, *tpcClusterIdxStruct);
178 size_t offs = std::distance(tpcClusterIdxStruct->clustersLinear, cl);
179 this->mClustersLinearStatus[offs] = 0;
180 }
181 };
182
183 auto trackIndex = recoData.getPrimaryVertexMatchedTracks(); // Global ID's for associated tracks
184 auto vtxRefs = recoData.getPrimaryVertexMatchedTrackRefs(); // references from vertex to these track IDs
185 int nv = vtxRefs.size();
186 for (int iv = 0; iv < nv; iv++) {
187 const auto& vtref = vtxRefs[iv];
188 for (int is = 0; is < GTrackID::NSources; is++) {
189 auto dmask = GTrackID::getSourceDetectorsMask(is);
190 if (!GTrackID::getSourceDetectorsMask(is)[GTrackID::TPC]) {
191 continue;
192 }
193 char decisionSource = mAccTrackSources[is] ? KEEP : mRemMode;
194 int idMin = vtxRefs[iv].getFirstEntryOfSource(is), idMax = idMin + vtxRefs[iv].getEntriesOfSource(is);
195 for (int i = idMin; i < idMax; i++) {
196 auto decision = decisionSource;
197 auto vid = trackIndex[i];
198 auto tpcID = recoData.getTPCContributorGID(vid);
199 if (vid.isAmbiguous() && mTrackStatus[tpcID] != TrackDecision::NA) { // already processed
200 continue;
201 }
202 if (decisionSource == KEEP) {
203 const auto& tpcTr = tpcTracks[tpcID.getIndex()];
204 if (std::abs(tpcTr.getTgl()) < mMinAbsTgl || tpcTr.getNClusters() < mMinTPCClusters) {
205 decision = mRemMode;
206 }
207 }
208 selTPCTrack(tpcID, decision);
209 }
210 }
211 }
212
213 // copy filtered clusters and register them in the filtered access struct
214 int offset = 0;
215 for (unsigned int i = 0; i < o2::tpc::constants::MAXSECTOR; i++) {
216 for (unsigned int j = 0; j < o2::tpc::constants::MAXGLOBALPADROW; j++) {
217 mClusFiltered.nClusters[i][j] = 0;
218 for (unsigned int ic = 0; ic < tpcClusterIdxStruct->nClusters[i][j]; ic++) {
219 if (mClustersLinearStatus[offset] != DISCARD) {
220 mClustersLinearStatus[offset] = mClustersLinearFiltered.size();
221 mClustersLinearFiltered.push_back(tpcClusterIdxStruct->clustersLinear[offset]);
222 mClusFiltered.nClusters[i][j]++;
223 }
224 offset++;
225 }
226 }
227 }
228 mClusFiltered.clustersLinear = mClustersLinearFiltered.data();
229 mClusFiltered.setOffsetPtrs();
230
231 LOGP(info, "Accepted {} tracks out of {} and {} clusters out of {}", nSelTracks, tpcTracks.size(), mClusFiltered.nClustersTotal, tpcClusterIdxStruct->nClustersTotal);
232
233 // register new tracks with updated cluster references
234 for (size_t itr = 0; itr < tpcTracks.size(); itr++) {
235 if (mTrackStatus[itr] == REMOVE) { // track is discarded
236 continue;
237 } else if (mTrackStatus[itr] == REDUCE) { // fill track by 0s, discard clusters
238 auto& t = mTracksFiltered.emplace_back();
239 memset(&t, 0, sizeof(o2::tpc::TrackTPC));
240 if (mUseMC) {
241 mTPCTrkLabelsFiltered.emplace_back();
242 }
243 } else { // track is accepted
244 const auto& tor = tpcTracks[itr];
245 const auto& cref = tor.getClusterRef();
246 mTracksFiltered.push_back(tor);
247 mTracksFiltered.back().shiftFirstClusterRef(int(mTrackClusIdxFiltered.size()) - tor.getClusterRef().getFirstEntry());
248 size_t idx0 = mTrackClusIdxFiltered.size();
249 int nclTrack = cref.getEntries();
250 mTrackClusIdxFiltered.resize(mTrackClusIdxFiltered.size() + nclTrack + (nclTrack + 1) / 2);
251
252 // see explanations in the TrackTPC::getClusterReference
253 uint32_t* clIndArr = reinterpret_cast<uint32_t*>(&mTrackClusIdxFiltered[idx0]);
254 uint8_t* srIndArr = reinterpret_cast<uint8_t*>(clIndArr + nclTrack);
255 for (int ic = 0; ic < nclTrack; ic++) {
256 uint8_t sectorIndex, rowIndex;
257 const auto cl = &tor.getCluster(tpcTrackClusIdx, ic, *tpcClusterIdxStruct, sectorIndex, rowIndex);
258 unsigned int oldLinear = std::distance(tpcClusterIdxStruct->clustersLinear, cl);
259 unsigned int newLinear = mClustersLinearStatus[oldLinear];
260 if (newLinear == DISCARD) {
261 LOGP(fatal, "discarded cluster {} is selected", oldLinear);
262 }
263 clIndArr[ic] = newLinear - mClusFiltered.clusterOffset[sectorIndex][rowIndex];
264 srIndArr[ic] = sectorIndex;
265 srIndArr[ic + nclTrack] = rowIndex;
266 }
267 if (mUseMC) {
268 mTPCTrkLabelsFiltered.emplace_back(tpcTrkLabels[itr]);
269 }
270 }
271 }
272}
273
275{
277 return;
278 }
279}
280
282{
283 std::vector<OutputSpec> outputs;
284 for (int i = 0; i < o2::tpc::constants::MAXSECTOR; i++) {
285 outputs.emplace_back(o2::header::gDataOriginTPC, "CLUSTERNATIVEF", i, Lifetime::Timeframe);
286 if (useMC) {
287 outputs.emplace_back(o2::header::gDataOriginTPC, "CLNATIVEMCLBLF", i, Lifetime::Timeframe);
288 }
289 }
290 outputs.emplace_back("TPC", "TRACKSF", 0, Lifetime::Timeframe);
291 outputs.emplace_back("TPC", "CLUSREFSF", 0, Lifetime::Timeframe);
292 if (useMC) {
293 outputs.emplace_back("TPC", "TRACKSMCLBLF", 0, Lifetime::Timeframe);
294 }
295
296 auto dataRequest = std::make_shared<DataRequest>();
297
298 dataRequest->requestTracks(srcTracks, useMC);
299 dataRequest->requestClusters(srcClusters, useMC);
300 dataRequest->requestPrimaryVertices(useMC);
301
302 return DataProcessorSpec{
303 "tpc-data-filter",
304 dataRequest->inputs,
305 outputs,
306 AlgorithmSpec{adaptFromTask<TPCDataFilter>(dataRequest, srcTracks, useMC)},
307 Options{
308 {"suppress-rejected", VariantType::Bool, false, {"Remove suppressed tracks instead of reducing them"}},
309 {"min-abs-tgl", VariantType::Float, 0.0f, {"suppress tracks with abs tgL less that this threshold (e.g. noise tracks)"}},
310 {"min-tpc-clusters", VariantType::Int, 0, {"suppress tracks less clusters that this threshold (e.g. noise tracks)"}},
311 {"accept-track-sources", VariantType::String, std::string{GTrackID::ALL}, {"comma-separated list of track sources to accept"}}}};
312}
313
314} // namespace o2::global
Wrapper container for different reconstructed object types.
Definition of the GeometryManager class.
int32_t i
Helper for geometry and GRP related CCDB requests.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
Utility functions for MC particles.
Definition of the Names Generator class.
Definition of the parameter class for the detector electronics.
uint32_t j
Definition RawData.h:0
Wrapper container for different reconstructed object types.
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
static GRPGeomHelper & instance()
gsl::span< const TruthElement > getLabels(uint32_t dataindex) const
static mask_t getSourcesMask(const std::string_view srcList)
static constexpr std::string_view ALL
keywork for all sources
void addElement(uint32_t dataindex, TruthElement const &element, bool noElement=false)
size_t flatten_to(ContainerType &container) const
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
void snapshot(const Output &spec, T const &object)
decltype(auto) make(const Output &spec, Args... args)
ConfigParamRegistry const & options()
Definition InitContext.h:33
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
void process(o2::globaltracking::RecoContainer &recoData)
void sendOutput(ProcessingContext &pc)
void run(ProcessingContext &pc) final
~TPCDataFilter() final=default
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
void init(InitContext &ic) final
TPCDataFilter(std::shared_ptr< DataRequest > dr, GTrackID::mask_t src, bool useMC)
GLenum src
Definition glcorearb.h:1767
GLint GLsizei count
Definition glcorearb.h:399
GLuint buffer
Definition glcorearb.h:655
GLboolean * data
Definition glcorearb.h:298
GLintptr offset
Definition glcorearb.h:660
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
constexpr o2::header::DataOrigin gDataOriginTPC
Definition DataHeader.h:576
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > Options
o2::framework::DataProcessorSpec getTPCDataFilter(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClusters, bool useMC)
create a processor spec
detail::Bracket< float > Bracketf_t
Definition Primitive2D.h:40
constexpr int MAXSECTOR
Definition Constants.h:28
constexpr int MAXGLOBALPADROW
Definition Constants.h:34
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
GTrackID getTPCContributorGID(GTrackID source) const
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
std::unique_ptr< o2::tpc::internal::getWorkflowTPCInput_ret > inputsTPCclusters
uint32_t SubSpecificationType
Definition DataHeader.h:620
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int nClustersSector[constants::MAXSECTOR]
const o2::dataformats::ConstMCTruthContainerView< o2::MCCompLabel > * clustersMCTruth
const ClusterNative * clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
const ClusterNative * clustersLinear