CMS 3D CMS Logo

Phase2L1TGMTFwdMuonTranslator.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 
3 #ifndef PHASE2GMT_SAFWDMUONTRANSLATOR
4 #define PHASE2GMT_SAFWDMUONTRANSLATOR
5 
6 // system include files
7 #include <memory>
8 #include <sstream>
9 
10 // user include files
21 
22 //
23 // class declaration
24 //
25 using namespace Phase2L1GMT;
26 using namespace l1t;
27 
29 public:
31  ~Phase2L1TGMTFwdMuonTranslator() override = default;
32 
33  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
34 
35 private:
36  void produce(edm::Event&, const edm::EventSetup&) override;
37 
38  l1t::SAMuon Convertl1tMuon(const l1t::RegionalMuonCand& mu, const int bx_, bool isDisplaced = false);
39  l1t::MuonStubRefVector selectLayerBX(const l1t::MuonStubRefVector& all, int bx, uint layer);
40  void associateStubs(l1t::SAMuon&, const l1t::MuonStubRefVector&);
41 
42  l1t::SAMuon ConvertEMTFTrack(const l1t::phase2::EMTFTrack& track, const int bx_);
43 
44  // ----------member data ---------------------------
48 };
49 //
50 // constants, enums and typedefs
51 //
52 
53 //
54 // static data member definitions
55 //
56 
57 //
58 // constructors and destructor
59 //
61  : stubToken_(consumes<l1t::MuonStubCollection>(iConfig.getParameter<edm::InputTag>("stubs"))),
62  omtfTrackToken_(consumes<l1t::RegionalMuonCandBxCollection>(iConfig.getParameter<edm::InputTag>("omtfTracks"))),
63  emtfTrackToken_(consumes<l1t::phase2::EMTFTrackCollection>(iConfig.getParameter<edm::InputTag>("emtfTracks"))) {
64  produces<std::vector<l1t::SAMuon> >("prompt").setBranchAlias("prompt");
65  produces<std::vector<l1t::SAMuon> >("displaced").setBranchAlias("displaced");
66 }
67 
68 // ------------ method called to produce the data ------------
70  using namespace edm;
71 
73  iEvent.getByToken(stubToken_, stubHandle);
74 
76  iEvent.getByToken(emtfTrackToken_, emtf_tracks);
77 
79  iEvent.getByToken(omtfTrackToken_, omtf_tracks);
80 
81  // Process Stubs
83 
84  for (uint i = 0; i < stubHandle->size(); ++i) {
85  l1t::MuonStubRef stub(stubHandle, i);
86 
87  if (stub->bxNum() == 0)
88  stubs.push_back(stub);
89  }
90 
91  // Collect Muons
92  std::vector<SAMuon> prompt;
93 
94  // TODO: Will receive hybrid stubs from OMTF/EMTF
95  std::vector<SAMuon> displaced;
96 
97  // Convert OMTF Muons to SAMuons
98  for (unsigned int i = 0; i < omtf_tracks->size(0); ++i) {
99  const l1t::RegionalMuonCand& mu = omtf_tracks->at(0, i);
100  // Since OMTF is using Phase-1 LSB, will convert to SAMuon locally
101  // We should move to passing words in future
102  l1t::SAMuon samuon;
103  if (mu.hwPt() > 0) {
104  samuon = Convertl1tMuon(mu, 0);
105  //now associate the stubs
106  associateStubs(samuon, stubs);
107  prompt.push_back(samuon);
108  }
109  if (mu.hwPtUnconstrained() > 0) {
110  samuon = Convertl1tMuon(mu, 0, true);
111  //now associate the stubs
112  associateStubs(samuon, stubs);
113  displaced.push_back(samuon);
114  }
115  }
116 
117  // Convert EMTF++ Tracks to SAMuons
118  for (unsigned int track_id = 0; track_id < emtf_tracks->size(); ++track_id) {
119  const auto& track = emtf_tracks->at(track_id);
120 
121  // Short-Circuit: Only keep valid tracks that are in BX=0
122  if ((track.valid() == 0) || (track.bx() != 0)) {
123  continue;
124  }
125 
126  // Short-Circuit: Only keep tracks with quality above 3 to avoid single hit tracks
127  if (track.emtfQuality() <= 3) {
128  continue;
129  }
130 
131  // Short-Circuit: Only keep tracks with the max relevance score (127)
132  if (track.emtfRels() != 127) {
133  continue;
134  }
135 
136  auto samuon = ConvertEMTFTrack(track, 0);
137 
138  //now associate the stubs
139  associateStubs(samuon, stubs);
140 
141  // Add To Collections
142  if (track.unconstrained()) {
143  displaced.push_back(samuon);
144  } else {
145  prompt.push_back(samuon);
146  }
147  }
148 
149  // Output Prompt Muon Collection
150  std::unique_ptr<std::vector<l1t::SAMuon> > prompt_ptr = std::make_unique<std::vector<l1t::SAMuon> >(prompt);
151  std::unique_ptr<std::vector<l1t::SAMuon> > displaced_ptr = std::make_unique<std::vector<l1t::SAMuon> >(displaced);
152  iEvent.put(std::move(prompt_ptr), "prompt");
153  iEvent.put(std::move(displaced_ptr), "displaced");
154 }
155 
156 // === FUNCTION ============================================================
157 // Name: Phase2L1TGMTFwdMuonTranslator::Convertl1tMuon
158 // Description:
159 // ===========================================================================
161  ap_uint<BITSSAQUAL> qual = mu.hwQual();
162  int charge = mu.hwSign();
163 
164  ap_uint<BITSGTPT> pt = 0;
165  if (!isDisplaced && mu.hwPt() > 0)
166  pt = round(mu.hwPt() * 0.5 / LSBpt); // Phase-1 LSB 0.5GeV
167  if (isDisplaced && mu.hwPtUnconstrained() > 0)
168  pt = round(mu.hwPtUnconstrained() * 1.0 / LSBpt); // Phase-1 LSB 1.0GeV!!
169 
170  // BEWARE: THIS CONVERSION IS ONLY VALID FOR OMTF
171  constexpr double p1phiLSB = 2 * M_PI / 576;
172  // From the uGMTConfiguration of OMTF. OMTF send in local phi!!
173  // all others correspond to 120 degree sectors = 192 in int-scale
174  int globPhi = mu.processor() * 192 + mu.hwPhi();
175  // first processor starts at CMS phi = 15 degrees (24 in int)... Handle wrap-around with %. Add 576 to make sure the number is positive
176  globPhi = (globPhi + 600) % 576;
177  ap_int<BITSGTPHI> phi = round(globPhi * p1phiLSB / LSBphi); // Phase-1 LSB (2*pi/576)
178  ap_int<BITSGTETA> eta = round(mu.hwEta() * 0.010875 / LSBeta); // Phase-1 LSB 0.010875
179 
180  // FIXME: Below are not well defined in phase1 GMT
181  // Using the version from Correlator for now
182  ap_int<BITSSAZ0> z0 = 0; // No tracks info in Phase 1
183  // Use 2 bits with LSB = 30cm for BMTF and 25cm for EMTF currently, but subjet to change
184  ap_int<BITSSAD0> d0 = mu.hwDXY();
185 
186  //Here do not use the word format to GT but use the word format expected by GMT
187  int bstart = 0;
188  wordtype word(0);
189  bstart = wordconcat<wordtype>(word, bstart, 1, 1);
190  bstart = wordconcat<wordtype>(word, bstart, charge, 1);
191  bstart = wordconcat<wordtype>(word, bstart, pt, BITSPT);
192  bstart = wordconcat<wordtype>(word, bstart, phi, BITSPHI);
193  bstart = wordconcat<wordtype>(word, bstart, eta, BITSETA);
194  // bstart = wordconcat<wordtype>(word, bstart, z0, BITSSAZ0); NOT YET SUPPORTED BY GMT
195  bstart = wordconcat<wordtype>(word, bstart, d0, BITSSAD0);
196  bstart = wordconcat<wordtype>(
197  word, bstart, qual, 8); //FOR NOW 8 bits to be efficienct with Ghost busting. THIS IS ***NOT*** THE FINAL QUALITY
198 
199  // Calculate Lorentz Vector
201  SAMuon samuon(p4, charge, pt.to_uint(), eta.to_int(), phi.to_int(), z0.to_int(), d0.to_int(), qual.to_uint());
202  samuon.setTF(mu.trackFinderType());
203  samuon.setWord(word);
204 
205  return samuon;
206 } // ----- end of function Phase2L1TGMTFwdMuonTranslator::Convertl1tMuon -----
207 
209  int bx,
210  uint layer) {
212  for (const auto& stub : all) {
213  if (stub->bxNum() == bx && stub->tfLayer() == layer)
214  out.push_back(stub);
215  }
216  return out;
217 }
218 
220  for (unsigned int layer = 0; layer <= 4; ++layer) {
221  l1t::MuonStubRefVector selectedStubs = selectLayerBX(stubs, 0, layer);
222  int bestStubINT = -1;
223  float dPhi = 1000.0;
224  for (uint i = 0; i < selectedStubs.size(); ++i) {
225  const l1t::MuonStubRef& stub = selectedStubs[i];
226  float deltaPhi =
227  (stub->quality() & 0x1) ? stub->offline_coord1() - mu.p4().phi() : stub->offline_coord2() - mu.p4().phi();
228  if (deltaPhi > M_PI)
229  deltaPhi = deltaPhi - 2 * M_PI;
230  if (deltaPhi < -M_PI)
231  deltaPhi = deltaPhi + 2 * M_PI;
232  deltaPhi = fabs(deltaPhi);
233  float deltaEta = (stub->etaQuality() == 0 || (stub->etaQuality() & 0x1))
234  ? fabs(stub->offline_eta1() - mu.p4().eta())
235  : fabs(stub->offline_eta2() - mu.p4().eta());
236  if (deltaPhi < 0.3 && deltaEta < 0.3 && deltaPhi < dPhi) {
237  dPhi = deltaPhi;
238  bestStubINT = i;
239  }
240  }
241  if (bestStubINT >= 0) {
242  mu.addStub(selectedStubs[bestStubINT]);
243  }
244  }
245 }
246 
248  // Convert EMTF Phi and Theta to Global Phi and Eta
249  float track_phi =
251  float track_theta = emtf::phase2::tp::calcThetaRadFromInt(track.modelEta());
252  float track_eta = -1 * std::log(std::tan(track_theta / 2));
253 
254  track_theta *= track.endcap();
255  track_eta *= track.endcap();
256 
257  // Calculate Lorentz Vector
258  // Muon mass taken from L1Trigger/L1TMuon/plugins/L1TMuonProducer.cc
259  math::PtEtaPhiMLorentzVector p4(track.emtfPt() * LSBpt, track_eta, track_phi, 0.0);
260 
261  // Quantize Values
262  ap_uint<BITSSAQUAL> qual = track.emtfQuality(); // Quality provided by EMTF to GMT
263  int charge = track.emtfQ(); // EMTF uses the same convention
264  ap_uint<BITSGTPT> pt = track.emtfPt(); // Quantized by EMTF in the same units
265  ap_int<BITSGTPHI> phi = round(track_phi / LSBphi);
266  ap_int<BITSGTETA> eta = round(track_eta / LSBeta);
267  ap_int<BITSSAZ0> z0 = track.emtfZ0(); // Quantized by EMTF in the same units
268  ap_int<BITSSAD0> d0 = track.emtfD0(); // Quantized by EMTF in the same units
269 
270  //Here do not use the word format to GT but use the word format expected by GMT
271  int bstart = 0;
272  wordtype word(0);
273  bstart = wordconcat<wordtype>(word, bstart, 1, 1);
274  bstart = wordconcat<wordtype>(word, bstart, charge, 1);
275  bstart = wordconcat<wordtype>(word, bstart, pt, BITSPT);
276  bstart = wordconcat<wordtype>(word, bstart, phi, BITSPHI);
277  bstart = wordconcat<wordtype>(word, bstart, eta, BITSETA);
278  // bstart = wordconcat<wordtype>(word, bstart, z0, BITSSAZ0); NOT YET SUPPORTED BY GMT
279  bstart = wordconcat<wordtype>(word, bstart, d0, BITSSAD0);
280  bstart = wordconcat<wordtype>(
281  word, bstart, qual, 8); //FOR NOW 8 bits to be efficienct with Ghost busting. THIS IS ***NOT*** THE FINAL QUALITY
282 
283  SAMuon samuon(p4, charge, pt.to_uint(), eta.to_int(), phi.to_int(), z0.to_int(), d0.to_int(), qual.to_uint());
284 
285  // +1=Positive Endcap and -1=Negative Endcap
286  if (track.endcap() == 1)
287  samuon.setTF(tftype::emtf_pos);
288  else
289  samuon.setTF(tftype::emtf_neg);
290 
291  samuon.setWord(word);
292 
293  return samuon;
294 }
295 
296 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
298  //The following says we do not know what parameters are allowed so do no validation
299  // Please change this to state exactly what you do use, even if it is no parameters
301 
302  // Input Collections
303  desc.add<edm::InputTag>("stubs", edm::InputTag("gmtStubs"));
304  desc.add<edm::InputTag>("emtfTracks", edm::InputTag("simEmtfDigisPhase2"));
305  desc.add<edm::InputTag>("omtfTracks", edm::InputTag("simOmtfPhase2Digis"));
306 
307  // Register
308  descriptions.add("Phase2L1TGMTFwdMuonTranslator", desc);
309 }
310 
311 //define this as a plug-in
313 #endif
const float LSBphi
Definition: Constants.h:93
l1t::MuonStubRefVector selectLayerBX(const l1t::MuonStubRefVector &all, int bx, uint layer)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
def all(container)
workaround iterator generators for ROOT classes
Definition: cmstools.py:25
const int BITSSAD0
Definition: Constants.h:56
edm::EDGetTokenT< l1t::MuonStubCollection > stubToken_
delete x;
Definition: CaloConfig.h:22
float calcPhiLocRadFromInt(int)
Definition: TPUtils.cc:99
static const double deltaEta
Definition: CaloConstants.h:8
std::vector< edm::Ref< MuonStubCollection > > MuonStubRefVector
Definition: MuonStub.h:44
ap_uint< 64 > wordtype
Definition: Constants.h:101
unsigned size(int bx) const
PtEtaPhiMLorentzVectorD PtEtaPhiMLorentzVector
Lorentz vector with cartesian internal representation.
Definition: LorentzVector.h:25
l1t::SAMuon ConvertEMTFTrack(const l1t::phase2::EMTFTrack &track, const int bx_)
uint64_t word
const float LSBpt
Definition: Constants.h:92
int iEvent
Definition: GenABIO.cc:224
const int BITSETA
Definition: Constants.h:26
void produce(edm::Event &, const edm::EventSetup &) override
const int BITSPT
Definition: Constants.h:24
void setTF(tftype tf)
Definition: SAMuon.h:34
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
const int BITSPHI
Definition: Constants.h:25
const T & at(int bx, unsigned i) const
#define M_PI
std::vector< MuonStub > MuonStubCollection
Definition: MuonStub.h:40
const float LSBeta
Definition: Constants.h:94
float calcThetaRadFromInt(int)
Definition: TPUtils.cc:50
static constexpr float d0
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void associateStubs(l1t::SAMuon &, const l1t::MuonStubRefVector &)
l1t::SAMuon Convertl1tMuon(const l1t::RegionalMuonCand &mu, const int bx_, bool isDisplaced=false)
HLT enums.
edm::EDGetTokenT< l1t::phase2::EMTFTrackCollection > emtfTrackToken_
std::vector< EMTFTrack > EMTFTrackCollection
Definition: EMTFTrack.h:251
float calcPhiGlobRadFromLoc(int, float)
Definition: TPUtils.cc:85
def move(src, dest)
Definition: eostools.py:511
Phase2L1TGMTFwdMuonTranslator(const edm::ParameterSet &)
edm::EDGetTokenT< l1t::RegionalMuonCandBxCollection > omtfTrackToken_