|
15 | 15 | /// @brief Processor for the multiple time slots calibration |
16 | 16 |
|
17 | 17 | #include "DetectorsCalibration/TimeSlot.h" |
| 18 | +#include "DetectorsCalibration/TimeSlotMetaData.h" |
18 | 19 | #include "DetectorsBase/TFIDInfoHelper.h" |
19 | 20 | #include "DetectorsBase/GRPGeomHelper.h" |
20 | 21 | #include "CommonDataFormat/TFIDInfo.h" |
| 22 | +#include <TFile.h> |
| 23 | +#include <filesystem> |
21 | 24 | #include <deque> |
22 | 25 | #include <gsl/gsl> |
23 | 26 | #include <limits> |
24 | 27 | #include <type_traits> |
| 28 | +#include <unistd.h> |
25 | 29 |
|
26 | 30 | namespace o2 |
27 | 31 | { |
@@ -149,6 +153,32 @@ class TimeSlotCalibration |
149 | 153 | static constexpr bool value = type::value; |
150 | 154 | }; |
151 | 155 |
|
| 156 | + // methods for saving/reading data in the of the run in case of insufficient statistics |
| 157 | + bool getSavedSlotAllowed() const { return mSavedSlotAllowed; } |
| 158 | + void setSavedSlotAllowed(bool v) { mSavedSlotAllowed = v; } |
| 159 | + std::string getSaveFilePath() const; |
| 160 | + const std::string& getSaveFileName() const { return mSaveFileName; } |
| 161 | + void setSaveFileName(const std::string& n) { mSaveFileName = n; } |
| 162 | + void setSaveDirectory(const std::string& n) { mSaveDirectory = n; } |
| 163 | + virtual bool updateSaveMetaData(); |
| 164 | + |
| 165 | + // derived class using slot saving functionality must implement this method to write the |
| 166 | + // content of the slot, returning true on success |
| 167 | + virtual bool saveLastSlotData(TFile& fl) |
| 168 | + { |
| 169 | + LOG(fatal) << "This method must be implemented by derived class to write content of the slot to save"; |
| 170 | + return false; |
| 171 | + } |
| 172 | + // derived class using slot saving functionality must implement this method to adopt the content of the |
| 173 | + // saved slot, returning true on success. Provided metadata should be used to judge if the saved data is useful. |
| 174 | + virtual bool adoptSavedData(const TimeSlotMetaData& metadata, TFile& fl) |
| 175 | + { |
| 176 | + LOG(fatal) << "This method must be implemented by derived class to adopt content of the saved slot"; |
| 177 | + return false; |
| 178 | + } |
| 179 | + virtual bool loadSavedSlot(); |
| 180 | + virtual bool saveLastSlot(); |
| 181 | + |
152 | 182 | protected: |
153 | 183 | auto& getSlots() { return mSlots; } |
154 | 184 | uint32_t getRunStartOrbit() const |
@@ -186,6 +216,12 @@ class TimeSlotCalibration |
186 | 216 | bool mWasCheckedInfiniteSlot = false; // flag to know whether the statistics of the infinite slot was already checked |
187 | 217 | bool mUpdateAtTheEndOfRunOnly = false; |
188 | 218 | bool mFinalizeWhenReady = false; // if true: single bin is filled until ready, then closed and new one is added |
| 219 | + |
| 220 | + std::string mSaveDirectory = ""; // directory where the file is saved |
| 221 | + std::string mSaveFileName = ""; // filename for data saves in the end of the run |
| 222 | + TimeSlotMetaData mSaveMetaData{}; |
| 223 | + bool mSavedSlotAllowed = false; |
| 224 | + |
189 | 225 | ClassDef(TimeSlotCalibration, 1); |
190 | 226 | }; |
191 | 227 |
|
@@ -396,6 +432,100 @@ void TimeSlotCalibration<Input, Container>::print() const |
396 | 432 | } |
397 | 433 | } |
398 | 434 |
|
| 435 | +//_________________________________________________ |
| 436 | +template <typename Input, typename Container> |
| 437 | +bool TimeSlotCalibration<Input, Container>::updateSaveMetaData() |
| 438 | +{ |
| 439 | + if (mSlots.empty()) { |
| 440 | + LOG(warn) << "Nothing to save, no TimeSlots defined"; |
| 441 | + return false; |
| 442 | + } |
| 443 | + if (mSaveMetaData.startRun < 0) { |
| 444 | + mSaveMetaData.startRun = mCurrentTFInfo.runNumber; |
| 445 | + } |
| 446 | + mSaveMetaData.endRun = mCurrentTFInfo.runNumber; |
| 447 | + if (mSaveMetaData.startTime < 0) { |
| 448 | + mSaveMetaData.startTime = mSlots.back().getStartTimeMS(); |
| 449 | + } |
| 450 | + mSaveMetaData.endTime = mSlots.back().getEndTimeMS(); |
| 451 | + return true; |
| 452 | +} |
| 453 | + |
| 454 | +//_________________________________________________ |
| 455 | +template <typename Input, typename Container> |
| 456 | +bool TimeSlotCalibration<Input, Container>::saveLastSlot() |
| 457 | +{ |
| 458 | + if (!getSavedSlotAllowed()) { |
| 459 | + LOG(info) << "Slot saving is disabled"; |
| 460 | + return false; |
| 461 | + } |
| 462 | + if (!updateSaveMetaData()) { |
| 463 | + return false; |
| 464 | + } |
| 465 | + auto pth = getSaveFilePath(); |
| 466 | + auto pthTmp = pth + ".part"; |
| 467 | + TFile flout(pthTmp.c_str(), "recreate"); |
| 468 | + if (flout.IsZombie()) { |
| 469 | + LOGP(error, "failed to open save file {}", pth); |
| 470 | + unlink(pthTmp.c_str()); |
| 471 | + return false; |
| 472 | + } |
| 473 | + if (!saveLastSlotData(flout)) { // call used method to store data |
| 474 | + flout.Close(); |
| 475 | + unlink(pthTmp.c_str()); |
| 476 | + return false; |
| 477 | + } |
| 478 | + flout.WriteObjectAny(&mSaveMetaData, "o2::calibration::TimeSlotMetaData", "metadata"); |
| 479 | + flout.Close(); |
| 480 | + std::filesystem::rename(pthTmp, pth); |
| 481 | + LOGP(info, "Saved data of the last slot to {}", pth); |
| 482 | + return true; |
| 483 | +} |
| 484 | + |
| 485 | +//_________________________________________________ |
| 486 | +template <typename Input, typename Container> |
| 487 | +bool TimeSlotCalibration<Input, Container>::loadSavedSlot() |
| 488 | +{ |
| 489 | + if (!getSavedSlotAllowed()) { |
| 490 | + LOG(info) << "Saved slot usage is disabled"; |
| 491 | + return false; |
| 492 | + } |
| 493 | + auto pth = getSaveFilePath(); |
| 494 | + if (!std::filesystem::exists(pth)) { |
| 495 | + LOGP(info, "No save file {} is found", pth); |
| 496 | + return false; |
| 497 | + } |
| 498 | + TFile flin(pth.c_str()); |
| 499 | + if (flin.IsZombie()) { |
| 500 | + LOGP(error, "failed to open save file {}", pth); |
| 501 | + return false; |
| 502 | + } |
| 503 | + auto meta = (o2::calibration::TimeSlotMetaData*)flin.GetObjectChecked("metadata", "o2::calibration::TimeSlotMetaData"); |
| 504 | + if (!meta) { |
| 505 | + LOGP(error, "Failed to read metadata from {}", pth); |
| 506 | + return false; |
| 507 | + } |
| 508 | + auto res = adoptSavedData(*meta, flin); // up to the detector to decide if data should be accepted |
| 509 | + if (res) { |
| 510 | + mSaveMetaData.startRun = meta->startRun; |
| 511 | + mSaveMetaData.startTime = meta->startTime; |
| 512 | + updateSaveMetaData(); |
| 513 | + } |
| 514 | + flin.Close(); |
| 515 | + unlink(pth.c_str()); // cleanup used file |
| 516 | + return true; |
| 517 | +} |
| 518 | + |
| 519 | +//_________________________________________________ |
| 520 | +template <typename Input, typename Container> |
| 521 | +std::string TimeSlotCalibration<Input, Container>::getSaveFilePath() const |
| 522 | +{ |
| 523 | + if (mSaveFileName.empty()) { |
| 524 | + LOGP(fatal, "Save file name was not set"); |
| 525 | + } |
| 526 | + return fmt::format("{}{}{}", mSaveDirectory, ((!mSaveDirectory.empty() && mSaveDirectory.back() != '/') ? "/" : ""), mSaveFileName); |
| 527 | +} |
| 528 | + |
399 | 529 | } // namespace calibration |
400 | 530 | } // namespace o2 |
401 | 531 |
|
|
0 commit comments