CMS 3D CMS Logo

PrimaryVertexAnalyzer4PUSlimmed.cc
Go to the documentation of this file.
2 
7 
8 // reco track and vertex
11 
12 // TrackingParticle
15 
16 // associator
18 
19 // DQM
21 
22 #include <numeric>
23 
24 namespace {
25  template <typename T, size_t N>
26  std::array<T, N + 1> makeLogBins(const double min, const double max) {
27  const double minLog10 = std::log10(min);
28  const double maxLog10 = std::log10(max);
29  const double width = (maxLog10 - minLog10) / N;
30  std::array<T, N + 1> ret;
31  ret[0] = std::pow(10, minLog10);
32  const double mult = std::pow(10, width);
33  for (size_t i = 1; i <= N; ++i) {
34  ret[i] = ret[i - 1] * mult;
35  }
36  return ret;
37  }
38 } // namespace
39 
40 //
41 // constructors and destructor
42 //
44  : verbose_(iConfig.getUntrackedParameter<bool>("verbose", false)),
45  use_only_charged_tracks_(iConfig.getUntrackedParameter<bool>("use_only_charged_tracks", true)),
46  do_generic_sim_plots_(iConfig.getUntrackedParameter<bool>("do_generic_sim_plots")),
47  root_folder_(iConfig.getUntrackedParameter<std::string>("root_folder", "Validation/Vertices")),
48  vecPileupSummaryInfoToken_(consumes<std::vector<PileupSummaryInfo>>(edm::InputTag(std::string("addPileupInfo")))),
49  trackingParticleCollectionToken_(consumes<TrackingParticleCollection>(
50  iConfig.getUntrackedParameter<edm::InputTag>("trackingParticleCollection"))),
51  trackingVertexCollectionToken_(
52  consumes<TrackingVertexCollection>(iConfig.getUntrackedParameter<edm::InputTag>("trackingVertexCollection"))),
53  simToRecoAssociationToken_(
54  consumes<reco::SimToRecoCollection>(iConfig.getUntrackedParameter<edm::InputTag>("trackAssociatorMap"))),
55  recoToSimAssociationToken_(
56  consumes<reco::RecoToSimCollection>(iConfig.getUntrackedParameter<edm::InputTag>("trackAssociatorMap"))),
57  vertexAssociatorToken_(consumes<reco::VertexToTrackingVertexAssociator>(
58  iConfig.getUntrackedParameter<edm::InputTag>("vertexAssociator"))) {
59  reco_vertex_collections_ = iConfig.getParameter<std::vector<edm::InputTag>>("vertexRecoCollections");
60  for (auto const& l : reco_vertex_collections_) {
63  }
64  errorPrintedForColl_.resize(reco_vertex_collections_.size(), false);
65 }
66 
68 
69 //
70 // member functions
71 //
73  edm::Run const& iRun,
74  edm::EventSetup const& iSetup) {
75  // TODO(rovere) make this booking method shorter and smarter,
76  // factorizing similar histograms with different prefix in a single
77  // method call.
78  float log_bins[31] = {0.0, 0.0002, 0.0004, 0.0006, 0.0008, 0.001, 0.002, 0.004, 0.006, 0.008, 0.01,
79  0.02, 0.04, 0.06, 0.08, 0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 2.0,
80  4.0, 6.0, 8.0, 10.0, 20.0, 40.0, 60.0, 80.0, 100.0};
81  auto const log_mergez_bins = makeLogBins<float, 16>(1e-4, 1); // 4 bins / 10x
82 
83  auto const log_pt_bins = makeLogBins<float, 100>(0.1, 1e4);
84  float log_pt2_bins[16] = {
85  0.0, 0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 100.0, 200.0, 500.0, 1000.0, 2000.0, 5000.0, 10000.0};
86  float log_ntrk_bins[25] = {0., 2.0, 4.0, 6.0, 8.0, 10., 12.0, 14.0, 16.0, 18.0, 22.0, 26.0, 30.0,
87  35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 70.0, 80.0, 90.0, 100.0, 150.0, 200.0};
88 
89  // TODO(rovere) Possibly change or add the main DQMStore booking
90  // interface to allow booking a TProfile with variable bin-width
91  // using an array of floats, as done for the TH1F case, not of
92  // doubles.
93  double log_pt2_bins_double[16] = {
94  0.0, 0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 100.0, 200.0, 500.0, 1000.0, 2000.0, 5000.0, 10000.0};
95 
96  i.setCurrentFolder(root_folder_);
98  mes_["root_folder"]["GenVtx_vs_BX"] = i.book2D("GenVtx_vs_BX", "GenVtx_vs_BX", 16, -12.5, 3.5, 200, 0., 200.);
99  // Generated Primary Vertex Plots
100  mes_["root_folder"]["GenPV_X"] = i.book1D("GenPV_X", "GeneratedPV_X", 120, -0.6, 0.6);
101  mes_["root_folder"]["GenPV_Y"] = i.book1D("GenPV_Y", "GeneratedPV_Y", 120, -0.6, 0.6);
102  mes_["root_folder"]["GenPV_Z"] = i.book1D("GenPV_Z", "GeneratedPV_Z", 120, -60., 60.);
103  mes_["root_folder"]["GenPV_R"] = i.book1D("GenPV_R", "GeneratedPV_R", 120, 0, 0.6);
104  mes_["root_folder"]["GenPV_Pt2"] = i.book1D("GenPV_Pt2", "GeneratedPV_Sum-pt2", 15, &log_pt2_bins[0]);
105  mes_["root_folder"]["GenPV_NumTracks"] =
106  i.book1D("GenPV_NumTracks", "GeneratedPV_NumTracks", 24, &log_ntrk_bins[0]);
107  mes_["root_folder"]["GenPV_ClosestDistanceZ"] =
108  i.book1D("GenPV_ClosestDistanceZ", "GeneratedPV_ClosestDistanceZ", 30, &log_bins[0]);
109 
110  // All Generated Vertices, used for efficiency plots
111  mes_["root_folder"]["GenAllV_NumVertices"] =
112  i.book1D("GenAllV_NumVertices", "GeneratedAllV_NumVertices", 100, 0., 200.);
113  mes_["root_folder"]["GenAllV_X"] = i.book1D("GenAllV_X", "GeneratedAllV_X", 120, -0.6, 0.6);
114  mes_["root_folder"]["GenAllV_Y"] = i.book1D("GenAllV_Y", "GeneratedAllV_Y", 120, -0.6, 0.6);
115  mes_["root_folder"]["GenAllV_Z"] = i.book1D("GenAllV_Z", "GeneratedAllV_Z", 120, -60, 60);
116  mes_["root_folder"]["GenAllV_R"] = i.book1D("GenAllV_R", "GeneratedAllV_R", 120, 0, 0.6);
117  mes_["root_folder"]["GenAllV_Pt2"] = i.book1D("GenAllV_Pt2", "GeneratedAllV_Sum-pt2", 15, &log_pt2_bins[0]);
118  mes_["root_folder"]["GenAllV_NumTracks"] =
119  i.book1D("GenAllV_NumTracks", "GeneratedAllV_NumTracks", 24, &log_ntrk_bins[0]);
120  mes_["root_folder"]["GenAllV_ClosestDistanceZ"] =
121  i.book1D("GenAllV_ClosestDistanceZ", "GeneratedAllV_ClosestDistanceZ", 30, &log_bins[0]);
122  mes_["root_folder"]["GenAllV_PairDistanceZ"] =
123  i.book1D("GenAllV_PairDistanceZ", "GeneratedAllV_PairDistanceZ", 1000, 0, 20);
124  mes_["root_folder"]["SignalIsHighestPt2"] = i.book1D("SignalIsHighestPt2", "SignalIsHighestPt2", 2, -0.5, 1.5);
125  }
126 
127  for (auto const& l : reco_vertex_collections_) {
128  std::string label = l.label();
129  std::string current_folder = root_folder_ + "/" + label;
130  i.setCurrentFolder(current_folder);
131 
132  auto book1d = [&](const char* name, int bins, double min, double max) {
133  mes_[label][name] = i.book1D(name, name, bins, min, max);
134  };
135  auto book1dlogx = [&](const char* name, int bins, const float* xbinedges) {
136  mes_[label][name] = i.book1D(name, name, bins, xbinedges);
137  };
138  auto book2d = [&](const char* name, int xbins, double xmin, double xmax, int ybins, double ymin, double ymax) {
139  mes_[label][name] = i.book2D(name, name, xbins, xmin, xmax, ybins, ymin, ymax);
140  };
141  auto book2dlogx = [&](const char* name, int xbins, const float* xbinedges, int ybins, double ymin, double ymax) {
142  auto me = i.book2D(name, name, xbins, xbinedges[0], xbinedges[xbins], ybins, ymin, ymax);
143  me->getTH2F()->GetXaxis()->Set(xbins, xbinedges);
144  mes_[label][name] = me;
145  };
146 
147  mes_[label]["RecoVtx_vs_GenVtx"] =
148  i.bookProfile("RecoVtx_vs_GenVtx", "RecoVtx_vs_GenVtx", 125, 0., 250., 250, 0., 250.);
149  mes_[label]["MatchedRecoVtx_vs_GenVtx"] =
150  i.bookProfile("MatchedRecoVtx_vs_GenVtx", "MatchedRecoVtx_vs_GenVtx", 125, 0., 250., 250, 0., 250.);
151  mes_[label]["KindOfSignalPV"] = i.book1D("KindOfSignalPV", "KindOfSignalPV", 9, -0.5, 8.5);
152  mes_[label]["KindOfSignalPV"]->getTH1()->GetXaxis()->SetBinLabel(1, "!Highest!Assoc2Any");
153  mes_[label]["KindOfSignalPV"]->getTH1()->GetXaxis()->SetBinLabel(2, "Highest!Assoc2Any");
154  mes_[label]["KindOfSignalPV"]->getTH1()->GetXaxis()->SetBinLabel(3, "!HighestAssoc2First");
155  mes_[label]["KindOfSignalPV"]->getTH1()->GetXaxis()->SetBinLabel(4, "HighestAssoc2First");
156  mes_[label]["KindOfSignalPV"]->getTH1()->GetXaxis()->SetBinLabel(5, "!HighestAssoc2!First");
157  mes_[label]["KindOfSignalPV"]->getTH1()->GetXaxis()->SetBinLabel(6, "HighestAssoc2!First");
158  mes_[label]["KindOfSignalPV"]->getTH1()->GetXaxis()->SetBinLabel(7, "!HighestAssoc2First");
159  mes_[label]["KindOfSignalPV"]->getTH1()->GetXaxis()->SetBinLabel(8, "HighestAssoc2First");
160  mes_[label]["MisTagRate"] = i.book1D("MisTagRate", "MisTagRate", 2, -0.5, 1.5);
161  mes_[label]["MisTagRate_vs_PU"] = i.bookProfile("MisTagRate_vs_PU", "MisTagRate_vs_PU", 125, 0., 250., 2, 0., 1.);
162  mes_[label]["MisTagRate_vs_sum-pt2"] =
163  i.bookProfile("MisTagRate_vs_sum-pt2", "MisTagRate_vs_sum-pt2", 15, &log_pt2_bins_double[0], 2, 0., 1.);
164  mes_[label]["MisTagRate_vs_Z"] = i.bookProfile("MisTagRate_vs_Z", "MisTagRate_vs_Z", 120, -60., 60., 2, 0., 1.);
165  mes_[label]["MisTagRate_vs_R"] = i.bookProfile("MisTagRate_vs_R", "MisTagRate_vs_R", 120, 0., 0.6, 2, 0., 1.);
166  mes_[label]["MisTagRate_vs_NumTracks"] =
167  i.bookProfile("MisTagRate_vs_NumTracks", "MisTagRate_vs_NumTracks", 100, 0., 200, 2, 0., 1.);
168  mes_[label]["MisTagRateSignalIsHighest"] =
169  i.book1D("MisTagRateSignalIsHighest", "MisTagRateSignalIsHighest", 2, -0.5, 1.5);
170  mes_[label]["MisTagRateSignalIsHighest_vs_PU"] =
171  i.bookProfile("MisTagRateSignalIsHighest_vs_PU", "MisTagRateSignalIsHighest_vs_PU", 125, 0., 250., 2, 0., 1.);
172  mes_[label]["MisTagRateSignalIsHighest_vs_sum-pt2"] = i.bookProfile("MisTagRateSignalIsHighest_vs_sum-pt2",
173  "MisTagRateSignalIsHighest_vs_sum-pt2",
174  15,
175  &log_pt2_bins_double[0],
176  2,
177  0.,
178  1.);
179  mes_[label]["MisTagRateSignalIsHighest_vs_Z"] =
180  i.bookProfile("MisTagRateSignalIsHighest_vs_Z", "MisTagRateSignalIsHighest_vs_Z", 120, -60., 60., 2, 0., 1.);
181  mes_[label]["MisTagRateSignalIsHighest_vs_R"] =
182  i.bookProfile("MisTagRateSignalIsHighest_vs_R", "MisTagRateSignalIsHighest_vs_R", 120, 0., 0.6, 2, 0., 1.);
183  mes_[label]["MisTagRateSignalIsHighest_vs_NumTracks"] = i.bookProfile(
184  "MisTagRateSignalIsHighest_vs_NumTracks", "MisTagRateSignalIsHighest_vs_NumTracks", 100, 0., 200, 2, 0., 1.);
185  mes_[label]["MisTagRateSignalIsNotHighest"] =
186  i.book1D("MisTagRateSignalIsNotHighest", "MisTagRateSignalIsNotHighest", 2, -0.5, 1.5);
187  mes_[label]["MisTagRateSignalIsNotHighest_vs_PU"] = i.bookProfile(
188  "MisTagRateSignalIsNotHighest_vs_PU", "MisTagRateSignalIsNotHighest_vs_PU", 125, 0., 250., 2, 0., 1.);
189  mes_[label]["MisTagRateSignalIsNotHighest_vs_sum-pt2"] = i.bookProfile("MisTagRateSignalIsNotHighest_vs_sum-pt2",
190  "MisTagRateSignalIsNotHighest_vs_sum-pt2",
191  15,
192  &log_pt2_bins_double[0],
193  2,
194  0.,
195  1.);
196  mes_[label]["MisTagRateSignalIsNotHighest_vs_Z"] = i.bookProfile(
197  "MisTagRateSignalIsNotHighest_vs_Z", "MisTagRateSignalIsNotHighest_vs_Z", 120, -60., 60., 2, 0., 1.);
198  mes_[label]["MisTagRateSignalIsNotHighest_vs_R"] = i.bookProfile(
199  "MisTagRateSignalIsNotHighest_vs_R", "MisTagRateSignalIsNotHighest_vs_R", 120, 0., 0.6, 2, 0., 1.);
200  mes_[label]["MisTagRateSignalIsNotHighest_vs_NumTracks"] =
201  i.bookProfile("MisTagRateSignalIsNotHighest_vs_NumTracks",
202  "MisTagRateSignalIsNotHighest_vs_NumTracks",
203  100,
204  0.,
205  200,
206  2,
207  0.,
208  1.);
209  mes_[label]["TruePVLocationIndex"] =
210  i.book1D("TruePVLocationIndex", "TruePVLocationIndexInRecoVertexCollection", 12, -1.5, 10.5);
211  mes_[label]["TruePVLocationIndexCumulative"] =
212  i.book1D("TruePVLocationIndexCumulative", "TruePVLocationIndexInRecoVertexCollectionCumulative", 3, -1.5, 1.5);
213  mes_[label]["TruePVLocationIndexSignalIsHighest"] =
214  i.book1D("TruePVLocationIndexSignalIsHighest",
215  "TruePVLocationIndexSignalIsHighestInRecoVertexCollection",
216  12,
217  -1.5,
218  10.5);
219  mes_[label]["TruePVLocationIndexSignalIsNotHighest"] =
220  i.book1D("TruePVLocationIndexSignalIsNotHighest",
221  "TruePVLocationIndexSignalIsNotHighestInRecoVertexCollection",
222  12,
223  -1.5,
224  10.5);
225  // All Generated Vertices. Used for Efficiency plots We kind of
226  // duplicate plots here in case we want to perform more detailed
227  // studies on a selection of generated vertices, not on all of them.
228  mes_[label]["GenAllAssoc2Reco_NumVertices"] =
229  i.book1D("GenAllAssoc2Reco_NumVertices", "GeneratedAllAssoc2Reco_NumVertices", 100, 0., 200.);
230  mes_[label]["GenAllAssoc2Reco_X"] = i.book1D("GenAllAssoc2Reco_X", "GeneratedAllAssoc2Reco_X", 120, -0.6, 0.6);
231  mes_[label]["GenAllAssoc2Reco_Y"] = i.book1D("GenAllAssoc2Reco_Y", "GeneratedAllAssoc2Reco_Y", 120, -0.6, 0.6);
232  mes_[label]["GenAllAssoc2Reco_Z"] = i.book1D("GenAllAssoc2Reco_Z", "GeneratedAllAssoc2Reco_Z", 120, -60, 60);
233  mes_[label]["GenAllAssoc2Reco_R"] = i.book1D("GenAllAssoc2Reco_R", "GeneratedAllAssoc2Reco_R", 120, 0, 0.6);
234  mes_[label]["GenAllAssoc2Reco_Pt2"] =
235  i.book1D("GenAllAssoc2Reco_Pt2", "GeneratedAllAssoc2Reco_Sum-pt2", 15, &log_pt2_bins[0]);
236  mes_[label]["GenAllAssoc2Reco_NumTracks"] =
237  i.book1D("GenAllAssoc2Reco_NumTracks", "GeneratedAllAssoc2Reco_NumTracks", 24, &log_ntrk_bins[0]);
238  mes_[label]["GenAllAssoc2Reco_ClosestDistanceZ"] =
239  i.book1D("GenAllAssoc2Reco_ClosestDistanceZ", "GeneratedAllAssoc2Reco_ClosestDistanceZ", 30, &log_bins[0]);
240  book1d("GenPVAssoc2RecoPV_X", 120, -0.6, 0.6);
241  book1d("GenPVAssoc2RecoPV_Y", 120, -0.6, 0.6);
242  book1d("GenPVAssoc2RecoPV_Z", 120, -60, 60);
243 
244  // All Generated Vertices Matched to a Reconstructed vertex. Used
245  // for Efficiency plots
246  mes_[label]["GenAllAssoc2RecoMatched_NumVertices"] =
247  i.book1D("GenAllAssoc2RecoMatched_NumVertices", "GeneratedAllAssoc2RecoMatched_NumVertices", 100, 0., 200.);
248  mes_[label]["GenAllAssoc2RecoMatched_X"] =
249  i.book1D("GenAllAssoc2RecoMatched_X", "GeneratedAllAssoc2RecoMatched_X", 120, -0.6, 0.6);
250  mes_[label]["GenAllAssoc2RecoMatched_Y"] =
251  i.book1D("GenAllAssoc2RecoMatched_Y", "GeneratedAllAssoc2RecoMatched_Y", 120, -0.6, 0.6);
252  mes_[label]["GenAllAssoc2RecoMatched_Z"] =
253  i.book1D("GenAllAssoc2RecoMatched_Z", "GeneratedAllAssoc2RecoMatched_Z", 120, -60, 60);
254  mes_[label]["GenAllAssoc2RecoMatched_R"] =
255  i.book1D("GenAllAssoc2RecoMatched_R", "GeneratedAllAssoc2RecoMatched_R", 120, 0, 0.6);
256  mes_[label]["GenAllAssoc2RecoMatched_Pt2"] =
257  i.book1D("GenAllAssoc2RecoMatched_Pt2", "GeneratedAllAssoc2RecoMatched_Sum-pt2", 15, &log_pt2_bins[0]);
258  mes_[label]["GenAllAssoc2RecoMatched_NumTracks"] =
259  i.book1D("GenAllAssoc2RecoMatched_NumTracks", "GeneratedAllAssoc2RecoMatched_NumTracks", 24, &log_ntrk_bins[0]);
260  mes_[label]["GenAllAssoc2RecoMatched_ClosestDistanceZ"] = i.book1D(
261  "GenAllAssoc2RecoMatched_ClosestDistanceZ", "GeneratedAllAssoc2RecoMatched_ClosestDistanceZ", 30, &log_bins[0]);
262  book1d("GenPVAssoc2RecoPVMatched_X", 120, -0.6, 0.6);
263  book1d("GenPVAssoc2RecoPVMatched_Y", 120, -0.6, 0.6);
264  book1d("GenPVAssoc2RecoPVMatched_Z", 120, -60, 60);
265 
266  // All Generated Vertices Multi-Matched to a Reconstructed vertex. Used
267  // for Duplicate rate plots
268  mes_[label]["GenAllAssoc2RecoMultiMatched_NumVertices"] = i.book1D(
269  "GenAllAssoc2RecoMultiMatched_NumVertices", "GeneratedAllAssoc2RecoMultiMatched_NumVertices", 100, 0., 200.);
270  mes_[label]["GenAllAssoc2RecoMultiMatched_X"] =
271  i.book1D("GenAllAssoc2RecoMultiMatched_X", "GeneratedAllAssoc2RecoMultiMatched_X", 120, -0.6, 0.6);
272  mes_[label]["GenAllAssoc2RecoMultiMatched_Y"] =
273  i.book1D("GenAllAssoc2RecoMultiMatched_Y", "GeneratedAllAssoc2RecoMultiMatched_Y", 120, -0.6, 0.6);
274  mes_[label]["GenAllAssoc2RecoMultiMatched_Z"] =
275  i.book1D("GenAllAssoc2RecoMultiMatched_Z", "GeneratedAllAssoc2RecoMultiMatched_Z", 120, -60, 60);
276  mes_[label]["GenAllAssoc2RecoMultiMatched_R"] =
277  i.book1D("GenAllAssoc2RecoMultiMatched_R", "GeneratedAllAssoc2RecoMultiMatched_R", 120, 0, 0.6);
278  mes_[label]["GenAllAssoc2RecoMultiMatched_Pt2"] = i.book1D(
279  "GenAllAssoc2RecoMultiMatched_Pt2", "GeneratedAllAssoc2RecoMultiMatched_Sum-pt2", 15, &log_pt2_bins[0]);
280  mes_[label]["GenAllAssoc2RecoMultiMatched_NumTracks"] = i.book1D("GenAllAssoc2RecoMultiMatched_NumTracks",
281  "GeneratedAllAssoc2RecoMultiMatched_NumTracks",
282  24,
283  &log_ntrk_bins[0]);
284  mes_[label]["GenAllAssoc2RecoMultiMatched_ClosestDistanceZ"] =
285  i.book1D("GenAllAssoc2RecoMultiMatched_ClosestDistanceZ",
286  "GeneratedAllAssoc2RecoMultiMatched_ClosestDistanceZ",
287  30,
288  &log_bins[0]);
289 
290  // All Reco Vertices. Used for {Fake,Duplicate}-Rate plots
291  mes_[label]["RecoAllAssoc2Gen_NumVertices"] =
292  i.book1D("RecoAllAssoc2Gen_NumVertices", "ReconstructedAllAssoc2Gen_NumVertices", 100, 0., 200.);
293  mes_[label]["RecoAllAssoc2Gen_X"] = i.book1D("RecoAllAssoc2Gen_X", "ReconstructedAllAssoc2Gen_X", 120, -0.6, 0.6);
294  mes_[label]["RecoAllAssoc2Gen_Y"] = i.book1D("RecoAllAssoc2Gen_Y", "ReconstructedAllAssoc2Gen_Y", 120, -0.6, 0.6);
295  mes_[label]["RecoAllAssoc2Gen_Z"] = i.book1D("RecoAllAssoc2Gen_Z", "ReconstructedAllAssoc2Gen_Z", 120, -60, 60);
296  mes_[label]["RecoAllAssoc2Gen_R"] = i.book1D("RecoAllAssoc2Gen_R", "ReconstructedAllAssoc2Gen_R", 120, 0, 0.6);
297  mes_[label]["RecoAllAssoc2Gen_Pt2"] =
298  i.book1D("RecoAllAssoc2Gen_Pt2", "ReconstructedAllAssoc2Gen_Sum-pt2", 15, &log_pt2_bins[0]);
299  mes_[label]["RecoAllAssoc2Gen_Ndof"] =
300  i.book1D("RecoAllAssoc2Gen_Ndof", "ReconstructedAllAssoc2Gen_Ndof", 120, 0., 240.);
301  mes_[label]["RecoAllAssoc2Gen_NumTracks"] =
302  i.book1D("RecoAllAssoc2Gen_NumTracks", "ReconstructedAllAssoc2Gen_NumTracks", 24, &log_ntrk_bins[0]);
303  mes_[label]["RecoAllAssoc2Gen_PU"] = i.book1D("RecoAllAssoc2Gen_PU", "ReconstructedAllAssoc2Gen_PU", 125, 0., 250.);
304  mes_[label]["RecoAllAssoc2Gen_ClosestDistanceZ"] =
305  i.book1D("RecoAllAssoc2Gen_ClosestDistanceZ", "ReconstructedAllAssoc2Gen_ClosestDistanceZ", 30, &log_bins[0]);
306  mes_[label]["RecoAllAssoc2GenProperties"] =
307  i.book1D("RecoAllAssoc2GenProperties", "ReconstructedAllAssoc2Gen_Properties", 8, -0.5, 7.5);
308  mes_[label]["RecoAllAssoc2Gen_PairDistanceZ"] =
309  i.book1D("RecoAllAssoc2Gen_PairDistanceZ", "RecoAllAssoc2Gen_PairDistanceZ", 1000, 0, 20);
310 
311  // All Reconstructed Vertices Matched to a Generated vertex. Used
312  // for Fake-Rate plots
313  mes_[label]["RecoAllAssoc2GenMatched_NumVertices"] =
314  i.book1D("RecoAllAssoc2GenMatched_NumVertices", "ReconstructedAllAssoc2GenMatched_NumVertices", 100, 0., 200.);
315  mes_[label]["RecoAllAssoc2GenMatched_X"] =
316  i.book1D("RecoAllAssoc2GenMatched_X", "ReconstructedAllAssoc2GenMatched_X", 120, -0.6, 0.6);
317  mes_[label]["RecoAllAssoc2GenMatched_Y"] =
318  i.book1D("RecoAllAssoc2GenMatched_Y", "ReconstructedAllAssoc2GenMatched_Y", 120, -0.6, 0.6);
319  mes_[label]["RecoAllAssoc2GenMatched_Z"] =
320  i.book1D("RecoAllAssoc2GenMatched_Z", "ReconstructedAllAssoc2GenMatched_Z", 120, -60, 60);
321  mes_[label]["RecoAllAssoc2GenMatched_R"] =
322  i.book1D("RecoAllAssoc2GenMatched_R", "ReconstructedAllAssoc2GenMatched_R", 120, 0, 0.6);
323  mes_[label]["RecoAllAssoc2GenMatched_Pt2"] =
324  i.book1D("RecoAllAssoc2GenMatched_Pt2", "ReconstructedAllAssoc2GenMatched_Sum-pt2", 15, &log_pt2_bins[0]);
325  mes_[label]["RecoAllAssoc2GenMatched_Ndof"] =
326  i.book1D("RecoAllAssoc2GenMatched_Ndof", "ReconstructedAllAssoc2GenMatched_Ndof", 120, 0., 240.);
327  mes_[label]["RecoAllAssoc2GenMatched_NumTracks"] = i.book1D(
328  "RecoAllAssoc2GenMatched_NumTracks", "ReconstructedAllAssoc2GenMatched_NumTracks", 24, &log_ntrk_bins[0]);
329  mes_[label]["RecoAllAssoc2GenMatched_PU"] =
330  i.book1D("RecoAllAssoc2GenMatched_PU", "ReconstructedAllAssoc2GenMatched_PU", 125, 0., 250.);
331  mes_[label]["RecoAllAssoc2GenMatched_ClosestDistanceZ"] =
332  i.book1D("RecoAllAssoc2GenMatched_ClosestDistanceZ",
333  "ReconstructedAllAssoc2GenMatched_ClosestDistanceZ",
334  30,
335  &log_bins[0]);
336 
337  // All Reconstructed Vertices Multi-Matched to a Generated vertex. Used
338  // for Merge-Rate plots
339  mes_[label]["RecoAllAssoc2GenMultiMatched_NumVertices"] = i.book1D(
340  "RecoAllAssoc2GenMultiMatched_NumVertices", "ReconstructedAllAssoc2GenMultiMatched_NumVertices", 100, 0., 200.);
341  mes_[label]["RecoAllAssoc2GenMultiMatched_X"] =
342  i.book1D("RecoAllAssoc2GenMultiMatched_X", "ReconstructedAllAssoc2GenMultiMatched_X", 120, -0.6, 0.6);
343  mes_[label]["RecoAllAssoc2GenMultiMatched_Y"] =
344  i.book1D("RecoAllAssoc2GenMultiMatched_Y", "ReconstructedAllAssoc2GenMultiMatched_Y", 120, -0.6, 0.6);
345  mes_[label]["RecoAllAssoc2GenMultiMatched_Z"] =
346  i.book1D("RecoAllAssoc2GenMultiMatched_Z", "ReconstructedAllAssoc2GenMultiMatched_Z", 120, -60, 60);
347  mes_[label]["RecoAllAssoc2GenMultiMatched_R"] =
348  i.book1D("RecoAllAssoc2GenMultiMatched_R", "ReconstructedAllAssoc2GenMultiMatched_R", 120, 0, 0.6);
349  mes_[label]["RecoAllAssoc2GenMultiMatched_Pt2"] = i.book1D(
350  "RecoAllAssoc2GenMultiMatched_Pt2", "ReconstructedAllAssoc2GenMultiMatched_Sum-pt2", 15, &log_pt2_bins[0]);
351  mes_[label]["RecoAllAssoc2GenMultiMatched_NumTracks"] = i.book1D("RecoAllAssoc2GenMultiMatched_NumTracks",
352  "ReconstructedAllAssoc2GenMultiMatched_NumTracks",
353  24,
354  &log_ntrk_bins[0]);
355  mes_[label]["RecoAllAssoc2GenMultiMatched_PU"] =
356  i.book1D("RecoAllAssoc2GenMultiMatched_PU", "ReconstructedAllAssoc2GenMultiMatched_PU", 125, 0., 250.);
357  mes_[label]["RecoAllAssoc2GenMultiMatched_ClosestDistanceZ"] =
358  i.book1D("RecoAllAssoc2GenMultiMatched_ClosestDistanceZ",
359  "ReconstructedAllAssoc2GenMultiMatched_ClosestDistanceZ",
360  log_mergez_bins.size() - 1,
361  &log_mergez_bins[0]);
362 
363  // All Reconstructed Vertices Matched to a Multi-Matched Gen
364  // Vertex. Used for Duplicate rate plots done w.r.t. Reco
365  // Quantities. We basically want to ask how many times a RecoVTX
366  // has been reconstructed and associated to a SimulatedVTX that
367  // has been linked to at least another RecoVTX. In this sense this
368  // RecoVTX is a duplicate of the same, real GenVTX.
369  mes_[label]["RecoAllAssoc2MultiMatchedGen_NumVertices"] =
370  i.book1D("RecoAllAssoc2MultiMatchedGen_NumVertices", "RecoAllAssoc2MultiMatchedGen_NumVertices", 100, 0., 200.);
371  mes_[label]["RecoAllAssoc2MultiMatchedGen_X"] =
372  i.book1D("RecoAllAssoc2MultiMatchedGen_X", "RecoAllAssoc2MultiMatchedGen_X", 120, -0.6, 0.6);
373  mes_[label]["RecoAllAssoc2MultiMatchedGen_Y"] =
374  i.book1D("RecoAllAssoc2MultiMatchedGen_Y", "RecoAllAssoc2MultiMatchedGen_Y", 120, -0.6, 0.6);
375  mes_[label]["RecoAllAssoc2MultiMatchedGen_Z"] =
376  i.book1D("RecoAllAssoc2MultiMatchedGen_Z", "RecoAllAssoc2MultiMatchedGen_Z", 120, -60, 60);
377  mes_[label]["RecoAllAssoc2MultiMatchedGen_R"] =
378  i.book1D("RecoAllAssoc2MultiMatchedGen_R", "RecoAllAssoc2MultiMatchedGen_R", 120, 0, 0.6);
379  mes_[label]["RecoAllAssoc2MultiMatchedGen_Pt2"] =
380  i.book1D("RecoAllAssoc2MultiMatchedGen_Pt2", "RecoAllAssoc2MultiMatchedGen_Sum-pt2", 15, &log_pt2_bins[0]);
381  mes_[label]["RecoAllAssoc2MultiMatchedGen_NumTracks"] = i.book1D(
382  "RecoAllAssoc2MultiMatchedGen_NumTracks", "RecoAllAssoc2MultiMatchedGen_NumTracks", 24, &log_ntrk_bins[0]);
383  mes_[label]["RecoAllAssoc2MultiMatchedGen_PU"] =
384  i.book1D("RecoAllAssoc2MultiMatchedGen_PU", "RecoAllAssoc2MultiMatchedGen_PU", 125, 0., 250.);
385  mes_[label]["RecoAllAssoc2MultiMatchedGen_ClosestDistanceZ"] =
386  i.book1D("RecoAllAssoc2MultiMatchedGen_ClosestDistanceZ",
387  "RecoAllAssoc2MultiMatchedGen_ClosestDistanceZ",
388  30,
389  &log_bins[0]);
390  mes_[label]["RecoAllAssoc2GenSimForMerge_ClosestDistanceZ"] =
391  i.book1D("RecoAllAssoc2GenSimForMerge_ClosestDistanceZ",
392  "RecoAllAssoc2GenSimForMerge_ClosestDistanceZ",
393  log_mergez_bins.size() - 1,
394  &log_mergez_bins[0]);
395 
396  // Resolution and pull histograms
397  const double resolpt2 = 10;
398 
399  const double minPull = -10;
400  const double maxPull = 10;
401  const double nPull = 100;
402 
403  auto bookResolPull = [&](const std::string& prefix, const double resolx, const double resoly, const double resolz) {
404  book1d((prefix + "_ResolX").c_str(), 100, -resolx, resolx);
405  book1d((prefix + "_ResolY").c_str(), 100, -resoly, resoly);
406  book1d((prefix + "_ResolZ").c_str(), 100, -resolz, resolz);
407  book1d((prefix + "_ResolPt2").c_str(), 100, -resolpt2, resolpt2);
408  book1d((prefix + "_PullX").c_str(), 250, -25, 25);
409  book1d((prefix + "_PullY").c_str(), 250, -25, 25);
410  book1d((prefix + "_PullZ").c_str(), 250, -25, 25);
411 
412  book2d((prefix + "_ResolX_vs_PU").c_str(), 125, 0., 250., 100, -resolx, resolx);
413  book2d((prefix + "_ResolY_vs_PU").c_str(), 125, 0., 250., 100, -resoly, resoly);
414  book2d((prefix + "_ResolZ_vs_PU").c_str(), 125, 0., 250., 100, -resolz, resolz);
415  book2d((prefix + "_ResolPt2_vs_PU").c_str(), 125, 0., 250., 100, -resolpt2, resolpt2);
416  book2d((prefix + "_PullX_vs_PU").c_str(), 125, 0., 250., nPull, minPull, maxPull);
417  book2d((prefix + "_PullY_vs_PU").c_str(), 125, 0., 250., nPull, minPull, maxPull);
418  book2d((prefix + "_PullZ_vs_PU").c_str(), 125, 0., 250., nPull, minPull, maxPull);
419 
420  book2dlogx((prefix + "_ResolX_vs_NumTracks").c_str(), 24, &log_ntrk_bins[0], 100, -resolx, resolx);
421  book2dlogx((prefix + "_ResolY_vs_NumTracks").c_str(), 24, &log_ntrk_bins[0], 100, -resoly, resoly);
422  book2dlogx((prefix + "_ResolZ_vs_NumTracks").c_str(), 24, &log_ntrk_bins[0], 100, -resolz, resolz);
423  book2dlogx((prefix + "_ResolPt2_vs_NumTracks").c_str(), 24, &log_ntrk_bins[0], 100, -resolpt2, resolpt2);
424  book2dlogx((prefix + "_PullX_vs_NumTracks").c_str(), 24, &log_ntrk_bins[0], nPull, minPull, maxPull);
425  book2dlogx((prefix + "_PullY_vs_NumTracks").c_str(), 24, &log_ntrk_bins[0], nPull, minPull, maxPull);
426  book2dlogx((prefix + "_PullZ_vs_NumTracks").c_str(), 24, &log_ntrk_bins[0], nPull, minPull, maxPull);
427 
428  book2d((prefix + "_ResolX_vs_Z").c_str(), 120, -60, 60, 100, -resolx, resolx);
429  book2d((prefix + "_ResolY_vs_Z").c_str(), 120, -60, 60, 100, -resoly, resoly);
430  book2d((prefix + "_ResolZ_vs_Z").c_str(), 120, -60, 60, 100, -resolz, resolz);
431  book2d((prefix + "_ResolPt2_vs_Z").c_str(), 120, -60, 60, 100, -resolpt2, resolpt2);
432  book2d((prefix + "_PullX_vs_Z").c_str(), 120, -60, 60, nPull, minPull, maxPull);
433  book2d((prefix + "_PullY_vs_Z").c_str(), 120, -60, 60, nPull, minPull, maxPull);
434  book2d((prefix + "_PullZ_vs_Z").c_str(), 120, -60, 60, nPull, minPull, maxPull);
435 
436  book2dlogx((prefix + "_ResolX_vs_Pt").c_str(), log_pt_bins.size() - 1, &log_pt_bins[0], 100, -resolx, resolx);
437  book2dlogx((prefix + "_ResolY_vs_Pt").c_str(), log_pt_bins.size() - 1, &log_pt_bins[0], 100, -resoly, resoly);
438  book2dlogx((prefix + "_ResolZ_vs_Pt").c_str(), log_pt_bins.size() - 1, &log_pt_bins[0], 100, -resolz, resolz);
439  book2dlogx(
440  (prefix + "_ResolPt2_vs_Pt").c_str(), log_pt_bins.size() - 1, &log_pt_bins[0], 100, -resolpt2, resolpt2);
441  book2dlogx((prefix + "_PullX_vs_Pt").c_str(), log_pt_bins.size() - 1, &log_pt_bins[0], nPull, minPull, maxPull);
442  book2dlogx((prefix + "_PullY_vs_Pt").c_str(), log_pt_bins.size() - 1, &log_pt_bins[0], nPull, minPull, maxPull);
443  book2dlogx((prefix + "_PullZ_vs_Pt").c_str(), log_pt_bins.size() - 1, &log_pt_bins[0], nPull, minPull, maxPull);
444  };
445 
446  bookResolPull("RecoAllAssoc2GenMatched", 0.1, 0.1, 0.1); // Non-merged vertices
447  bookResolPull("RecoAllAssoc2GenMatchedMerged", 0.1, 0.1, 0.1); // Merged vertices
448  bookResolPull(
449  "RecoPVAssoc2GenPVMatched", 0.01, 0.01, 0.01); // PV, when correctly matched, regardless if merged or not
450 
451  // Purity histograms
452  // Reco PV (vtx0) matched to hard-scatter gen vertex
453  book1d("RecoPVAssoc2GenPVMatched_Purity", 50, 0, 1);
454  book1d("RecoPVAssoc2GenPVMatched_Missing", 50, 0, 1);
455  book2d("RecoPVAssoc2GenPVMatched_Purity_vs_Index", 100, 0, 100, 50, 0, 1);
456 
457  // RECO PV (vtx0) not matched to hard-scatter gen vertex
458  book1d("RecoPVAssoc2GenPVNotMatched_Purity", 50, 0, 1);
459  book1d("RecoPVAssoc2GenPVNotMatched_Missing", 50, 0, 1);
460  book2d("RecoPVAssoc2GenPVNotMatched_Purity_vs_Index", 100, 0, 100, 50, 0, 1);
461 
462  // Purity vs. fake rate
463  book1d("RecoAllAssoc2Gen_Purity", 50, 0, 1); // denominator
464  book1d("RecoAllAssoc2GenMatched_Purity", 50, 0, 1); // 1-numerator
465 
466  // Vertex sum(pt2)
467  // The first two are orthogonal (i.e. their sum includes all reco vertices)
468  book1dlogx("RecoAssoc2GenPVMatched_Pt2", 15, &log_pt2_bins[0]);
469  book1dlogx("RecoAssoc2GenPVNotMatched_Pt2", 15, &log_pt2_bins[0]);
470 
471  book1dlogx("RecoAssoc2GenPVMatchedNotHighest_Pt2", 15, &log_pt2_bins[0]);
472  book1dlogx("RecoAssoc2GenPVNotMatched_GenPVTracksRemoved_Pt2", 15, &log_pt2_bins[0]);
473 
474  // Shared tracks
475  book1d("RecoAllAssoc2GenSingleMatched_SharedTrackFractionReco", 50, 0, 1);
476  book1d("RecoAllAssoc2GenMultiMatched_SharedTrackFractionReco", 50, 0, 1);
477  book1d("RecoAllAssoc2GenSingleMatched_SharedTrackFractionRecoMatched", 50, 0, 1);
478  book1d("RecoAllAssoc2GenMultiMatched_SharedTrackFractionRecoMatched", 50, 0, 1);
479 
480  book1d("RecoAllAssoc2GenSingleMatched_SharedTrackFractionSim", 50, 0, 1);
481  book1d("RecoAllAssoc2GenMultiMatched_SharedTrackFractionSim", 50, 0, 1);
482  book1d("RecoAllAssoc2GenSingleMatched_SharedTrackFractionSimMatched", 50, 0, 1);
483  book1d("RecoAllAssoc2GenMultiMatched_SharedTrackFractionSimMatched", 50, 0, 1);
484  }
485 }
486 
488  if (v.eventId.event() == 0) {
489  mes_["root_folder"]["GenPV_X"]->Fill(v.x);
490  mes_["root_folder"]["GenPV_Y"]->Fill(v.y);
491  mes_["root_folder"]["GenPV_Z"]->Fill(v.z);
492  mes_["root_folder"]["GenPV_R"]->Fill(v.r);
493  mes_["root_folder"]["GenPV_Pt2"]->Fill(v.ptsq);
494  mes_["root_folder"]["GenPV_NumTracks"]->Fill(v.nGenTrk);
495  if (v.closest_vertex_distance_z > 0.)
496  mes_["root_folder"]["GenPV_ClosestDistanceZ"]->Fill(v.closest_vertex_distance_z);
497  }
498  mes_["root_folder"]["GenAllV_X"]->Fill(v.x);
499  mes_["root_folder"]["GenAllV_Y"]->Fill(v.y);
500  mes_["root_folder"]["GenAllV_Z"]->Fill(v.z);
501  mes_["root_folder"]["GenAllV_R"]->Fill(v.r);
502  mes_["root_folder"]["GenAllV_Pt2"]->Fill(v.ptsq);
503  mes_["root_folder"]["GenAllV_NumTracks"]->Fill(v.nGenTrk);
504  if (v.closest_vertex_distance_z > 0.)
505  mes_["root_folder"]["GenAllV_ClosestDistanceZ"]->Fill(v.closest_vertex_distance_z);
506 }
507 
510  mes_[label]["GenAllAssoc2Reco_X"]->Fill(v.x);
511  mes_[label]["GenAllAssoc2Reco_Y"]->Fill(v.y);
512  mes_[label]["GenAllAssoc2Reco_Z"]->Fill(v.z);
513  mes_[label]["GenAllAssoc2Reco_R"]->Fill(v.r);
514  mes_[label]["GenAllAssoc2Reco_Pt2"]->Fill(v.ptsq);
515  mes_[label]["GenAllAssoc2Reco_NumTracks"]->Fill(v.nGenTrk);
516  if (v.closest_vertex_distance_z > 0.)
517  mes_[label]["GenAllAssoc2Reco_ClosestDistanceZ"]->Fill(v.closest_vertex_distance_z);
518  if (!v.rec_vertices.empty()) {
519  mes_[label]["GenAllAssoc2RecoMatched_X"]->Fill(v.x);
520  mes_[label]["GenAllAssoc2RecoMatched_Y"]->Fill(v.y);
521  mes_[label]["GenAllAssoc2RecoMatched_Z"]->Fill(v.z);
522  mes_[label]["GenAllAssoc2RecoMatched_R"]->Fill(v.r);
523  mes_[label]["GenAllAssoc2RecoMatched_Pt2"]->Fill(v.ptsq);
524  mes_[label]["GenAllAssoc2RecoMatched_NumTracks"]->Fill(v.nGenTrk);
525  if (v.closest_vertex_distance_z > 0.)
526  mes_[label]["GenAllAssoc2RecoMatched_ClosestDistanceZ"]->Fill(v.closest_vertex_distance_z);
527  }
528  if (v.rec_vertices.size() > 1) {
529  mes_[label]["GenAllAssoc2RecoMultiMatched_X"]->Fill(v.x);
530  mes_[label]["GenAllAssoc2RecoMultiMatched_Y"]->Fill(v.y);
531  mes_[label]["GenAllAssoc2RecoMultiMatched_Z"]->Fill(v.z);
532  mes_[label]["GenAllAssoc2RecoMultiMatched_R"]->Fill(v.r);
533  mes_[label]["GenAllAssoc2RecoMultiMatched_Pt2"]->Fill(v.ptsq);
534  mes_[label]["GenAllAssoc2RecoMultiMatched_NumTracks"]->Fill(v.nGenTrk);
535  if (v.closest_vertex_distance_z > 0.)
536  mes_[label]["GenAllAssoc2RecoMultiMatched_ClosestDistanceZ"]->Fill(v.closest_vertex_distance_z);
537  }
538 }
539 
541  const std::string& label, const PrimaryVertexAnalyzer4PUSlimmed::simPrimaryVertex& v, bool genPVMatchedToRecoPV) {
542  mes_[label]["GenPVAssoc2RecoPV_X"]->Fill(v.x);
543  mes_[label]["GenPVAssoc2RecoPV_Y"]->Fill(v.y);
544  mes_[label]["GenPVAssoc2RecoPV_Z"]->Fill(v.z);
545  if (genPVMatchedToRecoPV) {
546  mes_[label]["GenPVAssoc2RecoPVMatched_X"]->Fill(v.x);
547  mes_[label]["GenPVAssoc2RecoPVMatched_Y"]->Fill(v.y);
548  mes_[label]["GenPVAssoc2RecoPVMatched_Z"]->Fill(v.z);
549  }
550 }
551 
553  const std::string& label, int num_pileup_vertices, PrimaryVertexAnalyzer4PUSlimmed::recoPrimaryVertex& v) {
554  mes_[label]["RecoAllAssoc2Gen_X"]->Fill(v.x);
555  mes_[label]["RecoAllAssoc2Gen_Y"]->Fill(v.y);
556  mes_[label]["RecoAllAssoc2Gen_Z"]->Fill(v.z);
557  mes_[label]["RecoAllAssoc2Gen_R"]->Fill(v.r);
558  mes_[label]["RecoAllAssoc2Gen_Pt2"]->Fill(v.ptsq);
559  mes_[label]["RecoAllAssoc2Gen_Ndof"]->Fill(v.recVtx->ndof());
560  mes_[label]["RecoAllAssoc2Gen_NumTracks"]->Fill(v.nRecoTrk);
561  mes_[label]["RecoAllAssoc2Gen_PU"]->Fill(num_pileup_vertices);
562  mes_[label]["RecoAllAssoc2Gen_Purity"]->Fill(v.purity);
563  if (v.closest_vertex_distance_z > 0.)
564  mes_[label]["RecoAllAssoc2Gen_ClosestDistanceZ"]->Fill(v.closest_vertex_distance_z);
565  if (!v.sim_vertices.empty()) {
566  v.kind_of_vertex |= recoPrimaryVertex::MATCHED;
567  mes_[label]["RecoAllAssoc2GenMatched_X"]->Fill(v.x);
568  mes_[label]["RecoAllAssoc2GenMatched_Y"]->Fill(v.y);
569  mes_[label]["RecoAllAssoc2GenMatched_Z"]->Fill(v.z);
570  mes_[label]["RecoAllAssoc2GenMatched_R"]->Fill(v.r);
571  mes_[label]["RecoAllAssoc2GenMatched_Pt2"]->Fill(v.ptsq);
572  mes_[label]["RecoAllAssoc2GenMatched_Ndof"]->Fill(v.recVtx->ndof());
573  mes_[label]["RecoAllAssoc2GenMatched_NumTracks"]->Fill(v.nRecoTrk);
574  mes_[label]["RecoAllAssoc2GenMatched_PU"]->Fill(num_pileup_vertices);
575  mes_[label]["RecoAllAssoc2GenMatched_Purity"]->Fill(v.purity);
576  if (v.closest_vertex_distance_z > 0.)
577  mes_[label]["RecoAllAssoc2GenMatched_ClosestDistanceZ"]->Fill(v.closest_vertex_distance_z);
578 
579  // Fill resolution and pull plots here (as in MultiTrackValidator)
580  fillResolutionAndPullHistograms(label, num_pileup_vertices, v, false);
581 
582  // Now keep track of all RecoVTX associated to a SimVTX that
583  // itself is associated to more than one RecoVTX, for
584  // duplicate-rate plots on reco quantities.
585  if (v.sim_vertices_internal[0]->rec_vertices.size() > 1) {
586  v.kind_of_vertex |= recoPrimaryVertex::DUPLICATE;
587  mes_[label]["RecoAllAssoc2MultiMatchedGen_X"]->Fill(v.x);
588  mes_[label]["RecoAllAssoc2MultiMatchedGen_Y"]->Fill(v.y);
589  mes_[label]["RecoAllAssoc2MultiMatchedGen_Z"]->Fill(v.z);
590  mes_[label]["RecoAllAssoc2MultiMatchedGen_R"]->Fill(v.r);
591  mes_[label]["RecoAllAssoc2MultiMatchedGen_Pt2"]->Fill(v.ptsq);
592  mes_[label]["RecoAllAssoc2MultiMatchedGen_NumTracks"]->Fill(v.nRecoTrk);
593  mes_[label]["RecoAllAssoc2MultiMatchedGen_PU"]->Fill(num_pileup_vertices);
594  if (v.closest_vertex_distance_z > 0.)
595  mes_[label]["RecoAllAssoc2MultiMatchedGen_ClosestDistanceZ"]->Fill(v.closest_vertex_distance_z);
596  }
597  // This is meant to be used as "denominator" for the merge-rate
598  // plots produced starting from reco quantities. We enter here
599  // only if the reco vertex has been associated, since we need info
600  // from the SimVTX associated to it. In this regard, the final
601  // merge-rate plot coming from reco is not to be intended as a
602  // pure efficiency-like plot, since the normalization is biased.
603  if (v.sim_vertices_internal[0]->closest_vertex_distance_z > 0.)
604  mes_[label]["RecoAllAssoc2GenSimForMerge_ClosestDistanceZ"]->Fill(
605  v.sim_vertices_internal[0]->closest_vertex_distance_z);
606  }
607  // this plots are meant to be used to compute the merge rate
608  if (v.sim_vertices.size() > 1) {
609  v.kind_of_vertex |= recoPrimaryVertex::MERGED;
610  mes_[label]["RecoAllAssoc2GenMultiMatched_X"]->Fill(v.x);
611  mes_[label]["RecoAllAssoc2GenMultiMatched_Y"]->Fill(v.y);
612  mes_[label]["RecoAllAssoc2GenMultiMatched_Z"]->Fill(v.z);
613  mes_[label]["RecoAllAssoc2GenMultiMatched_R"]->Fill(v.r);
614  mes_[label]["RecoAllAssoc2GenMultiMatched_Pt2"]->Fill(v.ptsq);
615  mes_[label]["RecoAllAssoc2GenMultiMatched_NumTracks"]->Fill(v.nRecoTrk);
616  mes_[label]["RecoAllAssoc2GenMultiMatched_PU"]->Fill(num_pileup_vertices);
617  if (v.sim_vertices_internal[0]->closest_vertex_distance_z > 0.)
618  mes_[label]["RecoAllAssoc2GenMultiMatched_ClosestDistanceZ"]->Fill(
619  v.sim_vertices_internal[0]->closest_vertex_distance_z);
620  }
621  mes_[label]["RecoAllAssoc2GenProperties"]->Fill(v.kind_of_vertex);
622 
624  if (v.sim_vertices.size() == 1) {
625  prefix = "RecoAllAssoc2GenSingleMatched_SharedTrackFraction";
626  } else if (v.sim_vertices.size() > 1) {
627  prefix = "RecoAllAssoc2GenMultiMatched_SharedTrackFraction";
628  }
629 
630  for (size_t i = 0; i < v.sim_vertices.size(); ++i) {
631  const double sharedTracks = v.sim_vertices_num_shared_tracks[i];
632  const simPrimaryVertex* simV = v.sim_vertices_internal[i];
633  mes_[label][prefix + "Reco"]->Fill(sharedTracks / v.nRecoTrk);
634  mes_[label][prefix + "RecoMatched"]->Fill(sharedTracks / v.num_matched_sim_tracks);
635  mes_[label][prefix + "Sim"]->Fill(sharedTracks / simV->nGenTrk);
636  mes_[label][prefix + "SimMatched"]->Fill(sharedTracks / simV->num_matched_reco_tracks);
637  }
638 }
639 
641  const std::string& label,
642  int num_pileup_vertices,
644  bool isPV) {
645  std::string prefix = "RecoAllAssoc2GenMatched";
646  if (v.sim_vertices_internal.size() > 1) {
647  prefix += "Merged";
648  }
649  if (isPV) {
650  prefix = "RecoPVAssoc2GenPVMatched";
651  }
652 
653  // Use the best match as defined by the vertex truth associator
654  // reco-tracks as the best match
655  const simPrimaryVertex& bestMatch = *(v.sim_vertices_internal[0]);
656  const double xres = v.x - bestMatch.x;
657  const double yres = v.y - bestMatch.y;
658  const double zres = v.z - bestMatch.z;
659  const double pt2res = v.ptsq - bestMatch.ptsq;
660 
661  const double xresol = xres;
662  const double yresol = yres;
663  const double zresol = zres;
664  const double pt2resol = pt2res / v.ptsq;
665  const double xpull = xres / v.recVtx->xError();
666  const double ypull = yres / v.recVtx->yError();
667  const double zpull = zres / v.recVtx->zError();
668 
669  mes_[label][prefix + "_ResolX"]->Fill(xresol);
670  mes_[label][prefix + "_ResolY"]->Fill(yresol);
671  mes_[label][prefix + "_ResolZ"]->Fill(zresol);
672  mes_[label][prefix + "_ResolPt2"]->Fill(pt2resol);
673  mes_[label][prefix + "_PullX"]->Fill(xpull);
674  mes_[label][prefix + "_PullY"]->Fill(ypull);
675  mes_[label][prefix + "_PullZ"]->Fill(zpull);
676 
677  mes_[label][prefix + "_ResolX_vs_PU"]->Fill(num_pileup_vertices, xresol);
678  mes_[label][prefix + "_ResolY_vs_PU"]->Fill(num_pileup_vertices, yresol);
679  mes_[label][prefix + "_ResolZ_vs_PU"]->Fill(num_pileup_vertices, zresol);
680  mes_[label][prefix + "_ResolPt2_vs_PU"]->Fill(num_pileup_vertices, pt2resol);
681  mes_[label][prefix + "_PullX_vs_PU"]->Fill(num_pileup_vertices, xpull);
682  mes_[label][prefix + "_PullY_vs_PU"]->Fill(num_pileup_vertices, ypull);
683  mes_[label][prefix + "_PullZ_vs_PU"]->Fill(num_pileup_vertices, zpull);
684 
685  mes_[label][prefix + "_ResolX_vs_NumTracks"]->Fill(v.nRecoTrk, xresol);
686  mes_[label][prefix + "_ResolY_vs_NumTracks"]->Fill(v.nRecoTrk, yresol);
687  mes_[label][prefix + "_ResolZ_vs_NumTracks"]->Fill(v.nRecoTrk, zresol);
688  mes_[label][prefix + "_ResolPt2_vs_NumTracks"]->Fill(v.nRecoTrk, pt2resol);
689  mes_[label][prefix + "_PullX_vs_NumTracks"]->Fill(v.nRecoTrk, xpull);
690  mes_[label][prefix + "_PullY_vs_NumTracks"]->Fill(v.nRecoTrk, ypull);
691  mes_[label][prefix + "_PullZ_vs_NumTracks"]->Fill(v.nRecoTrk, zpull);
692 
693  mes_[label][prefix + "_ResolX_vs_Z"]->Fill(v.z, xresol);
694  mes_[label][prefix + "_ResolY_vs_Z"]->Fill(v.z, yresol);
695  mes_[label][prefix + "_ResolZ_vs_Z"]->Fill(v.z, zresol);
696  mes_[label][prefix + "_ResolPt2_vs_Z"]->Fill(v.z, pt2resol);
697  mes_[label][prefix + "_PullX_vs_Z"]->Fill(v.z, xpull);
698  mes_[label][prefix + "_PullY_vs_Z"]->Fill(v.z, ypull);
699  mes_[label][prefix + "_PullZ_vs_Z"]->Fill(v.z, zpull);
700 
701  mes_[label][prefix + "_ResolX_vs_Pt"]->Fill(v.pt, xresol);
702  mes_[label][prefix + "_ResolY_vs_Pt"]->Fill(v.pt, yresol);
703  mes_[label][prefix + "_ResolZ_vs_Pt"]->Fill(v.pt, zresol);
704  mes_[label][prefix + "_ResolPt2_vs_Pt"]->Fill(v.pt, pt2resol);
705  mes_[label][prefix + "_PullX_vs_Pt"]->Fill(v.pt, xpull);
706  mes_[label][prefix + "_PullY_vs_Pt"]->Fill(v.pt, ypull);
707  mes_[label][prefix + "_PullZ_vs_Pt"]->Fill(v.pt, zpull);
708 }
709 
711  auto found = r2s_->find(recoTrack);
712 
713  // reco track not matched to any TP
714  if (found == r2s_->end())
715  return false;
716 
717  // reco track matched to some TP from signal vertex
718  for (const auto& tp : found->val) {
719  if (tp.first->eventId().bunchCrossing() == 0 && tp.first->eventId().event() == 0)
720  return true;
721  }
722 
723  // reco track not matched to any TP from signal vertex
724  return false;
725 }
726 
728  std::vector<recoPrimaryVertex>& recopvs,
729  int genpv_position_in_reco_collection,
730  bool signal_is_highest_pt) {
731  if (recopvs.empty())
732  return;
733 
734  std::vector<double> vtx_sumpt_sigmatched;
735  std::vector<double> vtx_sumpt2_sigmatched;
736 
737  vtx_sumpt_sigmatched.reserve(recopvs.size());
738  vtx_sumpt2_sigmatched.reserve(recopvs.size());
739 
740  // Calculate purity
741  for (auto& v : recopvs) {
742  double sumpt_all = 0;
743  double sumpt_sigmatched = 0;
744  double sumpt2_sigmatched = 0;
745  const reco::Vertex* vertex = v.recVtx;
746  for (auto iTrack = vertex->tracks_begin(); iTrack != vertex->tracks_end(); ++iTrack) {
747  double pt = (*iTrack)->pt();
748  sumpt_all += pt;
749  if (matchRecoTrack2SimSignal(*iTrack)) {
750  sumpt_sigmatched += pt;
751  sumpt2_sigmatched += pt * pt;
752  }
753  }
754  v.purity = sumpt_sigmatched / sumpt_all;
755 
756  vtx_sumpt_sigmatched.push_back(sumpt_sigmatched);
757  vtx_sumpt2_sigmatched.push_back(sumpt2_sigmatched);
758  }
759 
760  const double vtxAll_sumpt_sigmatched = std::accumulate(vtx_sumpt_sigmatched.begin(), vtx_sumpt_sigmatched.end(), 0.0);
761  const double vtxNot0_sumpt_sigmatched = vtxAll_sumpt_sigmatched - vtx_sumpt_sigmatched[0];
762  const double missing = vtxNot0_sumpt_sigmatched / vtxAll_sumpt_sigmatched;
763 
764  // Fill purity
765  std::string prefix = "RecoPVAssoc2GenPVNotMatched_";
766  if (genpv_position_in_reco_collection == 0)
767  prefix = "RecoPVAssoc2GenPVMatched_";
768 
769  mes_[label][prefix + "Purity"]->Fill(recopvs[0].purity);
770  mes_[label][prefix + "Missing"]->Fill(missing);
771  auto hpurity = mes_[label][prefix + "Purity_vs_Index"];
772  for (size_t i = 0; i < recopvs.size(); ++i) {
773  hpurity->Fill(i, recopvs[i].purity);
774  }
775 
776  // Fill sumpt2
777  for (size_t i = 0; i < recopvs.size(); ++i) {
778  if (static_cast<int>(i) == genpv_position_in_reco_collection) {
779  mes_[label]["RecoAssoc2GenPVMatched_Pt2"]->Fill(recopvs[i].ptsq);
780  } else {
781  double pt2 = recopvs[i].ptsq;
782  mes_[label]["RecoAssoc2GenPVNotMatched_Pt2"]->Fill(pt2);
783  // Subtract hard-scatter track pt2 from the pileup pt2
784  double pt2_pu = pt2 - vtx_sumpt2_sigmatched[i];
785  mes_[label]["RecoAssoc2GenPVNotMatched_GenPVTracksRemoved_Pt2"]->Fill(pt2_pu);
786  }
787  }
788  if (!signal_is_highest_pt && genpv_position_in_reco_collection >= 0)
789  mes_[label]["RecoAssoc2GenPVMatchedNotHighest_Pt2"]->Fill(recopvs[genpv_position_in_reco_collection].ptsq);
790 }
791 
792 /* Extract information form TrackingParticles/TrackingVertex and fill
793  * the helper class simPrimaryVertex with proper generation-level
794  * information */
795 std::vector<PrimaryVertexAnalyzer4PUSlimmed::simPrimaryVertex> PrimaryVertexAnalyzer4PUSlimmed::getSimPVs(
797  std::vector<PrimaryVertexAnalyzer4PUSlimmed::simPrimaryVertex> simpv;
798  int current_event = -1;
799 
800  if (verbose_) {
801  std::cout << "getSimPVs TrackingVertexCollection " << std::endl;
802  }
803 
804  for (TrackingVertexCollection::const_iterator v = tVC->begin(); v != tVC->end(); ++v) {
805  if (verbose_) {
806  std::cout << "BunchX.EventId: " << v->eventId().bunchCrossing() << "." << (v->eventId()).event()
807  << " Position: " << v->position() << " G4/HepMC Vertices: " << v->g4Vertices().size() << "/"
808  << v->genVertices().size() << " t = " << v->position().t() * 1.e12
809  << " == 0:" << (v->position().t() > 0) << std::endl;
810  for (TrackingVertex::g4v_iterator gv = v->g4Vertices_begin(); gv != v->g4Vertices_end(); gv++) {
811  std::cout << *gv << std::endl;
812  }
813  std::cout << "----------" << std::endl;
814 
815  } // end of verbose_ session
816 
817  // I'd rather change this and select only vertices that come from
818  // BX=0. We should keep only the first vertex from all the events
819  // at BX=0.
820  if (v->eventId().bunchCrossing() != 0)
821  continue;
822  if (v->eventId().event() != current_event) {
823  current_event = v->eventId().event();
824  } else {
825  continue;
826  }
827  // TODO(rovere) is this really necessary?
828  if (fabs(v->position().z()) > 1000)
829  continue; // skip funny junk vertices
830 
831  // could be a new vertex, check all primaries found so far to avoid
832  // multiple entries
833  simPrimaryVertex sv(v->position().x(), v->position().y(), v->position().z());
834  sv.eventId = v->eventId();
835  sv.sim_vertex = TrackingVertexRef(tVC, std::distance(tVC->begin(), v));
836 
837  for (TrackingParticleRefVector::iterator iTrack = v->daughterTracks_begin(); iTrack != v->daughterTracks_end();
838  ++iTrack) {
839  // TODO(rovere) isn't it always the case? Is it really worth
840  // checking this out?
841  // sv.eventId = (**iTrack).eventId();
842  assert((**iTrack).eventId().bunchCrossing() == 0);
843  }
844  // TODO(rovere) maybe get rid of this old logic completely ... ?
845  simPrimaryVertex* vp = nullptr; // will become non-NULL if a vertex
846  // is found and then point to it
847  for (std::vector<simPrimaryVertex>::iterator v0 = simpv.begin(); v0 != simpv.end(); v0++) {
848  if ((sv.eventId == v0->eventId) && (fabs(sv.x - v0->x) < 1e-5) && (fabs(sv.y - v0->y) < 1e-5) &&
849  (fabs(sv.z - v0->z) < 1e-5)) {
850  vp = &(*v0);
851  break;
852  }
853  }
854  if (!vp) {
855  // this is a new vertex, add it to the list of sim-vertices
856  simpv.push_back(sv);
857  vp = &simpv.back();
858  if (verbose_) {
859  std::cout << "this is a new vertex " << sv.eventId.event() << " " << sv.x << " " << sv.y << " " << sv.z
860  << std::endl;
861  }
862  } else {
863  if (verbose_) {
864  std::cout << "this is not a new vertex" << sv.x << " " << sv.y << " " << sv.z << std::endl;
865  }
866  }
867 
868  // Loop over daughter track(s) as Tracking Particles
869  for (TrackingVertex::tp_iterator iTP = v->daughterTracks_begin(); iTP != v->daughterTracks_end(); ++iTP) {
870  auto momentum = (*(*iTP)).momentum();
871  const reco::Track* matched_best_reco_track = nullptr;
872  double match_quality = -1;
873  if (use_only_charged_tracks_ && (**iTP).charge() == 0)
874  continue;
875  if (s2r_->find(*iTP) != s2r_->end()) {
876  matched_best_reco_track = (*s2r_)[*iTP][0].first.get();
877  match_quality = (*s2r_)[*iTP][0].second;
878  }
879  if (verbose_) {
880  std::cout << " Daughter momentum: " << momentum;
881  std::cout << " Daughter type " << (*(*iTP)).pdgId();
882  std::cout << " matched: " << (matched_best_reco_track != nullptr);
883  std::cout << " match-quality: " << match_quality;
884  std::cout << std::endl;
885  }
886  vp->ptot.setPx(vp->ptot.x() + momentum.x());
887  vp->ptot.setPy(vp->ptot.y() + momentum.y());
888  vp->ptot.setPz(vp->ptot.z() + momentum.z());
889  vp->ptot.setE(vp->ptot.e() + (**iTP).energy());
890  vp->ptsq += ((**iTP).pt() * (**iTP).pt());
891  // TODO(rovere) only select charged sim-particles? If so, maybe
892  // put it as a configuration parameter?
893  if (matched_best_reco_track) {
895  vp->average_match_quality += match_quality;
896  }
897  // TODO(rovere) get rid of cuts on sim-tracks
898  // TODO(rovere) be consistent between simulated tracks and
899  // reconstructed tracks selection
900  // count relevant particles
901  if (((**iTP).pt() > 0.2) && (fabs((**iTP).eta()) < 2.5) && (**iTP).charge() != 0) {
902  vp->nGenTrk++;
903  }
904  } // End of for loop on daughters sim-particles
905  if (vp->num_matched_reco_tracks)
906  vp->average_match_quality /= static_cast<float>(vp->num_matched_reco_tracks);
907  if (verbose_) {
908  std::cout << "average number of associated tracks: "
909  << vp->num_matched_reco_tracks / static_cast<float>(vp->nGenTrk)
910  << " with average quality: " << vp->average_match_quality << std::endl;
911  }
912  } // End of for loop on tracking vertices
913 
914  if (verbose_) {
915  std::cout << "------- PrimaryVertexAnalyzer4PUSlimmed simPVs from "
916  "TrackingVertices "
917  "-------"
918  << std::endl;
919  for (std::vector<simPrimaryVertex>::iterator v0 = simpv.begin(); v0 != simpv.end(); v0++) {
920  std::cout << "z=" << v0->z << " event=" << v0->eventId.event() << std::endl;
921  }
922  std::cout << "-----------------------------------------------" << std::endl;
923  } // End of for summary on discovered simulated primary vertices.
924 
925  // In case of no simulated vertices, break here
926  if (simpv.empty())
927  return simpv;
928 
929  // Now compute the closest distance in z between all simulated vertex
930  // first initialize
931  auto prev_z = simpv.back().z;
932  for (simPrimaryVertex& vsim : simpv) {
933  vsim.closest_vertex_distance_z = std::abs(vsim.z - prev_z);
934  prev_z = vsim.z;
935  }
936  // then calculate
937  for (std::vector<simPrimaryVertex>::iterator vsim = simpv.begin(); vsim != simpv.end(); vsim++) {
938  std::vector<simPrimaryVertex>::iterator vsim2 = vsim;
939  vsim2++;
940  for (; vsim2 != simpv.end(); vsim2++) {
941  double distance = std::abs(vsim->z - vsim2->z);
942  // need both to be complete
943  vsim->closest_vertex_distance_z = std::min(vsim->closest_vertex_distance_z, distance);
944  vsim2->closest_vertex_distance_z = std::min(vsim2->closest_vertex_distance_z, distance);
945  }
946  }
947  return simpv;
948 }
949 
950 /* Extract information form recoVertex and fill the helper class
951  * recoPrimaryVertex with proper reco-level information */
952 std::vector<PrimaryVertexAnalyzer4PUSlimmed::recoPrimaryVertex> PrimaryVertexAnalyzer4PUSlimmed::getRecoPVs(
953  const edm::Handle<edm::View<reco::Vertex>>& tVC) {
954  std::vector<PrimaryVertexAnalyzer4PUSlimmed::recoPrimaryVertex> recopv;
955 
956  if (verbose_) {
957  std::cout << "getRecoPVs TrackingVertexCollection " << std::endl;
958  }
959 
960  for (auto v = tVC->begin(); v != tVC->end(); ++v) {
961  if (verbose_) {
962  std::cout << " Position: " << v->position() << std::endl;
963  }
964 
965  // Skip junk vertices
966  if (fabs(v->z()) > 1000)
967  continue;
968  if (v->isFake() || !v->isValid())
969  continue;
970 
971  recoPrimaryVertex sv(v->position().x(), v->position().y(), v->position().z());
972  sv.recVtx = &(*v);
973  sv.recVtxRef = reco::VertexBaseRef(tVC, std::distance(tVC->begin(), v));
974  // this is a new vertex, add it to the list of reco-vertices
975  recopv.push_back(sv);
977 
978  // Loop over daughter track(s)
979  for (auto iTrack = v->tracks_begin(); iTrack != v->tracks_end(); ++iTrack) {
980  auto momentum = (*(*iTrack)).innerMomentum();
981  // TODO(rovere) better handle the pixelVertices, whose tracks
982  // do not have the innerMomentum defined. This is a temporary
983  // hack to overcome this problem.
984  if (momentum.mag2() == 0)
985  momentum = (*(*iTrack)).momentum();
986  if (verbose_) {
987  std::cout << " Daughter momentum: " << momentum;
988  std::cout << std::endl;
989  }
990  vp->pt += std::sqrt(momentum.perp2());
991  vp->ptsq += (momentum.perp2());
992  vp->nRecoTrk++;
993 
994  auto matched = r2s_->find(*iTrack);
995  if (matched != r2s_->end()) {
997  }
998 
999  } // End of for loop on daughters reconstructed tracks
1000  } // End of for loop on tracking vertices
1001 
1002  if (verbose_) {
1003  std::cout << "------- PrimaryVertexAnalyzer4PUSlimmed recoPVs from "
1004  "VertexCollection "
1005  "-------"
1006  << std::endl;
1007  for (std::vector<recoPrimaryVertex>::iterator v0 = recopv.begin(); v0 != recopv.end(); v0++) {
1008  std::cout << "z=" << v0->z << std::endl;
1009  }
1010  std::cout << "-----------------------------------------------" << std::endl;
1011  } // End of for summary on reconstructed primary vertices.
1012 
1013  // In case of no reco vertices, break here
1014  if (recopv.empty())
1015  return recopv;
1016 
1017  // Now compute the closest distance in z between all reconstructed vertex
1018  // first initialize
1019  auto prev_z = recopv.back().z;
1020  for (recoPrimaryVertex& vreco : recopv) {
1021  vreco.closest_vertex_distance_z = std::abs(vreco.z - prev_z);
1022  prev_z = vreco.z;
1023  }
1024  for (std::vector<recoPrimaryVertex>::iterator vreco = recopv.begin(); vreco != recopv.end(); vreco++) {
1025  std::vector<recoPrimaryVertex>::iterator vreco2 = vreco;
1026  vreco2++;
1027  for (; vreco2 != recopv.end(); vreco2++) {
1028  double distance = std::abs(vreco->z - vreco2->z);
1029  // need both to be complete
1030  vreco->closest_vertex_distance_z = std::min(vreco->closest_vertex_distance_z, distance);
1031  vreco2->closest_vertex_distance_z = std::min(vreco2->closest_vertex_distance_z, distance);
1032  }
1033  }
1034  return recopv;
1035 }
1036 
1037 void PrimaryVertexAnalyzer4PUSlimmed::resetSimPVAssociation(std::vector<simPrimaryVertex>& simpv) {
1038  for (auto& v : simpv) {
1039  v.rec_vertices.clear();
1040  }
1041 }
1042 
1043 // ------------ method called to produce the data ------------
1044 void PrimaryVertexAnalyzer4PUSlimmed::matchSim2RecoVertices(std::vector<simPrimaryVertex>& simpv,
1045  const reco::VertexSimToRecoCollection& vertex_s2r) {
1046  if (verbose_) {
1047  std::cout << "PrimaryVertexAnalyzer4PUSlimmed::matchSim2RecoVertices " << std::endl;
1048  }
1049  for (std::vector<simPrimaryVertex>::iterator vsim = simpv.begin(); vsim != simpv.end(); vsim++) {
1050  auto matched = vertex_s2r.find(vsim->sim_vertex);
1051  if (matched != vertex_s2r.end()) {
1052  for (const auto& vertexRefQuality : matched->val) {
1053  vsim->rec_vertices.push_back(&(*(vertexRefQuality.first)));
1054  }
1055  }
1056 
1057  if (verbose_) {
1058  if (!vsim->rec_vertices.empty()) {
1059  for (auto const& v : vsim->rec_vertices) {
1060  std::cout << "Found a matching vertex for genVtx " << vsim->z << " at " << v->z()
1061  << " with sign: " << fabs(v->z() - vsim->z) / v->zError() << std::endl;
1062  }
1063  } else {
1064  std::cout << "No matching vertex for " << vsim->z << std::endl;
1065  }
1066  }
1067  } // end for loop on simulated vertices
1068  if (verbose_) {
1069  std::cout << "Done with matching sim vertices" << std::endl;
1070  }
1071 }
1072 
1073 void PrimaryVertexAnalyzer4PUSlimmed::matchReco2SimVertices(std::vector<recoPrimaryVertex>& recopv,
1074  const reco::VertexRecoToSimCollection& vertex_r2s,
1075  const std::vector<simPrimaryVertex>& simpv) {
1076  for (std::vector<recoPrimaryVertex>::iterator vrec = recopv.begin(); vrec != recopv.end(); vrec++) {
1077  auto matched = vertex_r2s.find(vrec->recVtxRef);
1078  if (matched != vertex_r2s.end()) {
1079  for (const auto& vertexRefQuality : matched->val) {
1080  const auto tvPtr = &(*(vertexRefQuality.first));
1081  vrec->sim_vertices.push_back(tvPtr);
1082  }
1083 
1084  for (const TrackingVertex* tv : vrec->sim_vertices) {
1085  // Set pointers to internal simVertex objects
1086  for (const auto& vv : simpv) {
1087  if (&(*(vv.sim_vertex)) == tv) {
1088  vrec->sim_vertices_internal.push_back(&vv);
1089  continue;
1090  }
1091  }
1092 
1093  // Calculate number of shared tracks
1094  vrec->sim_vertices_num_shared_tracks.push_back(calculateVertexSharedTracks(*(vrec->recVtx), *tv, *r2s_));
1095  }
1096  }
1097 
1098  if (verbose_) {
1099  for (auto v : vrec->sim_vertices) {
1100  std::cout << "Found a matching vertex for reco: " << vrec->z << " at gen:" << v->position().z()
1101  << " with sign: " << fabs(vrec->z - v->position().z()) / vrec->recVtx->zError() << std::endl;
1102  }
1103  }
1104  } // end for loop on reconstructed vertices
1105 }
1106 
1108  using edm::Handle;
1109  using edm::View;
1110  using std::cout;
1111  using std::endl;
1112  using std::vector;
1113  using namespace reco;
1114 
1115  std::vector<float> pileUpInfo_z;
1116 
1117  // get the pileup information
1119  if (iEvent.getByToken(vecPileupSummaryInfoToken_, puinfoH)) {
1120  for (auto const& pu_info : *puinfoH.product()) {
1121  if (do_generic_sim_plots_) {
1122  mes_["root_folder"]["GenVtx_vs_BX"]->Fill(pu_info.getBunchCrossing(), pu_info.getPU_NumInteractions());
1123  }
1124  if (pu_info.getBunchCrossing() == 0) {
1125  pileUpInfo_z = pu_info.getPU_zpositions();
1126  if (verbose_) {
1127  for (auto const& p : pileUpInfo_z) {
1128  std::cout << "PileUpInfo on Z vertex: " << p << std::endl;
1129  }
1130  }
1131  break;
1132  }
1133  }
1134  }
1135 
1137  iEvent.getByToken(trackingParticleCollectionToken_, TPCollectionH);
1138  if (!TPCollectionH.isValid())
1139  edm::LogWarning("PrimaryVertexAnalyzer4PUSlimmed") << "TPCollectionH is not valid";
1140 
1142  iEvent.getByToken(trackingVertexCollectionToken_, TVCollectionH);
1143  if (!TVCollectionH.isValid())
1144  edm::LogWarning("PrimaryVertexAnalyzer4PUSlimmed") << "TVCollectionH is not valid";
1145 
1146  // TODO(rovere) the idea is to put in case a track-selector in front
1147  // of this module and then use its label to get the selected tracks
1148  // out of the event instead of making an hard-coded selection in the
1149  // code.
1150 
1152  iEvent.getByToken(simToRecoAssociationToken_, simToRecoH);
1153  if (simToRecoH.isValid())
1154  s2r_ = simToRecoH.product();
1155  else
1156  edm::LogWarning("PrimaryVertexAnalyzer4PUSlimmed") << "simToRecoH is not valid";
1157 
1159  iEvent.getByToken(recoToSimAssociationToken_, recoToSimH);
1160  if (recoToSimH.isValid())
1161  r2s_ = recoToSimH.product();
1162  else
1163  edm::LogWarning("PrimaryVertexAnalyzer4PUSlimmed") << "recoToSimH is not valid";
1164 
1165  // Vertex associator
1167  iEvent.getByToken(vertexAssociatorToken_, vertexAssociatorH);
1168  if (!vertexAssociatorH.isValid()) {
1169  edm::LogWarning("PrimaryVertexAnalyzer4PUSlimmed") << "vertexAssociatorH is not valid";
1170  return;
1171  }
1172  const reco::VertexToTrackingVertexAssociator& vertexAssociator = *(vertexAssociatorH.product());
1173 
1174  std::vector<simPrimaryVertex> simpv; // a list of simulated primary
1175  // MC vertices
1176  // TODO(rovere) use move semantic?
1177  simpv = getSimPVs(TVCollectionH);
1178  // TODO(rovere) 1 vertex is not, by definition, pileup, and should
1179  // probably be subtracted?
1180  int kind_of_signal_vertex = 0;
1181  int num_pileup_vertices = simpv.size();
1183  mes_["root_folder"]["GenAllV_NumVertices"]->Fill(simpv.size());
1184  bool signal_is_highest_pt =
1185  std::max_element(simpv.begin(), simpv.end(), [](const simPrimaryVertex& lhs, const simPrimaryVertex& rhs) {
1186  return lhs.ptsq < rhs.ptsq;
1187  }) == simpv.begin();
1188  kind_of_signal_vertex |= (signal_is_highest_pt << HIGHEST_PT);
1189  if (do_generic_sim_plots_) {
1190  mes_["root_folder"]["SignalIsHighestPt2"]->Fill(signal_is_highest_pt ? 1. : 0.);
1191  computePairDistance(simpv, mes_["root_folder"]["GenAllV_PairDistanceZ"]);
1192  }
1193 
1194  int label_index = -1;
1195  for (size_t iToken = 0, endToken = reco_vertex_collection_tokens_.size(); iToken < endToken; ++iToken) {
1196  auto const& vertex_token = reco_vertex_collection_tokens_[iToken];
1197  std::vector<recoPrimaryVertex> recopv; // a list of reconstructed
1198  // primary MC vertices
1199  std::string label = reco_vertex_collections_[++label_index].label();
1201  if (!iEvent.getByToken(vertex_token, recVtxs)) {
1202  if (!errorPrintedForColl_[iToken]) {
1203  edm::LogWarning("PrimaryVertexAnalyzer4PUSlimmed")
1204  << "Skipping vertex collection: " << label << " since it is missing.";
1205  errorPrintedForColl_[iToken] = true;
1206  }
1207  continue;
1208  }
1209 
1210  {
1211  // check upfront that refs to track are (likely) to be valid
1212  bool ok = true;
1213  for (const auto& v : *recVtxs) {
1214  if (v.tracksSize() > 0) {
1215  const auto& ref = v.trackRefAt(0);
1216  if (ref.isNull() || !ref.isAvailable()) {
1217  if (!errorPrintedForColl_[iToken]) {
1218  edm::LogWarning("PrimaryVertexAnalyzer4PUSlimmed")
1219  << "Skipping vertex collection: " << label
1220  << " since likely the track collection the vertex has refs pointing to is missing (at least the "
1221  "first TrackBaseRef is null or not available)";
1222  errorPrintedForColl_[iToken] = true;
1223  }
1224  ok = false;
1225  }
1226  }
1227  }
1228  if (!ok)
1229  continue;
1230  }
1231 
1232  reco::VertexRecoToSimCollection vertex_r2s = vertexAssociator.associateRecoToSim(recVtxs, TVCollectionH);
1233  reco::VertexSimToRecoCollection vertex_s2r = vertexAssociator.associateSimToReco(recVtxs, TVCollectionH);
1234 
1235  resetSimPVAssociation(simpv);
1236  matchSim2RecoVertices(simpv, vertex_s2r);
1237  recopv = getRecoPVs(recVtxs);
1238  computePairDistance(recopv, mes_[label]["RecoAllAssoc2Gen_PairDistanceZ"]);
1239  matchReco2SimVertices(recopv, vertex_r2s, simpv);
1240 
1241  int num_total_gen_vertices_assoc2reco = 0;
1242  int num_total_reco_vertices_assoc2gen = 0;
1243  int num_total_gen_vertices_multiassoc2reco = 0;
1244  int num_total_reco_vertices_multiassoc2gen = 0;
1245  int num_total_reco_vertices_duplicate = 0;
1246  int genpv_position_in_reco_collection = -1;
1247  for (auto const& v : simpv) {
1248  float mistag = 1.;
1249  // TODO(rovere) put selectors here in front of fill* methods.
1250  if (v.eventId.event() == 0) {
1251  if (!recVtxs->empty() && std::find(v.rec_vertices.begin(), v.rec_vertices.end(), &((*recVtxs.product())[0])) !=
1252  v.rec_vertices.end()) {
1253  mistag = 0.;
1254  kind_of_signal_vertex |= (1 << IS_ASSOC2FIRST_RECO);
1255  } else {
1256  if (!v.rec_vertices.empty()) {
1257  kind_of_signal_vertex |= (1 << IS_ASSOC2ANY_RECO);
1258  }
1259  }
1260  mes_[label]["KindOfSignalPV"]->Fill(kind_of_signal_vertex);
1261  mes_[label]["MisTagRate"]->Fill(mistag);
1262  mes_[label]["MisTagRate_vs_PU"]->Fill(simpv.size(), mistag);
1263  mes_[label]["MisTagRate_vs_sum-pt2"]->Fill(v.ptsq, mistag);
1264  mes_[label]["MisTagRate_vs_Z"]->Fill(v.z, mistag);
1265  mes_[label]["MisTagRate_vs_R"]->Fill(v.r, mistag);
1266  mes_[label]["MisTagRate_vs_NumTracks"]->Fill(v.nGenTrk, mistag);
1267  if (signal_is_highest_pt) {
1268  mes_[label]["MisTagRateSignalIsHighest"]->Fill(mistag);
1269  mes_[label]["MisTagRateSignalIsHighest_vs_PU"]->Fill(simpv.size(), mistag);
1270  mes_[label]["MisTagRateSignalIsHighest_vs_sum-pt2"]->Fill(v.ptsq, mistag);
1271  mes_[label]["MisTagRateSignalIsHighest_vs_Z"]->Fill(v.z, mistag);
1272  mes_[label]["MisTagRateSignalIsHighest_vs_R"]->Fill(v.r, mistag);
1273  mes_[label]["MisTagRateSignalIsHighest_vs_NumTracks"]->Fill(v.nGenTrk, mistag);
1274  } else {
1275  mes_[label]["MisTagRateSignalIsNotHighest"]->Fill(mistag);
1276  mes_[label]["MisTagRateSignalIsNotHighest_vs_PU"]->Fill(simpv.size(), mistag);
1277  mes_[label]["MisTagRateSignalIsNotHighest_vs_sum-pt2"]->Fill(v.ptsq, mistag);
1278  mes_[label]["MisTagRateSignalIsNotHighest_vs_Z"]->Fill(v.z, mistag);
1279  mes_[label]["MisTagRateSignalIsNotHighest_vs_R"]->Fill(v.r, mistag);
1280  mes_[label]["MisTagRateSignalIsNotHighest_vs_NumTracks"]->Fill(v.nGenTrk, mistag);
1281  }
1282  // Now check at which location the Simulated PV has been
1283  // reconstructed in the primary vertex collection
1284  // at-hand. Mark it with fake index -1 if it was not
1285  // reconstructed at all.
1286 
1287  auto iv = (*recVtxs.product()).begin();
1288  for (int pv_position_in_reco_collection = 0; iv != (*recVtxs.product()).end();
1289  ++pv_position_in_reco_collection, ++iv) {
1290  if (std::find(v.rec_vertices.begin(), v.rec_vertices.end(), &(*iv)) != v.rec_vertices.end()) {
1291  mes_[label]["TruePVLocationIndex"]->Fill(pv_position_in_reco_collection);
1292  const bool genPVMatchedToRecoPV = (pv_position_in_reco_collection == 0);
1293  mes_[label]["TruePVLocationIndexCumulative"]->Fill(genPVMatchedToRecoPV ? 0 : 1);
1294 
1295  if (signal_is_highest_pt) {
1296  mes_[label]["TruePVLocationIndexSignalIsHighest"]->Fill(pv_position_in_reco_collection);
1297  } else {
1298  mes_[label]["TruePVLocationIndexSignalIsNotHighest"]->Fill(pv_position_in_reco_collection);
1299  }
1300 
1301  fillRecoAssociatedGenPVHistograms(label, v, genPVMatchedToRecoPV);
1302  if (genPVMatchedToRecoPV) {
1303  auto pv = recopv[0];
1304  assert(pv.recVtx == &(*iv));
1305  fillResolutionAndPullHistograms(label, num_pileup_vertices, pv, true);
1306  }
1307  genpv_position_in_reco_collection = pv_position_in_reco_collection;
1308  break;
1309  }
1310  }
1311 
1312  // If we reached the end, it means that the Simulated PV has not
1313  // been associated to any reconstructed vertex: mark it as
1314  // missing in the reconstructed vertex collection using the fake
1315  // index -1.
1316  if (iv == (*recVtxs.product()).end()) {
1317  mes_[label]["TruePVLocationIndex"]->Fill(-1.);
1318  mes_[label]["TruePVLocationIndexCumulative"]->Fill(-1.);
1319  if (signal_is_highest_pt)
1320  mes_[label]["TruePVLocationIndexSignalIsHighest"]->Fill(-1.);
1321  else
1322  mes_[label]["TruePVLocationIndexSignalIsNotHighest"]->Fill(-1.);
1323  }
1324  }
1325 
1326  if (!v.rec_vertices.empty())
1327  num_total_gen_vertices_assoc2reco++;
1328  if (v.rec_vertices.size() > 1)
1329  num_total_gen_vertices_multiassoc2reco++;
1330  // No need to N-tplicate the Gen-related cumulative histograms:
1331  // fill them only at the first iteration
1332  if (do_generic_sim_plots_ && label_index == 0)
1335  }
1336  calculatePurityAndFillHistograms(label, recopv, genpv_position_in_reco_collection, signal_is_highest_pt);
1337 
1338  mes_[label]["GenAllAssoc2Reco_NumVertices"]->Fill(simpv.size(), simpv.size());
1339  mes_[label]["GenAllAssoc2RecoMatched_NumVertices"]->Fill(simpv.size(), num_total_gen_vertices_assoc2reco);
1340  mes_[label]["GenAllAssoc2RecoMultiMatched_NumVertices"]->Fill(simpv.size(), num_total_gen_vertices_multiassoc2reco);
1341  for (auto& v : recopv) {
1342  fillGenAssociatedRecoVertexHistograms(label, num_pileup_vertices, v);
1343  if (!v.sim_vertices.empty()) {
1344  num_total_reco_vertices_assoc2gen++;
1345  if (v.sim_vertices_internal[0]->rec_vertices.size() > 1) {
1346  num_total_reco_vertices_duplicate++;
1347  }
1348  }
1349  if (v.sim_vertices.size() > 1)
1350  num_total_reco_vertices_multiassoc2gen++;
1351  }
1352  mes_[label]["RecoAllAssoc2Gen_NumVertices"]->Fill(recopv.size(), recopv.size());
1353  mes_[label]["RecoAllAssoc2GenMatched_NumVertices"]->Fill(recopv.size(), num_total_reco_vertices_assoc2gen);
1354  mes_[label]["RecoAllAssoc2GenMultiMatched_NumVertices"]->Fill(recopv.size(),
1355  num_total_reco_vertices_multiassoc2gen);
1356  mes_[label]["RecoAllAssoc2MultiMatchedGen_NumVertices"]->Fill(recopv.size(), num_total_reco_vertices_duplicate);
1357  mes_[label]["RecoVtx_vs_GenVtx"]->Fill(simpv.size(), recopv.size());
1358  mes_[label]["MatchedRecoVtx_vs_GenVtx"]->Fill(simpv.size(), num_total_reco_vertices_assoc2gen);
1359  }
1360 } // end of analyze
1361 
1362 template <class T>
1364  for (unsigned int i = 0; i < collection.size(); ++i) {
1365  for (unsigned int j = i + 1; j < collection.size(); ++j) {
1366  me->Fill(std::abs(collection[i].z - collection[j].z));
1367  }
1368  }
1369 }
void matchSim2RecoVertices(std::vector< simPrimaryVertex > &, const reco::VertexSimToRecoCollection &)
void fillGenAssociatedRecoVertexHistograms(const std::string &, int, recoPrimaryVertex &v)
std::vector< PrimaryVertexAnalyzer4PUSlimmed::recoPrimaryVertex > getRecoPVs(const edm::Handle< edm::View< reco::Vertex >> &)
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
bool matchRecoTrack2SimSignal(const reco::TrackBaseRef &)
void resetSimPVAssociation(std::vector< simPrimaryVertex > &)
edm::EDGetTokenT< reco::SimToRecoCollection > simToRecoAssociationToken_
int32_t *__restrict__ iv
const double xbins[]
void fillRecoAssociatedGenPVHistograms(const std::string &label, const PrimaryVertexAnalyzer4PUSlimmed::simPrimaryVertex &v, bool genPVMatchedToRecoPV)
void computePairDistance(const T &collection, MonitorElement *me)
std::vector< SimVertex >::const_iterator g4v_iterator
ret
prodAgent to be discontinued
edm::RefToBase< reco::Vertex > VertexBaseRef
persistent reference to a Vertex, using views
Definition: VertexFwd.h:21
T const * product() const
Definition: Handle.h:70
void bookHistograms(DQMStore::IBooker &i, edm::Run const &, edm::EventSetup const &) override
PrimaryVertexAnalyzer4PUSlimmed(const edm::ParameterSet &)
edm::AssociationMap< edm::OneToManyWithQualityGeneric< CaloParticleCollection, reco::CaloClusterCollection, std::pair< float, float > > > SimToRecoCollection
edm::EDGetTokenT< TrackingVertexCollection > trackingVertexCollectionToken_
edm::EDGetTokenT< std::vector< PileupSummaryInfo > > vecPileupSummaryInfoToken_
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
assert(be >=bs)
missing
Definition: combine.py:5
const_iterator find(const key_type &k) const
find element with specified reference key
const_iterator end() const
last iterator over the map (read only)
char const * label
void analyze(const edm::Event &, const edm::EventSetup &) override
int iEvent
Definition: GenABIO.cc:224
std::vector< PrimaryVertexAnalyzer4PUSlimmed::simPrimaryVertex > getSimPVs(const edm::Handle< TrackingVertexCollection > &)
std::vector< edm::InputTag > reco_vertex_collections_
T sqrt(T t)
Definition: SSEVec.h:19
void fillResolutionAndPullHistograms(const std::string &, int, recoPrimaryVertex &v, bool)
def pv(vc)
Definition: MetAnalyzer.py:7
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void calculatePurityAndFillHistograms(const std::string &, std::vector< recoPrimaryVertex > &, int, bool)
const reco::SimToRecoCollection * s2r_
std::vector< edm::EDGetTokenT< edm::View< reco::Vertex > > > reco_vertex_collection_tokens_
void fillGenericGenVertexHistograms(const simPrimaryVertex &v)
edm::Ref< TrackingVertexCollection > TrackingVertexRef
#define N
Definition: blowfish.cc:9
def bestMatch(object, matchCollection)
Definition: deltar.py:138
std::vector< TrackingVertex > TrackingVertexCollection
std::array< T, N+1 > makeLogBins(const T &min, const T &max)
std::map< std::string, std::map< std::string, MonitorElement * > > mes_
void fillRecoAssociatedGenVertexHistograms(const std::string &, const simPrimaryVertex &v)
bool isValid() const
Definition: HandleBase.h:70
void matchReco2SimVertices(std::vector< recoPrimaryVertex > &, const reco::VertexRecoToSimCollection &, const std::vector< simPrimaryVertex > &)
edm::EDGetTokenT< reco::VertexToTrackingVertexAssociator > vertexAssociatorToken_
edm::EDGetTokenT< reco::RecoToSimCollection > recoToSimAssociationToken_
fixed size matrix
HLT enums.
unsigned int calculateVertexSharedTracks(const reco::Vertex &recoV, const TrackingVertex &simV, const reco::RecoToSimCollection &trackRecoToSimAssociation)
std::vector< TrackingParticle > TrackingParticleCollection
Log< level::Warning, false > LogWarning
long double T
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
const reco::RecoToSimCollection * r2s_
Definition: Run.h:45
edm::AssociationMap< edm::OneToManyWithQualityGeneric< reco::CaloClusterCollection, CaloParticleCollection, float > > RecoToSimCollection
edm::EDGetTokenT< TrackingParticleCollection > trackingParticleCollectionToken_