14 #include <Eigen/Dense>
18 #include <tracking/calibration/BoostVectorStandAlone.h>
19 #include <tracking/calibration/Splitter.h>
20 #include <tracking/calibration/tools.h>
21 #include <tracking/calibration/minimizer.h>
23 #include <BoostVectorStandAlone.h>
26 #include <minimizer.h>
30 using Eigen::VectorXd;
31 using Eigen::Vector3d;
32 using Eigen::MatrixXd;
33 using Eigen::Matrix3d;
36 namespace Belle2::BoostVectorCalib {
39 double median(
double* v,
int n)
41 B2ASSERT(
"At least 3 points to get median", n > 2);
44 std::nth_element(v, v + n / 2, v + n);
47 std::nth_element(v, v + n / 2, v + n);
50 std::nth_element(v, v + n / 2 - 1, v + n);
51 double v2 = v[n / 2 - 1];
62 vector<Event> getEvents(TTree* tr)
66 events.reserve(tr->GetEntries());
70 tr->SetBranchAddress(
"run", &evt.run);
71 tr->SetBranchAddress(
"exp", &evt.exp);
72 tr->SetBranchAddress(
"event", &evt.evtNo);
74 TVector3* p0 =
nullptr;
75 TVector3* p1 =
nullptr;
77 tr->SetBranchAddress(
"mu0_p", &p0);
78 tr->SetBranchAddress(
"mu1_p", &p1);
80 tr->SetBranchAddress(
"mu0_pid", &evt.mu0.pid);
81 tr->SetBranchAddress(
"mu1_pid", &evt.mu1.pid);
84 tr->SetBranchAddress(
"time", &evt.t);
87 for (
int i = 0; i < tr->GetEntries(); ++i) {
95 events.push_back(evt);
99 sort(events.begin(), events.end(), [](Event e1, Event e2) {return e1.t < e2.t;});
114 Vector3d pars(-c, -s, -1);
116 res = res.array().square();
118 return median(res.data(), res.rows());
124 MatrixXd toMat(
const vector<vector<double>>& vecs)
126 MatrixXd mat(vecs[0].size(), vecs.size());
128 for (
unsigned k = 0; k < vecs.size(); ++k)
129 for (
unsigned i = 0; i < vecs[k].size(); ++i)
130 mat(i, k) = vecs[k][i];
136 vector<double> getRapidities(vector<TVector3> vecs, vector<double> boostDir)
138 TVector3 boost(boostDir[0], boostDir[1], 1);
139 boost = boost.Unit();
141 double th0 = vecs[0].Angle(boost);
142 double th1 = vecs[1].Angle(boost);
144 const double mL = 105.6583745e-3;
146 double pMu0 = vecs[0].Mag();
147 double pMu1 = vecs[1].Mag();
149 double C0 = 1. / sqrt(pow(mL / pMu0, 2) + 1);
150 double C1 = 1. / sqrt(pow(mL / pMu1, 2) + 1);
152 double y0 = atanh(cos(th0) * C0);
153 double y1 = atanh(cos(th1) * C1);
159 vector<double> fitBoostFast(
const vector<Event>& evts)
161 vector<double> vCos, vSin, vData;
163 for (
const auto& e : evts) {
164 if (e.nBootStrap * e.isSig == 0)
continue;
165 vector<TVector3> vecs = {e.mu0.p, e.mu1.p};
168 TVector3 n = vecs[0].Cross(vecs[1]);
169 double phi = n.Phi();
170 double angle = M_PI / 2 - n.Theta();
171 auto res = make_pair(phi, tan(angle));
173 for (
int i = 0; i < e.nBootStrap * e.isSig; ++i) {
174 vCos.push_back(cos(res.first));
175 vSin.push_back(sin(res.first));
176 vData.push_back(res.second);
183 fun.mat = toMat({vCos, vSin, vData});
184 fun.res.resize(vCos.size());
186 auto res =
getMinimum(fun, 130e-3 , 170e-3, -20e-3, 20e-3);
200 vector<Event>
filter(
const vector<Event>& evts,
const vector<double>& boostDir,
double pidCut,
double rapCut)
204 for (
const auto& e : evts) {
205 for (
int i = 0; i < e.nBootStrap * e.isSig; ++i) {
208 if (e.mu0.pid < pidCut || e.mu1.pid < pidCut) {
212 vector<TVector3> vecs = {e.mu0.p, e.mu1.p};
213 vector<double> raps = getRapidities(vecs, boostDir);
215 double yDiff = abs(raps[0] - raps[1]) / 2;
218 if (yDiff > rapCut)
continue;
230 double fitBoostMagnitude(
const vector<Event>& evts,
const vector<double>& boostDir)
233 vector<double> yAvgVec;
235 for (
auto e : evts) {
236 if (e.nBootStrap * e.isSig == 0)
continue;
237 vector<TVector3> vecs = {e.mu0.p, e.mu1.p};
239 vector<double> raps = getRapidities(vecs, boostDir);
241 double yAvg = (raps[0] + raps[1]) / 2.;
242 for (
int i = 0; i < e.nBootStrap * e.isSig; ++i) {
243 yAvgVec.push_back(yAvg);
247 return median(yAvgVec.data(), yAvgVec.size());
256 void add(Vector3d v) { vecs.push_back(v); }
259 Vector3d
getNom()
const {
return vecs[0]; }
264 Matrix3d res = Matrix3d::Zero();
265 for (
unsigned i = 1; i < vecs.size(); ++i) {
266 Vector3d diff = vecs[i] - vecs[0];
267 res += diff * diff.transpose();
270 res *= 1. / (vecs.size() - 1);
280 TVector3 getBoostVector(
const vector<Event>& evts)
283 vector<double> boostDir = fitBoostFast(evts);
286 double yMag = fitBoostMagnitude(evts, boostDir);
289 double beta = tanh(yMag);
292 TVector3 bVec = TVector3(boostDir[0], boostDir[1], 1);
295 bVec = beta * bVec.Unit();
301 pair<Vector3d, Matrix3d> getBoostAndError(vector<Event> evts)
303 evts =
filter(evts, {151.986e-3 , 0}, 0.9, 1.0 );
307 const int nBoost = 10;
308 for (
int i = 0; i < nBoost; ++i) {
311 e.nBootStrap = gRandom->Poisson(1);
313 TVector3 b = getBoostVector(evts);
314 Vector3d boost(b.X(), b.Y(), b.Z());
317 return make_pair(var.getNom(), var.getCov());
322 vector<vector<Event>> separate(
const vector<Event>& evts,
const vector<double>& splitPoints)
324 vector<vector<Event>> evtsOut(splitPoints.size() + 1);
326 for (
const auto& ev : evts) {
327 for (
int i = 0; i < int(splitPoints.size()) - 1; ++i) {
328 if (splitPoints[i] < ev.t && ev.t < splitPoints[i + 1]) {
329 evtsOut[i + 1].push_back(ev);
334 if (splitPoints.size() >= 1) {
335 if (ev.t < splitPoints.front()) evtsOut.front().push_back(ev);
336 if (ev.t > splitPoints.back()) evtsOut.back().push_back(ev);
338 evtsOut[0].push_back(ev);
350 tuple<vector<VectorXd>, vector<MatrixXd>, MatrixXd> runBoostVectorAnalysis(vector<Event> evts,
351 const vector<double>& splitPoints)
353 int n = splitPoints.size() + 1;
354 vector<VectorXd> boostVec(n);
355 vector<MatrixXd> boostVecUnc(n);
356 MatrixXd boostVecSpred;
358 vector<vector<Event>> evtsSep = separate(evts, splitPoints);
361 for (
int i = 0; i < n; ++i) {
363 tie(boostVec[i], boostVecUnc[i]) = getBoostAndError(evtsSep[i]);
367 double aX = 1e3 * boostVec[i][0] / boostVec[i][2];
369 double aY = 1e3 * boostVec[i][1] / boostVec[i][2];
372 double eX = 1e3 * sqrt(boostVecUnc[i](0, 0)) / boostVec[i](2);
374 double eY = 1e3 * sqrt(boostVecUnc[i](1, 1)) / boostVec[i](2);
376 B2INFO(evtsSep[i][0].run <<
" " << i <<
" " << evtsSep[i].size() <<
" : " << aX <<
"+-" << eX <<
" " << aY <<
"+-" << eY <<
377 " : " << 1e3 * boostVec[i].norm());
381 boostVecSpred = MatrixXd::Zero(3, 3);
383 return make_tuple(boostVec, boostVecUnc, boostVecSpred);
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
std::vector< double > getMinimum(std::function< double(double, double)> fun, double xMin, double xMax, double yMin, double yMax)
Get minimum of 2D function in the rectangular domain defined by xMin,xMax & yMin,yMax.
const std::vector< double > v2
MATLAB generated random vector.
const std::vector< double > v1
MATLAB generated random vector.
Functor to minimize median of residuals^2.
double operator()(double c, double s)
get median of residuals^2
VectorXd res
vector with residuals^2
MatrixXd mat
Matrix of the linear system.
Structure to store all bootstrap replicas.
MatrixXd getCov() const
Get cov matrix with unc.
Vector3d getNom() const
Get the nominal result.
void add(Vector3d v)
Add replica.
vector< Vector3d > vecs
Vector of replicas.