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  CTPPSDetId rpId((*proton.contributingLocalTracks().begin())->rpId());
609  unsigned int decRPId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
610 
611  const bool n1f1 = (armTrackCounter_N[rpId.arm()] == 1 && armTrackCounter_F[rpId.arm()] == 1);
612 
613  singleRPPlots_[decRPId].fill(proton, armTrackCounter[rpId.arm()], n1f1);
614 
615  if (proton.validFit())
616  singleRPMultiplicity[decRPId]++;
617  }
618 
619  for (const auto it : singleRPMultiplicity)
620  singleRPPlots_[it.first].h_multiplicity->Fill(it.second);
621 
622  // make multi-RP-reco plots
623  for (const auto &proton : *hRecoProtonsMultiRP) {
624  CTPPSDetId rpId((*proton.contributingLocalTracks().begin())->rpId());
625  unsigned int armId = rpId.arm();
626 
627  const bool n1f1 = (armTrackCounter_N[armId] == 1 && armTrackCounter_F[armId] == 1);
628 
629  multiRPPlots_[armId].fill(proton, armTrackCounter[armId], n1f1);
630 
631  if (proton.validFit())
632  multiRPMultiplicity[armId]++;
633  }
634 
635  for (const auto it : multiRPMultiplicity) {
636  const auto &pl = multiRPPlots_[it.first];
637  pl.h_multiplicity->Fill(it.second);
638  pl.h2_timing_tracks_vs_prot_mult->Fill(it.second, armTimingTrackCounter[it.first]);
639  }
640 
641  // define "clean condition" for each arm
642  map<unsigned int, bool> clCo;
643  clCo[0] = (singleRPMultiplicity[rpId_45_N_] && singleRPMultiplicity[rpId_45_F_] && multiRPMultiplicity[0] == 1);
644  clCo[1] = (singleRPMultiplicity[rpId_56_N_] && singleRPMultiplicity[rpId_56_F_] && multiRPMultiplicity[1] == 1);
645 
646  // plot distances between multi-RP protons and timing tracks in the same arm
647  for (const auto &proton : *hRecoProtonsMultiRP) {
648  if (!proton.validFit())
649  continue;
650 
651  CTPPSDetId rpId_proton((*proton.contributingLocalTracks().begin())->rpId());
652  unsigned int armId = rpId_proton.arm();
653  const auto &pl = multiRPPlots_[armId];
654 
655  for (const auto &tr : *hTracks) {
656  CTPPSDetId rpId_tr(tr.rpId());
657  if (rpId_tr.arm() != armId)
658  continue;
659 
660  const bool trackerRP =
661  (rpId_tr.subdetId() == CTPPSDetId::sdTrackingStrip || rpId_tr.subdetId() == CTPPSDetId::sdTrackingPixel);
662  if (trackerRP)
663  continue;
664 
665  double x_tr = -1., x_ti = -1.;
666  double de_x = 0., de_x_unc = 0.;
667  CalculateTimingTrackingDistance(proton, tr, geometry, x_tr, x_ti, de_x, de_x_unc);
668 
669  const double rd = (de_x_unc > 0.) ? de_x / de_x_unc : -1E10;
670  const auto &ac = ppsAssociationCuts->getAssociationCuts(armId);
671  const bool match = (ac.getTiTrMin() <= fabs(rd) && fabs(rd) <= ac.getTiTrMax());
672 
673  pl.h_de_x_timing_vs_tracking->Fill(de_x);
674  pl.h_de_x_rel_timing_vs_tracking->Fill(rd);
675  pl.h_de_x_match_timing_vs_tracking->Fill(match ? 1. : 0.);
676 
677  if (clCo[armId] && armTimingTrackCounter[armId] == 1) {
678  pl.h2_x_timing_vs_x_tracking_ClCo->Fill(x_tr, x_ti);
679 
680  pl.h_de_x_timing_vs_tracking_ClCo->Fill(de_x);
681  pl.h_de_x_rel_timing_vs_tracking_ClCo->Fill(rd);
682  pl.h_de_x_match_timing_vs_tracking_ClCo->Fill(match ? 1. : 0.);
683 
684  pl.p_time_unc_vs_x_ClCo->Fill(x_tr, proton.timeError());
685  }
686  }
687  }
688 
689  // plot xy maps
690  for (const auto &proton : *hRecoProtonsMultiRP) {
691  if (!proton.validFit())
692  continue;
693 
694  CTPPSDetId rpId((*proton.contributingLocalTracks().begin())->rpId());
695  unsigned int armId = rpId.arm();
696  const auto &pl = multiRPPlots_[armId];
697  const auto &nTimingTracks = armTimingTrackCounter[armId];
698 
699  if (!clCo[armId])
700  continue;
701 
702  double x_ref = 0., y_ref = 0.;
703  if (armId == 0) {
704  x_ref = tr_L_N->x();
705  y_ref = tr_L_N->y();
706  }
707  if (armId == 1) {
708  x_ref = tr_R_N->x();
709  y_ref = tr_R_N->y();
710  }
711 
712  if (nTimingTracks == 0)
713  pl.h2_y_vs_x_tt0_ClCo->Fill(x_ref, y_ref);
714  if (nTimingTracks == 1)
715  pl.h2_y_vs_x_tt1_ClCo->Fill(x_ref, y_ref);
716  if (nTimingTracks > 1)
717  pl.h2_y_vs_x_ttm_ClCo->Fill(x_ref, y_ref);
718  }
719 
720  // make correlation plots
721  for (const auto &proton_m : *hRecoProtonsMultiRP) {
722  CTPPSDetId rpId_m((*proton_m.contributingLocalTracks().begin())->rpId());
723  unsigned int arm = rpId_m.arm();
724 
725  const reco::ForwardProton *p_s_N = nullptr, *p_s_F = nullptr;
726 
727  for (const auto &proton_s : *hRecoProtonsSingleRP) {
728  // skip if source of single-RP reco not included in multi-RP reco
729  const auto key_s = proton_s.contributingLocalTracks()[0].key();
730  bool compatible = false;
731  for (const auto &tr_m : proton_m.contributingLocalTracks()) {
732  if (tr_m.key() == key_s) {
733  compatible = true;
734  break;
735  }
736  }
737 
738  if (!compatible)
739  continue;
740 
741  // fill single-multi plots
742  CTPPSDetId rpId_s((*proton_s.contributingLocalTracks().begin())->rpId());
743  const unsigned int idx = rpId_s.arm() * 1000 + rpId_s.station() * 100 + rpId_s.rp() * 10 + rpId_s.arm();
744  singleMultiCorrelationPlots_[idx].fill(proton_s, proton_m);
745 
746  // select protons for arm-correlation plots
747  const unsigned int rpDecId_s = rpId_s.arm() * 100 + rpId_s.station() * 10 + rpId_s.rp();
748  if (rpDecId_s == rpId_45_N_ || rpDecId_s == rpId_56_N_)
749  p_s_N = &proton_s;
750  if (rpDecId_s == rpId_45_F_ || rpDecId_s == rpId_56_F_)
751  p_s_F = &proton_s;
752  }
753 
754  // fill arm-correlation plots
755  if (p_s_N && p_s_F)
756  armCorrelationPlots_[arm].fill(*p_s_N, *p_s_F, proton_m);
757  }
758 }
759 
760 //----------------------------------------------------------------------------------------------------
761 
763  LogInfo("CTPPSProtonReconstructionPlotter") << "n_non_empty_events = " << n_non_empty_events_;
764 
765  auto f_out = std::make_unique<TFile>(outputFile_.c_str(), "recreate");
766 
767  p_x_L_diffNF_vs_x_L_N_->Write();
768  p_x_R_diffNF_vs_x_R_N_->Write();
769 
770  p_y_L_diffNF_vs_y_L_N_->Write();
771  p_y_R_diffNF_vs_y_R_N_->Write();
772 
773  TDirectory *d_singleRPPlots = f_out->mkdir("singleRPPlots");
774  for (const auto &it : singleRPPlots_) {
775  gDirectory = d_singleRPPlots->mkdir(Form("rp%u", it.first));
776  it.second.write();
777  }
778 
779  TDirectory *d_multiRPPlots = f_out->mkdir("multiRPPlots");
780  for (const auto &it : multiRPPlots_) {
781  gDirectory = d_multiRPPlots->mkdir(Form("arm%u", it.first));
782  it.second.write();
783  }
784 
785  TDirectory *d_singleMultiCorrelationPlots = f_out->mkdir("singleMultiCorrelationPlots");
786  for (const auto &it : singleMultiCorrelationPlots_) {
787  unsigned int si_rp = it.first / 10;
788  unsigned int mu_arm = it.first % 10;
789 
790  gDirectory = d_singleMultiCorrelationPlots->mkdir(Form("si_rp%u_mu_arm%u", si_rp, mu_arm));
791  it.second.write();
792  }
793 
794  TDirectory *d_armCorrelationPlots = f_out->mkdir("armCorrelationPlots");
795  for (const auto &it : armCorrelationPlots_) {
796  gDirectory = d_armCorrelationPlots->mkdir(Form("arm%u", it.first));
797  it.second.write();
798  }
799 }
800 
801 //----------------------------------------------------------------------------------------------------
802 
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
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:19
#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)