15 #include "TMinuitMinimizer.h"
23 bool improved_estimate,
28 useImprovedInitialEstimate_(improved_estimate),
29 multi_rp_algorithm_(mrpaUndefined),
34 TMinuitMinimizer::UseStaticMinuit(
false);
37 if (multiRPAlgorithm ==
"chi2")
39 else if (multiRPAlgorithm ==
"newton")
41 else if (multiRPAlgorithm ==
"anal-iter")
45 throw cms::Exception(
"ProtonReconstructionAlgorithm") <<
"Algorithm '" << multiRPAlgorithm <<
"' not understood.";
48 double pStart[] = {0, 0, 0, 0};
71 vector<double> xiValues =
74 rpod.
s_xi_vs_x_d = make_shared<TSpline3>(
"", xDValues.data(), xiValues.data(), xiValues.size());
100 const std::vector<double> &vy,
103 double s_1 = 0., s_x = 0., s_xx = 0., s_y = 0., s_xy = 0.;
104 for (
unsigned int i = 0;
i < vx.size(); ++
i) {
107 s_xx += vx[
i] * vx[
i];
109 s_xy += vx[
i] * vy[
i];
112 const double d = s_xx * s_1 - s_x * s_x;
113 a = (s_1 * s_xy - s_x * s_y) /
d;
114 b = (-s_x * s_xy + s_xx * s_y) /
d;
141 oit->second.optics->transport(k_in, k_out);
144 const double x = k_out.
x - oit->second.x0;
145 const double y = k_out.
y - oit->second.y0;
148 const double x_diff_norm = (
x -
track->x() * 1E-1) / (
track->xUnc() * 1E-1);
149 const double y_diff_norm = (
y -
track->y() * 1E-1) / (
track->yUnc() * 1E-1);
152 s2 += x_diff_norm * x_diff_norm + y_diff_norm * y_diff_norm;
173 std::ostream &os)
const {
175 for (
const auto &it :
tracks) {
179 <<
"Optics data not available for RP " << it->rpId() <<
", i.e. " <<
CTPPSDetId(it->rpId()) <<
".";
183 double xi_init = 0., th_x_init = 0.;
186 double x_N =
tracks[0]->x() * 1E-1,
187 x_F =
tracks[1]->x() * 1E-1;
192 const double a = i_F.ch1 * i_N.
la1 - i_N.
ch1 * i_F.la1;
194 i_F.ch0 * i_N.
la1 - i_N.
ch0 * i_F.la1 + i_F.ch1 * i_N.
la0 - i_N.
ch1 * i_F.la0 + x_N * i_F.la1 - x_F * i_N.
la1;
195 const double c = x_N * i_F.la0 - x_F * i_N.
la0 + i_F.ch0 * i_N.
la0 - i_N.
ch0 * i_F.la0;
196 const double D =
b *
b - 4. *
a *
c;
197 const double sqrt_D = (
D >= 0.) ?
sqrt(
D) : 0.;
199 xi_init = (-
b + sqrt_D) / 2. /
a;
200 th_x_init = (x_N - i_N.
ch0 - i_N.
ch1 * xi_init) / (i_N.
la0 + i_N.
la1 * xi_init);
202 double s_xi0 = 0., s_1 = 0.;
205 double xi = oit->second.s_xi_vs_x_d->Eval(
track->x() * 1E-1 + oit->second.x0);
211 xi_init = s_xi0 / s_1;
214 if (!std::isfinite(xi_init))
216 if (!std::isfinite(th_x_init))
220 double y[2] = {0}, v_y[2] = {0}, L_y[2] = {0};
221 unsigned int y_idx = 0;
228 y[y_idx] =
track->y() * 1E-1 - oit->second.s_y_d_vs_xi->Eval(xi_init);
229 v_y[y_idx] = oit->second.s_v_y_vs_xi->Eval(xi_init);
230 L_y[y_idx] = oit->second.s_L_y_vs_xi->Eval(xi_init);
235 double vtx_y_init = 0.;
236 double th_y_init = 0.;
239 const double det_y = v_y[0] * L_y[1] - L_y[0] * v_y[1];
240 vtx_y_init = (det_y != 0.) ? (L_y[1] *
y[0] - L_y[0] *
y[1]) / det_y : 0.;
241 th_y_init = (det_y != 0.) ? (v_y[0] *
y[1] - v_y[1] *
y[0]) / det_y : 0.;
244 th_y_init = (
y[1] / L_y[1] +
y[0] / L_y[0]) / 2.;
247 if (!std::isfinite(vtx_y_init))
249 if (!std::isfinite(th_y_init))
255 os <<
"ProtonReconstructionAlgorithm::reconstructFromMultiRP(" << armId <<
")" << std::endl
256 <<
" initial estimate: xi_init = " << xi_init <<
", th_x_init = " << th_x_init
257 <<
", th_y_init = " << th_y_init <<
", vtx_y_init = " << vtx_y_init <<
"." << std::endl;
262 double xi = 0., th_x = 0., th_y = 0., vtx_y = 0.;
269 fitter_->Config().ParSettings(0).Set(
"xi", xi_init, 0.005);
270 fitter_->Config().ParSettings(1).Set(
"th_x", th_x_init, 2E-6);
271 fitter_->Config().ParSettings(2).Set(
"th_y", th_y_init, 2E-6);
272 fitter_->Config().ParSettings(3).Set(
"vtx_y", vtx_y_init, 10E-6);
275 fitter_->Config().ParSettings(3).Fix();
294 map<unsigned int, signed int> index_map = {
296 {(
unsigned int)FP::Index::th_x, 1},
297 {(
unsigned int)FP::Index::th_y, 2},
298 {(
unsigned int)FP::Index::vtx_y, ((
fitVtxY_) ? 3 : -1)},
299 {(
unsigned int)FP::Index::vtx_x, -1},
302 for (
unsigned int i = 0;
i < (
unsigned int)FP::Index::num_indices; ++
i) {
303 signed int fit_i = index_map[
i];
305 for (
unsigned int j = 0;
j < (
unsigned int)FP::Index::num_indices; ++
j) {
306 signed int fit_j = index_map[
j];
308 cm(
i,
j) = (fit_i >= 0 && fit_j >= 0) ?
result.CovMatrix(fit_i, fit_j) : 0.;
316 const double maxXiDiff = 1E-6;
317 const double xi_ep = 1E-5;
320 double x_N =
tracks[0]->x() * 1E-1,
321 x_F =
tracks[1]->x() * 1E-1;
323 double y_N =
tracks[0]->y() * 1E-1,
324 y_F =
tracks[1]->y() * 1E-1;
331 double xi_prev = xi_init;
335 const double gp = (
newtonGoalFcn(xi_prev + xi_ep, x_N, x_F, i_N, i_F) -
g) / xi_ep;
337 xi = xi_prev -
g /
gp;
341 const double d_x_eff_N = i_N.
s_x_d_vs_xi->Eval(xi_prev) / xi_prev;
342 const double d_x_eff_F = i_F.s_x_d_vs_xi->Eval(xi_prev) / xi_prev;
344 const double l_x_N = i_N.
s_L_x_vs_xi->Eval(xi_prev);
345 const double l_x_F = i_F.s_L_x_vs_xi->Eval(xi_prev);
347 xi = (l_x_N * x_F - l_x_F * x_N) / (l_x_N * d_x_eff_F - l_x_F * d_x_eff_N);
350 if (
abs(
xi - xi_prev) < maxXiDiff) {
358 th_x = (x_F - i_F.s_x_d_vs_xi->Eval(
xi)) / i_F.s_L_x_vs_xi->Eval(
xi);
362 const double y_eff_F = y_F - i_F.s_y_d_vs_xi->Eval(
xi);
365 const double l_y_F = i_F.s_L_y_vs_xi->Eval(
xi);
368 const double v_y_F = i_F.s_v_y_vs_xi->Eval(
xi);
370 const double det = l_y_N * v_y_F - l_y_F * v_y_N;
373 th_y = (y_eff_N * v_y_F - y_eff_F * v_y_N) / det;
374 vtx_y = (l_y_N * y_eff_F - l_y_F * y_eff_N) / det;
376 th_y = (y_eff_N / l_y_N + y_eff_F / l_y_F) / 2.;
385 os <<
" fit valid=" <<
valid << std::endl
386 <<
" xi=" <<
xi <<
", th_x=" << th_x <<
", th_y=" << th_y <<
", vtx_y=" << vtx_y <<
", chiSq = " <<
chi2
390 const double sign_z = (armId == 0) ? +1. : -1.;
392 const double cos_th_sq = 1. - th_x * th_x - th_y * th_y;
393 const double cos_th = (cos_th_sq > 0.) ?
sqrt(cos_th_sq) : 1.;
394 const double p = lhcInfo.
energy() * (1. -
xi);
397 sign_z *
p * cos_th);
407 std::ostream &os)
const {
411 os <<
"reconstructFromSingleRP(" <<
rpId.arm() * 100 +
rpId.station() * 10 +
rpId.rp() <<
")" << std::endl;
417 <<
"Optics data not available for RP " <<
track->rpId() <<
", i.e. " <<
rpId <<
".";
420 const double x_full =
track->x() * 1E-1 + oit->second.x0;
421 const double xi = oit->second.s_xi_vs_x_d->Eval(x_full);
422 const double L_y = oit->second.s_L_y_vs_xi->Eval(
xi);
423 const double th_y =
track->y() * 1E-1 / L_y;
425 const double ep_x = 1E-6;
426 const double dxi_dx = (oit->second.s_xi_vs_x_d->Eval(x_full + ep_x) -
xi) / ep_x;
427 const double xi_unc =
abs(dxi_dx) *
track->xUnc() * 1E-1;
429 const double ep_xi = 1E-4;
430 const double dL_y_dxi = (oit->second.s_L_y_vs_xi->Eval(
xi + ep_xi) - L_y) / ep_xi;
431 const double th_y_unc_sq = th_y * th_y * (
pow(
track->yUnc() /
track->y(), 2.) +
pow(dL_y_dxi * xi_unc / L_y, 2.));
434 os <<
" xi = " <<
xi <<
" +- " << xi_unc <<
", th_y = " << th_y <<
" +- " <<
sqrt(th_y_unc_sq) <<
"."
442 const double cos_th_sq = 1. - th_y * th_y;
443 const double cos_th = (cos_th_sq > 0.) ?
sqrt(cos_th_sq) : 1.;
444 const double p = lhcInfo.
energy() * (1. -
xi);
445 const FP::Vector momentum(0.,
p * th_y, sign_z *
p * cos_th);
449 cm((
int)FP::Index::th_y, (
int)FP::Index::th_y) = th_y_unc_sq;