14#include "CLHEP/GenericFunctions/CumulativeChiSquare.hh"
15#include "CLHEP/Units/PhysicalConstants.h"
16#include "CLHEP/Units/SystemOfUnits.h"
17#include "GaudiKernel/MsgStream.h"
23 init(0.5 * CLHEP::mm);
48 const Amg::Vector3D& r_w2,
const double r_r2,
const double r_sigma22,
49 const int& r_case)
const {
60 double mx1=0, bx1=0, mx2=0, bx2=0;
66 if (r_case < 1 || r_case > 4) {
67 throw std::runtime_error(
68 Form(
"File: %s, Line: %d\nQuasianalyticLineReconstruction::tangent() - Illegal case %i, must be 1,2,3, or 4.", __FILE__,
77 e3prime = (r_w2 - r_w1).
unit();
81 if (r_case == 1 || r_case == 2) {
82 sinalpha = std::abs(r_r2 - r_r1) / (r_w2 - r_w1).
mag();
83 cosalpha = std::sqrt(1.0 - sinalpha * sinalpha);
87 p1 = r_w1 + ((1 && r_r2 >= r_r1) - (1 && r_r2 < r_r1)) * r_r1 * (cosalpha * e2prime - sinalpha * e3prime);
88 p2 = r_w2 + ((1 && r_r2 >= r_r1) - (1 && r_r2 < r_r1)) * r_r2 * (cosalpha * e2prime - sinalpha * e3prime);
93 p1 = r_w1 - ((1 && r_r2 >= r_r1) - (1 && r_r2 < r_r1)) * r_r1 * (cosalpha * e2prime + sinalpha * e3prime);
94 p2 = r_w2 - ((1 && r_r2 >= r_r1) - (1 && r_r2 < r_r1)) * r_r2 * (cosalpha * e2prime + sinalpha * e3prime);
99 if (r_case == 3 || r_case == 4) {
100 sinalpha = (r_r1 + r_r2) / (r_w2 - r_w1).mag();
101 cosalpha = std::sqrt(1.0 - sinalpha * sinalpha);
105 p1 = r_w1 + r_r1 * (cosalpha * e2prime + sinalpha * e3prime);
106 p2 = r_w2 - r_r2 * (cosalpha * e2prime + sinalpha * e3prime);
111 p1 = r_w1 - r_r1 * (cosalpha * e2prime - sinalpha * e3prime);
112 p2 = r_w2 + r_r2 * (cosalpha * e2prime - sinalpha * e3prime);
117 if ((p2 - p1).
z() != 0.0) {
121 direction[2] = 1.0e-99;
128 tang =
MTStraightLine(mx1, bx1, mx2, bx2, 1.0, 1.0, std::sqrt(r_sigma12 + r_sigma22) / std::abs(p2.z() - p1.z()),
129 std::sqrt(r_sigma12 + p1.z() * p1.z() * (r_sigma12 + r_sigma22) / std::pow(p2.z() - p1.z(), 2)));
136 const int& r_cand_case,
const std::vector<Amg::Vector3D>& r_w,
137 const std::vector<double>&
r_r,
const std::vector<double>& r_sigma2,
138 double& r_chi2)
const {
143 int nb_hits(r_index_set.
size());
147 std::vector<double> mx1, bx1, mx2, bx2;
149 std::vector<double> mx1_err, bx1_err, mx2_err, bx2_err;
153 Amg::Vector3D e2prime(0.0, 0.0, 0.0), e3prime(0.0, 0.0, 0.0);
167 aux_track =
tangent(r_w[r_k_cand],
r_r[r_k_cand], r_sigma2[r_k_cand], r_w[r_l_cand],
r_r[r_l_cand], r_sigma2[r_l_cand], r_cand_case);
172 mx1.push_back(aux_track.
a_x1());
174 bx1.push_back(aux_track.
b_x1());
176 mx2.push_back(aux_track.
a_x2());
178 bx2.push_back(aux_track.
b_x2());
185 for (
int kk = 0; kk < nb_hits - 1; kk++) {
186 for (
int ll = kk + 1; ll < nb_hits; ll++) {
187 int k(r_index_set[kk]);
188 int l(r_index_set[ll]);
190 if (k == r_k_cand && l == r_l_cand) {
continue; }
193 e3prime = (r_w[l] - r_w[k]).
unit();
197 d1 = (r_w[k] -
a).
dot(u) * u - (r_w[k] -
a);
199 d2 = (r_w[l] -
a).
dot(u) * u - (r_w[l] -
a);
205 if (d1.dot(d2) >= 0) {
206 sinalpha = std::abs(
r_r[l] -
r_r[k]) / (r_w[l] - r_w[k]).
mag();
207 cosalpha = std::sqrt(1.0 - sinalpha * sinalpha);
209 if (d1.dot(e2prime) >= 0) {
211 p1 = r_w[k] +
r_r[k] * (cosalpha * e2prime - sinalpha * e3prime);
213 p1 = r_w[k] +
r_r[k] * (cosalpha * e2prime + sinalpha * e3prime);
217 p1 = r_w[k] -
r_r[k] * (cosalpha * e2prime - sinalpha * e3prime);
219 p1 = r_w[k] -
r_r[k] * (cosalpha * e2prime + sinalpha * e3prime);
223 if (d2.dot(e2prime) >= 0) {
225 p2 = r_w[l] +
r_r[l] * (cosalpha * e2prime - sinalpha * e3prime);
227 p2 = r_w[l] +
r_r[l] * (cosalpha * e2prime + sinalpha * e3prime);
231 p2 = r_w[l] -
r_r[l] * (cosalpha * e2prime - sinalpha * e3prime);
233 p2 = r_w[l] -
r_r[l] * (cosalpha * e2prime + sinalpha * e3prime);
239 if (d1.dot(d2) < 0) {
240 sinalpha = (
r_r[l] +
r_r[k]) / (r_w[l] - r_w[k]).mag();
241 cosalpha = std::sqrt(1.0 - sinalpha * sinalpha);
244 if (d1.dot(e2prime) >= 0 && d2.dot(e2prime) <= 0) {
245 p1 = r_w[k] +
r_r[k] * (cosalpha * e2prime + sinalpha * e3prime);
246 p2 = r_w[l] -
r_r[l] * (cosalpha * e2prime + sinalpha * e3prime);
250 if (d1.dot(e2prime) < 0 && d2.dot(e2prime) >= 0) {
251 p1 = r_w[k] -
r_r[k] * (cosalpha * e2prime - sinalpha * e3prime);
252 p2 = r_w[l] +
r_r[l] * (cosalpha * e2prime - sinalpha * e3prime);
257 if ((p2 - p1).
z() != 0.0) {
261 direction[2] = (1.0e-99);
264 mx1.push_back(tang.
a_x1());
265 bx1.push_back(tang.
b_x1());
266 mx2.push_back(tang.
a_x2());
267 bx2.push_back(tang.
b_x2());
269 mx1_err.push_back(1.0);
270 bx1_err.push_back(1.0);
272 mx2_err.push_back((r_sigma2[k] + r_sigma2[l]) / std::pow(p2.z() - p1.z(), 2));
273 bx2_err.push_back(r_sigma2[k] + p1.z() * p1.z() * (r_sigma2[k] + r_sigma2[l]) / std::pow(p2.z() - p1.z(), 2));
278 nb_tangents = nb_tangents + 1;
291 for (
int k = 0; k < nb_tangents; k++) {
292 if (mx2_err[k] > 0) {
293 sum[0] = sum[0] + mx2[k] / mx2_err[k];
294 sum[1] = sum[1] + 1.0 / mx2_err[k];
296 sum[0] = sum[0] + mx2[k];
297 sum[1] = sum[1] + 1.0;
299 if (bx2_err[k] > 0) {
300 sum[2] = sum[2] + bx2[k] / bx2_err[k];
301 sum[3] = sum[3] + 1.0 / bx2_err[k];
303 sum[2] = sum[2] + bx2[k];
304 sum[3] = sum[3] + 1.0;
308 aux_track =
MTStraightLine(0.0, 0.0, sum[0] / sum[1], sum[2] / sum[3], 0.0, 1.0, std::sqrt(1.0 / sum[1]), std::sqrt(1.0 / sum[3]));
311 for (
int k = 0; k < nb_hits; k++) {
312 r_chi2 = r_chi2 + std::pow(aux_track.
distFromLine(r_w[r_index_set[k]]) -
r_r[r_index_set[k]], 2) / r_sigma2[k];
322 if (maxR < 7 || maxR > 15)
323 throw std::runtime_error(Form(
324 "File: %s, Line: %d\nQuasianalyticLineReconstruction::setMaxRadius() - given radius %.3f not supported, neither MDT nor sMDT",
325 __FILE__, __LINE__, maxR));
337 return fit(r_segment, r_selection, final_track);
347 unsigned int nb_selected_hits(0);
350 std::vector<unsigned> selected_hits_index(r_selection.size());
354 std::vector<Amg::Vector3D> w;
355 std::vector<double>
r;
356 std::vector<double> sigma2;
357 unsigned int counter1{0}, counter2{0}, counter3{0};
358 unsigned int max_cand_hits{0};
360 int max_cand_HOTs{0};
363 std::vector<int> k_cand, l_cand;
364 std::vector<int> cand_case;
365 std::vector<int> nb_HOTs;
368 std::vector<IndexSet> index_set;
370 std::vector<double> intercept;
387 <<
"Class QuasianalyticLineReconstruction, method fit: Vector with selected hits unequal to the number of hits on the segment! "
388 "The user selection will be ignored!"
393 for (
unsigned int k : r_selection) {
394 if (k == 0) { nb_selected_hits = nb_selected_hits + 1; }
412 if (nb_selected_hits < 3) {
414 log << MSG::WARNING <<
"Class QuasianalyticLineReconstruction, method fit: Too few hits for the track reconstructions!" <<
endmsg;
423 selected_hits.clear();
427 selected_hits_index.clear();
436 selected_hits.push_back(hit);
437 selected_hits_index.push_back(k);
442 if (sigma2[counter2] == 0) { sigma2[counter2] = std::pow(0.1 * CLHEP::mm, 2); }
444 counter2 = counter2 + 1;
446 nb_selected_hits = selected_hits.size();
447 if (nb_selected_hits < 3)
return false;
457 for (
unsigned int k = 0; k < nb_selected_hits; k++) {
458 for (
unsigned int l = k + 1; l < nb_selected_hits; l++) {
461 diff = difftime(end, start);
464 log << MSG::WARNING <<
"Class QuasianalyticLineReconstruction, method fit: time-out for track finding after " <<
m_time_out
470 for (
unsigned int r_case = 1; r_case < 5; r_case++) {
471 tangents[r_case - 1] =
tangent(w[l],
r[l], sigma2[l], w[k],
r[k], sigma2[k], r_case);
476 for (
unsigned int r_case = 1; r_case < 5; r_case++) {
480 std::vector<int> indices;
482 for (
unsigned int n = 0; n < nb_selected_hits; n++) {
484 if (std::abs(std::abs(tangents[r_case - 1].signDistFrom(aux_line)) -
r[n]) <
m_r_max) { counter3++; }
485 if (std::abs(std::abs(tangents[r_case - 1].signDistFrom(aux_line)) -
r[n]) <=
m_road_width) {
486 counter1 = counter1 + 1;
487 indices.push_back(n);
491 aux_set =
IndexSet(counter1, indices);
493 for (
int ca = 0; ca < nb_candidates; ca++) {
494 if (aux_set == index_set[ca] && std::abs(intercept[ca] - tangents[r_case - 1].b_x2()) <
m_road_width) {
499 if (same) {
continue; }
500 nb_candidates = nb_candidates + 1;
503 cand_case.push_back(r_case);
504 index_set.push_back(aux_set);
505 intercept.push_back(tangents[r_case - 1].b_x2());
506 nb_HOTs.push_back(counter3);
507 if (counter1 > max_cand_hits) { max_cand_hits = counter1; }
518 if (max_cand_hits < 3) {
return false; }
521 for (
int ca = 0; ca < nb_candidates; ca++) {
522 if (index_set[ca].size() < max_cand_hits) {
continue; }
524 aux_track =
track_candidate(index_set[ca], k_cand[ca], l_cand[ca], cand_case[ca], w,
r, sigma2, aux_chi2);
525 if (nb_HOTs[ca] >= max_cand_HOTs) {
526 max_cand_HOTs = nb_HOTs[ca];
527 if (
chi2 == -1.0 ||
chi2 > aux_chi2) {
529 final_track = aux_track;
535 MdtHitVec final_track_hits(max_cand_hits);
536 for (
unsigned int k = 0; k < max_cand_hits; k++) { final_track_hits[k] = selected_hits[index_set[candidate][k]]; }
544 if (std::isnan(
chi2)) {
chi2 = 1.0e6; }
547 std::vector<unsigned int> refit_hit_selection(r_selection.size(), 1);
548 for (
unsigned int k = 0; k < max_cand_hits; k++) { refit_hit_selection[selected_hits_index[index_set[candidate][k]]] = 0; }
553 if (
m_nfitter.fit(r_segment, refit_hit_selection)) {
555 if (dir.z() == 0.0) { dir[2] = (1.0e-99); }
565 for (
unsigned int k = 0; k < max_cand_hits; k++) {
569 double r(std::abs(final_track_hits[k]->driftRadius()));
570 chi2 += std::pow(d -
r, 2) / final_track_hits[k]->sigma2DriftRadius();
572 if (std::isnan(
chi2)) {
chi2 = 1.0e6; }
Scalar mag() const
mag method
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
bool m_refine_segment
flags
std::vector< unsigned int > HitSelection
void sort()
sort the indices in ascending order
unsigned int size() const
get the number of indices
Amg::Vector3D directionVector() const
get the direction vector of the straight line
double distFromLine(const Amg::Vector3D &point) const
get the distance of point point from straight line
double b_x2() const
get the intercept of the straight line in the x2-x3 plane
double b_x1_error() const
get the error on the intercept of the straight line in the x1-x3 plane
double a_x2() const
get the slope of the straight line in the x2-x3 plane
double b_x1() const
get the intercept of the straight line in the x1-x3 plane
Amg::Vector3D positionVector() const
get the position vector of the straight line
double a_x1() const
get the slope of the straight line in the x1-x3 plane
double b_x2_error() const
get the slope of the intercept of the straight line in the x2-x3 plane
double a_x1_error() const
get the error on the slope of the straight line in the x1-x3 plane
void setUsedHits(const MdtHitVec &hits)
double signDistFrom(const MTStraightLine &h) const
get the signed distance of two lines (if both are parallel, dist>0)
double a_x2_error() const
get the error on the slope of the straight line in the x2-x3 plane
void setChi2(double chi2)
Cache the chi2.
Athena-independent part of the MdtCalibHit.
float driftRadius() const
retrieve the radius of the drift circle
float sigma2DriftRadius() const
retrieve the error squared on the radius of the drift circle
float sigmaDriftRadius() const
retrieve the error on the radius of the drift circle
void setDistanceToTrack(float dist, float sigmaDist)
sets the distance to the fitted track and its error
const Amg::Vector3D & localPosition() const
retrieve the position expressed in local (station) coordinates
A MuonCalibSegment is a reconstructed three dimensional track segment in the MuonSpectrometer.
unsigned int mdtHitsOnTrack() const
retrieve the number of MdtCalibHitBase s assigned to this segment
void refineMdtSelection(const std::vector< unsigned int > &new_selection)
move trck hits to close hits
const Amg::Vector3D & direction() const
retrieve local direction of segment (on station level) retrieve the transformation from local chamber...
std::shared_ptr< MdtCalibHitBase > MdtHitPtr
typedef for a collection of MdtCalibHitBase s
unsigned int hitsOnTrack() const
retrieve the sum of all XxxCalibHits assigned to the MuonCalibSegment
const MdtHitVec & mdtHOT() const
retrieve the full set of MdtCalibHitBase s assigned to this segment
void set(double chi2, const Amg::Vector3D &pos, const Amg::Vector3D &dir)
const Amg::Vector3D & position() const
retrieve local position of segment (on station level)
MuonCalibSegment::MdtHitVec MdtHitVec
MTStraightLine tangent(const Amg::Vector3D &r_w1, const double r_r1, const double r_sigma12, const Amg::Vector3D &r_w2, const double r_r2, const double r_sigma22, const int &r_case) const
MuonCalibSegment::MdtHitPtr MdtHitPtr
void setMaxRadius(const double maxR)
set the max innerRadius, default for MDT sMDT 7.1mm, MDT 14.6mm
double roadWidth() const
get the road width used in the pattern recognition
void setRoadWidth(const double r_road_width)
set the road width for the pattern recognition = r_road_width
bool fit(MuonCalibSegment &r_segment) const
reconstruction of the track using all hits in the segment "r_segment", returns true in case of succes...
void setTimeOut(const double time_out)
set the time-out for the track finding to time_out (in seconds)
MTStraightLine track_candidate(const IndexSet &r_index_set, const int &r_k_cand, const int &r_l_cand, const int &r_cand_case, const std::vector< Amg::Vector3D > &r_w, const std::vector< double > &r_r, const std::vector< double > &r_sigma2, double &r_chi2) const
double chi2(TH1 *h0, TH1 *h1)
const std::string selection
singleton-like access to IMessageSvc via open function and helper
Eigen::Matrix< double, 3, 1 > Vector3D
IMessageSvc * getMessageSvc(bool quiet=false)
CscCalcPed - algorithm that finds the Cathode Strip Chamber pedestals from an RDO.