CMS 3D CMS Logo

PrimaryVertexResolution.cc
Go to the documentation of this file.
6 
9 
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 } // namespace
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  const bool forceSCAL_;
69 
71 
72  struct BinningY {
73  explicit BinningY(const edm::ParameterSet& iConfig)
74  : maxResol_(iConfig.getUntrackedParameter<double>("maxResol")),
75  binsResol_(iConfig.getUntrackedParameter<int>("binsResol")),
76  maxPull_(iConfig.getUntrackedParameter<double>("maxPull")),
77  binsPull_(iConfig.getUntrackedParameter<int>("binsPull")) {}
78 
79  const double maxResol_;
80  const int binsResol_;
81  const double maxPull_;
82  const int binsPull_;
83  };
84 
85  struct BinningX {
86  explicit BinningX(const edm::ParameterSet& iConfig)
87  : minNtracks_(iConfig.getUntrackedParameter<double>("minNtracks")),
88  maxNtracks_(iConfig.getUntrackedParameter<double>("maxNtracks")),
89  binsNtracks_(iConfig.getUntrackedParameter<int>("binsNtracks")),
90  minNvertices_(iConfig.getUntrackedParameter<double>("minNvertices")),
91  maxNvertices_(iConfig.getUntrackedParameter<double>("maxNvertices")),
92  binsNvertices_(iConfig.getUntrackedParameter<int>("binsNvertices")),
93  maxXY_(iConfig.getUntrackedParameter<double>("maxXY")),
94  binsXY_(iConfig.getUntrackedParameter<int>("binsXY")),
95  maxZ_(iConfig.getUntrackedParameter<double>("maxZ")),
96  binsZ_(iConfig.getUntrackedParameter<int>("binsZ")),
97  minPt_(iConfig.getUntrackedParameter<double>("minPt")),
98  maxPt_(iConfig.getUntrackedParameter<double>("maxPt")),
99  minLumi_(iConfig.getUntrackedParameter<double>("minLumi")),
100  maxLumi_(iConfig.getUntrackedParameter<double>("maxLumi")) {}
101 
102  const int minNtracks_;
103  const int maxNtracks_;
104  const int binsNtracks_;
105  const int minNvertices_;
106  const int maxNvertices_;
107  const int binsNvertices_;
108  const double maxXY_;
109  const int binsXY_;
110  const double maxZ_;
111  const int binsZ_;
112  const double minPt_;
113  const double maxPt_;
114  const double minLumi_;
115  const double maxLumi_;
116  };
117 
118  class Resolution {
119  public:
120  Resolution(const reco::Vertex& vertex1, const reco::Vertex& vertex2) {
121  const double diffx = vertex1.x() - vertex2.x();
122  const double diffy = vertex1.y() - vertex2.y();
123  const double diffz = vertex1.z() - vertex2.z();
124 
125  // Take into account the need to divide by sqrt(2) already in
126  // the filling so that we can use DQMGenericClient for the
127  // gaussian fits
128  const double invSqrt2 = 1. / std::sqrt(2.);
129  resx_ = diffx * invSqrt2;
130  resy_ = diffy * invSqrt2;
131  resz_ = diffz * invSqrt2;
132 
133  pullx_ = diffx / std::sqrt(sqr(vertex1.xError()) + sqr(vertex2.xError()));
134  pully_ = diffy / std::sqrt(sqr(vertex1.yError()) + sqr(vertex2.yError()));
135  pullz_ = diffz / std::sqrt(sqr(vertex1.zError()) + sqr(vertex2.zError()));
136 
137  avgx_ = (vertex1.x() + vertex2.x()) / 2.;
138  avgy_ = (vertex1.y() + vertex2.y()) / 2.;
139  avgz_ = (vertex1.z() + vertex2.z()) / 2.;
140  }
141 
142  double resx() const { return resx_; }
143  double resy() const { return resy_; }
144  double resz() const { return resz_; }
145 
146  double pullx() const { return pullx_; }
147  double pully() const { return pully_; }
148  double pullz() const { return pullz_; }
149 
150  double avgx() const { return avgx_; }
151  double avgy() const { return avgy_; }
152  double avgz() const { return avgz_; }
153 
154  private:
155  double resx_;
156  double resy_;
157  double resz_;
158  double pullx_;
159  double pully_;
160  double pullz_;
161  double avgx_;
162  double avgy_;
163  double avgz_;
164  };
165 
166  class DiffPlots {
167  public:
168  explicit DiffPlots(const std::string& postfix, const BinningY& binY) : postfix_(postfix), binningY_(binY) {}
169 
170  template <typename T>
171  void bookLogX(DQMStore::IBooker& iBooker, const T& binArray) {
172  book(iBooker, binArray.size() - 1, binArray.front(), binArray.back());
173  setLogX(binArray.size() - 1, binArray.data());
174  }
175 
176  template <typename... Args>
177  void book(DQMStore::IBooker& iBooker, Args&&... args) {
178  const auto binsResol = binningY_.binsResol_;
179  const auto maxResol = binningY_.maxResol_;
180  hDiffX_ = iBooker.book2D("res_x_vs_" + postfix_,
181  "Resolution of X vs. " + postfix_,
182  std::forward<Args>(args)...,
183  binsResol,
184  -maxResol,
185  maxResol);
186  hDiffY_ = iBooker.book2D("res_y_vs_" + postfix_,
187  "Resolution of Y vs. " + postfix_,
188  std::forward<Args>(args)...,
189  binsResol,
190  -maxResol,
191  maxResol);
192  hDiffZ_ = iBooker.book2D("res_z_vs_" + postfix_,
193  "Resolution of Z vs. " + postfix_,
194  std::forward<Args>(args)...,
195  binsResol,
196  -maxResol,
197  maxResol);
198 
199  const auto binsPull = binningY_.binsPull_;
200  const auto maxPull = binningY_.maxPull_;
201  hPullX_ = iBooker.book2D("pull_x_vs_" + postfix_,
202  "Pull of X vs. " + postfix_,
203  std::forward<Args>(args)...,
204  binsPull,
205  -maxPull,
206  maxPull);
207  hPullY_ = iBooker.book2D("pull_y_vs_" + postfix_,
208  "Pull of Y vs. " + postfix_,
209  std::forward<Args>(args)...,
210  binsPull,
211  -maxPull,
212  maxPull);
213  hPullZ_ = iBooker.book2D("pull_z_vs_" + postfix_,
214  "Pull of Z vs. " + postfix_,
215  std::forward<Args>(args)...,
216  binsPull,
217  -maxPull,
218  maxPull);
219  }
220  template <typename... Args>
221  void setLogX(Args&&... args) {
222  hDiffX_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
223  hDiffY_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
224  hDiffZ_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
225 
226  hPullX_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
227  hPullY_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
228  hPullZ_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
229  }
230 
231  template <typename T>
232  void fill(const Resolution& res, const T ref) {
233  hDiffX_->Fill(ref, res.resx());
234  hDiffY_->Fill(ref, res.resy());
235  hDiffZ_->Fill(ref, res.resz());
236  hPullX_->Fill(ref, res.pullx());
237  hPullY_->Fill(ref, res.pully());
238  hPullZ_->Fill(ref, res.pullz());
239  }
240 
241  private:
250  };
251 
252  class Plots {
253  public:
254  Plots(const BinningX& binX, const BinningY& binY)
255  : binningX_(binX),
256  binningY_(binY),
257  hDiff_Ntracks_("ntracks", binY),
258  hDiff_sumPt_("sumpt", binY),
259  hDiff_Nvertices_("nvertices", binY),
260  hDiff_X_("X", binY),
261  hDiff_Y_("Y", binY),
262  hDiff_Z_("Z", binY),
263  hDiff_instLumiScal_("instLumiScal", binY) {}
264 
265  void book(DQMStore::IBooker& iBooker) {
266  const auto binsResol = binningY_.binsResol_;
267  const auto maxResol = binningY_.maxResol_;
268  hDiffX_ = iBooker.book1D("res_x", "Resolution of X", binsResol, -maxResol, maxResol);
269  hDiffY_ = iBooker.book1D("res_y", "Resolution of Y", binsResol, -maxResol, maxResol);
270  hDiffZ_ = iBooker.book1D("res_z", "Resolution of Z", binsResol, -maxResol, maxResol);
271 
272  const auto binsPull = binningY_.binsPull_;
273  const auto maxPull = binningY_.maxPull_;
274  hPullX_ = iBooker.book1D(+"pull_x", "Pull of X", binsPull, -maxPull, maxPull);
275  hPullY_ = iBooker.book1D(+"pull_y", "Pull of Y", binsPull, -maxPull, maxPull);
276  hPullZ_ = iBooker.book1D(+"pull_z", "Pull of Z", binsPull, -maxPull, maxPull);
277 
283 
284  constexpr int binsPt = 30;
285  hDiff_sumPt_.bookLogX(iBooker, makeLogBins<float, binsPt>(binningX_.minPt_, binningX_.maxPt_));
286 
287  constexpr int binsLumi = 100;
288  hDiff_instLumiScal_.bookLogX(iBooker, makeLogBins<float, binsLumi>(binningX_.minLumi_, binningX_.maxLumi_));
289  }
290 
291  void calculateAndFillResolution(const std::vector<reco::TransientTrack>& tracks,
292  size_t nvertices,
293  float lumi,
294  std::mt19937& engine,
295  AdaptiveVertexFitter& fitter);
296 
297  private:
300 
307 
315  };
316 
317  // Binning
320 
321  // Histograms
324 
325  std::mt19937 engine_;
326 };
327 
329  : ttbToken_(esConsumes(edm::ESInputTag("", iConfig.getUntrackedParameter<std::string>("transientTrackBuilder")))),
330  vertexSrc_(consumes<reco::VertexCollection>(iConfig.getUntrackedParameter<edm::InputTag>("vertexSrc"))),
331  beamspotSrc_(consumes<reco::BeamSpot>(iConfig.getUntrackedParameter<edm::InputTag>("beamspotSrc"))),
332  lumiScalersSrc_(consumes<LumiScalersCollection>(iConfig.getUntrackedParameter<edm::InputTag>("lumiScalersSrc"))),
333  metaDataSrc_(consumes<OnlineLuminosityRecord>(iConfig.getUntrackedParameter<edm::InputTag>("metaDataSrc"))),
334  forceSCAL_(iConfig.getUntrackedParameter<bool>("forceSCAL")),
335  rootFolder_(iConfig.getUntrackedParameter<std::string>("rootFolder")),
336  binningX_(iConfig),
337  binningY_(iConfig),
338  hPV_(binningX_, binningY_),
339  hOtherV_(binningX_, binningY_) {}
340 
342 
345  desc.addUntracked<edm::InputTag>("vertexSrc", edm::InputTag("trackingDQMgoodOfflinePrimaryVertices"));
346  desc.addUntracked<edm::InputTag>("beamspotSrc", edm::InputTag("offlineBeamSpot"));
347  desc.addUntracked<edm::InputTag>("lumiScalersSrc", edm::InputTag("scalersRawToDigi"));
348  desc.addUntracked<edm::InputTag>("metaDataSrc", edm::InputTag("onlineMetaDataDigis"));
349  desc.addUntracked<bool>("forceSCAL", true);
350  desc.addUntracked<std::string>("rootFolder", "OfflinePV/Resolution");
351  desc.addUntracked<std::string>("transientTrackBuilder", "TransientTrackBuilder");
352 
353  // Y axes
354  desc.addUntracked<double>("maxResol", 0.02);
355  desc.addUntracked<int>("binsResol", 100);
356 
357  desc.addUntracked<double>("maxPull", 5);
358  desc.addUntracked<int>("binsPull", 100);
359 
360  // X axes
361  desc.addUntracked<double>("minNtracks", -0.5);
362  desc.addUntracked<double>("maxNtracks", 119.5);
363  desc.addUntracked<int>("binsNtracks", 60);
364 
365  desc.addUntracked<double>("minNvertices", -0.5);
366  desc.addUntracked<double>("maxNvertices", 199.5);
367  desc.addUntracked<int>("binsNvertices", 100);
368 
369  desc.addUntracked<double>("maxXY", 0.15);
370  desc.addUntracked<int>("binsXY", 100);
371 
372  desc.addUntracked<double>("maxZ", 30.);
373  desc.addUntracked<int>("binsZ", 100);
374 
375  desc.addUntracked<double>("minPt", 1);
376  desc.addUntracked<double>("maxPt", 1e3);
377 
378  desc.addUntracked<double>("minLumi", 200.);
379  desc.addUntracked<double>("maxLumi", 20000.);
380 
381  descriptions.add("primaryVertexResolution", desc);
382 }
383 
385  iBooker.setCurrentFolder(rootFolder_ + "/PV");
386  hPV_.book(iBooker);
387 
388  iBooker.setCurrentFolder(rootFolder_ + "/OtherV");
389  hOtherV_.book(iBooker);
390 }
391 
394  const reco::VertexCollection& vertices = *hvertices;
395  if (vertices.empty())
396  return;
397 
398  edm::Handle<reco::BeamSpot> hbeamspot = iEvent.getHandle(beamspotSrc_);
399  const reco::BeamSpot& beamspot = *hbeamspot;
400 
401  float lumi = -1.;
402  if (forceSCAL_) {
404  if (lumiScalers.isValid() && !lumiScalers->empty()) {
405  LumiScalersCollection::const_iterator scalit = lumiScalers->begin();
406  lumi = scalit->instantLumi();
407  }
408  } else {
410  if (metaData.isValid())
411  lumi = metaData->instLumi();
412  }
413 
414  const TransientTrackBuilder& ttBuilder = iSetup.getData(ttbToken_);
415 
416  // deterministic seed from the event number
417  // should not bias the result as the event number is already
418  // assigned randomly-enough
419  engine_.seed(iEvent.id().event() + (iEvent.id().luminosityBlock() << 10) + (iEvent.id().run() << 20));
420 
421  // The PV
422  auto iPV = cbegin(vertices);
423  const reco::Vertex& thePV = *iPV;
424  const auto nvertices = vertices.size();
425  if (thePV.tracksSize() >= 4) {
426  auto sortedTracks = sortTracksByPt(thePV, ttBuilder, beamspot);
427  hPV_.calculateAndFillResolution(sortedTracks, nvertices, lumi, engine_, fitter_);
428  }
429  ++iPV;
430 
431  // Other vertices
432  for (auto endPV = cend(vertices); iPV != endPV; ++iPV) {
433  if (iPV->tracksSize() >= 4) {
434  auto sortedTracks = sortTracksByPt(*iPV, ttBuilder, beamspot);
435  hOtherV_.calculateAndFillResolution(sortedTracks, nvertices, lumi, engine_, fitter_);
436  }
437  }
438 }
439 
440 std::vector<reco::TransientTrack> PrimaryVertexResolution::sortTracksByPt(const reco::Vertex& thePV,
441  const TransientTrackBuilder& ttBuilder,
442  const reco::BeamSpot& beamspot) {
443  std::vector<const reco::Track*> sortedTracks;
444  sortedTracks.reserve(thePV.tracksSize());
446  thePV.tracks_begin(), thePV.tracks_end(), std::back_inserter(sortedTracks), [](const reco::TrackBaseRef& ref) {
447  return &(*ref);
448  });
449  std::sort(sortedTracks.begin(), sortedTracks.end(), [](const reco::Track* a, const reco::Track* b) {
450  return a->pt() > b->pt();
451  });
452 
453  std::vector<reco::TransientTrack> ttracks;
454  ttracks.reserve(sortedTracks.size());
455  std::transform(sortedTracks.begin(), sortedTracks.end(), std::back_inserter(ttracks), [&](const reco::Track* track) {
456  auto tt = ttBuilder.build(track);
457  tt.setBeamSpot(beamspot);
458  return tt;
459  });
460  return ttracks;
461 }
462 
463 void PrimaryVertexResolution::Plots::calculateAndFillResolution(const std::vector<reco::TransientTrack>& tracks,
464  size_t nvertices,
465  float lumi,
466  std::mt19937& engine,
467  AdaptiveVertexFitter& fitter) {
468  const size_t end = tracks.size() % 2 == 0 ? tracks.size() : tracks.size() - 1;
469 
470  std::vector<reco::TransientTrack> set1, set2;
471  set1.reserve(end / 2);
472  set2.reserve(end / 2);
473 
474  auto dis = std::uniform_int_distribution<>(0, 1); // [0, 1]
475 
476  double sumpt1 = 0, sumpt2 = 0;
477  for (size_t i = 0; i < end; i += 2) {
478  const size_t set1_i = dis(engine);
479  const size_t set2_i = 1 - set1_i;
480 
481  set1.push_back(tracks[i + set1_i]);
482  set2.push_back(tracks[i + set2_i]);
483 
484  sumpt1 += set1.back().track().pt();
485  sumpt2 += set2.back().track().pt();
486  }
487 
488  // For resolution we only fit
489  TransientVertex vertex1 = fitter.vertex(set1);
490  TransientVertex vertex2 = fitter.vertex(set2);
491 
492  Resolution res(vertex1, vertex2);
493  hDiffX_->Fill(res.resx());
494  hDiffY_->Fill(res.resy());
495  hDiffZ_->Fill(res.resz());
496  hPullX_->Fill(res.pullx());
497  hPullY_->Fill(res.pully());
498  hPullZ_->Fill(res.pullz());
499 
500  hDiff_Ntracks_.fill(res, set1.size());
502  res,
503  (sumpt1 + sumpt2) /
504  2.0); // taking average is probably the best we can do, anyway they should be close to each other
505  hDiff_Nvertices_.fill(res, nvertices);
506 
507  if (vertex1.isValid() && vertex2.isValid()) {
508  hDiff_X_.fill(res, res.avgx());
509  hDiff_Y_.fill(res, res.avgy());
510  hDiff_Z_.fill(res, res.avgz());
511  }
512 
514 }
515 
const edm::ESGetToken< TransientTrackBuilder, TransientTrackRecord > ttbToken_
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
BinningX(const edm::ParameterSet &iConfig)
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
double z() const
z coordinate
Definition: Vertex.h:134
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
void book(DQMStore::IBooker &iBooker)
ret
prodAgent to be discontinued
void calculateAndFillResolution(const std::vector< reco::TransientTrack > &tracks, size_t nvertices, float lumi, std::mt19937 &engine, AdaptiveVertexFitter &fitter)
PrimaryVertexResolution(const edm::ParameterSet &iConfig)
void book(DQMStore::IBooker &iBooker, Args &&... args)
Class to contain the online luminosity from soft FED 1022.
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
float instLumi() const
Return the luminosity for the current nibble.
double zError() const
error on z
Definition: Vertex.h:142
void analyze(const edm::Event &, const edm::EventSetup &) override
CachingVertex< 5 > vertex(const std::vector< reco::TransientTrack > &) const override
std::vector< Vertex > VertexCollection
Definition: Vertex.h:31
double xError() const
error on x
Definition: Vertex.h:138
trackRef_iterator tracks_end() const
last iterator over tracks
Definition: Vertex.h:111
Definition: Electron.h:6
size_t tracksSize() const
number of tracks
Definition: Vertex.h:113
reco::TransientTrack build(const reco::Track *p) const
void Fill(long long x)
Plots(const BinningX &binX, const BinningY &binY)
int iEvent
Definition: GenABIO.cc:224
Definition: TTTypes.h:54
bool isValid() const
T sqrt(T t)
Definition: SSEVec.h:19
void fill(const Resolution &res, const T ref)
void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override
BinningY(const edm::ParameterSet &iConfig)
edm::EDGetTokenT< LumiScalersCollection > lumiScalersSrc_
trackRef_iterator tracks_begin() const
first iterator over tracks
Definition: Vertex.h:109
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
void bookLogX(DQMStore::IBooker &iBooker, const T &binArray)
double x() const
x coordinate
Definition: Vertex.h:130
double y() const
y coordinate
Definition: Vertex.h:132
edm::EDGetTokenT< reco::VertexCollection > vertexSrc_
DiffPlots(const std::string &postfix, const BinningY &binY)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
#define N
Definition: blowfish.cc:9
std::array< T, N+1 > makeLogBins(const T &min, const T &max)
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:221
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)
bool isValid() const
Definition: HandleBase.h:70
fixed size matrix
HLT enums.
double yError() const
error on y
Definition: Vertex.h:140
double a
Definition: hdecay.h:121
Square< F >::type sqr(const F &f)
Definition: Square.h:14
std::vector< LumiScalers > LumiScalersCollection
Definition: LumiScalers.h:144
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
long double T
edm::EDGetTokenT< OnlineLuminosityRecord > metaDataSrc_
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
Definition: Run.h:45
unsigned transform(const HcalDetId &id, unsigned transformCode)