17 #include <Eigen/Dense>
21 #include <tracking/calibration/BoostVectorStandAlone.h>
22 #include <tracking/calibration/Splitter.h>
23 #include <tracking/calibration/tools.h>
24 #include <tracking/calibration/minimizer.h>
26 #include <BoostVectorStandAlone.h>
29 #include <minimizer.h>
33 using Eigen::VectorXd;
34 using Eigen::Vector3d;
35 using Eigen::MatrixXd;
36 using Eigen::Matrix3d;
44 namespace BoostVectorCalib {
47 double median(
double* v,
int n)
49 B2ASSERT(
"At least 3 points to get median", n > 2);
52 std::nth_element(v, v + n / 2, v + n);
55 std::nth_element(v, v + n / 2, v + n);
58 std::nth_element(v, v + n / 2 - 1, v + n);
59 double v2 = v[n / 2 - 1];
70 vector<Event> getEvents(TTree* tr)
74 events.reserve(tr->GetEntries());
78 tr->SetBranchAddress(
"run", &evt.run);
79 tr->SetBranchAddress(
"exp", &evt.exp);
80 tr->SetBranchAddress(
"event", &evt.evtNo);
82 TVector3* p0 =
nullptr;
83 TVector3* p1 =
nullptr;
85 tr->SetBranchAddress(
"mu0_p", &p0);
86 tr->SetBranchAddress(
"mu1_p", &p1);
88 tr->SetBranchAddress(
"mu0_pid", &evt.mu0.pid);
89 tr->SetBranchAddress(
"mu1_pid", &evt.mu1.pid);
92 tr->SetBranchAddress(
"time", &evt.t);
95 for (
int i = 0; i < tr->GetEntries(); ++i) {
103 events.push_back(evt);
107 sort(events.begin(), events.end(), [](Event e1, Event e2) {return e1.t < e2.t;});
122 Vector3d pars(-c, -s, -1);
124 res = res.array().square();
126 return median(res.data(), res.rows());
132 MatrixXd toMat(
const vector<vector<double>>& vecs)
134 MatrixXd mat(vecs[0].size(), vecs.size());
136 for (
unsigned k = 0; k < vecs.size(); ++k)
137 for (
unsigned i = 0; i < vecs[k].size(); ++i)
138 mat(i, k) = vecs[k][i];
144 vector<double> getRapidities(vector<TVector3> vecs, vector<double> boostDir)
146 TVector3 boost(boostDir[0], boostDir[1], 1);
147 boost = boost.Unit();
149 double th0 = vecs[0].Angle(boost);
150 double th1 = vecs[1].Angle(boost);
152 const double mL = 105.6583745e-3;
154 double pMu0 = vecs[0].Mag();
155 double pMu1 = vecs[1].Mag();
157 double C0 = 1. / sqrt(pow(mL / pMu0, 2) + 1);
158 double C1 = 1. / sqrt(pow(mL / pMu1, 2) + 1);
160 double y0 = atanh(cos(th0) * C0);
161 double y1 = atanh(cos(th1) * C1);
167 vector<double> fitBoostFast(
const vector<Event>& evts)
169 vector<double> vCos, vSin, vData;
171 for (
const auto& e : evts) {
172 if (
e.nBootStrap *
e.isSig == 0)
continue;
173 vector<TVector3> vecs = {
e.mu0.p,
e.mu1.p};
176 TVector3 n = vecs[0].Cross(vecs[1]);
177 double phi = n.Phi();
178 double angle = M_PI / 2 - n.Theta();
179 auto res = make_pair(phi, tan(angle));
181 for (
int i = 0; i <
e.nBootStrap *
e.isSig; ++i) {
182 vCos.push_back(cos(res.first));
183 vSin.push_back(sin(res.first));
184 vData.push_back(res.second);
191 fun.mat = toMat({vCos, vSin, vData});
192 fun.res.resize(vCos.size());
194 auto res = getMinimum(fun, 130e-3 , 170e-3, -20e-3, 20e-3);
208 vector<Event>
filter(
const vector<Event>& evts,
const vector<double>& boostDir,
double pidCut,
double rapCut)
212 for (
const auto& e : evts) {
213 for (
int i = 0; i <
e.nBootStrap *
e.isSig; ++i) {
216 if (!isnan(
e.mu0.pid) && !isnan(
e.mu0.pid)) {
217 if (
e.mu0.pid < pidCut ||
e.mu1.pid < pidCut) {
222 vector<TVector3> vecs = {
e.mu0.p,
e.mu1.p};
223 vector<double> raps = getRapidities(vecs, boostDir);
225 double yDiff = abs(raps[0] - raps[1]) / 2;
228 if (yDiff > rapCut)
continue;
240 double fitBoostMagnitude(
const vector<Event>& evts,
const vector<double>& boostDir)
243 vector<double> yAvgVec;
245 for (
auto e : evts) {
246 if (
e.nBootStrap *
e.isSig == 0)
continue;
247 vector<TVector3> vecs = {
e.mu0.p,
e.mu1.p};
249 vector<double> raps = getRapidities(vecs, boostDir);
251 double yAvg = (raps[0] + raps[1]) / 2.;
252 for (
int i = 0; i <
e.nBootStrap *
e.isSig; ++i) {
253 yAvgVec.push_back(yAvg);
257 return median(yAvgVec.data(), yAvgVec.size());
266 void add(Vector3d v) { vecs.push_back(v); }
269 Vector3d
getNom()
const {
return vecs[0]; }
274 Matrix3d res = Matrix3d::Zero();
275 for (
unsigned i = 1; i < vecs.size(); ++i) {
276 Vector3d diff = vecs[i] - vecs[0];
277 res += diff * diff.transpose();
280 res *= 1. / (vecs.size() - 1);
290 TVector3 getBoostVector(
const vector<Event>& evts)
293 vector<double> boostDir = fitBoostFast(evts);
296 double yMag = fitBoostMagnitude(evts, boostDir);
299 double beta = tanh(yMag);
302 TVector3 bVec = TVector3(boostDir[0], boostDir[1], 1);
305 bVec = beta * bVec.Unit();
311 pair<Vector3d, Matrix3d> getBoostAndError(vector<Event> evts)
313 evts =
filter(evts, {151.986e-3 , 0}, 0.9, 1.0 );
317 const int nBoost = 10;
318 for (
int i = 0; i < nBoost; ++i) {
321 e.nBootStrap = gRandom->Poisson(1);
323 TVector3 b = getBoostVector(evts);
324 Vector3d boost(b.X(), b.Y(), b.Z());
327 return make_pair(var.getNom(), var.getCov());
332 vector<vector<Event>> separate(
const vector<Event>& evts,
const vector<double>& splitPoints)
334 vector<vector<Event>> evtsOut(splitPoints.size() + 1);
336 for (
const auto& ev : evts) {
337 for (
int i = 0; i < int(splitPoints.size()) - 1; ++i) {
338 if (splitPoints[i] < ev.t && ev.t < splitPoints[i + 1]) {
339 evtsOut[i + 1].push_back(ev);
344 if (splitPoints.size() >= 1) {
345 if (ev.t < splitPoints.front()) evtsOut.front().push_back(ev);
346 if (ev.t > splitPoints.back()) evtsOut.back().push_back(ev);
348 evtsOut[0].push_back(ev);
360 tuple<vector<VectorXd>, vector<MatrixXd>, MatrixXd> runBoostVectorAnalysis(vector<Event> evts,
361 const vector<double>& splitPoints)
363 int n = splitPoints.size() + 1;
364 vector<VectorXd> boostVec(n);
365 vector<MatrixXd> boostVecUnc(n);
366 MatrixXd boostVecSpred;
368 vector<vector<Event>> evtsSep = separate(evts, splitPoints);
371 for (
int i = 0; i < n; ++i) {
373 tie(boostVec[i], boostVecUnc[i]) = getBoostAndError(evtsSep[i]);
377 double aX = 1e3 * boostVec[i][0] / boostVec[i][2];
379 double aY = 1e3 * boostVec[i][1] / boostVec[i][2];
382 double eX = 1e3 * sqrt(boostVecUnc[i](0, 0)) / boostVec[i](2);
384 double eY = 1e3 * sqrt(boostVecUnc[i](1, 1)) / boostVec[i](2);
386 B2INFO(evtsSep[i][0].run <<
" " << i <<
" " << evtsSep[i].size() <<
" : " << aX <<
"+-" << eX <<
" " << aY <<
"+-" << eY <<
387 " : " << 1e3 * boostVec[i].norm());
391 boostVecSpred = MatrixXd::Zero(3, 3);
393 return make_tuple(boostVec, boostVecUnc, boostVecSpred);