15 #include "TMinuitMinimizer.h"
23 bool improved_estimate,
26 : verbosity_(verbosity),
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};
59 for (
const auto &
p : opticalFunctions) {
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;
130 0., parameters[1], parameters[3], parameters[2], parameters[0]};
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.;
203 for (
const auto &
track : tracks) {
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;
222 for (
const auto &
track : tracks) {
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))
252 unsigned int armId =
CTPPSDetId((*tracks.begin())->rpId()).arm();
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();
285 const double *
params = result.GetParams();
287 valid = result.IsValid();
288 chi2 = result.Chi2();
294 map<unsigned int, signed int> index_map = {
295 {(
unsigned int)FP::Index::xi, 0},
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.;
315 const unsigned int maxIterations = 100;
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;
332 for (
unsigned int it = 0; it < maxIterations; ++it) {
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);
361 const double y_eff_N = y_N - i_N.
s_y_d_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);
398 signed int ndf = 2. * tracks.size() - ((
fitVtxY_) ? 4. : 3.);
400 return reco::ForwardProton(chi2, ndf, vertex, momentum, xi, cm, FP::ReconstructionMethod::multiRP, tracks, valid);
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) <<
"."
440 const double sign_z = (
CTPPSDetId(track->rpId()).arm() == 0) ? +1. : -1.;
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);
448 cm((
int)FP::Index::xi, (
int)FP::Index::xi) = xi_unc * xi_unc;
449 cm((
int)FP::Index::th_y, (
int)FP::Index::th_y) = th_y_unc_sq;
454 return reco::ForwardProton(0., 0, vertex, momentum, xi, cm, FP::ReconstructionMethod::singleRP, trk,
true);
std::unique_ptr< ROOT::Fit::Fitter > fitter_
fitter object
std::shared_ptr< const TSpline3 > s_xi_vs_x_d
const edm::EventSetup & c
optics data associated with 1 RP
class for calculation of chi^2
ROOT::Math::Plane3D::Vector Vector
reco::ForwardProton reconstructFromSingleRP(const CTPPSLocalTrackLiteRef &track, const LHCInfo &lhcInfo, std::ostream &os) const
run proton reconstruction using single-RP strategy
auto const & tracks
cannot be loose
math::Error< 5 >::type CovarianceMatrix
const std::vector< double > & getXiValues() const
std::map< unsigned int, RPOpticsData > m_rp_optics_
map: RP id –> optics data
double y0
beam vertical position, cm
std::shared_ptr< const TSpline3 > s_x_d_vs_xi
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
const std::map< unsigned int, RPOpticsData > * m_rp_optics
void init(const LHCInterpolatedOpticalFunctionsSetCollection &opticalFunctions)
const std::vector< std::shared_ptr< const TSpline3 > > & splines() const
enum ProtonReconstructionAlgorithm::@1005 multi_rp_algorithm_
std::unique_ptr< ChiSquareCalculator > chiSquareCalculator_
object to calculate chi^2
bool useImprovedInitialEstimate_
double ch0
intercept for linear approximation of
ProtonReconstructionAlgorithm(bool fit_vtx_y, bool improved_estimate, const std::string &multiRPAlgorithm, unsigned int verbosity)
double x0
beam horizontal position, cm
static double newtonGoalFcn(double xi, double x_N, double x_F, const RPOpticsData &i_N, const RPOpticsData &i_F)
double la1
slope for linear approximation of
reco::ForwardProton reconstructFromMultiRP(const CTPPSLocalTrackLiteRefVector &tracks, const LHCInfo &lhcInfo, std::ostream &os) const
run proton reconstruction using multiple-RP strategy
double operator()(const double *parameters) const
static void doLinearFit(const std::vector< double > &vx, const std::vector< double > &vy, double &b, double &a)
Abs< T >::type abs(const T &t)
proton kinematics description
const CTPPSLocalTrackLiteRefVector * tracks
double la0
intercept for linear approximation of
void transport(const Kinematics &input, Kinematics &output, bool calculateAngles=false) const
transports proton according to the splines
std::shared_ptr< const TSpline3 > s_v_y_vs_xi
DecomposeProduct< arg, typename Div::arg > D
Set of optical functions corresponding to one scoring plane along LHC, including splines for interpol...
Base class for CTPPS detector IDs.
std::shared_ptr< const TSpline3 > s_L_y_vs_xi
float const energy() const
void push_back(value_type const &ref)
Add a Ref<C, T> to the RefVector.
const LHCInterpolatedOpticalFunctionsSet * optics
double ch1
slope for linear approximation of
std::shared_ptr< const TSpline3 > s_L_x_vs_xi
std::shared_ptr< const TSpline3 > s_y_d_vs_xi
Power< A, B >::type pow(const A &a, const B &b)
const std::vector< std::vector< double > > & getFcnValues() const