File indexing completed on 2024-04-06 12:26:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include "RecoMuon/L2MuonSeedGenerator/src/L2MuonSeedGenerator.h"
0020
0021
0022 #include "FWCore/Framework/interface/ConsumesCollector.h"
0023 #include "FWCore/Framework/interface/EventSetup.h"
0024 #include "FWCore/Framework/interface/Event.h"
0025 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0026 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0027
0028 #include "TrackingTools/TrajectoryParametrization/interface/GlobalTrajectoryParameters.h"
0029 #include "TrackingTools/TrajectoryParametrization/interface/CurvilinearTrajectoryError.h"
0030 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
0031 #include "TrackingTools/TrajectoryState/interface/FreeTrajectoryState.h"
0032 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
0033 #include "TrackingTools/KalmanUpdators/interface/Chi2MeasurementEstimator.h"
0034 #include "TrackingTools/DetLayers/interface/DetLayer.h"
0035
0036 #include "RecoMuon/TrackingTools/interface/MuonServiceProxy.h"
0037 #include "RecoMuon/TrackingTools/interface/MuonPatternRecoDumper.h"
0038
0039 using namespace std;
0040 using namespace edm;
0041 using namespace l1extra;
0042
0043
0044 L2MuonSeedGenerator::L2MuonSeedGenerator(const edm::ParameterSet& iConfig)
0045 : theSource(iConfig.getParameter<InputTag>("InputObjects")),
0046 theL1GMTReadoutCollection(iConfig.getParameter<InputTag>("GMTReadoutCollection")),
0047 thePropagatorName(iConfig.getParameter<string>("Propagator")),
0048 theL1MinPt(iConfig.getParameter<double>("L1MinPt")),
0049 theL1MaxEta(iConfig.getParameter<double>("L1MaxEta")),
0050 theL1MinQuality(iConfig.getParameter<unsigned int>("L1MinQuality")),
0051 useOfflineSeed(iConfig.getUntrackedParameter<bool>("UseOfflineSeed", false)),
0052 useUnassociatedL1(iConfig.existsAs<bool>("UseUnassociatedL1") ? iConfig.getParameter<bool>("UseUnassociatedL1")
0053 : true) {
0054 gmtToken_ = consumes<L1MuGMTReadoutCollection>(theL1GMTReadoutCollection);
0055 muCollToken_ = consumes<L1MuonParticleCollection>(theSource);
0056
0057 if (useOfflineSeed) {
0058 theOfflineSeedLabel = iConfig.getUntrackedParameter<InputTag>("OfflineSeedLabel");
0059 offlineSeedToken_ = consumes<edm::View<TrajectorySeed> >(theOfflineSeedLabel);
0060 }
0061
0062
0063 ParameterSet serviceParameters = iConfig.getParameter<ParameterSet>("ServiceParameters");
0064
0065
0066 theService = new MuonServiceProxy(serviceParameters, consumesCollector());
0067
0068
0069 theEstimator = new Chi2MeasurementEstimator(10000.);
0070
0071 produces<L2MuonTrajectorySeedCollection>();
0072 }
0073
0074
0075 L2MuonSeedGenerator::~L2MuonSeedGenerator() {
0076 if (theService)
0077 delete theService;
0078 if (theEstimator)
0079 delete theEstimator;
0080 }
0081
0082 void L2MuonSeedGenerator::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0083 const std::string metname = "Muon|RecoMuon|L2MuonSeedGenerator";
0084 MuonPatternRecoDumper debug;
0085
0086 auto output = std::make_unique<L2MuonTrajectorySeedCollection>();
0087
0088
0089 edm::Handle<L1MuGMTReadoutCollection> gmtrc_handle;
0090 iEvent.getByToken(gmtToken_, gmtrc_handle);
0091 L1MuGMTReadoutRecord const& gmtrr = gmtrc_handle.product()->getRecord(0);
0092
0093 edm::Handle<L1MuonParticleCollection> muColl;
0094 iEvent.getByToken(muCollToken_, muColl);
0095 LogTrace(metname) << "Number of muons " << muColl->size() << endl;
0096
0097 edm::Handle<edm::View<TrajectorySeed> > offlineSeedHandle;
0098 vector<int> offlineSeedMap;
0099 if (useOfflineSeed) {
0100 iEvent.getByToken(offlineSeedToken_, offlineSeedHandle);
0101 LogTrace(metname) << "Number of offline seeds " << offlineSeedHandle->size() << endl;
0102 offlineSeedMap = vector<int>(offlineSeedHandle->size(), 0);
0103 }
0104
0105 L1MuonParticleCollection::const_iterator it;
0106 L1MuonParticleRef::key_type l1ParticleIndex = 0;
0107
0108 for (it = muColl->begin(); it != muColl->end(); ++it, ++l1ParticleIndex) {
0109 const L1MuGMTExtendedCand muonCand = (*it).gmtMuonCand();
0110 unsigned int quality = 0;
0111 bool valid_charge = false;
0112 ;
0113
0114 if (muonCand.empty()) {
0115 LogWarning(metname) << "L2MuonSeedGenerator: WARNING, no L1MuGMTCand! " << endl;
0116 LogWarning(metname) << "L2MuonSeedGenerator: this should make sense only within MC tests" << endl;
0117
0118 quality = 7;
0119 valid_charge = true;
0120 } else {
0121 quality = muonCand.quality();
0122 valid_charge = muonCand.charge_valid();
0123 }
0124
0125 float pt = (*it).pt();
0126 float eta = (*it).eta();
0127 float theta = 2 * atan(exp(-eta));
0128 float phi = (*it).phi();
0129 int charge = (*it).charge();
0130
0131 if (!valid_charge)
0132 charge = 0;
0133 bool barrel = !(*it).isForward();
0134
0135
0136
0137 if (!(muonCand.empty())) {
0138 int idx = -1;
0139 vector<L1MuRegionalCand> rmc;
0140 if (!muonCand.isRPC()) {
0141 idx = muonCand.getDTCSCIndex();
0142 if (muonCand.isFwd())
0143 rmc = gmtrr.getCSCCands();
0144 else
0145 rmc = gmtrr.getDTBXCands();
0146 } else {
0147 idx = muonCand.getRPCIndex();
0148 if (muonCand.isFwd())
0149 rmc = gmtrr.getFwdRPCCands();
0150 else
0151 rmc = gmtrr.getBrlRPCCands();
0152 }
0153 if (idx >= 0) {
0154 eta = rmc[idx].etaValue();
0155
0156
0157 if (!valid_charge)
0158 charge = rmc[idx].chargeValue();
0159 }
0160 }
0161
0162 if (pt < theL1MinPt || fabs(eta) > theL1MaxEta)
0163 continue;
0164
0165 LogTrace(metname) << "New L2 Muon Seed";
0166 LogTrace(metname) << "Pt = " << pt << " GeV/c";
0167 LogTrace(metname) << "eta = " << eta;
0168 LogTrace(metname) << "theta = " << theta << " rad";
0169 LogTrace(metname) << "phi = " << phi << " rad";
0170 LogTrace(metname) << "charge = " << charge;
0171 LogTrace(metname) << "In Barrel? = " << barrel;
0172
0173 if (quality <= theL1MinQuality)
0174 continue;
0175 LogTrace(metname) << "quality = " << quality;
0176
0177
0178 theService->update(iSetup);
0179
0180 const DetLayer* detLayer = nullptr;
0181 float radius = 0.;
0182
0183 CLHEP::Hep3Vector vec(0., 1., 0.);
0184 vec.setTheta(theta);
0185 vec.setPhi(phi);
0186
0187
0188 if (barrel) {
0189 LogTrace(metname) << "The seed is in the barrel";
0190
0191
0192 DetId id = DTChamberId(0, 2, 0);
0193 detLayer = theService->detLayerGeometry()->idToLayer(id);
0194 LogTrace(metname) << "L2 Layer: " << debug.dumpLayer(detLayer);
0195
0196 const BoundSurface* sur = &(detLayer->surface());
0197 const BoundCylinder* bc = dynamic_cast<const BoundCylinder*>(sur);
0198
0199 radius = fabs(bc->radius() / sin(theta));
0200
0201 LogTrace(metname) << "radius " << radius;
0202
0203 if (pt < 3.5)
0204 pt = 3.5;
0205 } else {
0206 LogTrace(metname) << "The seed is in the endcap";
0207
0208 DetId id;
0209
0210 if (theta < Geom::pi() / 2.)
0211 id = CSCDetId(1, 2, 0, 0, 0);
0212 else
0213 id = CSCDetId(2, 2, 0, 0, 0);
0214
0215 detLayer = theService->detLayerGeometry()->idToLayer(id);
0216 LogTrace(metname) << "L2 Layer: " << debug.dumpLayer(detLayer);
0217
0218 radius = fabs(detLayer->position().z() / cos(theta));
0219
0220 if (pt < 1.0)
0221 pt = 1.0;
0222 }
0223
0224 vec.setMag(radius);
0225
0226 GlobalPoint pos(vec.x(), vec.y(), vec.z());
0227
0228 GlobalVector mom(pt * cos(phi), pt * sin(phi), pt * cos(theta) / sin(theta));
0229
0230 GlobalTrajectoryParameters param(pos, mom, charge, &*theService->magneticField());
0231 AlgebraicSymMatrix55 mat;
0232
0233 mat[0][0] = (0.25 / pt) * (0.25 / pt);
0234 if (!barrel)
0235 mat[0][0] = (0.4 / pt) * (0.4 / pt);
0236
0237
0238 if (!valid_charge)
0239 mat[0][0] = (1. / pt) * (1. / pt);
0240
0241 mat[1][1] = 0.05 * 0.05;
0242 mat[2][2] = 0.2 * 0.2;
0243 mat[3][3] = 20. * 20.;
0244 mat[4][4] = 20. * 20.;
0245
0246 CurvilinearTrajectoryError error(mat);
0247
0248 const FreeTrajectoryState state(param, error);
0249
0250 LogTrace(metname) << "Free trajectory State from the parameters";
0251 LogTrace(metname) << debug.dumpFTS(state);
0252
0253
0254 TrajectoryStateOnSurface tsos = theService->propagator(thePropagatorName)->propagate(state, detLayer->surface());
0255
0256 LogTrace(metname) << "State after the propagation on the layer";
0257 LogTrace(metname) << debug.dumpLayer(detLayer);
0258 LogTrace(metname) << debug.dumpFTS(state);
0259
0260 if (tsos.isValid()) {
0261
0262 std::vector<pair<const GeomDet*, TrajectoryStateOnSurface> > detsWithStates =
0263 detLayer->compatibleDets(tsos, *theService->propagator(thePropagatorName), *theEstimator);
0264 if (!detsWithStates.empty()) {
0265 TrajectoryStateOnSurface newTSOS = detsWithStates.front().second;
0266 const GeomDet* newTSOSDet = detsWithStates.front().first;
0267
0268 LogTrace(metname) << "Most compatible det";
0269 LogTrace(metname) << debug.dumpMuonId(newTSOSDet->geographicalId());
0270
0271 LogDebug(metname) << "L1 info: Det and State:";
0272 LogDebug(metname) << debug.dumpMuonId(newTSOSDet->geographicalId());
0273
0274 if (newTSOS.isValid()) {
0275
0276
0277 LogDebug(metname) << "pos: (r=" << newTSOS.globalPosition().mag()
0278 << ", phi=" << newTSOS.globalPosition().phi() << ", eta=" << newTSOS.globalPosition().eta()
0279 << ")";
0280 LogDebug(metname) << "mom: (q*pt=" << newTSOS.charge() * newTSOS.globalMomentum().perp()
0281 << ", phi=" << newTSOS.globalMomentum().phi() << ", eta=" << newTSOS.globalMomentum().eta()
0282 << ")";
0283
0284
0285
0286
0287
0288 edm::OwnVector<TrackingRecHit> container;
0289
0290 if (useOfflineSeed) {
0291 const TrajectorySeed* assoOffseed = associateOfflineSeedToL1(offlineSeedHandle, offlineSeedMap, newTSOS);
0292
0293 if (assoOffseed != nullptr) {
0294 PTrajectoryStateOnDet const& seedTSOS = assoOffseed->startingState();
0295 for (auto const& tsci : assoOffseed->recHits()) {
0296 container.push_back(tsci);
0297 }
0298 output->push_back(
0299 L2MuonTrajectorySeed(seedTSOS, container, alongMomentum, L1MuonParticleRef(muColl, l1ParticleIndex)));
0300 } else {
0301 if (useUnassociatedL1) {
0302
0303 PTrajectoryStateOnDet const& seedTSOS =
0304 trajectoryStateTransform::persistentState(newTSOS, newTSOSDet->geographicalId().rawId());
0305 output->push_back(L2MuonTrajectorySeed(
0306 seedTSOS, container, alongMomentum, L1MuonParticleRef(muColl, l1ParticleIndex)));
0307 }
0308 }
0309 } else {
0310
0311 PTrajectoryStateOnDet const& seedTSOS =
0312 trajectoryStateTransform::persistentState(newTSOS, newTSOSDet->geographicalId().rawId());
0313 output->push_back(
0314 L2MuonTrajectorySeed(seedTSOS, container, alongMomentum, L1MuonParticleRef(muColl, l1ParticleIndex)));
0315 }
0316 }
0317 }
0318 }
0319 }
0320
0321 iEvent.put(std::move(output));
0322 }
0323
0324
0325 const TrajectorySeed* L2MuonSeedGenerator::associateOfflineSeedToL1(edm::Handle<edm::View<TrajectorySeed> >& offseeds,
0326 std::vector<int>& offseedMap,
0327 TrajectoryStateOnSurface& newTsos) {
0328 const std::string metlabel = "Muon|RecoMuon|L2MuonSeedGenerator";
0329 MuonPatternRecoDumper debugtmp;
0330
0331 edm::View<TrajectorySeed>::const_iterator offseed, endOffseed = offseeds->end();
0332 const TrajectorySeed* selOffseed = nullptr;
0333 double bestDr = 99999.;
0334 unsigned int nOffseed(0);
0335 int lastOffseed(-1);
0336
0337 for (offseed = offseeds->begin(); offseed != endOffseed; ++offseed, ++nOffseed) {
0338 if (offseedMap[nOffseed] != 0)
0339 continue;
0340 GlobalPoint glbPos = theService->trackingGeometry()
0341 ->idToDet(offseed->startingState().detId())
0342 ->surface()
0343 .toGlobal(offseed->startingState().parameters().position());
0344 GlobalVector glbMom = theService->trackingGeometry()
0345 ->idToDet(offseed->startingState().detId())
0346 ->surface()
0347 .toGlobal(offseed->startingState().parameters().momentum());
0348
0349
0350 double preDr = deltaR(newTsos.globalPosition().eta(), newTsos.globalPosition().phi(), glbPos.eta(), glbPos.phi());
0351 if (preDr > 1.0)
0352 continue;
0353
0354 const FreeTrajectoryState offseedFTS(
0355 glbPos, glbMom, offseed->startingState().parameters().charge(), &*theService->magneticField());
0356 TrajectoryStateOnSurface offseedTsos =
0357 theService->propagator(thePropagatorName)->propagate(offseedFTS, newTsos.surface());
0358 LogDebug(metlabel) << "Offline seed info: Det and State" << std::endl;
0359 LogDebug(metlabel) << debugtmp.dumpMuonId(offseed->startingState().detId()) << std::endl;
0360
0361
0362 LogDebug(metlabel) << "pos: (r=" << offseedFTS.position().mag() << ", phi=" << offseedFTS.position().phi()
0363 << ", eta=" << offseedFTS.position().eta() << ")" << std::endl;
0364 LogDebug(metlabel) << "mom: (q*pt=" << offseedFTS.charge() * offseedFTS.momentum().perp()
0365 << ", phi=" << offseedFTS.momentum().phi() << ", eta=" << offseedFTS.momentum().eta() << ")"
0366 << std::endl
0367 << std::endl;
0368
0369
0370 if (offseedTsos.isValid()) {
0371 LogDebug(metlabel) << "Offline seed info after propagation to L1 layer:" << std::endl;
0372
0373
0374 LogDebug(metlabel) << "pos: (r=" << offseedTsos.globalPosition().mag()
0375 << ", phi=" << offseedTsos.globalPosition().phi()
0376 << ", eta=" << offseedTsos.globalPosition().eta() << ")" << std::endl;
0377 LogDebug(metlabel) << "mom: (q*pt=" << offseedTsos.charge() * offseedTsos.globalMomentum().perp()
0378 << ", phi=" << offseedTsos.globalMomentum().phi()
0379 << ", eta=" << offseedTsos.globalMomentum().eta() << ")" << std::endl
0380 << std::endl;
0381
0382 double newDr = deltaR(newTsos.globalPosition().eta(),
0383 newTsos.globalPosition().phi(),
0384 offseedTsos.globalPosition().eta(),
0385 offseedTsos.globalPosition().phi());
0386 LogDebug(metlabel) << " -- DR = " << newDr << std::endl;
0387 if (newDr < 0.3 && newDr < bestDr) {
0388 LogDebug(metlabel) << " --> OK! " << newDr << std::endl << std::endl;
0389 selOffseed = &*offseed;
0390 bestDr = newDr;
0391 offseedMap[nOffseed] = 1;
0392 if (lastOffseed > -1)
0393 offseedMap[lastOffseed] = 0;
0394 lastOffseed = nOffseed;
0395 } else {
0396 LogDebug(metlabel) << " --> Rejected. " << newDr << std::endl << std::endl;
0397 }
0398 } else {
0399 LogDebug(metlabel) << "Invalid offline seed TSOS after propagation!" << std::endl << std::endl;
0400 }
0401 }
0402
0403 return selOffseed;
0404 }