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