ATLAS Offline Software
Loading...
Searching...
No Matches
AdaptiveResidualSmoothing.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <TString.h> // for Form
8
9#include <algorithm>
10#include <fstream>
11#include <iostream>
12
14#include "CLHEP/Matrix/Vector.h"
15#include "GaudiKernel/MsgStream.h"
21#include "TSpline.h"
22using namespace CLHEP;
23using namespace MuonCalib;
24
27void AdaptiveResidualSmoothing::addResidual(const double radius, const double residual) {
28 // make the data point //
29 CLHEP::HepVector point(2);
30 point[0] = radius;
31 point[1] = residual;
32 DataPoint residual_point(point, 0);
33
34 // store the data point //
35 m_residual_point.push_back(residual_point);
36
37 return;
38}
39bool AdaptiveResidualSmoothing::addResidualsFromSegment(MuonCalibSegment &seg, bool curved, double road_width) {
41 // VARIABLES //
43
44 CLHEP::HepVector point(2); // auxiliary point
45 IMdtPatRecFitter *fitter = nullptr;
46
48 // RESIDUAL DETERMINATION AND STORAGE //
50
51 // perform fit //
52 if (curved) {
53 // set road width /
54 m_cfitter.setRoadWidth(road_width);
55
56 // set fitter pointer //
57 fitter = &m_cfitter;
58
59 } else {
60 // set road width /
61 m_sfitter.setRoadWidth(road_width);
62
63 // set fitter pointer //
64 fitter = &m_sfitter;
65 }
66
67 fitter->SetRefineSegmentFlag(false);
68
69 CurvedLine curved_track;
70 MTStraightLine straight_track;
72
73 // perform the track fit; return in case of failure //
74
75 // reject bad fits //
76 if (curved) {
77 if (!m_cfitter.fit(seg, selection, curved_track)) return false;
78 if (curved_track.chi2PerDegreesOfFreedom() > 50) { return false; }
79 } else {
80 if (!m_sfitter.fit(seg, selection, straight_track)) return false;
81 if (straight_track.chi2PerDegreesOfFreedom() > 50) { return false; }
82 }
83
84 // store the residuals //
85 const MuonCalibSegment::MdtHitVec &trackHits = curved ? curved_track.trackHits() : straight_track.trackHits();
86 for (const auto & trackHit : trackHits) {
87 point[0] = trackHit->driftRadius();
88 point[1] = trackHit->driftRadius() - std::abs(trackHit->signedDistanceToTrack());
89 m_residual_point.emplace_back(point, 0);
90 }
91
92 return true;
93}
94
95RtRelationLookUp AdaptiveResidualSmoothing::performSmoothing(const IRtRelation &rt_rel, unsigned int nb_entries_per_bin, bool fix_t_min,
96 bool fix_t_max) {
98 // VARIABLES //
100
102 std::vector<unsigned int> ref_coord(1);
103
105 // CHECKS //
107
108 if (m_residual_point.size() == 0) {
109 throw std::runtime_error(
110 Form("File: %s, Line: %d\nAdaptiveResidualSmoothing::performSmoothing - No residuals stored.", __FILE__, __LINE__));
111 }
112
113 if (m_residual_point.size() < nb_entries_per_bin) {
114 throw std::runtime_error(
115 Form("File: %s, Line: %d\nAdaptiveResidualSmoothing::performSmoothing - Not enough residuals stored.", __FILE__, __LINE__));
116 }
117
119 // PERFORM BINNING //
121
122 ref_coord[0] = 0;
123 bin_maker.binDataPoints(nb_entries_per_bin, ref_coord);
124
126 // DETERMINE r-t COORECTION //
128
129 // get a polygon through the bin centres //
130 std::vector<double> rad(bin_maker.getBins().size());
131 std::vector<SamplePoint> corr(bin_maker.getBins().size());
132 for (unsigned int k = 0; k < bin_maker.getBins().size(); k++) {
133 rad[k] = (bin_maker.getBins()[k])->centreOfGravity()[0];
134 corr[k].set_x1(rad[k]);
135 corr[k].set_x2((bin_maker.getBins()[k])->centreOfGravity()[1]);
136 corr[k].set_error(1.0);
137 }
138 std::sort(rad.begin(), rad.end());
139
140 std::vector<double> radi;
141 radi.push_back(rad[0]);
142 unsigned int counter(0);
143 for (unsigned int k = 1; k < rad.size(); k++) {
144 if (rad[counter] < rad[k]) {
145 radi.push_back(rad[k]);
146 counter++;
147 }
148 }
149
150 PolygonBase polygon(radi);
151 BaseFunctionFitter fitter(bin_maker.getBins().size());
152 fitter.fit_parameters(corr, 1, corr.size(), polygon);
153
154 // create an improved r-t relationship //
155 std::vector<double> rt_params;
156 rt_params.push_back(rt_rel.tLower());
157 rt_params.push_back(0.01 * (rt_rel.tUpper() - rt_rel.tLower()));
158 // ofstream outfile("out2.txt");
159 for (double t = rt_rel.tLower(); t <= rt_rel.tUpper(); t = t + rt_params[1]) {
160 double delta_r(0.0);
161 for (unsigned int l = 0; l < radi.size(); l++) {
162 delta_r = delta_r + fitter.coefficients()[l] * polygon.value(l, rt_rel.radius(t));
163 }
164 if (fix_t_min && (rt_rel.radius(t) < 0.5)) { delta_r = 0.0; }
165 if (fix_t_max && (rt_rel.radius(t) > 14.1)) { delta_r = 0.0; }
166 rt_params.push_back(rt_rel.radius(t) - delta_r);
167 }
168
169 RtRelationLookUp improved_rt(rt_params);
170 // for (double t=rt_rel.tLower(); t<=rt_rel.tUpper(); t=t+rt_params[1]) {
171 // outfile << rt_rel.radius(t) << "\t" << improved_rt.radius(t)
172 // << "\t" << endl;
173 // }
174
175 return improved_rt;
176}
177
178RtRelationLookUp AdaptiveResidualSmoothing::performSmoothing(const IRtRelation &rt_rel, const bool &fix_t_min, const bool &fix_t_max) {
180 // VARIABLES //
182
183 unsigned int nb_bins; // number of bins in r
184 unsigned int min_nb_entries_per_bin(20); // minimum number of
185 // entries per bin
186 double step_size; // real step size [mm]
187 double r_max(16.0); // maximum drift radius
188 double aux_rad; // auxiliary radius
189 double aux_corr; // auxiliary correction value
190 unsigned int bin_index;
191
193 // DETERMINE THE NUMBER OF BINS //
195
196 // take the sqrt from the number of residuals to determine the binsize.
197 // for low stat, a larger statistical error on the bins is allowed
198 // for example:
199 // 1000 segments -> 7.6% and 35 bins
200 // 5000 segments -> 5.1% and 64 bins
201 // 10000 segments-> 4.1% and 91 bins
202 nb_bins = static_cast<unsigned int>(std::sqrt(m_residual_point.size() / 6.));
203
204 // calculate min_nb_per_bin
205 if (nb_bins == 0) { nb_bins = 1; }
206 min_nb_entries_per_bin = m_residual_point.size() / nb_bins;
207
209 // RETURN IF THERE ARE NO RESIDUALS //
211
212 if (m_residual_point.size() == 0) {
213 MsgStream log(Athena::getMessageSvc(), "AdaptiveResidualSmoothing");
214 log << MSG::WARNING << "performSmoothing() - No residuals are stored. no correction applied to r(t)!" << endmsg;
215 }
216
217 step_size = r_max / static_cast<double>(nb_bins);
218
220 // DETERMINE THE AVERAGE RESIDUAL VALUES IN THE RADIAL BINS //
222
223 // vector for the correction function //
224 std::vector<SamplePoint> corr(nb_bins);
225 std::vector<double> radii(nb_bins);
226
227 // sort the residuals point in the residual value for a simple outlyer //
228 // rejection performed later //
229 for (auto & k : m_residual_point) { k.setReferenceComponent(1); }
230 sort(m_residual_point.begin(), m_residual_point.end());
231
232 // auxiliary data point arrays //
233 std::vector<std::vector<const DataPoint *> > sample_points_per_r_bin(nb_bins);
234
235 // group data points in r bins //
236 for (auto & k : m_residual_point) {
237 if (std::abs(k.dataVector()[0]) >= r_max) { continue; }
238 bin_index = static_cast<unsigned int>(std::abs(k.dataVector()[0]) / step_size);
239 sample_points_per_r_bin[bin_index].push_back(&k);
240 }
241
242 // loop over the r bins and determine the r-t corrections //
243 // static ofstream outfile("tmp.txt");
244 // outfile << endl;
245 for (unsigned int bin = 0; bin < nb_bins; bin++) {
246 aux_rad = 0.0;
247 aux_corr = 0.0;
248
249 // remove the first and last 1% of the residuals as simple outlyer removal //
250 unsigned int k_min(static_cast<unsigned int>(0.01 * sample_points_per_r_bin[bin].size()));
251 unsigned int k_max(static_cast<unsigned int>(0.99 * sample_points_per_r_bin[bin].size()));
252 // outfile << bin << "\t" << (0.5+bin)*step_size << "\t"
253 // << k_min << "\t" << k_max << endl;
254
255 // loop over residuals in a bin
256 for (unsigned int k = k_min; k < k_max; k++) {
257 aux_rad = aux_rad + sample_points_per_r_bin[bin][k]->dataVector()[0];
258 aux_corr = aux_corr + sample_points_per_r_bin[bin][k]->dataVector()[1];
259 }
260 if (k_max - k_min < 0.25 * min_nb_entries_per_bin) {
261 radii[bin] = (0.5 + bin) * step_size;
262 corr[bin] = SamplePoint(radii[bin], 0.0, 1.0);
263 } else {
264 radii[bin] = aux_rad / static_cast<double>(k_max - k_min);
265 corr[bin] = SamplePoint(radii[bin], aux_corr / static_cast<double>(k_max - k_min), 1.0);
266 }
267 }
268
269 // correction polygon //
270 PolygonBase polygon(radii);
271 BaseFunctionFitter fitter(nb_bins);
272 fitter.fit_parameters(corr, 1, corr.size(), polygon);
273
274 // create output r-t relationship //
275 std::vector<double> rt_params;
276 rt_params.push_back(rt_rel.tLower());
277 rt_params.push_back(0.01 * (rt_rel.tUpper() - rt_rel.tLower()));
278 // ofstream outfile("out2.txt");
279 for (double t = rt_rel.tLower(); t <= rt_rel.tUpper(); t = t + rt_params[1]) {
280 double delta_r(0.0);
281 for (unsigned int l = 0; l < radii.size(); l++) {
282 delta_r = delta_r + fitter.coefficients()[l] * polygon.value(l, rt_rel.radius(t));
283 }
284 if (rt_rel.radius(t) > r_max) { delta_r = 0.0; }
285 if (fix_t_min && (rt_rel.radius(t) < 0.5)) { delta_r = 0.0; }
286 if (fix_t_max && (rt_rel.radius(t) > 14.1)) { delta_r = 0.0; }
287 rt_params.push_back(rt_rel.radius(t) - delta_r);
288 }
289
290 RtRelationLookUp improved_rt(rt_params);
291 // for (double t=rt_rel.tLower(); t<=rt_rel.tUpper(); t=t+rt_params[1]) {
292 // outfile << rt_rel.radius(t) << "\t" << improved_rt.radius(t)
293 // << "\t" << endl;
294 // }
295
296 return improved_rt;
297}
298double AdaptiveResidualSmoothing::t_from_r(const IRtRelation &rt_rel, const double r) {
300 // VARIABLES //
302
303 double precision(0.001); // spatial precision of the inversion
304 double t_max(rt_rel.tUpper()); // upper time search limit
305 double t_min(rt_rel.tLower()); // lower time search limit
306
308 // SEARCH FOR THE CORRESPONDING DRIFT TIME //
310
311 while (t_max - t_min > 0.1 && std::abs(rt_rel.radius(0.5 * (t_min + t_max)) - r) > precision) {
312 if (rt_rel.radius(0.5 * (t_min + t_max)) > r) {
313 t_max = 0.5 * (t_min + t_max);
314 } else {
315 t_min = 0.5 * (t_min + t_max);
316 }
317 }
318
319 return 0.5 * (t_min + t_max);
320}
#define endmsg
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
bool addResidualsFromSegment(MuonCalibSegment &seg, bool curved, double road_width)
reconstruct the given segment and store the residuals; if curved is true a curved segment fit is perf...
void clear()
clear the memory of the class
void addResidual(const double radius, const double residual)
add the residual at the given radius
RtRelationLookUp performSmoothing(const IRtRelation &rt_rel, unsigned int nb_entries_per_bin, bool fix_t_min, bool fix_t_max)
use the stored residuals to improve the given r-t relationship to give smoother residuals; the user h...
double t_from_r(const IRtRelation &rt_rel, const double r)
This class performs a fit of a linear combination of base functions to a set of sample points.
const std::vector< DataBin * > & getBins() const
get the bins determined by the method "binDataPoints"
bool binDataPoints(const unsigned int &bin_content, std::vector< unsigned int > &ref_coord)
group the data points into bins of equal content "bin_content"; returns true in case of success,...
double chi2PerDegreesOfFreedom() const
Return chi2 / number of TrackHits - 3.
const MdtHitVec & trackHits() const
Interface class for MdtSegment fitters performing a pattern recognition.
std::vector< unsigned int > HitSelection
generic interface for a rt-relation
Definition IRtRelation.h:19
virtual double tLower() const =0
Returns the lower time covered by the r-t.
virtual double radius(double t) const =0
returns drift radius for a given time
virtual double tUpper() const =0
Returns the upper time covered by the r-t.
const MdtHitVec & trackHits() const
double chi2PerDegreesOfFreedom() const
Return chi2 / number of TrackHits - 2.
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
std::vector< MdtHitPtr > MdtHitVec
This class provides functions which allow the user to express a polygon as a linear combination of th...
Definition PolygonBase.h:42
double value(const int k, const double x) const
get the value of the k-th base function at x
Equidistant look up table for rt-relations with the time as key.
This class provides a sample point for the BaseFunctionFitter.
Definition SamplePoint.h:15
const std::string selection
singleton-like access to IMessageSvc via open function and helper
int r
Definition globals.cxx:22
IMessageSvc * getMessageSvc(bool quiet=false)
CscCalcPed - algorithm that finds the Cathode Strip Chamber pedestals from an RDO.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.