13 #include <tracking/calibration/Splitter.h>
14 #include <TMatrixDSym.h>
19 #include <framework/database/EventDependency.h>
20 #include <framework/datastore/StoreArray.h>
21 #include <calibration/CalibrationAlgorithm.h>
23 #include <Eigen/Dense>
46 TMatrixDSym mOut(mIn.rows());
47 for (
int i = 0; i < mIn.rows(); ++i)
48 for (
int j = 0; j < mIn.cols(); ++j)
49 mOut(i, j) = (mIn(i, j) + mIn(j, i)) / 2.;
56 return TVector3(vIn(0), vIn(1), vIn(2));
60 inline int getID(
const std::vector<double>& breaks,
double t)
62 for (
int i = 0; i < int(breaks.size()) + 1; ++i) {
63 double s = (i == 0) ? 0 : breaks[i - 1];
64 double e = (i == int(breaks.size())) ? 1e20 : breaks[i];
73 std::vector<Eigen::VectorXd>
cnt;
88 std::vector<std::map<ExpRun, std::pair<double, double>>>
subIntervals;
104 for (
unsigned i = 0; i < calVec.size(); ++i) {
105 if (calVec[i].pars.cnt.size() != 0)
continue;
106 const auto& r = calVec[i].subIntervals;
110 Eigen::Vector3d ipNow;
111 Eigen::MatrixXd ipeNow;
112 Eigen::MatrixXd sizeMatNow;
114 double distMin = 1e20;
116 for (
unsigned j = 0; j < calVec.size(); ++j) {
117 if (calVec[j].isCalibrated ==
false)
continue;
118 const auto& rJ = calVec[j].subIntervals;
119 for (
unsigned jj = 0; jj < rJ.size(); ++jj) {
120 const auto& rNow = rJ[jj];
121 double s = rNow.begin()->second.first;
122 double e = rNow.rbegin()->second.second;
124 double dist1 = (s - End >= 0) ? (s - End) : 1e20;
125 double dist2 = (Start - e >= 0) ? (Start - e) : 1e20;
126 double dist = std::min(dist1, dist2);
128 if (dist < distMin) {
129 ipNow = calVec[j].pars.cnt.at(jj);
130 ipeNow = calVec[j].pars.cntUnc.at(jj);
131 sizeMatNow = calVec[j].pars.spreadMat;
138 calVec[i].pars.cnt.resize(r.size());
139 calVec[i].pars.cntUnc.resize(r.size());
140 for (
unsigned ii = 0; ii < r.size(); ++ii) {
141 calVec[i].pars.cnt.at(ii) = ipNow;
142 calVec[i].pars.cntUnc.at(ii) = ipeNow;
144 calVec[i].pars.spreadMat = sizeMatNow;
150 inline void addShortRun(std::vector<CalibrationData>& calVec, std::pair<
ExpRun, std::pair<double, double>> shortRun)
152 double shortStart = shortRun.second.first;
153 double shortEnd = shortRun.second.second;
155 double distMin = 1e20;
156 int iMin = -1, jMin = -1;
158 for (
unsigned i = 0; i < calVec.size(); ++i) {
159 if (calVec[i].isCalibrated ==
false)
161 for (
unsigned j = 0; j < calVec[i].subIntervals.size(); ++j) {
162 for (
auto I : calVec[i].subIntervals[j]) {
163 double s = I.second.first;
164 double e = I.second.second;
166 double dist1 = (s - shortEnd >= 0) ? (s - shortEnd) : 1e20;
167 double dist2 = (shortStart - e >= 0) ? (shortStart - e) : 1e20;
168 double dist = std::min(dist1, dist2);
170 if (dist < distMin) {
179 B2ASSERT(
"Must be found", iMin != -1 && jMin != -1);
180 calVec[iMin].subIntervals[jMin].insert(shortRun);
187 double factor = pow(FLT_RADIX, DBL_MANT_DIG);
188 static const long long fEnc = pow(2, 32);
191 double mantisa = std::frexp(val, &e);
192 long long mantisaI = mantisa * factor;
195 mantisaI = (mantisaI / fEnc) * fEnc + num;
197 mantisaI = factor / 2 + num;
201 double newVal = ldexp(mantisaI / factor, e);
209 double factor = pow(FLT_RADIX, DBL_MANT_DIG);
210 static const long long fEnc = pow(2, 32);
213 double mantisa = std::frexp(val, &e);
214 long long mantisaI = mantisa * factor;
216 return (mantisaI % fEnc);
223 template<
typename Evt>
224 inline void storePayloads(
const std::vector<Evt>& evts,
const std::vector<CalibrationData>& calVecConst, std::string objName,
225 std::function<TObject*(Eigen::VectorXd, Eigen::MatrixXd, Eigen::MatrixXd) > getCalibObj)
227 auto calVec = calVecConst;
230 ExpRun exprunLast(-1, -1);
234 for (
unsigned i = 0; i < calVec.size(); ++i) {
235 const auto& r = calVec[i].subIntervals;
237 for (
int k = 0; k < int(r.size()); ++k) {
239 for (
auto I : r[k]) {
243 if (calVec[i].pars.cntUnc.at(k).rows() == 3) {
244 calVec[i].pars.cntUnc.at(k)(0, 1) = calVec[i].pars.cntUnc.at(k)(1, 0) =
encodeNumber(calVec[i].pars.cntUnc.at(k)(0, 1),
245 round(I.second.first * 3600));
246 calVec[i].pars.cntUnc.at(k)(0, 2) = calVec[i].pars.cntUnc.at(k)(2, 0) =
encodeNumber(calVec[i].pars.cntUnc.at(k)(0, 2),
247 round(I.second.second * 3600));
249 calVec[i].pars.cntUnc.at(k)(0, 0) =
encodeNumber(calVec[i].pars.cntUnc.at(k)(0, 0), round(I.second.first * 3600));
250 calVec[i].pars.spreadMat(0, 0) =
encodeNumber(calVec[i].pars.spreadMat(0, 0), round(I.second.second * 3600));
253 TObject* obj = getCalibObj(calVec[i].pars.cnt.at(k), calVec[i].pars.cntUnc.at(k), calVec[i].pars.spreadMat);
254 if (exprun != exprunLast) {
264 breakPoint = calVec[i].breakPoints.at(k - 1).evt;
265 B2ASSERT(
"Payload saving consistency", calVec[i].breakPoints.at(k - 1).run == exprun.run);
267 B2ASSERT(
"Payload saving consistency", i != 0);
271 breakPoint = pos.evt;
272 B2ASSERT(
"Payload saving consistency", pos.run == exprun.run);
274 intraRun->
add(breakPoint, obj);
290 std::function<TObject*(Eigen::VectorXd, Eigen::MatrixXd, Eigen::MatrixXd) > getCalibObj)
292 auto calVec = calVecConst;
295 std::set<ExpRun> existingRuns;
296 for (
unsigned i = 0; i < calVec.size(); ++i) {
297 const auto& r = calVec[i].subIntervals;
299 for (
int k = 0; k < int(r.size()); ++k) {
301 for (
auto I : r[k]) {
304 if (existingRuns.count(exprun) != 0)
305 B2FATAL(
"Intra-run dependence exists");
306 existingRuns.insert(exprun);
313 for (
unsigned i = 0; i < calVec.size(); ++i) {
314 const auto& r = calVec[i].subIntervals;
316 for (
unsigned k = 0; k < r.size(); ++k) {
318 TObject* obj = getCalibObj(calVec[i].pars.cnt.at(k), calVec[i].pars.cntUnc.at(k), calVec[i].pars.spreadMat);
320 ExpRun start = (r[k].cbegin()->first);
321 ExpRun last = (r[k].crbegin()->first);
333 template<
typename Evt,
typename Fun>
342 B2INFO(
"Start of loop startTime endTime : " << rStart <<
" " << rEnd);
346 std::vector<Evt> evtsNow;
348 std::vector<int> Counts(breaks.size() + 1, 0);
350 for (
const auto& ev : evts) {
351 if (rStart <= ev.t && ev.t < rEnd) {
352 evtsNow.push_back(ev);
353 ++Counts.at(
getID(breaks, ev.t));
357 B2ASSERT(
"Number of intervals vs number of breakPoints", r.size() == breaks.size() + 1);
360 for (
int k = 0; k < 10; ++k) {
361 int iMin = min_element(Counts.begin(), Counts.end()) - Counts.begin();
362 if (Counts.size() >= 2 && Counts[iMin] < 50) {
366 else if (iMin ==
int(Counts.size()) - 1)
369 if (Counts[iMin + 1] < Counts[iMin - 1])
374 B2ASSERT(
"Number of intervals equal to size of counters", r.size() == Counts.size());
377 r.erase(r.begin() + iMin);
379 Counts[iM] += Counts[iMin];
380 Counts.erase(Counts.begin() + iMin);
384 B2INFO(
"#events " <<
" : " << evtsNow.size());
385 B2INFO(
"Breaks size " <<
" : " << breaks.size());
391 if (breaks.size() > 0)
392 B2INFO(
"StartOfCalibInterval (run,evtNo,vtxIntervalsSize) " << calD.
breakPoints.at(0).run <<
" " <<
398 if (evtsNow.size() < 50) {
403 B2INFO(
"Start of running calibration over calibration interval");
406 B2INFO(
"End of running analysis - SpreadMatX : " << sqrt(abs(calD.
pars.
spreadMat(0, 0))));
407 B2ASSERT(
"All subintervals have calibration of the mean value", calD.
pars.
cnt.size() == r.size());
408 B2ASSERT(
"All subintervals have calibration of the unc. of mean", calD.
pars.
cntUnc.size() == r.size());
426 template<
typename Fun1,
typename Fun2>
428 std::function<TObject*(Eigen::VectorXd, Eigen::MatrixXd, Eigen::MatrixXd)> calibObjCreator,
429 TString m_lossFunctionOuter, TString m_lossFunctionInner)
432 if (!tracks || tracks->GetEntries() < 15) {
434 B2WARNING(
"Too few data : " << tracks->GetEntries());
435 return CalibrationAlgorithm::EResult::c_NotEnoughData;
437 B2INFO(
"Number of tracks: " << tracks->GetEntries());
440 auto evts = GetEvents(tracks);
443 std::map<ExpRun, std::pair<double, double>> runsInfoOrg =
getRunInfo(evts);
444 std::map<ExpRun, std::pair<double, double>> runsRemoved;
445 auto runsInfo =
filter(runsInfoOrg, 2. / 60, runsRemoved);
448 if (runsInfo.size() == 0) {
449 B2WARNING(
"Too short run");
450 return CalibrationAlgorithm::EResult::c_NotEnoughData;
455 auto splits = splt.
getIntervals(runsInfo, evts, m_lossFunctionOuter, m_lossFunctionInner);
458 std::vector<CalibrationData> calVec;
459 for (
auto s : splits) {
461 calVec.push_back(calD);
468 for (
auto shortRun : runsRemoved) {
475 return CalibrationAlgorithm::EResult::c_OK;
EResult
The result of calibration.
Class for handling changing conditions as a function of event number.
void add(unsigned int event, TObject *object)
Add an object to the intra run dependency.
A class that describes the interval of experiments/runs for which an object in the database is valid.
Class that allows to split runs into the intervals of intended properties given by the lossFunction.
std::vector< std::vector< std::map< ExpRun, std::pair< double, double > > > > getIntervals(const std::map< ExpRun, std::pair< double, double >> &runs, std::vector< Evt > evts, TString lossFunctionOuter, TString lossFunctionInner, double atomSize=3./60)
Function to merge/divide runs into the calibration intervals of given characteristic length.
static std::vector< double > getBreaks(std::vector< std::map< ExpRun, std::pair< double, double >>> res)
Get vector with breaks of the calib.
static std::pair< double, double > getStartEnd(std::vector< std::map< ExpRun, std::pair< double, double >>> res)
Get the start/end time of the calibration interval (vector of the calib.
static Database & Instance()
Instance of a singleton Database.
bool storeData(const std::string &name, TObject *object, const IntervalOfValidity &iov)
Store an object in the database.
std::map< ExpRun, std::pair< double, double > > filter(const std::map< ExpRun, std::pair< double, double >> &runs, double cut, std::map< ExpRun, std::pair< double, double >> &runsRemoved)
filter events to remove runs shorter than cut, it stores removed runs in runsRemoved
ExpRunEvt getPosition(const std::vector< Evt > &events, double tEdge)
Get the exp-run-evt number from the event time [hours].
void storePayloadsNoIntraRun(const std::vector< CalibrationData > &calVecConst, std::string objName, std::function< TObject *(Eigen::VectorXd, Eigen::MatrixXd, Eigen::MatrixXd) > getCalibObj)
Store payloads to files, where calib data have no intra-run dependence.
void addShortRun(std::vector< CalibrationData > &calVec, std::pair< ExpRun, std::pair< double, double >> shortRun)
Extrapolate calibration to the very short runs which were filtered before.
unsigned decodeNumber(double val)
Decode the integer number encoded in val.
double encodeNumber(double val, unsigned num)
Encode integer num into double val such that val is nearly not changed (maximally by a relative shift...
static std::map< ExpRun, std::pair< double, double > > mergeIntervals(std::map< ExpRun, std::pair< double, double >> I1, std::map< ExpRun, std::pair< double, double >> I2)
Merge two subintervals into one subinterval.
int getID(const std::vector< double > &breaks, double t)
get id of the time point t
CalibrationData runAlgorithm(const std::vector< Evt > &evts, std::vector< std::map< ExpRun, std::pair< double, double >>> range, Fun runCalibAnalysis)
run calibration algorithm for single calibration interval
TMatrixDSym toTMatrixDSym(Eigen::MatrixXd mIn)
Function that converts Eigen symmetric matrix to ROOT matrix.
CalibrationAlgorithm::EResult runCalibration(TTree *tracks, const std::string &calibName, Fun1 GetEvents, Fun2 calibAnalysis, std::function< TObject *(Eigen::VectorXd, Eigen::MatrixXd, Eigen::MatrixXd)> calibObjCreator, TString m_lossFunctionOuter, TString m_lossFunctionInner)
Run the the calibration over the whole event sample.
void extrapolateCalibration(std::vector< CalibrationData > &calVec)
Extrapolate calibration to intervals where it failed.
void storePayloads(const std::vector< Evt > &evts, const std::vector< CalibrationData > &calVecConst, std::string objName, std::function< TObject *(Eigen::VectorXd, Eigen::MatrixXd, Eigen::MatrixXd) > getCalibObj)
Store payloads to files.
std::map< ExpRun, std::pair< double, double > > getRunInfo(const std::vector< Evt > &evts)
Get the map of runs, where each run contains pair with start/end time [hours].
std::vector< ExpRunEvt > convertSplitPoints(const std::vector< Evt > &events, std::vector< double > splitPoints)
Convert splitPoints [hours] to breakPoints in ExpRunEvt.
TVector3 toTVector3(Eigen::VectorXd vIn)
Function that converts Eigen vector to ROOT vector.
Abstract base class for different kinds of events.
The parameters related to single calibration interval.
std::vector< Eigen::MatrixXd > cntUnc
vector of uncertainties of means for each calib. subinterval
std::vector< double > pulls
vector of pulls between mumu and hadB methods (for eCMS)
Eigen::MatrixXd spreadMat
spread CovMatrix
double shift
difference between eCMS for hadronic B decay method and mumu method, i.e. hadB - mumu
std::vector< Eigen::VectorXd > cnt
vector of means for each calib. subinterval
double shiftUnc
stat uncertainty of the shift
int size() const
number of the subintervals
double spreadUnc
stat uncertainty of the spread (for eCMS)
Parameters and data relevant for single calibration interval.
std::vector< std::map< ExpRun, std::pair< double, double > > > subIntervals
vector of the start and end times of the calibration subintervals
CalibPars pars
The parameters of the calibration itself.
bool isCalibrated
true if calibration run was successful
std::vector< ExpRunEvt > breakPoints
vector with break points positions
Struct containing exp number and run number.