Project
Loading...
Searching...
No Matches
TrackMCLabelFinderSpec.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
16
18
19#include <string>
20#include <stdexcept>
21#include <unordered_map>
22#include <vector>
23
24#include <gsl/span>
25
27
30#include "Framework/Task.h"
31#include "Framework/Logger.h"
33
35
38
42
43namespace o2
44{
45namespace mch
46{
47
48using namespace std;
49using namespace o2::framework;
50
52{
53 public:
54 //_________________________________________________________________________________________________
57 {
58 LOG(info) << "initializing track MC label finder";
59 if (!mMCReader.initFromDigitContext(ic.options().get<std::string>("incontext").c_str())) {
60 throw invalid_argument("initialization of MCKinematicsReader failed");
61 }
62 double sigmaCut = ic.options().get<double>("sigma-cut");
63 mMaxMatchingChi2 = 2. * sigmaCut * sigmaCut;
64 }
65
66 //_________________________________________________________________________________________________
69 {
70 // get the input messages
71 auto digitROFs = pc.inputs().get<gsl::span<ROFRecord>>("digitrofs");
72 auto digitlabels = pc.inputs().get<const dataformats::MCTruthContainer<MCCompLabel>*>("digitlabels");
73 auto trackROFs = pc.inputs().get<gsl::span<ROFRecord>>("trackrofs");
74 auto tracks = pc.inputs().get<gsl::span<TrackMCH>>("tracks");
75 auto clusters = pc.inputs().get<gsl::span<Cluster>>("clusters");
76
77 // digit and track ROFs must be synchronized
78 int nROFs = digitROFs.size();
79 if (trackROFs.size() != nROFs) {
80 throw length_error(fmt::format("inconsistent ROFs: {} tracksROFs vs {} digitROFs", trackROFs.size(), nROFs));
81 }
82
83 std::vector<o2::MCCompLabel> tracklabels;
84
85 for (int iROF = 0; iROF < nROFs; ++iROF) {
86
87 // skip interation records with no reconstructed tracks
88 auto trackROF = trackROFs[iROF];
89 if (trackROF.getNEntries() == 0) {
90 continue;
91 }
92
93 // digits and tracks must belong to the same IR
94 auto digitROF = digitROFs[iROF];
95 if (digitROF.getBCData() != trackROF.getBCData()) {
96 throw logic_error("inconsistent ROF");
97 }
98
99 // get the MC labels of every particles contributing to that IR and produce the associated MC clusters
100 std::unordered_map<MCCompLabel, std::vector<Cluster>> mcClusterMap{};
101 for (int iDigit = digitROF.getFirstIdx(); iDigit <= digitROF.getLastIdx(); ++iDigit) {
102 for (const auto& label : digitlabels->getLabels(iDigit)) {
103 if (label.isCorrect() && mcClusterMap.count(label) == 0) {
104 makeMCClusters(mMCReader.getTrackRefs(label.getSourceID(), label.getEventID(), label.getTrackID()),
105 mcClusterMap[label]);
106 }
107 }
108 }
109
110 // try to pair every reconstructed tracks with every MC tracks to set MC labels
111 for (int iTrack = trackROF.getFirstIdx(); iTrack <= trackROF.getLastIdx(); ++iTrack) {
112 for (const auto& [label, mcClusters] : mcClusterMap) {
113 if (match(clusters.subspan(tracks[iTrack].getFirstClusterIdx(), tracks[iTrack].getNClusters()), mcClusters)) {
114 tracklabels.push_back(label);
115 break;
116 }
117 }
118 if (tracklabels.size() != iTrack + 1) {
119 tracklabels.push_back(MCCompLabel());
120 }
121 }
122 }
123
124 // send the track MC labels
125 pc.outputs().snapshot(OutputRef{"tracklabels"}, tracklabels);
126 }
127
128 private:
129 //_________________________________________________________________________________________________
131 void makeMCClusters(gsl::span<const TrackReference> mcTrackRefs, std::vector<Cluster>& mcClusters) const
132 {
133 int deId(-1);
134 int clusterIdx(0);
135 for (const auto& trackRef : mcTrackRefs) {
136 if (trackRef.getDetectorId() != o2::detectors::DetID::MCH) {
137 deId = -1;
138 continue;
139 }
140 if (trackRef.getUserId() == deId) {
141 auto& cluster = mcClusters.back();
142 cluster.x = (cluster.x + trackRef.X()) / 2.;
143 cluster.y = (cluster.y + trackRef.Y()) / 2.;
144 cluster.z = (cluster.z + trackRef.Z()) / 2.;
145 deId = -1; // to create a new cluster in case the track re-enter the DE (loop)
146 } else {
147 deId = trackRef.getUserId();
148 mcClusters.push_back({trackRef.X(), trackRef.Y(), trackRef.Z(), 0.f, 0.f,
149 Cluster::buildUniqueId(deId / 100 - 1, deId, clusterIdx++), 0u, 0u});
150 }
151 }
152 }
153
154 //_________________________________________________________________________________________________
158 bool match(gsl::span<const Cluster> clusters, const std::vector<Cluster>& mcClusters) const
159 {
160 int nMatched(0);
161 bool hasMatched[5] = {false, false, false, false, false};
162 for (const auto& cluster : clusters) {
163 for (const auto& mcCluster : mcClusters) {
164 if (cluster.getDEId() == mcCluster.getDEId()) {
165 double dx = cluster.x - mcCluster.x;
166 double dy = cluster.y - mcCluster.y;
167 double chi2 = dx * dx / (cluster.ex * cluster.ex) + dy * dy / (cluster.ey * cluster.ey);
168 if (chi2 <= mMaxMatchingChi2) {
169 hasMatched[cluster.getChamberId() / 2] = true;
170 ++nMatched;
171 break;
172 }
173 }
174 }
175 }
176 return ((hasMatched[0] || hasMatched[1]) && (hasMatched[3] || hasMatched[4]) && 2 * nMatched > clusters.size());
177 }
178
179 steer::MCKinematicsReader mMCReader{};
180 double mMaxMatchingChi2 = 32.;
181};
182
183//_________________________________________________________________________________________________
185 const char* digitRofDataDescription,
186 const char* digitLabelDataDescription)
187{
188 std::string input =
189 fmt::format("digitrofs:MCH/{}/0;digitlabels:MCH/{}/0", digitRofDataDescription,
190 digitLabelDataDescription);
191 input +=
192 ";trackrofs:MCH/TRACKROFS/0;"
193 "tracks:MCH/TRACKS/0;"
194 "clusters:MCH/TRACKCLUSTERS/0";
195 return DataProcessorSpec{
196 specName,
197 o2::framework::select(input.c_str()),
198 Outputs{OutputSpec{{"tracklabels"}, "MCH", "TRACKLABELS", 0, Lifetime::Timeframe}},
199 AlgorithmSpec{adaptFromTask<TrackMCLabelFinderTask>()},
200 Options{{"incontext", VariantType::String, "collisioncontext.root", {"Take collision context from this file"}},
201 {"sigma-cut", VariantType::Double, 4., {"Sigma cut to match simulated and reconstructed clusters"}}}};
202}
203
204} // end namespace mch
205} // end namespace o2
Definition of the MCH cluster minimal structure.
Definition of the MCH ROFrame record.
Definition of the MCH track.
Definition of a data processor to match the reconstructed tracks with the simulated ones.
const char * specName
A container to hold and manage MC truth information/labels.
static constexpr ID MCH
Definition DetID.h:72
void snapshot(const Output &spec, T const &object)
ConfigParamRegistry const & options()
Definition InitContext.h:33
decltype(auto) get(R binding, int part=0) const
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
void init(framework::InitContext &ic)
prepare the task from the context
void run(framework::ProcessingContext &pc)
assign every reconstructed track a MC label, pointing to the corresponding particle or fake
bool initFromDigitContext(std::string_view filename)
gsl::span< o2::TrackReference > getTrackRefs(int source, int event, int track) const
get all primaries for a certain event
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > select(char const *matcher="")
std::vector< OutputSpec > Outputs
o2::framework::DataProcessorSpec getTrackMCLabelFinderSpec(const char *specName, const char *digitRofDataDescription, const char *digitLabelDataDescription)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters