File indexing completed on 2025-03-08 03:06:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include "CondFormats/BeamSpotObjects/interface/BeamSpotObjects.h"
0014 #include "CondFormats/DataRecord/interface/BeamSpotObjectsRcd.h"
0015 #include "CondFormats/BeamSpotObjects/interface/BeamSpotOnlineObjects.h"
0016 #include "CondFormats/DataRecord/interface/BeamSpotOnlineHLTObjectsRcd.h"
0017 #include "CondFormats/DataRecord/interface/BeamSpotOnlineLegacyObjectsRcd.h"
0018 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
0019 #include "DataFormats/Common/interface/Handle.h"
0020 #include "DataFormats/GeometryCommonDetAlgo/interface/GlobalError.h"
0021 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerEvmReadoutRecord.h"
0022 #include "DataFormats/Scalers/interface/BeamSpotOnline.h"
0023 #include "FWCore/Framework/interface/ESHandle.h"
0024 #include "FWCore/Framework/interface/Event.h"
0025 #include "FWCore/Framework/interface/EventSetup.h"
0026 #include "FWCore/Framework/interface/stream/EDProducer.h"
0027 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0028 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0029 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0030 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0031 #include "FWCore/Utilities/interface/ESGetToken.h"
0032 #include "FWCore/Utilities/interface/TypeDemangler.h"
0033
0034 class BeamSpotOnlineProducer : public edm::stream::EDProducer<> {
0035 public:
0036
0037 explicit BeamSpotOnlineProducer(const edm::ParameterSet& iConf);
0038
0039 void beginLuminosityBlock(const edm::LuminosityBlock& lumi, const edm::EventSetup& setup) override;
0040
0041
0042 void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
0043
0044
0045 static void fillDescriptions(edm::ConfigurationDescriptions& iDesc);
0046
0047 private:
0048
0049 bool shouldShout(const edm::Event& iEvent) const;
0050 bool processRecords(const edm::LuminosityBlock& iLumi, const edm::EventSetup& iSetup, bool shoutMODE);
0051 void createBeamSpotFromRecord(const BeamSpotObjects& spotDB);
0052 template <typename RecordType, typename TokenType>
0053 const BeamSpotOnlineObjects& getBeamSpotFromRecord(const TokenType& token,
0054 const edm::LuminosityBlock& lumi,
0055 const edm::EventSetup& setup);
0056 const BeamSpotOnlineObjects& chooseBS(const BeamSpotOnlineObjects& bs1, const BeamSpotOnlineObjects& bs2);
0057 bool processScalers(const edm::Event& iEvent, bool shoutMODE);
0058 void createBeamSpotFromScaler(const BeamSpotOnline& spotOnline);
0059 bool isInvalidScaler(const BeamSpotOnline& spotOnline, bool shoutMODE) const;
0060 void createBeamSpotFromDB(const edm::EventSetup& iSetup, bool shoutMODE);
0061
0062
0063 const bool changeFrame_;
0064 const double theMaxZ, theSetSigmaZ;
0065 double theMaxR2;
0066 const int timeThreshold_;
0067 const double sigmaZThreshold_, sigmaXYThreshold_;
0068 const bool useBSOnlineRecords_;
0069 const edm::EDGetTokenT<BeamSpotOnlineCollection> scalerToken_;
0070 const edm::EDGetTokenT<L1GlobalTriggerEvmReadoutRecord> l1GtEvmReadoutRecordToken_;
0071 const edm::ESGetToken<BeamSpotObjects, BeamSpotObjectsRcd> beamToken_;
0072 const edm::ESGetToken<BeamSpotOnlineObjects, BeamSpotOnlineLegacyObjectsRcd> beamTokenLegacy_;
0073 const edm::ESGetToken<BeamSpotOnlineObjects, BeamSpotOnlineHLTObjectsRcd> beamTokenHLT_;
0074
0075 reco::BeamSpot result;
0076 const unsigned int theBeamShoutMode;
0077 BeamSpotOnlineObjects fakeBS_;
0078 };
0079
0080 using namespace edm;
0081
0082 BeamSpotOnlineProducer::BeamSpotOnlineProducer(const ParameterSet& iconf)
0083 : changeFrame_(iconf.getParameter<bool>("changeToCMSCoordinates")),
0084 theMaxZ(iconf.getParameter<double>("maxZ")),
0085 theSetSigmaZ(iconf.getParameter<double>("setSigmaZ")),
0086 timeThreshold_(iconf.getParameter<int>("timeThreshold")),
0087 sigmaZThreshold_(iconf.getParameter<double>("sigmaZThreshold")),
0088 sigmaXYThreshold_(iconf.getParameter<double>("sigmaXYThreshold") * 1E-4),
0089 useBSOnlineRecords_(iconf.getParameter<bool>("useBSOnlineRecords")),
0090 scalerToken_(useBSOnlineRecords_ ? edm::EDGetTokenT<BeamSpotOnlineCollection>()
0091 : consumes<BeamSpotOnlineCollection>(iconf.getParameter<InputTag>("src"))),
0092 l1GtEvmReadoutRecordToken_(consumes<L1GlobalTriggerEvmReadoutRecord>(iconf.getParameter<InputTag>("gtEvmLabel"))),
0093 beamToken_(esConsumes<BeamSpotObjects, BeamSpotObjectsRcd>()),
0094 beamTokenLegacy_(
0095 esConsumes<BeamSpotOnlineObjects, BeamSpotOnlineLegacyObjectsRcd, edm::Transition::BeginLuminosityBlock>()),
0096 beamTokenHLT_(
0097 esConsumes<BeamSpotOnlineObjects, BeamSpotOnlineHLTObjectsRcd, edm::Transition::BeginLuminosityBlock>()),
0098 theBeamShoutMode(iconf.getUntrackedParameter<unsigned int>("beamMode", 11)) {
0099 fakeBS_.setType(reco::BeamSpot::Fake);
0100 theMaxR2 = iconf.getParameter<double>("maxRadius");
0101 theMaxR2 *= theMaxR2;
0102
0103 produces<reco::BeamSpot>();
0104 }
0105
0106 void BeamSpotOnlineProducer::fillDescriptions(edm::ConfigurationDescriptions& iDesc) {
0107 edm::ParameterSetDescription ps;
0108 ps.add<bool>("changeToCMSCoordinates", false);
0109 ps.add<double>("maxZ", 40.);
0110 ps.add<double>("setSigmaZ", -1.);
0111 ps.addUntracked<unsigned int>("beamMode", 11);
0112 ps.addOptional<InputTag>("src", InputTag("hltScalersRawToDigi"))->setComment("SCAL decommissioned after Run 2");
0113 ps.add<InputTag>("gtEvmLabel", InputTag(""));
0114 ps.add<double>("maxRadius", 2.0);
0115 ps.add<bool>("useBSOnlineRecords", false);
0116 ps.add<int>("timeThreshold", 48)->setComment("hours");
0117 ps.add<double>("sigmaZThreshold", 2.)->setComment("cm");
0118 ps.add<double>("sigmaXYThreshold", 4.)->setComment("um");
0119 iDesc.addWithDefaultLabel(ps);
0120 }
0121
0122 void BeamSpotOnlineProducer::beginLuminosityBlock(const edm::LuminosityBlock& lumi, const edm::EventSetup& setup) {
0123
0124 if (useBSOnlineRecords_) {
0125 processRecords(lumi, setup, true);
0126 }
0127 }
0128
0129 void BeamSpotOnlineProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0130
0131 bool shoutMODE = shouldShout(iEvent);
0132 bool fallBackToDB{false};
0133
0134
0135 if (useBSOnlineRecords_) {
0136 fallBackToDB = result.type() != reco::BeamSpot::Tracker;
0137 } else {
0138
0139 fallBackToDB = processScalers(iEvent, shoutMODE);
0140 }
0141
0142
0143 if (fallBackToDB) {
0144 createBeamSpotFromDB(iSetup, shoutMODE);
0145 }
0146
0147 std::unique_ptr<reco::BeamSpot> toput = std::make_unique<reco::BeamSpot>(result);
0148 iEvent.put(std::move(toput));
0149 }
0150
0151 bool BeamSpotOnlineProducer::shouldShout(const edm::Event& iEvent) const {
0152 edm::Handle<L1GlobalTriggerEvmReadoutRecord> gtEvmReadoutRecord;
0153 if (iEvent.getByToken(l1GtEvmReadoutRecordToken_, gtEvmReadoutRecord)) {
0154 return gtEvmReadoutRecord->gtfeWord().beamMode() == theBeamShoutMode;
0155 }
0156 return true;
0157 }
0158
0159 bool BeamSpotOnlineProducer::processRecords(const edm::LuminosityBlock& iLumi,
0160 const edm::EventSetup& iSetup,
0161 bool shoutMODE) {
0162 auto const& spotDBLegacy = getBeamSpotFromRecord<BeamSpotOnlineLegacyObjectsRcd>(beamTokenLegacy_, iLumi, iSetup);
0163 auto const& spotDBHLT = getBeamSpotFromRecord<BeamSpotOnlineHLTObjectsRcd>(beamTokenHLT_, iLumi, iSetup);
0164 auto const& spotDB = chooseBS(spotDBLegacy, spotDBHLT);
0165
0166 if (spotDB.beamType() != reco::BeamSpot::Tracker) {
0167 if (shoutMODE) {
0168 edm::LogWarning("BeamSpotOnlineProducer") << "None of the online records holds a valid beam spot. The Online "
0169 "Beam Spot producer falls back to the PCL value.";
0170 }
0171 return true;
0172 }
0173
0174
0175 createBeamSpotFromRecord(spotDB);
0176 return false;
0177 }
0178
0179 template <typename RecordType, typename TokenType>
0180 const BeamSpotOnlineObjects& BeamSpotOnlineProducer::getBeamSpotFromRecord(const TokenType& token,
0181 const LuminosityBlock& lumi,
0182 const EventSetup& setup) {
0183 auto const bsRecord = setup.tryToGet<RecordType>();
0184 const auto& recordTypeName = edm::typeDemangle(typeid(RecordType).name());
0185 if (!bsRecord) {
0186 edm::LogWarning("BeamSpotOnlineProducer") << "No " << recordTypeName << " found in the EventSetup";
0187 return fakeBS_;
0188 }
0189 const auto& bsHandle = setup.getHandle(token);
0190 if (bsHandle.isValid()) {
0191 const auto& bs = *bsHandle;
0192 if (bs.sigmaZ() < sigmaZThreshold_ || bs.beamWidthX() < sigmaXYThreshold_ || bs.beamWidthY() < sigmaXYThreshold_ ||
0193 bs.beamType() != reco::BeamSpot::Tracker) {
0194 edm::LogWarning("BeamSpotOnlineProducer")
0195 << "The beam spot record does not pass the fit sanity checks (record: " << recordTypeName << ")" << std::endl
0196 << "sigmaZ: " << bs.sigmaZ() << std::endl
0197 << "sigmaX: " << bs.beamWidthX() << std::endl
0198 << "sigmaY: " << bs.beamWidthY() << std::endl
0199 << "type: " << bs.beamType();
0200 return fakeBS_;
0201 }
0202 auto lumitime = std::chrono::seconds(lumi.beginTime().unixTime());
0203 auto bstime = std::chrono::microseconds(bs.creationTime());
0204 auto threshold = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::hours(timeThreshold_)).count();
0205 if ((lumitime - bstime).count() > threshold) {
0206 edm::LogWarning("BeamSpotOnlineProducer")
0207 << "The beam spot record is too old. (record: " << recordTypeName << ")" << std::endl
0208 << "record creation time: " << std::chrono::duration_cast<std::chrono::seconds>(bstime).count()
0209 << "lumi block time: " << std::chrono::duration_cast<std::chrono::seconds>(lumitime).count();
0210 return fakeBS_;
0211 }
0212 return bs;
0213 } else {
0214 edm::LogWarning("BeamSpotOnlineProducer") << "Invalid online beam spot handle for the record: " << recordTypeName;
0215 return fakeBS_;
0216 }
0217 }
0218
0219 const BeamSpotOnlineObjects& BeamSpotOnlineProducer::chooseBS(const BeamSpotOnlineObjects& bs1,
0220 const BeamSpotOnlineObjects& bs2) {
0221 if (bs1.beamType() == reco::BeamSpot::Tracker && bs2.beamType() == reco::BeamSpot::Tracker) {
0222 return bs1.sigmaZ() > bs2.sigmaZ() ? bs1 : bs2;
0223 } else if (bs1.beamType() == reco::BeamSpot::Tracker) {
0224 return bs1;
0225 } else if (bs2.beamType() == reco::BeamSpot::Tracker) {
0226 return bs2;
0227 } else {
0228 return fakeBS_;
0229 }
0230 }
0231
0232 void BeamSpotOnlineProducer::createBeamSpotFromRecord(const BeamSpotObjects& spotDB) {
0233 double f = changeFrame_ ? -1.0 : 1.0;
0234 reco::BeamSpot::Point apoint(f * spotDB.x(), f * spotDB.y(), f * spotDB.z());
0235
0236 reco::BeamSpot::CovarianceMatrix matrix;
0237 for (int i = 0; i < reco::BeamSpot::dimension; ++i) {
0238 for (int j = 0; j < reco::BeamSpot::dimension; ++j) {
0239 matrix(i, j) = spotDB.covariance(i, j);
0240 }
0241 }
0242
0243 double sigmaZ = (theSetSigmaZ > 0) ? theSetSigmaZ : spotDB.sigmaZ();
0244 result = reco::BeamSpot(apoint, sigmaZ, spotDB.dxdz(), spotDB.dydz(), spotDB.beamWidthX(), matrix);
0245 result.setBeamWidthY(spotDB.beamWidthY());
0246 result.setEmittanceX(spotDB.emittanceX());
0247 result.setEmittanceY(spotDB.emittanceY());
0248 result.setbetaStar(spotDB.betaStar());
0249 result.setType(reco::BeamSpot::Tracker);
0250 }
0251
0252 bool BeamSpotOnlineProducer::processScalers(const edm::Event& iEvent, bool shoutMODE) {
0253 edm::Handle<BeamSpotOnlineCollection> handleScaler;
0254 iEvent.getByToken(scalerToken_, handleScaler);
0255
0256 if (handleScaler->empty()) {
0257 return true;
0258 }
0259
0260
0261 BeamSpotOnline spotOnline = *(handleScaler->begin());
0262 createBeamSpotFromScaler(spotOnline);
0263
0264
0265 if (isInvalidScaler(spotOnline, shoutMODE)) {
0266 return true;
0267 }
0268 return false;
0269 }
0270
0271 void BeamSpotOnlineProducer::createBeamSpotFromScaler(const BeamSpotOnline& spotOnline) {
0272 double f = changeFrame_ ? -1.0 : 1.0;
0273 reco::BeamSpot::Point apoint(f * spotOnline.x(), spotOnline.y(), f * spotOnline.z());
0274
0275 reco::BeamSpot::CovarianceMatrix matrix;
0276 matrix(0, 0) = spotOnline.err_x() * spotOnline.err_x();
0277 matrix(1, 1) = spotOnline.err_y() * spotOnline.err_y();
0278 matrix(2, 2) = spotOnline.err_z() * spotOnline.err_z();
0279 matrix(3, 3) = spotOnline.err_sigma_z() * spotOnline.err_sigma_z();
0280
0281 double sigmaZ = (theSetSigmaZ > 0) ? theSetSigmaZ : spotOnline.sigma_z();
0282 result = reco::BeamSpot(apoint, sigmaZ, spotOnline.dxdz(), f * spotOnline.dydz(), spotOnline.width_x(), matrix);
0283 result.setBeamWidthY(spotOnline.width_y());
0284 result.setEmittanceX(0.0);
0285 result.setEmittanceY(0.0);
0286 result.setbetaStar(0.0);
0287 result.setType(reco::BeamSpot::LHC);
0288 }
0289
0290 bool BeamSpotOnlineProducer::isInvalidScaler(const BeamSpotOnline& spotOnline, bool shoutMODE) const {
0291 if (spotOnline.x() == 0 && spotOnline.y() == 0 && spotOnline.z() == 0 && spotOnline.width_x() == 0 &&
0292 spotOnline.width_y() == 0) {
0293 if (shoutMODE) {
0294 edm::LogWarning("BeamSpotOnlineProducer")
0295 << "Online Beam Spot producer falls back to DB due to zero scaler values.";
0296 }
0297 return true;
0298 }
0299
0300 double r2 = spotOnline.x() * spotOnline.x() + spotOnline.y() * spotOnline.y();
0301 if (std::abs(spotOnline.z()) >= theMaxZ || r2 >= theMaxR2) {
0302 if (shoutMODE) {
0303 edm::LogError("BeamSpotOnlineProducer")
0304 << "Online Beam Spot producer falls back to DB due to out-of-range scaler values: " << spotOnline.x() << ", "
0305 << spotOnline.y() << ", " << spotOnline.z();
0306 }
0307 return true;
0308 }
0309 return false;
0310 }
0311
0312 void BeamSpotOnlineProducer::createBeamSpotFromDB(const edm::EventSetup& iSetup, bool shoutMODE) {
0313 edm::ESHandle<BeamSpotObjects> beamhandle = iSetup.getHandle(beamToken_);
0314 const BeamSpotObjects* spotDB = beamhandle.product();
0315
0316 reco::BeamSpot::Point apoint(spotDB->x(), spotDB->y(), spotDB->z());
0317
0318 reco::BeamSpot::CovarianceMatrix matrix;
0319 for (int i = 0; i < reco::BeamSpot::dimension; ++i) {
0320 for (int j = 0; j < reco::BeamSpot::dimension; ++j) {
0321 matrix(i, j) = spotDB->covariance(i, j);
0322 }
0323 }
0324
0325 result = reco::BeamSpot(apoint, spotDB->sigmaZ(), spotDB->dxdz(), spotDB->dydz(), spotDB->beamWidthX(), matrix);
0326 result.setBeamWidthY(spotDB->beamWidthY());
0327 result.setEmittanceX(spotDB->emittanceX());
0328 result.setEmittanceY(spotDB->emittanceY());
0329 result.setbetaStar(spotDB->betaStar());
0330 result.setType(reco::BeamSpot::Tracker);
0331
0332 GlobalError bse(result.rotatedCovariance3D());
0333 if ((bse.cxx() <= 0.0) || (bse.cyy() <= 0.0) || (bse.czz() <= 0.0)) {
0334 edm::LogError("UnusableBeamSpot") << "Beamspot from DB fallback has invalid errors: " << result.covariance();
0335 }
0336 }
0337
0338 #include "FWCore/Framework/interface/MakerMacros.h"
0339 DEFINE_FWK_MODULE(BeamSpotOnlineProducer);