Project
Loading...
Searching...
No Matches
TrackSamplerSpec.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 "TrackSamplerSpec.h"
18
19#include <iostream>
20#include <fstream>
21#include <stdexcept>
22
27#include "Framework/Lifetime.h"
28#include "Framework/Output.h"
29#include "Framework/OutputRef.h"
30#include "Framework/Task.h"
31#include "Framework/Logger.h"
32
36#include "MCHBase/TrackBlock.h"
37#include "TrackAtVtxStruct.h"
38
39namespace o2
40{
41namespace mch
42{
43
44using namespace std;
45using namespace o2::framework;
46
48{
49 public:
50 //_________________________________________________________________________________________________
52 {
54 LOG(info) << "initializing track sampler";
55
56 auto inputFileName = ic.options().get<std::string>("infile");
57 mInputFile.open(inputFileName, ios::binary);
58 if (!mInputFile.is_open()) {
59 throw invalid_argument("cannot open input file" + inputFileName);
60 }
61 if (mInputFile.peek() == EOF) {
62 throw length_error("input file is empty");
63 }
64
65 mNEventsPerTF = ic.options().get<int>("nEventsPerTF");
66 if (mNEventsPerTF < 1) {
67 throw invalid_argument("number of events per time frame must be >= 1");
68 }
69
70 auto stop = [this]() {
72 LOG(info) << "stop track sampler";
73 this->mInputFile.close();
74 };
75 ic.services().get<CallbackService>().set<CallbackService::Id::Stop>(stop);
76 }
77
78 //_________________________________________________________________________________________________
80 {
82
83 static uint32_t event(0);
84
85 // reached eof
86 if (mInputFile.peek() == EOF) {
87 pc.services().get<ControlService>().endOfStream();
88 // pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
89 return;
90 }
91
92 // create the output messages
93 auto& rofs = pc.outputs().make<std::vector<ROFRecord>>(OutputRef{"rofs"});
94 auto& tracks = pc.outputs().make<std::vector<TrackMCH>>(OutputRef{"tracks"});
95 auto& clusters = pc.outputs().make<std::vector<Cluster>>(OutputRef{"clusters"});
96
97 // loop over the requested number of events (or until eof) and fill the messages
98 for (int iEvt = 0; iEvt < mNEventsPerTF && mInputFile.peek() != EOF; ++iEvt) {
99 int nTracks = readOneEvent(tracks, clusters);
100 rofs.emplace_back(o2::InteractionRecord{0, event++}, tracks.size() - nTracks, nTracks);
101 }
102 }
103
104 //_________________________________________________________________________________________________
107 {
110
111 // read the number of tracks at vertex, MCH tracks and attached clusters
112 int nTracksAtVtx(-1);
113 mInputFile.read(reinterpret_cast<char*>(&nTracksAtVtx), sizeof(int));
114 if (mInputFile.fail()) {
115 throw length_error("invalid input");
116 }
117 int nMCHTracks(-1);
118 mInputFile.read(reinterpret_cast<char*>(&nMCHTracks), sizeof(int));
119 if (mInputFile.fail()) {
120 throw length_error("invalid input");
121 }
122 int nClusters(-1);
123 mInputFile.read(reinterpret_cast<char*>(&nClusters), sizeof(int));
124 if (mInputFile.fail()) {
125 throw length_error("invalid input");
126 }
127
128 if (nTracksAtVtx < 0 || nMCHTracks < 0 || nClusters < 0) {
129 throw length_error("invalid input");
130 }
131 if (nMCHTracks > 0 && nClusters == 0) {
132 throw length_error("clusters are missing");
133 }
134
135 // skip the tracks at vertex if any
136 if (nTracksAtVtx > 0) {
137 mInputFile.seekg(nTracksAtVtx * sizeof(TrackAtVtxStruct), std::ios::cur);
138 if (mInputFile.fail()) {
139 throw length_error("invalid input");
140 }
141 }
142
143 if (nMCHTracks > 0) {
144
145 // read the MCH tracks
146 int trackOffset = tracks.size();
147 tracks.resize(trackOffset + nMCHTracks);
148 mInputFile.read(reinterpret_cast<char*>(&tracks[trackOffset]), nMCHTracks * sizeof(TrackMCH));
149 if (mInputFile.fail()) {
150 throw length_error("invalid input");
151 }
152
153 // read the attached clusters
154 int clusterOffset = clusters.size();
155 clusters.resize(clusterOffset + nClusters);
156 mInputFile.read(reinterpret_cast<char*>(&clusters[clusterOffset]), nClusters * sizeof(Cluster));
157 if (mInputFile.fail()) {
158 throw length_error("invalid input");
159 }
160
161 // modify the cluster references
162 for (auto itTrack = tracks.begin() + trackOffset; itTrack < tracks.end(); ++itTrack) {
163 itTrack->setClusterRef(clusterOffset, itTrack->getNClusters());
164 clusterOffset += itTrack->getNClusters();
165 }
166 if (clusterOffset != clusters.size()) {
167 throw length_error("inconsistent cluster references");
168 }
169 }
170
171 return nMCHTracks;
172 }
173
174 std::ifstream mInputFile{};
176};
177
178//_________________________________________________________________________________________________
180{
181 Outputs outputs{};
182 if (forTrackFitter) {
183 outputs.emplace_back(OutputLabel{"rofs"}, "MCH", "TRACKROFSIN", 0, Lifetime::Timeframe);
184 outputs.emplace_back(OutputLabel{"tracks"}, "MCH", "TRACKSIN", 0, Lifetime::Timeframe);
185 outputs.emplace_back(OutputLabel{"clusters"}, "MCH", "TRACKCLUSTERSIN", 0, Lifetime::Timeframe);
186 } else {
187 outputs.emplace_back(OutputLabel{"rofs"}, "MCH", "TRACKROFS", 0, Lifetime::Timeframe);
188 outputs.emplace_back(OutputLabel{"tracks"}, "MCH", "TRACKS", 0, Lifetime::Timeframe);
189 outputs.emplace_back(OutputLabel{"clusters"}, "MCH", "TRACKCLUSTERS", 0, Lifetime::Timeframe);
190 }
191
192 return DataProcessorSpec{
193 specName,
194 Inputs{},
195 outputs,
196 AlgorithmSpec{adaptFromTask<TrackSamplerTask>()},
197 Options{{"infile", VariantType::String, "", {"input filename"}},
198 {"nEventsPerTF", VariantType::Int, 1, {"number of events per time frame"}}}};
199}
200
201} // end namespace mch
202} // 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 read and send tracks.
const char * specName
int nClusters
decltype(auto) make(const Output &spec, Args... args)
ServiceRegistryRef services()
Definition InitContext.h:34
ConfigParamRegistry const & options()
Definition InitContext.h:33
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
ServiceRegistryRef services()
The services registry associated with this processing context.
MCH track external format.
Definition TrackMCH.h:34
void run(framework::ProcessingContext &pc)
void init(framework::InitContext &ic)
int mNEventsPerTF
number of events per time frame
std::ifstream mInputFile
input file
int readOneEvent(std::vector< TrackMCH, o2::pmr::polymorphic_allocator< TrackMCH > > &tracks, std::vector< Cluster, o2::pmr::polymorphic_allocator< Cluster > > &clusters)
struct _cl_event * event
Definition glcorearb.h:2982
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 getTrackSamplerSpec(const char *specName, bool forTrackFitter)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
cluster minimal structure
Definition Cluster.h:31
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters