CMS 3D CMS Logo

CTPPSProtonReconstructionPlotter.cc
Go to the documentation of this file.
1 /****************************************************************************
2 * Authors:
3 * Jan Kašpar (jan.kaspar@gmail.com)
4 ****************************************************************************/
5 
6 #include <memory>
7 
16 
18 
22 
27 
28 #include "TFile.h"
29 #include "TGraphErrors.h"
30 #include "TH1D.h"
31 #include "TH2D.h"
32 #include "TProfile.h"
33 
34 //----------------------------------------------------------------------------------------------------
35 
37 public:
40 
41 private:
42  void analyze(const edm::Event &, const edm::EventSetup &) override;
43 
44  void endJob() override;
45 
51 
52  unsigned int rpId_45_N_, rpId_45_F_;
53  unsigned int rpId_56_N_, rpId_56_F_;
54 
56 
57  signed int maxNonEmptyEvents_;
58 
59  static void profileToRMSGraph(TProfile *p, TGraphErrors *g) {
60  for (int bi = 1; bi <= p->GetNbinsX(); ++bi) {
61  double c = p->GetBinCenter(bi);
62 
63  double N = p->GetBinEntries(bi);
64  double Sy = p->GetBinContent(bi) * N;
65  double Syy = p->GetSumw2()->At(bi);
66 
67  double si_sq = Syy / N - Sy * Sy / N / N;
68  double si = (si_sq >= 0.) ? sqrt(si_sq) : 0.;
69  double si_unc_sq = si_sq / 2. / N; // Gaussian approximation
70  double si_unc = (si_unc_sq >= 0.) ? sqrt(si_unc_sq) : 0.;
71 
72  int idx = g->GetN();
73  g->SetPoint(idx, c, si);
74  g->SetPointError(idx, 0., si_unc);
75  }
76  }
77 
79  const CTPPSLocalTrackLite &tr,
80  const CTPPSGeometry &geometry,
81  double &x_tr,
82  double &x_ti,
83  double &de_x,
84  double &de_x_unc);
85 
86  struct SingleRPPlots {
87  std::unique_ptr<TH1D> h_multiplicity;
88  std::unique_ptr<TH1D> h_xi;
89  std::unique_ptr<TH2D> h2_th_y_vs_xi;
90  std::unique_ptr<TProfile> p_th_y_vs_xi;
91 
92  std::map<unsigned int, TH1D *> m_h_xi_nTracks;
93  std::unique_ptr<TH1D> h_xi_n1f1;
94 
96  : h_multiplicity(new TH1D("", ";reconstructed protons", 11, -0.5, 10.5)),
97  h_xi(new TH1D("", ";#xi", 100, 0., 0.3)),
98  h2_th_y_vs_xi(new TH2D("", ";#xi;#theta_{y} (rad)", 100, 0., 0.3, 100, -500E-6, +500E-6)),
99  p_th_y_vs_xi(new TProfile("", ";#xi;#theta_{y} (rad)", 100, 0., 0.3)),
100  h_xi_n1f1(new TH1D("", ";#xi", 100, 0., 0.3)) {
101  for (unsigned int n = 2; n <= 10; ++n)
102  m_h_xi_nTracks[n] = new TH1D(*h_xi);
103  }
104 
105  void fill(const reco::ForwardProton &p, unsigned int nTracks, bool n1f1) {
106  if (p.validFit()) {
107  h_xi->Fill(p.xi());
108 
109  const double th_y = p.thetaY();
110  h2_th_y_vs_xi->Fill(p.xi(), th_y);
111  p_th_y_vs_xi->Fill(p.xi(), th_y);
112 
113  auto it = m_h_xi_nTracks.find(nTracks);
114  if (it != m_h_xi_nTracks.end())
115  it->second->Fill(p.xi());
116 
117  if (n1f1)
118  h_xi_n1f1->Fill(p.xi());
119  }
120  }
121 
122  void write() const {
123  h_multiplicity->Write("h_multiplicity");
124  h_xi->Write("h_xi");
125 
126  h2_th_y_vs_xi->Write("h2_th_y_vs_xi");
127  p_th_y_vs_xi->Write("p_th_y_vs_xi");
128 
129  TDirectory *d_top = gDirectory;
130 
131  gDirectory = d_top->mkdir("h_xi_nTracks");
132  for (const auto p : m_h_xi_nTracks) {
133  char buf[100];
134  sprintf(buf, "h_xi_nTracks_%u", p.first);
135  p.second->Write(buf);
136  }
137 
138  gDirectory = d_top;
139 
140  h_xi_n1f1->Write("h_xi_n1f1");
141  }
142  };
143 
144  std::map<unsigned int, SingleRPPlots> singleRPPlots_;
145 
146  struct MultiRPPlots {
147  std::unique_ptr<TH1D> h_multiplicity;
149  std::unique_ptr<TH1D> h_t_xi_range1, h_t_xi_range2, h_t_xi_range3;
150  std::unique_ptr<TH1D> h_time, h_time_unc;
151  std::unique_ptr<TProfile> p_time_unc_vs_x_ClCo, p_time_unc_vs_xi;
154  std::unique_ptr<TProfile> p_th_x_vs_xi, p_th_y_vs_xi, p_vtx_y_vs_xi;
155 
156  std::unique_ptr<TH2D> h2_timing_tracks_vs_prot_mult;
157 
158  std::map<unsigned int, TH1D *> m_h_xi_nTracks;
159  std::unique_ptr<TH1D> h_xi_n1f1;
160 
161  std::unique_ptr<TH2D> h2_x_timing_vs_x_tracking_ClCo;
162 
166 
168 
170  : h_multiplicity(new TH1D("", ";reconstructed protons per event", 11, -0.5, 10.5)),
171  h_xi(new TH1D("", ";#xi", 100, 0., 0.3)),
172  h_th_x(new TH1D("", ";#theta_{x} (rad)", 250, -500E-6, +500E-6)),
173  h_th_y(new TH1D("", ";#theta_{y} (rad)", 500, -1000E-6, +1000E-6)),
174  h_vtx_y(new TH1D("", ";vtx_{y} (cm)", 100, -100E-3, +100E-3)),
175  h_chi_sq(new TH1D("", ";#chi^{2}", 100, 0., 10.)),
176  h_log_chi_sq(new TH1D("", ";log_{10} #chi^{2}", 100, -20., 5.)),
177  h_chi_sq_norm(new TH1D("", ";#chi^{2}/ndf", 100, 0., 5.)),
178  h_time(new TH1D("", ";time (ns)", 100, -2., +2.)),
179  h_time_unc(new TH1D("", ";time unc (ns)", 100, -1., +1.)),
180  p_time_unc_vs_x_ClCo(new TProfile("", ";x_tracking (mm);time unc (ns)", 100, 0., 30.)),
181  p_time_unc_vs_xi(new TProfile("", ";xi;time unc (ns)", 100, 0., 0.3)),
182  h_n_contrib_tracking_tracks(new TH1D("", ";n of contrib. tracking tracks per reco proton", 4, -0.5, +3.5)),
183  h_n_contrib_timing_tracks(new TH1D("", ";n of contrib. timing tracks per reco proton", 4, -0.5, +3.5)),
184  h2_th_x_vs_xi(new TH2D("", ";#xi;#theta_{x} (rad)", 100, 0., 0.3, 100, -500E-6, +500E-6)),
185  h2_th_y_vs_xi(new TH2D("", ";#xi;#theta_{y} (rad)", 100, 0., 0.3, 100, -500E-6, +500E-6)),
186  h2_vtx_y_vs_xi(new TH2D("", ";#xi;vtx_{y} (cm)", 100, 0., 0.3, 100, -100E-3, +100E-3)),
187  p_th_x_vs_xi(new TProfile("", ";#xi;#theta_{x} (rad)", 100, 0., 0.3)),
188  p_th_y_vs_xi(new TProfile("", ";#xi;#theta_{y} (rad)", 100, 0., 0.3)),
189  p_vtx_y_vs_xi(new TProfile("", ";#xi;vtx_{y} (cm)", 100, 0., 0.3)),
191  new TH2D("", ";reco protons per event;timing tracks per event", 11, -0.5, 10.5, 11, -0.5, 10.5)),
192  h_xi_n1f1(new TH1D("", ";#xi", 100, 0., 0.3)),
193 
195  new TH2D("", ";x_tracking (mm);x_timing (mm)", 100, 0., 20., 100, 0., 20.)),
196  h_de_x_timing_vs_tracking(new TH1D("", ";#Delta x (mm)", 200, -1., +1.)),
197  h_de_x_rel_timing_vs_tracking(new TH1D("", ";#Delta x / #sigma(x)", 200, -20., +20.)),
198  h_de_x_match_timing_vs_tracking(new TH1D("", ";match between tracking and timing tracks", 2, -0.5, +1.5)),
199  h_de_x_timing_vs_tracking_ClCo(new TH1D("", ";#Delta x (mm)", 200, -1., +1.)),
200  h_de_x_rel_timing_vs_tracking_ClCo(new TH1D("", ";#Delta x / #sigma(x)", 200, -20., +20.)),
202  new TH1D("", ";match between tracking and timing tracks", 2, -0.5, +1.5)),
203 
204  h2_y_vs_x_tt0_ClCo(new TH2D("", ";x (mm);y (mm)", 100, -5., 25., 100, -15., +15.)),
205  h2_y_vs_x_tt1_ClCo(new TH2D("", ";x (mm);y (mm)", 100, -5., 25., 100, -15., +15.)),
206  h2_y_vs_x_ttm_ClCo(new TH2D("", ";x (mm);y (mm)", 100, -5., 25., 100, -15., +15.)) {
207  std::vector<double> v_t_bin_edges;
208  for (double t = 0; t <= 5.;) {
209  v_t_bin_edges.push_back(t);
210  const double de_t = 0.05 + 0.09 * t + 0.02 * t * t;
211  t += de_t;
212  }
213  h_t_unif = std::make_unique<TH1D>("", ";|t| (GeV^2)", 100, 0., 5.);
214  h_t = std::make_unique<TH1D>("", ";|t| (GeV^2)", v_t_bin_edges.size() - 1, v_t_bin_edges.data());
215  h_t_xi_range1 = std::make_unique<TH1D>("", ";|t| (GeV^2)", v_t_bin_edges.size() - 1, v_t_bin_edges.data());
216  h_t_xi_range2 = std::make_unique<TH1D>("", ";|t| (GeV^2)", v_t_bin_edges.size() - 1, v_t_bin_edges.data());
217  h_t_xi_range3 = std::make_unique<TH1D>("", ";|t| (GeV^2)", v_t_bin_edges.size() - 1, v_t_bin_edges.data());
218  h2_t_vs_xi = std::make_unique<TH2D>(
219  "", ";#xi;|t| (GeV^2)", 100, 0., 0.3, v_t_bin_edges.size() - 1, v_t_bin_edges.data());
220 
221  for (unsigned int n = 2; n <= 10; ++n)
222  m_h_xi_nTracks[n] = new TH1D(*h_xi);
223  }
224 
225  void fill(const reco::ForwardProton &p, unsigned int nTracks, bool n1f1) {
226  if (!p.validFit())
227  return;
228 
229  unsigned int n_contrib_tracking_tracks = 0, n_contrib_timing_tracks = 0;
230  for (const auto &tr : p.contributingLocalTracks()) {
231  CTPPSDetId detId(tr->rpId());
232  if (detId.subdetId() == CTPPSDetId::sdTrackingStrip || detId.subdetId() == CTPPSDetId::sdTrackingPixel)
233  n_contrib_tracking_tracks++;
234  if (detId.subdetId() == CTPPSDetId::sdTimingDiamond || detId.subdetId() == CTPPSDetId::sdTimingFastSilicon)
235  n_contrib_timing_tracks++;
236  }
237 
238  const double th_x = p.thetaX();
239  const double th_y = p.thetaY();
240  const double mt = -p.t();
241 
242  h_chi_sq->Fill(p.chi2());
243  h_log_chi_sq->Fill(log10(p.chi2()));
244  if (p.ndof() > 0)
245  h_chi_sq_norm->Fill(p.normalizedChi2());
246 
247  h_n_contrib_tracking_tracks->Fill(n_contrib_tracking_tracks);
248  h_n_contrib_timing_tracks->Fill(n_contrib_timing_tracks);
249 
250  h_xi->Fill(p.xi());
251 
252  h_th_x->Fill(th_x);
253  h_th_y->Fill(th_y);
254 
255  h_vtx_y->Fill(p.vertex().y());
256 
257  h_t_unif->Fill(mt);
258  h_t->Fill(mt);
259  if (p.xi() > 0.04 && p.xi() < 0.07)
260  h_t_xi_range1->Fill(mt);
261  if (p.xi() > 0.07 && p.xi() < 0.10)
262  h_t_xi_range2->Fill(mt);
263  if (p.xi() > 0.10 && p.xi() < 0.13)
264  h_t_xi_range3->Fill(mt);
265 
266  if (p.timeError() > 0.) {
267  h_time->Fill(p.time());
268  h_time_unc->Fill(p.timeError());
269  //p_time_unc_vs_x_ClCo filled in ClCo code below
270  p_time_unc_vs_xi->Fill(p.xi(), p.timeError());
271  }
272 
273  h2_th_x_vs_xi->Fill(p.xi(), th_x);
274  h2_th_y_vs_xi->Fill(p.xi(), th_y);
275  h2_vtx_y_vs_xi->Fill(p.xi(), p.vertex().y());
276  h2_t_vs_xi->Fill(p.xi(), mt);
277 
278  p_th_x_vs_xi->Fill(p.xi(), th_x);
279  p_th_y_vs_xi->Fill(p.xi(), th_y);
280  p_vtx_y_vs_xi->Fill(p.xi(), p.vertex().y());
281 
282  auto it = m_h_xi_nTracks.find(nTracks);
283  if (it != m_h_xi_nTracks.end())
284  it->second->Fill(p.xi());
285 
286  if (n1f1)
287  h_xi_n1f1->Fill(p.xi());
288  }
289 
290  void write() const {
291  h_multiplicity->Write("h_multiplicity");
292 
293  h_chi_sq->Write("h_chi_sq");
294  h_log_chi_sq->Write("h_log_chi_sq");
295  h_chi_sq_norm->Write("h_chi_sq_norm");
296 
297  h_n_contrib_tracking_tracks->Write("h_n_contrib_tracking_tracks");
298  h_n_contrib_timing_tracks->Write("h_n_contrib_timing_tracks");
299 
300  h2_timing_tracks_vs_prot_mult->Write("h2_timing_tracks_vs_prot_mult");
301 
302  h_xi->Write("h_xi");
303 
304  h_th_x->Write("h_th_x");
305  h2_th_x_vs_xi->Write("h2_th_x_vs_xi");
306  p_th_x_vs_xi->Write("p_th_x_vs_xi");
307  auto g_th_x_RMS_vs_xi = std::make_unique<TGraphErrors>();
308  profileToRMSGraph(p_th_x_vs_xi.get(), g_th_x_RMS_vs_xi.get());
309  g_th_x_RMS_vs_xi->Write("g_th_x_RMS_vs_xi");
310 
311  h_th_y->Write("h_th_y");
312  h2_th_y_vs_xi->Write("h2_th_y_vs_xi");
313  p_th_y_vs_xi->Write("p_th_y_vs_xi");
314  auto g_th_y_RMS_vs_xi = std::make_unique<TGraphErrors>();
315  profileToRMSGraph(p_th_y_vs_xi.get(), g_th_y_RMS_vs_xi.get());
316  g_th_y_RMS_vs_xi->Write("g_th_y_RMS_vs_xi");
317 
318  h_vtx_y->Write("h_vtx_y");
319  h2_vtx_y_vs_xi->Write("h2_vtx_y_vs_xi");
320  p_vtx_y_vs_xi->Write("p_vtx_y_vs_xi");
321  auto g_vtx_y_RMS_vs_xi = std::make_unique<TGraphErrors>();
322  profileToRMSGraph(p_vtx_y_vs_xi.get(), g_vtx_y_RMS_vs_xi.get());
323  g_vtx_y_RMS_vs_xi->Write("g_vtx_y_RMS_vs_xi");
324 
325  h_t->Scale(1., "width");
326 
327  h_t_unif->Write("h_t_unif");
328  h_t->Write("h_t");
329  h_t_xi_range1->Write("h_t_xi_range1");
330  h_t_xi_range2->Write("h_t_xi_range2");
331  h_t_xi_range3->Write("h_t_xi_range3");
332 
333  h2_t_vs_xi->Write("h2_t_vs_xi");
334 
335  h_time->Write("h_time");
336  h_time_unc->Write("h_time_unc");
337  p_time_unc_vs_x_ClCo->Write("p_time_unc_vs_x_ClCo");
338  p_time_unc_vs_xi->Write("p_time_unc_vs_xi");
339 
340  TDirectory *d_top = gDirectory;
341 
342  gDirectory = d_top->mkdir("h_xi_nTracks");
343  for (const auto p : m_h_xi_nTracks) {
344  char buf[100];
345  sprintf(buf, "h_xi_nTracks_%u", p.first);
346  p.second->Write(buf);
347  }
348 
349  gDirectory = d_top;
350 
351  h_xi_n1f1->Write("h_xi_n1f1");
352 
353  h2_x_timing_vs_x_tracking_ClCo->Write("h2_x_timing_vs_x_tracking_ClCo");
354 
355  h_de_x_timing_vs_tracking->Write("h_de_x_timing_vs_tracking");
356  h_de_x_rel_timing_vs_tracking->Write("h_de_x_rel_timing_vs_tracking");
357  h_de_x_match_timing_vs_tracking->Write("h_de_x_match_timing_vs_tracking");
358 
359  h_de_x_timing_vs_tracking_ClCo->Write("h_de_x_timing_vs_tracking_ClCo");
360  h_de_x_rel_timing_vs_tracking_ClCo->Write("h_de_x_rel_timing_vs_tracking_ClCo");
361  h_de_x_match_timing_vs_tracking_ClCo->Write("h_de_x_match_timing_vs_tracking_ClCo");
362 
363  h2_y_vs_x_tt0_ClCo->Write("h2_y_vs_x_tt0_ClCo");
364  h2_y_vs_x_tt1_ClCo->Write("h2_y_vs_x_tt1_ClCo");
365  h2_y_vs_x_ttm_ClCo->Write("h2_y_vs_x_ttm_ClCo");
366  }
367  };
368 
369  std::map<unsigned int, MultiRPPlots> multiRPPlots_;
370 
372  std::unique_ptr<TH2D> h2_xi_mu_vs_xi_si;
373  std::unique_ptr<TH1D> h_xi_diff_mu_si, h_xi_diff_si_mu;
374 
375  std::unique_ptr<TH2D> h2_xi_diff_si_mu_vs_xi_mu;
376  std::unique_ptr<TProfile> p_xi_diff_si_mu_vs_xi_mu;
377 
378  std::unique_ptr<TH2D> h2_th_y_mu_vs_th_y_si;
379 
381  : h2_xi_mu_vs_xi_si(new TH2D("", ";#xi_{single};#xi_{multi}", 100, 0., 0.3, 100, 0., 0.3)),
382  h_xi_diff_mu_si(new TH1D("", ";#xi_{multi} - #xi_{single}", 100, -0.1, +0.1)),
383  h_xi_diff_si_mu(new TH1D("", ";#xi_{single} - #xi_{multi}", 100, -0.1, +0.1)),
385  new TH2D("", ";#xi_{multi};#xi_{single} - #xi_{multi}", 100, 0., 0.3, 100, -0.10, 0.10)),
386  p_xi_diff_si_mu_vs_xi_mu(new TProfile("", ";#xi_{multi};#xi_{single} - #xi_{multi}", 100, 0., 0.3)),
388  new TH2D("", ";#theta^{*}_{y,si};#theta^{*}_{y,mu}", 100, -500E-6, +500E-6, 100, -500E-6, +500E-6)) {}
389 
390  void fill(const reco::ForwardProton &p_single, const reco::ForwardProton &p_multi) {
391  if (p_single.validFit() && p_multi.validFit()) {
392  h2_xi_mu_vs_xi_si->Fill(p_single.xi(), p_multi.xi());
393  h_xi_diff_mu_si->Fill(p_multi.xi() - p_single.xi());
394  h_xi_diff_si_mu->Fill(p_single.xi() - p_multi.xi());
395 
396  h2_xi_diff_si_mu_vs_xi_mu->Fill(p_multi.xi(), p_single.xi() - p_multi.xi());
397  p_xi_diff_si_mu_vs_xi_mu->Fill(p_multi.xi(), p_single.xi() - p_multi.xi());
398 
399  const double th_y_si = p_single.thetaY();
400  const double th_y_mu = p_multi.thetaY();
401 
402  h2_th_y_mu_vs_th_y_si->Fill(th_y_si, th_y_mu);
403  }
404  }
405 
406  void write() const {
407  h2_xi_mu_vs_xi_si->Write("h2_xi_mu_vs_xi_si");
408  h_xi_diff_mu_si->Write("h_xi_diff_mu_si");
409  h_xi_diff_si_mu->Write("h_xi_diff_si_mu");
410 
411  h2_xi_diff_si_mu_vs_xi_mu->Write("h2_xi_diff_si_mu_vs_xi_mu");
412  p_xi_diff_si_mu_vs_xi_mu->Write("p_xi_diff_si_mu_vs_xi_mu");
413 
414  h2_th_y_mu_vs_th_y_si->Write("h2_th_y_mu_vs_th_y_si");
415  }
416  };
417 
418  std::map<unsigned int, SingleMultiCorrelationPlots> singleMultiCorrelationPlots_;
419 
421  std::unique_ptr<TH1D> h_xi_si_diffNF;
422  std::unique_ptr<TH2D> h2_xi_si_diffNF_vs_xi_mu;
423  std::unique_ptr<TProfile> p_xi_si_diffNF_vs_xi_mu;
424 
425  std::unique_ptr<TH1D> h_th_y_si_diffNF;
426  std::unique_ptr<TProfile> p_th_y_si_diffNF_vs_xi_mu;
427 
429  : h_xi_si_diffNF(new TH1D("", ";#xi_{sF} - #xi_{sN}", 100, -0.02, +0.02)),
430  h2_xi_si_diffNF_vs_xi_mu(new TH2D("", ";#xi_{m};#xi_{sF} - #xi_{sN}", 100, 0., 0.3, 100, -0.02, +0.02)),
431  p_xi_si_diffNF_vs_xi_mu(new TProfile("", ";#xi_{m};#xi_{sF} - #xi_{sN}", 100, 0., 0.3)),
432  h_th_y_si_diffNF(new TH1D("", ";#theta_{y,sF} - #theta_{y,sN}", 100, -100E-6, +100E-6)),
433  p_th_y_si_diffNF_vs_xi_mu(new TProfile("", ";#xi_{m};#theta_{y,sF} - #theta_{y,sN}", 100, 0., 0.3)) {}
434 
435  void fill(const reco::ForwardProton &p_s_N, const reco::ForwardProton &p_s_F, const reco::ForwardProton &p_m) {
436  if (!p_s_N.validFit() || !p_s_F.validFit() || !p_m.validFit())
437  return;
438 
439  const double th_y_s_N = p_s_N.thetaY();
440  const double th_y_s_F = p_s_F.thetaY();
441 
442  h_xi_si_diffNF->Fill(p_s_F.xi() - p_s_N.xi());
443  h2_xi_si_diffNF_vs_xi_mu->Fill(p_m.xi(), p_s_F.xi() - p_s_N.xi());
444  p_xi_si_diffNF_vs_xi_mu->Fill(p_m.xi(), p_s_F.xi() - p_s_N.xi());
445 
446  h_th_y_si_diffNF->Fill(th_y_s_F - th_y_s_N);
447  p_th_y_si_diffNF_vs_xi_mu->Fill(p_m.xi(), th_y_s_F - th_y_s_N);
448  }
449 
450  void write() const {
451  h_xi_si_diffNF->Write("h_xi_si_diffNF");
452  h2_xi_si_diffNF_vs_xi_mu->Write("h2_xi_si_diffNF_vs_xi_mu");
453  p_xi_si_diffNF_vs_xi_mu->Write("p_xi_si_diffNF_vs_xi_mu");
454 
455  h_th_y_si_diffNF->Write("h_th_y_si_diffNF");
456  p_th_y_si_diffNF_vs_xi_mu->Write("p_th_y_si_diffNF_vs_xi_mu");
457  }
458  };
459 
460  std::map<unsigned int, ArmCorrelationPlots> armCorrelationPlots_;
461 
462  std::unique_ptr<TProfile> p_x_L_diffNF_vs_x_L_N_, p_x_R_diffNF_vs_x_R_N_;
463  std::unique_ptr<TProfile> p_y_L_diffNF_vs_y_L_N_, p_y_R_diffNF_vs_y_R_N_;
464 
466 };
467 
468 //----------------------------------------------------------------------------------------------------
469 
470 using namespace std;
471 using namespace edm;
472 
473 //----------------------------------------------------------------------------------------------------
474 
476  : tokenTracks_(consumes<CTPPSLocalTrackLiteCollection>(ps.getParameter<edm::InputTag>("tagTracks"))),
477  tokenRecoProtonsSingleRP_(
478  consumes<reco::ForwardProtonCollection>(ps.getParameter<InputTag>("tagRecoProtonsSingleRP"))),
479  tokenRecoProtonsMultiRP_(
480  consumes<reco::ForwardProtonCollection>(ps.getParameter<InputTag>("tagRecoProtonsMultiRP"))),
481  geometryESToken_(esConsumes()),
482  ppsAssociationCutsToken_(esConsumes<PPSAssociationCuts, PPSAssociationCutsRcd>()),
483 
484  rpId_45_N_(ps.getParameter<unsigned int>("rpId_45_N")),
485  rpId_45_F_(ps.getParameter<unsigned int>("rpId_45_F")),
486  rpId_56_N_(ps.getParameter<unsigned int>("rpId_56_N")),
487  rpId_56_F_(ps.getParameter<unsigned int>("rpId_56_F")),
488 
489  outputFile_(ps.getParameter<string>("outputFile")),
490  maxNonEmptyEvents_(ps.getUntrackedParameter<signed int>("maxNonEmptyEvents", -1)),
491 
492  p_x_L_diffNF_vs_x_L_N_(new TProfile("p_x_L_diffNF_vs_x_L_N", ";x_{LN};x_{LF} - x_{LN}", 100, 0., +20.)),
493  p_x_R_diffNF_vs_x_R_N_(new TProfile("p_x_R_diffNF_vs_x_R_N", ";x_{RN};x_{RF} - x_{RN}", 100, 0., +20.)),
494 
495  p_y_L_diffNF_vs_y_L_N_(new TProfile("p_y_L_diffNF_vs_y_L_N", ";y_{LN};y_{LF} - y_{LN}", 100, -20., +20.)),
496  p_y_R_diffNF_vs_y_R_N_(new TProfile("p_y_R_diffNF_vs_y_R_N", ";y_{RN};y_{RF} - y_{RN}", 100, -20., +20.)),
497 
498  n_non_empty_events_(0) {}
499 
500 //----------------------------------------------------------------------------------------------------
501 
503  const CTPPSLocalTrackLite &tr_ti,
504  const CTPPSGeometry &geometry,
505  double &x_tr,
506  double &x_ti,
507  double &de_x,
508  double &de_x_unc) {
509  // identify tracking-RP tracks
510  const auto &tr_i = *proton.contributingLocalTracks().at(0);
511  const auto &tr_j = *proton.contributingLocalTracks().at(1);
512 
513  const double z_i = geometry.rpTranslation(tr_i.rpId()).z();
514  const double z_j = geometry.rpTranslation(tr_j.rpId()).z();
515 
516  // interpolation from tracking RPs
517  const double z_ti = -geometry.rpTranslation(tr_ti.rpId()).z(); // the minus sign fixes a bug in the diamond geometry
518  const double f_i = (z_ti - z_j) / (z_i - z_j), f_j = (z_i - z_ti) / (z_i - z_j);
519  const double x_inter = f_i * tr_i.x() + f_j * tr_j.x();
520  const double x_inter_unc_sq = f_i * f_i * tr_i.xUnc() * tr_i.xUnc() + f_j * f_j * tr_j.xUnc() * tr_j.xUnc();
521 
522  // save distance
523  x_tr = x_inter;
524  x_ti = tr_ti.x();
525 
526  de_x = tr_ti.x() - x_inter;
527  de_x_unc = sqrt(tr_ti.xUnc() * tr_ti.xUnc() + x_inter_unc_sq);
528 }
529 
530 //----------------------------------------------------------------------------------------------------
531 
533  // get input
535  event.getByToken(tokenTracks_, hTracks);
536 
537  Handle<reco::ForwardProtonCollection> hRecoProtonsSingleRP;
538  event.getByToken(tokenRecoProtonsSingleRP_, hRecoProtonsSingleRP);
539 
540  Handle<reco::ForwardProtonCollection> hRecoProtonsMultiRP;
541  event.getByToken(tokenRecoProtonsMultiRP_, hRecoProtonsMultiRP);
542 
543  if (!hRecoProtonsSingleRP->empty())
545 
547  throw cms::Exception("CTPPSProtonReconstructionPlotter") << "Number of non empty events reached maximum.";
548 
549  // get conditions
550  const auto &geometry = iSetup.getData(geometryESToken_);
552 
553  // track plots
554  const CTPPSLocalTrackLite *tr_L_N = nullptr;
555  const CTPPSLocalTrackLite *tr_L_F = nullptr;
556  const CTPPSLocalTrackLite *tr_R_N = nullptr;
557  const CTPPSLocalTrackLite *tr_R_F = nullptr;
558  std::map<unsigned int, unsigned int> armTrackCounter, armTimingTrackCounter;
559  std::map<unsigned int, unsigned int> armTrackCounter_N, armTrackCounter_F;
560 
561  for (const auto &tr : *hTracks) {
562  CTPPSDetId rpId(tr.rpId());
563  unsigned int decRPId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
564 
565  if (decRPId == rpId_45_N_) {
566  tr_L_N = &tr;
567  armTrackCounter_N[0]++;
568  }
569  if (decRPId == rpId_45_F_) {
570  tr_L_F = &tr;
571  armTrackCounter_F[0]++;
572  }
573  if (decRPId == rpId_56_N_) {
574  tr_R_N = &tr;
575  armTrackCounter_N[1]++;
576  }
577  if (decRPId == rpId_56_F_) {
578  tr_R_F = &tr;
579  armTrackCounter_F[1]++;
580  }
581 
582  armTrackCounter[rpId.arm()]++;
583 
584  const bool trackerRP =
585  (rpId.subdetId() == CTPPSDetId::sdTrackingStrip || rpId.subdetId() == CTPPSDetId::sdTrackingPixel);
586  if (!trackerRP)
587  armTimingTrackCounter[rpId.arm()]++;
588  }
589 
590  if (tr_L_N && tr_L_F) {
591  p_x_L_diffNF_vs_x_L_N_->Fill(tr_L_N->x(), tr_L_F->x() - tr_L_N->x());
592  p_y_L_diffNF_vs_y_L_N_->Fill(tr_L_N->y(), tr_L_F->y() - tr_L_N->y());
593  }
594 
595  if (tr_R_N && tr_R_F) {
596  p_x_R_diffNF_vs_x_R_N_->Fill(tr_R_N->x(), tr_R_F->x() - tr_R_N->x());
597  p_y_R_diffNF_vs_y_R_N_->Fill(tr_R_N->y(), tr_R_F->y() - tr_R_N->y());
598  }
599 
600  // initialise multiplicity counters
601  std::map<unsigned int, unsigned int> singleRPMultiplicity, multiRPMultiplicity;
602  singleRPMultiplicity[rpId_45_N_] = singleRPMultiplicity[rpId_45_F_] = singleRPMultiplicity[rpId_56_N_] =
603  singleRPMultiplicity[rpId_56_F_] = 0;
604  multiRPMultiplicity[0] = multiRPMultiplicity[1] = 0;
605 
606  // make single-RP-reco plots
607  for (const auto &proton : *hRecoProtonsSingleRP) {
608  // workaround for https://github.com/cms-sw/cmssw/issues/44931#issuecomment-2142898754
609  const auto &pcLTiter = *proton.contributingLocalTracks().begin();
610  assert(pcLTiter.isNonnull());
611  CTPPSDetId rpId(pcLTiter->rpId());
612  unsigned int decRPId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
613 
614  const bool n1f1 = (armTrackCounter_N[rpId.arm()] == 1 && armTrackCounter_F[rpId.arm()] == 1);
615 
616  singleRPPlots_[decRPId].fill(proton, armTrackCounter[rpId.arm()], n1f1);
617 
618  if (proton.validFit())
619  singleRPMultiplicity[decRPId]++;
620  }
621 
622  for (const auto it : singleRPMultiplicity)
623  singleRPPlots_[it.first].h_multiplicity->Fill(it.second);
624 
625  // make multi-RP-reco plots
626  for (const auto &proton : *hRecoProtonsMultiRP) {
627  CTPPSDetId rpId((*proton.contributingLocalTracks().begin())->rpId());
628  unsigned int armId = rpId.arm();
629 
630  const bool n1f1 = (armTrackCounter_N[armId] == 1 && armTrackCounter_F[armId] == 1);
631 
632  multiRPPlots_[armId].fill(proton, armTrackCounter[armId], n1f1);
633 
634  if (proton.validFit())
635  multiRPMultiplicity[armId]++;
636  }
637 
638  for (const auto it : multiRPMultiplicity) {
639  const auto &pl = multiRPPlots_[it.first];
640  pl.h_multiplicity->Fill(it.second);
641  pl.h2_timing_tracks_vs_prot_mult->Fill(it.second, armTimingTrackCounter[it.first]);
642  }
643 
644  // define "clean condition" for each arm
645  map<unsigned int, bool> clCo;
646  clCo[0] = (singleRPMultiplicity[rpId_45_N_] && singleRPMultiplicity[rpId_45_F_] && multiRPMultiplicity[0] == 1);
647  clCo[1] = (singleRPMultiplicity[rpId_56_N_] && singleRPMultiplicity[rpId_56_F_] && multiRPMultiplicity[1] == 1);
648 
649  // plot distances between multi-RP protons and timing tracks in the same arm
650  for (const auto &proton : *hRecoProtonsMultiRP) {
651  if (!proton.validFit())
652  continue;
653 
654  CTPPSDetId rpId_proton((*proton.contributingLocalTracks().begin())->rpId());
655  unsigned int armId = rpId_proton.arm();
656  const auto &pl = multiRPPlots_[armId];
657 
658  for (const auto &tr : *hTracks) {
659  CTPPSDetId rpId_tr(tr.rpId());
660  if (rpId_tr.arm() != armId)
661  continue;
662 
663  const bool trackerRP =
664  (rpId_tr.subdetId() == CTPPSDetId::sdTrackingStrip || rpId_tr.subdetId() == CTPPSDetId::sdTrackingPixel);
665  if (trackerRP)
666  continue;
667 
668  double x_tr = -1., x_ti = -1.;
669  double de_x = 0., de_x_unc = 0.;
670  CalculateTimingTrackingDistance(proton, tr, geometry, x_tr, x_ti, de_x, de_x_unc);
671 
672  const double rd = (de_x_unc > 0.) ? de_x / de_x_unc : -1E10;
673  const auto &ac = ppsAssociationCuts->getAssociationCuts(armId);
674  const bool match = (ac.getTiTrMin() <= fabs(rd) && fabs(rd) <= ac.getTiTrMax());
675 
676  pl.h_de_x_timing_vs_tracking->Fill(de_x);
677  pl.h_de_x_rel_timing_vs_tracking->Fill(rd);
678  pl.h_de_x_match_timing_vs_tracking->Fill(match ? 1. : 0.);
679 
680  if (clCo[armId] && armTimingTrackCounter[armId] == 1) {
681  pl.h2_x_timing_vs_x_tracking_ClCo->Fill(x_tr, x_ti);
682 
683  pl.h_de_x_timing_vs_tracking_ClCo->Fill(de_x);
684  pl.h_de_x_rel_timing_vs_tracking_ClCo->Fill(rd);
685  pl.h_de_x_match_timing_vs_tracking_ClCo->Fill(match ? 1. : 0.);
686 
687  pl.p_time_unc_vs_x_ClCo->Fill(x_tr, proton.timeError());
688  }
689  }
690  }
691 
692  // plot xy maps
693  for (const auto &proton : *hRecoProtonsMultiRP) {
694  if (!proton.validFit())
695  continue;
696 
697  CTPPSDetId rpId((*proton.contributingLocalTracks().begin())->rpId());
698  unsigned int armId = rpId.arm();
699  const auto &pl = multiRPPlots_[armId];
700  const auto &nTimingTracks = armTimingTrackCounter[armId];
701 
702  if (!clCo[armId])
703  continue;
704 
705  double x_ref = 0., y_ref = 0.;
706  if (armId == 0) {
707  x_ref = tr_L_N->x();
708  y_ref = tr_L_N->y();
709  }
710  if (armId == 1) {
711  x_ref = tr_R_N->x();
712  y_ref = tr_R_N->y();
713  }
714 
715  if (nTimingTracks == 0)
716  pl.h2_y_vs_x_tt0_ClCo->Fill(x_ref, y_ref);
717  if (nTimingTracks == 1)
718  pl.h2_y_vs_x_tt1_ClCo->Fill(x_ref, y_ref);
719  if (nTimingTracks > 1)
720  pl.h2_y_vs_x_ttm_ClCo->Fill(x_ref, y_ref);
721  }
722 
723  // make correlation plots
724  for (const auto &proton_m : *hRecoProtonsMultiRP) {
725  CTPPSDetId rpId_m((*proton_m.contributingLocalTracks().begin())->rpId());
726  unsigned int arm = rpId_m.arm();
727 
728  const reco::ForwardProton *p_s_N = nullptr, *p_s_F = nullptr;
729 
730  for (const auto &proton_s : *hRecoProtonsSingleRP) {
731  // skip if source of single-RP reco not included in multi-RP reco
732  const auto key_s = proton_s.contributingLocalTracks()[0].key();
733  bool compatible = false;
734  for (const auto &tr_m : proton_m.contributingLocalTracks()) {
735  if (tr_m.key() == key_s) {
736  compatible = true;
737  break;
738  }
739  }
740 
741  if (!compatible)
742  continue;
743 
744  // fill single-multi plots
745  CTPPSDetId rpId_s((*proton_s.contributingLocalTracks().begin())->rpId());
746  const unsigned int idx = rpId_s.arm() * 1000 + rpId_s.station() * 100 + rpId_s.rp() * 10 + rpId_s.arm();
747  singleMultiCorrelationPlots_[idx].fill(proton_s, proton_m);
748 
749  // select protons for arm-correlation plots
750  const unsigned int rpDecId_s = rpId_s.arm() * 100 + rpId_s.station() * 10 + rpId_s.rp();
751  if (rpDecId_s == rpId_45_N_ || rpDecId_s == rpId_56_N_)
752  p_s_N = &proton_s;
753  if (rpDecId_s == rpId_45_F_ || rpDecId_s == rpId_56_F_)
754  p_s_F = &proton_s;
755  }
756 
757  // fill arm-correlation plots
758  if (p_s_N && p_s_F)
759  armCorrelationPlots_[arm].fill(*p_s_N, *p_s_F, proton_m);
760  }
761 }
762 
763 //----------------------------------------------------------------------------------------------------
764 
766  LogInfo("CTPPSProtonReconstructionPlotter") << "n_non_empty_events = " << n_non_empty_events_;
767 
768  auto f_out = std::make_unique<TFile>(outputFile_.c_str(), "recreate");
769 
770  p_x_L_diffNF_vs_x_L_N_->Write();
771  p_x_R_diffNF_vs_x_R_N_->Write();
772 
773  p_y_L_diffNF_vs_y_L_N_->Write();
774  p_y_R_diffNF_vs_y_R_N_->Write();
775 
776  TDirectory *d_singleRPPlots = f_out->mkdir("singleRPPlots");
777  for (const auto &it : singleRPPlots_) {
778  gDirectory = d_singleRPPlots->mkdir(Form("rp%u", it.first));
779  it.second.write();
780  }
781 
782  TDirectory *d_multiRPPlots = f_out->mkdir("multiRPPlots");
783  for (const auto &it : multiRPPlots_) {
784  gDirectory = d_multiRPPlots->mkdir(Form("arm%u", it.first));
785  it.second.write();
786  }
787 
788  TDirectory *d_singleMultiCorrelationPlots = f_out->mkdir("singleMultiCorrelationPlots");
789  for (const auto &it : singleMultiCorrelationPlots_) {
790  unsigned int si_rp = it.first / 10;
791  unsigned int mu_arm = it.first % 10;
792 
793  gDirectory = d_singleMultiCorrelationPlots->mkdir(Form("si_rp%u_mu_arm%u", si_rp, mu_arm));
794  it.second.write();
795  }
796 
797  TDirectory *d_armCorrelationPlots = f_out->mkdir("armCorrelationPlots");
798  for (const auto &it : armCorrelationPlots_) {
799  gDirectory = d_armCorrelationPlots->mkdir(Form("arm%u", it.first));
800  it.second.write();
801  }
802 }
803 
804 //----------------------------------------------------------------------------------------------------
805 
static void profileToRMSGraph(TProfile *p, TGraphErrors *g)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
std::map< unsigned int, MultiRPPlots > multiRPPlots_
edm::EDGetTokenT< reco::ForwardProtonCollection > tokenRecoProtonsSingleRP_
const CTPPSLocalTrackLiteRefVector & contributingLocalTracks() const
list of RP tracks that contributed to this global track
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
std::map< unsigned int, SingleRPPlots > singleRPPlots_
Local (=single RP) track with essential information only.
uint32_t arm() const
Definition: CTPPSDetId.h:57
void analyze(const edm::Event &, const edm::EventSetup &) override
float thetaY() const
horizontal scattering angle, in rad
Definition: ForwardProton.h:83
edm::ESGetToken< PPSAssociationCuts, PPSAssociationCutsRcd > ppsAssociationCutsToken_
edm::ESGetToken< CTPPSGeometry, VeryForwardRealGeometryRecord > geometryESToken_
edm::EDGetTokenT< CTPPSLocalTrackLiteCollection > tokenTracks_
value_type const at(size_type idx) const
Retrieve an element of the RefVector.
Definition: RefVector.h:83
float y() const
returns the vertical track position
assert(be >=bs)
void fill(const reco::ForwardProton &p_single, const reco::ForwardProton &p_multi)
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 CutsPerArm & getAssociationCuts(const int sector) const
float x() const
returns the horizontal track position
T sqrt(T t)
Definition: SSEVec.h:23
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
float xi() const
longitudinal fractional momentum loss
Definition: ForwardProton.h:79
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:130
std::map< unsigned int, ArmCorrelationPlots > armCorrelationPlots_
The manager class for TOTEM RP geometry.
Definition: CTPPSGeometry.h:30
Log< level::Info, false > LogInfo
bool validFit() const
flag for the fit validity
#define N
Definition: blowfish.cc:9
std::vector< CTPPSLocalTrackLite > CTPPSLocalTrackLiteCollection
Collection of CTPPSLocalTrackLite objects.
Base class for CTPPS detector IDs.
Definition: CTPPSDetId.h:32
void CalculateTimingTrackingDistance(const reco::ForwardProton &proton, const CTPPSLocalTrackLite &tr, const CTPPSGeometry &geometry, double &x_tr, double &x_ti, double &de_x, double &de_x_unc)
float xUnc() const
returns the horizontal track position uncertainty
fixed size matrix
HLT enums.
CTPPSProtonReconstructionPlotter(const edm::ParameterSet &)
std::map< unsigned int, SingleMultiCorrelationPlots > singleMultiCorrelationPlots_
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
uint32_t rpId() const
returns the RP id
std::vector< ForwardProton > ForwardProtonCollection
Collection of ForwardProton objects.
void fill(const reco::ForwardProton &p_s_N, const reco::ForwardProton &p_s_F, const reco::ForwardProton &p_m)
edm::EDGetTokenT< reco::ForwardProtonCollection > tokenRecoProtonsMultiRP_
Definition: event.py:1
void fill(const reco::ForwardProton &p, unsigned int nTracks, bool n1f1)
void fill(const reco::ForwardProton &p, unsigned int nTracks, bool n1f1)