File indexing completed on 2025-05-23 23:49:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <memory>
0021
0022
0023 #include "CondFormats/BeamSpotObjects/interface/BeamSpotObjects.h"
0024 #include "CondFormats/DataRecord/interface/BeamSpotObjectsRcd.h"
0025 #include "CondFormats/DataRecord/interface/BeamSpotTransientObjectsRcd.h"
0026 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
0027 #include "DataFormats/Common/interface/Handle.h"
0028 #include "DataFormats/Scalers/interface/BeamSpotOnline.h"
0029 #include "FWCore/Framework/interface/ESHandle.h"
0030 #include "FWCore/Framework/interface/ESWatcher.h"
0031 #include "FWCore/Framework/interface/Event.h"
0032 #include "FWCore/Framework/interface/EventSetup.h"
0033 #include "FWCore/Framework/interface/Frameworkfwd.h"
0034 #include "FWCore/Framework/interface/MakerMacros.h"
0035 #include "FWCore/Framework/interface/global/EDAnalyzer.h"
0036 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0037 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0038 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0039 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0040 #include "FWCore/Utilities/interface/ESGetToken.h"
0041 #include "FWCore/Utilities/interface/InputTag.h"
0042 #include "RecoVertex/VertexTools/interface/VertexDistance3D.h"
0043
0044
0045
0046
0047
0048 namespace {
0049
0050 struct Significance {
0051 Significance(const double& a, const double& b, const double& errA, const double& errB, const std::string& var)
0052 : m_A(a), m_B(b), m_ErrA(errA), m_ErrB(errB), m_var(var) {
0053 if (m_ErrA == 0 && m_ErrB == 0) {
0054 edm::LogError("LogicalError") << "Can't calculate significance when both errors are zero!" << std::endl;
0055 }
0056 m_combinedError = std::sqrt((m_ErrA * m_ErrA) + (m_ErrB * m_ErrB));
0057 }
0058
0059 inline void printBeamSpotComparison(
0060 const std::string& varName, double A, double ErrA, double B, double ErrB, double combinedError) {
0061 edm::LogPrint("BeamSpotCompatibilityChecker")
0062 << std::fixed << std::setprecision(6) << std::left << std::setw(10) << " " + varName << std::right
0063 << std::setw(12) << A << std::setw(14) << ErrA << std::setw(12) << B << std::setw(14) << ErrB << std::setw(14)
0064 << std::abs(A - B) << std::setw(14) << combinedError << std::setw(12) << std::abs(A - B) / combinedError
0065 << std::endl;
0066 }
0067
0068 float getSig(const bool verbose) {
0069 if (verbose) {
0070 printBeamSpotComparison(m_var, m_A, m_ErrA, m_B, m_ErrB, m_combinedError);
0071 }
0072 return std::abs(m_A - m_B) / m_combinedError;
0073 }
0074
0075 private:
0076 double m_A;
0077 double m_B;
0078 double m_ErrA;
0079 double m_ErrB;
0080 double m_ErrAB;
0081 std::string m_var;
0082 double m_combinedError;
0083 };
0084 }
0085
0086 class BeamSpotCompatibilityChecker : public edm::global::EDAnalyzer<> {
0087 public:
0088 explicit BeamSpotCompatibilityChecker(const edm::ParameterSet&);
0089 ~BeamSpotCompatibilityChecker() override = default;
0090
0091 void analyze(edm::StreamID, edm::Event const&, edm::EventSetup const&) const final;
0092 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0093 static std::array<float, 6> compareBS(const reco::BeamSpot& BSA, const reco::BeamSpot& BSB, const bool verbose);
0094 static double computeBeamSpotCompatibility(const reco::BeamSpot& beamSpot1, const reco::BeamSpot& beamSpot2);
0095
0096 private:
0097
0098 static constexpr int cmToum = 10000;
0099 const double warningThreshold_;
0100 const double throwingThreshold_;
0101 const bool verbose_;
0102 const bool dbFromEvent_;
0103
0104
0105 const edm::EDGetTokenT<reco::BeamSpot> bsFromFileToken_;
0106
0107
0108 bool useTransientRecord_;
0109
0110
0111 edm::ESGetToken<BeamSpotObjects, BeamSpotObjectsRcd> bsFromDBToken_;
0112
0113
0114 edm::ESGetToken<BeamSpotObjects, BeamSpotTransientObjectsRcd> bsFromTransientDBToken_;
0115
0116
0117 edm::EDGetTokenT<reco::BeamSpot> dbBSfromEventToken_;
0118
0119 template <typename RecordT>
0120 reco::BeamSpot getBeamSpotFromES(edm::EventSetup const& iSetup,
0121 edm::ESGetToken<BeamSpotObjects, RecordT> const& token) const {
0122 edm::ESHandle<BeamSpotObjects> beamhandle = iSetup.getHandle(token);
0123 const BeamSpotObjects* aSpot = beamhandle.product();
0124
0125
0126 reco::BeamSpot::Point apoint(aSpot->x(), aSpot->y(), aSpot->z());
0127
0128 reco::BeamSpot::CovarianceMatrix matrix;
0129 for (int i = 0; i < reco::BeamSpot::dimension; ++i)
0130 for (int j = 0; j < reco::BeamSpot::dimension; ++j)
0131 matrix(i, j) = aSpot->covariance(i, j);
0132
0133
0134 return reco::BeamSpot(apoint, aSpot->sigmaZ(), aSpot->dxdz(), aSpot->dydz(), aSpot->beamWidthX(), matrix);
0135 }
0136 };
0137
0138
0139
0140
0141 BeamSpotCompatibilityChecker::BeamSpotCompatibilityChecker(const edm::ParameterSet& iConfig)
0142 : warningThreshold_(iConfig.getParameter<double>("warningThr")),
0143 throwingThreshold_(iConfig.getParameter<double>("errorThr")),
0144 verbose_(iConfig.getUntrackedParameter<bool>("verbose", false)),
0145 dbFromEvent_(iConfig.getParameter<bool>("dbFromEvent")),
0146 bsFromFileToken_(consumes<reco::BeamSpot>(iConfig.getParameter<edm::InputTag>("bsFromFile"))) {
0147
0148 if (warningThreshold_ > throwingThreshold_) {
0149 throw cms::Exception("ConfigurationError")
0150 << __PRETTY_FUNCTION__ << "\n Warning threshold (" << warningThreshold_
0151 << ") cannot be smaller than the throwing threshold (" << throwingThreshold_ << ")" << std::endl;
0152 }
0153
0154 if (dbFromEvent_) {
0155 edm::LogInfo("BeamSpotCompatibilityChecker")
0156 << "The Database Beam Spot is going to be taken from the File via BeamSpotProducer!";
0157 dbBSfromEventToken_ = consumes<reco::BeamSpot>(iConfig.getParameter<edm::InputTag>("bsFromDB"));
0158 } else {
0159 useTransientRecord_ = iConfig.getParameter<bool>("useTransientRecord");
0160 if (useTransientRecord_) {
0161 edm::LogInfo("BeamSpotCompatibilityChecker") << "Using BeamSpot from BeamSpotTransientObjectsRcd.";
0162 bsFromTransientDBToken_ = esConsumes<BeamSpotObjects, BeamSpotTransientObjectsRcd>();
0163 } else {
0164 edm::LogInfo("BeamSpotCompatibilityChecker") << "Using BeamSpot from BeamSpotObjectsRcd.";
0165 bsFromDBToken_ = esConsumes<BeamSpotObjects, BeamSpotObjectsRcd>();
0166 }
0167 dbBSfromEventToken_ = edm::EDGetTokenT<reco::BeamSpot>();
0168 }
0169 }
0170
0171
0172
0173
0174
0175
0176 void BeamSpotCompatibilityChecker::analyze(edm::StreamID sid,
0177 edm::Event const& iEvent,
0178 edm::EventSetup const& iSetup) const {
0179 using namespace edm;
0180 reco::BeamSpot spotFile, spotDB;
0181
0182 edm::Handle<reco::BeamSpot> beamSpotFromFileHandle;
0183 iEvent.getByToken(bsFromFileToken_, beamSpotFromFileHandle);
0184 spotFile = *beamSpotFromFileHandle;
0185
0186 double file_BSx0 = spotFile.x0();
0187 double file_BSy0 = spotFile.y0();
0188 double file_BSz0 = spotFile.z0();
0189 double file_Beamsigmaz = spotFile.sigmaZ();
0190 double file_BeamWidthX = spotFile.BeamWidthX();
0191 double file_BeamWidthY = spotFile.BeamWidthY();
0192
0193 if (!dbFromEvent_) {
0194 if (useTransientRecord_) {
0195 spotDB = getBeamSpotFromES(iSetup, bsFromTransientDBToken_);
0196 } else {
0197 spotDB = getBeamSpotFromES(iSetup, bsFromDBToken_);
0198 }
0199 } else {
0200
0201 edm::Handle<reco::BeamSpot> beamSpotFromDBHandle;
0202 iEvent.getByToken(dbBSfromEventToken_, beamSpotFromDBHandle);
0203 spotDB = *beamSpotFromDBHandle;
0204 }
0205
0206 double db_BSx0 = spotDB.x0();
0207 double db_BSy0 = spotDB.y0();
0208 double db_BSz0 = spotDB.z0();
0209 double db_Beamsigmaz = spotDB.sigmaZ();
0210 double db_BeamWidthX = spotDB.BeamWidthX();
0211 double db_BeamWidthY = spotDB.BeamWidthY();
0212
0213 double deltaX0 = file_BSx0 - db_BSx0;
0214 double deltaY0 = file_BSy0 - db_BSy0;
0215 double deltaZ0 = file_BSz0 - db_BSz0;
0216 double deltaSigmaX = file_BeamWidthX - db_BeamWidthX;
0217 double deltaSigmaY = file_BeamWidthY - db_BeamWidthY;
0218 double deltaSigmaZ = file_Beamsigmaz - db_Beamsigmaz;
0219
0220 if (verbose_) {
0221 edm::LogPrint("BeamSpotCompatibilityChecker") << "BS from DB: \n" << spotDB << std::endl;
0222 edm::LogPrint("BeamSpotCompatibilityChecker") << "BS from File: \n" << spotFile << std::endl;
0223 }
0224
0225 auto significances = compareBS(spotDB, spotFile, verbose_);
0226 std::vector<std::string> labels = {"x0", "y0", "z0", "sigmaX", "sigmaY", "sigmaZ"};
0227
0228 std::string msg = " |delta X0| = " + std::to_string(std::abs(deltaX0) * cmToum) +
0229 " um\n |delta Y0| = " + std::to_string(std::abs(deltaY0) * cmToum) +
0230 " um\n |delta Z0| = " + std::to_string(std::abs(deltaZ0)) +
0231 " cm\n |delta sigmaX| = " + std::to_string(std::abs(deltaSigmaX) * cmToum) +
0232 " um\n |delta sigmaY| = " + std::to_string(std::abs(deltaSigmaY) * cmToum) +
0233 " um\n |delta sigmaZ| = " + std::to_string(std::abs(deltaSigmaZ)) + " cm";
0234
0235
0236
0237
0238
0239
0240 for (unsigned int i = 0; i < 3; i++) {
0241 auto sig = significances.at(i);
0242 if (sig > throwingThreshold_) {
0243 edm::LogError("BeamSpotCompatibilityChecker") << msg.c_str() << std::endl;
0244 throw cms::Exception("BeamSpotCompatibilityChecker")
0245 << " [" << __PRETTY_FUNCTION__ << "]\n DB-File BeamSpot " << labels.at(i) << " distance significance is "
0246 << sig << ", exceeds the threshold of " << throwingThreshold_ << "!" << std::endl;
0247 } else if (sig > warningThreshold_) {
0248 edm::LogWarning("BeamSpotCompatibilityChecker") << msg.c_str() << std::endl;
0249 edm::LogWarning("BeamSpotCompatibilityChecker")
0250 << " [" << __PRETTY_FUNCTION__ << "]\n DB-File BeamSpot " << labels.at(i) << " distance significance is "
0251 << sig << ", exceeds the threshold of " << warningThreshold_ << "!" << std::endl;
0252 }
0253 }
0254 }
0255
0256 std::array<float, 6> BeamSpotCompatibilityChecker::compareBS(const reco::BeamSpot& spotA,
0257 const reco::BeamSpot& spotB,
0258 const bool verbose) {
0259 if (verbose) {
0260 edm::LogPrint("BeamSpotCompatibilityChecker")
0261 << std::fixed << std::setprecision(6) << std::left << std::setw(10) << " Var" << std::right << std::setw(12)
0262 << "DB" << std::setw(14) << "+/-" << std::setw(12) << "File" << std::setw(14) << "+/-" << std::setw(14)
0263 << "|delta|" << std::setw(14) << "+/-" << std::setw(12) << "Sig";
0264 edm::LogPrint("BeamSpotCompatibilityChecker") << std::string(102, '-');
0265 }
0266
0267
0268 auto calcSignificance = [&](auto a, auto b, auto aErr, auto bErr, auto var) {
0269 return Significance(a, b, aErr, bErr, var).getSig(verbose);
0270 };
0271
0272
0273 std::array<float, 6> ret = {
0274 {calcSignificance(spotA.x0(), spotB.x0(), spotA.x0Error(), spotB.x0Error(), "x"),
0275 calcSignificance(spotA.y0(), spotB.y0(), spotA.y0Error(), spotB.y0Error(), "y"),
0276 calcSignificance(spotA.z0(), spotB.z0(), spotA.z0Error(), spotB.z0Error(), "z"),
0277 calcSignificance(
0278 spotA.BeamWidthX(), spotB.BeamWidthX(), spotA.BeamWidthXError(), spotB.BeamWidthXError(), "widthX"),
0279 calcSignificance(
0280 spotA.BeamWidthY(), spotB.BeamWidthY(), spotA.BeamWidthYError(), spotB.BeamWidthYError(), "witdhY"),
0281 calcSignificance(spotA.sigmaZ(), spotB.sigmaZ(), spotA.sigmaZ0Error(), spotB.sigmaZ0Error(), "witdthZ")}};
0282
0283 if (verbose) {
0284 edm::LogPrint("BeamSpotCompatibilityChecker") << std::string(102, '-');
0285 }
0286
0287 return ret;
0288 }
0289
0290 double BeamSpotCompatibilityChecker::computeBeamSpotCompatibility(const reco::BeamSpot& beamSpot1,
0291 const reco::BeamSpot& beamSpot2) {
0292 reco::Vertex vertex1(
0293 reco::Vertex::Point(beamSpot1.x0(), beamSpot1.y0(), beamSpot1.z0()), beamSpot1.rotatedCovariance3D(), 0, 0, 0);
0294 reco::Vertex vertex2(
0295 reco::Vertex::Point(beamSpot2.x0(), beamSpot2.y0(), beamSpot2.z0()), beamSpot2.rotatedCovariance3D(), 0, 0, 0);
0296
0297
0298 VertexDistance3D distanceCalculator;
0299
0300 double significance = distanceCalculator.distance(vertex1, vertex2).significance();
0301
0302
0303 return significance;
0304 }
0305
0306
0307 void BeamSpotCompatibilityChecker::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0308 edm::ParameterSetDescription desc;
0309 desc.add<double>("warningThr", 1.)->setComment("Threshold on the signficances to emit a warning");
0310 desc.add<double>("errorThr", 3.)->setComment("Threshold on the signficances to abort the job");
0311 desc.addUntracked<bool>("verbose", false)->setComment("verbose output");
0312 desc.add<edm::InputTag>("bsFromFile", edm::InputTag(""))
0313 ->setComment("edm::InputTag on the BeamSpot from the File (Reference)");
0314
0315
0316 desc.ifValue(
0317 edm::ParameterDescription<bool>(
0318 "dbFromEvent",
0319 true,
0320 true,
0321 edm::Comment("Switch to take the (target) DB beamspot from the event instead of the EventSetup")),
0322 true >> edm::ParameterDescription<edm::InputTag>(
0323 "bsFromDB",
0324 edm::InputTag(""),
0325 true,
0326 edm::Comment("edm::InputTag on the BeamSpot from the Event (Target) (used if dbFromEvent = true")) or
0327 false >> edm::ParameterDescription<bool>(
0328 "useTransientRecord",
0329 false,
0330 true,
0331 edm::Comment("Use transient BeamSpot record (used if dbFromEvent = false)")));
0332
0333 descriptions.addWithDefaultLabel(desc);
0334 }
0335
0336
0337 DEFINE_FWK_MODULE(BeamSpotCompatibilityChecker);