Project
Loading...
Searching...
No Matches
TrackSinkSpec.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
17#include "TrackSinkSpec.h"
18
19#include <iostream>
20#include <fstream>
21#include <stdexcept>
22#include <vector>
23
24#include <gsl/span>
25
30#include "Framework/Lifetime.h"
31#include "Framework/Task.h"
32#include "Framework/Logger.h"
33
37#include "MCHBase/TrackBlock.h"
38#include "TrackAtVtxStruct.h"
39
40namespace o2
41{
42namespace mch
43{
44
45using namespace std;
46using namespace o2::framework;
47
49{
50 public:
51 //_________________________________________________________________________________________________
53 {
55 LOG(info) << "initializing track sink";
56
57 auto outputFileName = ic.options().get<std::string>("outfile");
58 mOutputFile.open(outputFileName, ios::out | ios::binary);
59 if (!mOutputFile.is_open()) {
60 throw invalid_argument("Cannot open output file" + outputFileName);
61 }
62
63 auto stop = [this]() {
65 LOG(info) << "stop track sink";
66 this->mOutputFile.close();
67 };
68 ic.services().get<CallbackService>().set<CallbackService::Id::Stop>(stop);
69 }
70
71 //_________________________________________________________________________________________________
73 {
75
76 // get the input messages
77 gsl::span<const ROFRecord> rofs{};
78 gsl::span<const TrackMCH> tracks{};
79 gsl::span<const Cluster> clusters{};
80 if (pc.inputs().getPos("rofs") >= 0) {
81 rofs = pc.inputs().get<gsl::span<ROFRecord>>("rofs");
82 tracks = pc.inputs().get<gsl::span<TrackMCH>>("tracks");
83 clusters = pc.inputs().get<gsl::span<Cluster>>("clusters");
84 }
85 gsl::span<const char> tracksAtVtx{};
86 if (pc.inputs().getPos("tracksAtVtx") >= 0) {
87 tracksAtVtx = pc.inputs().get<gsl::span<char>>("tracksAtVtx");
88 }
89
90 // loop over events based on ROF records, if any, or based on the tracks-at-vertex message otherwise
91 if (!rofs.empty()) {
92
93 int tracksAtVtxOffset(0);
94 std::vector<TrackMCH> eventTracks{};
95 for (const auto& rof : rofs) {
96
97 // get the MCH tracks, attached clusters and corresponding tracks at vertex (if any)
98 auto eventClusters = getEventTracksAndClusters(rof, tracks, clusters, eventTracks);
99 auto eventTracksAtVtx = getEventTracksAtVtx(tracksAtVtx, tracksAtVtxOffset);
100
101 // write the number of tracks at vertex, MCH tracks and attached clusters
102 int nEventTracksAtVtx = eventTracksAtVtx.size() / sizeof(TrackAtVtxStruct);
103 mOutputFile.write(reinterpret_cast<char*>(&nEventTracksAtVtx), sizeof(int));
104 int nEventTracks = eventTracks.size();
105 mOutputFile.write(reinterpret_cast<char*>(&nEventTracks), sizeof(int));
106 int nEventClusters = eventClusters.size();
107 mOutputFile.write(reinterpret_cast<char*>(&nEventClusters), sizeof(int));
108
109 // write the tracks at vertex, MCH tracks and attached clusters
110 mOutputFile.write(eventTracksAtVtx.data(), eventTracksAtVtx.size());
111 mOutputFile.write(reinterpret_cast<const char*>(eventTracks.data()), eventTracks.size() * sizeof(TrackMCH));
112 mOutputFile.write(reinterpret_cast<const char*>(eventClusters.data()), eventClusters.size_bytes());
113 }
114
115 // at this point we should have dumped all the tracks at vertex, if any
116 if (tracksAtVtxOffset != tracksAtVtx.size()) {
117 throw length_error("inconsistent payload");
118 }
119
120 } else if (!tracksAtVtx.empty()) {
121
122 int tracksAtVtxOffset(0);
123 int zero(0);
124 while (tracksAtVtxOffset != tracksAtVtx.size()) {
125
126 // get the tracks at vertex
127 auto eventTracksAtVtx = getEventTracksAtVtx(tracksAtVtx, tracksAtVtxOffset);
128
129 // write the number of tracks at vertex (number of MCH tracks and attached clusters = 0)
130 int nEventTracksAtVtx = eventTracksAtVtx.size() / sizeof(TrackAtVtxStruct);
131 mOutputFile.write(reinterpret_cast<char*>(&nEventTracksAtVtx), sizeof(int));
132 mOutputFile.write(reinterpret_cast<char*>(&zero), sizeof(int));
133 mOutputFile.write(reinterpret_cast<char*>(&zero), sizeof(int));
134
135 // write the tracks at vertex
136 mOutputFile.write(eventTracksAtVtx.data(), eventTracksAtVtx.size());
137 }
138
139 } else {
140
141 int zero(0);
142 mOutputFile.write(reinterpret_cast<char*>(&zero), sizeof(int));
143 mOutputFile.write(reinterpret_cast<char*>(&zero), sizeof(int));
144 mOutputFile.write(reinterpret_cast<char*>(&zero), sizeof(int));
145 }
146 }
147
148 //_________________________________________________________________________________________________
149 gsl::span<const Cluster> getEventTracksAndClusters(const ROFRecord& rof, gsl::span<const TrackMCH> tracks,
150 gsl::span<const Cluster> clusters,
151 std::vector<TrackMCH>& eventTracks) const
152 {
156
157 eventTracks.clear();
158
159 if (rof.getNEntries() < 1) {
160 return {};
161 }
162
163 if (rof.getLastIdx() >= tracks.size()) {
164 throw length_error("missing tracks");
165 }
166
167 eventTracks.insert(eventTracks.end(), tracks.begin() + rof.getFirstIdx(), tracks.begin() + rof.getLastIdx() + 1);
168
169 int clusterIdxOffset = eventTracks.front().getFirstClusterIdx();
170 for (auto& track : eventTracks) {
171 track.setClusterRef(track.getFirstClusterIdx() - clusterIdxOffset, track.getNClusters());
172 }
173
174 if (eventTracks.back().getLastClusterIdx() + clusterIdxOffset >= clusters.size()) {
175 throw length_error("missing clusters");
176 }
177
178 return clusters.subspan(clusterIdxOffset, eventTracks.back().getLastClusterIdx() + 1);
179 }
180
181 //_________________________________________________________________________________________________
182 gsl::span<const char> getEventTracksAtVtx(gsl::span<const char> tracksAtVtx, int& tracksAtVtxOffset) const
183 {
186
187 if (tracksAtVtx.empty()) {
188 return {};
189 }
190
191 if (tracksAtVtx.size() - tracksAtVtxOffset < sizeof(int)) {
192 throw length_error("inconsistent payload");
193 }
194
195 int nEventTracksAtVtx = *reinterpret_cast<const int*>(&tracksAtVtx[tracksAtVtxOffset]);
196 tracksAtVtxOffset += sizeof(int);
197
198 int payloadSize = nEventTracksAtVtx * sizeof(TrackAtVtxStruct);
199 if (tracksAtVtx.size() - tracksAtVtxOffset < payloadSize) {
200 throw length_error("inconsistent payload");
201 }
202
203 tracksAtVtxOffset += payloadSize;
204 return tracksAtVtx.subspan(tracksAtVtxOffset - payloadSize, payloadSize);
205 }
206
207 std::ofstream mOutputFile{};
208};
209
210//_________________________________________________________________________________________________
211o2::framework::DataProcessorSpec getTrackSinkSpec(const char* specName, bool mchTracks, bool tracksAtVtx)
212{
213 Inputs inputs{};
214 if (mchTracks) {
215 inputs.emplace_back("rofs", "MCH", "TRACKROFS", 0, Lifetime::Timeframe);
216 inputs.emplace_back("tracks", "MCH", "TRACKS", 0, Lifetime::Timeframe);
217 inputs.emplace_back("clusters", "MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe);
218 }
219 if (tracksAtVtx) {
220 inputs.emplace_back("tracksAtVtx", "MCH", "TRACKSATVERTEX", 0, Lifetime::Timeframe);
221 }
222 if (inputs.empty()) {
223 throw invalid_argument("nothing to write");
224 }
225
226 return DataProcessorSpec{
227 specName,
228 inputs,
229 Outputs{},
230 AlgorithmSpec{adaptFromTask<TrackSinkTask>()},
231 Options{{"outfile", VariantType::String, "AliESDs.out.dat", {"output filename"}}}};
232}
233
234} // end namespace mch
235} // end namespace o2
Definition of the MCH cluster minimal structure.
std::vector< o2::its::TrackITS > tracks
Definition of the MCH ROFrame record.
Definition of the MCH track parameters minimal structure.
Definition of the MCH track.
Definition of a data processor to print the tracks.
const char * specName
ServiceRegistryRef services()
Definition InitContext.h:34
ConfigParamRegistry const & options()
Definition InitContext.h:33
int getPos(const char *name) const
decltype(auto) get(R binding, int part=0) const
InputRecord & inputs()
The inputs associated with this processing context.
int getLastIdx() const
get the index of the last associated object
Definition ROFRecord.h:59
int getNEntries() const
get the number of associated objects
Definition ROFRecord.h:55
int getFirstIdx() const
get the index of the first associated object
Definition ROFRecord.h:57
MCH track external format.
Definition TrackMCH.h:34
std::ofstream mOutputFile
output file
void init(framework::InitContext &ic)
void run(framework::ProcessingContext &pc)
gsl::span< const Cluster > getEventTracksAndClusters(const ROFRecord &rof, gsl::span< const TrackMCH > tracks, gsl::span< const Cluster > clusters, std::vector< TrackMCH > &eventTracks) const
gsl::span< const char > getEventTracksAtVtx(gsl::span< const char > tracksAtVtx, int &tracksAtVtxOffset) const
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > Inputs
std::vector< OutputSpec > Outputs
o2::framework::DataProcessorSpec getTrackSinkSpec(const char *specName, bool mchTracks, bool tracksAtVtx)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters