15 #include "TMinuitMinimizer.h" 23 bool improved_estimate,
25 : verbosity_(verbosity),
27 useImprovedInitialEstimate_(improved_estimate),
32 TMinuitMinimizer::UseStaticMinuit(
false);
35 double pStart[] = {0, 0, 0, 0};
46 for (
const auto &
p : opticalFunctions) {
56 vector<double> xiValues =
59 rpod.
s_xi_vs_x_d = make_shared<TSpline3>(
"", xDValues.data(), xiValues.data(), xiValues.size());
85 const std::vector<double> &vy,
88 double s_1 = 0., s_x = 0., s_xx = 0., s_y = 0., s_xy = 0.;
89 for (
unsigned int i = 0;
i < vx.size(); ++
i) {
92 s_xx += vx[
i] * vx[
i];
94 s_xy += vx[
i] * vy[
i];
97 const double d = s_xx * s_1 - s_x * s_x;
98 a = (s_1 * s_xy - s_x * s_y) / d;
99 b = (-s_x * s_xy + s_xx * s_y) / d;
115 0., parameters[1], parameters[3], parameters[2], parameters[0]};
124 auto oit = m_rp_optics->find(rpId);
126 oit->second.optics->transport(k_in, k_out);
129 const double x = k_out.
x - oit->second.x0;
130 const double y = k_out.
y - oit->second.y0;
133 const double x_diff_norm = (x -
track->x() * 1E-1) / (
track->xUnc() * 1E-1);
134 const double y_diff_norm = (y -
track->y() * 1E-1) / (
track->yUnc() * 1E-1);
137 s2 += x_diff_norm * x_diff_norm + y_diff_norm * y_diff_norm;
147 std::ostream &os)
const {
149 for (
const auto &it : tracks) {
153 <<
"Optics data not available for RP " << it->rpId() <<
", i.e. " <<
CTPPSDetId(it->rpId()) <<
".";
157 double xi_init = 0., th_x_init = 0.;
160 double x_N = tracks[0]->x() * 1E-1,
161 x_F = tracks[1]->x() * 1E-1;
166 const double a = i_F.ch1 * i_N.
la1 - i_N.
ch1 * i_F.la1;
168 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;
169 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;
170 const double D = b * b - 4. * a *
c;
171 const double sqrt_D = (D >= 0.) ?
sqrt(D) : 0.;
173 xi_init = (-b + sqrt_D) / 2. / a;
174 th_x_init = (x_N - i_N.
ch0 - i_N.
ch1 * xi_init) / (i_N.
la0 + i_N.
la1 * xi_init);
176 double s_xi0 = 0., s_1 = 0.;
177 for (
const auto &
track : tracks) {
179 double xi = oit->second.s_xi_vs_x_d->Eval(
track->x() * 1E-1 + oit->second.x0);
185 xi_init = s_xi0 / s_1;
188 if (!std::isfinite(xi_init))
190 if (!std::isfinite(th_x_init))
194 double y[2] = {0}, v_y[2] = {0}, L_y[2] = {0};
195 unsigned int y_idx = 0;
196 for (
const auto &
track : tracks) {
202 y[y_idx] =
track->y() * 1E-1 - oit->second.s_y_d_vs_xi->Eval(xi_init);
203 v_y[y_idx] = oit->second.s_v_y_vs_xi->Eval(xi_init);
204 L_y[y_idx] = oit->second.s_L_y_vs_xi->Eval(xi_init);
209 double vtx_y_init = 0.;
210 double th_y_init = 0.;
213 const double det_y = v_y[0] * L_y[1] - L_y[0] * v_y[1];
214 vtx_y_init = (det_y != 0.) ? (L_y[1] * y[0] - L_y[0] * y[1]) / det_y : 0.;
215 th_y_init = (det_y != 0.) ? (v_y[0] * y[1] - v_y[1] * y[0]) / det_y : 0.;
218 th_y_init = (y[1] / L_y[1] + y[0] / L_y[0]) / 2.;
221 if (!std::isfinite(vtx_y_init))
223 if (!std::isfinite(th_y_init))
226 unsigned int armId =
CTPPSDetId((*tracks.begin())->rpId()).arm();
229 os <<
"ProtonReconstructionAlgorithm::reconstructFromMultiRP(" << armId <<
")" << std::endl
230 <<
" initial estimate: xi_init = " << xi_init <<
", th_x_init = " << th_x_init
231 <<
", th_y_init = " << th_y_init <<
", vtx_y_init = " << vtx_y_init <<
"." << std::endl;
234 fitter_->Config().ParSettings(0).Set(
"xi", xi_init, 0.005);
235 fitter_->Config().ParSettings(1).Set(
"th_x", th_x_init, 2E-6);
236 fitter_->Config().ParSettings(2).Set(
"th_y", th_y_init, 2E-6);
237 fitter_->Config().ParSettings(3).Set(
"vtx_y", vtx_y_init, 10E-6);
240 fitter_->Config().ParSettings(3).Fix();
250 const double *
params = result.GetParams();
253 os <<
" xi=" << params[0] <<
" +- " << result.Error(0) <<
", th_x=" << params[1] <<
" +-" << result.Error(1)
254 <<
", th_y=" << params[2] <<
" +-" << result.Error(2) <<
", vtx_y=" << params[3] <<
" +-" << result.Error(3)
255 <<
", chiSq = " << result.Chi2() << std::endl;
260 const double sign_z = (armId == 0) ? +1. : -1.;
262 const double xi = params[0];
263 const double th_x = params[1];
264 const double th_y = params[2];
265 const double cos_th =
sqrt(1. - th_x * th_x - th_y * th_y);
266 const double p = lhcInfo.
energy() * (1. -
xi);
269 sign_z * p * cos_th);
270 signed int ndf = 2. * tracks.size() - ((
fitVtxY_) ? 4. : 3.);
272 map<unsigned int, signed int> index_map = {
274 {(
unsigned int)FP::Index::th_x, 1},
275 {(
unsigned int)FP::Index::th_y, 2},
276 {(
unsigned int)FP::Index::vtx_y, ((
fitVtxY_) ? 3 : -1)},
277 {(
unsigned int)FP::Index::vtx_x, -1},
281 for (
unsigned int i = 0;
i < (
unsigned int)FP::Index::num_indices; ++
i) {
282 signed int fit_i = index_map[
i];
284 for (
unsigned int j = 0;
j < (
unsigned int)FP::Index::num_indices; ++
j) {
285 signed int fit_j = index_map[
j];
287 cm(
i,
j) = (fit_i >= 0 && fit_j >= 0) ? result.CovMatrix(fit_i, fit_j) : 0.;
292 result.Chi2(), ndf,
vertex, momentum,
xi, cm, FP::ReconstructionMethod::multiRP,
tracks, result.IsValid());
299 std::ostream &os)
const {
303 os <<
"reconstructFromSingleRP(" << rpId.
arm() * 100 + rpId.station() * 10 + rpId.rp() <<
")" << std::endl;
309 <<
"Optics data not available for RP " << track->rpId() <<
", i.e. " << rpId <<
".";
312 const double x_full = track->x() * 1E-1 + oit->second.x0;
313 const double xi = oit->second.s_xi_vs_x_d->Eval(x_full);
314 const double L_y = oit->second.s_L_y_vs_xi->Eval(xi);
315 const double th_y = track->y() * 1E-1 / L_y;
317 const double ep_x = 1E-6;
318 const double dxi_dx = (oit->second.s_xi_vs_x_d->Eval(x_full + ep_x) -
xi) / ep_x;
319 const double xi_unc =
abs(dxi_dx) * track->xUnc() * 1E-1;
321 const double ep_xi = 1E-4;
322 const double dL_y_dxi = (oit->second.s_L_y_vs_xi->Eval(xi + ep_xi) - L_y) / ep_xi;
323 const double th_y_unc = th_y *
sqrt(
pow(track->yUnc() / track->y(), 2.) +
pow(dL_y_dxi * xi_unc / L_y, 2.));
326 os <<
" xi = " << xi <<
" +- " << xi_unc <<
", th_y = " << th_y <<
" +- " << th_y_unc <<
"." << std::endl;
331 const double sign_z = (
CTPPSDetId(track->rpId()).arm() == 0) ? +1. : -1.;
333 const double cos_th =
sqrt(1. - th_y * th_y);
334 const double p = lhcInfo.
energy() * (1. -
xi);
335 const FP::Vector momentum(0., p * th_y, sign_z * p * cos_th);
338 cm((
int)
FP::Index::xi, (
int)FP::Index::xi) = xi_unc * xi_unc;
339 cm((
int)FP::Index::th_y, (
int)FP::Index::th_y) = th_y_unc * th_y_unc;
344 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
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
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
void init(const LHCInterpolatedOpticalFunctionsSetCollection &opticalFunctions)
const std::vector< std::shared_ptr< const TSpline3 > > & splines() const
std::unique_ptr< ChiSquareCalculator > chiSquareCalculator_
object to calculate chi^2
bool useImprovedInitialEstimate_
double ch0
intercept for linear approximation of
double x0
beam horizontal position, cm
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
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...
ProtonReconstructionAlgorithm(bool fit_vtx_y, bool improved_estimate, unsigned int verbosity)
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_y_d_vs_xi
Power< A, B >::type pow(const A &a, const B &b)
const std::vector< std::vector< double > > & getFcnValues() const