CMS 3D CMS Logo

MuonPathFitter.cc
Go to the documentation of this file.
2 #include <cmath>
3 #include <memory>
4 
5 using namespace edm;
6 using namespace std;
7 using namespace cmsdt;
8 
9 // ============================================================================
10 // Constructors and destructor
11 // ============================================================================
14  std::shared_ptr<GlobalCoordsObtainer> &globalcoordsobtainer)
15  : MuonPathAnalyzer(pset, iC), debug_(pset.getUntrackedParameter<bool>("debug")) {
16  if (debug_)
17  LogDebug("MuonPathFitter") << "MuonPathAnalyzer: constructor";
18 
19  //shift phi
20  int rawId;
21  shift_filename_ = pset.getParameter<edm::FileInPath>("shift_filename");
22  std::ifstream ifin3(shift_filename_.fullPath());
23  double shift;
24  if (ifin3.fail()) {
25  throw cms::Exception("Missing Input File")
26  << "MuonPathFitter::MuonPathFitter() - Cannot find " << shift_filename_.fullPath();
27  }
28  while (ifin3.good()) {
29  ifin3 >> rawId >> shift;
31  }
32 
33  int wh, st, se, maxdrift;
34  maxdrift_filename_ = pset.getParameter<edm::FileInPath>("maxdrift_filename");
35  std::ifstream ifind(maxdrift_filename_.fullPath());
36  if (ifind.fail()) {
37  throw cms::Exception("Missing Input File")
38  << "MPSLFilter::MPSLFilter() - Cannot find " << maxdrift_filename_.fullPath();
39  }
40  while (ifind.good()) {
41  ifind >> wh >> st >> se >> maxdrift;
42  maxdriftinfo_[wh][st][se] = maxdrift;
43  }
44 
46  globalcoordsobtainer_ = globalcoordsobtainer;
47 }
48 
50  if (debug_)
51  LogDebug("MuonPathFitter") << "MuonPathAnalyzer: destructor";
52 }
53 
54 // ============================================================================
55 // Main methods (initialise, run, finish)
56 // ============================================================================
57 
58 //------------------------------------------------------------------
59 //--- Metodos privados
60 //------------------------------------------------------------------
61 
63  int XI_WIDTH,
64  int COEFF_WIDTH_T0,
65  int COEFF_WIDTH_POSITION,
66  int COEFF_WIDTH_SLOPE,
67  int PRECISSION_T0,
68  int PRECISSION_POSITION,
69  int PRECISSION_SLOPE,
70  int PROD_RESIZE_T0,
71  int PROD_RESIZE_POSITION,
72  int PROD_RESIZE_SLOPE,
73  int MAX_DRIFT_TDC,
74  int sl) {
75  const int PARTIALS_PRECISSION = 4;
76  const int PARTIALS_SHR_T0 = PRECISSION_T0 - PARTIALS_PRECISSION;
77  const int PARTIALS_SHR_POSITION = PRECISSION_POSITION - PARTIALS_PRECISSION;
78  const int PARTIALS_SHR_SLOPE = PRECISSION_SLOPE - PARTIALS_PRECISSION;
79  const int PARTIALS_WIDTH_T0 = PROD_RESIZE_T0 - PARTIALS_SHR_T0;
80  const int PARTIALS_WIDTH_POSITION = PROD_RESIZE_POSITION - PARTIALS_SHR_POSITION;
81  const int PARTIALS_WIDTH_SLOPE = PROD_RESIZE_SLOPE - PARTIALS_SHR_SLOPE;
82 
83  const int WIDTH_TO_PREC = 11 + PARTIALS_PRECISSION;
84  const int WIDTH_SLOPE_PREC = 14 + PARTIALS_PRECISSION;
85  const int WIDTH_POSITION_PREC = WIDTH_SLOPE_PREC + 1;
86 
87  const int SEMICHAMBER_H_PRECISSION = 13 + PARTIALS_PRECISSION;
88  const float SEMICHAMBER_H_REAL = ((235. / 2.) / (16. * 6.5)) * std::pow(2, SEMICHAMBER_H_PRECISSION);
89  const int SEMICHAMBER_H = (int)SEMICHAMBER_H_REAL; // signed(SEMICHAMBER_H_WIDTH-1 downto 0)
90 
91  const int SEMICHAMBER_RES_SHR = SEMICHAMBER_H_PRECISSION;
92 
93  const int LYRANDAHALF_RES_SHR = 4;
94 
95  const int CHI2_CALC_RES_BITS = 7;
96 
97  /*******************************
98  clock cycle 1
99  *******************************/
100  std::vector<int> normalized_times;
101  std::vector<int> normalized_wirepos;
102 
103  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
104  // normalized times
105  // this should be resized to an unsigned of 10 bits (max drift time ~508 TDC counts, using 9+1 to include tolerance)
106  // leaving it as an integer for now
107  // we are obtaining the difference as the difference in BX + the LS bits from the hit time
108 
109  if (fit_common_in.hits_valid[i] == 1) {
110  int dif_bx = (fit_common_in.hits[i].ti >> (WIDTH_FULL_TIME - WIDTH_COARSED_TIME)) - fit_common_in.coarse_bctr;
111 
112  int tmp_norm_time = (dif_bx << (WIDTH_FULL_TIME - WIDTH_COARSED_TIME)) +
113  (fit_common_in.hits[i].ti % (int)std::pow(2, WIDTH_FULL_TIME - WIDTH_COARSED_TIME));
114  // resize test
115  // this has implications in the FW (reducing number of bits).
116  // we keep here the int as it is, but we do the same check done in the fw
117  std::vector<int> tmp_dif_bx_vector;
118  vhdl_int_to_unsigned(dif_bx, tmp_dif_bx_vector);
119  vhdl_resize_unsigned(tmp_dif_bx_vector, 12);
120  if (!vhdl_resize_unsigned_ok(tmp_dif_bx_vector, WIDTH_DIFBX))
121  return fit_common_out_t();
122 
123  normalized_times.push_back(tmp_norm_time);
124  int tmp_wirepos = fit_common_in.hits[i].wp - (fit_common_in.coarse_wirepos << WIREPOS_NORM_LSB_IGNORED);
125  // resize test
126  std::vector<int> tmp_wirepos_vector;
127  vhdl_int_to_signed(tmp_wirepos, tmp_wirepos_vector);
128  vhdl_resize_signed(tmp_wirepos_vector, WIREPOS_WIDTH);
129  if (!vhdl_resize_signed_ok(tmp_wirepos_vector, XI_WIDTH))
130  return fit_common_out_t();
131 
132  normalized_wirepos.push_back(tmp_wirepos);
133  } else { // dummy hit
134  normalized_times.push_back(-1);
135  normalized_wirepos.push_back(-1);
136  }
137  }
138 
139  /*******************************
140  clock cycle 2
141  *******************************/
142 
143  std::vector<int> xi_arr;
144  // min and max times are computed throught several clk cycles in the fw,
145  // here we compute it at once
146  int min_hit_time = 999999, max_hit_time = 0;
147  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
148  if (fit_common_in.hits_valid[i] == 1) {
149  // calculate xi array
150  auto tmp_xi_incr = normalized_wirepos[i];
151  tmp_xi_incr += (-1 + 2 * fit_common_in.lateralities[i]) * normalized_times[i];
152 
153  // resize test
154  std::vector<int> tmp_xi_incr_vector;
155  vhdl_int_to_signed(tmp_xi_incr, tmp_xi_incr_vector);
156  vhdl_resize_signed(tmp_xi_incr_vector, XI_WIDTH + 1);
157  if (!vhdl_resize_signed_ok(tmp_xi_incr_vector, XI_WIDTH))
158  return fit_common_out_t();
159  xi_arr.push_back(tmp_xi_incr);
160 
161  // calculate min and max times
162  if (normalized_times[i] < min_hit_time) {
163  min_hit_time = normalized_times[i];
164  }
165  if (normalized_times[i] > max_hit_time) {
166  max_hit_time = normalized_times[i];
167  }
168  } else {
169  xi_arr.push_back(-1);
170  }
171  }
172 
173  /*******************************
174  clock cycle 3
175  *******************************/
176 
177  std::vector<int> products_t0;
178  std::vector<int> products_position;
179  std::vector<int> products_slope;
180  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
181  if (fit_common_in.hits_valid[i] == 0) {
182  products_t0.push_back(-1);
183  products_position.push_back(-1);
184  products_slope.push_back(-1);
185  } else {
186  products_t0.push_back(xi_arr[i] * vhdl_signed_to_int(fit_common_in.coeffs.t0[i]));
187  products_position.push_back(xi_arr[i] * vhdl_signed_to_int(fit_common_in.coeffs.position[i]));
188  products_slope.push_back(xi_arr[i] * vhdl_signed_to_int(fit_common_in.coeffs.slope[i]));
189  }
190  }
191 
192  /*******************************
193  clock cycle 4
194  *******************************/
195  // Do the 8 element sums
196  int t0_prec = 0, position_prec = 0, slope_prec = 0;
197  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
198  if (fit_common_in.hits_valid[i] == 0) {
199  continue;
200  } else {
201  t0_prec += products_t0[i] >> PARTIALS_SHR_T0;
202  position_prec += products_position[i] >> PARTIALS_SHR_POSITION;
203  slope_prec += products_slope[i] >> PARTIALS_SHR_SLOPE;
204  }
205  }
206 
207  /*******************************
208  clock cycle 5
209  *******************************/
210  // Do resize tests for the computed sums with full precision
211  std::vector<int> t0_prec_vector, position_prec_vector, slope_prec_vector;
212  vhdl_int_to_signed(t0_prec, t0_prec_vector);
213 
214  vhdl_resize_signed(t0_prec_vector, PARTIALS_WIDTH_T0);
215  if (!vhdl_resize_signed_ok(t0_prec_vector, WIDTH_TO_PREC))
216  return fit_common_out_t();
217 
218  vhdl_int_to_signed(position_prec, position_prec_vector);
219  vhdl_resize_signed(position_prec_vector, PARTIALS_WIDTH_POSITION);
220  if (!vhdl_resize_signed_ok(position_prec_vector, WIDTH_POSITION_PREC))
221  return fit_common_out_t();
222 
223  vhdl_int_to_signed(slope_prec, slope_prec_vector);
224  vhdl_resize_signed(slope_prec_vector, PARTIALS_WIDTH_SLOPE);
225  if (!vhdl_resize_signed_ok(slope_prec_vector, WIDTH_SLOPE_PREC))
226  return fit_common_out_t();
227 
228  /*******************************
229  clock cycle 6
230  *******************************/
231  // Round the fitting parameters to the final resolution;
232  // in vhdl something more sofisticated is done, here we do a float division, round
233  // and cast again to integer
234 
235  int norm_t0 = ((t0_prec >> (PARTIALS_PRECISSION - 1)) + 1) >> 1;
236  int norm_position = ((position_prec >> (PARTIALS_PRECISSION - 1)) + 1) >> 1;
237  int norm_slope = ((slope_prec >> (PARTIALS_PRECISSION - 1)) + 1) >> 1;
238 
239  // Calculate the (-xi) + pos (+/-) t0, which only is lacking the slope term to become the residuals
240  std::vector<int> res_partials_arr;
241  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
242  if (fit_common_in.hits_valid[i] == 0) {
243  res_partials_arr.push_back(-1);
244  } else {
245  int tmp_position_prec = position_prec - (xi_arr[i] << PARTIALS_PRECISSION);
246  // rounding
247  tmp_position_prec += std::pow(2, PARTIALS_PRECISSION - 1);
248 
249  tmp_position_prec += (-1 + 2 * fit_common_in.lateralities[i]) * t0_prec;
250  res_partials_arr.push_back(tmp_position_prec);
251  }
252  }
253 
254  // calculate the { slope x semichamber, slope x 1.5 layers, slope x 0.5 layers }
255  // these 3 values are later combined with different signs to get the slope part
256  // of the residual for each of the layers.
257  int slope_x_halfchamb = (((long int)slope_prec * (long int)SEMICHAMBER_H)) >> SEMICHAMBER_RES_SHR;
258  if (sl == 2)
259  slope_x_halfchamb = 0;
260  int slope_x_3semicells = (slope_prec * 3) >> LYRANDAHALF_RES_SHR;
261  int slope_x_1semicell = (slope_prec * 1) >> LYRANDAHALF_RES_SHR;
262 
263  /*******************************
264  clock cycle 7
265  *******************************/
266  // Complete the residuals calculation by constructing the slope term (1/2)
267  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
268  if (fit_common_in.hits_valid[i] == 1) {
269  if (i % 4 == 0)
270  res_partials_arr[i] -= slope_x_3semicells;
271  else if (i % 4 == 1)
272  res_partials_arr[i] -= slope_x_1semicell;
273  else if (i % 4 == 2)
274  res_partials_arr[i] += slope_x_1semicell;
275  else
276  res_partials_arr[i] += slope_x_3semicells;
277  }
278  }
279 
280  /*******************************
281  clock cycle 8
282  *******************************/
283  // Complete the residuals calculation by constructing the slope term (2/2)
284  std::vector<int> residuals, position_prec_arr;
285  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
286  if (fit_common_in.hits_valid[i] == 0) {
287  residuals.push_back(-1);
288  position_prec_arr.push_back(-1);
289  } else {
290  int tmp_position_prec = res_partials_arr[i];
291  tmp_position_prec += (-1 + 2 * (int)(i >= NUM_LAYERS)) * slope_x_halfchamb;
292  position_prec_arr.push_back(tmp_position_prec);
293  residuals.push_back(abs(tmp_position_prec >> PARTIALS_PRECISSION));
294  }
295  }
296 
297  // minimum and maximum fit t0
298  int min_t0 = max_hit_time - MAX_DRIFT_TDC - T0_CUT_TOLERANCE;
299  int max_t0 = min_hit_time + T0_CUT_TOLERANCE;
300 
301  /*******************************
302  clock cycle 9
303  *******************************/
304  // Prepare addition of coarse_offset to T0 (T0 de-normalization)
305  int t0_fine = norm_t0 & (int)(std::pow(2, 5) - 1);
306  int t0_bx_sign = ((int)(norm_t0 < 0)) * 1;
307  int t0_bx_abs = abs(norm_t0 >> 5);
308 
309  // De-normalize Position and slope
310  int position = (fit_common_in.coarse_wirepos << WIREPOS_NORM_LSB_IGNORED) + norm_position;
311  int slope = norm_slope;
312 
313  // Apply T0 cuts
314  if (norm_t0 < min_t0)
315  return fit_common_out_t();
316  if (norm_t0 > max_t0)
317  return fit_common_out_t();
318 
319  // square the residuals
320  std::vector<int> squared_residuals;
321  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
322  if (fit_common_in.hits_valid[i] == 0) {
323  squared_residuals.push_back(-1);
324  } else {
325  squared_residuals.push_back(residuals[i] * residuals[i]);
326  }
327  }
328 
329  // check for residuals overflow
330  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
331  if (fit_common_in.hits_valid[i] == 1) {
332  std::vector<int> tmp_vector;
333  int tmp_position_prec = (position_prec_arr[i] >> PARTIALS_PRECISSION);
334  vhdl_int_to_signed(tmp_position_prec, tmp_vector);
335  vhdl_resize_signed(tmp_vector, WIDTH_POSITION_PREC);
336  if (!vhdl_resize_signed_ok(tmp_vector, CHI2_CALC_RES_BITS + 1))
337  return fit_common_out_t();
338  // Commented for now, maybe later we need to do something here
339  // if ((tmp_position_prec / (int) std::pow(2, CHI2_CALC_RES_BITS)) > 0)
340  // return fit_common_out_t();
341  }
342  }
343 
344  /*******************************
345  clock cycle 10, 11, 12
346  *******************************/
347  int t0 = t0_fine;
348  t0 += (fit_common_in.coarse_bctr - (-1 + 2 * t0_bx_sign) * t0_bx_abs) * (int)std::pow(2, 5);
349 
350  int chi2 = 0;
351  for (int i = 0; i < 2 * NUM_LAYERS; i++) {
352  if (fit_common_in.hits_valid[i] == 1) {
353  chi2 += squared_residuals[i];
354  }
355  }
356 
357  // Impose the thresholds
358 
359  if (chi2 / 16 >= (int)round(chi2Th_ * (std::pow((float)MAX_DRIFT_TDC / ((float)CELL_SEMILENGTH / 10.), 2)) / 16.))
360  return fit_common_out_t();
361 
362  fit_common_out_t fit_common_out;
363  fit_common_out.position = position;
364  fit_common_out.slope = slope;
365  fit_common_out.t0 = t0;
366  fit_common_out.chi2 = chi2;
367  fit_common_out.valid_fit = 1;
368 
369  return fit_common_out;
370 }
371 
373  short COEFF_WIDTH_T0,
374  short COEFF_WIDTH_POSITION,
375  short COEFF_WIDTH_SLOPE,
376  short LOLY,
377  short HILY) {
378  coeffs_t res;
379  int ctr = 0;
380  for (int i = LOLY; i <= HILY; i++) {
381  res.t0[i] = vhdl_slice(slv, COEFF_WIDTH_T0 + ctr - 1, ctr);
383  res.t0[i] = vhdl_slice(res.t0[i], COEFF_WIDTH_T0 - 1, 0);
384  ctr += COEFF_WIDTH_T0;
385  }
386  for (int i = LOLY; i <= HILY; i++) {
387  res.position[i] = vhdl_slice(slv, COEFF_WIDTH_POSITION + ctr - 1, ctr);
389  res.position[i] = vhdl_slice(res.position[i], COEFF_WIDTH_POSITION - 1, 0);
390  ctr += COEFF_WIDTH_POSITION;
391  }
392  for (int i = LOLY; i <= HILY; i++) {
393  res.slope[i] = vhdl_slice(slv, COEFF_WIDTH_SLOPE + ctr - 1, ctr);
395  res.slope[i] = vhdl_slice(res.slope[i], COEFF_WIDTH_SLOPE - 1, 0);
396  ctr += COEFF_WIDTH_SLOPE;
397  }
398  return res;
399 }
int maxdriftinfo_[5][4][14]
std::vector< int > lateralities
std::vector< SLhitP > hits
edm::FileInPath maxdrift_filename_
edm::ESGetToken< DTGeometry, MuonGeometryRecord > dtGeomH
void vhdl_int_to_signed(int value, std::vector< int > &v)
static const double slope[3]
int vhdl_signed_to_int(std::vector< int > v)
bool vhdl_resize_signed_ok(std::vector< int > v, int new_size)
std::vector< int > vhdl_slice(std::vector< int > v, int upper, int lower)
constexpr int WIDTH_COARSED_TIME
Definition: constants.h:252
constexpr int WIREPOS_WIDTH
Definition: constants.h:257
constexpr int T0_CUT_TOLERANCE
Definition: constants.h:291
std::map< int, float > shiftinfo_
Definition: Electron.h:6
constexpr int CELL_SEMILENGTH
Definition: constants.h:314
void vhdl_resize_unsigned(std::vector< int > &v, int new_size)
void vhdl_resize_signed(std::vector< int > &v, int new_size)
coeff_arr_t slope
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
constexpr int WIDTH_FULL_TIME
Definition: constants.h:251
MuonPathFitter(const edm::ParameterSet &pset, edm::ConsumesCollector &iC, std::shared_ptr< GlobalCoordsObtainer > &globalcoordsobtainer)
edm::FileInPath shift_filename_
std::shared_ptr< GlobalCoordsObtainer > globalcoordsobtainer_
coeffs_t RomDataConvert(std::vector< int > slv, short COEFF_WIDTH_T0, short COEFF_WIDTH_POSITION, short COEFF_WIDTH_SLOPE, short LOLY, short HILY)
constexpr int GENERIC_COEFF_WIDTH
Definition: constants.h:250
constexpr int WIDTH_DIFBX
Definition: constants.h:253
void vhdl_int_to_unsigned(int value, std::vector< int > &v)
bool vhdl_resize_unsigned_ok(std::vector< int > v, int new_size)
HLT enums.
static int position[264][3]
Definition: ReadPGInfo.cc:289
coeff_arr_t t0
static unsigned int const shift
constexpr int WIREPOS_NORM_LSB_IGNORED
Definition: constants.h:258
const std::string & fullPath() const
Definition: FileInPath.cc:144
~MuonPathFitter() override
coeff_arr_t position
const bool debug_
fit_common_out_t fit(fit_common_in_t fit_common_in, int XI_WIDTH, int COEFF_WIDTH_T0, int COEFF_WIDTH_POSITION, int COEFF_WIDTH_SLOPE, int PRECISSION_T0, int PRECISSION_POSITION, int PRECISSION_SLOPE, int PROD_RESIZE_T0, int PROD_RESIZE_POSITION, int PROD_RESIZE_SLOPE, int MAX_DRIFT_TDC, int sl)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
std::vector< int > hits_valid
#define LogDebug(id)