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.
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 PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
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 ...
Defining DataPointCompositeObject explicitly as copiable.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters