CMS 3D CMS Logo

PPSAlignmentHarvester.cc
Go to the documentation of this file.
1 /****************************************************************************
2 * Authors:
3 * Jan Kašpar (jan.kaspar@gmail.com)
4 * Mateusz Kocot (mateuszkocot99@gmail.com)
5 ****************************************************************************/
6 
10 
16 
18 
20 
24 
27 
29 
30 #include <memory>
31 #include <map>
32 #include <vector>
33 #include <string>
34 #include <fstream>
35 #include <iomanip>
36 #include <cmath>
37 #include <utility>
38 #include <algorithm>
39 
40 #include "TH1D.h"
41 #include "TH2D.h"
42 #include "TGraph.h"
43 #include "TGraphErrors.h"
44 #include "TF1.h"
45 #include "TProfile.h"
46 #include "TFile.h"
47 #include "TKey.h"
48 #include "TSpline.h"
49 #include "TCanvas.h"
50 
51 //----------------------------------------------------------------------------------------------------
52 
54 public:
56  ~PPSAlignmentHarvester() override;
57 
58  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
59 
60 private:
61  void dqmEndJob(DQMStore::IBooker& iBooker, DQMStore::IGetter& iGetter) override;
62  void dqmEndRun(DQMStore::IBooker& iBooker,
63  DQMStore::IGetter& iGetter,
64  edm::Run const& iRun,
65  edm::EventSetup const& iSetup) override;
66 
67  // ------------ x alignment ------------
68  std::unique_ptr<TGraphErrors> buildGraphFromVector(const std::vector<PPSAlignmentConfiguration::PointErrors>& pv);
69  std::unique_ptr<TGraphErrors> buildGraphFromMonitorElements(DQMStore::IGetter& iGetter,
71  const std::vector<MonitorElement*>& mes,
72  const unsigned int fitProfileMinBinEntries,
73  const unsigned int fitProfileMinNReasonable);
74  void doMatch(DQMStore::IBooker& iBooker,
77  TGraphErrors* g_ref,
78  TGraphErrors* g_test,
80  const double sh_min,
81  const double sh_max,
82  double& sh_best,
83  double& sh_best_unc);
84 
85  void xAlignment(DQMStore::IBooker& iBooker,
86  DQMStore::IGetter& iGetter,
88  const PPSAlignmentConfiguration& cfg_ref);
89 
90  std::map<unsigned int, double> sh_x_map_;
91 
92  // ------------ x alignment relative ------------
94 
95  // ------------ y alignment ------------
96  static double findMax(const TF1* ff_fit);
97  TH1D* buildModeGraph(DQMStore::IBooker& iBooker,
98  const MonitorElement* h2_y_vs_x,
101 
103 
104  // ------------ other member data and methods ------------
105  static void writeCutPlot(
106  TH2D* h, const double a, const double c, const double si, const double n_si, const std::string& label);
107  static std::unique_ptr<TH1D> getTH1DFromTGraphErrors(TGraphErrors* graph,
108  const std::string& title = "",
109  const std::string& labels = "",
110  int n = -1,
111  double binWidth = -1.,
112  double min = -1.);
113 
115 
118 
119  // variables from parameters
121  const std::vector<std::string> sequence_;
122  const bool overwriteShX_;
126  const std::pair<double, double> xCorrRange_;
127  const std::pair<double, double> yCorrRange_;
128  const unsigned int detectorId_;
129  const unsigned int subdetectorId_;
130  const bool debug_;
131 
132  // other class variables
133  std::unique_ptr<TFile> debugFile_;
134  std::ofstream textResultsFile_;
135  int seqPos = 1; // position in sequence_
136 
138 
141 
144 };
145 
146 // -------------------------------- DQMEDHarvester methods --------------------------------
147 
150  edm::ESInputTag("", ""))),
152  edm::ESInputTag("", "reference"))),
153  dqmDir_(iConfig.getParameter<std::string>("dqm_dir")),
154  sequence_(iConfig.getParameter<std::vector<std::string>>("sequence")),
155  overwriteShX_(iConfig.getParameter<bool>("overwrite_sh_x")),
156  writeSQLiteResults_(iConfig.getParameter<bool>("write_sqlite_results")),
157  xAliRelFinalSlopeFixed_(iConfig.getParameter<bool>("x_ali_rel_final_slope_fixed")),
158  yAliFinalSlopeFixed_(iConfig.getParameter<bool>("y_ali_final_slope_fixed")),
159  xCorrRange_(std::make_pair(iConfig.getParameter<double>("x_corr_min") / 1000.,
160  iConfig.getParameter<double>("x_corr_max") / 1000.)), // um -> mm
161  yCorrRange_(std::make_pair(iConfig.getParameter<double>("y_corr_min") / 1000.,
162  iConfig.getParameter<double>("y_corr_max") / 1000.)), // um -> mm
163  detectorId_(iConfig.getParameter<unsigned int>("detector_id")),
164  subdetectorId_(iConfig.getParameter<unsigned int>("subdetector_id")),
165  debug_(iConfig.getParameter<bool>("debug")) {
166  auto textResultsPath = iConfig.getParameter<std::string>("text_results_path");
167  if (!textResultsPath.empty()) {
168  textResultsFile_.open(textResultsPath, std::ios::out | std::ios::trunc);
169  }
170  if (debug_) {
171  debugFile_ = std::make_unique<TFile>("debug_harvester.root", "recreate");
172  }
173 
174  edm::LogInfo("PPSAlignmentHarvester").log([&](auto& li) {
175  li << "parameters:\n";
176  li << "* dqm_dir: " << dqmDir_ << "\n";
177  li << "* sequence:\n";
178  for (unsigned int i = 0; i < sequence_.size(); i++) {
179  li << " " << i + 1 << ": " << sequence_[i] << "\n";
180  }
181  li << "* overwrite_sh_x: " << std::boolalpha << overwriteShX_ << "\n";
182  li << "* text_results_path: " << textResultsPath << "\n";
183  li << "* write_sqlite_results: " << std::boolalpha << writeSQLiteResults_ << "\n";
184  li << "* x_ali_rel_final_slope_fixed: " << std::boolalpha << xAliRelFinalSlopeFixed_ << "\n";
185  li << "* y_ali_final_slope_fixed: " << std::boolalpha << yAliFinalSlopeFixed_ << "\n";
186  // print in um
187  li << "* x_corr_min: " << std::fixed << xCorrRange_.first * 1000. << ", x_corr_max: " << xCorrRange_.second * 1000.
188  << "\n";
189  // print in um
190  li << "* y_corr_min: " << std::fixed << yCorrRange_.first * 1000. << ", y_corr_max: " << yCorrRange_.second * 1000.
191  << "\n";
192  li << "* detector_id: " << detectorId_ << "\n";
193  li << "* subdetector_id: " << subdetectorId_ << "\n";
194  li << "* debug: " << std::boolalpha << debug_;
195  });
196 }
197 
199  if (textResultsFile_.is_open()) {
200  textResultsFile_.close();
201  }
202 }
203 
206 
207  desc.add<std::string>("dqm_dir", "AlCaReco/PPSAlignment");
208  desc.add<std::vector<std::string>>("sequence", {"x_alignment", "x_alignment_relative", "y_alignment"});
209  desc.add<bool>("overwrite_sh_x", true);
210  desc.add<std::string>("text_results_path", "./alignment_results.txt");
211  desc.add<bool>("write_sqlite_results", false);
212  desc.add<bool>("x_ali_rel_final_slope_fixed", false);
213  desc.add<bool>("y_ali_final_slope_fixed", false);
214  desc.add<double>("x_corr_min", -1'000'000.);
215  desc.add<double>("x_corr_max", 1'000'000.);
216  desc.add<double>("y_corr_min", -1'000'000.);
217  desc.add<double>("y_corr_max", 1'000'000.);
218  desc.add<unsigned int>("detector_id", 7);
219  desc.add<unsigned int>("subdetector_id", 4);
220  desc.add<bool>("debug", false);
221 
222  descriptions.addWithDefaultLabel(desc);
223 }
224 
226 
228  DQMStore::IGetter& iGetter,
229  edm::Run const& iRun,
230  edm::EventSetup const& iSetup) {
231  const auto& cfg = iSetup.getData(esTokenTest_);
232 
233  const auto& cfg_ref = iSetup.getData(esTokenReference_);
234 
235  // setting default sh_x values from config
236  for (const auto& sc : {cfg.sectorConfig45(), cfg.sectorConfig56()}) {
237  for (const auto& rpc : {sc.rp_N_, sc.rp_F_}) {
238  sh_x_map_[rpc.id_] = rpc.sh_x_;
239  }
240  }
241  edm::LogInfo("PPSAlignmentHarvester").log([&](auto& li) {
242  li << "Setting sh_x from config of:\n";
243  for (const auto& sc : {cfg.sectorConfig45(), cfg.sectorConfig56()}) {
244  for (const auto& rpc : {sc.rp_N_, sc.rp_F_}) {
245  li << " " << rpc.name_ << " to " << std::fixed << std::setprecision(3) << rpc.sh_x_;
246  if (rpc.name_ != "R_2_F")
247  li << "\n";
248  }
249  }
250  });
251 
252  bool doXAli = false, doXAliRel = false, doYAli = false;
253  for (const std::string& aliMethod : sequence_) {
254  if (aliMethod == "x_alignment") {
255  xAlignment(iBooker, iGetter, cfg, cfg_ref);
256  doXAli = true;
257  } else if (aliMethod == "x_alignment_relative") {
258  xAlignmentRelative(iBooker, iGetter, cfg);
259  doXAliRel = true;
260  } else if (aliMethod == "y_alignment") {
261  yAlignment(iBooker, iGetter, cfg);
262  doYAli = true;
263  } else
264  edm::LogError("PPSAlignmentHarvester") << aliMethod << " is a wrong method name.";
265  seqPos++;
266  }
267 
268  // merge results from all the specified methods
269  CTPPSRPAlignmentCorrectionsData finalResults;
270  if (doXAli) { // x alignment
271  finalResults.addCorrections(xAliResults_);
272  if (doXAliRel) { // merge with x alignment relative
273  for (const auto& sc : {cfg.sectorConfig45(), cfg.sectorConfig56()}) {
274  // extract shifts
275  double d_x_N = xAliResults_.getRPCorrection(sc.rp_N_.id_).getShX();
276  double d_x_F = xAliResults_.getRPCorrection(sc.rp_F_.id_).getShX();
277 
278  double d_x_rel_N, d_x_rel_F;
280  d_x_rel_N = xAliRelResultsSlopeFixed_.getRPCorrection(sc.rp_N_.id_).getShX();
281  d_x_rel_F = xAliRelResultsSlopeFixed_.getRPCorrection(sc.rp_F_.id_).getShX();
282  } else {
283  d_x_rel_N = xAliRelResults_.getRPCorrection(sc.rp_N_.id_).getShX();
284  d_x_rel_F = xAliRelResults_.getRPCorrection(sc.rp_F_.id_).getShX();
285  }
286 
287  // merge the results
288  double b = d_x_rel_N - d_x_rel_F;
289  double xCorrRel = b + d_x_F - d_x_N;
290 
291  CTPPSRPAlignmentCorrectionData corrRelN(xCorrRel / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
292  finalResults.addRPCorrection(sc.rp_N_.id_, corrRelN);
293  CTPPSRPAlignmentCorrectionData corrRelF(-xCorrRel / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
294  finalResults.addRPCorrection(sc.rp_F_.id_, corrRelF);
295  }
296  }
297  }
298  if (doYAli) { // y alignment
299  if (yAliFinalSlopeFixed_) {
301  } else {
302  finalResults.addCorrections(yAliResults_);
303  }
304  }
305 
306  // check if the results are within the reasonability ranges xCorrRange and yCorrRange
307  for (const auto& sc : {cfg.sectorConfig45(), cfg.sectorConfig56()}) {
308  for (const auto& rpc : {sc.rp_F_, sc.rp_N_}) {
309  auto& rpResults = finalResults.getRPCorrection(rpc.id_);
310 
311  if (!(xCorrRange_.first <= rpResults.getShX() && rpResults.getShX() <= xCorrRange_.second)) {
312  edm::LogWarning("PPSAlignmentHarvester")
313  << "The horizontal shift of " << rpc.name_ << " (" << std::fixed << std::setw(9) << std::setprecision(1)
314  << rpResults.getShX() * 1000. << " um) outside of the reasonability range. Setting it to 0.";
315  rpResults.setShX(0.);
316  rpResults.setShXUnc(0.);
317  }
318 
319  if (!(yCorrRange_.first <= rpResults.getShY() && rpResults.getShY() <= yCorrRange_.second)) {
320  edm::LogWarning("PPSAlignmentHarvester")
321  << "The vertical shift of " << rpc.name_ << " (" << std::fixed << std::setw(9) << std::setprecision(1)
322  << rpResults.getShY() * 1000. << " um) outside of the reasonability range. Setting it to 0.";
323  rpResults.setShY(0.);
324  rpResults.setShYUnc(0.);
325  }
326  }
327  }
328 
329  // print the text results
330  edm::LogInfo("PPSAlignmentHarvester") << "final merged results:\n" << finalResults;
331 
332  if (textResultsFile_.is_open()) {
333  textResultsFile_ << "final merged results:\n" << finalResults;
334  }
335 
336  // if requested, store the results in a DB object
337  if (writeSQLiteResults_) {
338  CTPPSRPAlignmentCorrectionsData longIdFinalResults = getLongIdResults(finalResults);
339  edm::LogInfo("PPSAlignmentHarvester") << "trying to store final merged results with long ids:\n"
340  << longIdFinalResults;
341 
343  if (poolDbService.isAvailable()) {
344  poolDbService->writeOneIOV(
345  longIdFinalResults, poolDbService->currentTime(), "CTPPSRPAlignmentCorrectionsDataRcd");
346  } else {
347  edm::LogWarning("PPSAlignmentHarvester")
348  << "Could not store the results in a DB object. PoolDBService not available.";
349  }
350  }
351 
352  // if debug_, save nice-looking cut plots with the worker data in the debug ROOT file
353  if (debug_) {
354  TDirectory* cutsDir = debugFile_->mkdir("cuts");
355  for (const auto& sc : {cfg.sectorConfig45(), cfg.sectorConfig56()}) {
356  TDirectory* sectorDir = cutsDir->mkdir(sc.name_.c_str());
357 
358  gDirectory = sectorDir->mkdir("cut_h");
359  auto* h2_cut_h_bef_monitor = iGetter.get(dqmDir_ + "/worker/" + sc.name_ + "/cuts/cut_h/h2_cut_h_bef");
360  auto* h2_cut_h_aft_monitor = iGetter.get(dqmDir_ + "/worker/" + sc.name_ + "/cuts/cut_h/h2_cut_h_aft");
361  writeCutPlot(
362  h2_cut_h_bef_monitor->getTH2D(), sc.cut_h_a_, sc.cut_h_c_, cfg.n_si(), sc.cut_h_si_, "canvas_before");
363  writeCutPlot(h2_cut_h_aft_monitor->getTH2D(), sc.cut_h_a_, sc.cut_h_c_, cfg.n_si(), sc.cut_h_si_, "canvas_after");
364 
365  gDirectory = sectorDir->mkdir("cut_v");
366  auto* h2_cut_v_bef_monitor = iGetter.get(dqmDir_ + "/worker/" + sc.name_ + "/cuts/cut_v/h2_cut_v_bef");
367  auto* h2_cut_v_aft_monitor = iGetter.get(dqmDir_ + "/worker/" + sc.name_ + "/cuts/cut_v/h2_cut_v_aft");
368  writeCutPlot(
369  h2_cut_v_bef_monitor->getTH2D(), sc.cut_v_a_, sc.cut_v_c_, cfg.n_si(), sc.cut_v_si_, "canvas_before");
370  writeCutPlot(h2_cut_v_aft_monitor->getTH2D(), sc.cut_v_a_, sc.cut_v_c_, cfg.n_si(), sc.cut_v_si_, "canvas_after");
371  }
372  }
373 }
374 
375 // -------------------------------- x alignment methods --------------------------------
376 
377 // Builds graph from a vector of points (with errors).
378 std::unique_ptr<TGraphErrors> PPSAlignmentHarvester::buildGraphFromVector(
379  const std::vector<PPSAlignmentConfiguration::PointErrors>& pv) {
380  auto g = std::make_unique<TGraphErrors>();
381 
382  for (unsigned int i = 0; i < pv.size(); i++) {
383  const auto& p = pv[i];
384  g->SetPoint(i, p.x_, p.y_);
385  g->SetPointError(i, p.ex_, p.ey_);
386  }
387  g->Sort();
388 
389  return g;
390 }
391 
392 // Builds a TGraphErrors from slice plots represented as MonitorElements.
394  DQMStore::IGetter& iGetter,
396  const std::vector<MonitorElement*>& mes,
397  const unsigned int fitProfileMinBinEntries,
398  const unsigned int fitProfileMinNReasonable) {
399  auto g = std::make_unique<TGraphErrors>();
400 
401  for (auto* me : mes) {
402  if (me->getName() == "h_y") // find "h_y"
403  {
404  // retrieve parent directory
405  std::string parentPath = me->getPathname();
406  size_t parentPos = parentPath.substr(0, parentPath.size() - 1).find_last_of('/') + 1;
407  std::string parentName = parentPath.substr(parentPos);
408  std::replace(parentName.begin(), parentName.end(), '_', '.'); // replace _ with .
409  size_t d = parentName.find('-');
410  const double x_min = std::stod(parentName.substr(0, d));
411  const double x_max = std::stod(parentName.substr(d + 1));
412 
413  TH1D* h_y = me->getTH1D();
414 
415  // collect "p_y_diffFN_vs_y" corresponding to found "h_y"
416  auto* p_y_diffFN_vs_y_monitor = iGetter.get(parentPath + "p_y_diffFN_vs_y");
417  if (p_y_diffFN_vs_y_monitor == nullptr) {
418  edm::LogWarning("PPSAlignmentHarvester") << "[x_alignment] could not find p_y_diffFN_vs_y in: " << parentPath;
419  continue;
420  }
421  TProfile* p_y_diffFN_vs_y = p_y_diffFN_vs_y_monitor->getTProfile();
422 
423  double y_cen = h_y->GetMean() + rpc.y_cen_add_;
424  double y_width = h_y->GetRMS() * rpc.y_width_mult_;
425 
426  double sl, sl_unc;
427  int fr = alig_utils::fitProfile(
428  p_y_diffFN_vs_y, y_cen, y_width, fitProfileMinBinEntries, fitProfileMinNReasonable, sl, sl_unc);
429  if (fr != 0)
430  continue;
431 
432  if (debug_)
433  p_y_diffFN_vs_y->Write(parentName.c_str());
434 
435  int idx = g->GetN();
436  g->SetPoint(idx, (x_max + x_min) / 2., sl);
437  g->SetPointError(idx, (x_max - x_min) / 2., sl_unc);
438  }
439  }
440  g->Sort();
441 
442  return g;
443 }
444 
445 // Matches reference data with test data.
449  TGraphErrors* g_ref,
450  TGraphErrors* g_test,
452  const double sh_min,
453  const double sh_max,
454  double& sh_best,
455  double& sh_best_unc) {
456  const auto range_test = cfg.alignment_x_meth_o_ranges().at(rpc.id_);
457 
458  // print config
459  edm::LogInfo("PPSAlignmentHarvester") << std::fixed << std::setprecision(3) << "[x_alignment] "
460  << "ref: x_min = " << range_ref.x_min_ << ", x_max = " << range_ref.x_max_
461  << "\n"
462  << "test: x_min = " << range_test.x_min_ << ", x_max = " << range_test.x_max_;
463 
464  // make spline from g_ref
465  auto s_ref = std::make_unique<TSpline3>("s_ref", g_ref->GetX(), g_ref->GetY(), g_ref->GetN());
466 
467  // book match-quality graphs
468  auto g_n_points = std::make_unique<TGraph>();
469  g_n_points->SetName("g_n_points");
470  g_n_points->SetTitle(";sh;N");
471  auto g_chi_sq = std::make_unique<TGraph>();
472  g_chi_sq->SetName("g_chi_sq");
473  g_chi_sq->SetTitle(";sh;S2");
474  auto g_chi_sq_norm = std::make_unique<TGraph>();
475  g_chi_sq_norm->SetName("g_chi_sq_norm");
476  g_chi_sq_norm->SetTitle(";sh;S2 / N");
477 
478  // optimalisation variables
479  double S2_norm_best = 1E100;
480 
481  for (double sh = sh_min; sh <= sh_max; sh += cfg.x_ali_sh_step()) {
482  // calculate chi^2
483  int n_points = 0;
484  double S2 = 0.;
485 
486  for (int i = 0; i < g_test->GetN(); ++i) {
487  const double x_test = g_test->GetX()[i];
488  const double y_test = g_test->GetY()[i];
489  const double y_test_unc = g_test->GetErrorY(i);
490 
491  const double x_ref = x_test + sh;
492 
493  if (x_ref < range_ref.x_min_ || x_ref > range_ref.x_max_ || x_test < range_test.x_min_ ||
494  x_test > range_test.x_max_)
495  continue;
496 
497  const double y_ref = s_ref->Eval(x_ref);
498 
499  int js = -1, jg = -1;
500  double xs = -1E100, xg = +1E100;
501  for (int j = 0; j < g_ref->GetN(); ++j) {
502  const double x = g_ref->GetX()[j];
503  if (x < x_ref && x > xs) {
504  xs = x;
505  js = j;
506  }
507  if (x > x_ref && x < xg) {
508  xg = x;
509  jg = j;
510  }
511  }
512  if (jg == -1)
513  jg = js;
514 
515  const double y_ref_unc = (g_ref->GetErrorY(js) + g_ref->GetErrorY(jg)) / 2.;
516 
517  n_points++;
518  const double S2_inc = pow(y_test - y_ref, 2.) / (y_ref_unc * y_ref_unc + y_test_unc * y_test_unc);
519  S2 += S2_inc;
520  }
521 
522  // update best result
523  double S2_norm = S2 / n_points;
524 
525  if (S2_norm < S2_norm_best) {
526  S2_norm_best = S2_norm;
527  sh_best = sh;
528  }
529 
530  // fill in graphs
531  int idx = g_n_points->GetN();
532  g_n_points->SetPoint(idx, sh, n_points);
533  g_chi_sq->SetPoint(idx, sh, S2);
534  g_chi_sq_norm->SetPoint(idx, sh, S2_norm);
535  }
536 
537  auto ff_pol2 = std::make_unique<TF1>("ff_pol2", "[0] + [1]*x + [2]*x*x");
538 
539  // determine uncertainty
540  double fit_range = cfg.methOUncFitRange();
541  g_chi_sq->Fit(ff_pol2.get(), "Q", "", sh_best - fit_range, sh_best + fit_range);
542  sh_best_unc = 1. / sqrt(ff_pol2->GetParameter(2));
543 
544  // print results
545  edm::LogInfo("PPSAlignmentHarvester") << std::fixed << std::setprecision(3) << "[x_alignment] "
546  << "sh_best = (" << sh_best << " +- " << sh_best_unc << ") mm";
547 
548  auto g_test_shifted = std::make_unique<TGraphErrors>(*g_test);
549  for (int i = 0; i < g_test_shifted->GetN(); ++i) {
550  g_test_shifted->GetX()[i] += sh_best;
551  }
552 
553  std::unique_ptr<TH1D> histPtr = getTH1DFromTGraphErrors(
554  g_test_shifted.get(), "test_shifted", ";x (mm);S", rpc.x_slice_n_, rpc.x_slice_w_, rpc.x_slice_min_ + sh_best);
555  iBooker.book1DD("h_test_shifted", histPtr.get());
556 
557  if (debug_) {
558  // save graphs
559  g_n_points->Write();
560  g_chi_sq->Write();
561  g_chi_sq_norm->Write();
562  g_test_shifted->SetTitle(";x (mm);S");
563  g_test_shifted->Write("g_test_shifted");
564 
565  // save results
566  auto g_results = std::make_unique<TGraph>();
567  g_results->SetName("g_results");
568  g_results->SetPoint(0, sh_best, sh_best_unc);
569  g_results->SetPoint(1, range_ref.x_min_, range_ref.x_max_);
570  g_results->SetPoint(2, range_test.x_min_, range_test.x_max_);
571  g_results->Write();
572 
573  // save debug canvas
574  auto c_cmp = std::make_unique<TCanvas>("c_cmp");
575  g_ref->SetLineColor(1);
576  g_ref->SetName("g_ref");
577  g_ref->Draw("apl");
578 
579  g_test->SetLineColor(4);
580  g_test->SetName("g_test");
581  g_test->Draw("pl");
582 
583  g_test_shifted->SetLineColor(2);
584  g_test_shifted->SetName("g_test_shifted");
585 
586  g_test_shifted->Draw("pl");
587  c_cmp->Write();
588  }
589 }
590 
591 // method o
593  DQMStore::IGetter& iGetter,
595  const PPSAlignmentConfiguration& cfg_ref) {
596  TDirectory* xAliDir = nullptr;
597  if (debug_)
598  xAliDir = debugFile_->mkdir((std::to_string(seqPos) + ": x alignment").c_str());
599 
600  for (const auto& [sc, sc_ref] : {std::make_pair(cfg.sectorConfig45(), cfg_ref.sectorConfig45()),
601  std::make_pair(cfg.sectorConfig56(), cfg_ref.sectorConfig56())}) {
602  for (const auto& [rpc, rpc_ref] :
603  {std::make_pair(sc.rp_F_, sc_ref.rp_F_), std::make_pair(sc.rp_N_, sc_ref.rp_N_)}) {
604  auto mes_test = iGetter.getAllContents(dqmDir_ + "/worker/" + sc.name_ + "/near_far/x slices " + rpc.position_);
605  if (mes_test.empty()) {
606  edm::LogWarning("PPSAlignmentHarvester") << "[x_alignment] " << rpc.name_ << ": could not load mes_test";
607  continue;
608  }
609 
610  TDirectory* rpDir = nullptr;
611  if (debug_)
612  rpDir = xAliDir->mkdir(rpc.name_.c_str());
613 
614  auto vec_ref = cfg_ref.matchingReferencePoints().at(rpc.id_);
615  if (vec_ref.empty()) {
616  edm::LogInfo("PPSAlignmentHarvester") << "[x_alignment] " << rpc.name_ << ": reference points vector is empty";
617  continue;
618  }
619 
620  std::unique_ptr<TGraphErrors> g_ref = buildGraphFromVector(vec_ref);
621 
622  if (debug_)
623  gDirectory = rpDir->mkdir("fits_test");
624  std::unique_ptr<TGraphErrors> g_test = buildGraphFromMonitorElements(
625  iGetter, rpc, mes_test, cfg.fitProfileMinBinEntries(), cfg.fitProfileMinNReasonable());
626 
627  // require minimal number of points
628  if (g_ref->GetN() < (int)cfg.methOGraphMinN() || g_test->GetN() < (int)cfg.methOGraphMinN()) {
629  edm::LogWarning("PPSAlignmentHarvester")
630  << "[x_alignment] " << rpc.name_ << ": insufficient data, skipping (g_ref " << g_ref->GetN() << "/"
631  << cfg.methOGraphMinN() << ", g_test " << g_test->GetN() << "/" << cfg.methOGraphMinN() << ")";
632  continue;
633  }
634 
635  iBooker.setCurrentFolder(dqmDir_ + "/harvester/x alignment/" + rpc.name_);
636 
637  std::unique_ptr<TH1D> histPtr = getTH1DFromTGraphErrors(
638  g_ref.get(), "ref", ";x (mm);S", rpc_ref.x_slice_n_, rpc_ref.x_slice_w_, rpc_ref.x_slice_min_);
639  iBooker.book1DD("h_ref", histPtr.get());
640 
641  histPtr =
642  getTH1DFromTGraphErrors(g_test.get(), "test", ";x (mm);S", rpc.x_slice_n_, rpc.x_slice_w_, rpc.x_slice_min_);
643  iBooker.book1DD("h_test", histPtr.get());
644 
645  if (debug_) {
646  gDirectory = rpDir;
647  g_ref->SetTitle(";x (mm);S");
648  g_ref->Write("g_ref");
649  g_test->SetTitle(";x (mm);S");
650  g_test->Write("g_test");
651  }
652 
653  const auto& shiftRange = cfg.matchingShiftRanges().at(rpc.id_);
654  double sh = 0., sh_unc = 0.;
655 
656  // matching
657  doMatch(iBooker,
658  cfg,
659  rpc,
660  g_ref.get(),
661  g_test.get(),
662  cfg_ref.alignment_x_meth_o_ranges().at(rpc.id_),
663  shiftRange.x_min_,
664  shiftRange.x_max_,
665  sh,
666  sh_unc);
667 
668  // save the results
669  CTPPSRPAlignmentCorrectionData rpResult(sh, sh_unc, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
670  xAliResults_.setRPCorrection(rpc.id_, rpResult);
671  edm::LogInfo("PPSAlignmentHarvester") << std::fixed << std::setprecision(3) << "[x_alignment] "
672  << "Setting sh_x of " << rpc.name_ << " to " << sh;
673 
674  // update the shift
675  if (overwriteShX_) {
676  sh_x_map_[rpc.id_] = sh;
677  }
678  }
679  }
680 
681  edm::LogInfo("PPSAlignmentHarvester") << seqPos << ": x_alignment:\n" << xAliResults_;
682 
683  if (textResultsFile_.is_open())
684  textResultsFile_ << seqPos << ": x_alignment:\n" << xAliResults_ << "\n\n";
685 }
686 
687 // -------------------------------- x alignment relative methods --------------------------------
688 
690  DQMStore::IGetter& iGetter,
692  TDirectory* xAliRelDir = nullptr;
693  if (debug_)
694  xAliRelDir = debugFile_->mkdir((std::to_string(seqPos) + ": x_alignment_relative").c_str());
695 
696  auto ff = std::make_unique<TF1>("ff", "[0] + [1]*(x - [2])");
697  auto ff_sl_fix = std::make_unique<TF1>("ff_sl_fix", "[0] + [1]*(x - [2])");
698 
699  // processing
700  for (const auto& sc : {cfg.sectorConfig45(), cfg.sectorConfig56()}) {
701  TDirectory* sectorDir = nullptr;
702  if (debug_) {
703  sectorDir = xAliRelDir->mkdir(sc.name_.c_str());
704  gDirectory = sectorDir;
705  }
706 
707  auto* p_x_diffFN_vs_x_N_monitor = iGetter.get(dqmDir_ + "/worker/" + sc.name_ + "/near_far/p_x_diffFN_vs_x_N");
708  if (p_x_diffFN_vs_x_N_monitor == nullptr) {
709  edm::LogWarning("PPSAlignmentHarvester")
710  << "[x_alignment_relative] " << sc.name_ << ": cannot load data, skipping";
711  continue;
712  }
713  TProfile* p_x_diffFN_vs_x_N = p_x_diffFN_vs_x_N_monitor->getTProfile();
714 
715  if (p_x_diffFN_vs_x_N->GetEntries() < cfg.nearFarMinEntries()) {
716  edm::LogWarning("PPSAlignmentHarvester")
717  << "[x_alignment_relative] " << sc.name_ << ": insufficient data, skipping (near_far "
718  << p_x_diffFN_vs_x_N->GetEntries() << "/" << cfg.nearFarMinEntries() << ")";
719  continue;
720  }
721 
722  const double x_min = cfg.alignment_x_relative_ranges().at(sc.rp_N_.id_).x_min_;
723  const double x_max = cfg.alignment_x_relative_ranges().at(sc.rp_N_.id_).x_max_;
724 
725  const double sh_x_N = sh_x_map_[sc.rp_N_.id_];
726  double slope = sc.slope_;
727 
728  // calculate the results without slope fixed
729  ff->SetParameters(0., slope, 0.);
730  ff->FixParameter(2, -sh_x_N);
731  ff->SetLineColor(2);
732  p_x_diffFN_vs_x_N->Fit(ff.get(), "Q", "", x_min, x_max);
733 
734  const double a = ff->GetParameter(1), a_unc = ff->GetParError(1);
735  const double b = ff->GetParameter(0), b_unc = ff->GetParError(0);
736 
737  edm::LogInfo("PPSAlignmentHarvester")
738  << "[x_alignment_relative] " << sc.name_ << ":\n"
739  << std::fixed << std::setprecision(3) << " x_min = " << x_min << ", x_max = " << x_max << "\n"
740  << " sh_x_N = " << sh_x_N << ", slope (fix) = " << slope << ", slope (fitted) = " << a;
741 
742  // relative shift: XF - XN -> XF - XN - b = (XF - b/2) - (XN + b/2)
743  CTPPSRPAlignmentCorrectionData rpResult_N(+b / 2., b_unc / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
744  xAliRelResults_.setRPCorrection(sc.rp_N_.id_, rpResult_N);
745  CTPPSRPAlignmentCorrectionData rpResult_F(-b / 2., b_unc / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
746  xAliRelResults_.setRPCorrection(sc.rp_F_.id_, rpResult_F);
747 
748  // calculate the results with slope fixed
749  ff_sl_fix->SetParameters(0., slope, 0.);
750  ff_sl_fix->FixParameter(1, slope);
751  ff_sl_fix->FixParameter(2, -sh_x_N);
752  ff_sl_fix->SetLineColor(4);
753  p_x_diffFN_vs_x_N->Fit(ff_sl_fix.get(), "Q+", "", x_min, x_max);
754 
755  const double b_fs = ff_sl_fix->GetParameter(0), b_fs_unc = ff_sl_fix->GetParError(0);
756 
757  // relative shift: XF - XN -> XF - XN - b_fs = (XF - b_fs/2) - (XN + b_fs/2)
758  CTPPSRPAlignmentCorrectionData rpResult_sl_fix_N(+b_fs / 2., b_fs_unc / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
759  xAliRelResultsSlopeFixed_.setRPCorrection(sc.rp_N_.id_, rpResult_sl_fix_N);
760  CTPPSRPAlignmentCorrectionData rpResult_sl_fix_F(-b_fs / 2., b_fs_unc / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
761  xAliRelResultsSlopeFixed_.setRPCorrection(sc.rp_F_.id_, rpResult_sl_fix_F);
762 
763  edm::LogInfo("PPSAlignmentHarvester")
764  << "[x_alignment_relative] " << std::fixed << std::setprecision(3) << "ff: " << ff->GetParameter(0) << " + "
765  << ff->GetParameter(1) << " * (x - " << ff->GetParameter(2) << "), ff_sl_fix: " << ff_sl_fix->GetParameter(0)
766  << " + " << ff_sl_fix->GetParameter(1) << " * (x - " << ff_sl_fix->GetParameter(2) << ")";
767 
768  // rebook the diffFN plot in the harvester
769  iBooker.setCurrentFolder(dqmDir_ + "/harvester/x_alignment_relative/" + sc.name_);
770  iBooker.bookProfile("p_x_diffFN_vs_x_N", p_x_diffFN_vs_x_N);
771 
772  if (debug_) {
773  p_x_diffFN_vs_x_N->Write("p_x_diffFN_vs_x_N");
774 
775  auto g_results = std::make_unique<TGraph>();
776  g_results->SetPoint(0, sh_x_N, 0.);
777  g_results->SetPoint(1, a, a_unc);
778  g_results->SetPoint(2, b, b_unc);
779  g_results->SetPoint(3, b_fs, b_fs_unc);
780  g_results->Write("g_results");
781  }
782  }
783 
784  // write results
785  edm::LogInfo("PPSAlignmentHarvester") << seqPos << ": x_alignment_relative:\n"
786  << xAliRelResults_ << seqPos + 1 << ": x_alignment_relative_sl_fix:\n"
788 
789  if (textResultsFile_.is_open()) {
790  textResultsFile_ << seqPos << ": x_alignment_relative:\n" << xAliRelResults_ << "\n";
791  textResultsFile_ << seqPos << ": x_alignment_relative_sl_fix:\n" << xAliRelResultsSlopeFixed_ << "\n\n";
792  }
793 }
794 
795 // -------------------------------- y alignment methods --------------------------------
796 
797 double PPSAlignmentHarvester::findMax(const TF1* ff_fit) {
798  const double mu = ff_fit->GetParameter(1);
799  const double si = ff_fit->GetParameter(2);
800 
801  // unreasonable fit?
802  if (si > 25. || std::fabs(mu) > 100.)
803  return 1E100;
804 
805  double x_max = 1E100;
806  double y_max = -1E100;
807  for (double x = mu - si; x <= mu + si; x += 0.001) {
808  double y = ff_fit->Eval(x);
809  if (y > y_max) {
810  x_max = x;
811  y_max = y;
812  }
813  }
814 
815  return x_max;
816 }
817 
819  const MonitorElement* h2_y_vs_x,
822  TDirectory* d_top = nullptr;
823  if (debug_)
824  d_top = gDirectory;
825 
826  auto ff_fit = std::make_unique<TF1>("ff_fit", "[0] * exp(-(x-[1])*(x-[1])/2./[2]/[2]) + [3] + [4]*x");
827 
828  int h_n = h2_y_vs_x->getNbinsX();
829  double diff = h2_y_vs_x->getTH2D()->GetXaxis()->GetBinWidth(1) / 2.;
830  auto h_mode = iBooker.book1DD("mode",
831  ";x (mm); mode of y (mm)",
832  h_n,
833  h2_y_vs_x->getTH2D()->GetXaxis()->GetBinCenter(1) - diff,
834  h2_y_vs_x->getTH2D()->GetXaxis()->GetBinCenter(h_n) + diff);
835 
836  // find mode for each bin
837  for (int bix = 1; bix <= h_n; bix++) {
838  const double x = h2_y_vs_x->getTH2D()->GetXaxis()->GetBinCenter(bix);
839 
840  char buf[100];
841  sprintf(buf, "h_y_x=%.3f", x);
842  TH1D* h_y = h2_y_vs_x->getTH2D()->ProjectionY(buf, bix, bix);
843 
844  if (h_y->GetEntries() < cfg.multSelProjYMinEntries())
845  continue;
846 
847  if (debug_) {
848  sprintf(buf, "x=%.3f", x);
849  gDirectory = d_top->mkdir(buf);
850  }
851 
852  double conMax = -1.;
853  double conMax_x = 0.;
854  for (int biy = 1; biy < h_y->GetNbinsX(); biy++) {
855  if (h_y->GetBinContent(biy) > conMax) {
856  conMax = h_y->GetBinContent(biy);
857  conMax_x = h_y->GetBinCenter(biy);
858  }
859  }
860 
861  ff_fit->SetParameters(conMax, conMax_x, h_y->GetRMS() * 0.75, 0., 0.);
862  ff_fit->FixParameter(4, 0.);
863 
864  double x_min = rpc.x_min_fit_mode_, x_max = rpc.x_max_fit_mode_;
865  h_y->Fit(ff_fit.get(), "Q", "", x_min, x_max);
866 
867  ff_fit->ReleaseParameter(4);
868  double w = std::min(4., 2. * ff_fit->GetParameter(2));
869  x_min = ff_fit->GetParameter(1) - w;
870  x_max = std::min(rpc.y_max_fit_mode_, ff_fit->GetParameter(1) + w);
871 
872  h_y->Fit(ff_fit.get(), "Q", "", x_min, x_max);
873 
874  if (debug_)
875  h_y->Write("h_y");
876 
877  double y_mode = findMax(ff_fit.get());
878  const double y_mode_fit_unc = ff_fit->GetParameter(2) / 10;
879  const double y_mode_sys_unc = cfg.y_mode_sys_unc();
880  double y_mode_unc = std::sqrt(y_mode_fit_unc * y_mode_fit_unc + y_mode_sys_unc * y_mode_sys_unc);
881 
882  const double chiSqThreshold = cfg.chiSqThreshold();
883 
884  const bool valid =
885  !(std::fabs(y_mode_unc) > cfg.y_mode_unc_max_valid() || std::fabs(y_mode) > cfg.y_mode_max_valid() ||
886  ff_fit->GetChisquare() / ff_fit->GetNDF() > chiSqThreshold);
887 
888  if (debug_) {
889  auto g_data = std::make_unique<TGraph>();
890  g_data->SetPoint(0, y_mode, y_mode_unc);
891  g_data->SetPoint(1, ff_fit->GetChisquare(), ff_fit->GetNDF());
892  g_data->SetPoint(2, valid, 0.);
893  g_data->Write("g_data");
894  }
895 
896  if (!valid)
897  continue;
898 
899  h_mode->Fill(x, y_mode);
900  h_mode->setBinError(bix, y_mode_unc);
901  }
902 
903  return h_mode->getTH1D();
904 }
905 
907  DQMStore::IGetter& iGetter,
909  TDirectory* yAliDir = nullptr;
910  if (debug_)
911  yAliDir = debugFile_->mkdir((std::to_string(seqPos) + ": y_alignment").c_str());
912 
913  auto ff = std::make_unique<TF1>("ff", "[0] + [1]*(x - [2])");
914  auto ff_sl_fix = std::make_unique<TF1>("ff_sl_fix", "[0] + [1]*(x - [2])");
915 
916  // processing
917  for (const auto& sc : {cfg.sectorConfig45(), cfg.sectorConfig56()}) {
918  for (const auto& rpc : {sc.rp_F_, sc.rp_N_}) {
919  TDirectory* rpDir = nullptr;
920  if (debug_) {
921  rpDir = yAliDir->mkdir(rpc.name_.c_str());
922  gDirectory = rpDir->mkdir("x");
923  }
924 
925  auto* h2_y_vs_x =
926  iGetter.get(dqmDir_ + "/worker/" + sc.name_ + "/multiplicity selection/" + rpc.name_ + "/h2_y_vs_x");
927 
928  if (h2_y_vs_x == nullptr) {
929  edm::LogWarning("PPSAlignmentHarvester") << "[y_alignment] " << rpc.name_ << ": cannot load data, skipping";
930  continue;
931  }
932 
933  iBooker.setCurrentFolder(dqmDir_ + "/harvester/y alignment/" + rpc.name_);
934  auto* h_y_cen_vs_x = buildModeGraph(iBooker, h2_y_vs_x, cfg, rpc);
935 
936  if ((unsigned int)h_y_cen_vs_x->GetEntries() < cfg.modeGraphMinN()) {
937  edm::LogWarning("PPSAlignmentHarvester")
938  << "[y_alignment] " << rpc.name_ << ": insufficient data, skipping (mode graph "
939  << h_y_cen_vs_x->GetEntries() << "/" << cfg.modeGraphMinN() << ")";
940  continue;
941  }
942 
943  const double x_min = cfg.alignment_y_ranges().at(rpc.id_).x_min_;
944  const double x_max = cfg.alignment_y_ranges().at(rpc.id_).x_max_;
945 
946  const double sh_x = sh_x_map_[rpc.id_];
947  double slope = rpc.slope_;
948 
949  // calculate the results without slope fixed
950  ff->SetParameters(0., 0., 0.);
951  ff->FixParameter(2, -sh_x);
952  ff->SetLineColor(2);
953  h_y_cen_vs_x->Fit(ff.get(), "Q", "", x_min, x_max);
954 
955  const double a = ff->GetParameter(1), a_unc = ff->GetParError(1); // slope
956  const double b = ff->GetParameter(0), b_unc = ff->GetParError(0); // intercept
957 
958  edm::LogInfo("PPSAlignmentHarvester")
959  << "[y_alignment] " << rpc.name_ << ":\n"
960  << std::fixed << std::setprecision(3) << " x_min = " << x_min << ", x_max = " << x_max << "\n"
961  << " sh_x = " << sh_x << ", slope (fix) = " << slope << ", slope (fitted) = " << a;
962 
963  // vertical shift y -> y - b
964  CTPPSRPAlignmentCorrectionData rpResult(0., 0., -b, b_unc, 0., 0., 0., 0., 0., 0., 0., 0.);
965  yAliResults_.setRPCorrection(rpc.id_, rpResult);
966 
967  // calculate the results with slope fixed
968  ff_sl_fix->SetParameters(0., 0., 0.);
969  ff_sl_fix->FixParameter(1, slope);
970  ff_sl_fix->FixParameter(2, -sh_x);
971  ff_sl_fix->SetLineColor(4);
972  h_y_cen_vs_x->Fit(ff_sl_fix.get(), "Q+", "", x_min, x_max);
973 
974  const double b_fs = ff_sl_fix->GetParameter(0), b_fs_unc = ff_sl_fix->GetParError(0); // intercept
975 
976  CTPPSRPAlignmentCorrectionData rpResult_sl_fix(0., 0., -b_fs, b_fs_unc, 0., 0., 0., 0., 0., 0., 0., 0.);
977  yAliResultsSlopeFixed_.setRPCorrection(rpc.id_, rpResult_sl_fix);
978 
979  edm::LogInfo("PPSAlignmentHarvester")
980  << "[y_alignment] " << std::fixed << std::setprecision(3) << "ff: " << ff->GetParameter(0) << " + "
981  << ff->GetParameter(1) << " * (x - " << ff->GetParameter(2) << "), ff_sl_fix: " << ff_sl_fix->GetParameter(0)
982  << " + " << ff_sl_fix->GetParameter(1) << " * (x - " << ff_sl_fix->GetParameter(2) << ")";
983 
984  if (debug_) {
985  gDirectory = rpDir;
986 
987  h_y_cen_vs_x->SetTitle(";x (mm); mode of y (mm)");
988  h_y_cen_vs_x->Write("h_y_cen_vs_x");
989 
990  auto g_results = std::make_unique<TGraph>();
991  g_results->SetPoint(0, sh_x, 0.);
992  g_results->SetPoint(1, a, a_unc);
993  g_results->SetPoint(2, -b, b_unc);
994  g_results->SetPoint(3, -b_fs, b_fs_unc);
995  g_results->Write("g_results");
996  }
997  }
998  }
999 
1000  // write results
1001  edm::LogInfo("PPSAlignmentHarvester") << seqPos << ": y_alignment:\n"
1002  << yAliResults_ << seqPos << ": y_alignment_sl_fix:\n"
1004 
1005  if (textResultsFile_.is_open()) {
1006  textResultsFile_ << seqPos << ": y_alignment:\n" << yAliResults_ << "\n";
1007  textResultsFile_ << seqPos << ": y_alignment_sl_fix:\n" << yAliResultsSlopeFixed_ << "\n\n";
1008  }
1009 }
1010 
1011 // -------------------------------- other methods --------------------------------
1012 
1013 // Creates a plot showing a cut applied by the worker. Used only for debug purposes.
1015  TH2D* h, const double a, const double c, const double n_si, const double si, const std::string& label) {
1016  auto canvas = std::make_unique<TCanvas>();
1017  canvas->SetName(label.c_str());
1018  canvas->SetLogz(1);
1019 
1020  h->Draw("colz");
1021 
1022  double x_min = -30.;
1023  double x_max = 30.;
1024 
1025  auto g_up = std::make_unique<TGraph>();
1026  g_up->SetName("g_up");
1027  g_up->SetPoint(0, x_min, -a * x_min - c + n_si * si);
1028  g_up->SetPoint(1, x_max, -a * x_max - c + n_si * si);
1029  g_up->SetLineColor(1);
1030  g_up->Draw("l");
1031 
1032  auto g_down = std::make_unique<TGraph>();
1033  g_down->SetName("g_down");
1034  g_down->SetPoint(0, x_min, -a * x_min - c - n_si * si);
1035  g_down->SetPoint(1, x_max, -a * x_max - c - n_si * si);
1036  g_down->SetLineColor(1);
1037  g_down->Draw("l");
1038 
1039  canvas->Write();
1040 }
1041 
1042 // Points in TGraph should be sorted (TGraph::Sort())
1043 // if n, binWidth, or min is set to -1, method will find it on its own
1045  TGraphErrors* graph, const std::string& title, const std::string& labels, int n, double binWidth, double min) {
1046  std::unique_ptr<TH1D> hist;
1047  if (n == 0) {
1048  hist = std::make_unique<TH1D>(title.c_str(), labels.c_str(), 0, -10., 10.);
1049  } else if (n == 1) {
1050  hist = std::make_unique<TH1D>(title.c_str(), labels.c_str(), 1, graph->GetPointX(0) - 5., graph->GetPointX(0) + 5.);
1051  } else {
1052  n = n == -1 ? graph->GetN() : n;
1053  binWidth = binWidth == -1 ? graph->GetPointX(1) - graph->GetPointX(0) : binWidth;
1054  double diff = binWidth / 2.;
1055  min = min == -1 ? graph->GetPointX(0) - diff : min;
1056  double max = min + n * binWidth;
1057  hist = std::make_unique<TH1D>(title.c_str(), labels.c_str(), n, min, max);
1058  }
1059 
1060  for (int i = 0; i < graph->GetN(); i++) {
1061  double x, y;
1062  graph->GetPoint(i, x, y);
1063  hist->Fill(x, y);
1064  hist->SetBinError(hist->GetXaxis()->FindBin(x), graph->GetErrorY(i));
1065  }
1066  return hist;
1067 }
1068 
1069 // Get Long 32-bit detector ID from short 3-digit ID
1071  CTPPSRPAlignmentCorrectionsData longIdResults;
1072  for (const auto& [shortId, correction] : shortIdResults.getRPMap()) {
1073  unsigned int arm = shortId / 100;
1074  unsigned int station = (shortId / 10) % 10;
1075  unsigned int rp = shortId % 10;
1076 
1077  uint32_t longDetId = detectorId_ << 28 | subdetectorId_ << 25 | arm << 24 | station << 22 | rp << 19;
1078 
1079  longIdResults.addRPCorrection(longDetId, correction);
1080  }
1081 
1082  return longIdResults;
1083 }
1084 
void dqmEndRun(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter, edm::Run const &iRun, edm::EventSetup const &iSetup) override
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
int fitProfile(TProfile *p, double x_mean, double x_rms, unsigned int minBinEntries, unsigned int minNBinsReasonable, double &sl, double &sl_unc)
Definition: utils.cc:14
void xAlignment(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter, const PPSAlignmentConfiguration &cfg, const PPSAlignmentConfiguration &cfg_ref)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
CTPPSRPAlignmentCorrectionData & getRPCorrection(unsigned int id)
returns the correction value from the RP map
const std::map< unsigned int, SelectionRange > & alignment_x_meth_o_ranges() const
static void writeCutPlot(TH2D *h, const double a, const double c, const double si, const double n_si, const std::string &label)
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
std::map< unsigned int, double > sh_x_map_
CTPPSRPAlignmentCorrectionsData getLongIdResults(CTPPSRPAlignmentCorrectionsData finalResults)
edm::ESGetToken< PPSAlignmentConfiguration, PPSAlignmentConfigurationRcd > esTokenReference_
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
T w() const
CTPPSRPAlignmentCorrectionsData xAliRelResults_
static std::unique_ptr< TH1D > getTH1DFromTGraphErrors(TGraphErrors *graph, const std::string &title="", const std::string &labels="", int n=-1, double binWidth=-1., double min=-1.)
static const double slope[3]
def replace(string, replacements)
const std::pair< double, double > yCorrRange_
CTPPSRPAlignmentCorrectionsData yAliResults_
void setRPCorrection(unsigned int id, const CTPPSRPAlignmentCorrectionData &ac)
sets the alignment correction for the given RP
Log< level::Error, false > LogError
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
const mapType & getRPMap() const
returns the map of RP alignment corrections
static std::string to_string(const XMLCh *ch)
void xAlignmentRelative(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter, const PPSAlignmentConfiguration &cfg)
std::unique_ptr< TGraphErrors > buildGraphFromVector(const std::vector< PPSAlignmentConfiguration::PointErrors > &pv)
char const * label
CTPPSRPAlignmentCorrectionsData yAliResultsSlopeFixed_
MonitorElement * book1DD(TString const &name, TString const &title, int nchX, double lowX, double highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:155
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const SectorConfig & sectorConfig45() const
MonitorElement * bookProfile(TString const &name, TString const &title, int nchX, double lowX, double highX, int, double lowY, double highY, char const *option="s", FUNC onbooking=NOOP())
Definition: DQMStore.h:408
CTPPSRPAlignmentCorrectionsData xAliResults_
PPSAlignmentHarvester(const edm::ParameterSet &iConfig)
T sqrt(T t)
Definition: SSEVec.h:23
virtual std::vector< dqm::harvesting::MonitorElement * > getAllContents(std::string const &path) const
Definition: DQMStore.cc:641
const std::map< unsigned int, std::vector< PointErrors > > & matchingReferencePoints() const
void doMatch(DQMStore::IBooker &iBooker, const PPSAlignmentConfiguration &cfg, const PPSAlignmentConfiguration::RPConfig &rpc, TGraphErrors *g_ref, TGraphErrors *g_test, const PPSAlignmentConfiguration::SelectionRange &range_ref, const double sh_min, const double sh_max, double &sh_best, double &sh_best_unc)
Hash writeOneIOV(const T &payload, Time_t time, const std::string &recordName)
Transition
Definition: Transition.h:12
void yAlignment(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter, const PPSAlignmentConfiguration &cfg)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
static double findMax(const TF1 *ff_fit)
const std::vector< std::string > sequence_
edm::ESGetToken< PPSAlignmentConfiguration, PPSAlignmentConfigurationRcd > esTokenTest_
void addRPCorrection(unsigned int, const CTPPSRPAlignmentCorrectionData &, bool sumErrors=true, bool addSh=true, bool addRot=true)
d
Definition: ztail.py:151
std::unique_ptr< TFile > debugFile_
void addCorrections(const CTPPSRPAlignmentCorrectionsData &, bool sumErrors=true, bool addSh=true, bool addRot=true)
adds (merges) corrections on top of the current values
Log< level::Info, false > LogInfo
void dqmEndJob(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter) override
std::unique_ptr< TGraphErrors > buildGraphFromMonitorElements(DQMStore::IGetter &iGetter, const PPSAlignmentConfiguration::RPConfig &rpc, const std::vector< MonitorElement *> &mes, const unsigned int fitProfileMinBinEntries, const unsigned int fitProfileMinNReasonable)
double b
Definition: hdecay.h:120
const SectorConfig & sectorConfig56() const
virtual MonitorElement * get(std::string const &fullpath) const
Definition: DQMStore.cc:712
Container for CTPPS RP alignment corrections. The corrections are stored on two levels - RP and senso...
TH1D * buildModeGraph(DQMStore::IBooker &iBooker, const MonitorElement *h2_y_vs_x, const PPSAlignmentConfiguration &cfg, const PPSAlignmentConfiguration::RPConfig &rpc)
HLT enums.
const std::pair< double, double > xCorrRange_
double a
Definition: hdecay.h:121
CTPPSRPAlignmentCorrectionsData xAliRelResultsSlopeFixed_
def canvas(sub, attr)
Definition: svgfig.py:482
virtual int getNbinsX() const
get # of bins in X-axis
bool isAvailable() const
Definition: Service.h:40
Log< level::Warning, false > LogWarning
const unsigned int detectorId_
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
const unsigned int subdetectorId_
Alignment correction for an element of the CT-PPS detector. Within the geometry description, every sensor (more generally every element) is given its translation and rotation. These two quantities shall be understood in local-to-global coordinate transform. That is, if r_l is a point in local coordinate system and x_g in global, then it holds.
Definition: Run.h:45
virtual TH2D * getTH2D() const