CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CSCHitFromStripOnly.cc
Go to the documentation of this file.
1 // This is CSCHitFromStripOnly.cc
2 
8 
10 
13 
16 
17 #include <algorithm>
18 #include <string>
19 #include <vector>
20 
21 
22 CSCHitFromStripOnly::CSCHitFromStripOnly( const edm::ParameterSet& ps ) : recoConditions_(0), calcped_(0) {
23 
24  useCalib = ps.getParameter<bool>("CSCUseCalibrations");
25  bool useStaticPedestals = ps.getParameter<bool>("CSCUseStaticPedestals");
26  int noOfTimeBinsForDynamicPed = ps.getParameter<int>("CSCNoOfTimeBinsForDynamicPedestal");
27 
28  theThresholdForAPeak = ps.getParameter<double>("CSCStripPeakThreshold");
29  theThresholdForCluster = ps.getParameter<double>("CSCStripClusterChargeCut");
30 
31  LogTrace("CSCRecHit") << "[CSCHitFromStripOnly] CSCUseStaticPedestals = " << useStaticPedestals;
32  if ( !useStaticPedestals ) LogTrace("CSCRecHit") << "[CSCHitFromStripOnly] CSCNoOfTimeBinsForDynamicPedestal = "
33  << noOfTimeBinsForDynamicPed;
34 
35  if ( useStaticPedestals ) {
37  }
38  else {
39  if ( noOfTimeBinsForDynamicPed == 1 ) {
41  }
42  else {
43  calcped_ = new CSCDynamicPedestal2(); // NORMAL DEFAULT!
44  }
45  }
46 
47 }
48 
49 
51  delete calcped_;
52 }
53 
54 
55 /* runStrip
56  *
57  * Search for strip with ADC output exceeding theThresholdForAPeak. For each of these strips,
58  * build a cluster of strip of size theClusterSize (typically 3 strips). Finally, make
59  * a Strip Hit out of these clusters by finding the center-of-mass position of the hit
60  */
61 std::vector<CSCStripHit> CSCHitFromStripOnly::runStrip( const CSCDetId& id, const CSCLayer* layer,
62  const CSCStripDigiCollection::Range& rstripd )
63 {
64 
65  std::vector<CSCStripHit> hitsInLayer;
66 
67  // cache layer info for ease of access
68  id_ = id;
69  layer_ = layer;
70  nstrips_ = layer->chamber()->specs()->nStrips();
71 
72  tmax_cluster = 5;
73 
74  // Get gain correction weights for all strips in layer, and cache in gainWeight.
75  // They're used in fillPulseHeights below.
76  if ( useCalib ) {
78  }
79 
80  // Store pulseheights from SCA and find maxima (potential hits)
81  fillPulseHeights( rstripd );
82  findMaxima(id);
83 
84  // Make a Strip Hit out of each strip local maximum
85  for ( size_t imax = 0; imax != theMaxima.size(); ++imax ) {
86 
87  // Initialize parameters entering the CSCStripHit
89  theStrips.clear();
90  strips_adc.clear();
91  strips_adcRaw.clear();
92 
93  // makeCluster calls findHitOnStripPosition to determine the centroid position
94 
95  // Remember, the array starts at 0, but the stripId starts at 1...
96  float strippos = makeCluster( theMaxima[imax]+1 );
97 
98  //if ( strippos < 0 || tmax_cluster < 3 ){
99  // the strippos (as calculated here) is not used later on in
101  // with the negative charges allowed it can become negative
102  if ( tmax_cluster < 3 ){
103  theClosestMaximum.push_back(99); // to keep proper vector size
104  continue;
105  }
106  //---- If two maxima are too close the error assigned will be width/sqrt(12) - see CSCXonStrip_MatchGatti.cc
107  int maximum_to_left = 99; //---- If there is one maximum - the distance is set to 99 (strips)
108  int maximum_to_right = 99;
109  if(imax<theMaxima.size()-1){
110  maximum_to_right = theMaxima.at(imax+1) - theMaxima.at(imax);
111  }
112  if(imax>0 ){
113  maximum_to_left = theMaxima.at(imax-1) - theMaxima.at(imax);
114  }
115  if(fabs(maximum_to_right) < fabs(maximum_to_left)){
116  theClosestMaximum.push_back(maximum_to_right);
117  }
118  else{
119  theClosestMaximum.push_back(maximum_to_left);
120  }
121 
122  //---- Check if a neighbouring strip is a dead strip
123  //bool deadStrip = isNearDeadStrip(id, theMaxima.at(imax));
124  bool deadStripL = isDeadStrip(id, theMaxima.at(imax)-1);
125  bool deadStripR = isDeadStrip(id, theMaxima.at(imax)+1);
126  short int aDeadStrip = 0;
127  if(!deadStripL && !deadStripR){
128  aDeadStrip = 0;
129  }
130  else if(deadStripL && deadStripR){
131  aDeadStrip = 255;
132  }
133  else{
134  if(deadStripL){
135  aDeadStrip = theMaxima.at(imax)-1;
136  }
137  else{
138  aDeadStrip = theMaxima.at(imax)+1;
139  }
140  }
141  //std::cout << " Size of theStrips from SCSHitFromStripOnly: " << theStrips.size() << std::endl;
142 
145  std::vector<int> theL1AStrips;
146  for(int ila=0; ila<(int)theStrips.size(); ila++){
147  bool stripMatchCounter=false;
148  for ( CSCStripDigiCollection::const_iterator itl1 = rstripd.first; itl1 != rstripd.second; ++itl1 ) {
149  int stripNproto = (*itl1).getStrip();
150  if(id_.ring() != 4){
151  if(theStrips[ila]==stripNproto){
152  stripMatchCounter=true;
153  std::vector<int> L1AP=(*itl1).getL1APhase();
154  int L1AbitOnPlace=0;
155  for(int iBit=0; iBit<(int)L1AP.size(); iBit++){
156  L1AbitOnPlace=L1AbitOnPlace|(L1AP[iBit] << (15-iBit));
157  }
158  theL1AStrips.push_back(theStrips[ila] | L1AbitOnPlace);
159  }
160  }
161  else{
162  for(int tripl=0; tripl<3; ++tripl){
163  if(theStrips[ila]==(stripNproto+tripl*16)){
164  stripMatchCounter=true;
165  std::vector<int> L1AP=(*itl1).getL1APhase();
166  int L1AbitOnPlace=0;
167  for(int iBit=0; iBit<(int)L1AP.size(); iBit++){
168  L1AbitOnPlace=L1AbitOnPlace|(L1AP[iBit] << (15-iBit));
169  }
170  theL1AStrips.push_back(theStrips[ila] | L1AbitOnPlace);
171  }
172  }
173  }
174  }
175  if(!stripMatchCounter){
176  theL1AStrips.push_back(theStrips[ila]);
177  }
178  }
180 
181  CSCStripHit striphit( id, strippos, tmax_cluster, theL1AStrips, strips_adc, strips_adcRaw,
182  theConsecutiveStrips.at(imax), theClosestMaximum.at(imax), aDeadStrip);
183  hitsInLayer.push_back( striphit );
184  }
185 
187  /*
188  for(std::vector<CSCStripHit>::const_iterator itSHit=hitsInLayer.begin(); itSHit!=hitsInLayer.end(); ++itSHit){
189  (*itSHit).print();
190  }
191  */
192  return hitsInLayer;
193 }
194 
195 
196 /* makeCluster
197  *
198  */
199 float CSCHitFromStripOnly::makeCluster( int centerStrip ) {
200 
201  float strippos = -1.;
203  std::vector<CSCStripHitData> stripDataV;
204 
205  // We only want to use strip position in terms of strip # for the strip hit. //@@ What other choice is there?
206 
207  // If the cluster size is such that you go beyond the edge of detector, shrink cluster appropriately
208  for ( int i = 1; i < theClusterSize/2 + 1; ++i ) {
209 
210  if ( centerStrip - i < 1 || centerStrip + i > int(nstrips_) ) {
211 
212  // Shrink cluster size, but keep it an odd number of strips.
213  clusterSize = 2*i - 1;
214  }
215  }
216  for ( int i = -clusterSize/2; i <= clusterSize/2; ++i ) {
217  CSCStripHitData data = makeStripData(centerStrip, i);
218  stripDataV.push_back( data );
219  theStrips.push_back( centerStrip + i );
220  }
221  strippos = findHitOnStripPosition( stripDataV, centerStrip );
222 
223  return strippos;
224 }
225 
226 
231 
232  CSCStripHitData prelimData;
233  int thisStrip = centerStrip+offset;
234 
235  int tmax = thePulseHeightMap[centerStrip-1].tmax();
236  tmax_cluster = tmax;
237 
238  std::vector<float> adc(4);
239  std::vector<float> adcRaw(4);
240 
241  // Fill adc & adcRaw
242 
243  int istart = tmax-1;
244  int istop = std::min( tmax+2, 7 ) ; // there are only time bins 0-7
245  adc[3] = 0.1; // in case it isn't filled
246 
247  if ( tmax > 2 && tmax < 7 ) { // for time bins 3-6
248  int ibin = thisStrip-1;
249 
250  std::copy( thePulseHeightMap[ibin].ph().begin()+istart,
251  thePulseHeightMap[ibin].ph().begin()+istop+1, adc.begin() );
252 
253  std::copy( thePulseHeightMap[ibin].phRaw().begin()+istart,
254  thePulseHeightMap[ibin].phRaw().begin()+istop+1, adcRaw.begin() );
255  }
256  else {
257  adc[0] = 0.1;
258  adc[1] = 0.1;
259  adc[2] = 0.1;
260  adc[3] = 0.1;
261  adcRaw = adc;
262  LogTrace("CSCRecHit") << "[CSCHitFromStripOnly::makeStripData] Tmax out of range: contact CSC expert!";
263  }
264 
265  if ( offset == 0 ) {
266  prelimData = CSCStripHitData(thisStrip, tmax_cluster, adcRaw, adc);
267  } else {
268  int sign = offset>0 ? 1 : -1;
269  // If there's another maximum that would like to use part of this cluster,
270  // it gets shared in proportion to the height of the maxima
271  for ( int i = 1; i <= clusterSize/2; ++i ) {
272 
273  // Find the direction of the offset
274  int testStrip = thisStrip + sign*i;
275  std::vector<int>::iterator otherMax = find(theMaxima.begin(), theMaxima.end(), testStrip-1);
276 
277  // No other maxima found, so just store
278  if ( otherMax == theMaxima.end() ) {
279  prelimData = CSCStripHitData(thisStrip, tmax_cluster, adcRaw, adc); }
280  else {
281 
282  // Another maximum found - share
283  std::vector<float> adc1(4);
284  std::vector<float> adcRaw1(4);
285  std::vector<float> adc2(4);
286  std::vector<float> adcRaw2(4);
287  // In case we only copy (below) into 3 of the 4 bins i.e. when istart=5, istop=7
288  adc1[3] = 0.1;
289  adc2[3] = 0.1;
290  adcRaw1[3] = 0.1;
291  adcRaw2[3] = 0.1;
292 
293  // Fill adcN with content of time bins tmax-1 to tmax+2 (if it exists!)
294  if ( tmax > 2 && tmax < 7 ) { // for time bin tmax from 3-6
295  int ibin = testStrip-1;
296  int jbin = centerStrip-1;
297  std::copy(thePulseHeightMap[ibin].ph().begin()+istart,
298  thePulseHeightMap[ibin].ph().begin()+istop+1, adc1.begin());
299 
300  std::copy(thePulseHeightMap[ibin].phRaw().begin()+istart,
301  thePulseHeightMap[ibin].phRaw().begin()+istop+1, adcRaw1.begin());
302 
303  std::copy(thePulseHeightMap[jbin].ph().begin()+istart,
304  thePulseHeightMap[jbin].ph().begin()+istop+1, adc2.begin());
305 
306  std::copy(thePulseHeightMap[jbin].phRaw().begin()+istart,
307  thePulseHeightMap[jbin].phRaw().begin()+istop+1, adcRaw2.begin());
308  }
309  else {
310  adc1.assign(4, 0.1);
311  adcRaw1 = adc1;
312  adc2.assign(4, 0.1);
313  adcRaw2 = adc2;
314  }
315 
316  // Scale shared strip B ('adc') by ratio of peak of ADC counts from central strip A ('adc2')
317  // to sum of A and neighbouring maxima C ('adc1')
318 
319  for (size_t k = 0; k < 4; ++k){
320  if(adc1[k]>0 && adc2[k]>0) adc[k] = adc[k] * adc2[k] / ( adc1[k]+adc2[k] );
321  if(adcRaw1[k]>0 && adcRaw2[k]>0) adcRaw[k] = adcRaw[k] * adcRaw2[k] / ( adcRaw1[k]+adcRaw2[k] );
322  }
323  prelimData = CSCStripHitData(thisStrip, tmax_cluster, adcRaw, adc);
324  }
325  }
326  }
327  return prelimData;
328 }
329 
330 
331 /* fillPulseHeights
332  *
333  */
335 
336  // Loop over strip digis in one CSCLayer and fill PulseHeightMap with pedestal-subtracted
337  // SCA pulse heights.
338 
339  thePulseHeightMap.clear();
340  thePulseHeightMap.resize(100); //@@ WHY NOT JUST 80?
341 
342  // for storing sca pulseheights once they may no longer be integer (e.g. after ped subtraction)
343  std::vector<float> sca;
344  sca.reserve(8);
345  for ( CSCStripDigiCollection::const_iterator it = rstripd.first; it != rstripd.second; ++it ) {
346  int thisChannel = (*it).getStrip();
347  std::vector<int> scaRaw = (*it).getADCCounts();
348  sca.clear();
349  // Fill sca from scaRaw, implicitly converting to float
350  std::copy( scaRaw.begin(), scaRaw.end(), std::back_inserter( sca ));
351 
352  //@@ Find bin with largest pulseheight (_before_ ped subtraction - shouldn't matter, right?)
353  int tmax = std::max_element( sca.begin(), sca.end() ) - sca.begin(); // counts from 0
354 
355  // get pedestal - calculated as appropriate - for this sca pulse
356  float ped = calcped_->pedestal(sca, recoConditions_, id_, thisChannel );
357 
358  // subtract the pedestal (from BOTH sets of sca pulseheights)
359  std::for_each( sca.begin(), sca.end(), CSCSubtractPedestal( ped ) );
360  std::for_each( scaRaw.begin(), scaRaw.end(), CSCSubtractPedestal( ped ) );
361 
362  //@@ Max in first 3 or last time bins is unacceptable, if so set to zero (why?)
363  float phmax = 0.;
364  if ( tmax > 2 && tmax < 7 ) {
365  phmax = sca[tmax];
366  }
367 
368  // Fill the map, possibly apply gains from cond data, and unfold ME1A channels
369  // (To apply gains use CSCStripData::op*= which scales only the non-raw sca ph's;
370  // but note that both sca & scaRaw are pedestal-subtracted.)
371 
372  if ( id_.ring() != 4 ) { // non-ME1a
373  thePulseHeightMap[thisChannel-1] = CSCStripData( thisChannel, phmax, tmax, scaRaw, sca );
374  if ( useCalib ) thePulseHeightMap[thisChannel-1] *= gainWeight[thisChannel-1];
375  }
376  else { // ME1a, so unfold its 16 channels to its 48 strips
377  for ( int j = 0; j < 3; ++j ) {
378  thePulseHeightMap[thisChannel-1+16*j] = CSCStripData( thisChannel+16*j, phmax, tmax, scaRaw, sca );
379  if ( useCalib ) thePulseHeightMap[thisChannel-1+16*j] *= gainWeight[thisChannel-1];
380  }
381  }
382 
383  }
384 }
385 
386 
387 /* findMaxima
388  *
389  * fills vector 'theMaxima' with the local maxima in the pulseheight distribution
390  * of the strips. The threshold defining a maximum is a configurable parameter.
391  * A typical value is 30.
392  */
394 
395  theMaxima.clear();
396  theConsecutiveStrips.clear();
397  theClosestMaximum.clear();
398  for ( size_t i=0; i!=thePulseHeightMap.size(); ++i ) {
399 
400  // sum 3 strips so that hits between strips are not suppressed
401  float heightCluster = 0.;
402 
403  bool maximumFound = false;
404  // Left edge of chamber
405  if(!isDeadStrip(id, i+1)){ // is it i or i+1
406  if ( i == 0 ) {
407  heightCluster = thePulseHeightMap[i].phmax()+thePulseHeightMap[i+1].phmax();
408  // Have found a strip Hit if...
409  if(thePulseHeightMap[i].phmax() >= thePulseHeightMap[i+1].phmax() &&
410  isPeakOK(i,heightCluster)){
411  theMaxima.push_back(i);
412  maximumFound = true;
413  }
414  // Right edge of chamber
415  } else if ( i == thePulseHeightMap.size()-1) {
416  heightCluster = thePulseHeightMap[i-1].phmax()+thePulseHeightMap[i].phmax();
417  // Have found a strip Hit if...
418  if(thePulseHeightMap[i].phmax() > thePulseHeightMap[i-1].phmax() &&
419  isPeakOK(i,heightCluster)){
420  theMaxima.push_back(i);
421  maximumFound = true;
422  }
423  // Any other strips
424  } else {
425  heightCluster = thePulseHeightMap[i-1].phmax()+thePulseHeightMap[i].phmax()+thePulseHeightMap[i+1].phmax();
426  // Have found a strip Hit if...
427  if(thePulseHeightMap[i].phmax() > thePulseHeightMap[i-1].phmax() &&
428  thePulseHeightMap[i].phmax() >= thePulseHeightMap[i+1].phmax() &&
429  isPeakOK(i,heightCluster)){
430  theMaxima.push_back(i);
431  maximumFound = true;
432  }
433  }
434  }
435  //---- Consecutive strips with charge (real cluster); if too wide - measurement is not accurate
436  if(maximumFound){
437  int numberOfConsecutiveStrips = 1;
438  float testThreshold = 10.;//---- ADC counts;
439  //---- this is not XTalk corrected so it is correct in first approximation only
440  int j = 0;
441  for(int l = 0; l<8; ++l){
442  if(j<0) edm::LogWarning("FailedStripCountingWrongConsecutiveStripNumber") << "This should never occur!!! Contact CSC expert!";
443  ++j;
444  bool signalPresent = false;
445  for(int k = 0; k<2; ++k){
446  j*= -1;//---- check from left and right
447  int anotherConsecutiveStrip = i+j;
448  if(anotherConsecutiveStrip>=0 && anotherConsecutiveStrip<int( thePulseHeightMap.size() )){
449  if(thePulseHeightMap[anotherConsecutiveStrip].phmax()>testThreshold){
450  ++numberOfConsecutiveStrips;
451  signalPresent = true;
452  }
453  }
454  }
455  if(!signalPresent){
456  break;
457  }
458  }
459  theConsecutiveStrips.push_back(numberOfConsecutiveStrips);
460  }
461  }
462 }
463 //
464 
465 bool CSCHitFromStripOnly::isPeakOK(int iStrip, float heightCluster){
466  int i = iStrip;
467  bool peakOK = ( thePulseHeightMap[i].phmax()>theThresholdForAPeak &&
468  heightCluster > theThresholdForCluster &&
469  // ... and proper peak time; note that the values below are used elsewhere in this file;
470  // they should become parameters or at least constants defined in appropriate place
471  thePulseHeightMap[i].tmax() > 2 && thePulseHeightMap[i].tmax() < 7);
472  return peakOK;
473 }
474 
475 
476 /* findHitOnStripPosition
477  *
478  */
479 float CSCHitFromStripOnly::findHitOnStripPosition( const std::vector<CSCStripHitData>& data, const int& centerStrip ) {
480 
481  float strippos = -1.;
482 
483  if ( data.size() < 1 ) return strippos;
484 
485  // biggestStrip is strip with largest pulse height
486  // Use pointer subtraction
487 
488  int biggestStrip = max_element(data.begin(), data.end()) - data.begin();
489  strippos = data[biggestStrip].strip() * 1.;
490 
491  // If more than one strip: use centroid to find center of cluster
492  // but only use time bin == tmax (otherwise, bias centroid).
493  float sum = 0.;
494  float sum_w= 0.;
495 
496  std::vector<float> w(4);
497  std::vector<float> wRaw(4);
498 
499  for ( size_t i = 0; i != data.size(); ++i ) {
500  w = data[i].ph();
501  wRaw = data[i].phRaw();
502 
503  // (Require ADC to be > 0.)
504  // No later studies suggest that this only do harm
505  /*
506  for ( size_t j = 0; j != w.size(); ++j ) {
507  if ( w[j] < 0. ) w[j] = 0.001;
508  }
509  */
510 
511 
512  // Fill the data members
513  std::copy( w.begin(), w.end(), std::back_inserter(strips_adc));
514  std::copy( wRaw.begin(), wRaw.end(), std::back_inserter(strips_adcRaw));
515 
516  if ( data[i].strip() < 1 ){
517  LogTrace("CSCRecHit") << "problem in indexing of strip, strip id is: " << data[i].strip();
518  }
519  sum_w += w[1];
520  sum += w[1] * data[i].strip();
521  }
522 
523  if ( sum_w > 0.) strippos = sum / sum_w;
524 
525  return strippos;
526 }
527 
528 bool CSCHitFromStripOnly::isNearDeadStrip(const CSCDetId& id, int centralStrip){
529 
530  //@@ Tim says: not sure I understand this properly... but just moved code to CSCRecoConditions
531  // where it can handle the conversion from strip to channel etc.
532  return recoConditions_->nearBadStrip( id, centralStrip );
533 
534 }
535 
536 bool CSCHitFromStripOnly::isDeadStrip(const CSCDetId& id, int centralStrip){
537  return recoConditions_->badStrip( id, centralStrip );
538 
539 }
540 
541 // Define space for static
int adc(sample_type sample)
get the ADC sample (12 bits)
int nStrips() const
const CSCLayer * layer_
CSCPedestalChoice * calcped_
T getParameter(std::string const &) const
void findMaxima(const CSCDetId &id)
Find local maxima.
int i
Definition: DBlmapReader.cc:9
void strip(std::string &input, const std::string &blanks=" \n\t")
Definition: stringTools.cc:16
std::vector< int > theConsecutiveStrips
std::vector< CSCStripHit > runStrip(const CSCDetId &id, const CSCLayer *layer, const CSCStripDigiCollection::Range &rstripd)
std::vector< int > theStrips
bool isDeadStrip(const CSCDetId &id, int centralStrip)
Is the strip &#39;bad&#39;?
#define min(a, b)
Definition: mlp_lapack.h:161
bool nearBadStrip(const CSCDetId &id, int geomStrip) const
Is a neighbour bad?
std::vector< int > theClosestMaximum
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
float findHitOnStripPosition(const std::vector< CSCStripHitData > &data, const int &centerStrip)
Find position of hit in strip cluster in terms of strip #.
CSCHitFromStripOnly(const edm::ParameterSet &ps)
static const int theClusterSize
PulseHeightMap thePulseHeightMap
const CSCChamberSpecs * specs() const
Definition: CSCChamber.h:42
const CSCRecoConditions * recoConditions_
void stripWeights(const CSCDetId &id, float *weights) const
int j
Definition: DBlmapReader.cc:9
virtual float pedestal(const std::vector< float > &sca, const CSCRecoConditions *cond=0, const CSCDetId id=0, int ichan=0)=0
bool badStrip(const CSCDetId &id, int geomStrip) const
Is the strip bad?
unsigned int offset(bool)
float makeCluster(int centerStrip)
Make clusters using local maxima.
#define LogTrace(id)
bool isNearDeadStrip(const CSCDetId &id, int centralStrip)
Is either neighbour &#39;bad&#39;?
int k[5][pyjets_maxn]
int ring() const
Definition: CSCDetId.h:77
static const double tmax[3]
std::vector< DigiType >::const_iterator const_iterator
std::vector< float > strips_adcRaw
std::vector< int > theMaxima
bool isPeakOK(int iStrip, float heightCluster)
#define begin
Definition: vmac.h:31
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
std::vector< float > strips_adc
std::pair< const_iterator, const_iterator > Range
void fillPulseHeights(const CSCStripDigiCollection::Range &rstripd)
Store SCA pulseheight information from strips in digis of one layer.
CSCStripHitData makeStripData(int centerStrip, int offset)
const CSCChamber * chamber() const
Definition: CSCLayer.h:52
T w() const