File indexing completed on 2025-06-20 01:53:08
0001 #include "DataFormats/L1TParticleFlow/interface/layer1_emulator.h"
0002 #include <cmath>
0003 #include <iostream>
0004 #include <cstdlib>
0005 #include <algorithm>
0006
0007 #ifdef CMSSW_GIT_HASH
0008 #include "DataFormats/Math/interface/deltaPhi.h"
0009 #else
0010 namespace reco {
0011 template <typename T>
0012 inline T reducePhiRange(T x) {
0013 T o2pi = 1. / (2. * M_PI);
0014 if (std::abs(x) <= T(M_PI))
0015 return x;
0016 T n = std::round(x * o2pi);
0017 return x - n * T(2. * M_PI);
0018 }
0019 inline double deltaPhi(double phi1, double phi2) { return reducePhiRange(phi1 - phi2); }
0020 }
0021 #endif
0022
0023 bool l1ct::HadCaloObjEmu::read(std::fstream& from) {
0024 src = nullptr;
0025 return readObj<HadCaloObj>(from, *this);
0026 }
0027 bool l1ct::HadCaloObjEmu::write(std::fstream& to) const { return writeObj<HadCaloObj>(*this, to); }
0028
0029 bool l1ct::EmCaloObjEmu::read(std::fstream& from) {
0030 src = nullptr;
0031 return readObj<EmCaloObj>(from, *this);
0032 }
0033 bool l1ct::EmCaloObjEmu::write(std::fstream& to) const { return writeObj<EmCaloObj>(*this, to); }
0034
0035 bool l1ct::TkObjEmu::read(std::fstream& from) {
0036 src = nullptr;
0037 return readObj<TkObj>(from, *this) && readVar(from, hwChi2) && readVar(from, simPt) && readVar(from, simCaloEta) &&
0038 readVar(from, simCaloPhi) && readVar(from, simVtxEta) && readVar(from, simVtxPhi) && readVar(from, simZ0) &&
0039 readVar(from, simD0);
0040 }
0041 bool l1ct::TkObjEmu::write(std::fstream& to) const {
0042 return writeObj<TkObj>(*this, to) && writeVar(hwChi2, to) && writeVar(simPt, to) && writeVar(simCaloEta, to) &&
0043 writeVar(simCaloPhi, to) && writeVar(simVtxEta, to) && writeVar(simVtxPhi, to) && writeVar(simZ0, to) &&
0044 writeVar(simD0, to);
0045 }
0046
0047 bool l1ct::MuObjEmu::read(std::fstream& from) {
0048 src = nullptr;
0049 return readObj<MuObj>(from, *this);
0050 }
0051 bool l1ct::MuObjEmu::write(std::fstream& to) const { return writeObj<MuObj>(*this, to); }
0052
0053 bool l1ct::PFChargedObjEmu::read(std::fstream& from) {
0054 srcTrack = nullptr;
0055 srcCluster = nullptr;
0056 srcMu = nullptr;
0057 srcCand = nullptr;
0058 return readObj<PFChargedObj>(from, *this);
0059 }
0060 bool l1ct::PFChargedObjEmu::write(std::fstream& to) const { return writeObj<PFChargedObj>(*this, to); }
0061
0062 bool l1ct::PFNeutralObjEmu::read(std::fstream& from) {
0063 srcCluster = nullptr;
0064 srcCand = nullptr;
0065 return readObj<PFNeutralObj>(from, *this);
0066 }
0067 bool l1ct::PFNeutralObjEmu::write(std::fstream& to) const { return writeObj<PFNeutralObj>(*this, to); }
0068
0069 bool l1ct::PuppiObjEmu::read(std::fstream& from) {
0070 srcTrack = nullptr;
0071 srcCluster = nullptr;
0072 srcMu = nullptr;
0073 srcCand = nullptr;
0074 return readObj<PuppiObj>(from, *this);
0075 }
0076 bool l1ct::PuppiObjEmu::write(std::fstream& to) const { return writeObj<PuppiObj>(*this, to); }
0077
0078 bool l1ct::EGIsoObjEmu::read(std::fstream& from) {
0079 srcCluster = nullptr;
0080 src_idx = -1;
0081 clearIsoVars();
0082 return readObj<EGIsoObj>(from, *this);
0083 }
0084
0085 bool l1ct::EGIsoObjEmu::write(std::fstream& to) const { return writeObj<EGIsoObj>(*this, to); }
0086
0087 bool l1ct::EGIsoEleObjEmu::read(std::fstream& from) {
0088 srcCluster = nullptr;
0089 srcTrack = nullptr;
0090 src_idx = -1;
0091 clearIsoVars();
0092 return readObj<EGIsoEleObj>(from, *this);
0093 }
0094
0095 bool l1ct::EGIsoEleObjEmu::write(std::fstream& to) const { return writeObj<EGIsoEleObj>(*this, to); }
0096
0097 l1ct::PFRegionEmu::PFRegionEmu(float etaCenter, float phicenter) {
0098 hwEtaCenter = Scales::makeGlbEta(etaCenter);
0099 hwPhiCenter = Scales::makeGlbPhi(phicenter);
0100 hwEtaHalfWidth = 0;
0101 hwPhiHalfWidth = 0;
0102 hwEtaExtra = 0;
0103 hwPhiExtra = 0;
0104 }
0105 l1ct::PFRegionEmu::PFRegionEmu(
0106 float etamin, float etamax, float phicenter, float phiwidth, float etaextra, float phiextra) {
0107 glbeta_t hwEtaMin = Scales::makeGlbEtaRoundEven(etamin);
0108 glbeta_t hwEtaMax = Scales::makeGlbEtaRoundEven(etamax);
0109
0110 hwEtaCenter = glbeta_t((hwEtaMin + hwEtaMax) / 2);
0111 hwPhiCenter = Scales::makeGlbPhi(phicenter);
0112 hwEtaHalfWidth = hwEtaCenter - hwEtaMin;
0113 hwPhiHalfWidth = Scales::makeGlbPhi(0.5 * phiwidth);
0114 hwEtaExtra = Scales::makeGlbEta(etaextra);
0115 hwPhiExtra = Scales::makeGlbPhi(phiextra);
0116 }
0117
0118 bool l1ct::PFRegionEmu::contains(float eta, float phi) const {
0119 float dphi = reco::deltaPhi(phi, floatPhiCenter());
0120 return (floatEtaMinExtra() <= eta && eta <= floatEtaMaxExtra() && -floatPhiHalfWidthExtra() <= dphi &&
0121 dphi <= floatPhiHalfWidthExtra());
0122 }
0123 bool l1ct::PFRegionEmu::containsHw(glbeta_t glbeta, glbphi_t glbphi) const {
0124 glbeta_t loceta = glbeta - hwEtaCenter;
0125 ap_int<glbphi_t::width + 1> locphi = glbphi - hwPhiCenter;
0126 if (locphi > Scales::INTPHI_PI)
0127 locphi -= Scales::INTPHI_TWOPI;
0128 else if (locphi <= -Scales::INTPHI_PI)
0129 locphi += Scales::INTPHI_TWOPI;
0130 return isInside(loceta, locphi);
0131 }
0132
0133 float l1ct::PFRegionEmu::localEta(float globalEta) const { return globalEta - floatEtaCenter(); }
0134 float l1ct::PFRegionEmu::localPhi(float globalPhi) const { return reco::deltaPhi(globalPhi, floatPhiCenter()); }
0135
0136 bool l1ct::PFRegionEmu::read(std::fstream& from) { return readObj<PFRegion>(from, *this); }
0137 bool l1ct::PFRegionEmu::write(std::fstream& to) const { return writeObj<PFRegion>(*this, to); }
0138
0139 bool l1ct::PVObjEmu::read(std::fstream& from) { return readObj<PVObj>(from, *this); }
0140 bool l1ct::PVObjEmu::write(std::fstream& to) const { return writeObj<PVObj>(*this, to); }
0141
0142 bool l1ct::RawInputs::read(std::fstream& from) {
0143 uint32_t number;
0144
0145 if (!readVar(from, number))
0146 return false;
0147 track.resize(number);
0148 for (auto& v : track) {
0149 if (!(v.region.read(from) && readMany(from, v.obj)))
0150 return false;
0151 }
0152
0153 if (!(muon.region.read(from) && readMany(from, muon.obj)))
0154 return false;
0155
0156 if (!readVar(from, number))
0157 return false;
0158 hgcalcluster.resize(number);
0159 for (auto& v : hgcalcluster) {
0160 if (!(v.region.read(from) && readMany(from, v.obj)))
0161 return false;
0162 }
0163
0164 if (!readVar(from, number))
0165 return false;
0166 gctHad.resize(number);
0167 for (auto& v : gctHad) {
0168 if (!(v.region.read(from) && readMany(from, v.obj)))
0169 return false;
0170 }
0171
0172 if (!readVar(from, number))
0173 return false;
0174 gctEm.resize(number);
0175 for (auto& v : gctEm) {
0176 if (!(v.region.read(from) && readMany(from, v.obj)))
0177 return false;
0178 }
0179
0180 return true;
0181 }
0182
0183 bool l1ct::RawInputs::write(std::fstream& to) const {
0184 uint32_t number;
0185
0186 number = track.size();
0187 if (!writeVar(number, to))
0188 return false;
0189 for (const auto& v : track) {
0190 if (!(v.region.write(to) && writeMany(v.obj, to)))
0191 return false;
0192 }
0193
0194 if (!(muon.region.write(to) && writeMany(muon.obj, to)))
0195 return false;
0196
0197 number = hgcalcluster.size();
0198 if (!writeVar(number, to))
0199 return false;
0200 for (const auto& v : hgcalcluster) {
0201 if (!(v.region.write(to) && writeMany(v.obj, to)))
0202 return false;
0203 }
0204
0205 number = gctHad.size();
0206 if (!writeVar(number, to))
0207 return false;
0208 for (const auto& v : gctHad) {
0209 if (!(v.region.write(to) && writeMany(v.obj, to)))
0210 return false;
0211 }
0212
0213 number = gctEm.size();
0214 if (!writeVar(number, to))
0215 return false;
0216 for (const auto& v : gctEm) {
0217 if (!(v.region.write(to) && writeMany(v.obj, to)))
0218 return false;
0219 }
0220 return true;
0221 }
0222 void l1ct::RawInputs::clear() {
0223 for (auto& r : track)
0224 r.clear();
0225 muon.clear();
0226 for (auto& h : hgcalcluster)
0227 h.clear();
0228 for (auto& h : gctHad)
0229 h.clear();
0230 for (auto& h : gctEm)
0231 h.clear();
0232 }
0233
0234 bool l1ct::RegionizerDecodedInputs::read(std::fstream& from) {
0235 uint32_t number;
0236
0237 if (!readVar(from, number))
0238 return false;
0239 hadcalo.resize(number);
0240 for (auto& v : hadcalo) {
0241 if (!(v.region.read(from) && readMany(from, v.obj)))
0242 return false;
0243 }
0244
0245 if (!readVar(from, number))
0246 return false;
0247 emcalo.resize(number);
0248 for (auto& v : emcalo) {
0249 if (!(v.region.read(from) && readMany(from, v.obj)))
0250 return false;
0251 }
0252
0253 if (!readVar(from, number))
0254 return false;
0255 track.resize(number);
0256 for (auto& v : track) {
0257 if (!(v.region.read(from) && readMany(from, v.obj)))
0258 return false;
0259 }
0260
0261 if (!(muon.region.read(from) && readMany(from, muon.obj)))
0262 return false;
0263
0264 return true;
0265 }
0266
0267 bool l1ct::RegionizerDecodedInputs::write(std::fstream& to) const {
0268 uint32_t number;
0269
0270 number = hadcalo.size();
0271 if (!writeVar(number, to))
0272 return false;
0273 for (const auto& v : hadcalo) {
0274 if (!(v.region.write(to) && writeMany(v.obj, to)))
0275 return false;
0276 }
0277
0278 number = emcalo.size();
0279 if (!writeVar(number, to))
0280 return false;
0281 for (const auto& v : emcalo) {
0282 if (!(v.region.write(to) && writeMany(v.obj, to)))
0283 return false;
0284 }
0285
0286 number = track.size();
0287 if (!writeVar(number, to))
0288 return false;
0289 for (const auto& v : track) {
0290 if (!(v.region.write(to) && writeMany(v.obj, to)))
0291 return false;
0292 }
0293
0294 if (!(muon.region.write(to) && writeMany(muon.obj, to)))
0295 return false;
0296
0297 return true;
0298 }
0299 void l1ct::RegionizerDecodedInputs::clear() {
0300 for (auto& r : hadcalo)
0301 r.clear();
0302 for (auto& r : emcalo)
0303 r.clear();
0304 for (auto& r : track)
0305 r.clear();
0306 muon.clear();
0307 }
0308
0309 bool l1ct::PFInputRegion::read(std::fstream& from) {
0310 return region.read(from) && readMany(from, hadcalo) && readMany(from, emcalo) && readMany(from, track) &&
0311 readMany(from, muon);
0312 }
0313 bool l1ct::PFInputRegion::write(std::fstream& to) const {
0314 return region.write(to) && writeMany(hadcalo, to) && writeMany(emcalo, to) && writeMany(track, to) &&
0315 writeMany(muon, to);
0316 }
0317 void l1ct::PFInputRegion::clear() {
0318 hadcalo.clear();
0319 emcalo.clear();
0320 track.clear();
0321 muon.clear();
0322 }
0323
0324 bool l1ct::OutputRegion::read(std::fstream& from) {
0325 return readMany(from, pfcharged) && readMany(from, pfneutral) && readMany(from, pfphoton) && readMany(from, pfmuon) &&
0326 readMany(from, puppi) && readMany(from, egphoton) && readMany(from, egelectron);
0327 }
0328 bool l1ct::OutputRegion::write(std::fstream& to) const {
0329 return writeMany(pfcharged, to) && writeMany(pfneutral, to) && writeMany(pfphoton, to) && writeMany(pfmuon, to) &&
0330 writeMany(puppi, to) && writeMany(egphoton, to) && writeMany(egelectron, to);
0331 }
0332
0333 void l1ct::OutputRegion::clear() {
0334 pfcharged.clear();
0335 pfphoton.clear();
0336 pfneutral.clear();
0337 pfmuon.clear();
0338 puppi.clear();
0339 egsta.clear();
0340 egphoton.clear();
0341 egelectron.clear();
0342 }
0343
0344
0345 namespace {
0346 template <typename TV>
0347 unsigned int count_nonnull(const TV& v) {
0348 typedef typename TV::value_type T;
0349 return std::count_if(v.begin(), v.end(), [](const T& p) { return p.hwPt > 0; });
0350 }
0351 template <typename TV, typename F>
0352 unsigned int count_nonnull_if(const TV& v, F pred) {
0353 unsigned int n = 0;
0354 for (auto& p : v) {
0355 if (p.hwPt > 0 && pred(p.hwId))
0356 ++n;
0357 }
0358 return n;
0359 }
0360 }
0361
0362 unsigned int l1ct::OutputRegion::nObj(ObjType type, bool usePuppi) const {
0363 switch (type) {
0364 case anyType:
0365 if (usePuppi)
0366 return ::count_nonnull(puppi);
0367 else
0368 return ::count_nonnull(pfcharged) + ::count_nonnull(pfphoton) + ::count_nonnull(pfneutral);
0369 case chargedType:
0370 if (usePuppi)
0371 return ::count_nonnull_if(puppi, [](const l1ct::ParticleID& i) { return i.charged(); });
0372 else
0373 return ::count_nonnull(pfcharged);
0374 case neutralType:
0375 if (usePuppi)
0376 return ::count_nonnull_if(puppi, [](const l1ct::ParticleID& i) { return i.neutral(); });
0377 else
0378 return ::count_nonnull(pfphoton) + ::count_nonnull(pfneutral);
0379 case electronType:
0380 if (usePuppi)
0381 return ::count_nonnull_if(puppi, [](const l1ct::ParticleID& i) { return i.isElectron(); });
0382 else
0383 return ::count_nonnull_if(pfcharged, [](const l1ct::ParticleID& i) { return i.isElectron(); });
0384 case muonType:
0385 if (usePuppi)
0386 return ::count_nonnull_if(puppi, [](const l1ct::ParticleID& i) { return i.isMuon(); });
0387 else
0388 return ::count_nonnull_if(pfcharged, [](const l1ct::ParticleID& i) { return i.isMuon(); });
0389 case chargedHadronType:
0390 if (usePuppi)
0391 return ::count_nonnull_if(puppi, [](const l1ct::ParticleID& i) { return i.isChargedHadron(); });
0392 else
0393 return ::count_nonnull_if(pfcharged, [](const l1ct::ParticleID& i) { return i.isChargedHadron(); });
0394 case neutralHadronType:
0395 if (usePuppi)
0396 return ::count_nonnull_if(puppi,
0397 [](const l1ct::ParticleID& i) { return i.rawId() == l1ct::ParticleID::HADZERO; });
0398 else
0399 return ::count_nonnull_if(pfneutral,
0400 [](const l1ct::ParticleID& i) { return i.rawId() == l1ct::ParticleID::HADZERO; });
0401 case photonType:
0402 if (usePuppi)
0403 return ::count_nonnull_if(puppi,
0404 [](const l1ct::ParticleID& i) { return i.rawId() == l1ct::ParticleID::PHOTON; });
0405 else
0406 return ::count_nonnull_if(pfneutral,
0407 [](const l1ct::ParticleID& i) { return i.rawId() == l1ct::ParticleID::PHOTON; }) +
0408 ::count_nonnull_if(pfphoton,
0409 [](const l1ct::ParticleID& i) { return i.rawId() == l1ct::ParticleID::PHOTON; });
0410 case egisoType:
0411 assert(!usePuppi);
0412 return ::count_nonnull(egphoton);
0413 case egisoeleType:
0414 assert(!usePuppi);
0415 return ::count_nonnull(egelectron);
0416 default:
0417 assert(false);
0418 }
0419 }
0420
0421 bool l1ct::OutputBoard::read(std::fstream& from) {
0422 return readVar(from, eta) && readVar(from, phi) && readMany(from, egphoton) && readMany(from, egelectron);
0423 }
0424 bool l1ct::OutputBoard::write(std::fstream& to) const {
0425 return writeVar(eta, to) && writeVar(phi, to) && writeMany(egphoton, to) && writeMany(egelectron, to);
0426 }
0427
0428 void l1ct::OutputBoard::clear() {
0429 egphoton.clear();
0430 egelectron.clear();
0431 }
0432
0433 bool l1ct::Event::read(std::fstream& from) {
0434 uint32_t version;
0435 if (!readVar(from, version))
0436 return false;
0437 if (version != VERSION) {
0438
0439
0440
0441
0442 abort();
0443 }
0444 return readVar(from, run) && readVar(from, lumi) && readVar(from, event) && raw.read(from) && decoded.read(from) &&
0445 readMany(from, pfinputs) && readMany(from, pvs) && readMany(from, pvs_emu) && readMany(from, out) &&
0446 readMany(from, board_out);
0447 }
0448 bool l1ct::Event::write(std::fstream& to) const {
0449 uint32_t version = VERSION;
0450 return writeVar(version, to) && writeVar(run, to) && writeVar(lumi, to) && writeVar(event, to) && raw.write(to) &&
0451 decoded.write(to) && writeMany(pfinputs, to) && writeMany(pvs, to) && writeMany(pvs_emu, to) &&
0452 writeMany(out, to) && writeMany(board_out, to);
0453 }
0454 void l1ct::Event::init(uint32_t arun, uint32_t alumi, uint64_t anevent) {
0455 clear();
0456 run = arun;
0457 lumi = alumi;
0458 event = anevent;
0459 }
0460 void l1ct::Event::clear() {
0461 run = 0;
0462 lumi = 0;
0463 event = 0;
0464 raw.clear();
0465 decoded.clear();
0466 for (auto& i : pfinputs)
0467 i.clear();
0468 pvs.clear();
0469 pvs_emu.clear();
0470 for (auto& i : out)
0471 i.clear();
0472 for (auto& i : board_out)
0473 i.clear();
0474 }