Project
Loading...
Searching...
No Matches
EMCALChannelCalibrator.h
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
17
18#ifndef EMCAL_CHANNEL_CALIBRATOR_H_
19#define EMCAL_CHANNEL_CALIBRATOR_H_
20
29#include "EMCALBase/Geometry.h"
30#include "CCDB/CcdbObjectInfo.h"
31#include "EMCALCalib/CalibDB.h"
33
34#include "Framework/Logger.h"
36#include "CCDB/CcdbApi.h"
38#include <boost/histogram.hpp>
39#include <boost/histogram/ostream.hpp>
40#include <boost/format.hpp>
41
42#include <array>
43#include <boost/histogram.hpp>
44#include <fstream>
45
46namespace o2
47{
48namespace emcal
49{
52template <typename DataInput, typename DataOutput>
54{
55 using TFType = o2::calibration::TFType;
57 using Cell = o2::emcal::Cell;
59 using CcdbObjectInfoVector = std::vector<CcdbObjectInfo>;
60
61 public:
62 EMCALChannelCalibrator(int nb = 1000, float r = 0.35) : mNBins(nb), mRange(r)
63 {
64 this->setSaveDirectory(EMCALCalibParams::Instance().filePathSave);
65 };
66
67 ~EMCALChannelCalibrator() final = default;
68
70 bool hasEnoughData(const Slot& slot) const final;
72 void initOutput() final;
73 void finalizeSlot(Slot& slot) final;
74 o2::calibration::TimeSlot<DataInput>& emplaceNewSlot(bool front, TFType tstart, TFType tend) final;
75
76 bool saveLastSlotData(TFile& fl) final;
77
78 bool adoptSavedData(const o2::calibration::TimeSlotMetaData& metadata, TFile& fl) final;
79
81 void setIsTest(bool isTest) { mTest = isTest; }
82 bool isTest() const { return mTest; }
83
84 const CcdbObjectInfoVector& getInfoVector() const { return mInfoVector; }
85 const std::vector<DataOutput>& getOutputVector() const { return mCalibObjectVector; }
86
88 bool getSaveAtEOR() const { return mSaveAtEOR; }
90 void setSaveAtEOR(bool tmp) { mSaveAtEOR = tmp; }
91
93 bool getLoadAtSOR() const { return mLoadAtSOR; }
95 void setLoadAtSOR(bool tmp) { mLoadAtSOR = tmp; }
96
98 std::shared_ptr<EMCALCalibExtractor> getCalibExtractor() { return mCalibrator; } // return shared pointer!
100 void SetCalibExtractor(std::shared_ptr<EMCALCalibExtractor> extr) { mCalibrator = extr; };
101
103
106 void setFillNr(int fn) { mFillNr = fn; }
107
111
114 void setCurrTSInHours(int ts) { mStartTSCalib = ts; }
115
116 private:
117 int mNBins = 0;
118 float mRange = 0.;
119 bool mTest = false;
120 bool mSaveAtEOR = false;
121 bool mLoadAtSOR = false;
122 o2::parameters::GRPECSObject::RunType mRunType = o2::parameters::GRPECSObject::RunType::NONE;
123 int mFillNr = 0;
124 int mStartTSCalib = -1;
125 std::shared_ptr<EMCALCalibExtractor> mCalibrator;
126
127 // output
128 CcdbObjectInfoVector mInfoVector; // vector of CCDB Infos , each element is filled with the CCDB description of the accompanying TimeSlewing object
129 std::vector<DataOutput> mCalibObjectVector;
130
131 ClassDefOverride(EMCALChannelCalibrator, 1);
132};
133
134//_____________________________________________
135template <typename DataInput, typename DataOutput>
137{
138 mInfoVector.clear();
139 mCalibObjectVector.clear();
140 std::string nameFile = "tcp.root";
141 if constexpr (std::is_same<DataInput, o2::emcal::EMCALChannelData>::value) {
142 nameFile = "bcm.root";
143 }
144
145 // this->setSaveFileName(nameFile);
146 // mNEvents = 0;
147 return;
148}
149
150//_____________________________________________
151template <typename DataInput, typename DataOutput>
153{
154 // in case of the end of run, we pretend to have enough data to trigger the saving of the calib objects to load them in the next run
155 if (mSaveAtEOR) {
156 return true;
157 }
158 const DataInput* c = slot.getContainer();
159 return (mTest ? true : c->hasEnoughData());
160}
161
162//_____________________________________________
163template <typename DataInput, typename DataOutput>
165{
166
167 // Extract results for the single slot
168 DataInput* c = slot.getContainer();
169 LOG(info) << "Finalize slot " << slot.getTFStart() << " <= TF <= " << slot.getTFEnd();
170 // check if slot contains a minimum amount of data
171 if (c->getNEvents() < EMCALCalibParams::Instance().minNEventsSaveSlot) {
172 LOG(info) << "Slot only contains " << c->getNEvents() << " events. Not saving this slot. " << EMCALCalibParams::Instance().minNEventsSaveSlot << " required";
173 return;
174 }
175
176 if constexpr (std::is_same<DataInput, o2::emcal::EMCALChannelData>::value) {
177 if (c->getNEvents() < EMCALCalibParams::Instance().minNEvents_bc) {
178 LOG(info) << "saving the slot with " << c->getNEvents() << " events. " << EMCALCalibParams::Instance().minNEvents_tc << " events needed for calibration";
179 this->saveLastSlot();
180 return;
181 }
182 } else if constexpr (std::is_same<DataInput, o2::emcal::EMCALTimeCalibData>::value) {
183 if (c->getNEvents() < EMCALCalibParams::Instance().minNEvents_tc) {
184 LOG(info) << "saving the slot with " << c->getNEvents() << " events. " << EMCALCalibParams::Instance().minNEvents_tc << " events needed for calibration";
185 this->saveLastSlot();
186 return;
187 }
188 }
189
190 // get the start timestamp of the slot. Either use the manually set start ts if available, or just the start time of the slot.
191 long tsStart = slot.getStartTimeMS();
192 if (EMCALCalibParams::Instance().useStaticStartTimeSlot && slot.getStaticStartTimeMS() > 0) {
193 tsStart = slot.getStaticStartTimeMS();
194 LOG(info) << "Adjusting the start TS of the slot from " << slot.getStartTimeMS() << " to " << slot.getStaticStartTimeMS();
195 }
196
197 std::map<std::string, std::string> md;
198 if constexpr (std::is_same<DataInput, o2::emcal::EMCALChannelData>::value) {
199 LOG(debug) << "Launching the calibration.";
200 o2::emcal::BadChannelMap bcm = mCalibrator->calibrateBadChannels(c->getHisto(), c->getHistoTime());
201 LOG(debug) << "Done with the calibraiton";
202 // for the CCDB entry
204 auto flName = o2::ccdb::CcdbApi::generateFileName(clName);
205 mInfoVector.emplace_back(CalibDB::getCDBPathBadChannelMap(), clName, flName, md, tsStart, slot.getEndTimeMS() + EMCALCalibParams::Instance().endTimeMargin, true);
206 mCalibObjectVector.push_back(bcm);
207
208 if ((EMCALCalibParams::Instance().localRootFilePath).find(".root") != std::string::npos) {
209 std::ifstream ffile(EMCALCalibParams::Instance().localRootFilePath.c_str());
210
211 TFile fLocalStorage((EMCALCalibParams::Instance().localRootFilePath).c_str(), ffile.good() == true ? "update" : "recreate");
212 fLocalStorage.cd();
213
214 TH2F* histBCMap = (TH2F*)bcm.getHistogramRepresentation();
215 std::string nameBCHist = "BadChannels_" + std::to_string(tsStart);
216 histBCMap->Write(nameBCHist.c_str(), TObject::kOverwrite);
217
218 TH2F hCalibHist = o2::utils::TH2FFromBoost(c->getHisto());
219 std::string nameBCInputHist = "EnergyVsCellID_" + std::to_string(tsStart);
220 hCalibHist.Write(nameBCInputHist.c_str(), TObject::kOverwrite);
221
222 TH2F hCalibHistTime = o2::utils::TH2FFromBoost(c->getHistoTime());
223 std::string nameBCInputHistTime = "TimeVsCellID_" + std::to_string(tsStart);
224 hCalibHistTime.Write(nameBCInputHistTime.c_str(), TObject::kOverwrite);
225
226 fLocalStorage.Close();
227 }
228 } else if constexpr (std::is_same<DataInput, o2::emcal::EMCALTimeCalibData>::value) {
230
231 // for the CCDB entry
232 auto clName = o2::utils::MemFileHelper::getClassName(slot);
233 auto flName = o2::ccdb::CcdbApi::generateFileName(clName);
234
235 // prepareCCDBobjectInfo
236 mInfoVector.emplace_back(CalibDB::getCDBPathTimeCalibrationParams(), clName, flName, md, tsStart, slot.getEndTimeMS() + EMCALCalibParams::Instance().endTimeMargin, true);
237 mCalibObjectVector.push_back(tcd);
238
239 if ((EMCALCalibParams::Instance().localRootFilePath).find(".root") != std::string::npos) {
240 std::ifstream ffile(EMCALCalibParams::Instance().localRootFilePath.c_str());
241
242 TFile fLocalStorage((EMCALCalibParams::Instance().localRootFilePath).c_str(), ffile.good() == true ? "update" : "recreate");
243 fLocalStorage.cd();
244 TH1F* histTCparams = (TH1F*)tcd.getHistogramRepresentation(false); // high gain calibration
245 std::string nameTCHist = "TCParams_HG_" + std::to_string(tsStart);
246 histTCparams->Write(nameTCHist.c_str(), TObject::kOverwrite);
247
248 TH1F* histTCparams_LG = (TH1F*)tcd.getHistogramRepresentation(true); // low gain calibration
249 std::string nameTCHist_LG = "TCParams_LG_" + std::to_string(tsStart);
250 histTCparams_LG->Write(nameTCHist_LG.c_str(), TObject::kOverwrite);
251
252 TH2F hCalibHist = o2::utils::TH2FFromBoost(c->getHisto());
253 std::string nameTCInputHist = "TimeVsCellID_" + std::to_string(tsStart);
254 hCalibHist.Write(nameTCInputHist.c_str(), TObject::kOverwrite);
255 fLocalStorage.Close();
256 }
257 }
258}
259
260template <typename DataInput, typename DataOutput>
262{
264 auto& slot = front ? cont.emplace_front(tstart, tend) : cont.emplace_back(tstart, tend);
265 slot.setContainer(std::make_unique<DataInput>());
266 return slot;
267}
268
271template <typename DataInput, typename DataOutput>
273{
274 LOG(info) << "EMC calib histos are saved in " << fl.GetName();
275 // we only have 1 slot
277 auto& slot = cont.at(0);
278 DataInput* c = slot.getContainer();
279
280 // get the start timestamp of the slot. Either use the manually set start ts if available, or just the start time of the slot.
281 long tsStart = slot.getStartTimeMS();
282 if (EMCALCalibParams::Instance().useStaticStartTimeSlot && slot.getStaticStartTimeMS() > 0) {
283 tsStart = slot.getStaticStartTimeMS();
284 }
285 // timestamp in hours and seconds
286 int timeNowHour = static_cast<int>(tsStart / o2::ccdb::CcdbObjectInfo::HOUR);
287 int timeNowSec = static_cast<int>(tsStart / o2::ccdb::CcdbObjectInfo::SECOND);
288
289 // create global event properties histogram. Same for both calibration types
290 TH1I hGlobalProperties("hGlobalProperties", "hGlobalProperties", 4, -0.5, 3.5);
291 hGlobalProperties.GetXaxis()->SetBinLabel(1, "Fill nr.");
292 hGlobalProperties.GetXaxis()->SetBinLabel(2, "run type");
293 hGlobalProperties.GetXaxis()->SetBinLabel(3, "ts in hours");
294 hGlobalProperties.GetXaxis()->SetBinLabel(4, "ts in seconds");
295 hGlobalProperties.SetBinContent(1, mFillNr);
296 hGlobalProperties.SetBinContent(2, mRunType);
297 hGlobalProperties.SetBinContent(3, timeNowHour);
298 hGlobalProperties.SetBinContent(4, timeNowSec);
299
300 if constexpr (std::is_same<DataInput, o2::emcal::EMCALChannelData>::value) {
301 auto hist = c->getHisto();
302 auto histTime = c->getHistoTime();
303
304 TH2F hEnergy = o2::utils::TH2FFromBoost(hist);
305 TH2F hTime = o2::utils::TH2FFromBoost(histTime, "histTime");
306 TH1D hNEvents("hNEvents", "hNEvents", 1, 0, 1);
307 hNEvents.SetBinContent(1, c->getNEvents());
308
309 fl.cd();
310 hEnergy.Write("EnergyVsCellID");
311 hTime.Write("TimeVsCellID");
312 hNEvents.Write("NEvents");
313 hGlobalProperties.Write("GlobalProperties");
314
315 } else if constexpr (std::is_same<DataInput, o2::emcal::EMCALTimeCalibData>::value) {
316 auto histTime = c->getHisto();
317 TH2F hTime = o2::utils::TH2FFromBoost(histTime);
318 TH1D hNEvents("hNEvents", "hNEvents", 1, 0, 1);
319 hNEvents.SetBinContent(1, c->getNEvents());
320
321 fl.cd();
322 hTime.Write("TimeVsCellID");
323 hNEvents.Write("NEvents");
324 hGlobalProperties.Write("GlobalProperties");
325 }
326
327 return true;
328}
329
333template <typename DataInput, typename DataOutput>
335{
336 LOG(info) << "Loading data from previous run";
337
338 if (!this->getSavedSlotAllowed() || !this->getLoadAtSOR())
339 return true;
340
342
343 if (cont.size() == 0) {
344 LOG(warning) << "cont.size() is 0, calibration objects from previous run cannot be loaded...";
345 return true;
346 }
347 auto& slot = cont.at(0);
348 DataInput* c = slot.getContainer();
349
350 // check run type and fill
351 TH1I* hGlobalProperties = (TH1I*)fl.Get("GlobalProperties");
352 if (!hGlobalProperties) {
353 LOG(error) << "GlobalProperties histogram not found. Will not load previous calibration histograms";
354 } else {
355 int fillNr = hGlobalProperties->GetBinContent(1);
356 int runType = hGlobalProperties->GetBinContent(2);
357 int tsOld = hGlobalProperties->GetBinContent(3);
358 int tsOldSec = (hGlobalProperties->GetNbinsX() > 3) ? hGlobalProperties->GetBinContent(4) : 0; // Protection as 4th bin was only added later
359 int tsDiff = (mStartTSCalib > 0 ? mStartTSCalib : static_cast<int>(o2::ccdb::getCurrentTimestamp() / o2::ccdb::CcdbObjectInfo::HOUR)) - tsOld; // get current timestamp if mStartTSCalib is not set
360 LOG(debug) << "tsOld " << tsOld << " tsNow " << (mStartTSCalib > 0 ? mStartTSCalib : static_cast<int>(o2::ccdb::getCurrentTimestamp() / o2::ccdb::CcdbObjectInfo::HOUR)) << " tsDiff " << tsDiff;
361
362 if (EMCALCalibParams::Instance().requireSameRunType && runType != static_cast<int>(mRunType)) {
363 LOG(info) << "adoptSavedData: Same run type required but run types differ: " << runType << " != " << static_cast<int>(mRunType);
364 return false;
365 }
366 if (EMCALCalibParams::Instance().requireSameFill && fillNr != mFillNr) {
367 LOG(info) << "adoptSavedData: Same fill nr. required but fills differ: " << fillNr << " != " << mFillNr;
368 return false;
369 }
370 if (EMCALCalibParams::Instance().tsDiffMax > 0 && (EMCALCalibParams::Instance().tsDiffMax < tsDiff || tsDiff < 0)) {
371 LOG(info) << "adoptSavedData: Maximum difference in ts is: " << EMCALCalibParams::Instance().tsDiffMax << " but " << tsDiff << " is given";
372 return false;
373 }
374 if (EMCALCalibParams::Instance().useStaticStartTimeSlot && tsOldSec > 0) {
375 slot.setStaticStartTimeMS(static_cast<long>(tsOldSec * o2::ccdb::CcdbObjectInfo::SECOND));
376 LOG(info) << "adoptSavedData: Setting the start timestamp to " << static_cast<long>(tsOldSec * o2::ccdb::CcdbObjectInfo::SECOND);
377 }
378 }
379
380 if constexpr (std::is_same<DataInput, o2::emcal::EMCALChannelData>::value) {
381 TH2D* hEnergy = (TH2D*)fl.Get("EnergyVsCellID");
382 TH2D* hTime = (TH2D*)fl.Get("TimeVsCellID");
383 if (!hEnergy || !hTime) {
384 return false;
385 }
386 auto hEnergyBoost = o2::utils::boostHistoFromRoot_2D<boostHisto2d>(hEnergy);
387 auto hTimeBoost = o2::utils::boostHistoFromRoot_2D<boostHisto2d>(hTime);
388
389 c->setHisto(hEnergyBoost);
390 c->setHistoTime(hTimeBoost);
391
392 } else if constexpr (std::is_same<DataInput, o2::emcal::EMCALTimeCalibData>::value) {
393 TH2D* hTime = (TH2D*)fl.Get("TimeVsCellID");
394 if (!hTime) {
395 return false;
396 }
397 auto hTimeBoost = o2::utils::boostHistoFromRoot_2D<boostHisto2d>(hTime);
398
399 c->setHisto(hTimeBoost);
400 }
401 TH1D* hEvents = (TH1D*)fl.Get("NEvents");
402 if (!hEvents) {
403 return false;
404 }
405 c->setNEvents(hEvents->GetBinContent(1));
406 LOG(info) << "successfully loaded histograms with " << hEvents->GetBinContent(1) << " events";
407
408 return true;
409}
410
411template <typename DataInput, typename DataOutput>
413{
414
416 if (cont.size() == 0) {
417 return false; // time slot object not yet there
418 }
419
420 auto& slot = cont.at(0);
421 DataInput* c = slot.getContainer();
422 c->setGainCalibFactors(gainCalibFactors);
423
424 return true;
425}
426
427} // end namespace emcal
428} // end namespace o2
429
430#endif /*EMCAL_CHANNEL_CALIBRATOR_H_ */
Utils and constants for calibration and related workflows.
Header of the AggregatedRunInfo struct.
uint32_t c
Definition RawData.h:2
std::ostringstream debug
long getStaticStartTimeMS() const
Definition TimeSlot.h:49
TFType getTFEnd() const
Definition TimeSlot.h:47
long getStartTimeMS() const
Definition TimeSlot.h:50
long getEndTimeMS() const
Definition TimeSlot.h:51
const Container * getContainer() const
Definition TimeSlot.h:53
TFType getTFStart() const
Definition TimeSlot.h:46
static std::string generateFileName(const std::string &inp)
Definition CcdbApi.cxx:798
static constexpr long HOUR
static constexpr long SECOND
CCDB container for masked cells in EMCAL.
TH2 * getHistogramRepresentation() const
Convert map into 2D histogram representation.
static const char * getCDBPathTimeCalibrationParams()
Get CDB path for the time calibration.
Definition CalibDB.h:338
static const char * getCDBPathBadChannelMap()
Get CDB path for the bad channel map.
Definition CalibDB.h:334
EMCAL compressed cell information.
Definition Cell.h:59
class used for managment of bad channel and time calibration template DataInput can be ChannelData or...
const std::vector< DataOutput > & getOutputVector() const
void initOutput() final
Initialize the vector of our output objects.
void setIsTest(bool isTest)
Set the testing status.
bool getSaveAtEOR() const
get if has enough data should be circumvented at EOR
bool adoptSavedData(const o2::calibration::TimeSlotMetaData &metadata, TFile &fl) final
Read histograms for energy and time vs cell ID to file.
bool getLoadAtSOR() const
get if has enough data should be circumvented at EOR
void setRunType(o2::parameters::GRPECSObject::RunType rt)
Set current run type.
o2::calibration::TimeSlot< DataInput > & emplaceNewSlot(bool front, TFType tstart, TFType tend) final
void setCurrTSInHours(int ts)
Set current timestamp obtained from data.
void SetCalibExtractor(std::shared_ptr< EMCALCalibExtractor > extr)
setter for mCalibrator
std::shared_ptr< EMCALCalibExtractor > getCalibExtractor()
Configure the calibrator.
const CcdbObjectInfoVector & getInfoVector() const
~EMCALChannelCalibrator() final=default
void setSaveAtEOR(bool tmp)
set if has enough data should be circumvented at EOR
bool hasEnoughData(const Slot &slot) const final
Checking if all channels have enough data to do calibration.
EMCALChannelCalibrator(int nb=1000, float r=0.35)
void setFillNr(int fn)
Set current fill number.
void setLoadAtSOR(bool tmp)
set if has enough data should be circumvented at EOR
bool saveLastSlotData(TFile &fl) final
Write histograms for energy and time vs cell ID to file.
bool setGainCalibrationFactors(o2::emcal::GainCalibrationFactors *gainCalibFactors)
CCDB container for the gain calibration factors.
TH1 * getHistogramRepresentation(bool isLowGain) const
Convert the time calibration coefficient array to a histogram.
GLboolean r
Definition glcorearb.h:1233
uint32_t TFType
Definition TimeSlot.h:29
long getCurrentTimestamp()
returns the timestamp in long corresponding to "now"
TH2F TH2FFromBoost(BoostHist hist, const char *name="hist")
Convert a 2D boost histogram to a root histogram.
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
unsigned int minNEventsSaveSlot
minimum amount a slot has to have in order to be taken into accoutn in finalize slot....
int tsDiffMax
if loading calib objects from previous run, limit time between the object being stored and loaded aga...
int minTimeForFit_tc
minimum cell time considered for the time calibration in ns
int restrictFitRangeToMax_tc
window around the largest entry within the minTimeForFit in which the fit is performed in ns
unsigned int minNEvents_tc
minimum number of events to trigger the calibration
long endTimeMargin
set end TS to 30 days after slot ends (1000 * 60 * 60 * 24 * 30)
unsigned int minNEvents_bc
minimum number of events to trigger the calibration
bool requireSameFill
if loading calib objects from previous run, require it to be in the same fill as the current one
bool requireSameRunType
if loading calib objects from previous run, require it to be the same run type
int maxTimeForFit_tc
maximum cell time considered for the time calibration in ns
static std::string getClassName(const T &obj)
get the class name of the object
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"