Skip to content

Commit e7c79ba

Browse files
committed
Possibility to have 1st calibration slot shorter than nominal
1 parent c594038 commit e7c79ba

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

Detectors/Calibration/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ In order to prepare only one CCDB object at the end of the run you can use `setU
4242

4343
See e.g. LHCClockCalibrator.h/cxx in AliceO2/Detectors/TOF/calibration/include/TOFCalibration/LHCClockCalibrator.h and AliceO2/Detectors/TOF/calibration/srcLHCClockCalibrator.cxx
4444

45+
Sometimes it might be useful to define the 1st slot of the run shorter than the nominal slot length, e.g. to not rely to long on the previous run or default calibration. In this case one can impose to the
46+
calibration class an offset using method `setStartOffsetFrac(float offset)`, where `offset` is a fractional of the nominal slot length to be subtracted from the nominal boundaries of all slots (except the
47+
very 1st one, whose startTF is set to 0). The fractional offset should be in `[0:0.95)` range, any value outside this range will be overridden to the nearest boundary.
48+
This feature is supported only for the finite slot-length calibrations. E.g. if the nominal slot length is 10 minutes `(==~210000 TFs)`, setting `setStartOffsetFrac(float 0.7)` will lead to 1st slot
49+
finalized after the first 3 minutes, while the rest of the slots will be defined with nominal 10 minutes coverage. If statistics of this 1st short slot is insufficient, it will be merged as usual
50+
with the next slot (note this if this happens, in the example above the 1st calibration will be available in 13 minutes...).
51+
4552
## TimeSlot<Container>
4653

4754
The TimeSlot is a templated class which takes as input type the Container that will hold the calibration data needed to produce the calibration objects (histograms, vectors, array...). Each calibration device could implement its own Container, according to its needs.

Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,35 @@ class TimeSlotCalibration
8787
setSlotLength(ntf);
8888
mSlotLengthInOrbits = 0;
8989
}
90+
setStartOffsetFrac(mStartOffsetFrac); // set once more to account for eventual dependencies
91+
mStartOffsetTFs = TFType(mSlotLength * mStartOffsetFrac);
92+
}
93+
94+
void setStartOffsetFrac(float f)
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 {
107+
mStartOffsetFrac = f;
108+
}
109+
if (mStartOffsetFrac || f != mStartOffsetFrac) {
110+
LOGP(info, "Imposing offset of {:4.2} x nominal slot length", mStartOffsetFrac);
111+
}
90112
}
91113

92114
void setFinalizeWhenReady()
93115
{
94116
mFinalizeWhenReady = true;
95117
setSlotLength(INFINITE_TF);
118+
mStartOffsetFrac = 0;
96119
}
97120

98121
void setUpdateAtTheEndOfRunOnly() { mUpdateAtTheEndOfRunOnly = kTRUE; }
@@ -219,7 +242,6 @@ class TimeSlotCalibration
219242
}
220243

221244
TFType tf2SlotMin(TFType tf) const;
222-
223245
std::deque<Slot> mSlots;
224246

225247
o2::dataformats::TFIDInfo mCurrentTFInfo{};
@@ -229,6 +251,8 @@ class TimeSlotCalibration
229251
TFType mFirstTF = 0;
230252
TFType mMaxSeenTF = 0; // largest TF processed
231253
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.
232256
TFType mCheckIntervalInfiniteSlot = 1; // will be used if the TF length is INFINITE_TF_int64 to decide
233257
// when to check if to call the finalize; otherwise it is called
234258
// at every new TF; note that this is an approximation,
@@ -381,16 +405,20 @@ void TimeSlotCalibration<Container>::finalizeOldestSlot()
381405
template <typename Container>
382406
inline TFType TimeSlotCalibration<Container>::tf2SlotMin(TFType tf) const
383407
{
384-
385408
// returns the min TF of the slot to which "tf" belongs
386-
387409
if (tf < mFirstTF) {
388410
throw std::runtime_error("invalid TF");
389411
}
390412
if (mUpdateAtTheEndOfRunOnly) {
391413
return mFirstTF;
392414
}
393-
uint64_t tft = int64_t(((tf - mFirstTF) / mSlotLength) * mSlotLength) + mFirstTF;
415+
int64_t tft = 0;
416+
tft = int64_t(((tf - mFirstTF + mStartOffsetTFs) / mSlotLength) * mSlotLength) + mFirstTF;
417+
if (tft > mStartOffsetTFs) {
418+
tft -= mStartOffsetTFs;
419+
} else {
420+
tft = 0;
421+
}
394422
return tft < o2::calibration::INFINITE_TF ? TFType(tft) : INFINITE_TF;
395423
}
396424

@@ -415,7 +443,7 @@ TimeSlot<Container>& TimeSlotCalibration<Container>::getSlotForTF(TFType tf)
415443
auto tfmn = tf2SlotMin(mSlots.front().getTFStart() - 1); // min TF of the slot corresponding to a TF smaller than the first seen
416444
auto tftgt = tf2SlotMin(tf); // min TF of the slot to which the TF "tf" would belong
417445
while (tfmn >= tftgt) {
418-
uint64_t tft = uint64_t(tfmn) + mSlotLength - 1;
446+
uint64_t tft = mSlots.front().getTFStart() - 1;
419447
TFType tfmx = tft < o2::calibration::INFINITE_TF ? TFType(tft) : o2::calibration::INFINITE_TF;
420448
LOG(info) << "Adding new slot for " << tfmn << " <= TF <= " << tfmx;
421449
auto& sl = emplaceNewSlot(true, tfmn, tfmx);
@@ -438,12 +466,15 @@ TimeSlot<Container>& TimeSlotCalibration<Container>::getSlotForTF(TFType tf)
438466
auto tfmn = mSlots.empty() ? tf2SlotMin(tf) : tf2SlotMin(mSlots.back().getTFEnd() + 1);
439467
do {
440468
uint64_t tft = uint64_t(tfmn) + mSlotLength - 1;
469+
if (mSlots.empty() && mStartOffsetTFs && tf < mStartOffsetTFs) { // if this was lowest possible TF, its length might be smaller than mSlotLength
470+
tft -= mStartOffsetTFs;
471+
}
441472
TFType tfmx = tft < o2::calibration::INFINITE_TF ? TFType(tft) : o2::calibration::INFINITE_TF;
442473
LOG(info) << "Adding new slot for " << tfmn << " <= TF <= " << tfmx;
443474
auto& sl = emplaceNewSlot(false, tfmn, tfmx);
444475
sl.setRunStartOrbit(getRunStartOrbit());
445476
sl.setStaticStartTimeMS(sl.getStartTimeMS());
446-
tfmn = tf2SlotMin(mSlots.back().getTFEnd() + 1);
477+
tfmn = tft < o2::calibration::INFINITE_TF ? mSlots.back().getTFEnd() + 1 : tft;
447478
} while (tf > mSlots.back().getTFEnd());
448479

449480
return mSlots.back();

0 commit comments

Comments
 (0)