Skip to content

Commit 5944370

Browse files
committed
Make BeamSpotOnlineProducer return consistent results
Now reset how the beam spot is calculated each LuminosityBlock in case the available EventSetup data products change. This avoids getting different results depending on the order in which LuminosityBlocks are seen in a job.
1 parent 69e8253 commit 5944370

File tree

1 file changed

+67
-62
lines changed

1 file changed

+67
-62
lines changed

RecoVertex/BeamSpotProducer/plugins/BeamSpotOnlineProducer.cc

Lines changed: 67 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ ________________________________________________________________**/
3131
#include "FWCore/Utilities/interface/ESGetToken.h"
3232
#include "FWCore/Utilities/interface/TypeDemangler.h"
3333

34+
#include <optional>
35+
3436
class BeamSpotOnlineProducer : public edm::stream::EDProducer<> {
3537
public:
3638
/// constructor
@@ -47,17 +49,19 @@ class BeamSpotOnlineProducer : public edm::stream::EDProducer<> {
4749
private:
4850
// helper methods
4951
bool shouldShout(const edm::Event& iEvent) const;
50-
bool processRecords(const edm::LuminosityBlock& iLumi, const edm::EventSetup& iSetup, bool shoutMODE);
51-
void createBeamSpotFromRecord(const BeamSpotObjects& spotDB);
52+
std::optional<reco::BeamSpot> processRecords(const edm::LuminosityBlock& iLumi,
53+
const edm::EventSetup& iSetup,
54+
bool shoutMODE) const;
55+
reco::BeamSpot createBeamSpotFromRecord(const BeamSpotObjects& spotDB) const;
5256
template <typename RecordType, typename TokenType>
53-
const BeamSpotOnlineObjects& getBeamSpotFromRecord(const TokenType& token,
57+
const BeamSpotOnlineObjects* getBeamSpotFromRecord(const TokenType& token,
5458
const edm::LuminosityBlock& lumi,
55-
const edm::EventSetup& setup);
56-
const BeamSpotOnlineObjects& chooseBS(const BeamSpotOnlineObjects& bs1, const BeamSpotOnlineObjects& bs2);
57-
bool processScalers(const edm::Event& iEvent, bool shoutMODE);
58-
void createBeamSpotFromScaler(const BeamSpotOnline& spotOnline);
59+
const edm::EventSetup& setup) const;
60+
const BeamSpotOnlineObjects* chooseBS(const BeamSpotOnlineObjects* bs1, const BeamSpotOnlineObjects* bs2) const;
61+
std::optional<reco::BeamSpot> processScalers(const edm::Event& iEvent, bool shoutMODE) const;
62+
reco::BeamSpot createBeamSpotFromScaler(const BeamSpotOnline& spotOnline) const;
5963
bool isInvalidScaler(const BeamSpotOnline& spotOnline, bool shoutMODE) const;
60-
void createBeamSpotFromDB(const edm::EventSetup& iSetup, bool shoutMODE);
64+
reco::BeamSpot createBeamSpotFromDB(const edm::EventSetup& iSetup, bool shoutMODE) const;
6165

6266
// data members
6367
const bool changeFrame_;
@@ -72,9 +76,8 @@ class BeamSpotOnlineProducer : public edm::stream::EDProducer<> {
7276
const edm::ESGetToken<BeamSpotOnlineObjects, BeamSpotOnlineLegacyObjectsRcd> beamTokenLegacy_;
7377
const edm::ESGetToken<BeamSpotOnlineObjects, BeamSpotOnlineHLTObjectsRcd> beamTokenHLT_;
7478

75-
reco::BeamSpot result;
79+
std::optional<reco::BeamSpot> lumiResult_;
7680
const unsigned int theBeamShoutMode;
77-
BeamSpotOnlineObjects fakeBS_;
7881
};
7982

8083
using namespace edm;
@@ -90,13 +93,12 @@ BeamSpotOnlineProducer::BeamSpotOnlineProducer(const ParameterSet& iconf)
9093
scalerToken_(useBSOnlineRecords_ ? edm::EDGetTokenT<BeamSpotOnlineCollection>()
9194
: consumes<BeamSpotOnlineCollection>(iconf.getParameter<InputTag>("src"))),
9295
l1GtEvmReadoutRecordToken_(consumes<L1GlobalTriggerEvmReadoutRecord>(iconf.getParameter<InputTag>("gtEvmLabel"))),
93-
beamToken_(esConsumes<BeamSpotObjects, BeamSpotObjectsRcd>()),
96+
beamToken_(esConsumes<BeamSpotObjects, BeamSpotObjectsRcd, edm::Transition::BeginLuminosityBlock>()),
9497
beamTokenLegacy_(
9598
esConsumes<BeamSpotOnlineObjects, BeamSpotOnlineLegacyObjectsRcd, edm::Transition::BeginLuminosityBlock>()),
9699
beamTokenHLT_(
97100
esConsumes<BeamSpotOnlineObjects, BeamSpotOnlineHLTObjectsRcd, edm::Transition::BeginLuminosityBlock>()),
98101
theBeamShoutMode(iconf.getUntrackedParameter<unsigned int>("beamMode", 11)) {
99-
fakeBS_.setType(reco::BeamSpot::Fake);
100102
theMaxR2 = iconf.getParameter<double>("maxRadius");
101103
theMaxR2 *= theMaxR2;
102104

@@ -122,29 +124,29 @@ void BeamSpotOnlineProducer::fillDescriptions(edm::ConfigurationDescriptions& iD
122124
void BeamSpotOnlineProducer::beginLuminosityBlock(const edm::LuminosityBlock& lumi, const edm::EventSetup& setup) {
123125
/// fetch online records only at the beginning of a lumisection
124126
if (useBSOnlineRecords_) {
125-
processRecords(lumi, setup, true);
127+
lumiResult_ = processRecords(lumi, setup, true);
128+
if (lumiResult_)
129+
return;
126130
}
131+
lumiResult_ = createBeamSpotFromDB(setup, true);
127132
}
128133

129134
void BeamSpotOnlineProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
130135
// Determine if we should "shout" based on the beam mode
131136
bool shoutMODE = shouldShout(iEvent);
132-
bool fallBackToDB{false};
133137

134-
// Use online records if enabled
135-
if (useBSOnlineRecords_) {
136-
fallBackToDB = result.type() != reco::BeamSpot::Tracker;
137-
} else {
138+
std::unique_ptr<reco::BeamSpot> toput;
139+
if (not useBSOnlineRecords_) {
138140
// Process online beam spot scalers
139-
fallBackToDB = processScalers(iEvent, shoutMODE);
141+
auto bs = processScalers(iEvent, shoutMODE);
142+
if (bs) {
143+
toput = std::make_unique<reco::BeamSpot>(std::move(*bs));
144+
}
140145
}
141-
142-
// Fallback to DB if necessary
143-
if (fallBackToDB) {
144-
createBeamSpotFromDB(iSetup, shoutMODE);
146+
if (not toput) {
147+
assert(lumiResult_);
148+
toput = std::make_unique<reco::BeamSpot>(*lumiResult_);
145149
}
146-
147-
std::unique_ptr<reco::BeamSpot> toput = std::make_unique<reco::BeamSpot>(result);
148150
iEvent.put(std::move(toput));
149151
}
150152

@@ -156,80 +158,82 @@ bool BeamSpotOnlineProducer::shouldShout(const edm::Event& iEvent) const {
156158
return true; // Default to "shout" if the record is missing
157159
}
158160

159-
bool BeamSpotOnlineProducer::processRecords(const edm::LuminosityBlock& iLumi,
160-
const edm::EventSetup& iSetup,
161-
bool shoutMODE) {
162-
auto const& spotDBLegacy = getBeamSpotFromRecord<BeamSpotOnlineLegacyObjectsRcd>(beamTokenLegacy_, iLumi, iSetup);
163-
auto const& spotDBHLT = getBeamSpotFromRecord<BeamSpotOnlineHLTObjectsRcd>(beamTokenHLT_, iLumi, iSetup);
164-
auto const& spotDB = chooseBS(spotDBLegacy, spotDBHLT);
161+
std::optional<reco::BeamSpot> BeamSpotOnlineProducer::processRecords(const edm::LuminosityBlock& iLumi,
162+
const edm::EventSetup& iSetup,
163+
bool shoutMODE) const {
164+
auto const* spotDBLegacy = getBeamSpotFromRecord<BeamSpotOnlineLegacyObjectsRcd>(beamTokenLegacy_, iLumi, iSetup);
165+
auto const* spotDBHLT = getBeamSpotFromRecord<BeamSpotOnlineHLTObjectsRcd>(beamTokenHLT_, iLumi, iSetup);
166+
auto const* spotDB = chooseBS(spotDBLegacy, spotDBHLT);
165167

166-
if (spotDB.beamType() != reco::BeamSpot::Tracker) {
168+
if (not spotDB) {
167169
if (shoutMODE) {
168170
edm::LogWarning("BeamSpotOnlineProducer") << "None of the online records holds a valid beam spot. The Online "
169171
"Beam Spot producer falls back to the PCL value.";
170172
}
171-
return true; // Trigger fallback to DB
173+
return {}; // Trigger fallback to DB
172174
}
173175

174176
// Create BeamSpot from transient record
175-
createBeamSpotFromRecord(spotDB);
176-
return false; // No fallback needed
177+
return createBeamSpotFromRecord(*spotDB);
177178
}
178179

179180
template <typename RecordType, typename TokenType>
180-
const BeamSpotOnlineObjects& BeamSpotOnlineProducer::getBeamSpotFromRecord(const TokenType& token,
181+
const BeamSpotOnlineObjects* BeamSpotOnlineProducer::getBeamSpotFromRecord(const TokenType& token,
181182
const LuminosityBlock& lumi,
182-
const EventSetup& setup) {
183+
const EventSetup& setup) const {
183184
auto const bsRecord = setup.tryToGet<RecordType>();
184-
const auto& recordTypeName = edm::typeDemangle(typeid(RecordType).name());
185185
if (!bsRecord) {
186+
const auto& recordTypeName = edm::typeDemangle(typeid(RecordType).name());
186187
edm::LogWarning("BeamSpotOnlineProducer") << "No " << recordTypeName << " found in the EventSetup";
187-
return fakeBS_;
188+
return nullptr;
188189
}
189190
const auto& bsHandle = setup.getHandle(token);
190191
if (bsHandle.isValid()) {
191192
const auto& bs = *bsHandle;
192193
if (bs.sigmaZ() < sigmaZThreshold_ || bs.beamWidthX() < sigmaXYThreshold_ || bs.beamWidthY() < sigmaXYThreshold_ ||
193194
bs.beamType() != reco::BeamSpot::Tracker) {
195+
const auto& recordTypeName = edm::typeDemangle(typeid(RecordType).name());
194196
edm::LogWarning("BeamSpotOnlineProducer")
195197
<< "The beam spot record does not pass the fit sanity checks (record: " << recordTypeName << ")" << std::endl
196198
<< "sigmaZ: " << bs.sigmaZ() << std::endl
197199
<< "sigmaX: " << bs.beamWidthX() << std::endl
198200
<< "sigmaY: " << bs.beamWidthY() << std::endl
199201
<< "type: " << bs.beamType();
200-
return fakeBS_;
202+
return nullptr;
201203
}
202204
auto lumitime = std::chrono::seconds(lumi.beginTime().unixTime());
203205
auto bstime = std::chrono::microseconds(bs.creationTime());
204206
auto threshold = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::hours(timeThreshold_)).count();
205207
if ((lumitime - bstime).count() > threshold) {
208+
const auto& recordTypeName = edm::typeDemangle(typeid(RecordType).name());
206209
edm::LogWarning("BeamSpotOnlineProducer")
207210
<< "The beam spot record is too old. (record: " << recordTypeName << ")" << std::endl
208211
<< " record creation time: " << std::chrono::duration_cast<std::chrono::seconds>(bstime).count()
209212
<< " lumi block time: " << std::chrono::duration_cast<std::chrono::seconds>(lumitime).count();
210-
return fakeBS_;
213+
return nullptr;
211214
}
212-
return bs;
215+
return &bs;
213216
} else {
217+
const auto& recordTypeName = edm::typeDemangle(typeid(RecordType).name());
214218
edm::LogWarning("BeamSpotOnlineProducer") << "Invalid online beam spot handle for the record: " << recordTypeName;
215-
return fakeBS_;
219+
return nullptr;
216220
}
217221
}
218222

219-
const BeamSpotOnlineObjects& BeamSpotOnlineProducer::chooseBS(const BeamSpotOnlineObjects& bs1,
220-
const BeamSpotOnlineObjects& bs2) {
221-
if (bs1.beamType() == reco::BeamSpot::Tracker && bs2.beamType() == reco::BeamSpot::Tracker) {
222-
return bs1.sigmaZ() > bs2.sigmaZ() ? bs1 : bs2;
223-
} else if (bs1.beamType() == reco::BeamSpot::Tracker) {
223+
const BeamSpotOnlineObjects* BeamSpotOnlineProducer::chooseBS(const BeamSpotOnlineObjects* bs1,
224+
const BeamSpotOnlineObjects* bs2) const {
225+
if (bs1 and bs2 and bs1->beamType() == reco::BeamSpot::Tracker && bs2->beamType() == reco::BeamSpot::Tracker) {
226+
return bs1->sigmaZ() > bs2->sigmaZ() ? bs1 : bs2;
227+
} else if (bs1 and bs1->beamType() == reco::BeamSpot::Tracker) {
224228
return bs1;
225-
} else if (bs2.beamType() == reco::BeamSpot::Tracker) {
229+
} else if (bs2 and bs2->beamType() == reco::BeamSpot::Tracker) {
226230
return bs2;
227231
} else {
228-
return fakeBS_;
232+
return nullptr;
229233
}
230234
}
231235

232-
void BeamSpotOnlineProducer::createBeamSpotFromRecord(const BeamSpotObjects& spotDB) {
236+
reco::BeamSpot BeamSpotOnlineProducer::createBeamSpotFromRecord(const BeamSpotObjects& spotDB) const {
233237
double f = changeFrame_ ? -1.0 : 1.0;
234238
reco::BeamSpot::Point apoint(f * spotDB.x(), f * spotDB.y(), f * spotDB.z());
235239

@@ -241,15 +245,16 @@ void BeamSpotOnlineProducer::createBeamSpotFromRecord(const BeamSpotObjects& spo
241245
}
242246

243247
double sigmaZ = (theSetSigmaZ > 0) ? theSetSigmaZ : spotDB.sigmaZ();
244-
result = reco::BeamSpot(apoint, sigmaZ, spotDB.dxdz(), spotDB.dydz(), spotDB.beamWidthX(), matrix);
248+
reco::BeamSpot result(apoint, sigmaZ, spotDB.dxdz(), spotDB.dydz(), spotDB.beamWidthX(), matrix);
245249
result.setBeamWidthY(spotDB.beamWidthY());
246250
result.setEmittanceX(spotDB.emittanceX());
247251
result.setEmittanceY(spotDB.emittanceY());
248252
result.setbetaStar(spotDB.betaStar());
249253
result.setType(reco::BeamSpot::Tracker);
254+
return result;
250255
}
251256

252-
bool BeamSpotOnlineProducer::processScalers(const edm::Event& iEvent, bool shoutMODE) {
257+
std::optional<reco::BeamSpot> BeamSpotOnlineProducer::processScalers(const edm::Event& iEvent, bool shoutMODE) const {
253258
edm::Handle<BeamSpotOnlineCollection> handleScaler;
254259
iEvent.getByToken(scalerToken_, handleScaler);
255260

@@ -258,21 +263,19 @@ bool BeamSpotOnlineProducer::processScalers(const edm::Event& iEvent, bool shout
258263
edm::LogWarning("BeamSpotOnlineProducer") << " Scalers handle is empty. The Online "
259264
"Beam Spot producer falls back to the PCL value.";
260265
}
261-
return true; // Fallback to DB if scaler collection is empty
266+
return {};
262267
}
263268

264269
// Extract data from scaler
265270
BeamSpotOnline spotOnline = *(handleScaler->begin());
266-
createBeamSpotFromScaler(spotOnline);
267-
268271
// Validate the scaler data
269272
if (isInvalidScaler(spotOnline, shoutMODE)) {
270-
return true; // Trigger fallback to DB
273+
return {}; // Trigger fallback to DB
271274
}
272-
return false; // No fallback needed
275+
return createBeamSpotFromScaler(spotOnline);
273276
}
274277

275-
void BeamSpotOnlineProducer::createBeamSpotFromScaler(const BeamSpotOnline& spotOnline) {
278+
reco::BeamSpot BeamSpotOnlineProducer::createBeamSpotFromScaler(const BeamSpotOnline& spotOnline) const {
276279
double f = changeFrame_ ? -1.0 : 1.0;
277280
reco::BeamSpot::Point apoint(f * spotOnline.x(), spotOnline.y(), f * spotOnline.z());
278281

@@ -283,12 +286,13 @@ void BeamSpotOnlineProducer::createBeamSpotFromScaler(const BeamSpotOnline& spot
283286
matrix(3, 3) = spotOnline.err_sigma_z() * spotOnline.err_sigma_z();
284287

285288
double sigmaZ = (theSetSigmaZ > 0) ? theSetSigmaZ : spotOnline.sigma_z();
286-
result = reco::BeamSpot(apoint, sigmaZ, spotOnline.dxdz(), f * spotOnline.dydz(), spotOnline.width_x(), matrix);
289+
reco::BeamSpot result(apoint, sigmaZ, spotOnline.dxdz(), f * spotOnline.dydz(), spotOnline.width_x(), matrix);
287290
result.setBeamWidthY(spotOnline.width_y());
288291
result.setEmittanceX(0.0);
289292
result.setEmittanceY(0.0);
290293
result.setbetaStar(0.0);
291294
result.setType(reco::BeamSpot::LHC);
295+
return result;
292296
}
293297

294298
bool BeamSpotOnlineProducer::isInvalidScaler(const BeamSpotOnline& spotOnline, bool shoutMODE) const {
@@ -313,7 +317,7 @@ bool BeamSpotOnlineProducer::isInvalidScaler(const BeamSpotOnline& spotOnline, b
313317
return false;
314318
}
315319

316-
void BeamSpotOnlineProducer::createBeamSpotFromDB(const edm::EventSetup& iSetup, bool shoutMODE) {
320+
reco::BeamSpot BeamSpotOnlineProducer::createBeamSpotFromDB(const edm::EventSetup& iSetup, bool shoutMODE) const {
317321
edm::ESHandle<BeamSpotObjects> beamhandle = iSetup.getHandle(beamToken_);
318322
const BeamSpotObjects* spotDB = beamhandle.product();
319323

@@ -326,7 +330,7 @@ void BeamSpotOnlineProducer::createBeamSpotFromDB(const edm::EventSetup& iSetup,
326330
}
327331
}
328332

329-
result = reco::BeamSpot(apoint, spotDB->sigmaZ(), spotDB->dxdz(), spotDB->dydz(), spotDB->beamWidthX(), matrix);
333+
reco::BeamSpot result(apoint, spotDB->sigmaZ(), spotDB->dxdz(), spotDB->dydz(), spotDB->beamWidthX(), matrix);
330334
result.setBeamWidthY(spotDB->beamWidthY());
331335
result.setEmittanceX(spotDB->emittanceX());
332336
result.setEmittanceY(spotDB->emittanceY());
@@ -337,6 +341,7 @@ void BeamSpotOnlineProducer::createBeamSpotFromDB(const edm::EventSetup& iSetup,
337341
if ((bse.cxx() <= 0.0) || (bse.cyy() <= 0.0) || (bse.czz() <= 0.0)) {
338342
edm::LogError("UnusableBeamSpot") << "Beamspot from DB fallback has invalid errors: " << result.covariance();
339343
}
344+
return result;
340345
}
341346

342347
#include "FWCore/Framework/interface/MakerMacros.h"

0 commit comments

Comments
 (0)