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 //_________________________________________________________________________________________________
105 int readOneEvent(std::vector<TrackMCH, o2::pmr::polymorphic_allocator<TrackMCH>>& tracks,
106 std::vector<Cluster, o2::pmr::polymorphic_allocator<Cluster>>& clusters)
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.
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 PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
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 ...
Defining DataPointCompositeObject explicitly as copiable.
cluster minimal structure
Definition Cluster.h:31
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters