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", true);
213  desc.add<bool>("y_ali_final_slope_fixed", true);
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  CTPPSRPAlignmentCorrectionData rpResult_N(+b / 2., b_unc / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
743  xAliRelResults_.setRPCorrection(sc.rp_N_.id_, rpResult_N);
744  CTPPSRPAlignmentCorrectionData rpResult_F(-b / 2., b_unc / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
745  xAliRelResults_.setRPCorrection(sc.rp_F_.id_, rpResult_F);
746 
747  // calculate the results with slope fixed
748  ff_sl_fix->SetParameters(0., slope, 0.);
749  ff_sl_fix->FixParameter(1, slope);
750  ff_sl_fix->FixParameter(2, -sh_x_N);
751  ff_sl_fix->SetLineColor(4);
752  p_x_diffFN_vs_x_N->Fit(ff_sl_fix.get(), "Q+", "", x_min, x_max);
753 
754  const double b_fs = ff_sl_fix->GetParameter(0), b_fs_unc = ff_sl_fix->GetParError(0);
755 
756  CTPPSRPAlignmentCorrectionData rpResult_sl_fix_N(+b_fs / 2., b_fs_unc / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
757  xAliRelResultsSlopeFixed_.setRPCorrection(sc.rp_N_.id_, rpResult_sl_fix_N);
758  CTPPSRPAlignmentCorrectionData rpResult_sl_fix_F(-b_fs / 2., b_fs_unc / 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
759  xAliRelResultsSlopeFixed_.setRPCorrection(sc.rp_F_.id_, rpResult_sl_fix_F);
760 
761  edm::LogInfo("PPSAlignmentHarvester")
762  << "[x_alignment_relative] " << std::fixed << std::setprecision(3) << "ff: " << ff->GetParameter(0) << " + "
763  << ff->GetParameter(1) << " * (x - " << ff->GetParameter(2) << "), ff_sl_fix: " << ff_sl_fix->GetParameter(0)
764  << " + " << ff_sl_fix->GetParameter(1) << " * (x - " << ff_sl_fix->GetParameter(2) << ")";
765 
766  // rebook the diffFN plot in the harvester
767  iBooker.setCurrentFolder(dqmDir_ + "/harvester/x_alignment_relative/" + sc.name_);
768  iBooker.bookProfile("p_x_diffFN_vs_x_N", p_x_diffFN_vs_x_N);
769 
770  if (debug_) {
771  p_x_diffFN_vs_x_N->Write("p_x_diffFN_vs_x_N");
772 
773  auto g_results = std::make_unique<TGraph>();
774  g_results->SetPoint(0, sh_x_N, 0.);
775  g_results->SetPoint(1, a, a_unc);
776  g_results->SetPoint(2, b, b_unc);
777  g_results->SetPoint(3, b_fs, b_fs_unc);
778  g_results->Write("g_results");
779  }
780  }
781 
782  // write results
783  edm::LogInfo("PPSAlignmentHarvester") << seqPos << ": x_alignment_relative:\n"
784  << xAliRelResults_ << seqPos + 1 << ": x_alignment_relative_sl_fix:\n"
786 
787  if (textResultsFile_.is_open()) {
788  textResultsFile_ << seqPos << ": x_alignment_relative:\n" << xAliRelResults_ << "\n";
789  textResultsFile_ << seqPos << ": x_alignment_relative_sl_fix:\n" << xAliRelResultsSlopeFixed_ << "\n\n";
790  }
791 }
792 
793 // -------------------------------- y alignment methods --------------------------------
794 
795 double PPSAlignmentHarvester::findMax(const TF1* ff_fit) {
796  const double mu = ff_fit->GetParameter(1);
797  const double si = ff_fit->GetParameter(2);
798 
799  // unreasonable fit?
800  if (si > 25. || std::fabs(mu) > 100.)
801  return 1E100;
802 
803  double x_max = 1E100;
804  double y_max = -1E100;
805  for (double x = mu - si; x <= mu + si; x += 0.001) {
806  double y = ff_fit->Eval(x);
807  if (y > y_max) {
808  x_max = x;
809  y_max = y;
810  }
811  }
812 
813  return x_max;
814 }
815 
817  const MonitorElement* h2_y_vs_x,
820  TDirectory* d_top = nullptr;
821  if (debug_)
822  d_top = gDirectory;
823 
824  auto ff_fit = std::make_unique<TF1>("ff_fit", "[0] * exp(-(x-[1])*(x-[1])/2./[2]/[2]) + [3] + [4]*x");
825 
826  int h_n = h2_y_vs_x->getNbinsX();
827  double diff = h2_y_vs_x->getTH2D()->GetXaxis()->GetBinWidth(1) / 2.;
828  auto h_mode = iBooker.book1DD("mode",
829  ";x (mm); mode of y (mm)",
830  h_n,
831  h2_y_vs_x->getTH2D()->GetXaxis()->GetBinCenter(1) - diff,
832  h2_y_vs_x->getTH2D()->GetXaxis()->GetBinCenter(h_n) + diff);
833 
834  // find mode for each bin
835  for (int bix = 1; bix <= h_n; bix++) {
836  const double x = h2_y_vs_x->getTH2D()->GetXaxis()->GetBinCenter(bix);
837 
838  char buf[100];
839  sprintf(buf, "h_y_x=%.3f", x);
840  TH1D* h_y = h2_y_vs_x->getTH2D()->ProjectionY(buf, bix, bix);
841 
842  if (h_y->GetEntries() < cfg.multSelProjYMinEntries())
843  continue;
844 
845  if (debug_) {
846  sprintf(buf, "x=%.3f", x);
847  gDirectory = d_top->mkdir(buf);
848  }
849 
850  double conMax = -1.;
851  double conMax_x = 0.;
852  for (int biy = 1; biy < h_y->GetNbinsX(); biy++) {
853  if (h_y->GetBinContent(biy) > conMax) {
854  conMax = h_y->GetBinContent(biy);
855  conMax_x = h_y->GetBinCenter(biy);
856  }
857  }
858 
859  ff_fit->SetParameters(conMax, conMax_x, h_y->GetRMS() * 0.75, 0., 0.);
860  ff_fit->FixParameter(4, 0.);
861 
862  double x_min = rpc.x_min_fit_mode_, x_max = rpc.x_max_fit_mode_;
863  h_y->Fit(ff_fit.get(), "Q", "", x_min, x_max);
864 
865  ff_fit->ReleaseParameter(4);
866  double w = std::min(4., 2. * ff_fit->GetParameter(2));
867  x_min = ff_fit->GetParameter(1) - w;
868  x_max = std::min(rpc.y_max_fit_mode_, ff_fit->GetParameter(1) + w);
869 
870  h_y->Fit(ff_fit.get(), "Q", "", x_min, x_max);
871 
872  if (debug_)
873  h_y->Write("h_y");
874 
875  double y_mode = findMax(ff_fit.get());
876  const double y_mode_fit_unc = ff_fit->GetParameter(2) / 10;
877  const double y_mode_sys_unc = cfg.y_mode_sys_unc();
878  double y_mode_unc = std::sqrt(y_mode_fit_unc * y_mode_fit_unc + y_mode_sys_unc * y_mode_sys_unc);
879 
880  const double chiSqThreshold = cfg.chiSqThreshold();
881 
882  const bool valid =
883  !(std::fabs(y_mode_unc) > cfg.y_mode_unc_max_valid() || std::fabs(y_mode) > cfg.y_mode_max_valid() ||
884  ff_fit->GetChisquare() / ff_fit->GetNDF() > chiSqThreshold);
885 
886  if (debug_) {
887  auto g_data = std::make_unique<TGraph>();
888  g_data->SetPoint(0, y_mode, y_mode_unc);
889  g_data->SetPoint(1, ff_fit->GetChisquare(), ff_fit->GetNDF());
890  g_data->SetPoint(2, valid, 0.);
891  g_data->Write("g_data");
892  }
893 
894  if (!valid)
895  continue;
896 
897  h_mode->Fill(x, y_mode);
898  h_mode->setBinError(bix, y_mode_unc);
899  }
900 
901  return h_mode->getTH1D();
902 }
903 
905  DQMStore::IGetter& iGetter,
907  TDirectory* yAliDir = nullptr;
908  if (debug_)
909  yAliDir = debugFile_->mkdir((std::to_string(seqPos) + ": y_alignment").c_str());
910 
911  auto ff = std::make_unique<TF1>("ff", "[0] + [1]*(x - [2])");
912  auto ff_sl_fix = std::make_unique<TF1>("ff_sl_fix", "[0] + [1]*(x - [2])");
913 
914  // processing
915  for (const auto& sc : {cfg.sectorConfig45(), cfg.sectorConfig56()}) {
916  for (const auto& rpc : {sc.rp_F_, sc.rp_N_}) {
917  TDirectory* rpDir = nullptr;
918  if (debug_) {
919  rpDir = yAliDir->mkdir(rpc.name_.c_str());
920  gDirectory = rpDir->mkdir("x");
921  }
922 
923  auto* h2_y_vs_x =
924  iGetter.get(dqmDir_ + "/worker/" + sc.name_ + "/multiplicity selection/" + rpc.name_ + "/h2_y_vs_x");
925 
926  if (h2_y_vs_x == nullptr) {
927  edm::LogWarning("PPSAlignmentHarvester") << "[y_alignment] " << rpc.name_ << ": cannot load data, skipping";
928  continue;
929  }
930 
931  iBooker.setCurrentFolder(dqmDir_ + "/harvester/y alignment/" + rpc.name_);
932  auto* h_y_cen_vs_x = buildModeGraph(iBooker, h2_y_vs_x, cfg, rpc);
933 
934  if ((unsigned int)h_y_cen_vs_x->GetEntries() < cfg.modeGraphMinN()) {
935  edm::LogWarning("PPSAlignmentHarvester")
936  << "[y_alignment] " << rpc.name_ << ": insufficient data, skipping (mode graph "
937  << h_y_cen_vs_x->GetEntries() << "/" << cfg.modeGraphMinN() << ")";
938  continue;
939  }
940 
941  const double x_min = cfg.alignment_y_ranges().at(rpc.id_).x_min_;
942  const double x_max = cfg.alignment_y_ranges().at(rpc.id_).x_max_;
943 
944  const double sh_x = sh_x_map_[rpc.id_];
945  double slope = rpc.slope_;
946 
947  // calculate the results without slope fixed
948  ff->SetParameters(0., 0., 0.);
949  ff->FixParameter(2, -sh_x);
950  ff->SetLineColor(2);
951  h_y_cen_vs_x->Fit(ff.get(), "Q", "", x_min, x_max);
952 
953  const double a = ff->GetParameter(1), a_unc = ff->GetParError(1);
954  const double b = ff->GetParameter(0), b_unc = ff->GetParError(0);
955 
956  edm::LogInfo("PPSAlignmentHarvester")
957  << "[y_alignment] " << rpc.name_ << ":\n"
958  << std::fixed << std::setprecision(3) << " x_min = " << x_min << ", x_max = " << x_max << "\n"
959  << " sh_x = " << sh_x << ", slope (fix) = " << slope << ", slope (fitted) = " << a;
960 
961  CTPPSRPAlignmentCorrectionData rpResult(0., 0., b, b_unc, 0., 0., 0., 0., 0., 0., 0., 0.);
962  yAliResults_.setRPCorrection(rpc.id_, rpResult);
963 
964  // calculate the results with slope fixed
965  ff_sl_fix->SetParameters(0., 0., 0.);
966  ff_sl_fix->FixParameter(1, slope);
967  ff_sl_fix->FixParameter(2, -sh_x);
968  ff_sl_fix->SetLineColor(4);
969  h_y_cen_vs_x->Fit(ff_sl_fix.get(), "Q+", "", x_min, x_max);
970 
971  const double b_fs = ff_sl_fix->GetParameter(0), b_fs_unc = ff_sl_fix->GetParError(0);
972 
973  CTPPSRPAlignmentCorrectionData rpResult_sl_fix(0., 0., b_fs, b_fs_unc, 0., 0., 0., 0., 0., 0., 0., 0.);
974  yAliResultsSlopeFixed_.setRPCorrection(rpc.id_, rpResult_sl_fix);
975 
976  edm::LogInfo("PPSAlignmentHarvester")
977  << "[y_alignment] " << std::fixed << std::setprecision(3) << "ff: " << ff->GetParameter(0) << " + "
978  << ff->GetParameter(1) << " * (x - " << ff->GetParameter(2) << "), ff_sl_fix: " << ff_sl_fix->GetParameter(0)
979  << " + " << ff_sl_fix->GetParameter(1) << " * (x - " << ff_sl_fix->GetParameter(2) << ")";
980 
981  if (debug_) {
982  gDirectory = rpDir;
983 
984  h_y_cen_vs_x->SetTitle(";x (mm); mode of y (mm)");
985  h_y_cen_vs_x->Write("h_y_cen_vs_x");
986 
987  auto g_results = std::make_unique<TGraph>();
988  g_results->SetPoint(0, sh_x, 0.);
989  g_results->SetPoint(1, a, a_unc);
990  g_results->SetPoint(2, b, b_unc);
991  g_results->SetPoint(3, b_fs, b_fs_unc);
992  g_results->Write("g_results");
993  }
994  }
995  }
996 
997  // write results
998  edm::LogInfo("PPSAlignmentHarvester") << seqPos << ": y_alignment:\n"
999  << yAliResults_ << seqPos << ": y_alignment_sl_fix:\n"
1001 
1002  if (textResultsFile_.is_open()) {
1003  textResultsFile_ << seqPos << ": y_alignment:\n" << yAliResults_ << "\n";
1004  textResultsFile_ << seqPos << ": y_alignment_sl_fix:\n" << yAliResultsSlopeFixed_ << "\n\n";
1005  }
1006 }
1007 
1008 // -------------------------------- other methods --------------------------------
1009 
1010 // Creates a plot showing a cut applied by the worker. Used only for debug purposes.
1012  TH2D* h, const double a, const double c, const double n_si, const double si, const std::string& label) {
1013  auto canvas = std::make_unique<TCanvas>();
1014  canvas->SetName(label.c_str());
1015  canvas->SetLogz(1);
1016 
1017  h->Draw("colz");
1018 
1019  double x_min = -30.;
1020  double x_max = 30.;
1021 
1022  auto g_up = std::make_unique<TGraph>();
1023  g_up->SetName("g_up");
1024  g_up->SetPoint(0, x_min, -a * x_min - c + n_si * si);
1025  g_up->SetPoint(1, x_max, -a * x_max - c + n_si * si);
1026  g_up->SetLineColor(1);
1027  g_up->Draw("l");
1028 
1029  auto g_down = std::make_unique<TGraph>();
1030  g_down->SetName("g_down");
1031  g_down->SetPoint(0, x_min, -a * x_min - c - n_si * si);
1032  g_down->SetPoint(1, x_max, -a * x_max - c - n_si * si);
1033  g_down->SetLineColor(1);
1034  g_down->Draw("l");
1035 
1036  canvas->Write();
1037 }
1038 
1039 // Points in TGraph should be sorted (TGraph::Sort())
1040 // if n, binWidth, or min is set to -1, method will find it on its own
1042  TGraphErrors* graph, const std::string& title, const std::string& labels, int n, double binWidth, double min) {
1043  std::unique_ptr<TH1D> hist;
1044  if (n == 0) {
1045  hist = std::make_unique<TH1D>(title.c_str(), labels.c_str(), 0, -10., 10.);
1046  } else if (n == 1) {
1047  hist = std::make_unique<TH1D>(title.c_str(), labels.c_str(), 1, graph->GetPointX(0) - 5., graph->GetPointX(0) + 5.);
1048  } else {
1049  n = n == -1 ? graph->GetN() : n;
1050  binWidth = binWidth == -1 ? graph->GetPointX(1) - graph->GetPointX(0) : binWidth;
1051  double diff = binWidth / 2.;
1052  min = min == -1 ? graph->GetPointX(0) - diff : min;
1053  double max = min + n * binWidth;
1054  hist = std::make_unique<TH1D>(title.c_str(), labels.c_str(), n, min, max);
1055  }
1056 
1057  for (int i = 0; i < graph->GetN(); i++) {
1058  double x, y;
1059  graph->GetPoint(i, x, y);
1060  hist->Fill(x, y);
1061  hist->SetBinError(hist->GetXaxis()->FindBin(x), graph->GetErrorY(i));
1062  }
1063  return hist;
1064 }
1065 
1066 // Get Long 32-bit detector ID from short 3-digit ID
1068  CTPPSRPAlignmentCorrectionsData longIdResults;
1069  for (const auto& [shortId, correction] : shortIdResults.getRPMap()) {
1070  unsigned int arm = shortId / 100;
1071  unsigned int station = (shortId / 10) % 10;
1072  unsigned int rp = shortId % 10;
1073 
1074  uint32_t longDetId = detectorId_ << 28 | subdetectorId_ << 25 | arm << 24 | station << 22 | rp << 19;
1075 
1076  longIdResults.addRPCorrection(longDetId, correction);
1077  }
1078 
1079  return longIdResults;
1080 }
1081 
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_
constexpr int pow(int x)
Definition: conifer.h:24
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:399
CTPPSRPAlignmentCorrectionsData xAliResults_
PPSAlignmentHarvester(const edm::ParameterSet &iConfig)
T sqrt(T t)
Definition: SSEVec.h:19
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
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