Project
Loading...
Searching...
No Matches
TimeSlotCalibration.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
12#ifndef DETECTOR_CALIB_TIMESLOTCALIB_H_
13#define DETECTOR_CALIB_TIMESLOTCALIB_H_
14
16
22#include <TFile.h>
23#include <filesystem>
24#include <deque>
25#include <gsl/gsl>
26#include <limits>
27#include <type_traits>
28#include <unistd.h>
29
30namespace o2
31{
32namespace framework
33{
34class ProcessingContext;
35}
36namespace calibration
37{
38
39template <typename Container>
41{
42 public:
45
47
49 virtual ~TimeSlotCalibration() = default;
50 float getMaxSlotsDelay() const { return mMaxSlotsDelay; }
51 void setMaxSlotsDelay(float v) { mMaxSlotsDelay = v > 0. ? v : 0.; }
52
53 TFType getSlotLength() const { return mSlotLength; }
55 {
56 if (v == 0) {
58 } else {
59 mSlotLength = v;
60 }
61 }
62
65
68
69 TFType getFirstTF() const { return mFirstTF; }
71
72 void setSlotLengthInSeconds(int s) { mSlotLengthInSeconds = s > 0 ? s : 1; }
73 void setSlotLengthInOrbits(int n) { mSlotLengthInOrbits = n > 0 ? n : 1; }
75 {
76 if (mSlotLengthInSeconds > 0) {
78 LOGP(info, "Redefining slot duration from {} s. to {} TFs", mSlotLengthInSeconds, ntf);
79 setSlotLength(ntf);
81 } else if (mSlotLengthInOrbits > 0) {
83 if (ntf < 1) {
84 ntf = 1;
85 }
86 LOGP(info, "Redefining slot duration from {} orbits to {} TFs", mSlotLengthInOrbits, ntf);
87 setSlotLength(ntf);
89 }
90 setStartOffsetFrac(mStartOffsetFrac); // set once more to account for eventual dependencies
92 }
93
95 {
96 if (mUpdateAtTheEndOfRunOnly || mFinalizeWhenReady || mSlotLength == INFINITE_TF) { // offset makes no sense for run-wide objects
97 if (f) {
98 LOGP(info, "Start offset is not supported in the INFINITE_TF slot length or UpdateAtTheEndOfRunOnly or FinalizeWhenReady modes");
99 }
100 return;
101 }
102 if (f < 0.) {
103 mStartOffsetFrac = 0.;
104 } else if (f > 0.95) {
105 mStartOffsetFrac = 0.95;
106 } else {
108 }
110 LOGP(info, "Imposing offset of {:4.2} x nominal slot length", mStartOffsetFrac);
111 }
112 }
113
120
122
123 int getNSlots() const { return mSlots.size(); }
125 Slot& getSlot(int i) { return (Slot&)mSlots.at(i); }
126 const Slot& getSlot(int i) const { return (Slot&)mSlots.at(i); }
127 const Slot& getLastSlot() const { return (Slot&)mSlots.back(); }
128 const Slot& getFirstSlot() const { return (Slot&)mSlots.front(); }
129
130 template <typename... DATA>
131 bool process(const DATA&... data);
132 virtual void checkSlotsToFinalize(TFType tf = INFINITE_TF, int maxDelay = 0);
133 virtual void finalizeOldestSlot();
134
135 virtual void reset()
136 { // reset to virgin state (need for start - stop - start)
137 mSlots.clear();
138 mLastClosedTF = 0;
139 mFirstTF = 0;
140 mMaxSeenTF = 0;
143 initOutput();
144 }
145
146 // Methods to be implemented by the derived user class
147
148 // implement and call this method te reset the output slots once they are not needed
149 virtual void initOutput() = 0;
150 // process the time slot container and add results to the output
151 virtual void finalizeSlot(Slot& slot) = 0;
152 // create new time slot in the beginning or the end of the slots pool
153 virtual Slot& emplaceNewSlot(bool front, TFType tstart, TFType tend) = 0;
154 // check if the slot has enough data to be finalized
155 virtual bool hasEnoughData(const Slot& slot) const = 0;
156
157 virtual void print() const;
158
161
162 // from https://stackoverflow.com/questions/87372/check-if-a-class-has-a-member-function-of-a-given-signature
163 // Primary template with a static assertion
164 // for a meaningful error message
165 // if it ever gets instantiated.
166 // We could leave it undefined if we didn't care.
167 template <typename, typename T>
169 static_assert(
170 std::integral_constant<T, false>::value,
171 "Second template parameter needs to be of function type.");
172 };
173
174 // specialization that does the checking
175
176 template <typename C, typename Ret, typename... Args>
177 struct has_fill_method<C, Ret(Args...)> {
178 private:
179 template <typename T>
180 static constexpr auto check(T*)
181 -> typename std::is_same<decltype(std::declval<T>().fill(std::declval<Args>()...)), Ret>::type; // attempt to call it and see if the return type is correct
182 template <typename>
183 static constexpr std::false_type check(...);
184 typedef decltype(check<C>(nullptr)) type;
185
186 public:
187 static constexpr bool value = type::value;
188 };
189
190 // methods for saving/reading data in the of the run in case of insufficient statistics
191 bool getSavedSlotAllowed() const { return mSavedSlotAllowed; }
193 std::string getSaveFilePath() const;
194 const std::string& getSaveFileName() const { return mSaveFileName; }
195 void setSaveFileName(const std::string& n) { mSaveFileName = n; }
196 void setSaveDirectory(const std::string& n) { mSaveDirectory = n; }
197 virtual bool updateSaveMetaData();
198
199 // derived class using slot saving functionality must implement this method to write the
200 // content of the slot, returning true on success
201 virtual bool saveLastSlotData(TFile& fl)
202 {
203 LOG(fatal) << "This method must be implemented by derived class to write content of the slot to save";
204 return false;
205 }
206 // derived class using slot saving functionality must implement this method to adopt the content of the
207 // saved slot, returning true on success. Provided metadata should be used to judge if the saved data is useful.
208 virtual bool adoptSavedData(const TimeSlotMetaData& metadata, TFile& fl)
209 {
210 LOG(fatal) << "This method must be implemented by derived class to adopt content of the saved slot";
211 return false;
212 }
213 virtual bool loadSavedSlot();
214 virtual bool saveLastSlot();
215
216 protected:
217 auto& getSlots() { return mSlots; }
218 uint32_t getRunStartOrbit() const
219 {
221 static unsigned int threshold = 512 * o2::base::GRPGeomHelper::getNHBFPerTF();
222 if (orb < 0) {
223 // If we have a firstTForbit between 1 and 512 * tf len, we disable the warning for negative runStartOrbit permanently, since this is a SYNTHETIC run.
224 static bool suppressRunStartWarning = false;
225 if (!suppressRunStartWarning) {
226 const auto* grpecs = o2::base::GRPGeomHelper::instance().getGRPECS();
227 if (grpecs) {
228 if (grpecs->getRunType() == o2::parameters::GRPECS::SYNTHETIC) {
229 suppressRunStartWarning = true;
230 }
231 } else if (mCurrentTFInfo.firstTForbit < threshold && mCurrentTFInfo.firstTForbit > 0) {
232 suppressRunStartWarning = true;
233 }
234 }
235
236 if (!suppressRunStartWarning && mCurrentTFInfo.firstTForbit >= threshold) {
237 LOGP(alarm, "Negative runStartOrbit = {} deduced from tfCounter={} and firstTForbit={}, enforcing runStartOrbit to 0", orb, mCurrentTFInfo.tfCounter, mCurrentTFInfo.firstTForbit);
238 }
239 orb = 0;
240 }
241 return uint32_t(orb);
242 }
243
245 std::deque<Slot> mSlots;
246
248 int mSlotLengthInSeconds = -1; // optionally provided slot length in seconds
249 int mSlotLengthInOrbits = -1; // optionally provided slot length in orbits
252 TFType mMaxSeenTF = 0; // largest TF processed
253 TFType mSlotLength = 1; // slot length in TFs
254 TFType mStartOffsetTFs = 0; // shift start of all TFs backwards by this amount (to make 1st slot effectively shorter: run_1st_tf to run_1st_tf - offset + mSlotLength), derived from mStartOffsetFrac
255 float mStartOffsetFrac = 0.; // shift start of all TFs backwards mSlotLength*mStartOffsetFrac TFs.
256 TFType mCheckIntervalInfiniteSlot = 1; // will be used if the TF length is INFINITE_TF_int64 to decide
257 // when to check if to call the finalize; otherwise it is called
258 // at every new TF; note that this is an approximation,
259 // since TFs come in async order
260 TFType mLastCheckedTFInfiniteSlot = 0; // will be used if the TF length is INFINITE_TF_int64 to book-keep
261 // the last TF at which we tried to calibrate
262 TFType mCheckDeltaIntervalInfiniteSlot = 1; // will be used if the TF length is INFINITE_TF_int64 when
263 // the check on the statistics returned false, to determine
264 // after how many TF to check again.
265 float mMaxSlotsDelay = 3.0; // difference in slot units between the current TF and oldest slot (end TF) to account for the TF
266
267 bool mWasCheckedInfiniteSlot = false; // flag to know whether the statistics of the infinite slot was already checked
269 bool mFinalizeWhenReady = false; // if true: single bin is filled until ready, then closed and new one is added
270
271 std::string mSaveDirectory = ""; // directory where the file is saved
272 std::string mSaveFileName = ""; // filename for data saves in the end of the run
274 bool mSavedSlotAllowed = false;
275
277};
278
279//_________________________________________________
280template <typename Container>
281template <typename... DATA>
283{
284 if (mCurrentTFInfo.discard) {
285 LOGP(warn, "Ignoring TF with discard flag on: Orbit {}, TFcounter {}, Run:{}, StartTime:{} CreationTime {}, ",
286 mCurrentTFInfo.firstTForbit,
287 mCurrentTFInfo.tfCounter,
288 mCurrentTFInfo.runNumber,
289 mCurrentTFInfo.startTime,
290 mCurrentTFInfo.creation);
291 return false; // ignore bad TF
292 }
293 static bool firstCall = true;
294 if (firstCall) {
295 firstCall = false;
296 checkSlotLength();
297 }
298
299 // process current TF
300 TFType tf = mCurrentTFInfo.tfCounter;
301 uint64_t maxDelay64 = uint64_t(mSlotLength * mMaxSlotsDelay);
302 TFType maxDelay = maxDelay64 > o2::calibration::INFINITE_TF ? o2::calibration::INFINITE_TF : TFType(maxDelay64);
303 if (!mUpdateAtTheEndOfRunOnly) { // if you update at the end of run only, then you accept everything
304 if (tf < mLastClosedTF || (!mSlots.empty() && getLastSlot().getTFStart() > tf + maxDelay64)) { // ignore TF; note that if you have only 1 timeslot
305 // which is INFINITE_TF wide, then maxDelay
306 // does not matter: you won't accept TFs from the past,
307 // so the first condition will be used
308 LOG(info) << "Ignoring TF " << tf << ", mLastClosedTF = " << mLastClosedTF;
309 return false;
310 }
311 }
312 auto& slotTF = getSlotForTF(tf);
313 using Cont_t = typename std::remove_pointer<decltype(slotTF.getContainer())>::type;
314 if constexpr (has_fill_method<Cont_t, void(const o2::dataformats::TFIDInfo&, const DATA&...)>::value) {
315 slotTF.getContainer()->fill(mCurrentTFInfo, data...);
316 } else {
317 slotTF.getContainer()->fill(data...);
318 }
319 if (tf > mMaxSeenTF) {
320 mMaxSeenTF = tf; // keep track of the most recent TF processed
321 }
322 if (!mUpdateAtTheEndOfRunOnly) { // if you update at the end of run only, you don't check at every TF which slots can be closed
323 // check if some slots are done
324 checkSlotsToFinalize(tf, maxDelay);
325 }
326
327 return true;
328}
329
330//_________________________________________________
331template <typename Container>
333{
334 // Check which slots can be finalized, provided the newly arrived TF is tf
335
336 // if slot finalization is asked as soon as the slot is ready, we need to check if we got enough statistics, and if so, redefine the slot
337 if (mSlots.size() == 1 && mFinalizeWhenReady) {
338 TFType checkInterval = mCheckIntervalInfiniteSlot + mLastCheckedTFInfiniteSlot;
339 if (mWasCheckedInfiniteSlot) {
340 checkInterval = mCheckDeltaIntervalInfiniteSlot + mLastCheckedTFInfiniteSlot;
341 }
342 if (tf >= checkInterval || tf == INFINITE_TF) {
343 LOG(debug) << "mMaxSeenTF = " << mMaxSeenTF << ", mLastCheckedTFInfiniteSlot = " << mLastCheckedTFInfiniteSlot << ", checkInterval = " << checkInterval << ", mSlots[0].getTFStart() = " << mSlots[0].getTFStart();
344 if (tf == INFINITE_TF) {
345 LOG(info) << "End of run reached, trying to calibrate what we have, if we have enough statistics";
346 } else {
347 LOG(info) << "Calibrating as soon as we have enough statistics:";
348 LOG(info) << "Update interval passed (" << checkInterval << "), checking slot for " << mSlots[0].getTFStart() << " <= TF <= " << INFINITE_TF;
349 }
350 mLastCheckedTFInfiniteSlot = tf;
351 if (hasEnoughData(mSlots[0])) {
352 mWasCheckedInfiniteSlot = false;
353 mSlots[0].setTFStart(mLastClosedTF);
354 mSlots[0].setTFEnd(mMaxSeenTF);
355 LOG(info) << "Finalizing slot for " << mSlots[0].getTFStart() << " <= TF <= " << mSlots[0].getTFEnd();
356 finalizeSlot(mSlots[0]); // will be removed after finalization
357 mLastClosedTF = mSlots[0].getTFEnd() < INFINITE_TF ? (mSlots[0].getTFEnd() + 1) : mSlots[0].getTFEnd() < INFINITE_TF; // will not accept any TF below this
358 mSlots.erase(mSlots.begin());
359 // creating a new slot if we are not at the end of run
360 if (tf != INFINITE_TF) {
361 LOG(info) << "Creating new slot for " << mLastClosedTF << " <= TF <= " << INFINITE_TF;
362 auto& sl = emplaceNewSlot(true, mLastClosedTF, INFINITE_TF);
363 sl.setRunStartOrbit(getRunStartOrbit());
364 }
365 } else {
366 LOG(info) << "Not enough data to calibrate";
367 mWasCheckedInfiniteSlot = true;
368 }
369 } else {
370 LOG(debug) << "Not trying to calibrate: either not at EoS, or update interval not passed";
371 }
372 } else {
373 // check if some slots are done
374 for (auto slot = mSlots.begin(); slot != mSlots.end();) {
375 uint64_t lim64 = uint64_t(maxDelay) + slot->getTFEnd();
376 TFType tfLim = lim64 < INFINITE_TF ? TFType(lim64) : INFINITE_TF;
377 if (tfLim < tf) {
378 if (hasEnoughData(*slot)) {
379 LOG(debug) << "Finalizing slot for " << slot->getTFStart() << " <= TF <= " << slot->getTFEnd();
380 finalizeSlot(*slot); // will be removed after finalization
381 } else if ((slot + 1) != mSlots.end()) {
382 LOG(info) << "Merging underpopulated slot " << slot->getTFStart() << " <= TF <= " << slot->getTFEnd()
383 << " to slot " << (slot + 1)->getTFStart() << " <= TF <= " << (slot + 1)->getTFEnd();
384 (slot + 1)->mergeToPrevious(*slot);
385 } else {
386 LOG(info) << "Discard underpopulated slot " << slot->getTFStart() << " <= TF <= " << slot->getTFEnd();
387 break; // slot has no enough stat. and there is no other slot to merge it to
388 }
389 mLastClosedTF = slot->getTFEnd() + 1; // will not accept any TF below this
390 LOG(info) << "closing slot " << slot->getTFStart() << " <= TF <= " << slot->getTFEnd();
391 slot = mSlots.erase(slot);
392 } else {
393 break; // all following slots will be even closer to the new TF
394 }
395 }
396 }
397}
398
399//_________________________________________________
400template <typename Container>
402{
403 // Enforce finalization and removal of the oldest slot
404 if (mSlots.empty()) {
405 LOG(warning) << "There are no slots defined";
406 return;
407 }
408 finalizeSlot(mSlots.front());
409 mLastClosedTF = mSlots.front().getTFEnd() + 1; // do not accept any TF below this
410 mSlots.erase(mSlots.begin());
411}
412
413//________________________________________
414template <typename Container>
416{
417 // returns the min TF of the slot to which "tf" belongs
418 if (tf < mFirstTF) {
419 throw std::runtime_error("invalid TF");
420 }
421 if (mUpdateAtTheEndOfRunOnly) {
422 return mFirstTF;
423 }
424 int64_t tft = 0;
425 tft = int64_t(((tf - mFirstTF + mStartOffsetTFs) / mSlotLength) * mSlotLength) + mFirstTF;
426 if (tft > mStartOffsetTFs) {
427 tft -= mStartOffsetTFs;
428 } else {
429 tft = 0;
430 }
431 return tft < o2::calibration::INFINITE_TF ? TFType(tft) : INFINITE_TF;
432}
433
434//_________________________________________________
435template <typename Container>
437{
438
439 LOG(debug) << "Getting slot for TF " << tf;
440 if (mUpdateAtTheEndOfRunOnly) {
441 if (!mSlots.empty() && mSlots.back().getTFEnd() < tf) {
442 mSlots.back().setTFEnd(tf);
443 } else if (mSlots.empty()) {
444 auto& sl = emplaceNewSlot(true, mFirstTF, tf);
445 sl.setRunStartOrbit(getRunStartOrbit());
446 sl.setStaticStartTimeMS(sl.getStartTimeMS());
447 }
448 return mSlots.back();
449 }
450
451 if (!mSlots.empty() && mSlots.front().getTFStart() > tf) { // we need to add a slot to the beginning
452 auto tfmn = tf2SlotMin(mSlots.front().getTFStart() - 1); // min TF of the slot corresponding to a TF smaller than the first seen
453 auto tftgt = tf2SlotMin(tf); // min TF of the slot to which the TF "tf" would belong
454 while (tfmn >= tftgt) {
455 uint64_t tft = mSlots.front().getTFStart() - 1;
457 LOG(info) << "Adding new slot for " << tfmn << " <= TF <= " << tfmx;
458 auto& sl = emplaceNewSlot(true, tfmn, tfmx);
459 sl.setRunStartOrbit(getRunStartOrbit());
460 sl.setStaticStartTimeMS(sl.getStartTimeMS());
461 if (!tfmn) {
462 break;
463 }
464 tfmn = tf2SlotMin(mSlots.front().getTFStart() - 1);
465 }
466 return mSlots[0];
467 }
468 for (auto it = mSlots.begin(); it != mSlots.end(); it++) {
469 auto rel = (*it).relateToTF(tf);
470 if (rel == 0) {
471 return (*it);
472 }
473 }
474 // need to add in the end
475 auto tfmn = mSlots.empty() ? tf2SlotMin(tf) : tf2SlotMin(mSlots.back().getTFEnd() + 1);
476 do {
477 uint64_t tft = uint64_t(tfmn) + mSlotLength - 1;
478 if (mSlots.empty() && mStartOffsetTFs && tf < mStartOffsetTFs) { // if this was lowest possible TF, its length might be smaller than mSlotLength
479 tft -= mStartOffsetTFs;
480 }
482 LOG(info) << "Adding new slot for " << tfmn << " <= TF <= " << tfmx;
483 auto& sl = emplaceNewSlot(false, tfmn, tfmx);
484 sl.setRunStartOrbit(getRunStartOrbit());
485 sl.setStaticStartTimeMS(sl.getStartTimeMS());
486 tfmn = tft < o2::calibration::INFINITE_TF ? mSlots.back().getTFEnd() + 1 : tft;
487 } while (tf > mSlots.back().getTFEnd());
488
489 return mSlots.back();
490}
491
492//_________________________________________________
493template <typename Container>
495{
496 for (int i = 0; i < getNSlots(); i++) {
497 LOG(info) << "Slot #" << i + 1 << " of " << getNSlots();
498 getSlot(i).print();
499 }
500}
501
502//_________________________________________________
503template <typename Container>
505{
506 if (mSlots.empty()) {
507 LOG(warn) << "Nothing to save, no TimeSlots defined";
508 return false;
509 }
510 if (mSaveMetaData.startRun < 0) {
511 mSaveMetaData.startRun = mCurrentTFInfo.runNumber;
512 }
513 mSaveMetaData.endRun = mCurrentTFInfo.runNumber;
514 if (mSaveMetaData.startTime < 0) {
515 mSaveMetaData.startTime = mSlots.back().getStartTimeMS();
516 }
517 mSaveMetaData.endTime = mSlots.back().getEndTimeMS();
518 return true;
519}
520
521//_________________________________________________
522template <typename Container>
524{
525 if (!getSavedSlotAllowed()) {
526 LOG(info) << "Slot saving is disabled";
527 return false;
528 }
529 if (!updateSaveMetaData()) {
530 return false;
531 }
532
533 if (!mSaveDirectory.empty() && !std::filesystem::exists(mSaveDirectory)) {
534 std::filesystem::create_directories(mSaveDirectory);
535 if (!std::filesystem::exists(mSaveDirectory)) {
536 LOGP(fatal, "could not create output directory {}", mSaveDirectory);
537 } else {
538 LOGP(info, "created calibration directory {}", mSaveDirectory);
539 }
540 }
541
542 auto pth = getSaveFilePath();
543 auto pthTmp = pth + ".part";
544 TFile flout(pthTmp.c_str(), "recreate");
545 if (flout.IsZombie()) {
546 LOGP(error, "failed to open save file {}", pth);
547 unlink(pthTmp.c_str());
548 return false;
549 }
550 if (!saveLastSlotData(flout)) { // call used method to store data
551 flout.Close();
552 unlink(pthTmp.c_str());
553 return false;
554 }
555 flout.WriteObjectAny(&mSaveMetaData, "o2::calibration::TimeSlotMetaData", "metadata");
556 flout.Close();
557 std::filesystem::rename(pthTmp, pth);
558 LOGP(info, "Saved data of the last slot to {}", pth);
559 return true;
560}
561
562//_________________________________________________
563template <typename Container>
565{
566 if (!getSavedSlotAllowed()) {
567 LOG(info) << "Saved slot usage is disabled";
568 return false;
569 }
570 auto pth = getSaveFilePath();
571 if (!std::filesystem::exists(pth)) {
572 LOGP(info, "No save file {} is found", pth);
573 return false;
574 }
575 TFile flin(pth.c_str());
576 if (flin.IsZombie()) {
577 LOGP(error, "failed to open save file {}", pth);
578 return false;
579 }
580 auto meta = (o2::calibration::TimeSlotMetaData*)flin.GetObjectChecked("metadata", "o2::calibration::TimeSlotMetaData");
581 if (!meta) {
582 LOGP(error, "Failed to read metadata from {}", pth);
583 return false;
584 }
585 auto res = adoptSavedData(*meta, flin); // up to the detector to decide if data should be accepted
586 if (res) {
587 mSaveMetaData.startRun = meta->startRun;
588 mSaveMetaData.startTime = meta->startTime;
589 updateSaveMetaData();
590 }
591 flin.Close();
592 unlink(pth.c_str()); // cleanup used file
593 return true;
594}
595
596//_________________________________________________
597template <typename Container>
599{
600 if (mSaveFileName.empty()) {
601 LOGP(fatal, "Save file name was not set");
602 }
603 return fmt::format("{}{}{}", mSaveDirectory, ((!mSaveDirectory.empty() && mSaveDirectory.back() != '/') ? "/" : ""), mSaveFileName);
604}
605
606} // namespace calibration
607} // namespace o2
608
609#endif
std::ostringstream debug
int32_t i
Helper for geometry and GRP related CCDB requests.
uint32_t res
Definition RawData.h:0
static GRPGeomHelper & instance()
virtual bool adoptSavedData(const TimeSlotMetaData &metadata, TFile &fl)
virtual void checkSlotsToFinalize(TFType tf=INFINITE_TF, int maxDelay=0)
void setSaveFileName(const std::string &n)
ClassDef(TimeSlotCalibration, 1)
const o2::dataformats::TFIDInfo & getCurrentTFInfo() const
o2::dataformats::TFIDInfo & getCurrentTFInfo()
virtual void finalizeSlot(Slot &slot)=0
void setSaveDirectory(const std::string &n)
virtual bool hasEnoughData(const Slot &slot) const =0
const std::string & getSaveFileName() const
virtual Slot & emplaceNewSlot(bool front, TFType tstart, TFType tend)=0
void setTFEnd(TFType v)
Definition TimeSlot.h:58
GLdouble n
Definition glcorearb.h:1982
const GLdouble * v
Definition glcorearb.h:832
GLdouble f
Definition glcorearb.h:310
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLboolean * data
Definition glcorearb.h:298
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
uint32_t TFType
Definition TimeSlot.h:29
constexpr TFType INFINITE_TF
Definition TimeSlot.h:30
constexpr double LHCOrbitMUS
void check(const std::vector< std::string > &arguments, const std::vector< ConfigParamSpec > &workflowOptions, const std::vector< DeviceSpec > &deviceSpecs, CheckMatrix &matrix)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::unique_ptr< GPUReconstructionTimeframe > tf
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"