CMS 3D CMS Logo

L2MuonSeedGenerator.cc
Go to the documentation of this file.
1 //-------------------------------------------------
2 //
15 //
16 //--------------------------------------------------
17 
18 // Class Header
20 
21 
22 // Framework
27 
35 
38 
39 using namespace std;
40 using namespace edm;
41 using namespace l1extra;
42 
43 // constructors
45  theSource(iConfig.getParameter<InputTag>("InputObjects")),
46  theL1GMTReadoutCollection(iConfig.getParameter<InputTag>("GMTReadoutCollection")),
47  thePropagatorName(iConfig.getParameter<string>("Propagator")),
48  theL1MinPt(iConfig.getParameter<double>("L1MinPt")),
49  theL1MaxEta(iConfig.getParameter<double>("L1MaxEta")),
50  theL1MinQuality(iConfig.getParameter<unsigned int>("L1MinQuality")),
51  useOfflineSeed(iConfig.getUntrackedParameter<bool>("UseOfflineSeed", false)),
52  useUnassociatedL1(iConfig.existsAs<bool>("UseUnassociatedL1") ?
53  iConfig.getParameter<bool>("UseUnassociatedL1") : true){
54 
55  gmtToken_ = consumes<L1MuGMTReadoutCollection>(theL1GMTReadoutCollection);
56  muCollToken_ = consumes<L1MuonParticleCollection>(theSource);
57 
58  if(useOfflineSeed) {
59  theOfflineSeedLabel = iConfig.getUntrackedParameter<InputTag>("OfflineSeedLabel");
60  offlineSeedToken_ = consumes<edm::View<TrajectorySeed> >(theOfflineSeedLabel);
61  }
62 
63  // service parameters
64  ParameterSet serviceParameters = iConfig.getParameter<ParameterSet>("ServiceParameters");
65 
66  // the services
67  theService = new MuonServiceProxy(serviceParameters);
68 
69  // the estimator
71 
72 
73  produces<L2MuonTrajectorySeedCollection>();
74 }
75 
76 // destructor
78  if (theService) delete theService;
79  if (theEstimator) delete theEstimator;
80 }
81 
83 {
84  const std::string metname = "Muon|RecoMuon|L2MuonSeedGenerator";
86 
87  auto output = std::make_unique<L2MuonTrajectorySeedCollection>();
88 
89  // Muon particles and GMT readout collection
91  iEvent.getByToken(gmtToken_,gmtrc_handle);
92  L1MuGMTReadoutRecord const& gmtrr = gmtrc_handle.product()->getRecord(0);
93 
95  iEvent.getByToken(muCollToken_, muColl);
96  LogTrace(metname) << "Number of muons " << muColl->size() << endl;
97 
98  edm::Handle<edm::View<TrajectorySeed> > offlineSeedHandle;
99  vector<int> offlineSeedMap;
100  if(useOfflineSeed) {
101  iEvent.getByToken(offlineSeedToken_, offlineSeedHandle);
102  LogTrace(metname) << "Number of offline seeds " << offlineSeedHandle->size() << endl;
103  offlineSeedMap = vector<int>(offlineSeedHandle->size(), 0);
104  }
105 
106  L1MuonParticleCollection::const_iterator it;
107  L1MuonParticleRef::key_type l1ParticleIndex = 0;
108 
109  for(it = muColl->begin(); it != muColl->end(); ++it,++l1ParticleIndex) {
110 
111  const L1MuGMTExtendedCand muonCand = (*it).gmtMuonCand();
112  unsigned int quality = 0;
113  bool valid_charge = false;;
114 
115  if ( muonCand.empty() ) {
116  LogWarning(metname) << "L2MuonSeedGenerator: WARNING, no L1MuGMTCand! " << endl;
117  LogWarning(metname) << "L2MuonSeedGenerator: this should make sense only within MC tests" << endl;
118  // FIXME! Temporary to handle the MC input
119  quality = 7;
120  valid_charge = true;
121  }
122  else {
123  quality = muonCand.quality();
124  valid_charge = muonCand.charge_valid();
125  }
126 
127  float pt = (*it).pt();
128  float eta = (*it).eta();
129  float theta = 2*atan(exp(-eta));
130  float phi = (*it).phi();
131  int charge = (*it).charge();
132  // Set charge=0 for the time being if the valid charge bit is zero
133  if (!valid_charge) charge = 0;
134  bool barrel = !(*it).isForward();
135 
136  // Get a better eta and charge from regional information
137  // Phi has the same resolution in GMT than regionally, is not it?
138  if ( !(muonCand.empty()) ) {
139  int idx = -1;
140  vector<L1MuRegionalCand> rmc;
141  if ( !muonCand.isRPC() ) {
142  idx = muonCand.getDTCSCIndex();
143  if (muonCand.isFwd()) rmc = gmtrr.getCSCCands();
144  else rmc = gmtrr.getDTBXCands();
145  } else {
146  idx = muonCand.getRPCIndex();
147  if (muonCand.isFwd()) rmc = gmtrr.getFwdRPCCands();
148  else rmc = gmtrr.getBrlRPCCands();
149  }
150  if (idx>=0) {
151  eta = rmc[idx].etaValue();
152  //phi = rmc[idx].phiValue();
153  // Use this charge if the valid charge bit is zero
154  if (!valid_charge) charge = rmc[idx].chargeValue();
155  }
156  }
157 
158  if ( pt < theL1MinPt || fabs(eta) > theL1MaxEta ) continue;
159 
160  LogTrace(metname) << "New L2 Muon Seed";
161  LogTrace(metname) << "Pt = " << pt << " GeV/c";
162  LogTrace(metname) << "eta = " << eta;
163  LogTrace(metname) << "theta = " << theta << " rad";
164  LogTrace(metname) << "phi = " << phi << " rad";
165  LogTrace(metname) << "charge = "<< charge;
166  LogTrace(metname) << "In Barrel? = "<< barrel;
167 
168  if ( quality <= theL1MinQuality ) continue;
169  LogTrace(metname) << "quality = "<< quality;
170 
171  // Update the services
172  theService->update(iSetup);
173 
174  const DetLayer *detLayer = 0;
175  float radius = 0.;
176 
177  CLHEP::Hep3Vector vec(0.,1.,0.);
178  vec.setTheta(theta);
179  vec.setPhi(phi);
180 
181  // Get the det layer on which the state should be put
182  if ( barrel ){
183  LogTrace(metname) << "The seed is in the barrel";
184 
185  // MB2
186  DetId id = DTChamberId(0,2,0);
187  detLayer = theService->detLayerGeometry()->idToLayer(id);
188  LogTrace(metname) << "L2 Layer: " << debug.dumpLayer(detLayer);
189 
190  const BoundSurface* sur = &(detLayer->surface());
191  const BoundCylinder* bc = dynamic_cast<const BoundCylinder*>(sur);
192 
193  radius = fabs(bc->radius()/sin(theta));
194 
195  LogTrace(metname) << "radius "<<radius;
196 
197  if ( pt < 3.5 ) pt = 3.5;
198  }
199  else {
200  LogTrace(metname) << "The seed is in the endcap";
201 
202  DetId id;
203  // ME2
204  if ( theta < Geom::pi()/2. )
205  id = CSCDetId(1,2,0,0,0);
206  else
207  id = CSCDetId(2,2,0,0,0);
208 
209  detLayer = theService->detLayerGeometry()->idToLayer(id);
210  LogTrace(metname) << "L2 Layer: " << debug.dumpLayer(detLayer);
211 
212  radius = fabs(detLayer->position().z()/cos(theta));
213 
214  if( pt < 1.0) pt = 1.0;
215  }
216 
217  vec.setMag(radius);
218 
219  GlobalPoint pos(vec.x(),vec.y(),vec.z());
220 
221  GlobalVector mom(pt*cos(phi), pt*sin(phi), pt*cos(theta)/sin(theta));
222 
223  GlobalTrajectoryParameters param(pos,mom,charge,&*theService->magneticField());
225 
226  mat[0][0] = (0.25/pt)*(0.25/pt); // sigma^2(charge/abs_momentum)
227  if ( !barrel ) mat[0][0] = (0.4/pt)*(0.4/pt);
228 
229  //Assign q/pt = 0 +- 1/pt if charge has been declared invalid
230  if (!valid_charge) mat[0][0] = (1./pt)*(1./pt);
231 
232  mat[1][1] = 0.05*0.05; // sigma^2(lambda)
233  mat[2][2] = 0.2*0.2; // sigma^2(phi)
234  mat[3][3] = 20.*20.; // sigma^2(x_transverse))
235  mat[4][4] = 20.*20.; // sigma^2(y_transverse))
236 
238 
239  const FreeTrajectoryState state(param,error);
240 
241  LogTrace(metname) << "Free trajectory State from the parameters";
242  LogTrace(metname) << debug.dumpFTS(state);
243 
244  // Propagate the state on the MB2/ME2 surface
245  TrajectoryStateOnSurface tsos = theService->propagator(thePropagatorName)->propagate(state, detLayer->surface());
246 
247  LogTrace(metname) << "State after the propagation on the layer";
248  LogTrace(metname) << debug.dumpLayer(detLayer);
249  LogTrace(metname) << debug.dumpFTS(state);
250 
251  if (tsos.isValid()) {
252  // Get the compatible dets on the layer
253  std::vector< pair<const GeomDet*,TrajectoryStateOnSurface> >
254  detsWithStates = detLayer->compatibleDets(tsos,
255  *theService->propagator(thePropagatorName),
256  *theEstimator);
257  if (detsWithStates.size()){
258 
259  TrajectoryStateOnSurface newTSOS = detsWithStates.front().second;
260  const GeomDet *newTSOSDet = detsWithStates.front().first;
261 
262  LogTrace(metname) << "Most compatible det";
263  LogTrace(metname) << debug.dumpMuonId(newTSOSDet->geographicalId());
264 
265  LogDebug(metname) << "L1 info: Det and State:";
266  LogDebug(metname) << debug.dumpMuonId(newTSOSDet->geographicalId());
267 
268  if (newTSOS.isValid()){
269 
270  //LogDebug(metname) << "(x, y, z) = (" << newTSOS.globalPosition().x() << ", "
271  // << newTSOS.globalPosition().y() << ", " << newTSOS.globalPosition().z() << ")";
272  LogDebug(metname) << "pos: (r=" << newTSOS.globalPosition().mag() << ", phi="
273  << newTSOS.globalPosition().phi() << ", eta=" << newTSOS.globalPosition().eta() << ")";
274  LogDebug(metname) << "mom: (q*pt=" << newTSOS.charge()*newTSOS.globalMomentum().perp() << ", phi="
275  << newTSOS.globalMomentum().phi() << ", eta=" << newTSOS.globalMomentum().eta() << ")";
276 
277  //LogDebug(metname) << "State on it";
278  //LogDebug(metname) << debug.dumpTSOS(newTSOS);
279 
280  //PTrajectoryStateOnDet seedTSOS;
282 
283  if(useOfflineSeed) {
284  const TrajectorySeed *assoOffseed =
285  associateOfflineSeedToL1(offlineSeedHandle, offlineSeedMap, newTSOS);
286 
287  if(assoOffseed!=0) {
288  PTrajectoryStateOnDet const & seedTSOS = assoOffseed->startingState();
290  tsci = assoOffseed->recHits().first,
291  tscie = assoOffseed->recHits().second;
292  for(; tsci!=tscie; ++tsci) {
293  container.push_back(*tsci);
294  }
295  output->push_back(L2MuonTrajectorySeed(seedTSOS,container,alongMomentum,
296  L1MuonParticleRef(muColl,l1ParticleIndex)));
297  }
298  else {
299  if(useUnassociatedL1) {
300  // convert the TSOS into a PTSOD
301  PTrajectoryStateOnDet const & seedTSOS = trajectoryStateTransform::persistentState( newTSOS,newTSOSDet->geographicalId().rawId());
302  output->push_back(L2MuonTrajectorySeed(seedTSOS,container,alongMomentum,
303  L1MuonParticleRef(muColl,l1ParticleIndex)));
304  }
305  }
306  }
307  else {
308  // convert the TSOS into a PTSOD
309  PTrajectoryStateOnDet const & seedTSOS = trajectoryStateTransform::persistentState( newTSOS,newTSOSDet->geographicalId().rawId());
310  output->push_back(L2MuonTrajectorySeed(seedTSOS,container,alongMomentum,
311  L1MuonParticleRef(muColl,l1ParticleIndex)));
312  }
313  }
314  }
315  }
316  }
317 
318  iEvent.put(std::move(output));
319 }
320 
321 
322 // FIXME: does not resolve ambiguities yet!
324  std::vector<int> & offseedMap,
325  TrajectoryStateOnSurface & newTsos) {
326 
327  const std::string metlabel = "Muon|RecoMuon|L2MuonSeedGenerator";
328  MuonPatternRecoDumper debugtmp;
329 
330  edm::View<TrajectorySeed>::const_iterator offseed, endOffseed = offseeds->end();
331  const TrajectorySeed *selOffseed = 0;
332  double bestDr = 99999.;
333  unsigned int nOffseed(0);
334  int lastOffseed(-1);
335 
336  for(offseed=offseeds->begin(); offseed!=endOffseed; ++offseed, ++nOffseed) {
337  if(offseedMap[nOffseed]!=0) continue;
338  GlobalPoint glbPos = theService->trackingGeometry()->idToDet(offseed->startingState().detId())->surface().toGlobal(offseed->startingState().parameters().position());
339  GlobalVector glbMom = theService->trackingGeometry()->idToDet(offseed->startingState().detId())->surface().toGlobal(offseed->startingState().parameters().momentum());
340 
341  // Preliminary check
342  double preDr = deltaR( newTsos.globalPosition().eta(), newTsos.globalPosition().phi(), glbPos.eta(), glbPos.phi() );
343  if(preDr > 1.0) continue;
344 
345  const FreeTrajectoryState offseedFTS(glbPos, glbMom, offseed->startingState().parameters().charge(), &*theService->magneticField());
346  TrajectoryStateOnSurface offseedTsos = theService->propagator(thePropagatorName)->propagate(offseedFTS, newTsos.surface());
347  LogDebug(metlabel) << "Offline seed info: Det and State" << std::endl;
348  LogDebug(metlabel) << debugtmp.dumpMuonId(offseed->startingState().detId()) << std::endl;
349  //LogDebug(metlabel) << "(x, y, z) = (" << newTSOS.globalPosition().x() << ", "
350  // << newTSOS.globalPosition().y() << ", " << newTSOS.globalPosition().z() << ")" << std::endl;
351  LogDebug(metlabel) << "pos: (r=" << offseedFTS.position().mag() << ", phi="
352  << offseedFTS.position().phi() << ", eta=" << offseedFTS.position().eta() << ")" << std::endl;
353  LogDebug(metlabel) << "mom: (q*pt=" << offseedFTS.charge()*offseedFTS.momentum().perp() << ", phi="
354  << offseedFTS.momentum().phi() << ", eta=" << offseedFTS.momentum().eta() << ")" << std::endl << std::endl;
355  //LogDebug(metlabel) << debugtmp.dumpFTS(offseedFTS) << std::endl;
356 
357  if(offseedTsos.isValid()) {
358  LogDebug(metlabel) << "Offline seed info after propagation to L1 layer:" << std::endl;
359  //LogDebug(metlabel) << "(x, y, z) = (" << offseedTsos.globalPosition().x() << ", "
360  // << offseedTsos.globalPosition().y() << ", " << offseedTsos.globalPosition().z() << ")" << std::endl;
361  LogDebug(metlabel) << "pos: (r=" << offseedTsos.globalPosition().mag() << ", phi="
362  << offseedTsos.globalPosition().phi() << ", eta=" << offseedTsos.globalPosition().eta() << ")" << std::endl;
363  LogDebug(metlabel) << "mom: (q*pt=" << offseedTsos.charge()*offseedTsos.globalMomentum().perp() << ", phi="
364  << offseedTsos.globalMomentum().phi() << ", eta=" << offseedTsos.globalMomentum().eta() << ")" << std::endl << std::endl;
365  //LogDebug(metlabel) << debugtmp.dumpTSOS(offseedTsos) << std::endl;
366  double newDr = deltaR( newTsos.globalPosition().eta(), newTsos.globalPosition().phi(),
367  offseedTsos.globalPosition().eta(), offseedTsos.globalPosition().phi() );
368  LogDebug(metlabel) << " -- DR = " << newDr << std::endl;
369  if( newDr<0.3 && newDr<bestDr ) {
370  LogDebug(metlabel) << " --> OK! " << newDr << std::endl << std::endl;
371  selOffseed = &*offseed;
372  bestDr = newDr;
373  offseedMap[nOffseed] = 1;
374  if(lastOffseed>-1) offseedMap[lastOffseed] = 0;
375  lastOffseed = nOffseed;
376  }
377  else {
378  LogDebug(metlabel) << " --> Rejected. " << newDr << std::endl << std::endl;
379  }
380  }
381  else {
382  LogDebug(metlabel) << "Invalid offline seed TSOS after propagation!" << std::endl << std::endl;
383  }
384  }
385 
386  return selOffseed;
387 }
#define LogDebug(id)
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
std::remove_cv< typename std::remove_reference< argument_type >::type >::type key_type
Definition: Ref.h:169
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:122
T perp() const
Definition: PV3DBase.h:72
edm::EDGetTokenT< l1extra::L1MuonParticleCollection > muCollToken_
edm::InputTag theL1GMTReadoutCollection
edm::EDGetTokenT< edm::View< TrajectorySeed > > offlineSeedToken_
std::string dumpLayer(const DetLayer *layer) const
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:460
const std::string metname
virtual void produce(edm::Event &, const edm::EventSetup &) override
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
PTrajectoryStateOnDet persistentState(const TrajectoryStateOnSurface &ts, unsigned int detid)
Geom::Theta< T > theta() const
GlobalPoint globalPosition() const
ROOT::Math::SMatrix< double, 5, 5, ROOT::Math::MatRepSym< double, 5 > > AlgebraicSymMatrix55
std::vector< L1MuRegionalCand > getBrlRPCCands() const
get barrel RPC candidates vector
virtual std::vector< DetWithState > compatibleDets(const TrajectoryStateOnSurface &startingState, const Propagator &prop, const MeasurementEstimator &est) const
~L2MuonSeedGenerator()
Destructor.
std::string dumpMuonId(const DetId &id) const
std::string dumpFTS(const FreeTrajectoryState &fts) const
std::vector< L1MuRegionalCand > getFwdRPCCands() const
get forward RPC candidates vector
uint32_t rawId() const
get the raw id
Definition: DetId.h:43
const TrajectorySeed * associateOfflineSeedToL1(edm::Handle< edm::View< TrajectorySeed > > &, std::vector< int > &, TrajectoryStateOnSurface &)
const unsigned theL1MinQuality
std::vector< L1MuRegionalCand > getCSCCands() const
get CSC candidates vector
void push_back(D *&d)
Definition: OwnVector.h:290
bool empty() const
is it an empty muon candidate?
Definition: L1MuGMTCand.h:64
int iEvent
Definition: GenABIO.cc:230
const SurfaceType & surface() const
T mag() const
Definition: PV3DBase.h:67
const_iterator begin() const
bool isRPC() const
get RPC bit (true=RPC, false = DT/CSC or matched)
recHitContainer::const_iterator const_iterator
bool charge_valid() const
is the charge valid ?
Definition: L1MuGMTCand.h:138
T z() const
Definition: PV3DBase.h:64
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
unsigned getRPCIndex() const
get index of contributing RPC muon
virtual const BoundSurface & surface() const =0
The surface of the GeometricSearchDet.
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:79
#define LogTrace(id)
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
unsigned int quality() const
get quality
Definition: L1MuGMTCand.h:93
Definition: DetId.h:18
PTrajectoryStateOnDet const & startingState() const
#define debug
Definition: HDRShower.cc:19
unsigned getDTCSCIndex() const
get index of contributing DT/CSC muon
MeasurementEstimator * theEstimator
virtual const Surface::PositionType & position() const
Returns position of the surface.
std::vector< L1MuRegionalCand > getDTBXCands() const
get DT candidates vector
range recHits() const
edm::Ref< L1MuonParticleCollection > L1MuonParticleRef
T eta() const
Definition: PV3DBase.h:76
MuonServiceProxy * theService
the event setup proxy, it takes care the services update
HLT enums.
GlobalVector globalMomentum() const
boost::indirect_iterator< typename seq_t::const_iterator > const_iterator
Definition: View.h:86
edm::EDGetTokenT< L1MuGMTReadoutCollection > gmtToken_
constexpr double pi()
Definition: Pi.h:31
L2MuonSeedGenerator(const edm::ParameterSet &)
Constructor.
bool isFwd() const
get forward bit (true=forward, false=barrel)
def move(src, dest)
Definition: eostools.py:510
edm::InputTag theOfflineSeedLabel