StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StSvtAnalysis.cc
1 /***************************************************************************
2  *
3  * $Id: StSvtAnalysis.cc,v 1.21 2005/07/23 03:37:33 perev Exp $
4  *
5  * Author: Selemon Bekele
6  ***************************************************************************
7  *
8  * Description: Fits the clusters to find the various moments (0th, 1st, 2nd)
9  * as well as peakADC, number of anodes, number of pixels,...
10  *
11  * Then catagorize the clusters with a flag. All flags<4 are
12  * good. A Flag==2 is a deconvoluted hit. All flags are mulitples
13  * of 2 so the user can check for all the reasons a hit was flag
14  * a certain way. When hits are catagorized we never judge solely
15  * on peakADc or integrated charge as this is a bias. See
16  * CatagorizeCluster() for details on how we callsify clusters.
17  * An additional cut is made for noisy anodes or timebuckets
18  * if there are more than 4 hits/event on them.
19  *
20  * Finally this code deconvolutes some clusters. At present we are
21  * quite conservative in which clusters we deconvolute. There has
22  * to be a clear valley between peaks in a cluster for hits to be
23  * deconvoluted. Look at PEAK_TO_VALLEY in isValidPeak() for more
24  * details.
25  *
26  * Flags: 0 = standard good
27  * 2 = deconvoluted
28  * 4 = more than 4 hits on eithe this anodes or time bucket
29  * for this event
30  * 8 = 1 pixel cluster with ADC<1 (could reuse this for something else)
31  * 16 = undershoot on wrong side
32  * 32 = topological cut. Based on num pixels, and charge
33  * 64 = topological cut based on relative widths in anode and time dir. Gets
34  * rid of tracks comming in at very shallow angles. You might want to
35  * rethink this one for special physics studies.
36  * 128 = A hit which was deconvoluted.
37  *
38  *
39  *
40  * Bugs: The method used to flad noisy anodes and time buckets is inefficient
41  * and should be looked at. We zero a huge array before each event. Sanjeev
42  *
43  * We still cant seem to classify hits on hydrid 10 as bad. Probebly
44  * will never be able to as the blob keeps messing up the peds here. Sanjeev
45  *
46  * At present I assume the arbitary offset to all anodes is 100. This will have
47  * to be made a variable and replaced in *3* places. Sanjeev
48 
49  * PedOffset is now subtracted properly Helen 17/08/00
50  *
51  ***************************************************************************
52  *
53  * Modifications by Jun Takahashi Dec 2002.
54  * 1. In oneOrTwoAnodeMoments, I included the line , mNumPixels++;
55  * 2. Created the function: LoadAnodeGains(), but it is set to 1 at the moment.
56  * 3. In CatagorizeCluster: Added new cuts and flags:
57  * flag: 44 laser spot.
58  * 17 cluster sequence bigger than 80 in time direction
59  * 10 single anode, with more than 10 time buckets.
60  * 13 Found a seconday peak after original peak.
61  * 15 Found a secondary peak before original peak.
62  *
63  *
64  * $Log: StSvtAnalysis.cc,v $
65  * Revision 1.21 2005/07/23 03:37:33 perev
66  * IdTruth + Cleanup
67  *
68  * Revision 1.20 2004/04/23 15:57:32 caines
69  * Flag as bad hits with 1 anode and peak less than 11
70  *
71  * Revision 1.19 2003/09/02 17:59:06 perev
72  * gcc 3.2 updates + WarnOff
73  *
74  * Revision 1.18 2003/04/30 20:38:45 perev
75  * Warnings cleanup. Modified lines marked VP
76  *
77  * Revision 1.17 2003/01/28 20:27:30 munhoz
78  * new filters for clusters
79  *
80  * Revision 1.16 2002/05/09 16:55:39 munhoz
81  * add reading bad anodes from DB
82  *
83  * Revision 1.15 2002/04/25 20:34:50 caines
84  * Pass bad anode information into cluster fitter
85  *
86  * Revision 1.14 2002/01/04 16:05:48 caines
87  * fix overstepping of array bounds
88  *
89  * Revision 1.13 2001/08/07 20:52:15 caines
90  * Implement better packing of svt hardware and charge values
91  *
92  * Revision 1.12 2001/04/25 18:34:44 perev
93  * HPcorrs
94  *
95  * Revision 1.11 2001/04/21 21:47:39 caines
96  * Fix int to double problem
97  *
98  * Revision 1.10 2000/11/30 20:42:58 caines
99  * Fix flag error and anode position error, use database
100  *
101  * Revision 1.9 2000/10/31 16:20:57 caines
102  * Added more functions to make the code more readable
103  *
104  * Revision 1.9 2000/10/23 13:47:03 Selemon
105  * Added more functions to make the code more readable
106  *
107  * Revision 1.8 2000/10/02 13:47:03 caines
108  * Fixed some array bound problems. Better flagging of hits
109  *
110  * Revision 1.7 2000/09/14 22:17:15 caines
111  * Fix memory problems
112  *
113  * Revision 1.6 2000/08/29 22:46:26 caines
114  * Fixed some memory leaks
115  *
116  * Revision 1.5 2000/08/24 04:27:56 caines
117  * Fixed casting warnings so compiles without errors on linux
118  *
119  * Revision 1.4 2000/08/21 13:06:57 caines
120  * Much improved hit finding and fitting
121  *
122  * Revision 1.3 2000/08 13:06:57 sanjeev
123  * changed flags so that we only have positive flags. All
124  * flags<4 are good.
125  *
126  * Revision 1.2 2000/08 13:06:57 sanjeev
127  * Added methods for peak finding, cluster fitting, and deconvoluting
128  *
129  *
130  **************************************************************************/
131 #include <Stiostream.h>
132 #include "Stiostream.h"
133 #include <assert.h>
134 #include <math.h>
135 #include <stdlib.h>
136 #include "StMessMgr.h"
137 #include "StSequence.hh"
138 #include "StMCTruth.h"
139 #include "StDAQMaker/StSVTReader.h"
140 #include "StSvtClassLibrary/StSvtHybridData.hh"
141 #include "StSvtClassLibrary/StSvtHybridBadAnodes.hh"
142 #include "StSvtAnalysis.hh"
143 
144 int Compare_Point ( const void *, const void *); //nedd to declare here for some odd reason.
145 
146 StSvtAnalysis::StSvtAnalysis(int TotalNumberOfHybrids)
147 {
148  mHybridData = NULL;
149  mHybridRawData = NULL;
150  mHybridCluster = NULL;
151  mSvtSequence = NULL;
152  mSvtBadAnode = NULL;
153 
154  m_nWrkBkt = 0;
155  m_nUndBkt = 0;
156  m_nGt8 = 0;
157  m_nSig = 0;
158  m_SvtEvt = 0;
159  mHitId = 0;
160 
161  mNumPixels = 0, mPeakADC = 0, mSumAdc = 0;
162  mMom0 = 0, mNeff = 0;
163  mDriftMom1 = 0, mAnodeMom1 = 0;
164  mDriftMom2 = 0, mAnodeMom2 = 0; mMom0 = 0, mNeff = 0;
165  mX_err=72., mY_err=75.; //default bin size/::sqrt(12)
166 
167  mMaxClu=0;
168  setMemory();
169  setArrays(TotalNumberOfHybrids);
170 
171 }
172 
173 void StSvtAnalysis::setMemory()
174  {
175  //call all new's here in init and hope we never go above 500. If we do we recall new and make it
176  //the larger size. Sanjeev
177 
178  mMaxClu = (mMaxClu)? mMaxClu*2 : 500;
179  mAuxArr.Set(mMaxClu*sizeof(StSvtAnalysisAux));
180  mAux = (StSvtAnalysisAux*)mAuxArr.GetArray();
181 }
182 
183 void StSvtAnalysis::setArrays(int TotalNumberOfHybrids)
184 {
185 
186  m_countBadAn = malloc_matrix_d (TotalNumberOfHybrids+1, 240+2); // number of hybrids bad anodes (>4 hits)
187  m_countBadTb = malloc_matrix_d (TotalNumberOfHybrids+1, 128+1); // bad time
188 
189  if (m_countBadAn == NULL || m_countBadTb == NULL) {
190  cout<<"You have a bad error assigning memory for counting bad SVT pixels"<<endl;
191  if (m_countBadAn==NULL) free_matrix_d(m_countBadAn, 240+2);
192  if (m_countBadTb==NULL) free_matrix_d(m_countBadTb, 128+1);
193  }
194 
195  m_Pixels = malloc_matrix_d (240+2, 128+2); //use these for deconvolution
196  m_Shadow = malloc_matrix_d (240+2, 128+2);
197  m_Raw = malloc_matrix_d (240+2, 128+2);
198 
199  if (m_Pixels == NULL || m_Shadow == NULL || m_Raw == NULL) {
200  cout<<"You have a fatal error in assigning memory in the cluster finder"<<endl;
201  if (m_Pixels) free_matrix_d (m_Pixels, 240+2);
202  if (m_Shadow) free_matrix_d (m_Shadow, 240+2);
203  if (m_Raw) free_matrix_d (m_Raw , 240+2);
204  }
205 
206  for (int i1=0;i1<242;i1++) {
207  for (int j1=0;j1<130;j1++) {
208  m_Pixels[i1][j1] = 0;
209  m_Shadow[i1][j1] = 0;
210  m_Raw[i1][j1] = 0;
211  }
212  }
213 
214  }
215 
216 
217 StSvtAnalysis::~StSvtAnalysis()
218 {
219 
220 }
221 void StSvtAnalysis::SetPointers(StSvtHybridData* hybAdjData,
222  StSvtHybridData* hybRawData,
223  StSvtHybridCluster* hybClu,
224  StSvtHybridBadAnodes* BadAnodes,
225  int NumberOfHybrids, int PedOffset )
226 // This is how the Maker communicates with this object to tell it where the data is. We also
227 // want access to the raw data for the deconvolution and for the one anode hits to get a better
228 // estimate of the 2nd moments. Sanjeev
229 {
230  mHybridData = hybAdjData;
231  mHybridRawData = hybRawData;
232  mHybridCluster = hybClu;
233  mPedOffset = PedOffset;
234  mSvtBadAnode = BadAnodes;
235 
236  mNumOfClusters = mHybridCluster->getNumberOfClusters();
237  if (mNumOfClusters>mMaxClu) setMemory();
238 
239  //this is called for each new event
240 
241  {for (int i=0; i<NumberOfHybrids; i++) {
242  {for (int j=0; j<242; j++) m_countBadAn[i][j] = 0;}
243  {for (int j=0; j<129; j++) m_countBadTb[i][j] = 0;}
244  }}
245 
246 }
247 
248 
249 void StSvtAnalysis::FirstAndLastAnodes()
250  // Calculate the First and last Anodes of all the clusters. Selemon
251 {
252  int actualAn = 0, actualan = 0, mem = 0;
253 
254  if (mNumOfClusters>mMaxClu) setMemory();
255 
256  for(int clu = 0; clu < mNumOfClusters; clu++)
257  {
258  StSvtAnalysisAux *aux = mAux+clu;
259  mem = 0; //add apr00 SUP
260  mNumOfMembers = mHybridCluster->getNumberOfMembers(clu);
261  aux->mInfo = mHybridCluster->getCluMemInfo(clu);
262 
263 
264  if(mNumOfMembers==1)
265  {
266  aux->mCluFirstAnode = aux->mInfo[mem].actualAnode;
267  aux->mCluLastAnode = aux->mCluFirstAnode;
268  }
269  else
270  {
271  {for(int j = 1; j<mNumOfMembers ; j++)
272  {
273  actualAn = aux->mInfo[mem].actualAnode;
274  actualan = aux->mInfo[j].actualAnode;
275 
276  if(actualAn < actualan)
277  aux->mCluFirstAnode = actualAn;
278  else
279  {
280  aux->mCluFirstAnode= actualan;
281  mem = j;
282  }
283  }}
284 
285  mem = 0;
286  {for(int j = 1; j<mNumOfMembers ; j++)
287  {
288  actualAn = aux->mInfo[mem].actualAnode;
289  actualan = aux->mInfo[j].actualAnode;
290 
291  if(actualAn > actualan)
292  aux->mCluLastAnode = actualAn;
293 
294  else
295  {
296  aux->mCluLastAnode = actualan;
297  mem = j;
298  }
299  }}
300 
301  }
302  }
303 }
304 
305 
306 void StSvtAnalysis::CluFirstTimeBin()
307  // Calculate the first time bin in the cluster. Selemon
308 {
309  int status , Seq, SeqStart = 0, seqStart = 0;
310  int listAn = 0, mseq = 0, mem;
311 
312  // StSequence* svtSequence;
313  if (mNumOfClusters>mMaxClu) setMemory();
314 
315  for(int clu = 0; clu < mNumOfClusters; clu++)
316  {
317  StSvtAnalysisAux *aux = mAux+clu;
318  aux->mInfo = mHybridCluster->getCluMemInfo(clu);
319  mNumOfMembers = mHybridCluster->getNumberOfMembers(clu);
320 
321  mem = 0;
322 
323  if(mNumOfMembers==1)
324  {
325  listAn = aux->mInfo[mem].listAnode;
326  mseq = aux->mInfo[mem].seq;
327 
328  status = mHybridData->getListSequences(listAn,Seq,mSvtSequence);
329  aux->mCluFirstTimeBin = mSvtSequence[mseq].startTimeBin;
330  }
331  else
332  {
333  for(int j = 1; j< mNumOfMembers; j++)
334  {
335  listAn = aux->mInfo[mem].listAnode;
336  mseq = aux->mInfo[mem].seq;
337  status = mHybridData->getListSequences(listAn,Seq,mSvtSequence);
338  SeqStart = mSvtSequence[mseq].startTimeBin;
339 
340  listAn = aux->mInfo[j].listAnode;
341  mseq = aux->mInfo[j].seq;
342  status = mHybridData->getListSequences(listAn,Seq,mSvtSequence);
343  seqStart = mSvtSequence[mseq].startTimeBin;
344 
345  if(SeqStart <= seqStart)
346  aux->mCluFirstTimeBin = SeqStart;
347  else
348  {
349  aux->mCluFirstTimeBin = seqStart;
350  mem = j;
351  }
352  }
353  }
354  }
355  }
356 
357 
358 void StSvtAnalysis::CluLastTimeBin()
359 //Calculate last time bin in cluster. Selemon.
360 {
361  int status , Seq, SeqStart = 0, SeqLength = 0, SeqEnd = 0, seqEnd = 0;
362  int listAn = 0, mseq = 0, mem;
363 
364  //StSequence* svtSequence;
365  if (mNumOfClusters>mMaxClu) setMemory();
366 
367  for(int clu = 0; clu < mNumOfClusters; clu++)
368  {
369  mAux[clu].mInfo = mHybridCluster->getCluMemInfo(clu);
370  mNumOfMembers = mHybridCluster->getNumberOfMembers(clu);
371 
372  mem = 0;
373 
374  if(mNumOfMembers==1)
375  {
376  listAn = mAux[clu].mInfo[mem].listAnode;
377  mseq = mAux[clu].mInfo[mem].seq;
378  status = mHybridData->getListSequences(listAn,Seq,mSvtSequence);
379  SeqStart = mSvtSequence[mseq].startTimeBin;
380  SeqLength = mSvtSequence[mseq].length;
381  SeqEnd = SeqStart + SeqLength - 1;
382  mAux[clu].mCluLastTimeBin = SeqEnd;
383  }
384  else
385  {
386  for(int j = 1; j< mNumOfMembers ; j++){
387  listAn = mAux[clu].mInfo[mem].listAnode;
388  mseq = mAux[clu].mInfo[mem].seq;
389  status = mHybridData->getListSequences(listAn,Seq,mSvtSequence);
390 
391  SeqStart = mSvtSequence[mseq].startTimeBin;
392  SeqLength = mSvtSequence[mseq].length;
393  SeqEnd = SeqStart + SeqLength - 1;
394 
395  listAn = mAux[clu].mInfo[j].listAnode;
396  mseq = mAux[clu].mInfo[j].seq;
397  status = mHybridData->getListSequences(listAn,Seq,mSvtSequence);
398 
399  SeqStart = mSvtSequence[mseq].startTimeBin;
400  SeqLength = mSvtSequence[mseq].length;
401  seqEnd = SeqStart + SeqLength - 1;
402 
403  if(SeqEnd > seqEnd)
404  mAux[clu].mCluLastTimeBin = SeqEnd;
405  else {
406  mAux[clu].mCluLastTimeBin = seqEnd;
407  mem = j;
408  }
409  }
410  }
411  }
412 }
413 
414 void StSvtAnalysis::MomentAnalysis(){
415 //Calculate the moments of the cluster. We do not fit to determine the charge but rather
416 //just count pixels ADC. This routine presently call the catagoriser and deconvoluter.
417 //We might want to transfer those calls to the Maker. At present though the catagorizer
418 //and deconvluter work on a cluster by cluser basis. The Maker works with collections
419 //of clusters so the logic would hav to change if this happens. Sanjeev
420 //
421 
422  if (m_hybIndex==6) m_SvtEvt++;
423 
424  FillRawAdc(); //Put the raw adcs for the whole hybrid into an 2D
425  //Array. If there is no info value is 0.
426 
427  if(mNumOfClusters > mMaxClu) setMemory();
428 
429  m_clu = mNumOfClusters-1; //keep track of # deconcoluted clusters.
430 
431  for(int clu = 0; clu < mNumOfClusters; clu++){ //loop over all clusters for one hybrid
432  calcMoments(clu);
433  }
434 
435  m_clu++; //make equal to mNumOfClusters
436 
437  ClearRawAdc(); //have to reset the raw adc's since the number of anodes
438  //returned for each hybrid will not be the same and are not
439  //guareented to be 240.
440 }
441 
442 
443 void StSvtAnalysis::LoadAnodeGains()
444 {
445  /*
446  FILE *fp = fopen("/home/jtakahas/star/gaincal/meanadc_out.dat","r");
447 
448  int hy,an;
449  float meanadc;
450  float gain=0;
451  int ncols;
452  int nlines = 0;
453 
454  if (fp){
455  while (1) {
456  ncols = fscanf(fp,"%d %d %f",&hy, &an, &meanadc);
457  if (ncols < 0) break;
458  if (meanadc > 50 || meanadc<15) gain=1;
459  else gain = 20/meanadc;
460  mAux[an].mAnodeGain[hy]=1;
461  //mAux[an].mAnodeGain[hy]=gain;
462  //cout << nlines << "\t" << hy << "\t" << an << "\t" << mAux[an].mAnodeGain[hy] << endl;
463  nlines++;
464  }
465  }
466  else{
467  */
468  for (int i=0;i<433;i++){
469  for (int j=0;j<241;j++){
470  mAnodeGain[i][j]=1;
471  }
472  }
473  // }
474  //fclose(fp);
475 }
476 
477 
478 void StSvtAnalysis::calcMoments(int clu){
479  int listAn , actualAn, numAnodes;
480  int mseq, Seq, stTimeBin, len;
481  float ADC=0;
482  unsigned char* adc;
483  StSvtAnalysisAux *aux = mAux + clu;
484  mNumPixels = 0, mPeakADC = 0,mSumAdc = 0, mHitId=0;
485  mDriftMom1 = 0, mAnodeMom1 = 0, mDriftMom2 = 0, mAnodeMom2 = 0, mMom0 = 0, mNeff = 0;
486 
487  int igt3=0, peakPosAn=0, peakPosTim=0, peakMem=0, peakPixel=0; //recall 1ADC = 4mV
488 
489  aux->mInfo = mHybridCluster->getCluMemInfo(clu);
490  mNumOfMembers = mHybridCluster->getNumberOfMembers(clu); //I guess this is the number of anodes
491 
492  numAnodes = GetLastAnode(clu)-GetFirstAnode(clu)+1; //this is not the same as mNumOfMembers for clusters while curl around!!
493 
494  mMyflag=0;
495  for(int mem = 0; mem < mNumOfMembers; mem++) {
496  listAn = aux->mInfo[mem].listAnode; //what is this??
497  mseq = aux->mInfo[mem].seq;
498  actualAn = aux->mInfo[mem].actualAnode; //actual anode
499 
500  mHybridData->getListSequences(listAn,Seq,mSvtSequence);
501  stTimeBin = mSvtSequence[mseq].startTimeBin;
502  len = mSvtSequence[mseq].length;
503  adc = mSvtSequence[mseq].firstAdc;
504  for(int j = 0; j < len; j++) { //loop over time in one sequence
505  ADC = (float)adc[j];
506  if (ADC==0 || ADC==255) ADC=ADC;
507  else ADC=ADC-mPedOffset; // mPedOffset subtraction.
508 
509  ADC=ADC*mAnodeGain[m_hybIndex][actualAn];
510  //do this else we distort the means of small clusters.
511  if (mPeakADC<ADC) {
512  mPeakADC=(int)ADC; peakPosAn=actualAn; peakPosTim=stTimeBin+j; peakMem=mem; peakPixel=j;
513  }
514 
515  if (ADC>1 && ADC<4000 && (stTimeBin+j)>=0 && (stTimeBin+j)<128 && actualAn>0 && actualAn<=240){
516  mNumPixels++;
517  if (ADC>3) igt3++;
518  mDriftMom1 += ADC * (stTimeBin + j + 0.5);
519  mAnodeMom1 += ADC * (actualAn - 0.5);
520  mDriftMom2 += ADC * (stTimeBin + j + 0.5) * (stTimeBin + j + 0.5);
521  mAnodeMom2 += ADC * (actualAn - 0.5) * (actualAn - 0.5);
522  mNeff += (int)(ADC * ADC);
523  mSumAdc += (int)ADC;
524  }
525  else {
526  //mHitId += -1;
527  //cout<<"You have funny SVT ADC or timebin or anodes numbers in this cluster"<<endl;
528  }
529  }
530  } //end loop over sequeces (members) from 1 cluster
531 
532 
533  // This will add the information of neighboring anodes to the 1/2 anode clusters.
534  if(numAnodes == 1 || numAnodes == 2){
535  mMyflag=1;
536  oneOrTwoAnodeMoments(clu, peakPosTim);
537  }
538 
539 
540  finalMoments(clu, numAnodes);
541  newCluster(clu, numAnodes,igt3);
542 }
543 
544 
545 void StSvtAnalysis::oneOrTwoAnodeMoments(int clu, int peakPosTim)
546 {
547  // Make the 2nd moments better for 1 anode hits. Look a little to the right of them for better calc.
548  // This routine adds ONLY the extra neighboring anodes information -1 and +1 anodes. JT
549  // Gets it from m_Raw
550 
551  int iAst, iAend;
552  float ADC=0;
553  iAst = GetFirstAnode(clu); iAend = GetLastAnode(clu);
554 
555 
556  if (iAst>1 && iAend<240 && peakPosTim>0 && peakPosTim<127){ /*do a better job for the 1 anode hits*/
557  for (int i=iAst-1; i<=iAend+1; i++) /*This is dangerous as we do it blindly*/
558  { /*It will mess up for a small fraction of hits*/
559 
560  if (i==iAst || i==iAend) continue; /*when another cluster is close by*/
561  for (int j=peakPosTim-1; j<=peakPosTim+1; j++)
562  {
563  ADC = (float)m_Raw[i][j]; // obs. m_Raw is already pedoffset subtracted.
564  ADC=ADC*mAnodeGain[m_hybIndex][i];
565 
566  if (ADC>0 && ADC<mPeakADC/2){ /*since we do this blindly lets at least put*/
567  mSumAdc += (int)ADC; /*some safety checks in*/
568  mDriftMom1 += ADC * (j+0.5);
569  mAnodeMom1 += ADC * (i-0.5);
570  mDriftMom2 += ADC * (j+0.5) * (j+0.5);
571  mAnodeMom2 += ADC * (i-0.5) * (i-0.5);
572  mNeff += int(ADC * ADC);
573  mNumPixels++; // Added this new line. JT.
574  }
575  }
576  }
577  }
578 }
579 
580 
581 void StSvtAnalysis::finalMoments(int clu,int numAnodes)
582 {
583 
584  if (mSumAdc>3) //fianlize the moment calculation and also estiame the cov's.
585  {
586  mMom0 = (double)mSumAdc;
587  mDriftMom1 = (double)mDriftMom1/mSumAdc;
588  mAnodeMom1 = (double)mAnodeMom1/mSumAdc;
589  mDriftMom2 = ::sqrt((double)mDriftMom2/mSumAdc - mDriftMom1*mDriftMom1); /*note no N/N-1*/
590  mAnodeMom2 = ::sqrt((double)mAnodeMom2/mSumAdc - mAnodeMom1*mAnodeMom1);
591  if (mDriftMom2>1000 || mDriftMom2<0 || mAnodeMom2>1000 || mAnodeMom2<0) /*calc fails occasionally*/
592  {
593  mDriftMom2 = -999; mAnodeMom2 = -999; mNeff = 0;
594  }
595 
596  if (mNeff>1) //the ones which are not are really bad
597  {
598  double Neff = (double) mSumAdc*mSumAdc/mNeff;
599  if (Neff>1.5) //make sure calc. does not mess up
600  {
601  mDriftMom2 = mDriftMom2 * ::sqrt( (double(mNeff)/(mNeff-1)) );
602  mAnodeMom2 = mAnodeMom2 * ::sqrt( (double(mNeff)/(mNeff-1)) );
603  if (mDriftMom2!=0) mY_err = 260.e-4*mDriftMom2/::sqrt(double(mNeff)); /*is 0 for 1 drift wonders. Units: cm*/
604  if (mAnodeMom2!=0) mX_err = 250.e-4*mAnodeMom2/::sqrt(double(mNeff)); /*is 0 for 1 anode wonders. Units: cm*/
605  }
606 
607  if (numAnodes==1 && mAnodeMom2==0) mAnodeMom2=0.288; //bin width/::sqrt(12)
608  if ( (GetLastTimeBin(clu)-GetFirstTimeBin(clu))==0 && mDriftMom2==0) mDriftMom2=0.288; //bin width/::sqrt(12)
609 
610  }
611  else
612  {
613  mHitId += 8;
614  mMom0 = -999.;
615  mDriftMom1 = -999.;
616  mAnodeMom1 = -999.;
617  mDriftMom2 = -999.;
618  mAnodeMom2 = -999.;
619  }
620  }
621 
622 }
623 
624 
625 void StSvtAnalysis::newCluster(int clu, int numAnodes, int igt3)
626 {
627 
628  int iQual, iRetu;
629  static int iRows=1, iCols=1;
630 
631  //These are all the objects used by the Maker to make the cluster object la mAux[clu].mCluID = clu; //unique ID
632  StSvtAnalysisAux *aux = mAux+clu;
633  aux->mCluDeconvID = clu; //at this point the origional cluster and deconv. one are the same
634  aux->mCluCharge = mMom0; //charge
635  //aux->mCluFlag = mHitId; // It will be filled later, so no need here. JT.
636  aux->m_oneortwo_flag = mMyflag; // added by JT.
637  aux->mMeanClusterTimeBin = mDriftMom1; //mean time
638  aux->mMeanClusterAnode = mAnodeMom1; //mean anode
639  aux->mSecondMomClusterTimeBin = mDriftMom2; //mean 2nd moment time
640  aux->mSecondMomClusterAnode = mAnodeMom2; //mean 2nd moment anode
641  aux->mCluXCov = 1.*mX_err*mX_err; //error in Anode
642  aux->mCluYCov = 4.*mY_err*mX_err; //error in Time is made arbitarily 2 time larger (4 time for cov). Check dist.
643  aux->mCluPeakAdc = mPeakADC; //peak ADC
644  aux->mCluNumPixels = mNumPixels; //number of pixels
645  aux->mCluNumAnodes = numAnodes; //number of anodes including loop backs.
646  aux->mHybridNum = m_hybIndex; //hybrid index.
647 
648 
649  for (int i1=0;i1<iRows;i1++) //be more clever in the futre but for now....
650  { //zero out previous box
651  for (int j1=0;j1<iCols;j1++)
652  {
653  m_Pixels[i1][j1] = 0; //used by deconvolution
654  m_Shadow[i1][j1] = 0;
655  }
656  }
657 
658 
659  //size of search area for deconvolution
660  iRows = mAux[clu].mCluLastAnode - mAux[clu].mCluFirstAnode +1+2; //+2 to account for 0 paddind around side
661  iCols = mAux[clu].mCluLastTimeBin - mAux[clu].mCluFirstTimeBin +1+2;
662 
663  Fill_Pixel_Array(clu); //Fill 2D array with ADC's. Easier for the search in this format.
664  iQual = CatagorizeCluster(iRows,iCols,igt3,clu); //Classify the cluster as good or bad.
665  mHitId += iQual; //Update previous classification
666  aux->mCluFlag = mHitId; //Set flag
667  if (mHitId==0 && m_deconv==1) iRetu = Deconvolve_Cluster(iRows, iCols, clu); //do the deconvolution only for some candidates
668 
669  if( (int)(.5+mAnodeMom1) > 0 && (int)(.5+mAnodeMom1) <= 241 )
670  m_countBadAn[m_hybIndex][(int)(.5+mAnodeMom1)]++; //count the noisy anodes and time for all hits whether good or bad
671  if( (int)(.5+mDriftMom1) >= 0 && (int)(.5+mDriftMom1) <= 128)
672  m_countBadTb[m_hybIndex][(int)(.5+mDriftMom1)]++; //invstigate this.
673 
674 
675  //cout<<"******* Moment Analysis finished *******"<<endl;
676 }
677 
678 
679 
680 int StSvtAnalysis:: CatagorizeCluster(int iRows, int iCols, int igt3, int clu)
681 /* Classify Cluster by topology */
682 //Calssify the clusters. Note everything is in base to to allow one to figure out many
683 //conditions simultaneously. Also not these might need fine tuning. I copied them over from
684 //what I saw in E896 but they might not be true in STAR. Also note that there are no crude
685 //cuts solely on peakAMP or Int. Charge. Sanjeev
686 {
687  int i, iUnderBkt, iWrgBkt;
688  float fThres;
689  int iQual=0;
690  int d_bkt=0, d_sig=0;
691  float fCut;
692  static int iNumCat = 0;
693  StSvtAnalysisAux *aux = mAux + clu;
694 
695  iNumCat++;
696  m_deconv = 0; //default is no deconvolution;
697 
698  // Check and change LASER cluster flag to 44. JT.
699  if ((m_hybIndex==293 && (mAnodeMom1>195 && mAnodeMom1<205) && (mDriftMom1>80 && mDriftMom1<100)) ||
700  (m_hybIndex==416 && (mAnodeMom1>195 && mAnodeMom1<203) && (mDriftMom1>85 && mDriftMom1<100)) ||
701  (m_hybIndex==416 && (mAnodeMom1>195 && mAnodeMom1<203) && (mDriftMom1>110 && mDriftMom1<125)) ) {
702  iQual=44;
703  return iQual;
704  }
705 
706  if (iCols >80) { // added by JT
707  iQual=17;
708  return iQual;
709  }
710 
711  if (aux->mCluNumAnodes ==1){ // added by JT
712  if(aux->mCluPeakAdc < 11) iQual = 11; // added by HC to remove noise hits
713  if(aux->mCluNumPixels >10) iQual = 10;
714  //if (aux->mMeanClusterTimeBin>30) iQual = 10;
715  }
716 
717  //
718  // Searches for secondary peaks, above my_noise variation.
719  // If it finds it, ir will return clus flag=13 or 15.
720  //
721  float my_noise=5;
722  int secondary_peak_after=0;
723  int secondary_peak_before=0;
724  int member_high_limit=0;
725  int member_low_limit=0;
726  for (int i1=0;i1<iRows;i1++){
727  member_high_limit=0;
728  member_low_limit=0;
729  for (int j1=m_col_p;j1<iCols-1;j1++){
730  if (m_Pixels[i1][j1+1] > (m_Pixels[i1][j1]+my_noise)) secondary_peak_after++;
731  }
732  for (int j2=m_col_p;j2>0;j2--){
733  if (m_Pixels[i1][j2-1] > (m_Pixels[i1][j2]+my_noise)) secondary_peak_before++;
734  }
735  }
736  if (secondary_peak_after>0) iQual=13;
737  if (secondary_peak_before>0) iQual=15;
738 
739  /*loop over central anode in time for undershoot*/
740  // iUnderBkt is the time index of when the undershoot starts in the central anode.
741  fThres = -0.03*(float)m_adc_p; // m_adc_p is the central anode pedoffset subtracted
742  iUnderBkt = 127; // if eq 0 or 61 then problem
743  i = m_col_p; /*NOTE SCG does not save much of the undershoot so*/
744  while (iUnderBkt==127 && i!=iCols-1) /*this is not so sensitive. Good for deconvolution*/
745  {
746  if ( (m_Pixels[m_row_p][i]+m_Pixels[m_row_p][i+1])/2. < fThres) iUnderBkt = i;
747  i++;
748  }
749 
750 
751  fThres = -0.3*(float)m_adc_p; /*now loop in wrong time direction for undershoot*/
752  iWrgBkt = 0;
753  i = m_col_p;
754  while (iWrgBkt==0 && i!=1)
755  {
756  if ( (m_Pixels[m_row_p][i]+m_Pixels[m_row_p][i-1])/2. < fThres) iWrgBkt = i;
757  i--;
758  }
759 
760  //Now figure out if we like these clusters.
761 
762  if (iWrgBkt>=1) { iQual += 16; m_nWrkBkt++;} // Undershoot in the wrong side
763  if (igt3<3 && (aux->mCluCharge<15 || aux->mCluNumPixels<4)) { iQual += 32; m_nGt8++; } // Cluster too small
764  if ((aux->mSecondMomClusterTimeBin>4*aux->mSecondMomClusterAnode &&
765  aux->mSecondMomClusterAnode <1 && aux->mSecondMomClusterAnode>0) ||
766  (aux->mSecondMomClusterAnode >4*aux->mSecondMomClusterTimeBin &&
767  aux->mSecondMomClusterTimeBin<1 && aux->mSecondMomClusterTimeBin>0) )
768  { iQual += 64; m_nSig++; }
769  //added by JT
770  if ( (aux->mSecondMomClusterTimeBin>6*aux->mSecondMomClusterAnode) ||
771  (aux->mSecondMomClusterAnode>6*aux->mSecondMomClusterTimeBin) )
772  { iQual += 65; m_nSig++; }
773 
774 
775  //look for deconvolution candidates
776 
777  if (iUnderBkt>m_col_p-2){ // From what I know, this condition is always true (JT) .
778  d_bkt = 1; //send to deconV
779  m_nUndBkt++; }
780 
781  fCut = fabs(1.15*aux->mSecondMomClusterTimeBin - aux->mSecondMomClusterAnode);
782  if ( (fCut<=0.5 && aux->mSecondMomClusterAnode<1.25 && aux->mSecondMomClusterTimeBin<1.25) ||
783  (aux->mSecondMomClusterAnode<0.5 && aux->mSecondMomClusterTimeBin<0.5))
784  d_sig = 0; //too lazy to do the inverse of the above
785  else
786  d_sig = 1;
787 
788  if (aux->mCluNumAnodes>1 && (d_sig==1 || (aux->mCluCharge>80 && d_bkt==1))) m_deconv = 1;
789  //if (aux->mCluNumAnodes>1 && (aux->mCluCharge>50 && d_bkt==1)) m_deconv = 1;
790  //if (aux->mCluCharge>50) m_deconv = 1;
791  //if (aux->mCluNumAnodes>1 && (d_sig==1)) m_deconv = 1;
792 
793  // if (iNumCat%50 == 1) cout<<"Wrong Clusters: iGt8: "<<m_nGt8<<" WrgBkt: "<<m_nWrkBkt<<" Sig: "<<m_nSig<<endl;
794 
795  return iQual;
796 
797 }
798 
799 /* Do the deconvolution */
800 
801 int StSvtAnalysis::Deconvolve_Cluster(int iRows, int iCols, int clu)
802 //Do the actual deconvolution here. We dont allow more than 10 peaks to be deconvluted. Sanjeev
803 {
804  POINT *Peaks;
805  int iNumPeaks = 0;
806  int iRetu = 0;
807 
808  //cout<<"Enter Deconvolve Cluster"<<endl;
809 
810  iNumPeaks = 0;
811  Peaks = Find_Peaks(iRows, iCols, &iNumPeaks); //search for valid peaks
812  if (Peaks==NULL) return 0;
813  if (iNumPeaks==0) iNumPeaks=1; /*Find Peak did not think the cluster was good but lets keep it anyway*/
814 
815  if (Peaks && iNumPeaks>1)
816  {
817  iRetu = Fit_Peaks(iRows, iCols, iNumPeaks, Peaks, clu); //fit the deconvoluted peaks and add to the end of the hit table
818  if (iRetu==0) return 0;
819  }
820 
821  return 1;
822  // cout<<"Exit Deconvolve Cluster"<<endl;
823 
824 }
825 
826 /*------------------------------------------------------------------
827 ROUTINE: POINT * Find_peaks
828 DESCRIPTION: find peaks within the local array
829 RETURN VALUE:
830 ------------------------------------------------------------------*/
831 POINT* StSvtAnalysis::Find_Peaks (int iRows, int iCols, int *iNumPeaks)
832 {
833  POINT *Array;
834  static POINT Peaks[10]; //only allow 10 peaks
835  int i, j, k;
836  float valley;
837 
838  Array = new POINT[(iRows+2) * (iCols+2)];
839  if (Array == NULL)
840  {
841  *iNumPeaks = 0;
842  return NULL;
843  }
844 
845  k = 0;
846  for (i=1; i<iRows-1; i++)
847  for (j=1; j<iCols-1; j++)
848  {
849  Array[k].x = i;
850  Array[k].y = j;
851  Array[k].val = m_Pixels[i][j];
852  Array[k].error = 1.;
853  k++;
854  }
855 
856  qsort (Array, k, sizeof (POINT), Compare_Point); //sort according to peak adc
857 
858  /* Now lets go find the peaks */
859 
860  *iNumPeaks = 0;
861  for (i = 0; i < k && *iNumPeaks <10; i++) //10 is the maximum number of peaks
862  {
863  int x = Array[i].x;
864  int y = Array[i].y;
865 
866  /*if (m_Shadow[x][y] == 0 && m_Pixels[x][y] > 10)*/
867  if (m_Shadow[x][y] == 0 && m_Pixels[x][y] > 6) //24 mV. This is the definition of a peak candidate
868  { //We use mShadow to block out areas already selected for a hit.
869  Peaks[*iNumPeaks].x = x;
870  Peaks[*iNumPeaks].y = y;
871  Peaks[*iNumPeaks].val = Array[i].val;
872  Peaks[*iNumPeaks].error = Array[i].error;
873  if ((valley=IsValidPeak (iRows, iCols, Peaks, *iNumPeaks))) //Is it a nicely seperated hit (based on peak/valley)
874  {
875  Peaks[*iNumPeaks].error = valley; //the error on the deconv. hits is proportional to how clean they
876  *iNumPeaks += 1; //are or how well seperated they are.
877  if (*iNumPeaks==2) Peaks[0].error = Peaks[1].error; /*make sure we change error on first peak*/
878  }
879  BlockOut (x, y);
880  }
881 
882  /* Make sure that these pixels never get used again */
883 
884  /*BlockOut ( x, y); moved up SUP*/
885  }
886 
887  delete[] Array;
888 
889  return Peaks;
890 
891 }
892 
893 /*------------------------------------------------------------------
894 ROUTINE: int Compare_Point
895 DESCRIPTION: evaluate the diff between two points
896 RETURN VALUE: the amplitude difference
897 ------------------------------------------------------------------*/
898 int Compare_Point ( const void *a, const void *b)
899 {
900  return (int)(static_cast<const POINT*>(b)->val - static_cast<const POINT*>(a)->val);
901 }
902 
903 /*------------------------------------------------------------------
904  ROUTINE: long IsValidPeak
905  DESCRIPTION: tries to determine if a candidate peak is a "real"
906  one. The cut is a peak-to-valley ratio cut. The p/v ratio is
907  determined between each candidate peak and
908  all previously-found peaks by walking the 2-D line between each
909  combination of peaks, looking for the 'valley' along the way.
910  If a candidate peak passes the p/v cut against all previous peaks
911  then it is accepted.
912  Changed the search path. Sanjeev 9/99
913  ARGUMENTS:
914  RETURN VALUE:
915  ------------------------------------------------------------------*/
916 float StSvtAnalysis::IsValidPeak(int iRows, int iCols, POINT *Peaks, int iNumPeaks)
917 {
918  int Px = Peaks[iNumPeaks].x, Py = Peaks[iNumPeaks].y, i;
919  float pval;
920  float val=0, peak=1, valley=0;
921  //float PEAK_TO_VALLEY = 2;
922 
923  for (i = 0; i < iNumPeaks; i++)
924  {
925  int dx, dy;
926  float fSlope;
927 
928  dx = Peaks[i].x - Px;
929  dy = Peaks[i].y - Py;
930 
931  if (dy != 0)
932  fSlope = (float) dx / (float) dy;
933  else
934  fSlope = 9999999.;
935 
936  peak = valley = val = (float) m_Pixels[Px][Py];
937 
938  //cout<<"Is valid peak: dx: "<<dx<<" dy: "<<dy<<" fslope: "<<fSlope<<" peak: "<<peak<<" Px: "<<Px<<" Py: "<<Py<<endl;
939 
940  /*for (; dx > 0; dx--)*/
941  while (dx!=0 || dy!=0)
942  {
943  if (dx!=0)
944  dy = (int)(dx /fSlope);
945  else
946  {
947  if (dy>0) dy--; if (dy<0) dy++;
948  }
949  val = m_Pixels[Px + dx][Py + dy];
950  //cout<<"is valid peak: loop dx: "<<dx<<" dy: "<<dy<<" val: "<<val<<endl;
951  if (val<valley && val!=0 && val!=1) valley = val; /*0 and 1 for dead anodes*/
952  if (dx>0) dx--;
953  if (dx<0) dx++;
954  }
955 
956  //cout<<"Is Valid Peak: valley: "<<valley<<endl;
957 
958  /*fRatio = (float) peak / (float) valley;
959  if (fRatio < PEAK_TO_VALLEY) return 0; */
960 
961  //Note we are quite conservative here. Or you could set this to 50% is you disagree. Sanjeev
962 
963  if (valley>0.75*peak) return 0; /*this must be true for all hits wrt each other*/
964  //if (valley>par->cuts[8]*peak) return 0;
965 
966  }
967 
968  //cout<<"IsValidPeak. Valley: "<<valley<<" Peak: "<<peak<<endl;
969 
970  //error set by looking at p/v
971 
972  pval = valley/peak;
973  if (pval<0.2)
974  pval=1;
975  else if (pval>=0.2 && pval<0.5)
976  pval=1.25;
977  else if (pval>=0.5)
978  pval=3*pval;
979 
980  return pval;
981 
982 }
983 
984 /*------------------------------------------------------------------
985  ROUTINE: long Fit_Peaks
986  DESCRIPTION: Fit the peaks in a merge configuration
987  ARGUMENTS:
988  RETURN VALUE:
989  ------------------------------------------------------------------*/
990 int StSvtAnalysis::Fit_Peaks(int iRows, int iCols, int iNumPeaks, POINT *Peaks, int clu)
991 //Fitthe deconv. clusters. Add them to the end of the cluster table
992 {
993  int i, j, k, iSum;
994  int iX, iY;
995  double fX, fY;
996  int iSum1;
997  float CovX, CovY;
998  float MomX, MomY;
999  int iFirstAnode, iFirstTime;
1000 
1001  mAux[clu].mCluFlag += 128; //Lets mark this cluster as being deconvoluted
1002 
1003  CovX = mAux[clu].mCluXCov; //use these for the deconv. Clusters
1004  CovY = mAux[clu].mCluYCov;
1005  MomX = mAux[clu].mSecondMomClusterAnode;
1006  MomY = mAux[clu].mSecondMomClusterTimeBin;
1007 
1008  iFirstAnode = mAux[clu].mCluFirstAnode-1; //need to knoe relative to where numbers
1009  iFirstTime = mAux[clu].mCluFirstTimeBin-1;
1010 
1011  for (i = 0; i < iNumPeaks; i++)
1012  {
1013  if (Peaks[i].x < 0 || Peaks[i].x > iRows) //sanity checks
1014  continue;
1015  if (Peaks[i].y < 0 || Peaks[i].y > iCols)
1016  continue;
1017 
1018  iSum1 = iSum = iX = iY = 0;
1019  for (j = Peaks[i].x - 1; j <= Peaks[i].x + 1; j++)
1020  {
1021  for (k = Peaks[i].y - 1; k <= Peaks[i].y + 1; k++)
1022  {
1023  iSum1 += m_Pixels[j][k];
1024  if (m_Pixels[j][k]>0)
1025  {
1026  iSum += m_Pixels[j][k];
1027  iX += (j) * m_Pixels[j][k];
1028  iY += (k) * m_Pixels[j][k];
1029  }
1030  }
1031  }
1032 
1033  if (iSum1 <=0) continue; /*Should hardly happen*/
1034 
1035  m_clu++;
1036  if (m_clu>mMaxClu) setMemory();
1037 
1038  fX = (double) iX / iSum;
1039  fY = (double) iY / iSum;
1040 
1041  mAux[m_clu].mCluID = m_clu; //new id gets put at end of hit table
1042  mAux[m_clu].mCluDeconvID = clu; //points to hit which was deconvoluted
1043  mAux[m_clu].mMeanClusterAnode = fX + iFirstAnode+0.5; /*so goes from 0-239 CHECK THIS!!!!!!!!*/
1044  mAux[m_clu].mMeanClusterTimeBin = fY + iFirstTime+0.5; /*so goes from 0-127*/
1045  mAux[m_clu].mCluPeakAdc = (int)Peaks[i].val; //peakADC
1046  mAux[m_clu].mCluCharge = iSum; //should not be used in de/dx
1047  mAux[m_clu].mCluFlag = 2; //says deconvoluted hit
1048  mAux[m_clu].mSecondMomClusterTimeBin = MomX; //Not really accuratly determined
1049  mAux[m_clu].mSecondMomClusterAnode = MomY; //Not really accuratly determined
1050 
1051  mAux[m_clu].mCluXCov = ::sqrt(2.)*CovX*Peaks[i].error; //errors based on origional error scaled by peak/valley
1052  mAux[m_clu].mCluYCov = ::sqrt(2.)*CovY*Peaks[i].error;
1053  mAux[m_clu].mCluNumPixels = 9999; //so dont mess up signal/noise calculation.
1054  mAux[m_clu].mCluNumAnodes = 9999; //ill defined for deconvolution
1055 
1056  //cout<<"In Deconvolute: x:" << mAux[m_clu].mMeanClusterAnode << " y: " << mAux[m_clu].mMeanClusterTimeBin
1057  // << " Peak: " << mCluPeakAdc[m_clu] << endl;
1058  //cout<<"_____________________________"<<endl<<endl;
1059 
1060  } //end loop over peaks
1061 
1062  return 1;
1063 }
1064 
1065 /*------------------------------------------------------------------
1066 ROUTINE: int BlockOut
1067 DESCRIPTION: mark pixel position as blocked
1068 RETURN VALUE: 0
1069 ------------------------------------------------------------------*/
1070 int StSvtAnalysis::BlockOut (int x, int y)
1071 //used in deconvolution to mask out areas already considered. Sanjeev
1072 {
1073  m_Shadow[x-1][y-1] = 1;
1074  m_Shadow[x-1][ y ] = 1;
1075  m_Shadow[x-1][y+1] = 1;
1076 
1077  m_Shadow[ x ][y-1] = 1;
1078  m_Shadow[ x ][ y ] = 1;
1079  m_Shadow[ x ][y+1] = 1;
1080 
1081  m_Shadow[x+1][y-1] = 1;
1082  m_Shadow[x+1][ y ] = 1;
1083  m_Shadow[x+1][y+1] = 1;
1084 
1085  return 0;
1086 }
1087 
1088 /*------------------------------------------------------------------
1089 ROUTINE: int **malloc_matrix
1090 DESCRIPTION: allocates memory for matrix to do deconvolution
1091 RETURN VALUE: pointer to the array
1092 ARGUMENTS: iRows, iCols : size of the array needed
1093 ------------------------------------------------------------------*/
1094 int** StSvtAnalysis::malloc_matrix_d (int iRows, int iCols)
1095 {
1096  int **Array = new int*[iRows];
1097  int *buf = new int[iRows*iCols];
1098  memset(buf,0,sizeof(int)*iRows*iCols);
1099  for (int i = 0; i < iRows; i++){Array[i] = buf; buf+=iCols;}
1100 
1101  return Array;
1102 }
1103 
1104 
1105 /*------------------------------------------------------------------
1106 ROUTINE: void free_matrix
1107 DESCRIPTION: deallocates memory used by matrix
1108 RETURN VALUE: none
1109 ARGUMENTS: *Array[] pointer to the array
1110 ARGUMENTS: iRows number of rows in the array
1111 ------------------------------------------------------------------*/
1112 
1113 void StSvtAnalysis::free_matrix_d (int *Array[], int )
1114 {
1115  delete [] Array[0];
1116  delete [] Array;
1117 }
1118 
1119 
1120 
1121 /*------------------------------------------------------------------
1122 ROUTINE: int Fill_Pixel_Array
1123 DESCRIPTION: fill the pixel array with ADC values
1124 RETURN VALUE: 0
1125 ------------------------------------------------------------------*/
1126 int StSvtAnalysis::Fill_Pixel_Array(int clu)
1127 //Fill a 2D array (m_Pixels[i][j]) with the cluster in question to be deconvoluted.
1128 // With pedestaloffset subtracted already
1129 {
1130  int listAn, mseq, actualAn, stTimeBin, len, Seq;
1131  unsigned char* adc;
1132  int iRow, iCol;
1133  int val;
1134 
1135  m_col_p = 0;
1136  m_row_p = 0;
1137  m_adc_p = 0; // ADC of the cluster PEAK, pedoffset subtracted
1138 
1139  mAux[clu].mInfo = mHybridCluster->getCluMemInfo(clu);
1140  mNumOfMembers = mHybridCluster->getNumberOfMembers(clu);
1141 
1142  //cout<<"in fill: number of anodes: "<<numAnodes<<endl;
1143 
1144  for(int mem = 0; mem < mNumOfMembers; mem++) //loop over anodes (can be same anode if curls!!)
1145  {
1146  listAn = mAux[clu].mInfo[mem].listAnode;
1147  mseq = mAux[clu].mInfo[mem].seq;
1148  actualAn = mAux[clu].mInfo[mem].actualAnode; //actual anode
1149 
1150  mHybridData->getListSequences(listAn,Seq,mSvtSequence);
1151  stTimeBin = mSvtSequence[mseq].startTimeBin;
1152  adc = mSvtSequence[mseq].firstAdc;
1153 
1154  len = mSvtSequence[mseq].length + 1-1;
1155  iRow = actualAn - mAux[clu].mCluFirstAnode + 1; //we pad the sides with 0 hence the -1
1156  iCol = stTimeBin - mAux[clu].mCluFirstTimeBin + 1;
1157 
1158  //cout << "Clu=" << clu<< " Irow=" << iRow << " Actual An=" << actualAn << " iCol=" << iCol << " stTimeBucket=" << stTimeBin << " and finally len=" << len << endl;
1159 
1160  for (int j=0; j<len; j++) {
1161  if (iRow<1 || iCol+j<1 || iRow>240 || iCol+j>128) {
1162  cout<<"Problem in Fill Pixel Array. iRow: " << iRow << " iCol: " << iCol+j<<endl;
1163  continue;
1164  }
1165  val = (int)adc[j];
1166  (val==0 || val==255) ? val=val : val=val-mPedOffset; // Note take off the Pedoffset
1167  m_Pixels[iRow][iCol+j] =val;
1168  if (val>m_adc_p) {
1169  m_adc_p=val;
1170  m_row_p=iRow;
1171  m_col_p=iCol+j;
1172  }
1173  }
1174  }
1175  return 1;
1176 }
1177 
1178 int StSvtAnalysis::FillRawAdc()
1179 //Get the raw adc data and fill a 2D array. Usefull if you want to look outside the found sequences
1180 {
1181  int* anodeList;
1182  int numAnodes,actualAn,numOfSeq,seqStart,seqLength;
1183  unsigned char* adc;
1184  StSequence* svtSequence;
1185  int ADC;
1186 
1187  //ofstream outFile("SvtHybAll_a.dat",ios::app);
1188  //if (m_hybIndex!=10 && m_hybIndex!=11)
1189  // outFile<<"Event # "<<m_SvtEvt<<" Hybrid #: "<<m_hybIndex<<endl;
1190 
1191  numAnodes = mHybridRawData->getAnodeList(anodeList);
1192  //cout<<"Raw number of anodes: "<<numAnodes<<endl;
1193 
1194 
1195  for(int an = 0; an < numAnodes; an++) {
1196  actualAn = anodeList[an];
1197  if( mSvtBadAnode)
1198  if(mSvtBadAnode->isBadAnode(actualAn)) continue; //Dont fill pixel array if anode is bad
1199  mHybridRawData->getListSequences(an,numOfSeq,svtSequence);
1200  for(int seq = 0; seq < numOfSeq; seq++) {
1201  seqStart = svtSequence[seq].startTimeBin;
1202  seqLength = svtSequence[seq].length;
1203  adc = svtSequence[seq].firstAdc;
1204  for (int j=0; j<seqLength; j++) {
1205  ADC = (int)adc[j];
1206  (ADC==0 || ADC==255) ? ADC=ADC : ADC=ADC-mPedOffset; //note subtract the PedOffset
1207  m_Raw[actualAn][seqStart+j] = ADC;
1208  //cout<<"Raw ADC: "<<actualAn<<" "<<seqStart+j<<" "<<ADC<<endl;
1209  /*
1210  if (m_hybIndex==417){
1211  cout << "RAW ADC = " << m_Raw[actualAn][seqStart+j] << " of anode " << actualAn << " and time bin " << seqStart+j << endl;
1212  }
1213  */
1214  //if (m_hybIndex!=10 && m_hybIndex!=11) outFile<<setw(4)<<ADC;
1215  }
1216  }
1217  //if (m_hybIndex!=10 && m_hybIndex!=11) outFile<<endl;
1218  }
1219 
1220  //outFile.close();
1221  return 1;
1222 }
1223 
1224 void StSvtAnalysis::ClearRawAdc()
1225 {
1226  for (int i1=0;i1<242;i1++) {
1227  for (int j1=0;j1<130;j1++) {
1228  m_Raw[i1][j1] = 0;
1229  }
1230  }
1231 }
1232 
1233 
1234 void StSvtAnalysis::SetBadAnTb(int nClus)
1235 //sets hot anodes and timebuckets if they have >4 hits/event.
1236 // coomneted out in StSVtClusteranalysismaker. JT.
1237 {
1238  int iHyb;
1239  int iAn, iTb;
1240 
1241  for (int i=0; i<nClus; i++) {
1242  iHyb = mAux[i].mHybridNum;
1243  iAn = (int)(.5+mAux[i].mMeanClusterAnode);
1244  iTb = (int)(.5+mAux[i].mMeanClusterTimeBin);
1245  if( iAn >=1 && iAn < 242){
1246  if (m_countBadAn[iHyb][iAn]>4) {mAux[i].mCluFlag += 4;}// cout<<"Hot Anodes: "<<iAn<<" Hyb: "<<iHyb<<endl;}
1247  }
1248  if( iTb >=0 && iTb < 129){
1249  if (m_countBadTb[iHyb][iTb]>4) {mAux[i].mCluFlag += 4;}//cout<<"Hot Time: "<<iTb<<" Hyb: "<<iHyb<<endl;}
1250  //if (iHyb==11) cout<<"Hot Stuff: "<<iAn<<" "<<m_countBadAn[iHyb][iAn]<<" "<<mCluFlag[i]<<endl;
1251  }
1252  }
1253 
1254 }
1255 
1256 void StSvtAnalysis::SetHybIndex(int index)
1257 {
1258  m_hybIndex = index;
1259 }
1260 
1261 int StSvtAnalysis::GetnSvtClu()
1262 {
1263  return m_clu;
1264 }
1265 
1266 int StSvtAnalysis::GetCluID(int clu)
1267 {
1268  return mAux[clu].mCluID;
1269 }
1270 
1271 int StSvtAnalysis::GetCluDeconvID(int clu)
1272 {
1273  return mAux[clu].mCluDeconvID;
1274 }
1275 
1276 int StSvtAnalysis::GetFirstAnode(int clu)
1277 {
1278 return mAux[clu].mCluFirstAnode;
1279 }
1280 
1281 int StSvtAnalysis::GetLastAnode(int clu)
1282 {
1283 return mAux[clu].mCluLastAnode;
1284 }
1285 
1286 int StSvtAnalysis::GetFirstTimeBin(int clu)
1287 {
1288 return mAux[clu].mCluFirstTimeBin;
1289 }
1290 
1291 int StSvtAnalysis::GetLastTimeBin(int clu)
1292 {
1293 return mAux[clu].mCluLastTimeBin;
1294 }
1295 
1296 
1297 int StSvtAnalysis::GetCluFlag(int clu)
1298 {
1299  return mAux[clu].mCluFlag;
1300 }
1301 
1302 double StSvtAnalysis::GetCluCharge(int clu)
1303 {
1304 return mAux[clu].mCluCharge;
1305 }
1306 
1307 int StSvtAnalysis::GetDeconvFlag(int clu)
1308 {
1309 return m_deconv;
1310 }
1311 
1312 double StSvtAnalysis::GetMeanClusterAnode(int clu)
1313 {
1314  return mAux[clu].mMeanClusterAnode;
1315 }
1316 
1317 double StSvtAnalysis::GetMeanClusterTimeBin(int clu)
1318 {
1319  return mAux[clu].mMeanClusterTimeBin;
1320 }
1321 
1322 double StSvtAnalysis::GetSecondMomClusterAnode(int clu)
1323 {
1324  return mAux[clu].mSecondMomClusterAnode;
1325 }
1326 
1327 double StSvtAnalysis::GetSecondMomClusterTimeBin(int clu)
1328 {
1329  return mAux[clu].mSecondMomClusterTimeBin;
1330 }
1331 
1332 double StSvtAnalysis::GetCluXCov(int clu)
1333 {
1334  return mAux[clu].mCluXCov;
1335 }
1336 
1337 double StSvtAnalysis::GetCluYCov(int clu)
1338 {
1339  return mAux[clu].mCluYCov;
1340 }
1341 
1342 int StSvtAnalysis::GetCluPeakAdc(int clu)
1343 {
1344  return mAux[clu].mCluPeakAdc;
1345 }
1346 
1347 int StSvtAnalysis::GetCluNumPixels(int clu)
1348 {
1349  return mAux[clu].mCluNumPixels;
1350 }
1351 
1352 int StSvtAnalysis::GetCluNumAnodes(int clu)
1353 {
1354  return mAux[clu].mCluNumAnodes;
1355 }
1356 
1357 int StSvtAnalysis::GetTruth(int clu)
1358 {
1359  return mAux[clu].mTruth;
1360 }
1361 int StSvtAnalysis::return_oneortwoanode_flag(int clu)
1362 {
1363  return mAux[clu].m_oneortwo_flag;
1364 }
1365 void StSvtAnalysis::updateTruth()
1366  // Calculate the first time bin in the cluster. Selemon
1367 {
1368  int status , nTru;
1369  int listAn = 0, mseq = 0, mem;
1370  StMCTruth *truList;
1371 
1372  for(int clu = 0; clu < mNumOfClusters; clu++)
1373  {
1374  StSvtAnalysisAux *aux = mAux+clu;
1375  if (!aux->mInfo) continue;
1376  mNumOfMembers = mHybridCluster->getNumberOfMembers(clu);
1377 
1378  mem = 0;
1379  StMCPivotTruth pivo(1);
1380  for(int j = 0; j< mNumOfMembers; j++){
1381  listAn = aux->mInfo[mem].listAnode;
1382  mseq = aux->mInfo[mem].seq;
1383  status = mHybridData->getListTruth(listAn,nTru,truList);
1384  if (!truList) return;
1385  pivo.Add(truList[mseq]);
1386  }
1387  aux->mTruth = int(pivo.Get());
1388  }
1389  }
1390 
1391