Project
Loading...
Searching...
No Matches
TOFClusterizerSpec.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#include "Framework/Lifetime.h"
17#include "Framework/Task.h"
18#include "Headers/DataHeader.h"
29#include "TOFBase/CalibTOFapi.h"
30#include "TStopwatch.h"
33#include "TOFBase/Utils.h"
37#include "TSystem.h"
38
39#include <memory> // for make_shared, make_unique, unique_ptr
40#include <vector>
41
42// RSTODO to remove once the framework will start propagating the header.firstTForbit
44
45using namespace o2::framework;
46using namespace o2::dataformats;
47
48namespace o2
49{
50namespace tof
51{
52
53// use the tasking system of DPL
54// just need to implement 2 special methods init + run (there is no need to inherit from anything)
56{
57 bool mUseMC = true;
58 bool mUseCCDB = false;
59 bool mIsCalib = false;
60 bool mIsCosmic = false;
61 int mTimeWin = 5000;
62 bool mUpdateCCDB = false;
63 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
64 std::string mCCDBurl;
65 o2::tof::CalibTOFapi* mCalibApi = nullptr;
66
67 public:
68 explicit TOFDPLClustererTask(std::shared_ptr<o2::base::GRPGeomRequest> gr, bool useMC, bool useCCDB, bool doCalib, bool isCosmic, std::string ccdb_url, bool isForCalib) : mGGCCDBRequest(gr), mUseMC(useMC), mUseCCDB(useCCDB), mIsCalib(doCalib), mIsCosmic(isCosmic), mCCDBurl(ccdb_url), mForCalib(isForCalib) {}
69
71 {
72 // nothing special to be set up
73 mTimer.Stop();
74 mTimer.Reset();
76 mTimeWin = ic.options().get<int>("cluster-time-window");
77 LOG(debug) << "Is calibration from cluster on? " << mIsCalib;
78 LOG(debug) << "DeltaTime for clusterization = " << mTimeWin << " ps";
79 LOG(debug) << "Is cosmics? " << mIsCosmic;
80
81 mClusterer.setCalibFromCluster(mIsCalib);
82 mClusterer.setDeltaTforClustering(mTimeWin);
83 mClusterer.setCalibStored(mForCalib);
84
85 mMultPerLongBC.resize(o2::base::GRPGeomHelper::instance().getNHBFPerTF() * o2::constants::lhc::LHCMaxBunches);
86 std::fill(mMultPerLongBC.begin(), mMultPerLongBC.end(), 0);
87 }
88
90 {
92 return;
93 }
94 if (matcher == ConcreteDataMatcher("TOF", "DiagnosticCal", 0)) {
95 mUpdateCCDB = true;
96 return;
97 }
98 if (matcher == ConcreteDataMatcher("TOF", "LHCphaseCal", 0)) {
99 mUpdateCCDB = true;
100 return;
101 }
102 if (matcher == ConcreteDataMatcher("TOF", "ChannelCalibCal", 0)) {
103 mUpdateCCDB = true;
104 return;
105 }
106 }
107
109 {
110 mTimer.Start(false);
111 // reset multiplicity counters
112 std::fill(mMultPerLongBC.begin(), mMultPerLongBC.end(), 0);
113
114 // get digit data
115 auto digits = pc.inputs().get<gsl::span<o2::tof::Digit>>("tofdigits");
116 auto row = pc.inputs().get<gsl::span<o2::tof::ReadoutWindowData>>("readoutwin");
117 auto dia = pc.inputs().get<o2::tof::Diagnostic*>("diafreq");
118 auto patterns = pc.inputs().get<pmr::vector<unsigned char>>("patterns");
119 updateTimeDependentParams(pc);
120 const auto& tinfo = pc.services().get<o2::framework::TimingInfo>();
121 mClusterer.setFirstOrbit(tinfo.firstTForbit);
122
123 auto labelvector = std::make_shared<std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>>();
124 if (mUseMC) {
125 auto digitlabels = pc.inputs().get<std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>*>("tofdigitlabels");
126 *labelvector.get() = std::move(*digitlabels);
127 mClusterer.setMCTruthContainer(&mClsLabels);
128 mClsLabels.clear();
129 }
130
131 if (!mUseCCDB && !mCalibApi) { // calibration objects set to zero
132 auto* lhcPhaseDummy = new o2::dataformats::CalibLHCphaseTOF();
133 auto* channelCalibDummy = new o2::dataformats::CalibTimeSlewingParamTOF();
134
135 lhcPhaseDummy->addLHCphase(0, 0);
136 lhcPhaseDummy->addLHCphase(2000000000, 0);
137
138 for (int ich = 0; ich < o2::dataformats::CalibTimeSlewingParamTOF::NCHANNELS; ich++) {
139 channelCalibDummy->addTimeSlewingInfo(ich, 0, 0);
142 channelCalibDummy->setFractionUnderPeak(sector, channelInSector, 1);
143 }
144 mCalibApi = new o2::tof::CalibTOFapi(long(0), lhcPhaseDummy, channelCalibDummy);
145 }
146
147 mCalibApi->setTimeStamp(tinfo.creation / 1000);
148
149 mClusterer.setCalibApi(mCalibApi);
150
151 mClusterer.clearDiagnostic();
152 mClusterer.addDiagnostic(*dia);
153
154 // call actual clustering routine
155 mClustersArray.clear();
156 if (mIsCalib) {
157 mClusterer.getInfoFromCluster()->clear();
158 }
159
160 if (mIsCosmic) {
161 mCosmicProcessor.clear();
162 }
163
164 for (unsigned int i = 0; i < row.size(); i++) {
165 //fill trm pattern but process them in clusterize since they are for readout windows
166 mCalibApi->resetTRMErrors();
167
168 // loop over crates
169 int kw = 0;
170 for (int crate = 0; crate < 72; crate++) {
171 int slot = -1;
172 int nwords = kw + row[i].getDiagnosticInCrate(crate);
173 int eword;
174 for (; kw < nwords; kw++) {
175 if (patterns[kw] > 28) { // new slot
176 if (slot > -1) { // fill previous
177 mCalibApi->processError(crate, slot, eword);
178 }
179 slot = patterns[kw] - 28;
180 eword = 0;
181
182 if (slot < 3 || slot > 12) { // not a valid slot -> don't fill otherwise mapping fails (slot 1 crate 0 is a bad condition)
183 slot = -1;
184 // LOG(info) << "not a valid slot in diagnostic words: slot = " << slot << " for crate " << crate;
185 }
186 } else if (slot > -1) { // process error in this slot
187 eword += 1 << patterns[kw];
188 }
189 }
190 } // end crate loop
191
192 //printf("# TOF readout window for clusterization = %d/%lu (N digits = %d)\n", i, row.size(), row[i].size());
193 auto digitsRO = row[i].getBunchChannelData(digits);
194 mReader.setDigitArray(&digitsRO);
195
196 if (mIsCosmic) {
197 mCosmicProcessor.process(mReader, i != 0);
198 }
199
200 if (mUseMC) {
201 mClusterer.process(mReader, mClustersArray, &(labelvector->at(i)));
202 } else {
203 mClusterer.process(mReader, mClustersArray, nullptr);
204 }
205 }
206 LOG(debug) << "TOF CLUSTERER : TRANSFORMED " << digits.size()
207 << " DIGITS TO " << mClustersArray.size() << " CLUSTERS";
208
209 // fill multiplicty counters
210 int det[5];
211 float pos[3];
212 for (const auto& cls : mClustersArray) {
213 double timeCl = cls.getTime();
214 int channel = cls.getMainContributingChannel(); // channel index
215 o2::tof::Geo::getVolumeIndices(channel, det); // detector index
216 o2::tof::Geo::getPos(det, pos); // detector position
217 timeCl -= sqrt(pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]) * 33.3564095 - 3000; // subtract minimal arrival time (keeping 3 ns of margin)
218
219 int longBC = int(timeCl * o2::tof::Geo::BC_TIME_INPS_INV);
220 if (longBC < 0 || longBC >= mMultPerLongBC.size()) {
221 continue;
222 }
223 mMultPerLongBC[longBC]++;
224 }
225
226 // send clusters
227 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CLUSTERS", 0}, mClustersArray);
228 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CLUSTERSMULT", 0}, mMultPerLongBC);
229 // send labels
230 if (mUseMC) {
231 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "CLUSTERSMCTR", 0}, mClsLabels);
232 }
233
234 if (mIsCalib) {
235 std::vector<CalibInfoCluster>* clusterCalInfo = mClusterer.getInfoFromCluster();
236 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "INFOCALCLUS", 0}, *clusterCalInfo);
237 }
238
239 if (mIsCosmic) {
240 std::vector<CosmicInfo>* cosmicInfo = mCosmicProcessor.getCosmicInfo();
241 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "INFOCOSMICS", 0}, *cosmicInfo);
242 std::vector<CalibInfoTrackCl>* cosmicTrack = mCosmicProcessor.getCosmicTrack();
243 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "INFOTRACKCOS", 0}, *cosmicTrack);
244 std::vector<int>* cosmicTrackSize = mCosmicProcessor.getCosmicTrackSize();
245 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "INFOTRACKSIZE", 0}, *cosmicTrackSize);
246 }
247
248 mTimer.Stop();
249 }
250
252 {
253 LOGF(debug, "TOF Clusterer total timing: Cpu: %.3e Real: %.3e s in %d slots",
254 mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
255 }
256
257 private:
258 void updateTimeDependentParams(ProcessingContext& pc)
259 {
261 static bool initOnceDone = false;
262 if (!initOnceDone) { // this params need to be queried only once
263 initOnceDone = true;
264 const auto bcs = o2::base::GRPGeomHelper::instance().getGRPLHCIF()->getBunchFilling().getFilledBCs();
265 for (auto bc : bcs) {
267 }
268 }
269
270 if (mUseCCDB) { // read calibration objects from ccdb
271 // check LHC phase
272 const auto lhcPhaseIn = pc.inputs().get<o2::dataformats::CalibLHCphaseTOF*>("tofccdbLHCphase");
273 const auto channelCalibIn = pc.inputs().get<o2::dataformats::CalibTimeSlewingParamTOF*>("tofccdbChannelCalib");
274 const auto diagnosticIn = pc.inputs().get<o2::tof::Diagnostic*>("tofccdbDia");
275
276 if (!mCalibApi) {
277 o2::dataformats::CalibLHCphaseTOF* lhcPhase = new o2::dataformats::CalibLHCphaseTOF(std::move(*lhcPhaseIn));
278 o2::dataformats::CalibTimeSlewingParamTOF* channelCalib = new CalibTimeSlewingParamTOF(std::move(*channelCalibIn));
279 o2::tof::Diagnostic* diagnostic = new o2::tof::Diagnostic(std::move(*diagnosticIn));
280 mCalibApi = new o2::tof::CalibTOFapi(long(0), lhcPhase, channelCalib, diagnostic);
281 mCalibApi->loadDiagnosticFrequencies();
282 mUpdateCCDB = false;
283 } else { // update if necessary
284 if (mUpdateCCDB) {
285 LOG(info) << "Update CCDB objects since new";
286 delete mCalibApi;
288 o2::dataformats::CalibTimeSlewingParamTOF* channelCalib = new CalibTimeSlewingParamTOF(*channelCalibIn);
289 o2::tof::Diagnostic* diagnostic = new o2::tof::Diagnostic(std::move(*diagnosticIn));
290 mCalibApi = new o2::tof::CalibTOFapi(long(0), lhcPhase, channelCalib, diagnostic);
291 mCalibApi->loadDiagnosticFrequencies();
292 mUpdateCCDB = false;
293 } else {
294 // do nothing
295 }
296 }
297 }
298 }
299
300 DigitDataReader mReader;
301 Clusterer mClusterer;
302 CosmicProcessor mCosmicProcessor;
303 TStopwatch mTimer;
304
305 std::vector<Cluster> mClustersArray;
306 MCLabelContainer mClsLabels;
307 std::vector<CalibInfoCluster> mClusterCalInfo;
308 bool mForCalib = false;
309
310 std::vector<int> mMultPerLongBC;
311};
312
313o2::framework::DataProcessorSpec getTOFClusterizerSpec(bool useMC, bool useCCDB, bool doCalib, bool isCosmic, std::string ccdb_url, bool isForCalib)
314{
315 std::vector<InputSpec> inputs;
316 inputs.emplace_back("tofdigits", o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe);
317 inputs.emplace_back("readoutwin", o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe);
318 inputs.emplace_back("diafreq", o2::header::gDataOriginTOF, "DIAFREQ", 0, Lifetime::Timeframe);
319 inputs.emplace_back("patterns", o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe);
320
321 if (useCCDB) {
322 // inputs.emplace_back("tofccdbLHCphase", "TOF", "StatusTOF", 0, Lifetime::Condition, ccdbParamSpec("TOF/Calib/Status"));
323 inputs.emplace_back("tofccdbDia", "TOF", "DiagnosticCal", 0, Lifetime::Condition, ccdbParamSpec("TOF/Calib/Diagnostic"));
324 inputs.emplace_back("tofccdbLHCphase", "TOF", "LHCphaseCal", 0, Lifetime::Condition, ccdbParamSpec("TOF/Calib/LHCphase"));
325 inputs.emplace_back("tofccdbChannelCalib", "TOF", "ChannelCalibCal", 0, Lifetime::Condition, ccdbParamSpec("TOF/Calib/ChannelCalib"));
326 // inputs.emplace_back("tofccdbChannelCalib", o2::header::gDataOriginTOF, "ChannelCalib");
327 }
328 if (useMC) {
329 inputs.emplace_back("tofdigitlabels", o2::header::gDataOriginTOF, "DIGITSMCTR", 0, Lifetime::Timeframe);
330 }
331
332 std::vector<OutputSpec> outputs;
333 outputs.emplace_back(o2::header::gDataOriginTOF, "CLUSTERS", 0, Lifetime::Timeframe);
334 outputs.emplace_back(o2::header::gDataOriginTOF, "CLUSTERSMULT", 0, Lifetime::Timeframe);
335 if (useMC) {
336 outputs.emplace_back(o2::header::gDataOriginTOF, "CLUSTERSMCTR", 0, Lifetime::Timeframe);
337 }
338
339 if (doCalib) {
340 outputs.emplace_back(o2::header::gDataOriginTOF, "INFOCALCLUS", 0, Lifetime::Timeframe);
341 }
342 if (isCosmic) {
343 outputs.emplace_back(o2::header::gDataOriginTOF, "INFOCOSMICS", 0, Lifetime::Timeframe);
344 outputs.emplace_back(o2::header::gDataOriginTOF, "INFOTRACKCOS", 0, Lifetime::Timeframe);
345 outputs.emplace_back(o2::header::gDataOriginTOF, "INFOTRACKSIZE", 0, Lifetime::Timeframe);
346 }
347 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false, // orbitResetTime
348 true, // GRPECS=true
349 true, // GRPLHCIF
350 false, // GRPMagField
351 false, // askMatLUT
353 inputs,
354 true);
355 return DataProcessorSpec{
356 "TOFClusterer",
357 inputs,
358 outputs,
359 AlgorithmSpec{adaptFromTask<TOFDPLClustererTask>(ggRequest, useMC, useCCDB, doCalib, isCosmic, ccdb_url, isForCalib)},
360 Options{{"cluster-time-window", VariantType::Int, 5000, {"time window for clusterization in ps"}}}};
361}
362
363} // end namespace tof
364} // end namespace o2
Class to store the output of the matching to TOF for calibration.
Class to use TOF calibration (decalibration, calibration)
Class to store the output of the matching to TOF for calibration.
Info from cosmic.
Managing digitsi in a RO window to provide cosmics candidates.
Definition of the TOF cluster.
Definition of the TOF hit reader.
uint64_t bc
Definition RawEventData.h:5
int32_t i
Helper for geometry and GRP related CCDB requests.
Definition of a container to keep Monte Carlo truth external to simulation objects.
uint16_t pos
Definition RawData.h:3
Definition of the TOF cluster finder.
std::ostringstream debug
void checkUpdates(o2::framework::ProcessingContext &pc)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
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.
ServiceRegistryRef services()
The services registry associated with this processing context.
void setTimeStamp(long t)
Definition CalibTOFapi.h:58
void processError(int crate, int trm, int mask)
void clearDiagnostic()
Definition Clusterer.h:73
void setDeltaTforClustering(float val)
Definition Clusterer.h:65
std::vector< o2::tof::CalibInfoCluster > * getInfoFromCluster()
Definition Clusterer.h:67
void setCalibStored(bool val=true)
Definition Clusterer.h:80
void setFirstOrbit(uint64_t orb)
void setCalibFromCluster(bool val=1)
Definition Clusterer.h:62
void setCalibApi(CalibApi *calibApi)
Definition Clusterer.h:52
void addDiagnostic(const Diagnostic &dia)
Definition Clusterer.h:68
void process(DataReader &r, std::vector< Cluster > &clusters, MCLabelContainer const *digitMCTruth)
Definition Clusterer.cxx:25
void setMCTruthContainer(o2::dataformats::MCTruthContainer< o2::MCCompLabel > *truth)
Definition Clusterer.h:50
std::vector< CalibInfoTrackCl > * getCosmicTrack()
std::vector< int > * getCosmicTrackSize()
void process(DigitDataReader &r, bool fill=true)
std::vector< CosmicInfo > * getCosmicInfo()
Diagnostic class for TOF.
Definition Diagnostic.h:32
void setDigitArray(const gsl::span< const o2::tof::Digit > *a)
Definition DataReader.h:63
static constexpr Double_t BC_TIME_INPS_INV
Definition Geo.h:104
static void getPos(Int_t *det, Float_t *pos)
Definition Geo.cxx:491
static void getVolumeIndices(Int_t index, Int_t *detId)
Definition Geo.cxx:543
void init(framework::InitContext &ic)
TOFDPLClustererTask(std::shared_ptr< o2::base::GRPGeomRequest > gr, bool useMC, bool useCCDB, bool doCalib, bool isCosmic, std::string ccdb_url, bool isForCalib)
void finaliseCCDB(o2::framework::ConcreteDataMatcher matcher, void *obj)
void endOfStream(EndOfStreamContext &ec)
void run(framework::ProcessingContext &pc)
static void addInteractionBC(int bc, bool fromCollisonCotext=false)
Definition Utils.cxx:52
constexpr o2::header::DataOrigin gDataOriginTOF
Definition DataHeader.h:575
constexpr int LHCMaxBunches
Definition of a container to keep/associate and arbitrary number of labels associated to an index wit...
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
std::vector< ConfigParamSpec > Options
std::vector< T, o2::pmr::polymorphic_allocator< T > > vector
o2::framework::DataProcessorSpec getTOFClusterizerSpec(bool useMC, bool useCCDB=0, bool doCalib=0, bool isCosmic=0, std::string ccdb_url="", bool isForCalib=false)
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< Digit > digits
std::vector< int > row