CMS 3D CMS Logo

ME0SegmentAlgorithm.cc
Go to the documentation of this file.
1 
8 #include "ME0SegmentAlgorithm.h"
9 #include "MuonSegFit.h"
10 
16 
17 #include <algorithm>
18 #include <cmath>
19 #include <iostream>
20 #include <string>
21 
22 /* Constructor
23  *
24  */
26 {
27  debug = ps.getUntrackedParameter<bool>("ME0Debug");
28  minHitsPerSegment = ps.getParameter<unsigned int>("minHitsPerSegment");
29  preClustering = ps.getParameter<bool>("preClustering");
30  dXclusBoxMax = ps.getParameter<double>("dXclusBoxMax");
31  dYclusBoxMax = ps.getParameter<double>("dYclusBoxMax");
32  preClustering_useChaining = ps.getParameter<bool>("preClusteringUseChaining");
33  dPhiChainBoxMax = ps.getParameter<double>("dPhiChainBoxMax");
34  dEtaChainBoxMax = ps.getParameter<double>("dEtaChainBoxMax");
35  dTimeChainBoxMax = ps.getParameter<double>("dTimeChainBoxMax");
36  maxRecHitsInCluster = ps.getParameter<int>("maxRecHitsInCluster");
37 
38  edm::LogVerbatim("ME0SegmentAlgorithm") << "[ME0SegmentAlgorithm::ctor] Parameters to build segments :: "
39  << "preClustering = "<<preClustering<<" preClustering_useChaining = "<<preClustering_useChaining
40  <<" dPhiChainBoxMax = "<<dPhiChainBoxMax<<" dEtaChainBoxMax = "<<dEtaChainBoxMax<<" dTimeChainBoxMax = "<<dTimeChainBoxMax
41  <<" minHitsPerSegment = "<<minHitsPerSegment<<" maxRecHitsInCluster = "<<maxRecHitsInCluster;
42 }
43 
44 /* Destructor
45  *
46  */
48 }
49 
50 
52 
53  #ifdef EDM_ML_DEBUG // have lines below only compiled when in debug mode
54  ME0DetId chId((ensemble.first)->id());
55  edm::LogVerbatim("ME0SegAlgoMM") << "[ME0SegmentAlgorithm::run] build segments in chamber " << chId << " which contains "<<rechits.size()<<" rechits";
56  for (auto rh=rechits.begin(); rh!=rechits.end(); ++rh){
57  auto me0id = (*rh)->rh->me0Id();
58  auto rhLP = (*rh)->lp;
59  edm::LogVerbatim("ME0SegmentAlgorithm") << "[RecHit :: Loc x = "<<std::showpos<<std::setw(9)<<rhLP.x()<<" Loc y = "<<std::showpos<<std::setw(9)<<rhLP.y()<<" Time = "<<std::showpos<<(*rh)->rh->tof()<<" -- "<<me0id.rawId()<<" = "<<me0id<<" ]";
60  }
61  #endif
62 
63  // pre-cluster rechits and loop over all sub clusters separately
64  std::vector<ME0Segment> segments_temp;
65  std::vector<ME0Segment> segments;
66  ProtoSegments rechits_clusters; // this is a collection of groups of rechits
67 
68  if(preClustering) {
69  // run a pre-clusterer on the given rechits to split obviously separated segment seeds:
71  // it uses X,Y,Z information; there are no configurable parameters used;
72  // the X, Y, Z "cuts" are just (much) wider than reasonable high pt segments
73  rechits_clusters = this->chainHits(chamber, rechits );
74  }
75  else{
76  // it uses X,Y information + configurable parameters
77  rechits_clusters = this->clusterHits(rechits );
78  }
79  // loop over the found clusters:
80  for(auto sub_rechits = rechits_clusters.begin(); sub_rechits != rechits_clusters.end(); ++sub_rechits ) {
81  // clear the buffer for the subset of segments:
82  segments_temp.clear();
83  // build the subset of segments:
84  this->buildSegments(chamber,(*sub_rechits), segments_temp );
85  // add the found subset of segments to the collection of all segments in this chamber:
86  segments.insert( segments.end(), segments_temp.begin(), segments_temp.end() );
87  }
88  return segments;
89  }
90  else {
91  HitAndPositionPtrContainer ptrRH; ptrRH.reserve(rechits.size());
92  for(const auto& rh : rechits) ptrRH.push_back(&rh);
93  this->buildSegments(chamber,ptrRH, segments);
94  return segments;
95  }
96 }
97 
98 
99 // ********************************************************************;
102 
103  ProtoSegments rechits_clusters; // this is a collection of groups of rechits
104 
105  float dXclus_box = 0.0;
106  float dYclus_box = 0.0;
107 
108  ProtoSegments seeds; seeds.reserve(rechits.size());
109 
110  std::vector<float> running_meanX; running_meanX.reserve(rechits.size());
111  std::vector<float> running_meanY; running_meanY.reserve(rechits.size());
112 
113  std::vector<float> seed_minX; seed_minX.reserve(rechits.size());
114  std::vector<float> seed_maxX; seed_maxX.reserve(rechits.size());
115  std::vector<float> seed_minY; seed_minY.reserve(rechits.size());
116  std::vector<float> seed_maxY; seed_maxY.reserve(rechits.size());
117 
118  // split rechits into subvectors and return vector of vectors:
119  // Loop over rechits
120  // Create one seed per hit
121  for(unsigned int i = 0; i < rechits.size(); ++i) {
122  seeds.push_back(HitAndPositionPtrContainer(1,&rechits[i]));
123 
124  // First added hit in seed defines the mean to which the next hit is compared
125  // for this seed.
126 
127  running_meanX.push_back( rechits[i].lp.x() );
128  running_meanY.push_back( rechits[i].lp.y() );
129 
130  // set min/max X and Y for box containing the hits in the precluster:
131  seed_minX.push_back( rechits[i].lp.x() );
132  seed_maxX.push_back( rechits[i].lp.x() );
133  seed_minY.push_back( rechits[i].lp.y() );
134  seed_maxY.push_back( rechits[i].lp.y() );
135  }
136 
137  // merge clusters that are too close
138  // measure distance between final "running mean"
139  for(size_t NNN = 0; NNN < seeds.size(); ++NNN) {
140  for(size_t MMM = NNN+1; MMM < seeds.size(); ++MMM) {
141  if(running_meanX[MMM] == running_max || running_meanX[NNN] == running_max ) {
142  LogDebug("ME0SegmentAlgorithm") << "[ME0SegmentAlgorithm::clusterHits]: ALARM! Skipping used seeds, this should not happen - inform developers!";
143  continue; //skip seeds that have been used
144  }
145 
146  // calculate cut criteria for simple running mean distance cut:
147  //dXclus = fabs(running_meanX[NNN] - running_meanX[MMM]);
148  //dYclus = fabs(running_meanY[NNN] - running_meanY[MMM]);
149  // calculate minmal distance between precluster boxes containing the hits:
150  if ( running_meanX[NNN] > running_meanX[MMM] ) dXclus_box = seed_minX[NNN] - seed_maxX[MMM];
151  else dXclus_box = seed_minX[MMM] - seed_maxX[NNN];
152  if ( running_meanY[NNN] > running_meanY[MMM] ) dYclus_box = seed_minY[NNN] - seed_maxY[MMM];
153  else dYclus_box = seed_minY[MMM] - seed_maxY[NNN];
154 
155 
156  if( dXclus_box < dXclusBoxMax && dYclus_box < dYclusBoxMax ) {
157  // merge clusters!
158  // merge by adding seed NNN to seed MMM and erasing seed NNN
159 
160  // calculate running mean for the merged seed:
161  if(seeds[NNN].size()+seeds[MMM].size() != 0) {
162  running_meanX[MMM] = (running_meanX[NNN]*seeds[NNN].size() + running_meanX[MMM]*seeds[MMM].size()) / (seeds[NNN].size()+seeds[MMM].size());
163  running_meanY[MMM] = (running_meanY[NNN]*seeds[NNN].size() + running_meanY[MMM]*seeds[MMM].size()) / (seeds[NNN].size()+seeds[MMM].size());
164  }
165 
166  // update min/max X and Y for box containing the hits in the merged cluster:
167  if ( seed_minX[NNN] < seed_minX[MMM] ) seed_minX[MMM] = seed_minX[NNN];
168  if ( seed_maxX[NNN] > seed_maxX[MMM] ) seed_maxX[MMM] = seed_maxX[NNN];
169  if ( seed_minY[NNN] < seed_minY[MMM] ) seed_minY[MMM] = seed_minY[NNN];
170  if ( seed_maxY[NNN] > seed_maxY[MMM] ) seed_maxY[MMM] = seed_maxY[NNN];
171 
172  // add seed NNN to MMM (lower to larger number)
173  seeds[MMM].insert(seeds[MMM].end(),seeds[NNN].begin(),seeds[NNN].end());
174 
175  // mark seed NNN as used (at the moment just set running mean to 999999.)
176  running_meanX[NNN] = running_max;
177  running_meanY[NNN] = running_max;
178  // we have merged a seed (NNN) to the highter seed (MMM) - need to contimue to
179  // next seed (NNN+1)
180  break;
181  }
182  }
183  }
184 
185  // hand over the final seeds to the output
186  // would be more elegant if we could do the above step with
187  // erasing the merged ones, rather than the
188  for(size_t NNN = 0; NNN < seeds.size(); ++NNN) {
189  if(running_meanX[NNN] == running_max) continue; //skip seeds that have been marked as used up in merging
190  rechits_clusters.push_back(seeds[NNN]);
191  }
192 
193  return rechits_clusters;
194 }
195 
196 
199 
200  ProtoSegments rechits_chains;
201  ProtoSegments seeds;
202  seeds.reserve(rechits.size());
203  std::vector<bool> usedCluster(rechits.size(),false);
204 
205  // split rechits into subvectors and return vector of vectors:
206  // Loop over rechits
207  // Create one seed per hit
208  for ( unsigned int i=0; i<rechits.size(); ++i){
209  if(std::abs(rechits[i].rh->tof()) > dTimeChainBoxMax) continue;
210  seeds.push_back(HitAndPositionPtrContainer(1,&rechits[i]));
211  }
212 
213  // merge chains that are too close ("touch" each other)
214  for(size_t NNN = 0; NNN < seeds.size(); ++NNN) {
215  for(size_t MMM = NNN+1; MMM < seeds.size(); ++MMM) {
216  if(usedCluster[MMM] || usedCluster[NNN]){
217  continue;
218  }
219  // all is in the way we define "good";
220  // try not to "cluster" the hits but to "chain" them;
221  // it does the clustering but also does a better job
222  // for inclined tracks (not clustering them together;
223  // crossed tracks would be still clustered together)
224  // 22.12.09: In fact it is not much more different
225  // than the "clustering", we just introduce another
226  // variable in the game - Z. And it makes sense
227  // to re-introduce Y (or actually wire group mumber)
228  // in a similar way as for the strip number - see
229  // the code below.
230  bool goodToMerge = isGoodToMerge(chamber, seeds[NNN], seeds[MMM]);
231  if(goodToMerge){
232  // merge chains!
233  // merge by adding seed NNN to seed MMM and erasing seed NNN
234 
235  // add seed NNN to MMM (lower to larger number)
236  seeds[MMM].insert(seeds[MMM].end(),seeds[NNN].begin(),seeds[NNN].end());
237 
238  // mark seed NNN as used
239  usedCluster[NNN] = true;
240  // we have merged a seed (NNN) to the highter seed (MMM) - need to contimue to
241  // next seed (NNN+1)
242  break;
243  }
244 
245  }
246  }
247 
248  // hand over the final seeds to the output
249  // would be more elegant if we could do the above step with
250  // erasing the merged ones, rather than the
251 
252  for(size_t NNN = 0; NNN < seeds.size(); ++NNN) {
253  if(usedCluster[NNN]) continue; //skip seeds that have been marked as used up in merging
254  rechits_chains.push_back(seeds[NNN]);
255  }
256 
257  //***************************************************************
258 
259  return rechits_chains;
260 }
261 
263  for(size_t iRH_new = 0;iRH_new<newChain.size();++iRH_new){
264  GlobalPoint pos_new = newChain[iRH_new]->gp;
265 
266  for(size_t iRH_old = 0;iRH_old<oldChain.size();++iRH_old){
267  GlobalPoint pos_old = oldChain[iRH_old]->gp;
268  // to be chained, two hits need to be in neighbouring layers...
269  // or better allow few missing layers (upto 3 to avoid inefficiencies);
270  // however we'll not make an angle correction because it
271  // worsen the situation in some of the "regular" cases
272  // (not making the correction means that the conditions for
273  // forming a cluster are different if we have missing layers -
274  // this could affect events at the boundaries )
275 
276  // to be chained, two hits need also to be "close" in phi and eta
277  if (std::abs(reco::deltaPhi( float(pos_new.phi()), float(pos_old.phi()) )) >= dPhiChainBoxMax) continue;
278  if (std::abs(pos_new.eta()-pos_old.eta()) >= dEtaChainBoxMax) continue;
279  // and the difference in layer index should be < (nlayers-1)
280  if (std::abs(int(newChain[iRH_new]->layer) - int(oldChain[iRH_old]->layer)) >= (chamber->id().nlayers()-1)) continue;
281  // and they should have a time difference compatible with the hypothesis
282  // that the rechits originate from the same particle, but were detected in different layers
283  if (std::abs(newChain[iRH_new]->rh->tof() - oldChain[iRH_old]->rh->tof()) >= dTimeChainBoxMax) continue;
284 
285  return true;
286  }
287  }
288  return false;
289 }
290 
291 void ME0SegmentAlgorithm::buildSegments(const ME0Chamber * chamber, const HitAndPositionPtrContainer& rechits, std::vector<ME0Segment>& me0segs) {
292  if (rechits.size() < minHitsPerSegment) return;
293 
294 #ifdef EDM_ML_DEBUG // have lines below only compiled when in debug mode
295  edm::LogVerbatim("ME0SegmentAlgorithm") << "[ME0SegmentAlgorithm::buildSegments] will now try to fit a ME0Segment from collection of "<<rechits.size()<<" ME0 RecHits";
296  for (auto rh=rechits.begin(); rh!=rechits.end(); ++rh){
297  auto me0id = (*rh)->rh->me0Id();
298  auto rhLP = (*rh)->lp;
299  edm::LogVerbatim("ME0SegmentAlgorithm") << "[RecHit :: Loc x = "<<std::showpos<<std::setw(9)<<rhLP.x()<<" Loc y = "<<std::showpos<<std::setw(9)<<rhLP.y()<<" Time = "<<std::showpos<<(*rh)->rh->tof()<<" -- "<<me0id.rawId()<<" = "<<me0id<<" ]";
300  }
301 #endif
302 
304  std::vector<const ME0RecHit*> bareRHs;
305 
306  // select hits from the ensemble and sort it
307  for (auto rh=rechits.begin(); rh!=rechits.end();rh++){
308  bareRHs.push_back((*rh)->rh );
309  // for segFit - using local point in chamber frame
310  ME0RecHit *newRH = (*rh)->rh->clone();
311  newRH->setPosition((*rh)->lp);
312 
313  MuonSegFit::MuonRecHitPtr trkRecHit(newRH);
314  muonRecHits.push_back(trkRecHit);
315  }
316 
317  // The actual fit on all hits of the vector of the selected Tracking RecHits:
318  sfit_ = std::make_unique<MuonSegFit>(muonRecHits);
319  bool goodfit = sfit_->fit();
320  edm::LogVerbatim("ME0SegmentAlgorithm") << "[ME0SegmentAlgorithm::buildSegments] ME0Segment fit done";
321 
322  // quit function if fit was not OK
323  if(!goodfit){
324  for (auto rh:muonRecHits) rh.reset();
325  return;
326  }
327 
328  // obtain all information necessary to make the segment:
329  LocalPoint protoIntercept = sfit_->intercept();
330  LocalVector protoDirection = sfit_->localdir();
331  AlgebraicSymMatrix protoErrors = sfit_->covarianceMatrix();
332  double protoChi2 = sfit_->chi2();
333  // Calculate the central value and uncertainty of the segment time
334  float averageTime=0.;
335  for (auto rh=rechits.begin(); rh!=rechits.end(); ++rh){
336  averageTime += (*rh)->rh->tof();
337  }
338  if(!rechits.empty()) averageTime=averageTime/(rechits.size());
339  float timeUncrt=0.;
340  for (auto rh=rechits.begin(); rh!=rechits.end(); ++rh){
341  timeUncrt += pow((*rh)->rh->tof()-averageTime,2);
342  }
343 
344  if(rechits.size() > 1) timeUncrt=timeUncrt/(rechits.size()-1);
345  timeUncrt = sqrt(timeUncrt);
346 
347  const float dPhi = chamber->computeDeltaPhi(protoIntercept,protoDirection);
348 
349  // save all information inside GEMCSCSegment
350  edm::LogVerbatim("ME0SegmentAlgorithm") << "[ME0SegmentAlgorithm::buildSegments] will now try to make ME0Segment from collection of "<<rechits.size()<<" ME0 RecHits";
351  ME0Segment tmp(bareRHs, protoIntercept, protoDirection, protoErrors, protoChi2, averageTime, timeUncrt, dPhi);
352 
353  edm::LogVerbatim("ME0SegmentAlgorithm") << "[ME0SegmentAlgorithm::buildSegments] ME0Segment made";
354  edm::LogVerbatim("ME0SegmentAlgorithm") << "[ME0SegmentAlgorithm::buildSegments] "<<tmp;
355 
356  for (auto rh:muonRecHits) rh.reset();
357  me0segs.push_back(tmp);
358  return;
359 }
#define LogDebug(id)
size
Write out results.
std::shared_ptr< TrackingRecHit > MuonRecHitPtr
Definition: MuonSegFit.h:41
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
bool isGoodToMerge(const ME0Chamber *chamber, const HitAndPositionPtrContainer &newChain, const HitAndPositionPtrContainer &oldChain)
void setPosition(LocalPoint pos)
Set local position.
Definition: ME0RecHit.h:72
void buildSegments(const ME0Chamber *chamber, const HitAndPositionPtrContainer &rechits, std::vector< ME0Segment > &me0segs)
unsigned int minHitsPerSegment
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
ME0DetId id() const
Return the ME0DetId of this chamber.
Definition: ME0Chamber.cc:14
std::vector< ME0Segment > run(const ME0Chamber *chamber, const HitAndPositionContainer &rechits) override
std::vector< HitAndPosition > HitAndPositionContainer
ProtoSegments chainHits(const ME0Chamber *chamber, const HitAndPositionContainer &rechits)
~ME0SegmentAlgorithm() override
Destructor.
std::vector< const HitAndPosition * > HitAndPositionPtrContainer
ProtoSegments clusterHits(const HitAndPositionContainer &rechits)
Utility functions.
float computeDeltaPhi(const LocalPoint &position, const LocalVector &direction) const
Definition: ME0Chamber.cc:82
std::unique_ptr< MuonSegFit > sfit_
T sqrt(T t)
Definition: SSEVec.h:18
std::vector< MuonRecHitPtr > MuonRecHitContainer
Definition: MuonSegFit.h:42
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
#define end
Definition: vmac.h:37
std::vector< HitAndPositionPtrContainer > ProtoSegments
Typedefs.
double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:22
ME0RecHit * clone() const override
Definition: ME0RecHit.cc:47
T eta() const
Definition: PV3DBase.h:76
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
int nlayers() const
For future modifications (implement more layers)
Definition: ME0DetId.h:82
#define begin
Definition: vmac.h:30
CLHEP::HepSymMatrix AlgebraicSymMatrix
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
ME0SegmentAlgorithm(const edm::ParameterSet &ps)
Constructor.