Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:09:07

0001 #include "FWCore/Framework/interface/Event.h"
0002 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0003 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0004 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0006 
0007 #include "DQMServices/Core/interface/DQMEDAnalyzer.h"
0008 #include "DQMServices/Core/interface/DQMStore.h"
0009 
0010 #include "DataFormats/Common/interface/Handle.h"
0011 #include "DataFormats/VertexReco/interface/Vertex.h"
0012 #include "DataFormats/VertexReco/interface/VertexFwd.h"
0013 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
0014 #include "DataFormats/Scalers/interface/LumiScalers.h"
0015 #include "DataFormats/OnlineMetaData/interface/OnlineLuminosityRecord.h"
0016 
0017 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
0018 #include "RecoVertex/VertexPrimitives/interface/TransientVertex.h"
0019 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
0020 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
0021 
0022 #include "RecoVertex/AdaptiveVertexFit/interface/AdaptiveVertexFitter.h"
0023 
0024 #include <random>
0025 
0026 namespace {
0027   template <typename T, size_t N>
0028   std::array<T, N + 1> makeLogBins(const double min, const double max) {
0029     const double minLog10 = std::log10(min);
0030     const double maxLog10 = std::log10(max);
0031     const double width = (maxLog10 - minLog10) / N;
0032     std::array<T, N + 1> ret;
0033     ret[0] = std::pow(10, minLog10);
0034     const double mult = std::pow(10, width);
0035     for (size_t i = 1; i <= N; ++i) {
0036       ret[i] = ret[i - 1] * mult;
0037     }
0038     return ret;
0039   }
0040 
0041   template <typename T>
0042   T sqr(T val) {
0043     return val * val;
0044   }
0045 }  // namespace
0046 
0047 class PrimaryVertexResolution : public DQMEDAnalyzer {
0048 public:
0049   PrimaryVertexResolution(const edm::ParameterSet& iConfig);
0050   ~PrimaryVertexResolution() override;
0051 
0052   void bookHistograms(DQMStore::IBooker&, edm::Run const&, edm::EventSetup const&) override;
0053   void analyze(const edm::Event&, const edm::EventSetup&) override;
0054 
0055   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0056 
0057 private:
0058   std::vector<reco::TransientTrack> sortTracksByPt(const reco::Vertex& thePV,
0059                                                    const TransientTrackBuilder& ttBuilder,
0060                                                    const reco::BeamSpot& beamspot);
0061 
0062   const edm::ESGetToken<TransientTrackBuilder, TransientTrackRecord> ttbToken_;
0063   edm::EDGetTokenT<reco::VertexCollection> vertexSrc_;
0064   edm::EDGetTokenT<reco::BeamSpot> beamspotSrc_;
0065   edm::EDGetTokenT<LumiScalersCollection> lumiScalersSrc_;
0066   edm::EDGetTokenT<OnlineLuminosityRecord> metaDataSrc_;
0067   const bool forceSCAL_;
0068   std::string rootFolder_;
0069 
0070   AdaptiveVertexFitter fitter_;
0071 
0072   struct BinningY {
0073     explicit BinningY(const edm::ParameterSet& iConfig)
0074         : maxResol_(iConfig.getUntrackedParameter<double>("maxResol")),
0075           binsResol_(iConfig.getUntrackedParameter<int>("binsResol")),
0076           maxPull_(iConfig.getUntrackedParameter<double>("maxPull")),
0077           binsPull_(iConfig.getUntrackedParameter<int>("binsPull")) {}
0078 
0079     const double maxResol_;
0080     const int binsResol_;
0081     const double maxPull_;
0082     const int binsPull_;
0083   };
0084 
0085   struct BinningX {
0086     explicit BinningX(const edm::ParameterSet& iConfig)
0087         : minNtracks_(iConfig.getUntrackedParameter<double>("minNtracks")),
0088           maxNtracks_(iConfig.getUntrackedParameter<double>("maxNtracks")),
0089           binsNtracks_(iConfig.getUntrackedParameter<int>("binsNtracks")),
0090           minNvertices_(iConfig.getUntrackedParameter<double>("minNvertices")),
0091           maxNvertices_(iConfig.getUntrackedParameter<double>("maxNvertices")),
0092           binsNvertices_(iConfig.getUntrackedParameter<int>("binsNvertices")),
0093           maxXY_(iConfig.getUntrackedParameter<double>("maxXY")),
0094           binsXY_(iConfig.getUntrackedParameter<int>("binsXY")),
0095           maxZ_(iConfig.getUntrackedParameter<double>("maxZ")),
0096           binsZ_(iConfig.getUntrackedParameter<int>("binsZ")),
0097           minPt_(iConfig.getUntrackedParameter<double>("minPt")),
0098           maxPt_(iConfig.getUntrackedParameter<double>("maxPt")),
0099           minLumi_(iConfig.getUntrackedParameter<double>("minLumi")),
0100           maxLumi_(iConfig.getUntrackedParameter<double>("maxLumi")) {}
0101 
0102     const int minNtracks_;
0103     const int maxNtracks_;
0104     const int binsNtracks_;
0105     const int minNvertices_;
0106     const int maxNvertices_;
0107     const int binsNvertices_;
0108     const double maxXY_;
0109     const int binsXY_;
0110     const double maxZ_;
0111     const int binsZ_;
0112     const double minPt_;
0113     const double maxPt_;
0114     const double minLumi_;
0115     const double maxLumi_;
0116   };
0117 
0118   class Resolution {
0119   public:
0120     Resolution(const reco::Vertex& vertex1, const reco::Vertex& vertex2) {
0121       const double diffx = vertex1.x() - vertex2.x();
0122       const double diffy = vertex1.y() - vertex2.y();
0123       const double diffz = vertex1.z() - vertex2.z();
0124 
0125       // Take into account the need to divide by sqrt(2) already in
0126       // the filling so that we can use DQMGenericClient for the
0127       // gaussian fits
0128       const double invSqrt2 = 1. / std::sqrt(2.);
0129       resx_ = diffx * invSqrt2;
0130       resy_ = diffy * invSqrt2;
0131       resz_ = diffz * invSqrt2;
0132 
0133       pullx_ = diffx / std::sqrt(sqr(vertex1.xError()) + sqr(vertex2.xError()));
0134       pully_ = diffy / std::sqrt(sqr(vertex1.yError()) + sqr(vertex2.yError()));
0135       pullz_ = diffz / std::sqrt(sqr(vertex1.zError()) + sqr(vertex2.zError()));
0136 
0137       avgx_ = (vertex1.x() + vertex2.x()) / 2.;
0138       avgy_ = (vertex1.y() + vertex2.y()) / 2.;
0139       avgz_ = (vertex1.z() + vertex2.z()) / 2.;
0140     }
0141 
0142     double resx() const { return resx_; }
0143     double resy() const { return resy_; }
0144     double resz() const { return resz_; }
0145 
0146     double pullx() const { return pullx_; }
0147     double pully() const { return pully_; }
0148     double pullz() const { return pullz_; }
0149 
0150     double avgx() const { return avgx_; }
0151     double avgy() const { return avgy_; }
0152     double avgz() const { return avgz_; }
0153 
0154   private:
0155     double resx_;
0156     double resy_;
0157     double resz_;
0158     double pullx_;
0159     double pully_;
0160     double pullz_;
0161     double avgx_;
0162     double avgy_;
0163     double avgz_;
0164   };
0165 
0166   class DiffPlots {
0167   public:
0168     explicit DiffPlots(const std::string& postfix, const BinningY& binY) : postfix_(postfix), binningY_(binY) {}
0169 
0170     template <typename T>
0171     void bookLogX(DQMStore::IBooker& iBooker, const T& binArray) {
0172       book(iBooker, binArray.size() - 1, binArray.front(), binArray.back());
0173       setLogX(binArray.size() - 1, binArray.data());
0174     }
0175 
0176     template <typename... Args>
0177     void book(DQMStore::IBooker& iBooker, Args&&... args) {
0178       const auto binsResol = binningY_.binsResol_;
0179       const auto maxResol = binningY_.maxResol_;
0180       hDiffX_ = iBooker.book2D("res_x_vs_" + postfix_,
0181                                "Resolution of X vs. " + postfix_,
0182                                std::forward<Args>(args)...,
0183                                binsResol,
0184                                -maxResol,
0185                                maxResol);
0186       hDiffY_ = iBooker.book2D("res_y_vs_" + postfix_,
0187                                "Resolution of Y vs. " + postfix_,
0188                                std::forward<Args>(args)...,
0189                                binsResol,
0190                                -maxResol,
0191                                maxResol);
0192       hDiffZ_ = iBooker.book2D("res_z_vs_" + postfix_,
0193                                "Resolution of Z vs. " + postfix_,
0194                                std::forward<Args>(args)...,
0195                                binsResol,
0196                                -maxResol,
0197                                maxResol);
0198 
0199       const auto binsPull = binningY_.binsPull_;
0200       const auto maxPull = binningY_.maxPull_;
0201       hPullX_ = iBooker.book2D("pull_x_vs_" + postfix_,
0202                                "Pull of X vs. " + postfix_,
0203                                std::forward<Args>(args)...,
0204                                binsPull,
0205                                -maxPull,
0206                                maxPull);
0207       hPullY_ = iBooker.book2D("pull_y_vs_" + postfix_,
0208                                "Pull of Y vs. " + postfix_,
0209                                std::forward<Args>(args)...,
0210                                binsPull,
0211                                -maxPull,
0212                                maxPull);
0213       hPullZ_ = iBooker.book2D("pull_z_vs_" + postfix_,
0214                                "Pull of Z vs. " + postfix_,
0215                                std::forward<Args>(args)...,
0216                                binsPull,
0217                                -maxPull,
0218                                maxPull);
0219     }
0220     template <typename... Args>
0221     void setLogX(Args&&... args) {
0222       hDiffX_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
0223       hDiffY_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
0224       hDiffZ_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
0225 
0226       hPullX_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
0227       hPullY_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
0228       hPullZ_->getTH2F()->GetXaxis()->Set(std::forward<Args>(args)...);
0229     }
0230 
0231     template <typename T>
0232     void fill(const Resolution& res, const T ref) {
0233       hDiffX_->Fill(ref, res.resx());
0234       hDiffY_->Fill(ref, res.resy());
0235       hDiffZ_->Fill(ref, res.resz());
0236       hPullX_->Fill(ref, res.pullx());
0237       hPullY_->Fill(ref, res.pully());
0238       hPullZ_->Fill(ref, res.pullz());
0239     }
0240 
0241   private:
0242     std::string postfix_;
0243     const BinningY& binningY_;
0244     MonitorElement* hDiffX_ = nullptr;
0245     MonitorElement* hDiffY_ = nullptr;
0246     MonitorElement* hDiffZ_ = nullptr;
0247     MonitorElement* hPullX_ = nullptr;
0248     MonitorElement* hPullY_ = nullptr;
0249     MonitorElement* hPullZ_ = nullptr;
0250   };
0251 
0252   class Plots {
0253   public:
0254     Plots(const BinningX& binX, const BinningY& binY)
0255         : binningX_(binX),
0256           binningY_(binY),
0257           hDiff_Ntracks_("ntracks", binY),
0258           hDiff_sumPt_("sumpt", binY),
0259           hDiff_Nvertices_("nvertices", binY),
0260           hDiff_X_("X", binY),
0261           hDiff_Y_("Y", binY),
0262           hDiff_Z_("Z", binY),
0263           hDiff_instLumiScal_("instLumiScal", binY) {}
0264 
0265     void book(DQMStore::IBooker& iBooker) {
0266       const auto binsResol = binningY_.binsResol_;
0267       const auto maxResol = binningY_.maxResol_;
0268       hDiffX_ = iBooker.book1D("res_x", "Resolution of X", binsResol, -maxResol, maxResol);
0269       hDiffY_ = iBooker.book1D("res_y", "Resolution of Y", binsResol, -maxResol, maxResol);
0270       hDiffZ_ = iBooker.book1D("res_z", "Resolution of Z", binsResol, -maxResol, maxResol);
0271 
0272       const auto binsPull = binningY_.binsPull_;
0273       const auto maxPull = binningY_.maxPull_;
0274       hPullX_ = iBooker.book1D(+"pull_x", "Pull of X", binsPull, -maxPull, maxPull);
0275       hPullY_ = iBooker.book1D(+"pull_y", "Pull of Y", binsPull, -maxPull, maxPull);
0276       hPullZ_ = iBooker.book1D(+"pull_z", "Pull of Z", binsPull, -maxPull, maxPull);
0277 
0278       hDiff_Ntracks_.book(iBooker, binningX_.binsNtracks_, binningX_.minNtracks_, binningX_.maxNtracks_);
0279       hDiff_Nvertices_.book(iBooker, binningX_.binsNvertices_, binningX_.minNvertices_, binningX_.maxNvertices_);
0280       hDiff_X_.book(iBooker, binningX_.binsXY_, -binningX_.maxXY_, binningX_.maxXY_);
0281       hDiff_Y_.book(iBooker, binningX_.binsXY_, -binningX_.maxXY_, binningX_.maxXY_);
0282       hDiff_Z_.book(iBooker, binningX_.binsZ_, -binningX_.maxZ_, binningX_.maxZ_);
0283 
0284       constexpr int binsPt = 30;
0285       hDiff_sumPt_.bookLogX(iBooker, makeLogBins<float, binsPt>(binningX_.minPt_, binningX_.maxPt_));
0286 
0287       constexpr int binsLumi = 100;
0288       hDiff_instLumiScal_.bookLogX(iBooker, makeLogBins<float, binsLumi>(binningX_.minLumi_, binningX_.maxLumi_));
0289     }
0290 
0291     void calculateAndFillResolution(const std::vector<reco::TransientTrack>& tracks,
0292                                     size_t nvertices,
0293                                     float lumi,
0294                                     std::mt19937& engine,
0295                                     AdaptiveVertexFitter& fitter);
0296 
0297   private:
0298     const BinningX& binningX_;
0299     const BinningY& binningY_;
0300 
0301     MonitorElement* hDiffX_ = nullptr;
0302     MonitorElement* hDiffY_ = nullptr;
0303     MonitorElement* hDiffZ_ = nullptr;
0304     MonitorElement* hPullX_ = nullptr;
0305     MonitorElement* hPullY_ = nullptr;
0306     MonitorElement* hPullZ_ = nullptr;
0307 
0308     DiffPlots hDiff_Ntracks_;
0309     DiffPlots hDiff_sumPt_;
0310     DiffPlots hDiff_Nvertices_;
0311     DiffPlots hDiff_X_;
0312     DiffPlots hDiff_Y_;
0313     DiffPlots hDiff_Z_;
0314     DiffPlots hDiff_instLumiScal_;
0315   };
0316 
0317   // Binning
0318   BinningX binningX_;
0319   BinningY binningY_;
0320 
0321   // Histograms
0322   Plots hPV_;
0323   Plots hOtherV_;
0324 
0325   std::mt19937 engine_;
0326 };
0327 
0328 PrimaryVertexResolution::PrimaryVertexResolution(const edm::ParameterSet& iConfig)
0329     : ttbToken_(esConsumes(edm::ESInputTag("", iConfig.getUntrackedParameter<std::string>("transientTrackBuilder")))),
0330       vertexSrc_(consumes<reco::VertexCollection>(iConfig.getUntrackedParameter<edm::InputTag>("vertexSrc"))),
0331       beamspotSrc_(consumes<reco::BeamSpot>(iConfig.getUntrackedParameter<edm::InputTag>("beamspotSrc"))),
0332       lumiScalersSrc_(consumes<LumiScalersCollection>(iConfig.getUntrackedParameter<edm::InputTag>("lumiScalersSrc"))),
0333       metaDataSrc_(consumes<OnlineLuminosityRecord>(iConfig.getUntrackedParameter<edm::InputTag>("metaDataSrc"))),
0334       forceSCAL_(iConfig.getUntrackedParameter<bool>("forceSCAL")),
0335       rootFolder_(iConfig.getUntrackedParameter<std::string>("rootFolder")),
0336       binningX_(iConfig),
0337       binningY_(iConfig),
0338       hPV_(binningX_, binningY_),
0339       hOtherV_(binningX_, binningY_) {}
0340 
0341 PrimaryVertexResolution::~PrimaryVertexResolution() {}
0342 
0343 void PrimaryVertexResolution::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0344   edm::ParameterSetDescription desc;
0345   desc.addUntracked<edm::InputTag>("vertexSrc", edm::InputTag("trackingDQMgoodOfflinePrimaryVertices"));
0346   desc.addUntracked<edm::InputTag>("beamspotSrc", edm::InputTag("offlineBeamSpot"));
0347   desc.addUntracked<edm::InputTag>("lumiScalersSrc", edm::InputTag("scalersRawToDigi"));
0348   desc.addUntracked<edm::InputTag>("metaDataSrc", edm::InputTag("onlineMetaDataDigis"));
0349   desc.addUntracked<bool>("forceSCAL", true);
0350   desc.addUntracked<std::string>("rootFolder", "OfflinePV/Resolution");
0351   desc.addUntracked<std::string>("transientTrackBuilder", "TransientTrackBuilder");
0352 
0353   // Y axes
0354   desc.addUntracked<double>("maxResol", 0.02);
0355   desc.addUntracked<int>("binsResol", 100);
0356 
0357   desc.addUntracked<double>("maxPull", 5);
0358   desc.addUntracked<int>("binsPull", 100);
0359 
0360   // X axes
0361   desc.addUntracked<double>("minNtracks", -0.5);
0362   desc.addUntracked<double>("maxNtracks", 119.5);
0363   desc.addUntracked<int>("binsNtracks", 60);
0364 
0365   desc.addUntracked<double>("minNvertices", -0.5);
0366   desc.addUntracked<double>("maxNvertices", 199.5);
0367   desc.addUntracked<int>("binsNvertices", 100);
0368 
0369   desc.addUntracked<double>("maxXY", 0.15);
0370   desc.addUntracked<int>("binsXY", 100);
0371 
0372   desc.addUntracked<double>("maxZ", 30.);
0373   desc.addUntracked<int>("binsZ", 100);
0374 
0375   desc.addUntracked<double>("minPt", 1);
0376   desc.addUntracked<double>("maxPt", 1e3);
0377 
0378   desc.addUntracked<double>("minLumi", 200.);
0379   desc.addUntracked<double>("maxLumi", 20000.);
0380 
0381   descriptions.add("primaryVertexResolution", desc);
0382 }
0383 
0384 void PrimaryVertexResolution::bookHistograms(DQMStore::IBooker& iBooker, edm::Run const&, edm::EventSetup const&) {
0385   iBooker.setCurrentFolder(rootFolder_ + "/PV");
0386   hPV_.book(iBooker);
0387 
0388   iBooker.setCurrentFolder(rootFolder_ + "/OtherV");
0389   hOtherV_.book(iBooker);
0390 }
0391 
0392 void PrimaryVertexResolution::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
0393   edm::Handle<reco::VertexCollection> hvertices = iEvent.getHandle(vertexSrc_);
0394   const reco::VertexCollection& vertices = *hvertices;
0395   if (vertices.empty())
0396     return;
0397 
0398   edm::Handle<reco::BeamSpot> hbeamspot = iEvent.getHandle(beamspotSrc_);
0399   const reco::BeamSpot& beamspot = *hbeamspot;
0400 
0401   float lumi = -1.;
0402   if (forceSCAL_) {
0403     edm::Handle<LumiScalersCollection> lumiScalers = iEvent.getHandle(lumiScalersSrc_);
0404     if (lumiScalers.isValid() && !lumiScalers->empty()) {
0405       LumiScalersCollection::const_iterator scalit = lumiScalers->begin();
0406       lumi = scalit->instantLumi();
0407     }
0408   } else {
0409     edm::Handle<OnlineLuminosityRecord> metaData = iEvent.getHandle(metaDataSrc_);
0410     if (metaData.isValid())
0411       lumi = metaData->instLumi();
0412   }
0413 
0414   const TransientTrackBuilder& ttBuilder = iSetup.getData(ttbToken_);
0415 
0416   // deterministic seed from the event number
0417   // should not bias the result as the event number is already
0418   // assigned randomly-enough
0419   engine_.seed(iEvent.id().event() + (iEvent.id().luminosityBlock() << 10) + (iEvent.id().run() << 20));
0420 
0421   // The PV
0422   auto iPV = cbegin(vertices);
0423   const reco::Vertex& thePV = *iPV;
0424   const auto nvertices = vertices.size();
0425   if (thePV.tracksSize() >= 4) {
0426     auto sortedTracks = sortTracksByPt(thePV, ttBuilder, beamspot);
0427     hPV_.calculateAndFillResolution(sortedTracks, nvertices, lumi, engine_, fitter_);
0428   }
0429   ++iPV;
0430 
0431   // Other vertices
0432   for (auto endPV = cend(vertices); iPV != endPV; ++iPV) {
0433     if (iPV->tracksSize() >= 4) {
0434       auto sortedTracks = sortTracksByPt(*iPV, ttBuilder, beamspot);
0435       hOtherV_.calculateAndFillResolution(sortedTracks, nvertices, lumi, engine_, fitter_);
0436     }
0437   }
0438 }
0439 
0440 std::vector<reco::TransientTrack> PrimaryVertexResolution::sortTracksByPt(const reco::Vertex& thePV,
0441                                                                           const TransientTrackBuilder& ttBuilder,
0442                                                                           const reco::BeamSpot& beamspot) {
0443   std::vector<const reco::Track*> sortedTracks;
0444   sortedTracks.reserve(thePV.tracksSize());
0445   std::transform(
0446       thePV.tracks_begin(), thePV.tracks_end(), std::back_inserter(sortedTracks), [](const reco::TrackBaseRef& ref) {
0447         return &(*ref);
0448       });
0449   std::sort(sortedTracks.begin(), sortedTracks.end(), [](const reco::Track* a, const reco::Track* b) {
0450     return a->pt() > b->pt();
0451   });
0452 
0453   std::vector<reco::TransientTrack> ttracks;
0454   ttracks.reserve(sortedTracks.size());
0455   std::transform(sortedTracks.begin(), sortedTracks.end(), std::back_inserter(ttracks), [&](const reco::Track* track) {
0456     auto tt = ttBuilder.build(track);
0457     tt.setBeamSpot(beamspot);
0458     return tt;
0459   });
0460   return ttracks;
0461 }
0462 
0463 void PrimaryVertexResolution::Plots::calculateAndFillResolution(const std::vector<reco::TransientTrack>& tracks,
0464                                                                 size_t nvertices,
0465                                                                 float lumi,
0466                                                                 std::mt19937& engine,
0467                                                                 AdaptiveVertexFitter& fitter) {
0468   const size_t end = tracks.size() % 2 == 0 ? tracks.size() : tracks.size() - 1;
0469 
0470   std::vector<reco::TransientTrack> set1, set2;
0471   set1.reserve(end / 2);
0472   set2.reserve(end / 2);
0473 
0474   auto dis = std::uniform_int_distribution<>(0, 1);  // [0, 1]
0475 
0476   double sumpt1 = 0, sumpt2 = 0;
0477   for (size_t i = 0; i < end; i += 2) {
0478     const size_t set1_i = dis(engine);
0479     const size_t set2_i = 1 - set1_i;
0480 
0481     set1.push_back(tracks[i + set1_i]);
0482     set2.push_back(tracks[i + set2_i]);
0483 
0484     sumpt1 += set1.back().track().pt();
0485     sumpt2 += set2.back().track().pt();
0486   }
0487 
0488   // For resolution we only fit
0489   TransientVertex vertex1 = fitter.vertex(set1);
0490   TransientVertex vertex2 = fitter.vertex(set2);
0491 
0492   Resolution res(vertex1, vertex2);
0493   hDiffX_->Fill(res.resx());
0494   hDiffY_->Fill(res.resy());
0495   hDiffZ_->Fill(res.resz());
0496   hPullX_->Fill(res.pullx());
0497   hPullY_->Fill(res.pully());
0498   hPullZ_->Fill(res.pullz());
0499 
0500   hDiff_Ntracks_.fill(res, set1.size());
0501   hDiff_sumPt_.fill(
0502       res,
0503       (sumpt1 + sumpt2) /
0504           2.0);  // taking average is probably the best we can do, anyway they should be close to each other
0505   hDiff_Nvertices_.fill(res, nvertices);
0506 
0507   if (vertex1.isValid() && vertex2.isValid()) {
0508     hDiff_X_.fill(res, res.avgx());
0509     hDiff_Y_.fill(res, res.avgy());
0510     hDiff_Z_.fill(res, res.avgz());
0511   }
0512 
0513   hDiff_instLumiScal_.fill(res, lumi);
0514 }
0515 
0516 #include "FWCore/Framework/interface/MakerMacros.h"
0517 DEFINE_FWK_MODULE(PrimaryVertexResolution);