StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Pileup.cxx
1 /**********************************************************************
2  *
3  * $Id: Pileup.cxx,v 1.1 2008/12/02 23:47:43 prindle Exp $
4  *
5  * Author: Duncan Prindle
6  *
7  **********************************************************************
8  *
9  * Description: Using first/last points on tracks characterize event vertex structure.
10  *
11  **********************************************************************/
12 
13 #include "TAxis.h"
14 #include "Pileup.h"
15 
16 ClassImp(Pileup)
17 
18 //-------------------------------------------------------
19 Pileup::Pileup() {
20 
21  mHPileup[0] = new TH1D("zFirst +","zFirst +",200,1,200);
22  mHPileup[1] = new TH1D("zFirst -","zFirst -",200,-200,-1);
23  mHPileup[2] = new TH1D("zLast +","zLast +",200,1,200);
24  mHPileup[3] = new TH1D("zLast -","zLast -",200,-200,-1);
25  mHPileup[4] = new TH1D("V_z +","V_z +",500,-250,250);
26  mHPileup[5] = new TH1D("V_z -","V_z -",500,-250,250);
27 
28  mHQA2D[0] = new TH2D("zFirst vs. zLast","zFirst vs. zLast",100,-200,200, 100,-200,200);
29  mHQA2D[1] = new TH2D("zFirst vs. zLast scaled","zFirst vs. zLast scaled",100,-200,200, 100,-250,250);
30  mHQA2D[2] = new TH2D("V_z vs. zLast","V_z vs. zLast",100,-200,200, 100,-250,250);
31 
32  mHQA2D[0]->SetMarkerStyle(20);
33  mHQA2D[0]->SetMarkerSize(0.5);
34  TAxis *x = mHQA2D[0]->GetXaxis();
35  TAxis *y = mHQA2D[0]->GetYaxis();
36  x->SetTitle("Z_{first}");
37  y->SetTitle("Z_{last}");
38  mHQA2D[1]->SetMarkerStyle(20);
39  mHQA2D[1]->SetMarkerSize(0.5);
40  x = mHQA2D[1]->GetXaxis();
41  y = mHQA2D[1]->GetYaxis();
42  x->SetTitle("Z_{first} at 65cm");
43  y->SetTitle("Z_{last} at 190cm");
44  mHQA2D[2]->SetMarkerStyle(20);
45  mHQA2D[2]->SetMarkerSize(0.5);
46  x = mHQA2D[2]->GetXaxis();
47  y = mHQA2D[2]->GetYaxis();
48  x->SetTitle("V_z");
49  y->SetTitle("Z_{last} at 190cm");
50 
51  mHQA1D[0] = new TH1D("QA zLast -","zLast -",400,-200,200);
52  mHQA1D[1] = new TH1D("QA V_z +","V_z +",500,-250,250);
53  mHQA1D[2] = new TH1D("QA V_z -","V_z -",500,-250,250);
54 
55  mDead[0] = 5;
56  mDead[1] = 5;
57  mDead[2] = 5;
58  mDead[3] = 5;
59  mDead[4] = 0;
60  mDead[5] = 0;
61  mDead[6] = 5;
62  mZEndplate = 212.75;
63  // Reasonably tight cuts on what we call matched pileup, vertex.
64  mZStartStopMatchMin = -10;
65  mZStartStopMatchMax = +10;
66  mZPeakMatchMin = -5;
67  mZPeakMatchMax = +3;
68  // Expand the pileup-good vertex range a bit (by 5cm on each side)
69  // Idea is that if a pileup is within 10cm of fitted vertex it may contribute
70  // tracks to the fitted or affect it in some other way.
71  //mZPileMatchMin = -12;
72  //mZPileMatchMax = +2;
73  mZPileMatchMin = -17;
74  mZPileMatchMax = +7;
75  mVerbose = 0;
76 }
77 
78 //-------------------------------------------------------
79 Pileup::~Pileup(){
80 cout << "Deleting a pileup object. " << endl;
81  for (int ih=0;ih<6;ih++) {
82  delete mHPileup[ih];
83  }
84  for (int ih=0;ih<3;ih++) {
85  delete mHQA1D[ih];
86  delete mHQA2D[ih];
87  }
88 };
89 
90 //-------------------------------------------------------
91 int Pileup::verbose() {
92  return mVerbose;
93 }
94 void Pileup::verbose(int val) {
95  // If non zero we print some possibly relevant information.
96  mVerbose = val;
97 }
98 
99 //-------------------------------------------------------
100 double Pileup::zEndplate() {
101  return mZEndplate;
102 }
103 void Pileup::zEndplate(double val) {
104  // Don't know where endplate is yet.
105  mZEndplate = val;
106 }
107 
108 //-------------------------------------------------------
109 double Pileup::zStartStopMatchMin() {
110  return mZStartStopMatchMin;
111 }
112 void Pileup::zStartStopMatchMin(double val) {
113  mZStartStopMatchMin = val;
114 }
115 
116 //-------------------------------------------------------
117 double Pileup::zPileMatchMin() {
118  return mZPileMatchMin;
119 }
120 void Pileup::zPileMatchMin(double val) {
121  mZPileMatchMin = val;
122 }
123 
124 //-------------------------------------------------------
125 double Pileup::zPeakMatchMin() {
126  return mZPeakMatchMin;
127 }
128 void Pileup::zPeakMatchMin(double val) {
129  mZPeakMatchMin = val;
130 }
131 
132 //-------------------------------------------------------
133 double Pileup::zStartStopMatchMax() {
134  return mZStartStopMatchMax;
135 }
136 void Pileup::zStartStopMatchMax(double val) {
137  mZStartStopMatchMax = val;
138 }
139 
140 //-------------------------------------------------------
141 double Pileup::zPileMatchMax() {
142  return mZPileMatchMax;
143 }
144 void Pileup::zPileMatchMax(double val) {
145  mZPileMatchMax = val;
146 }
147 
148 //-------------------------------------------------------
149 double Pileup::zPeakMatchMax() {
150  return mZPeakMatchMax;
151 }
152 void Pileup::zPeakMatchMax(double val) {
153  mZPeakMatchMax = val;
154 }
155 
156 //-------------------------------------------------------
157 double Pileup::dead(int ih) {
158  if (0 <= ih && ih < 7) {
159  return mDead[ih];
160  } else {
161  return -1;
162  }
163 }
164 void Pileup::dead(int ih, double dead) {
165  // Points are sometimes projected beyond central membrane.
166  // Want to ignore these as peaks. (Typically in ih = 0 to 3).
167  // We usually want to find all peaks in ih = 4 and 5 but in deciding
168  // whether or not point goes in 4 or 5 we use mDead[6] as a keep out.
169  if (0 <= ih && ih < 7) {
170  mDead[ih] = dead;
171  }
172 }
173 
174 
175 
176 //-------------------------------------------------------
177  double Pileup::z(int iv, int which) {
178  if (iv < 0 || mNVerts < iv) {
179  return -9999;
180  }
181  if (1 == mFlag[iv] || 2 == mFlag[iv] || 3 == mFlag[iv]) {
182  if (1 == which) {
183  return 0.5*(mVerts[iv][0] + mVerts[iv][2]);
184  } else if (2 == which) {
185  return mVerts[iv][0];
186  } else if (3 == which) {
187  return mVerts[iv][2];
188  } else if (4 == which) {
189  return mVerts[iv][4];
190  } else {
191  return -9999;
192  }
193  } else if (4 == mFlag[iv] || 5 == mFlag[iv]) {
194  if (1 == which) {
195  return mVerts[iv][0];
196  } else if (2 == which) {
197  return mVerts[iv][2];
198  } else if (3 == which) {
199  return mVerts[iv][4];
200  } else if (4 == which) {
201  return mVerts[iv][5];
202  } else {
203  return -9999;
204  }
205  } else if (6 == mFlag[iv]) {
206  if (1 == which) {
207  return 0.5*(mVerts[iv][0] + mVerts[iv][2]);
208  } else if (2 == which) {
209  return mVerts[iv][0];
210  } else if (3 == which) {
211  return mVerts[iv][2];
212  } else {
213  return -9999;
214  }
215  } else if (7 == mFlag[iv]) {
216  if (1 == which) {
217  return mVerts[iv][0];
218  } else {
219  return -9999;
220  }
221  }
222  return -9999;
223 }
224 //-------------------------------------------------------
225 int Pileup::n(int iv, int which) {
226  if (iv < 0 || mNVerts < iv) {
227  return -9999;
228  }
229  double num = -9999;
230  if (1 == mFlag[iv] || 2 == mFlag[iv] || 3 == mFlag[iv]) {
231  if (1 == which) {
232  num = mVerts[iv][1] + mVerts[iv][3];
233  } else if (2 == which) {
234  num = mVerts[iv][1];
235  } else if (3 == which) {
236  num = mVerts[iv][3];
237  } else {
238  num = -9999;
239  }
240  } else if (4 == mFlag[iv] || 5 == mFlag[iv]) {
241  if (1 == which) {
242  num = mVerts[iv][1];
243  } else if (2 == which) {
244  num = mVerts[iv][3];
245  } else {
246  num = -9999;
247  }
248  } else if (6 == mFlag[iv]) {
249  if (1 == which) {
250  num = mVerts[iv][1] + mVerts[iv][3];
251  } else if (2 == which) {
252  num = mVerts[iv][1];
253  } else if (3 == which) {
254  num = mVerts[iv][3];
255  } else {
256  num = -9999;
257  }
258  } else if (7 == mFlag[iv]) {
259  if (1 == which) {
260  num = mVerts[iv][1];
261  } else {
262  num = -9999;
263  }
264  }
265  return int(num);
266 }
267 
268 //-------------------------------------------------------
269  int Pileup::flag(int iv) {
270  if (iv < 0 || mNVerts < iv) {
271  return 0;
272  }
273  return mFlag[iv];
274 }
275 
276 //-------------------------------------------------------
277 int Pileup::nearest(StMuDst *muDst, double z, double *dist, int *mult) {
278 
279  fillHistos(muDst);
280  findPiles();
281 
282  // Given the pileup candidate distances we go through all pairs in V_z+ and V_z-
283  // looking for separation distance consistent with pileup distance.
284  // Keep track of which vertex is closest to z.
285  int nPileFound = 0;
286  double minDist = 9999.0;
287  int minNum = 0;
288  for (int ip=0;ip<mNPiles;ip++) {
289  for (int ip4=0;ip4<mNPeaks[4];ip4++) {
290  for (int ip5=0;ip5<mNPeaks[5];ip5++) {
291  double dist = -9999;
292  if (2 == mPileFlag[ip]) {
293  dist = mPos[4][ip4]-mPos[5][ip5] - mPileDist[ip];
294  } else if (3 == mPileFlag[ip]) {
295  dist = mPos[5][ip5]-mPos[4][ip4] - mPileDist[ip];
296  }
297  if ( mZPileMatchMin < dist && dist < mZPileMatchMax ) {
298  nPileFound += 2;
299  if (fabs(mPos[4][ip4]-z) < fabs(minDist)) {
300  minDist = mPos[4][ip4] - z;
301  minNum = int(mArea[4][ip4]);
302  }
303  if (fabs(mPos[5][ip5]-z) < fabs(minDist)) {
304  minDist = mPos[5][ip5] - z;
305  minNum = int(mArea[5][ip5]);
306  }
307  }
308  }
309  }
310  }
311  *dist = minDist;
312  *mult = minNum;
313  return nPileFound;
314 }
315 
316 //-------------------------------------------------------
317 int Pileup::find(StMuDst *muDst) {
318  // This invokes findPeaks to make lists of peaks in each of the pileup histograms.
319  // First try finding predicted pileup separation.
320  // Pre-pileup should have match of h[0] in h[3] or h[2] in h[1].
321  // Post-pileup should have match of h[2] in h[3]
322  // These will be used to predict the h[4]-h[5] separations.
323  // First pass through h[4], h[5] is to look for matches which we call good vertices.
324  // flag = 1;
325  // Then offset unmatched h[4] by predicted pileup distance. If we find unmatched we call it pileup.
326  // flag = 2 for pre-pileup
327  // flag = 3 for post-pileup
328  // If an unmatched matches an already matched flag according to whether matched was called
329  // good or not. (We are quite concerned about pileup reconstructing to actual vertex.)
330  // flag = 4 if h[4] was good
331  // flag = 5 if h[5] was good
332  // Finally, take all unmatched and copy into verts. If we have one h[4] and one h[5]
333  // pair them for convenience.
334  // flag = 6 we have pair of left overs
335  // flag = 7 otherwise
336 
337 
338  fillHistos(muDst);
339  findPiles();
340 
341 
342  // Now look for good, matching histograms in V_z.
343  for (int i=0;i<5;i++) {
344  mMatchM[i] = 0;
345  mUsedM[i] = 0;
346  mMatchP[i] = 0;
347  mUsedP[i] = 0;
348  }
349  int nVerts = 0;
350  for (int ip4=0;ip4<mNPeaks[4];ip4++) {
351  for (int ip5=0;ip5<mNPeaks[5];ip5++) {
352  if ( mZPeakMatchMin < mPos[4][ip4]-mPos[5][ip5] &&
353  mPos[4][ip4]-mPos[5][ip5] < mZPeakMatchMax) {
354  if (nVerts < 10) {
355  mVerts[nVerts][0] = mPos[4][ip4];
356  mVerts[nVerts][1] = mArea[4][ip4];
357  mVerts[nVerts][2] = mPos[5][ip5];
358  mVerts[nVerts][3] = mArea[5][ip5];
359  mVerts[nVerts][4] = mPos[4][ip4]-mPos[5][ip5];
360  mFlag[nVerts] = 1;
361  }
362  nVerts++;
363  mMatchP[ip4] = nVerts;
364  mMatchM[ip5] = nVerts;
365  mUsedP[ip4] = nVerts;
366  mUsedM[ip5] = nVerts;
367  if (mVerbose) {
368  cout << "Good vertex. pos4 = " << mPos[4][ip4] << ", pos5 = " << mPos[5][ip5] << endl;
369  }
370  }
371  }
372  }
373  // Try matching vertices to pileup.
374  for (int ip=0;ip<mNPiles;ip++) {
375  for (int ip4=0;ip4<mNPeaks[4];ip4++) {
376  for (int ip5=0;ip5<mNPeaks[5];ip5++) {
377  double dist = -9999;
378  if (2 == mPileFlag[ip]) {
379  dist = mPos[4][ip4]-mPos[5][ip5] - mPileDist[ip];
380  } else if (3 == mPileFlag[ip]) {
381  dist = mPos[5][ip5]-mPos[4][ip4] - mPileDist[ip];
382  }
383  if ( mZPileMatchMin < dist &&
384  dist < mZPileMatchMax ) {
385  if (!mMatchP[ip4] && !mMatchM[ip5]) {
386  if (nVerts < 10) {
387  mVerts[nVerts][0] = mPos[4][ip4];
388  mVerts[nVerts][1] = mArea[4][ip4];
389  mVerts[nVerts][2] = mPos[5][ip5];
390  mVerts[nVerts][3] = mArea[5][ip5];
391  mVerts[nVerts][4] = dist;
392  mFlag[nVerts] = mPileFlag[ip];
393  }
394  nVerts++;
395  mUsedP[ip4] = nVerts;
396  mUsedM[ip5] = nVerts;
397  if (mVerbose) {
398  cout << "Matched pileup at " << mPos[4][ip4] << " to " << mPos[5][ip5] << ". Expected distance of " << mPileDist[ip] << endl;
399  }
400  } else if (mMatchP[ip4]) {
401  if (nVerts < 10) {
402  mVerts[nVerts][0] = mPos[4][ip4];
403  mVerts[nVerts][1] = mArea[4][ip4];
404  mVerts[nVerts][2] = mPos[5][ip5];
405  mVerts[nVerts][3] = mArea[5][ip5];
406  // For this case we are storing predicted position - previously matched.
407  mVerts[nVerts][4] = dist;
408  // Also store predicted position.
409  if (2 == mPileFlag[ip]) {
410  mVerts[nVerts][5] = mPos[5][ip5] + mPileDist[ip];
411  } else if (3 == mPileFlag[ip]) {
412  mVerts[nVerts][5] = mPos[5][ip5] - mPileDist[ip];
413  }
414  mFlag[nVerts] = mPileFlag[ip] + 2;
415  }
416  nVerts++;
417  mUsedM[ip5] = nVerts;
418  if (mVerbose) {
419  cout << "!!!!!Matched pileup with good vertex? 4 ->" << mPos[4][ip4] << " 5 -> " << mPos[5][ip5] << ". Expected distance of " << mPileDist[ip] << endl;
420  }
421  } else if (mMatchM[ip5]) {
422  if (nVerts < 10) {
423  mVerts[nVerts][0] = mPos[5][ip5];
424  mVerts[nVerts][1] = mArea[5][ip5];
425  mVerts[nVerts][2] = mPos[4][ip4];
426  mVerts[nVerts][3] = mArea[4][ip4];
427  // For this case we are storing predicted position - previously matched.
428  mVerts[nVerts][4] = dist;
429  // Also store predicted position.
430  if (2 == mPileFlag[ip]) {
431  mVerts[nVerts][5] = mPos[4][ip4] - mPileDist[ip];
432  } else if (3 == mPileFlag[ip]) {
433  mVerts[nVerts][5] = mPos[4][ip4] + mPileDist[ip];
434  }
435  mFlag[nVerts] = mPileFlag[ip] + 2;
436  }
437  nVerts++;
438  mUsedP[ip4] = nVerts;
439  if (mVerbose) {
440  cout << "!!!!!Matched pileup with good vertex? 5 ->" << mPos[4][ip4] << " 5 -> " << mPos[5][ip5] << ". Expected distance of " << mPileDist[ip] << endl;
441  }
442  }
443  }
444  }
445  }
446  }
447  // Have singleton peaks left over. If a single pair (one in 4 and one in 5) put them together.
448  int iPlus[5], nPlus = 0;
449  for (int ip4=0;ip4<mNPeaks[4];ip4++) {
450  if (!mUsedP[ip4]) {
451  iPlus[nPlus] = ip4;
452  nPlus++;
453  }
454  }
455  int iMinus[5], nMinus = 0;
456  for (int ip5=0;ip5<mNPeaks[5];ip5++) {
457  if (!mUsedM[ip5]) {
458  iMinus[nMinus] = ip5;
459  nMinus++;
460  }
461  }
462  if ( nPlus==1 && nMinus==1) {
463  if (nVerts < 10) {
464  mVerts[nVerts][0] = mPos[4][iPlus[0]];
465  mVerts[nVerts][1] = mArea[4][iPlus[0]];
466  mVerts[nVerts][2] = mPos[5][iMinus[0]];
467  mVerts[nVerts][3] = mArea[5][iMinus[0]];
468  mVerts[nVerts][4] = mPos[4][iPlus[0]]-mPos[5][iMinus[0]];
469  mFlag[nVerts] = 6;
470  }
471  nVerts++;
472  } else {
473  for (int ip=0;ip<nPlus;ip++) {
474  if (nVerts < 10) {
475  mVerts[nVerts][0] = mPos[4][iPlus[ip]];
476  mVerts[nVerts][1] = mArea[4][iPlus[ip]];
477  mFlag[nVerts] = 7;
478  }
479  nVerts++;
480  }
481  for (int im=0;im<nMinus;im++) {
482  if (nVerts < 10) {
483  mVerts[nVerts][0] = mPos[5][iMinus[im]];
484  mVerts[nVerts][1] = mArea[5][iMinus[im]];
485  mFlag[nVerts] = 7;
486  }
487  nVerts++;
488  }
489  }
490  if (nVerts > 10) {
491  cout << "Found too many vertices; nVerts = " << nVerts << endl;
492  nVerts = 10;
493  }
494  mNVerts = nVerts;
495  return nVerts;
496 }
497 //-------------------------------------------------------
498 int Pileup::fillQAHistos(StMuDst *muDst) {
499  float x1, y1, z1, x2, y2, z2;
500  float zS1, zS2;
501  float r1, r2;
502  double phi1, phi2, pt;
503  int isec1, isec2;
504  int flag;
505 
506  for (int i=0;i<3;i++) {
507  mHQA1D[i]->Reset();
508  mHQA2D[i]->Reset();
509  }
510 
511  StMuTrack* track;
512  for (int it=0;it<muDst->globalTracks()->GetEntries();it++) {
513  track = muDst->globalTracks(it);
514  flag = track->flag();
515  if (flag < 0 || 700 <= flag) {
516  continue;
517  }
518  StThreeVectorF first = track->firstPoint();
519  StThreeVectorF last = track->lastPoint();
520  x1 = first.x();
521  y1 = first.y();
522  z1 = first.z();
523  x2 = last.x();
524  y2 = last.y();
525  z2 = last.z();
526  pt = track->pt();
527  if (pt < 0.4) {
528  continue;
529  }
530  phi1 = fabs(atan2(y1,x1)*360/(2*3.1415926));
531  isec1 = int((phi1+15.0)/30.0);
532  phi1 = fabs(phi1-30*isec1);
533  phi2 = fabs(atan2(y2,x2)*360/(2*3.1415926));
534  isec2 = int((phi2+15.0)/30.0);
535  phi2 = fabs(phi2-30*isec2);
536  r1 = sqrt( x1*x1 + y1*y1 );
537  r2 = sqrt( x2*x2 + y2*y2 );
538  if (r1 > 50 && fabs(z1) < 190.0 && fabs(z2) < 190.0 && phi1 < 12.0 && phi2 < 12.0) {
539  mHQA1D[0]->Fill(z1);
540  mHQA1D[1]->Fill(z2);
541  }
542  mHQA2D[0]->Fill(z1,z2);
543  zS1 = z1 + (z2-z1)*(65.0-r1)/(r2-r1);
544  zS2 = z2 + (z1-z2)*(190.0-r2)/(r1-r2);
545  mHQA2D[1]->Fill(zS1,zS2);
546  mHQA2D[2]->Fill((65.0*zS2-190.0*zS1)/(65.0-190.0),zS2);
547  mHQA1D[2]->Fill( (65.0*zS2-190.0*zS1) / (65.0-190.0) );
548 
549  }
550  return 1;
551 }
552 
553 //-------------------------------------------------------
554 int Pileup::fillHistos(StMuDst *muDst) {
555 
556  float x1, y1, z1, x2, y2, z2;
557  float r1, r2, Vz;
558  double phi1, phi2, pt;
559  int isec1, isec2;
560  int flag;
561 
562  for (int i=0;i<6;i++) {
563  mHPileup[i]->Reset();
564  }
565 
566  StMuTrack* track;
567  for (int it=0;it<muDst->globalTracks()->GetEntries();it++) {
568  track = muDst->globalTracks(it);
569  flag = track->flag();
570  if (flag < 0 || 700 <= flag) {
571  continue;
572  }
573  StThreeVectorF first = track->firstPoint();
574  StThreeVectorF last = track->lastPoint();
575  x1 = first.x();
576  y1 = first.y();
577  z1 = first.z();
578  x2 = last.x();
579  y2 = last.y();
580  z2 = last.z();
581  pt = track->pt();
582  if (pt < 0.2) {
583  continue;
584  }
585  r1 = sqrt( x1*x1 + y1*y1 );
586  r2 = sqrt( x2*x2 + y2*y2 );
587  Vz = (r1*z2-r2*z1)/(r1-r2);
588  // Note: It appears electronic readout continues past the central membrane (a good thing)
589  // and some points are reconstructed on the other side (a bad thing)
590  // For now use a "dead" zone of 5cm where we ignore tracks with a first or
591  // last point closer to the central membrane than that.
592  if (z2 > mDead[6]) {
593  mHPileup[4]->Fill(Vz);
594  } else if (z2 < -mDead[6]) {
595  mHPileup[5]->Fill(Vz);
596  }
597  // Tracks with first point in inner tracker probably not pileup
598  if (r1 < 50) {
599  continue;
600  }
601  // Tracks leaving via the endplate or starting on a sector
602  // boundary probably wash out start peak we are looking for.
603  phi1 = fabs(atan2(y1,x1)*360/(2*3.1415926));
604  isec1 = int((phi1+15.0)/30.0);
605  phi1 = fabs(phi1-30*isec1);
606  if (phi1 < 12) {
607  if (0 < z2 && z2 < 190) {
608  mHPileup[0]->Fill(z1);
609  } else if (-190 < z2 && z2 < 0) {
610  mHPileup[1]->Fill(z1);
611  }
612  }
613  // Tracks ending on a sector boundary probably wash out stop peak we are looking for.
614  // We also ignore tracks leaving via the endplate. (Could leave them in, but
615  // then in searching for peaks we have to ignore them)
616  phi2 = fabs(atan2(y2,x2)*360/(2*3.1415926));
617  isec2 = int((phi2+15.0)/30.0);
618  phi2 = fabs(phi2-30*isec2);
619  if (phi2 < 12 && fabs(z2) < 190) {
620  if (0 < z1) {
621  mHPileup[2]->Fill(z2);
622  } else {
623  mHPileup[3]->Fill(z2);
624  }
625  }
626  }
627  return 1;
628 }
629 
630 //-------------------------------------------------------
631 // This algorithm has problem when peaks are too close because we
632 // are trying to subtract local background.
633 int Pileup::findPeaks(int ih) {
634  int nBins = mHPileup[ih]->GetNbinsX();
635  double binStart = mHPileup[ih]->GetBinLowEdge(1);
636  double binWidth = mHPileup[ih]->GetBinWidth(1);
637  double avg = mHPileup[ih]->Integral() / 400.0;
638  double min = 2.5+mHPileup[ih]->Integral()*7/1000.0;
639  double sum, w, mean;
640 
641  int nPeaks = 0;
642  for (int i=2;i<nBins-1;i++) {
643  if (mHPileup[ih]->GetBinContent(i) > min) {
644  // Found bin that is statistically significantly above fluctuation.
645  // Add bins with higher than twice average content on both sides
646  sum = mHPileup[ih]->GetBinContent(i);
647  w = 1;
648  mean = i*mHPileup[ih]->GetBinContent(i);
649  int j = i-1;
650  while (mHPileup[ih]->GetBinContent(j) > 2*avg+1) {
651  sum += mHPileup[ih]->GetBinContent(j);
652  w += 1;
653  mean += j*mHPileup[ih]->GetBinContent(j);
654  j -= 1;
655  if (j == 0) {
656  break;
657  }
658  }
659  int imin = j-5;
660  j = i+1;
661  // Require consecutive bins below cut-off before terminating this peak.
662  while (mHPileup[ih]->GetBinContent(j) > 2*avg+1 || mHPileup[ih]->GetBinContent(j+1) > 2*avg+1) {
663  sum += mHPileup[ih]->GetBinContent(j);
664  w += 1;
665  mean += j*mHPileup[ih]->GetBinContent(j);
666  j += 1;
667  if (j == nBins) {
668  break;
669  }
670  }
671  int imax = j+5;
672  mean /= sum;
673  // Require peak area to be at least twice min.
674  // if (sum > 2*min) {
675  // Require signigficant peak if background flat.
676  if (sum-w*avg > 5*sqrt(w*avg)) {
677  // If peak is not significantly above its neighborhood we ignore it.
678  // sum five bins on either side, starting from min and max of current peak.
679  double back = 0;
680  if (imin > 5) {
681  int k = imin - 5;
682  for (int ib=0;ib<5;ib++) {
683  back += mHPileup[ih]->GetBinContent(ib+k);
684  }
685  }
686  if (imax < nBins-6) {
687  int k = imax;
688  for (int ib=0;ib<5;ib++) {
689  back += mHPileup[ih]->GetBinContent(ib+k);
690  }
691  }
692  if (imin <= 5 || imax > nBins-5) {
693  back *= 2;
694  }
695  back = w*back/10;
696  mean = mean*binWidth + binStart;
697  if (fabs(mean) > mDead[ih]) {
698  if (sum-back > 5*sqrt(back)) {
699  if (nPeaks < 5) {
700  mPos[ih][nPeaks] = mean;
701  mArea[ih][nPeaks] = sum;
702  mWidth[ih][nPeaks] = w;
703  }
704  nPeaks++;
705  if (mVerbose) {
706  printf("ih = %i: Width of peak = %f, area = %f, position = %f, background = %f\n",ih,w,sum,mean,back);
707  }
708  }
709  } else {
710  if (mVerbose) {
711  printf("Found a peak but it is in dead region. ");
712  printf("ih = %i:Width of peak = %f, area = %f, position = %f, background = %f\n",ih,w,sum,mean,back);
713  }
714  }
715  }
716  i = j+1;
717  }
718  }
719  return nPeaks;
720 }
721 //-------------------------------------------------------
722 int Pileup::testFindPeaks(TH1D *h, int ih) {
723  TH1D *lp = lowPass(h,1);
724 
725  int nBins = lp->GetNbinsX();
726  double binStart = lp->GetBinLowEdge(1);
727  double binWidth = lp->GetBinWidth(1);
728  double avg = lp->Integral() / nBins;
729  double min = 5*sqrt(avg);
730  double sum, w, mean;
731 
732  int nPeaks = 0;
733  for (int i=2;i<nBins-1;i++) {
734  if (lp->GetBinContent(i) > min) {
735  // Found bin that is statistically significantly above fluctuation.
736  // Add bins with higher than twice average content on both sides
737  sum = lp->GetBinContent(i);
738  w = 1;
739  mean = i*lp->GetBinContent(i);
740  int j = i-1;
741  // I bet we will need to split some peaks.
742  while (lp->GetBinContent(j) > 2*sqrt(avg)) {
743  sum += lp->GetBinContent(j);
744  w += 1;
745  mean += j*lp->GetBinContent(j);
746  j -= 1;
747  if (j == 0) {
748  break;
749  }
750  }
751  j = i+1;
752  while (lp->GetBinContent(j) > 2*sqrt(avg)) {
753  sum += lp->GetBinContent(j);
754  w += 1;
755  mean += j*lp->GetBinContent(j);
756  j += 1;
757  if (j == nBins) {
758  break;
759  }
760  }
761  mean /= sum;
762  // Require signigficant peak if background flat.
763  if (sum-w*avg > 5*sqrt(w*avg)) {
764  mean = mean*binWidth + binStart;
765  if (fabs(mean) > mDead[ih]) {
766  if (nPeaks < 5) {
767  mPos[ih][nPeaks] = mean;
768  mArea[ih][nPeaks] = sum;
769  mWidth[ih][nPeaks] = w;
770  }
771  nPeaks++;
772  if (mVerbose) {
773  printf("ih = %i: Width of peak = %f, area = %f, position = %f\n",ih,w,sum,mean);
774  }
775  } else {
776  if (mVerbose) {
777  printf("Found a peak but it is in dead region. ");
778  printf("ih = %i:Width of peak = %f, area = %f, position = %f\n",ih,w,sum,mean);
779  }
780  }
781  }
782  i = j+1;
783  }
784  }
785  delete lp;
786  return nPeaks;
787 }
788 //-------------------------------------------------------
789 TH1D* Pileup::lowPass(TH1D *h, int width) {
790  TH1D *lp = (TH1D *) h->Clone();
791  lp->Reset();
792  int upper = h->GetNbinsX();
793 
794  int nSum, jMin, jMax;
795  double sum;
796  for (int i=1;i<upper;i++) {
797  jMin = i-width < 1 ? 1 : i-width;
798  jMax = i+width >upper ? upper : i+width;
799  sum = 0;
800  nSum = 0;
801  for (int j=jMin;j<jMax;j++) {
802  sum += h->GetBinContent(j);
803  nSum++;
804  }
805  lp->SetBinContent(i,sum/nSum);
806  }
807  return lp;
808 }
809 //-------------------------------------------------------
810 int Pileup::findPiles() {
811  // Get list of possible vertices for all histograms.
812  for (int ih=0;ih<6;ih++) {
813  mNPeaks[ih] = findPeaks(ih);
814  if (mNPeaks[ih] > 5) {
815  cout << "Vertex " << ih << " had " << mNPeaks[ih] << " peaks found which is too big for my arrays." << endl;
816  mNPeaks[ih] = 5;
817  }
818  }
819 
820  mNPiles = 0;
821  // Look for pre pileup
822  // For each peak in 0 and 1 look for match in 3 and 2
823  for (int ip0=0;ip0<mNPeaks[0];ip0++) {
824  for (int ip3=0;ip3<mNPeaks[3];ip3++) {
825  if ( mZStartStopMatchMin < mPos[0][ip0]+mPos[3][ip3] &&
826  mPos[0][ip0]+mPos[3][ip3] < mZStartStopMatchMax) {
827  if (mVerbose) {
828  cout << "Possible match for pre + -. pos0 = " << mPos[0][ip0] << ", pos3 = " << mPos[3][ip3] << endl;
829  }
830  if (mNPiles < 10) {
831  // For pre pileup the drift distance is from the central membrane, so the vertex
832  // separation is twice that.
833  mPileDist[mNPiles] = mPos[0][ip0] - mPos[3][ip3];
834  mPileFlag[mNPiles] = 2;
835  }
836  mNPiles++;
837  }
838  }
839  }
840  for (int ip2=0;ip2<mNPeaks[2];ip2++) {
841  for (int ip1=0;ip1<mNPeaks[1];ip1++) {
842  if ( mZStartStopMatchMin < mPos[2][ip2]+mPos[1][ip1] &&
843  mPos[2][ip2]+mPos[1][ip1] < mZStartStopMatchMax) {
844  if (mVerbose) {
845  cout << "Possible match for pre - +. pos2 = " << mPos[2][ip2] << ", pos1 = " << mPos[1][ip1] << endl;
846  }
847  if (mNPiles < 10) {
848  mPileDist[mNPiles] = mPos[2][ip2] - mPos[1][ip1];
849  mPileFlag[mNPiles] = 2;
850  }
851  mNPiles++;
852  }
853  }
854  }
855  // Look for post pileup.
856  for (int ip2=0;ip2<mNPeaks[2];ip2++) {
857  for (int ip3=0;ip3<mNPeaks[3];ip3++) {
858  if ( mZStartStopMatchMin < mPos[2][ip2]+mPos[3][ip3] &&
859  mPos[2][ip2]+mPos[3][ip3] < mZStartStopMatchMax) {
860  if (mVerbose) {
861  cout << "Possible match for post. pos2 = " << mPos[2][ip2] << ", pos3 = " << mPos[3][ip3] << endl;
862  }
863  if (mNPiles < 10) {
864  // For post pileup the drift distance is from the endplate.
865  mPileDist[mNPiles] = mZEndplate-mPos[2][ip2] + mZEndplate+mPos[3][ip3];
866  mPileFlag[mNPiles] = 3;
867  }
868  mNPiles++;
869  }
870  }
871  }
872  if (mNPiles > 10) {
873  cout << "Found too many piles; nPiles = " << mNPiles << endl;
874  mNPiles = 10;
875  }
876  return mNPiles;
877 }
878 //-------------------------------------------------------
879 TH1D *Pileup::hist(int ih) {
880  // Return histograms used for examining vertex structure.
881  // For pileup track zStart and zEnd have to be in same half of TPC (except when point
882  // projected past the central membrane)
883  // A pileup candidate in one half of TPC must match candidate in other half.
884  // ih = 0 is zStart for zEnd > 0 pre pileup would match peak in ih = 3
885  // ih = 1 is zStart for zEnd < 0 pre pileup would match peak in ih = 2
886  // ih = 2 is zEnd for zStart > 0 post pileup would match -peak in ih=3
887  // ih = 3 is zEnd for zStart < 0 post pileup would match -peak in ih=2
888  // ih = 4 is sheared zEnd for zEnd > 0
889  // ih = 5 is sheared zEnd for zEnd < 0
890  // Good vertex should have peak in ih = 4 matched to peak in ih = 5.
891  // Pileup vertices will be offset in 4 and 5 by amount determined from 0-3.
892  if (ih < 0 || 5 < ih) {
893  return NULL;
894  }
895  return mHPileup[ih];
896 }
897 //-------------------------------------------------------
898 TH1D *Pileup::histQA1D(int ih) {
899  // Return 1D QA histogram
900  // ih = 0 is zStart (should contain peaks if pre pileup)
901  // ih = 1 is zEnd (should contain peaks if pre or post pileup)
902  // ih = 2 is sheared zEnd (should contain peaks for vertex positions)
903  if (ih < 0 || 2 < ih) {
904  return NULL;
905  }
906  return mHQA1D[ih];
907 }
908 //-------------------------------------------------------
909 TH2D *Pileup::histQA2D(int ih) {
910  // Return 2D QA histogram
911  // ih = 0 is raw zStart vs. zEnd (compare to 1D ih = 0 and ih = 1;
912  // ih = 1 is zStart vs. zEnd with values scaled to reference radii.
913  // ih = 2 is zStart vs sheared zEnd.
914  if (ih < 0 || 2 < ih) {
915  return NULL;
916  }
917  return mHQA2D[ih];
918 }
919 
920 
921 
922 
923 /**********************************************************************
924  *
925  * $Log: Pileup.cxx,v $
926  * Revision 1.1 2008/12/02 23:47:43 prindle
927  * Code to check for possible pileup. Really belongs in some vertex finding
928  * package but is here for now.
929  *
930  * initial check in of Pileup characterizer
931  *
932  *
933  *********************************************************************/
static TObjArray * globalTracks()
returns pointer to the global tracks list
Definition: StMuDst.h:303
Double_t pt() const
Returns pT at point of dca to primary vertex.
Definition: StMuTrack.h:256
short flag() const
Returns flag, (see StEvent manual for type information)
Definition: StMuTrack.h:230
const StThreeVectorF & firstPoint() const
Returns positions of first measured point.
Definition: StMuTrack.h:261
const StThreeVectorF & lastPoint() const
Returns positions of last measured point.
Definition: StMuTrack.h:262
Definition: Pileup.h:79