ATLAS Offline Software
T0Refinement.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
5 
6 #include <fstream>
7 #include <iostream>
8 
13 
14 using namespace MuonCalib;
15 
17  : m_qfitter (std::make_unique<StraightPatRec>()),
18  m_cfitter (std::make_unique<CurvedPatRec>()),
19  m_delta_t0 (30.0),
20  m_time_out (2.0)
21 {
22  m_qfitter->setRoadWidth(1.0); // 1.0 mm road width
23  m_qfitter->switchOnRefit();
24  m_qfitter->setTimeOut(m_time_out);
25  m_cfitter->setRoadWidth(1.0); // 1.0 mm road width
26  m_cfitter->setTimeOut(m_time_out);
27 }
28 
29 double T0Refinement::getDeltaT0(MuonCalibSegment* segment, const IRtRelation* rt, bool overwrite, double& error, bool& failed,
30  bool curved) {
32  // CHECK IF THERE ARE ENOUGH HITS ON THE SEGMENT //
34 
35  if (segment->mdtHitsOnTrack() < 3) { return 0.0; }
36 
38  // VARIABLES //
40 
41  double delta_t0_opt; // the best t0 correction
42  MuonCalibSegment seg(*segment); // segment used internally
43  NtupleStationId id((seg.mdtHOT())[0]->identify()); // station identifier
44  double time; // time and radius of a hit
45  double sigma; // sigma(r)
47  SimplePolynomial pol; // polynomial base functions x^k
48  std::vector<SamplePoint> my_points(3);
49  IMdtPatRecFitter* segment_fitter = nullptr;
50  if (curved) {
51  segment_fitter = m_cfitter.get();
52  } else {
53  segment_fitter = m_qfitter.get();
54  }
55  segment_fitter->SetRefineSegmentFlag(false);
56  IMdtSegmentFitter::HitSelection r_selection(seg.mdtHitsOnTrack(), 0);
57 
59  // DETERMINE THE CHI^2 VALUES FOR THREE DIFFERENT t0s //
61 
62  // original drift times //
63  m_qfitter->setFixSelection(false);
64  unsigned int k = 0;
65  for (const MuonCalibSegment::MdtHitPtr& mdt_hit : seg.mdtHOT()) {
66  time = mdt_hit->driftTime();
67  sigma = mdt_hit->sigmaDriftRadius();
68  if (sigma > 10.0 && std::abs(mdt_hit->driftRadius()) > 14.0) r_selection[k] = 1;
69  if (sigma > 10.0 && mdt_hit->driftTime() < 50.0) sigma = 0.3;
70  mdt_hit->setDriftRadius(rt->radius(time), sigma);
71  ++k;
72  }
73  MTStraightLine straight_track;
74  CurvedLine curved_track;
75  if (curved) {
76  if (!m_cfitter->fit(seg, r_selection, curved_track)) {
77  failed = true;
78  return 0.0;
79  }
80  } else {
81  if (!m_qfitter->fitCallByReference(seg, r_selection, straight_track)) {
82  failed = true;
83  return 0.0;
84  }
85  }
86 
87  my_points[0].set_x1(0.0);
88  if (curved) {
89  my_points[0].set_x2(curved_track.chi2PerDegreesOfFreedom());
90  } else {
91  my_points[0].set_x2(straight_track.chi2PerDegreesOfFreedom());
92  }
93  my_points[0].set_error(1.0);
94 
95  m_qfitter->setFixSelection(true);
96  // shift drift times by +m_delta_t0 and refit //
97  for (const MuonCalibSegment::MdtHitPtr& mdt_hit : seg.mdtHOT()) {
98  time = mdt_hit->driftTime() + m_delta_t0;
99  sigma = mdt_hit->sigmaDriftRadius();
100  mdt_hit->setDriftRadius(rt->radius(time), sigma);
101  }
102  if (!segment_fitter->fit(seg, r_selection)) {
103  failed = true;
104  return 0.0;
105  }
106 
107  my_points[1].set_x1(m_delta_t0);
108  if (curved) {
109  my_points[1].set_x2(curved_track.chi2PerDegreesOfFreedom());
110  } else {
111  my_points[1].set_x2(straight_track.chi2PerDegreesOfFreedom());
112  }
113  my_points[1].set_error(1.0);
114 
115  // shift drift times by -m_delta_t0 and refit //
116  for (const MuonCalibSegment::MdtHitPtr& mdt_hit : seg.mdtHOT()) {
117  if (my_points[1].x2() > my_points[0].x2()) {
118  time = mdt_hit->driftTime() - m_delta_t0;
119  my_points[2].set_x1(-m_delta_t0);
120  } else {
121  time = mdt_hit->driftTime() + 2.0 * m_delta_t0;
122  my_points[2].set_x1(2.0 * m_delta_t0);
123  }
124  sigma = mdt_hit->sigmaDriftRadius();
125  mdt_hit->setDriftRadius(rt->radius(time), sigma);
126  }
127  if (!segment_fitter->fit(seg, r_selection)) {
128  failed = true;
129  return 0.0;
130  }
131  if (curved) {
132  my_points[2].set_x2(curved_track.chi2PerDegreesOfFreedom());
133  } else {
134  my_points[2].set_x2(straight_track.chi2PerDegreesOfFreedom());
135  }
136  my_points[2].set_error(1.0);
137 
138  // negative branch of T0 shifts
139  if (my_points[1].x2() > my_points[0].x2() && my_points[2].x2() < my_points[0].x2()) {
140  my_points[1].set_x1(my_points[2].x1());
141  my_points[1].set_x2(my_points[2].x2());
142 
143  my_points[2].set_x1(-2.0 * m_delta_t0);
144 
145  for (const MuonCalibSegment::MdtHitPtr& mdt_hit : seg.mdtHOT()) {
146  time = mdt_hit->driftTime() - 2.0 * m_delta_t0;
147  sigma = mdt_hit->sigmaDriftRadius();
148  mdt_hit->setDriftRadius(rt->radius(time), sigma);
149  }
150  if (!segment_fitter->fit(seg, r_selection)) {
151  failed = true;
152  return 0.0;
153  }
154  if (curved) {
155  my_points[2].set_x2(curved_track.chi2PerDegreesOfFreedom());
156  } else {
157  my_points[2].set_x2(straight_track.chi2PerDegreesOfFreedom());
158  }
159  my_points[2].set_error(1.0);
160  }
161 
163  if (my_points[1].x1() < 0.0) {
164  for (unsigned int l = 3; my_points[l - 1].x2() < my_points[l - 2].x2() && std::abs(my_points[l - 1].x1()) < 200.0; l++) {
165  SamplePoint new_point;
166  new_point.set_x1(my_points[l - 1].x1() - m_delta_t0);
167 
168  for (const MuonCalibSegment::MdtHitPtr& mdt_hit : seg.mdtHOT()) {
169  time = mdt_hit->driftTime() + new_point.x1();
170  sigma = mdt_hit->sigmaDriftRadius();
171  mdt_hit->setDriftRadius(rt->radius(time), sigma);
172  }
173 
174  if (!segment_fitter->fit(seg, r_selection)) {
175  failed = true;
176  return 0.0;
177  }
178  if (curved) {
179  new_point.set_x2(curved_track.chi2PerDegreesOfFreedom());
180  } else {
181  new_point.set_x2(straight_track.chi2PerDegreesOfFreedom());
182  }
183  new_point.set_error(1.0);
184  my_points.push_back(new_point);
185  }
186  }
187 
189  if (my_points[2].x1() > 0.0) {
190  for (unsigned int l = 3; my_points[l - 1].x2() <= my_points[l - 2].x2() && std::abs(my_points[l - 1].x1()) < 200.0; l++) {
191  SamplePoint new_point;
192  new_point.set_x1(my_points[l - 1].x1() + m_delta_t0);
193  for (const MuonCalibSegment::MdtHitPtr& mdt_hit : seg.mdtHOT()) {
194  time = mdt_hit->driftTime() + new_point.x1();
195  sigma = mdt_hit->sigmaDriftRadius();
196  mdt_hit->setDriftRadius(rt->radius(time), sigma);
197  }
198  if (!segment_fitter->fit(seg, r_selection)) {
199  failed = true;
200  return 0.0;
201  }
202  if (curved) {
203  new_point.set_x2(curved_track.chi2PerDegreesOfFreedom());
204  } else {
205  new_point.set_x2(straight_track.chi2PerDegreesOfFreedom());
206  }
207  new_point.set_error(1.0);
208  my_points.push_back(new_point);
209  }
210  }
212  // CALCULATE THE BEST t0 CORRECTION //
214 
215  fitter.fit_parameters(my_points, my_points.size() - 2, my_points.size(), pol);
216  double nom(fitter.coefficients()[1]);
217  double denom(fitter.coefficients()[2]);
218  delta_t0_opt = -0.5 * nom / denom;
219  error = std::sqrt(1.0 / denom);
220  if (std::isnan(error)) {
221  failed = true;
222  return 0.0;
223  }
224 
225  double direction{-0.5}, min_chi2{DBL_MAX};
226  double best_t0 = delta_t0_opt;
227  double current_t0 = delta_t0_opt;
228  std::vector<double> t0s, chi2, mchi2;
229  while (1) {
230  for (const MuonCalibSegment::MdtHitPtr& mdt_hit : seg.mdtHOT()) {
231  time = mdt_hit->driftTime() + current_t0;
232  sigma = mdt_hit->sigmaDriftRadius();
233  mdt_hit->setDriftRadius(rt->radius(time), sigma);
234  }
235  if (!segment_fitter->fit(seg, r_selection)) {
236  failed = true;
237  return 0.0;
238  }
239  double chisq(0.0);
240  if (curved) {
241  chisq = curved_track.chi2PerDegreesOfFreedom();
242  } else {
243  chisq = straight_track.chi2PerDegreesOfFreedom();
244  }
245 
246  if (chisq < min_chi2) {
247  min_chi2 = chisq;
248  best_t0 = current_t0;
249  } else {
250  if (direction > 0) break;
251  direction = 0.5;
252  current_t0 = delta_t0_opt;
253  }
254  current_t0 += direction;
255  t0s.push_back(current_t0);
256  chi2.push_back(chisq);
257  mchi2.push_back(min_chi2);
258  if (t0s.size() > 100) {
259  failed = true;
260  return 0.0;
261  }
262  }
263 
265  // OVERWRITE THE SEGMENT, IF REQUESTED //
267  delta_t0_opt = best_t0;
268  failed = false;
269  if (!overwrite) { return delta_t0_opt; }
270  bool segment_t0_was_applied{false};
271  for (const MuonCalibSegment::MdtHitPtr& mdt_hit : seg.mdtHOT()) {
272  segment_t0_was_applied |= mdt_hit->segmentT0Applied();
273  time = mdt_hit->driftTime() + delta_t0_opt;
274  sigma = mdt_hit->sigmaDriftRadius();
275  if (sigma > 10.0 && segment->mdtHOT()[k]->driftTime() < 50.0) sigma = 0.3;
276  mdt_hit->setDriftTime(time);
277  mdt_hit->setDriftRadius(rt->radius(time), sigma);
278  mdt_hit->setSegmentT0Applied(true);
279  }
280  if (segment_t0_was_applied) {
281  segment->setFittedT0(segment->fittedT0() - delta_t0_opt);
282  } else {
283  segment->setFittedT0(-delta_t0_opt);
284  }
285 
286  segment_fitter->SetRefineSegmentFlag(true);
287  if (segment_fitter->fit(*segment, r_selection) == 0.0) {
288  failed = true;
289  return 0.0;
290  }
291 
292  if (segment->chi2() > 100.0) {
293  failed = true;
294  return 0.0;
295  }
296 
297  return delta_t0_opt;
298 }
299 void T0Refinement::setTimeOut(const double time_out) {
300  m_time_out = time_out;
301  return;
302 }
303 void T0Refinement::setRoadWidth(const double road_width) {
304  m_qfitter->setRoadWidth(road_width);
305  m_cfitter->setRoadWidth(road_width);
306 
307  return;
308 }
MuonCalib::IMdtSegmentFitter::fit
virtual bool fit(MuonCalibSegment &seg) const =0
fit using all hits
LArSamples::FitterData::fitter
const ShapeFitter * fitter
Definition: ShapeFitter.cxx:23
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
pdg_comparison.sigma
sigma
Definition: pdg_comparison.py:324
IMdtSegmentFitter.h
make_unique
std::unique_ptr< T > make_unique(Args &&... args)
Definition: SkimmingToolEXOT5.cxx:23
TRTCalib_cfilter.t0s
list t0s
Definition: TRTCalib_cfilter.py:110
MuonCalib::NtupleStationId
Definition: NtupleStationId.h:36
plotBeamSpotCompare.x2
x2
Definition: plotBeamSpotCompare.py:218
MuonCalib::CurvedLine
Definition: CurvedLine.h:30
MuonCalib::MuonCalibSegment
Definition: MuonCalibSegment.h:39
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
MuonCalib::SamplePoint::set_error
void set_error(const double merror)
Definition: SamplePoint.h:63
NtupleStationId.h
MuonCalib::CurvedPatRec
Definition: CurvedPatRec.h:35
MuonCalib::T0Refinement::m_delta_t0
double m_delta_t0
Definition: T0Refinement.h:72
MuonCalib::SamplePoint::set_x2
void set_x2(const double mx2)
set the error of the x2 coordinate sample point to merror
Definition: SamplePoint.h:61
MuonCalib::MTStraightLine::chi2PerDegreesOfFreedom
double chi2PerDegreesOfFreedom() const
Return chi2 / number of TrackHits - 2.
Definition: MTStraightLine.cxx:139
MuonCalib::BaseFunctionFitter
Definition: BaseFunctionFitter.h:39
MuonCalib::SamplePoint::x1
double x1() const
< get the x1 coordinate of the sample point
Definition: SamplePoint.h:43
MuonCalib::T0Refinement::setTimeOut
void setTimeOut(const double time_out)
set the time-out for pattern finding to time_out (s)
Definition: T0Refinement.cxx:299
MuonCalib::T0Refinement::getDeltaT0
double getDeltaT0(MuonCalibSegment *segment, const IRtRelation *rt, bool overwrite, double &error, bool &failed, bool curved=false)
determine a t0 correction for the given segment; the algorithm choses the correction such that the ch...
Definition: T0Refinement.cxx:29
chi2
double chi2(TH1 *h0, TH1 *h1)
Definition: comparitor.cxx:522
MuonCalib
CscCalcPed - algorithm that finds the Cathode Strip Chamber pedestals from an RDO.
Definition: CscCalcPed.cxx:22
compute_lumi.denom
denom
Definition: compute_lumi.py:76
T0Refinement.h
MuonCalib::MuonCalibSegment::mdtHitsOnTrack
unsigned int mdtHitsOnTrack() const
retrieve the number of MdtCalibHitBase s assigned to this segment
Definition: MuonCalibSegment.cxx:146
BaseFunctionFitter.h
MuonCalib::SimplePolynomial
Definition: SimplePolynomial.h:13
PlotSFuncertainty.nom
nom
Definition: PlotSFuncertainty.py:141
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:220
MuonCalib::IRtRelation::radius
virtual double radius(double t) const =0
returns drift radius for a given time
MuonCalib::SamplePoint
Definition: SamplePoint.h:16
MuonCalib::SamplePoint::set_x1
void set_x1(const double mx1)
set the x2 coordinate of the sample point to mx2
Definition: SamplePoint.h:59
MuonCalib::CurvedLine::chi2PerDegreesOfFreedom
double chi2PerDegreesOfFreedom() const
Return chi2 / number of TrackHits - 3.
Definition: CurvedLine.cxx:186
SimplePolynomial.h
MuonCalib::T0Refinement::m_cfitter
std::unique_ptr< CurvedPatRec > m_cfitter
Definition: T0Refinement.h:71
MuonCalib::IMdtPatRecFitter
Definition: IMdtPatRecFitter.h:18
MuonCalib::IMdtPatRecFitter::SetRefineSegmentFlag
void SetRefineSegmentFlag(const bool flag)
number of hits selected for track
Definition: IMdtPatRecFitter.h:34
MuonCalib::MTStraightLine
Definition: MTStraightLine.h:16
MuonCalib::T0Refinement::setRoadWidth
void setRoadWidth(const double road_width)
set the road with to road_width (mm) (default: 1mm)
Definition: T0Refinement.cxx:303
MuonCalib::MuonCalibSegment::mdtHOT
const MdtHitVec & mdtHOT() const
retrieve the full set of MdtCalibHitBase s assigned to this segment
Definition: MuonCalibSegment.cxx:147
error
Definition: IImpactPoint3dEstimator.h:70
MuonCalib::T0Refinement::T0Refinement
T0Refinement()
Default constructor.
Definition: T0Refinement.cxx:16
MuonCalib::IRtRelation
generic interface for a rt-relation
Definition: IRtRelation.h:15
MuonCalib::StraightPatRec
Definition: StraightPatRec.h:24
MuonCalib::T0Refinement::m_qfitter
std::unique_ptr< StraightPatRec > m_qfitter
Definition: T0Refinement.h:70
MuonCalib::MuonCalibSegment::MdtHitPtr
std::shared_ptr< MdtCalibHitBase > MdtHitPtr
typedef for a collection of MdtCalibHitBase s
Definition: MuonCalibSegment.h:44
fitman.k
k
Definition: fitman.py:528
NSWL1::PadTriggerAdapter::segment
Muon::NSW_PadTriggerSegment segment(const NSWL1::PadTrigger &data)
Definition: PadTriggerAdapter.cxx:5
MuonCalib::IMdtSegmentFitter::HitSelection
std::vector< unsigned int > HitSelection
Definition: IMdtSegmentFitter.h:32
MuonCalib::T0Refinement::m_time_out
double m_time_out
Definition: T0Refinement.h:73