test
CMS 3D CMS Logo

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