CMS 3D CMS Logo

CSCSimHitMatcher.cc
Go to the documentation of this file.
2 #include "TGraphErrors.h"
3 #include "TF1.h"
4 #include "TMinuitMinimizer.h"
5 
6 using namespace std;
7 
9  : MuonSimHitMatcher(ps, std::move(iC)) {
10  simHitPSet_ = ps.getParameterSet("cscSimHit");
11  verbose_ = simHitPSet_.getParameter<int>("verbose");
12  simMuOnly_ = simHitPSet_.getParameter<bool>("simMuOnly");
13  discardEleHits_ = simHitPSet_.getParameter<bool>("discardEleHits");
14 
16  geomToken_ = iC.esConsumes<CSCGeometry, MuonGeometryRecord>();
17 
18  //In order to make fitting ROOT histograms thread safe
19  // one must call this undocumented function
20  TMinuitMinimizer::UseStaticMinuit(false);
21 }
22 
25  geometry_ = &iSetup.getData(geomToken_);
27 }
28 
31  clear();
32 
33  // instantiates the track ids and simhits
35 
36  // hard cut on non-CSC muons
37  if (std::abs(track.momentum().eta()) < 0.9)
38  return;
39  if (std::abs(track.momentum().eta()) > 2.45)
40  return;
41 
43 
44  if (verbose_) {
45  edm::LogInfo("CSCSimHitMatcher") << "nTrackIds " << track_ids_.size() << " nSelectedCSCSimHits " << hits_.size();
46  edm::LogInfo("CSCSimHitMatcher") << "detids CSC " << detIds(0).size();
47 
48  for (const auto& id : detIds(0)) {
49  const auto& simhits = hitsInDetId(id);
50  const auto& simhits_gp = simHitsMeanPosition(simhits);
51  const auto& strips = hitStripsInDetId(id);
52  CSCDetId cscid(id);
53  if (cscid.station() == 1 and (cscid.ring() == 1 or cscid.ring() == 4)) {
54  edm::LogInfo("CSCSimHitMatcher") << "cscdetid " << CSCDetId(id) << ": " << simhits.size() << " "
55  << simhits_gp.phi() << " " << detid_to_hits_[id].size();
56  edm::LogInfo("CSCSimHitMatcher") << "nStrip " << strips.size();
57  edm::LogInfo("CSCSimHitMatcher") << "strips : ";
58  for (const auto& p : strips) {
59  edm::LogInfo("CSCSimHitMatcher") << p;
60  }
61  }
62  }
63  }
64 }
65 
67  for (const auto& track_id : track_ids_) {
68  for (const auto& h : simHits_) {
69  if (h.trackId() != track_id)
70  continue;
71  int pdgid = h.particleType();
72  if (simMuOnly_ && std::abs(pdgid) != 13)
73  continue;
74  // discard electron hits in the CSC chambers
75  if (discardEleHits_ && std::abs(pdgid) == 11)
76  continue;
77 
78  const CSCDetId& layer_id(h.detUnitId());
79  hits_.push_back(h);
80  detid_to_hits_[h.detUnitId()].push_back(h);
81  chamber_to_hits_[layer_id.chamberId().rawId()].push_back(h);
82  }
83  }
84 }
85 
86 std::set<unsigned int> CSCSimHitMatcher::detIds(int csc_type) const {
87  std::set<unsigned int> result;
88  for (const auto& p : detid_to_hits_) {
89  const auto& id = p.first;
90  if (csc_type > 0) {
91  CSCDetId detId(id);
92  if (MuonHitHelper::toCSCType(detId.station(), detId.ring()) != csc_type)
93  continue;
94  }
95  result.insert(id);
96  }
97  return result;
98 }
99 
100 std::set<unsigned int> CSCSimHitMatcher::chamberIds(int csc_type) const {
101  std::set<unsigned int> result;
102  for (const auto& p : chamber_to_hits_) {
103  const auto& id = p.first;
104  if (csc_type > 0) {
105  CSCDetId detId(id);
106  if (MuonHitHelper::toCSCType(detId.station(), detId.ring()) != csc_type)
107  continue;
108  }
109  result.insert(id);
110  }
111  return result;
112 }
113 
114 int CSCSimHitMatcher::nLayersWithHitsInChamber(unsigned int detid) const {
115  set<int> layers_with_hits;
116  for (const auto& h : MuonSimHitMatcher::hitsInChamber(detid)) {
117  const CSCDetId& idd(h.detUnitId());
118  layers_with_hits.insert(idd.layer());
119  }
120  return layers_with_hits.size();
121 }
122 
123 bool CSCSimHitMatcher::hitStation(int st, int nlayers) const {
124  int nst = 0;
125  for (const auto& ddt : chamberIds()) {
126  const CSCDetId id(ddt);
127  int ri(id.ring());
128  if (id.station() != st)
129  continue;
130 
131  // ME1/a case - check the ME1/b chamber
132  if (st == 1 and ri == 4) {
133  CSCDetId idME1b(id.endcap(), id.station(), 1, id.chamber(), 0);
134  const int nl1a(nLayersWithHitsInChamber(id.rawId()));
135  const int nl1b(nLayersWithHitsInChamber(idME1b.rawId()));
136  if (nl1a + nl1b < nlayers)
137  continue;
138  ++nst;
139  }
140  // ME1/b case - check the ME1/a chamber
141  else if (st == 1 and ri == 1) {
142  CSCDetId idME1a(id.endcap(), id.station(), 4, id.chamber(), 0);
143  const int nl1a(nLayersWithHitsInChamber(idME1a.rawId()));
144  const int nl1b(nLayersWithHitsInChamber(id.rawId()));
145  if (nl1a + nl1b < nlayers)
146  continue;
147  ++nst;
148  }
149  // default case
150  else {
151  const int nl(nLayersWithHitsInChamber(id.rawId()));
152  if (nl < nlayers)
153  continue;
154  ++nst;
155  }
156  }
157  return nst;
158 }
159 
161  return (hitStation(1, nlayers) + hitStation(2, nlayers) + hitStation(3, nlayers) + hitStation(4, nlayers));
162 }
163 
164 float CSCSimHitMatcher::LocalBendingInChamber(unsigned int detid) const {
165  const CSCDetId cscid(detid);
166  if (nLayersWithHitsInChamber(detid) < 6)
167  return -100;
168  float phi_layer1 = -10;
169  float phi_layer6 = 10;
170 
171  if (cscid.station() == 1 and (cscid.ring() == 1 or cscid.ring() == 4)) {
172  // phi in layer 1
173  const CSCDetId cscid1a(cscid.endcap(), cscid.station(), 4, cscid.chamber(), 1);
174  const CSCDetId cscid1b(cscid.endcap(), cscid.station(), 1, cscid.chamber(), 1);
175  const edm::PSimHitContainer& hits1a = MuonSimHitMatcher::hitsInDetId(cscid1a.rawId());
176  const edm::PSimHitContainer& hits1b = MuonSimHitMatcher::hitsInDetId(cscid1b.rawId());
177  const GlobalPoint& gp1a = simHitsMeanPosition(MuonSimHitMatcher::hitsInDetId(cscid1a.rawId()));
178  const GlobalPoint& gp1b = simHitsMeanPosition(MuonSimHitMatcher::hitsInDetId(cscid1b.rawId()));
179  if (!hits1a.empty() and !hits1b.empty())
180  phi_layer1 = (gp1a.phi() + gp1b.phi()) / 2.0;
181  else if (!hits1a.empty())
182  phi_layer1 = gp1a.phi();
183  else if (!hits1b.empty())
184  phi_layer1 = gp1b.phi();
185 
186  // phi in layer 6
187  const CSCDetId cscid6a(cscid.endcap(), cscid.station(), 4, cscid.chamber(), 6);
188  const CSCDetId cscid6b(cscid.endcap(), cscid.station(), 1, cscid.chamber(), 6);
189  const edm::PSimHitContainer& hits6a = MuonSimHitMatcher::hitsInDetId(cscid6a.rawId());
190  const edm::PSimHitContainer& hits6b = MuonSimHitMatcher::hitsInDetId(cscid6b.rawId());
191  const GlobalPoint& gp6a = simHitsMeanPosition(MuonSimHitMatcher::hitsInDetId(cscid6a.rawId()));
192  const GlobalPoint& gp6b = simHitsMeanPosition(MuonSimHitMatcher::hitsInDetId(cscid6b.rawId()));
193  if (!hits6a.empty() and !hits6b.empty())
194  phi_layer6 = (gp6a.phi() + gp6b.phi()) / 2.0;
195  else if (!hits6a.empty())
196  phi_layer6 = gp6a.phi();
197  else if (!hits6b.empty())
198  phi_layer6 = gp6b.phi();
199 
200  } else {
201  // phi in layer 1
202  const CSCDetId cscid1(cscid.endcap(), cscid.station(), cscid.ring(), cscid.chamber(), 1);
203  const GlobalPoint& gp1 = simHitsMeanPosition(MuonSimHitMatcher::hitsInDetId(cscid1.rawId()));
204  phi_layer1 = gp1.phi();
205 
206  // phi in layer 6
207  const CSCDetId cscid6(cscid.endcap(), cscid.station(), cscid.ring(), cscid.chamber(), 6);
208  const GlobalPoint& gp6 = simHitsMeanPosition(MuonSimHitMatcher::hitsInDetId(cscid6.rawId()));
209  phi_layer6 = gp6.phi();
210  }
211  return deltaPhi(phi_layer6, phi_layer1);
212 }
213 
214 // difference in strip per layer
215 void CSCSimHitMatcher::fitHitsInChamber(unsigned int detid, float& intercept, float& slope) const {
216  const CSCDetId cscid(detid);
217 
218  const auto& sim_hits = hitsInChamber(detid);
219 
220  if (sim_hits.empty())
221  return;
222 
223  vector<float> x;
224  vector<float> y;
225  vector<float> xe;
226  vector<float> ye;
227 
228  const float HALF_STRIP_ERROR = 0.288675;
229 
230  for (const auto& h : sim_hits) {
231  const LocalPoint& lp = h.entryPoint();
232  const auto& d = h.detUnitId();
233  float s = dynamic_cast<const CSCGeometry*>(geometry_)->layer(d)->geometry()->strip(lp);
234  // shift to key half strip layer (layer 3)
235  x.push_back(CSCDetId(d).layer() - 3);
236  y.push_back(s);
237  xe.push_back(float(0));
238  ye.push_back(2 * HALF_STRIP_ERROR);
239  }
240  if (x.size() < 2)
241  return;
242 
243  std::unique_ptr<TGraphErrors> gr(new TGraphErrors(x.size(), &x[0], &y[0], &xe[0], &ye[0]));
244  TF1 fit("fit", "pol1", -3, 4);
245  gr->Fit(&fit, "EMQN");
246 
247  intercept = fit.GetParameter(0);
248  slope = fit.GetParameter(1);
249 }
250 
252  if (sim_hits.empty())
253  return -1.f;
254 
255  float sums = 0.f;
256  size_t n = 0;
257  for (const auto& h : sim_hits) {
258  const LocalPoint& lp = h.entryPoint();
259  float s;
260  const auto& d = h.detUnitId();
261  s = dynamic_cast<const CSCGeometry*>(geometry_)->layer(d)->geometry()->strip(lp);
262  // convert to half-strip:
263  s *= 2.;
264  sums += s;
265  ++n;
266  }
267  if (n == 0)
268  return -1.f;
269  return sums / n;
270 }
271 
273  if (sim_hits.empty())
274  return -1.f;
275 
276  float sums = 0.f;
277  size_t n = 0;
278  for (const auto& h : sim_hits) {
279  const LocalPoint& lp = h.entryPoint();
280  float s;
281  const auto& d = h.detUnitId();
282  // find nearest wire
283  const auto& layerG(dynamic_cast<const CSCGeometry*>(geometry_)->layer(d)->geometry());
284  int nearestWire(layerG->nearestWire(lp));
285  // then find the corresponding wire group
286  s = layerG->wireGroup(nearestWire);
287  sums += s;
288  ++n;
289  }
290  if (n == 0)
291  return -1.f;
292  return sums / n;
293 }
294 
295 std::set<int> CSCSimHitMatcher::hitStripsInDetId(unsigned int detid, int margin_n_strips) const {
296  set<int> result;
297  const auto& simhits = MuonSimHitMatcher::hitsInDetId(detid);
298  CSCDetId id(detid);
299  int max_nstrips = dynamic_cast<const CSCGeometry*>(geometry_)->layer(id)->geometry()->numberOfStrips();
300  for (const auto& h : simhits) {
301  const LocalPoint& lp = h.entryPoint();
302  int central_strip = dynamic_cast<const CSCGeometry*>(geometry_)->layer(id)->geometry()->nearestStrip(lp);
303  int smin = central_strip - margin_n_strips;
304  smin = (smin > 0) ? smin : 1;
305  int smax = central_strip + margin_n_strips;
306  smax = (smax <= max_nstrips) ? smax : max_nstrips;
307  for (int ss = smin; ss <= smax; ++ss)
308  result.insert(ss);
309  }
310  return result;
311 }
312 
313 std::set<int> CSCSimHitMatcher::hitWiregroupsInDetId(unsigned int detid, int margin_n_wg) const {
314  set<int> result;
315  const auto& simhits = MuonSimHitMatcher::hitsInDetId(detid);
316  CSCDetId id(detid);
317  int max_n_wg = dynamic_cast<const CSCGeometry*>(geometry_)->layer(id)->geometry()->numberOfWireGroups();
318  for (const auto& h : simhits) {
319  const LocalPoint& lp = h.entryPoint();
320  const auto& layer_geo = dynamic_cast<const CSCGeometry*>(geometry_)->layer(id)->geometry();
321  int central_wg = layer_geo->wireGroup(layer_geo->nearestWire(lp));
322  int wg_min = central_wg - margin_n_wg;
323  wg_min = (wg_min > 0) ? wg_min : 1;
324  int wg_max = central_wg + margin_n_wg;
325  wg_max = (wg_max <= max_n_wg) ? wg_max : max_n_wg;
326  for (int wg = wg_min; wg <= wg_max; ++wg)
327  result.insert(wg);
328  }
329  return result;
330 }
331 
332 int CSCSimHitMatcher::nCoincidenceChambers(int min_n_layers) const {
333  int result = 0;
334  const auto& chamber_ids = chamberIds(0);
335  for (const auto& id : chamber_ids) {
336  if (nLayersWithHitsInChamber(id) >= min_n_layers)
337  result += 1;
338  }
339  return result;
340 }
341 
342 void CSCSimHitMatcher::chamberIdsToString(const std::set<unsigned int>& set) const {
343  for (const auto& p : set) {
344  CSCDetId detId(p);
345  edm::LogInfo("CSCSimHitMatcher") << " " << detId << "\n";
346  }
347 }
348 
349 std::set<unsigned int> CSCSimHitMatcher::chamberIdsStation(int station) const {
350  set<unsigned int> result;
351  switch (station) {
352  case 1: {
353  const auto& p1(chamberIds(MuonHitHelper::CSC_ME1a));
354  const auto& p2(chamberIds(MuonHitHelper::CSC_ME1b));
355  const auto& p3(chamberIds(MuonHitHelper::CSC_ME12));
356  const auto& p4(chamberIds(MuonHitHelper::CSC_ME13));
357  result.insert(p1.begin(), p1.end());
358  result.insert(p2.begin(), p2.end());
359  result.insert(p3.begin(), p3.end());
360  result.insert(p4.begin(), p4.end());
361  break;
362  }
363  case 2: {
364  const auto& p1(chamberIds(MuonHitHelper::CSC_ME21));
365  const auto& p2(chamberIds(MuonHitHelper::CSC_ME22));
366  result.insert(p1.begin(), p1.end());
367  result.insert(p2.begin(), p2.end());
368  break;
369  }
370  case 3: {
371  const auto& p1(chamberIds(MuonHitHelper::CSC_ME31));
372  const auto& p2(chamberIds(MuonHitHelper::CSC_ME32));
373  result.insert(p1.begin(), p1.end());
374  result.insert(p2.begin(), p2.end());
375  break;
376  }
377  case 4: {
378  const auto& p1(chamberIds(MuonHitHelper::CSC_ME41));
379  const auto& p2(chamberIds(MuonHitHelper::CSC_ME42));
380  result.insert(p1.begin(), p1.end());
381  result.insert(p2.begin(), p2.end());
382  break;
383  }
384  };
385  return result;
386 }
387 
const edm::PSimHitContainer & hitsInChamber(unsigned int) const
static int toCSCType(int st, int ri)
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
const TrackingGeometry * geometry_
edm::PSimHitContainer hits_
void match(const SimTrack &t, const SimVertex &v)
do the matching
std::map< unsigned int, edm::PSimHitContainer > detid_to_hits_
GlobalPoint simHitsMeanPosition(const edm::PSimHitContainer &sim_hits) const
int nCoincidenceChambers(int min_n_layers=4) const
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
static const double slope[3]
float simHitsMeanWG(const edm::PSimHitContainer &sim_hits) const
int nStations(int nl=4) const
ParameterSet const & getParameterSet(std::string const &) const
std::set< unsigned int > chamberIdsStation(int station) const
CSCSimHitMatcher(const edm::ParameterSet &iPS, edm::ConsumesCollector &&iC)
edm::ESGetToken< CSCGeometry, MuonGeometryRecord > geomToken_
bool hitStation(int, int) const
std::vector< unsigned > track_ids_
constexpr std::array< uint8_t, layerIndexSize > layer
void init(const edm::Event &e, const edm::EventSetup &eventSetup)
initialize the event
int iEvent
Definition: GenABIO.cc:224
int nLayersWithHitsInChamber(unsigned int) const
edm::PSimHitContainer simHits_
void chamberIdsToString(const std::set< unsigned int > &set) const
edm::ParameterSet simHitPSet_
std::set< unsigned int > chamberIds(int type=MuonHitHelper::CSC_ALL) const
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
std::map< unsigned int, edm::PSimHitContainer > chamber_to_hits_
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
int chamber() const
Definition: CSCDetId.h:62
float simHitsMeanStrip(const edm::PSimHitContainer &sim_hits) const
bool getData(T &iHolder) const
Definition: EventSetup.h:122
float LocalBendingInChamber(unsigned int detid) const
d
Definition: ztail.py:151
std::set< int > hitWiregroupsInDetId(unsigned int, int margin_n_wg=0) const
Log< level::Info, false > LogInfo
int station() const
Definition: CSCDetId.h:79
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
std::set< int > hitStripsInDetId(unsigned int, int margin_n_strips=0) const
int endcap() const
Definition: CSCDetId.h:85
void match(const SimTrack &t, const SimVertex &v)
do the matching
edm::EDGetTokenT< edm::PSimHitContainer > simHitInput_
std::set< unsigned int > detIds(int type=MuonHitHelper::CSC_ALL) const
const edm::PSimHitContainer & hitsInDetId(unsigned int) const
strips
#turn off noise in all subdetectors simHcalUnsuppressedDigis.doNoise = False mix.digitizers.hcal.doNoise = False simEcalUnsuppressedDigis.doNoise = False mix.digitizers.ecal.doNoise = False simEcalUnsuppressedDigis.doESNoise = False simSiPixelDigis.AddNoise = False mix.digitizers.pixel.AddNoise = False simSiStripDigis.Noise = False mix.digitizers.strip.AddNoise = False
Definition: DigiDM_cff.py:32
std::vector< PSimHit > PSimHitContainer
void init(const edm::Event &e, const edm::EventSetup &eventSetup)
initialize the event
int ring() const
Definition: CSCDetId.h:68
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
const TrackingGeometry * geometry()
def move(src, dest)
Definition: eostools.py:511
void fitHitsInChamber(unsigned int detid, float &mean, float &slope) const