CMS 3D CMS Logo

PrimaryVertexResolution.cc
Go to the documentation of this file.
7 
10 
16 
21 
23 
24 #include <random>
25 
26 namespace {
27  template <typename T, size_t N>
28  std::array<T, N+1> makeLogBins(const double min, const double max) {
29  const double minLog10 = std::log10(min);
30  const double maxLog10 = std::log10(max);
31  const double width = (maxLog10-minLog10)/N;
32  std::array<T, N+1> ret;
33  ret[0] = std::pow(10, minLog10);
34  const double mult = std::pow(10, width);
35  for ( size_t i=1; i<=N; ++i) {
36  ret[i] = ret[i-1]*mult;
37  }
38  return ret;
39  }
40 
41  template <typename T>
42  T sqr(T val) {
43  return val*val;
44  }
45 }
46 
48  public:
50  ~PrimaryVertexResolution() override;
51 
52  void bookHistograms(DQMStore::IBooker&, edm::Run const&, edm::EventSetup const&) override;
53  void analyze(const edm::Event&, const edm::EventSetup& ) override;
54 
55  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
56 
57  private:
58  std::vector<reco::TransientTrack> sortTracksByPt(const reco::Vertex& thePV,
59  const TransientTrackBuilder& ttBuilder,
60  const reco::BeamSpot& beamspot);
61 
67 
69 
70  struct BinningY {
71  explicit BinningY(const edm::ParameterSet& iConfig):
72  maxResol_(iConfig.getUntrackedParameter<double>("maxResol")),
73  binsResol_(iConfig.getUntrackedParameter<int>("binsResol")),
74  maxPull_(iConfig.getUntrackedParameter<double>("maxPull")),
75  binsPull_(iConfig.getUntrackedParameter<int>("binsPull"))
76  {}
77 
78  const double maxResol_;
79  const int binsResol_;
80  const double maxPull_;
81  const int binsPull_;
82  };
83 
84  struct BinningX {
85  explicit BinningX(const edm::ParameterSet& iConfig):
86  minNtracks_(iConfig.getUntrackedParameter<double>("minNtracks")),
87  maxNtracks_(iConfig.getUntrackedParameter<double>("maxNtracks")),
88  binsNtracks_(iConfig.getUntrackedParameter<int>("binsNtracks")),
89  minNvertices_(iConfig.getUntrackedParameter<double>("minNvertices")),
90  maxNvertices_(iConfig.getUntrackedParameter<double>("maxNvertices")),
91  binsNvertices_(iConfig.getUntrackedParameter<int>("binsNvertices")),
92  minPt_(iConfig.getUntrackedParameter<double>("minPt")),
93  maxPt_(iConfig.getUntrackedParameter<double>("maxPt")),
94  minLumi_(iConfig.getUntrackedParameter<double>("minLumi")),
95  maxLumi_(iConfig.getUntrackedParameter<double>("maxLumi"))
96  {}
97 
98  const int minNtracks_;
99  const int maxNtracks_;
100  const int binsNtracks_;
101  const int minNvertices_;
102  const int maxNvertices_;
103  const int binsNvertices_;
104  const double minPt_;
105  const double maxPt_;
106  const double minLumi_;
107  const double maxLumi_;
108  };
109 
110  class Resolution {
111  public:
112  Resolution(const reco::Vertex& vertex1, const reco::Vertex& vertex2) {
113  const double diffx = vertex1.x() - vertex2.x();
114  const double diffy = vertex1.y() - vertex2.y();
115  const double diffz = vertex1.z() - vertex2.z();
116 
117  // Take into account the need to divide by sqrt(2) already in
118  // the filling so that we can use DQMGenericClient for the
119  // gaussian fits
120  const double invSqrt2 = 1./std::sqrt(2.);
121  resx_ = diffx * invSqrt2;
122  resy_ = diffy * invSqrt2;
123  resz_ = diffz * invSqrt2;
124 
125  pullx_ = diffx / std::sqrt(sqr(vertex1.xError()) + sqr(vertex2.xError()));
126  pully_ = diffy / std::sqrt(sqr(vertex1.yError()) + sqr(vertex2.yError()));
127  pullz_ = diffz / std::sqrt(sqr(vertex1.zError()) + sqr(vertex2.zError()));
128  }
129 
130  double resx() const { return resx_; }
131  double resy() const { return resy_; }
132  double resz() const { return resz_; }
133 
134  double pullx() const { return pullx_; }
135  double pully() const { return pully_; }
136  double pullz() const { return pullz_; }
137 
138  private:
139  double resx_;
140  double resy_;
141  double resz_;
142  double pullx_;
143  double pully_;
144  double pullz_;
145  };
146 
147  class DiffPlots {
148  public:
149  explicit DiffPlots(const std::string& postfix, const BinningY& binY):
150  postfix_(postfix),
151  binningY_(binY)
152  {}
153 
154  template <typename T>
155  void bookLogX(DQMStore::IBooker& iBooker, const T& binArray) {
156  book(iBooker, binArray.size()-1, binArray.front(), binArray.back());
157  setLogX(binArray.size()-1, binArray.data());
158  }
159 
160  template <typename ...Args>
161  void book(DQMStore::IBooker& iBooker, Args&&... args) {
162  const auto binsResol = binningY_.binsResol_;
163  const auto maxResol = binningY_.maxResol_;
164  hDiffX_ = iBooker.book2D("res_x_vs_"+postfix_, "Resolution of X vs. "+postfix_, std::forward<Args>(args)..., binsResol,-maxResol,maxResol);
165  hDiffY_ = iBooker.book2D("res_y_vs_"+postfix_, "Resolution of Y vs. "+postfix_, std::forward<Args>(args)..., binsResol,-maxResol,maxResol);
166  hDiffZ_ = iBooker.book2D("res_z_vs_"+postfix_, "Resolution of Z vs. "+postfix_, std::forward<Args>(args)..., binsResol,-maxResol,maxResol);
167 
168  const auto binsPull = binningY_.binsPull_;
169  const auto maxPull = binningY_.maxPull_;
170  hPullX_ = iBooker.book2D("pull_x_vs_"+postfix_, "Pull of X vs. "+postfix_, std::forward<Args>(args)..., binsPull,-maxPull,maxPull);
171  hPullY_ = iBooker.book2D("pull_y_vs_"+postfix_, "Pull of Y vs. "+postfix_, std::forward<Args>(args)..., binsPull,-maxPull,maxPull);
172  hPullZ_ = iBooker.book2D("pull_z_vs_"+postfix_, "Pull of Z vs. "+postfix_, std::forward<Args>(args)..., binsPull,-maxPull,maxPull);
173  }
174  template <typename ...Args>
175  void setLogX(Args&&... args) {
176  hDiffX_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
177  hDiffY_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
178  hDiffZ_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
179 
180  hPullX_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
181  hPullY_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
182  hPullZ_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
183  }
184 
185  template <typename T>
186  void fill(const Resolution& res, const T ref) {
187  hDiffX_->Fill(ref, res.resx());
188  hDiffY_->Fill(ref, res.resy());
189  hDiffZ_->Fill(ref, res.resz());
190  hPullX_->Fill(ref, res.pullx());
191  hPullY_->Fill(ref, res.pully());
192  hPullZ_->Fill(ref, res.pullz());
193  }
194 
195  private:
198  MonitorElement *hDiffX_ = nullptr;
199  MonitorElement *hDiffY_ = nullptr;
200  MonitorElement *hDiffZ_ = nullptr;
201  MonitorElement *hPullX_ = nullptr;
202  MonitorElement *hPullY_ = nullptr;
203  MonitorElement *hPullZ_ = nullptr;
204  };
205 
206  class Plots {
207  public:
208  Plots(const BinningX& binX, const BinningY& binY):
209  binningX_(binX),
210  binningY_(binY),
211  hDiff_Ntracks_("ntracks", binY),
212  hDiff_sumPt_("sumpt", binY),
213  hDiff_Nvertices_("nvertices", binY),
214  hDiff_instLumiScal_("instLumiScal", binY)
215  {}
216 
217  void book(DQMStore::IBooker& iBooker) {
218  const auto binsResol = binningY_.binsResol_;
219  const auto maxResol = binningY_.maxResol_;
220  hDiffX_ = iBooker.book1D("res_x", "Resolution of X", binsResol, -maxResol, maxResol);
221  hDiffY_ = iBooker.book1D("res_y", "Resolution of Y", binsResol, -maxResol, maxResol);
222  hDiffZ_ = iBooker.book1D("res_z", "Resolution of Z", binsResol, -maxResol, maxResol);
223 
224  const auto binsPull = binningY_.binsPull_;
225  const auto maxPull = binningY_.maxPull_;
226  hPullX_ = iBooker.book1D(+"pull_x", "Pull of X", binsPull, -maxPull, maxPull);
227  hPullY_ = iBooker.book1D(+"pull_y", "Pull of Y", binsPull, -maxPull, maxPull);
228  hPullZ_ = iBooker.book1D(+"pull_z", "Pull of Z", binsPull, -maxPull, maxPull);
229 
230  hDiff_Ntracks_.book(iBooker, binningX_.binsNtracks_, binningX_.minNtracks_, binningX_.maxNtracks_);
231  hDiff_Nvertices_.book(iBooker, binningX_.binsNvertices_, binningX_.minNvertices_, binningX_.maxNvertices_);
232 
233  constexpr int binsPt = 30;
234  hDiff_sumPt_.bookLogX(iBooker, makeLogBins<float, binsPt>(binningX_.minPt_, binningX_.maxPt_));
235 
236  constexpr int binsLumi = 100;
237  hDiff_instLumiScal_.bookLogX(iBooker, makeLogBins<float, binsLumi>(binningX_.minLumi_, binningX_.maxLumi_));
238  }
239 
240  void calculateAndFillResolution(const std::vector<reco::TransientTrack>& tracks,
241  size_t nvertices,
242  const LumiScalersCollection& lumiScalers,
243  std::mt19937& engine,
244  AdaptiveVertexFitter& fitter);
245 
246  private:
249 
250  MonitorElement *hDiffX_ = nullptr;
251  MonitorElement *hDiffY_ = nullptr;
252  MonitorElement *hDiffZ_ = nullptr;
253  MonitorElement *hPullX_ = nullptr;
254  MonitorElement *hPullY_ = nullptr;
255  MonitorElement *hPullZ_ = nullptr;
256 
261  };
262 
263  // Binning
266 
267  // Histograms
270 
271  std::mt19937 engine_;
272 };
273 
275  vertexSrc_(consumes<reco::VertexCollection>(iConfig.getUntrackedParameter<edm::InputTag>("vertexSrc"))),
276  beamspotSrc_(consumes<reco::BeamSpot>(iConfig.getUntrackedParameter<edm::InputTag>("beamspotSrc"))),
277  lumiScalersSrc_(consumes<LumiScalersCollection>(iConfig.getUntrackedParameter<edm::InputTag>("lumiScalersSrc"))),
278  rootFolder_(iConfig.getUntrackedParameter<std::string>("rootFolder")),
279  transientTrackBuilder_(iConfig.getUntrackedParameter<std::string>("transientTrackBuilder")),
280  binningX_(iConfig),
281  binningY_(iConfig),
284 {}
285 
287 
290  desc.addUntracked<edm::InputTag>("vertexSrc", edm::InputTag("trackingDQMgoodOfflinePrimaryVertices"));
291  desc.addUntracked<edm::InputTag>("beamspotSrc", edm::InputTag("offlineBeamSpot"));
292  desc.addUntracked<edm::InputTag>("lumiScalersSrc", edm::InputTag("scalersRawToDigi"));
293  desc.addUntracked<std::string>("rootFolder", "OfflinePV/Resolution");
294  desc.addUntracked<std::string>("transientTrackBuilder", "TransientTrackBuilder");
295 
296  // Y axes
297  desc.addUntracked<double>("maxResol", 0.02);
298  desc.addUntracked<int>("binsResol", 100);
299 
300  desc.addUntracked<double>("maxPull", 5);
301  desc.addUntracked<int>("binsPull", 100);
302 
303  // X axes
304  desc.addUntracked<double>("minNtracks", -0.5);
305  desc.addUntracked<double>("maxNtracks", 119.5);
306  desc.addUntracked<int>("binsNtracks", 60);
307 
308  desc.addUntracked<double>("minNvertices", -0.5);
309  desc.addUntracked<double>("maxNvertices", 199.5);
310  desc.addUntracked<int>("binsNvertices", 100);
311 
312  desc.addUntracked<double>("minPt", 1);
313  desc.addUntracked<double>("maxPt", 1e3);
314 
315  desc.addUntracked<double>("minLumi", 200.);
316  desc.addUntracked<double>("maxLumi", 20000.);
317 
318  descriptions.add("primaryVertexResolution", desc);
319 }
320 
322  iBooker.setCurrentFolder(rootFolder_+"/PV");
323  hPV_.book(iBooker);
324 
325  iBooker.setCurrentFolder(rootFolder_+"/OtherV");
326  hOtherV_.book(iBooker);
327 }
328 
331  iEvent.getByToken(vertexSrc_, hvertices);
332  const reco::VertexCollection& vertices = *hvertices;
333  if(vertices.empty())
334  return;
335 
336  edm::Handle<reco::BeamSpot> hbeamspot;
337  iEvent.getByToken(beamspotSrc_, hbeamspot);
338  const reco::BeamSpot& beamspot = *hbeamspot;
339 
341  iEvent.getByToken(lumiScalersSrc_, hscalers);
342  const LumiScalersCollection& lumiScalers = *hscalers;
343 
344  edm::ESHandle<TransientTrackBuilder> ttBuilderHandle;
345  iSetup.get<TransientTrackRecord>().get(transientTrackBuilder_, ttBuilderHandle);
346  const TransientTrackBuilder& ttBuilder = *ttBuilderHandle;
347 
348  // deterministic seed from the event number
349  // should not bias the result as the event number is already
350  // assigned randomly-enough
351  engine_.seed( iEvent.id().event() + (iEvent.id().luminosityBlock()<<10) + (iEvent.id().run()<<20) );
352 
353  // The PV
354  auto iPV = cbegin(vertices);
355  const reco::Vertex& thePV = *iPV;
356  const auto nvertices = vertices.size();
357  if(thePV.tracksSize() >= 4) {
358  auto sortedTracks = sortTracksByPt(thePV, ttBuilder, beamspot);
359  hPV_.calculateAndFillResolution(sortedTracks, nvertices, lumiScalers, engine_, fitter_);
360  }
361  ++iPV;
362 
363  // Other vertices
364  for(auto endPV = cend(vertices); iPV != endPV; ++iPV) {
365  if(iPV->tracksSize() >= 4) {
366  auto sortedTracks = sortTracksByPt(*iPV, ttBuilder, beamspot);
367  hOtherV_.calculateAndFillResolution(sortedTracks, nvertices, lumiScalers, engine_, fitter_);
368  }
369  }
370 }
371 
372 std::vector<reco::TransientTrack> PrimaryVertexResolution::sortTracksByPt(const reco::Vertex& thePV,
373  const TransientTrackBuilder& ttBuilder,
374  const reco::BeamSpot& beamspot) {
375  std::vector<const reco::Track *> sortedTracks;
376  sortedTracks.reserve(thePV.tracksSize());
377  std::transform(thePV.tracks_begin(), thePV.tracks_end(), std::back_inserter(sortedTracks), [](const reco::TrackBaseRef& ref) {
378  return &(*ref);
379  });
380  std::sort(sortedTracks.begin(), sortedTracks.end(), [](const reco::Track *a, const reco::Track *b) {
381  return a->pt() > b->pt();
382  });
383 
384  std::vector<reco::TransientTrack> ttracks;
385  ttracks.reserve(sortedTracks.size());
386  std::transform(sortedTracks.begin(), sortedTracks.end(), std::back_inserter(ttracks), [&](const reco::Track *track) {
387  auto tt = ttBuilder.build(track);
388  tt.setBeamSpot(beamspot);
389  return tt;
390  });
391  return ttracks;
392 }
393 
394 void PrimaryVertexResolution::Plots::calculateAndFillResolution(const std::vector<reco::TransientTrack>& tracks,
395  size_t nvertices,
396  const LumiScalersCollection& lumiScalers,
397  std::mt19937& engine,
398  AdaptiveVertexFitter& fitter) {
399  const size_t end = tracks.size()%2 == 0 ? tracks.size() : tracks.size()-1;
400 
401  std::vector<reco::TransientTrack> set1, set2;
402  set1.reserve(end/2); set2.reserve(end/2);
403 
404  auto dis = std::uniform_int_distribution<>(0, 1); // [0, 1]
405 
406  double sumpt1=0, sumpt2=0;
407  for(size_t i=0; i<end; i += 2) {
408  const size_t set1_i = dis(engine);
409  const size_t set2_i = 1-set1_i;
410 
411  set1.push_back(tracks[i+set1_i]);
412  set2.push_back(tracks[i+set2_i]);
413 
414  sumpt1 += set1.back().track().pt();
415  sumpt2 += set2.back().track().pt();
416  }
417 
418  // For resolution we only fit
419  TransientVertex vertex1 = fitter.vertex(set1);
420  TransientVertex vertex2 = fitter.vertex(set2);
421 
422  Resolution res(vertex1, vertex2);
423  hDiffX_->Fill(res.resx());
424  hDiffY_->Fill(res.resy());
425  hDiffZ_->Fill(res.resz());
426  hPullX_->Fill(res.pullx());
427  hPullY_->Fill(res.pully());
428  hPullZ_->Fill(res.pullz());
429 
430  hDiff_Ntracks_.fill(res, set1.size());
431  hDiff_sumPt_.fill(res, (sumpt1+sumpt2)/2.0); // taking average is probably the best we can do, anyway they should be close to each other
432  hDiff_Nvertices_.fill(res, nvertices);
433 
434  if(!lumiScalers.empty()) {
435  hDiff_instLumiScal_.fill(res, lumiScalers.front().instantLumi());
436  }
437 }
438 
RunNumber_t run() const
Definition: EventID.h:39
EventNumber_t event() const
Definition: EventID.h:41
BinningX(const edm::ParameterSet &iConfig)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
trackRef_iterator tracks_end() const
last iterator over tracks
Definition: Vertex.cc:81
void book(DQMStore::IBooker &iBooker)
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
double zError() const
error on z
Definition: Vertex.h:123
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
void calculateAndFillResolution(const std::vector< reco::TransientTrack > &tracks, size_t nvertices, const LumiScalersCollection &lumiScalers, std::mt19937 &engine, AdaptiveVertexFitter &fitter)
double y() const
y coordinate
Definition: Vertex.h:113
PrimaryVertexResolution(const edm::ParameterSet &iConfig)
reco::TransientTrack build(const reco::Track *p) const
CachingVertex< 5 > vertex(const std::vector< reco::TransientTrack > &) const override
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
void analyze(const edm::Event &, const edm::EventSetup &) override
LuminosityBlockNumber_t luminosityBlock() const
Definition: EventID.h:40
#define constexpr
Definition: Electron.h:6
Plots(const BinningX &binX, const BinningY &binY)
int iEvent
Definition: GenABIO.cc:230
void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:268
T sqrt(T t)
Definition: SSEVec.h:18
void fill(const Resolution &res, const T ref)
double pt() const
track transverse momentum
Definition: TrackBase.h:621
void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override
BinningY(const edm::ParameterSet &iConfig)
MonitorElement * book1D(Args &&...args)
Definition: DQMStore.h:106
edm::EDGetTokenT< LumiScalersCollection > lumiScalersSrc_
double z() const
z coordinate
Definition: Vertex.h:115
#define end
Definition: vmac.h:39
void bookLogX(DQMStore::IBooker &iBooker, const T &binArray)
T min(T a, T b)
Definition: MathUtil.h:58
std::array< T, N+1 > makeLogBins(const T min, const T max)
edm::EDGetTokenT< reco::VertexCollection > vertexSrc_
DiffPlots(const std::string &postfix, const BinningY &binY)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
double x() const
x coordinate
Definition: Vertex.h:111
double xError() const
error on x
Definition: Vertex.h:119
#define N
Definition: blowfish.cc:9
MonitorElement * book2D(Args &&...args)
Definition: DQMStore.h:109
edm::EDGetTokenT< reco::BeamSpot > beamspotSrc_
double b
Definition: hdecay.h:120
void add(std::string const &label, ParameterSetDescription const &psetDescription)
std::vector< reco::TransientTrack > sortTracksByPt(const reco::Vertex &thePV, const TransientTrackBuilder &ttBuilder, const reco::BeamSpot &beamspot)
Resolution(const reco::Vertex &vertex1, const reco::Vertex &vertex2)
edm::EventID id() const
Definition: EventBase.h:60
fixed size matrix
HLT enums.
double a
Definition: hdecay.h:121
Square< F >::type sqr(const F &f)
Definition: Square.h:13
T get() const
Definition: EventSetup.h:62
std::vector< LumiScalers > LumiScalersCollection
Definition: LumiScalers.h:160
trackRef_iterator tracks_begin() const
first iterator over tracks
Definition: Vertex.cc:76
void book(DQMStore::IBooker &iBooker, Args &&...args)
long double T
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
double yError() const
error on y
Definition: Vertex.h:121
size_t tracksSize() const
number of tracks
Definition: Vertex.cc:71
Definition: Run.h:44