SDD injector analysis updated for operation at 20 MHz (F. Prino)
[u/mrichter/AliRoot.git] / ITS / AliITSOnlineSDDInjectors.cxx
1 /**************************************************************************
2  * Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15 #include "AliITSOnlineSDDInjectors.h"
16 #include <TH2F.h>
17 #include <TGraphErrors.h>
18 #include <TMath.h>
19
20 /* $Id$ */
21
22 ///////////////////////////////////////////////////////////////////
23 //                                                               //
24 // Implementation of the class used for SDD injector analysis    //
25 // Origin: F.Prino, Torino, prino@to.infn.it                     //
26 //                                                               //
27 ///////////////////////////////////////////////////////////////////
28
29 ClassImp(AliITSOnlineSDDInjectors)
30
31 const Float_t AliITSOnlineSDDInjectors::fgkSaturation = 1008.;
32 const Float_t AliITSOnlineSDDInjectors::fgkDefaultLThreshold = 5.;
33 const Float_t AliITSOnlineSDDInjectors::fgkDefaultHThreshold = 25.;
34 const Float_t AliITSOnlineSDDInjectors::fgkDefaultMinSpeed = 5.5;
35 const Float_t AliITSOnlineSDDInjectors::fgkDefaultMaxSpeed = 9.0;
36 const Float_t AliITSOnlineSDDInjectors::fgkDefaultMaxErr = 1.5;
37 const Int_t   AliITSOnlineSDDInjectors::fgkDefaultPolOrder = 3;
38 const Float_t AliITSOnlineSDDInjectors::fgkDefaultTimeStep = 50.;
39 const UShort_t AliITSOnlineSDDInjectors::fgkDefaultTbMin[kInjLines] = {10,50,100};
40 const UShort_t AliITSOnlineSDDInjectors::fgkDefaultTbMax[kInjLines] = {20,70,120};
41
42 //______________________________________________________________________
43 AliITSOnlineSDDInjectors::AliITSOnlineSDDInjectors():AliITSOnlineSDD(),fHisto(),fTbZero(0.),fParam(),fPolOrder(0),fMinDriftSpeed(0.),fMaxDriftSpeed(0.),fMaxDriftSpeedErr(0.),fLowThreshold(0.),fHighThreshold(0.),fFirstPadForFit(0),fLastPadForFit(0),fPadStatusCutForFit(0),fTimeStep(0.)
44 {
45   // default constructor
46   SetPositions();
47   SetDefaults();
48   SetTimeStep(fgkDefaultTimeStep);
49 }
50 //______________________________________________________________________
51 AliITSOnlineSDDInjectors::AliITSOnlineSDDInjectors(Int_t nddl, Int_t ncarlos, Int_t sid):AliITSOnlineSDD(nddl,ncarlos,sid),fHisto(),fTbZero(0.),fParam(),fPolOrder(0),fMinDriftSpeed(0.),fMaxDriftSpeed(0.),fMaxDriftSpeedErr(0.),fLowThreshold(0.),fHighThreshold(0.),fFirstPadForFit(0),fLastPadForFit(0),fPadStatusCutForFit(0),fTimeStep(0.)
52
53 // standard constructor
54   SetPositions();
55   SetDefaults();
56   SetTimeStep(fgkDefaultTimeStep);
57 }
58 //______________________________________________________________________
59 AliITSOnlineSDDInjectors::~AliITSOnlineSDDInjectors(){
60   // Destructor
61   // fHisto should not be deleted here because it points to an histo created 
62   // by the external code which calls the method AnalyzeEvent
63   // if(fHisto) delete fHisto;  
64   if(fParam) delete [] fParam;
65 }
66 //______________________________________________________________________
67 void AliITSOnlineSDDInjectors::SetDefaults(){
68   for(Int_t i=0;i<kInjLines;i++) 
69     SetInjLineRange(i,fgkDefaultTbMin[i],fgkDefaultTbMax[i]);
70   SetThresholds(fgkDefaultLThreshold,fgkDefaultHThreshold);
71   SetPolOrder(fgkDefaultPolOrder);
72   SetMinDriftSpeed(fgkDefaultMinSpeed);
73   SetMaxDriftSpeed(fgkDefaultMaxSpeed);
74   SetMaxDriftSpeedErr(fgkDefaultMaxErr);
75   SetFitLimits(1,kInjPads-2); // exclude first and last pad
76   SetPadStatusCutForFit();
77 }
78 //______________________________________________________________________
79 void AliITSOnlineSDDInjectors::SetPositions(){
80   // 
81   Float_t xLinFromCenterUm[kInjLines]={31860.,17460.,660.};
82   Float_t xAnodeFromCenterUm=35085;
83   for(Int_t i=0;i<kInjLines;i++){
84     fPosition[i]=xAnodeFromCenterUm-xLinFromCenterUm[i];
85     fPosition[i]/=10000.; // from microns to cm
86   }
87 }
88 //______________________________________________________________________
89 void AliITSOnlineSDDInjectors::Reset(){
90   //
91   for(Int_t i=0;i<kInjPads;i++){ 
92     fDriftSpeed[i]=0.;
93     fDriftSpeedErr[i]=0.;
94   }
95   for(Int_t i=0;i<kInjPads;i++){
96     for(Int_t j=0;j<kInjLines;j++){
97       fGoodInj[i][j]=0;
98       fCentroid[i][j]=0.;
99       fRMSCentroid[i][j]=0.;
100     }
101   }
102 }
103 //______________________________________________________________________
104 void AliITSOnlineSDDInjectors::AnalyzeEvent(TH2F* his){
105   //
106   Reset();
107   fHisto=his;
108   FindGoodInjectors();
109   FindCentroids();
110   CalcTimeBinZero();
111   for(Int_t j=0;j<kInjPads;j++) CalcDriftSpeed(j);
112   FitDriftSpeedVsAnode();
113 }
114 //______________________________________________________________________
115 TGraphErrors* AliITSOnlineSDDInjectors::GetTimeVsDistGraph(Int_t jpad) const{
116   // 
117   const Int_t kPts=kInjLines+1;
118   Float_t x[kPts],y[kPts],ex[kPts],ey[kPts];
119   x[0]=0.;
120   ex[0]=0.;
121   y[0]=fTbZero;
122   ey[0]=0.;
123   for(Int_t i=0;i<kInjLines;i++){
124     x[i+1]=fPosition[i];
125     ex[i+1]=0.;
126     y[i+1]=fCentroid[jpad][i];
127     ey[i+1]=fRMSCentroid[jpad][i];
128   }
129   TGraphErrors *g=new TGraphErrors(4,x,y,ex,ey);
130   return g;
131 }
132
133 //______________________________________________________________________
134 TGraphErrors* AliITSOnlineSDDInjectors::GetDriftSpeedGraph() const{
135   // 
136   Int_t ipt=0;
137   TGraphErrors *g=new TGraphErrors(0);
138   for(Int_t i=0;i<kInjPads;i++){
139     if(fDriftSpeed[i]>0){ 
140       g->SetPoint(ipt,GetAnodeNumber(i),fDriftSpeed[i]);
141       g->SetPointError(ipt,0,fDriftSpeedErr[i]);
142       ipt++;
143     }
144   }
145   return g;
146 }
147 //______________________________________________________________________
148 TGraphErrors* AliITSOnlineSDDInjectors::GetSelectedDriftSpeedGraph(Int_t minAcceptStatus) const{
149   // TGraphErrors with only pads with status of injector >= minAcceptStatus
150   Int_t ipt=0;
151   TGraphErrors *g=new TGraphErrors(0);
152   for(Int_t i=0;i<kInjPads;i++){
153     Int_t padStatus = GetInjPadStatus(i);
154     if(fDriftSpeed[i]>0 && padStatus >= minAcceptStatus ){
155       g->SetPoint(ipt,GetAnodeNumber(i),fDriftSpeed[i]);
156       g->SetPointError(ipt,0,fDriftSpeedErr[i]);
157       ipt++;
158     }
159   }
160   return g;
161 }
162 //______________________________________________________________________
163 void AliITSOnlineSDDInjectors::CalcTimeBinZero(){
164   //
165   Float_t tzero=0.,intCont=0.;
166   for(Int_t ian=0;ian<fgkNAnodes;ian++){
167     for(Int_t itb=1;itb<fTbMin[0];itb++){
168       Float_t cont=fHisto->GetBinContent(itb,ian+1);
169       if(cont>fLowThreshold){
170         tzero+=cont*float(itb);
171         intCont+=cont;
172       }
173     }
174   }
175   if(intCont>0) fTbZero=tzero/intCont;
176 }
177 //______________________________________________________________________
178 void AliITSOnlineSDDInjectors::FitDriftSpeedVsAnode(){
179   // fits the anode dependence of drift speed with a polynomial function
180   const Int_t kNn=fPolOrder+1;
181   Float_t **mat = new Float_t*[kNn];
182   for(Int_t i=0; i < kNn; i++) mat[i] = new Float_t[kNn];
183   Float_t *vect = new Float_t[kNn];
184
185   for(Int_t k1=0;k1<kNn;k1++){
186     vect[k1]=0;
187     for(Int_t k2=0;k2<kNn;k2++){
188       mat[k1][k2]=0;
189     }
190   }
191   Int_t npts = 0;
192   for(Int_t k1=0;k1<kNn;k1++){
193     for(Int_t jpad=fFirstPadForFit; jpad<=fLastPadForFit; jpad++){
194       Float_t x=(Float_t)GetAnodeNumber(jpad);
195       if(fDriftSpeed[jpad]>0 && GetInjPadStatus(jpad)>fPadStatusCutForFit){
196           vect[k1]+=fDriftSpeed[jpad]*TMath::Power(x,k1)/TMath::Power(fDriftSpeedErr[jpad],2);  
197           if(k1==0) npts++;
198           for(Int_t k2=0;k2<kNn;k2++){
199             mat[k1][k2]+=TMath::Power(x,k1+k2)/TMath::Power(fDriftSpeedErr[jpad],2);
200           }
201       }
202     }
203   }
204   if(npts<fPolOrder+1){ 
205     if(fParam) delete [] fParam;
206     fParam=new Float_t[kNn];
207     for(Int_t i=0; i<kNn;i++)fParam[i]=0;
208   }else{
209     Int_t *iPivot = new Int_t[kNn];
210     Int_t *indxR = new Int_t[kNn];
211     Int_t *indxC = new Int_t[kNn];
212     for(Int_t i=0;i<kNn;i++) iPivot[i]=0;
213     Int_t iCol=-1,iRow=-1;
214     for(Int_t i=0;i<kNn;i++){
215       Float_t big=0.;
216       for(Int_t j=0;j<kNn;j++){
217         if(iPivot[j]!=1){
218           for(Int_t k=0;k<kNn;k++){
219             if(iPivot[k]==0){
220               if(TMath::Abs(mat[j][k])>=big){
221                 big=TMath::Abs(mat[j][k]);
222                 iRow=j;
223                 iCol=k;
224               }
225             }
226           }
227         }
228       }
229       iPivot[iCol]++;
230       Float_t aux;
231       if(iRow!=iCol){
232         for(Int_t l=0;l<kNn;l++){
233           aux=mat[iRow][l];
234           mat[iRow][l]=mat[iCol][l];
235           mat[iCol][l]=aux;
236         }
237         aux=vect[iRow];
238         vect[iRow]=vect[iCol];
239         vect[iCol]=aux;
240       }
241       indxR[i]=iRow;
242       indxC[i]=iCol;
243       if(mat[iCol][iCol]==0) break;
244       Float_t pivinv=1./mat[iCol][iCol];
245       mat[iCol][iCol]=1;
246       for(Int_t l=0;l<kNn;l++) mat[iCol][l]*=pivinv;
247       vect[iCol]*=pivinv;
248       for(Int_t m=0;m<kNn;m++){
249         if(m!=iCol){
250           aux=mat[m][iCol];
251           mat[m][iCol]=0;
252           for(Int_t n=0;n<kNn;n++) mat[m][n]-=mat[iCol][n]*aux;
253           vect[m]-=vect[iCol]*aux;
254         }
255       }    
256     }
257     delete [] iPivot;
258     delete [] indxR;
259     delete [] indxC;
260     
261   
262     if(fParam) delete [] fParam;
263     fParam=new Float_t[kNn];
264     for(Int_t i=0; i<kNn;i++)fParam[i]=vect[i];
265   }
266
267   for(Int_t i=0; i < kNn; i++) delete [] mat[i];
268   delete [] mat;
269   delete [] vect;
270 }
271 //______________________________________________________________________
272 void AliITSOnlineSDDInjectors::CalcDriftSpeed(Int_t jpad){
273   // 
274   Float_t sumY=0,sumX=0,sumXX=0,sumYY=0.,sumXY=0,sumWEI=0.;
275   Int_t npt=0;
276   Float_t y[kInjLines],ey[kInjLines];
277   Float_t tzero=0,erry=0;
278   for(Int_t i=0;i<kInjLines;i++){ 
279     y[i]=fCentroid[jpad][i];
280     ey[i]=fRMSCentroid[jpad][i];
281   }
282   for(Int_t i=0;i<kInjLines;i++){
283     if(fGoodInj[jpad][i] && ey[i]!=0){
284       sumY+=y[i]/ey[i]/ey[i];
285       sumX+=fPosition[i]/ey[i]/ey[i];
286       sumXX+=fPosition[i]*fPosition[i]/ey[i]/ey[i];
287       sumYY+=y[i]*y[i]/ey[i]/ey[i];
288       sumXY+=fPosition[i]*y[i]/ey[i]/ey[i];
289       sumWEI+=1./ey[i]/ey[i];
290       tzero=fTbZero/ey[i]/ey[i];
291       erry=ey[i];
292       npt++;
293     }
294   }
295   Float_t vel=0,evel=0;
296   if(npt>1){ 
297     Float_t slope=(sumWEI*sumXY-sumY*sumX)/(sumWEI*sumXX-sumX*sumX);
298     Float_t eslope=TMath::Sqrt(sumWEI/(sumWEI*sumXX-sumX*sumX));
299     if(slope!=0 && fTimeStep>0.){
300       vel=1./slope*10000./fTimeStep;// micron/ns
301       evel=eslope/slope/slope*10000./fTimeStep;// micron/ns
302     }
303   }
304   if(npt==1){
305     Float_t slope=(sumY-tzero)/sumX;
306     Float_t eslope=erry/sumX;
307     if(slope!=0 && fTimeStep>0.){
308       vel=1./slope*10000./fTimeStep;// micron/ns    
309       evel=eslope/slope/slope*10000./fTimeStep;// micron/ns
310     }
311   }
312   if(vel>fMaxDriftSpeed||vel<fMinDriftSpeed || evel>fMaxDriftSpeedErr){ 
313     vel=0.;
314     evel=0.;
315   }
316   fDriftSpeed[jpad]=vel;
317   fDriftSpeedErr[jpad]=evel;
318 }
319 //______________________________________________________________________
320 Int_t AliITSOnlineSDDInjectors::GetAnodeNumber(Int_t iInjPad) const{
321   // Injectors location along anodes:
322   // Side left  (UP)   - channel 0: injectors on anodes 0,7,15,...,247,255 
323   // Side right (DOWN) - channel 1: injectors on anodes 0,8,16,...,248,255 
324   Int_t ian=-1;
325   if(iInjPad>=kInjPads) return ian;
326   if(fSide==1){  // right side
327     ian=iInjPad*8;
328     if(iInjPad==32) ian--;
329   }else{         // left side
330     ian=iInjPad*8-1;
331     if(iInjPad==0) ian=0;
332   }
333   return ian;
334 }
335 //______________________________________________________________________
336 Int_t AliITSOnlineSDDInjectors::GetInjPadNumberFromAnode(Int_t nAnode) const{
337   //
338   Int_t iInjPad=-1;
339   if(fSide==1){  // right side
340     if(nAnode%8==0) iInjPad=nAnode/8;
341     if(nAnode==255) iInjPad=32;
342   }else{         // left side
343     if(nAnode%8==7) iInjPad=1+nAnode/8;
344     if(nAnode==0) iInjPad=0;
345   }
346   if(nAnode>=256) iInjPad=-1;
347   return iInjPad;
348 }
349 //______________________________________________________________________
350 Int_t AliITSOnlineSDDInjectors::GetInjPadStatus(Int_t jpad) const{
351   // returns an integer value with status of injector lines for given pad/anode
352   // status=7  -->  111  all injector are good
353   // status=6  -->  110  1st line (close to anodes) is bad, other two are good
354   // ....
355   // status=1  -->  001  only 1st line (close to anodes) good
356   // status=0  -->  000  all lines are bad
357   Int_t istatus=0;
358   if(jpad>=0 && jpad<kInjPads){
359     for(Int_t jlin=0;jlin<kInjLines;jlin++) istatus+=fGoodInj[jpad][jlin]<<jlin;
360   }
361   return istatus;
362 }
363 //______________________________________________________________________
364 void AliITSOnlineSDDInjectors::FindGoodInjectors(){
365   // 
366   for(Int_t jpad=0;jpad<kInjPads;jpad++){
367     Int_t ian=GetAnodeNumber(jpad);
368     for(Int_t jlin=0;jlin<kInjLines;jlin++){
369       for(Int_t jjj=fTbMin[jlin];jjj<fTbMax[jlin];jjj++){
370         Float_t c1=fHisto->GetBinContent(jjj,ian+1);
371         Float_t c2=fHisto->GetBinContent(jjj+1,ian+1);
372         Float_t c3=fHisto->GetBinContent(jjj+2,ian+1);
373         if(c1>fLowThreshold && c2>fHighThreshold && c3>fLowThreshold){ 
374           fGoodInj[jpad][jlin]=1;
375           break;
376         }
377       }
378     }
379   }
380 }
381 //______________________________________________________________________
382 void AliITSOnlineSDDInjectors::FindCentroids(){
383   // 
384   for(Int_t jpad=0;jpad<kInjPads;jpad++){
385     Int_t ian=GetAnodeNumber(jpad);
386     for(Int_t jlin=0;jlin<kInjLines;jlin++){
387       if(!fGoodInj[jpad][jlin]) continue;
388       Float_t maxcont=0;
389       Int_t ilmax=-1;
390       for(Int_t jjj=fTbMin[jlin];jjj<fTbMax[jlin];jjj++){
391         Float_t cont=fHisto->GetBinContent(jjj,ian+1);
392         if(cont>maxcont){
393           maxcont=cont;
394           ilmax=jjj;
395         }
396       }
397       Float_t intCont=0;
398       Int_t jjj=ilmax;
399       while(1){
400         Float_t cont=fHisto->GetBinContent(jjj,ian+1);
401         if(cont<fLowThreshold) break;
402         if(cont<fgkSaturation){
403           fCentroid[jpad][jlin]+=cont*(Float_t)jjj;
404           fRMSCentroid[jpad][jlin]+=cont*TMath::Power((Float_t)jjj,2);
405           intCont+=cont;
406         }
407         jjj--;
408       }
409       jjj=ilmax+1;
410       while(1){
411         Float_t cont=fHisto->GetBinContent(jjj,ian+1);
412         if(cont<fLowThreshold) break;
413         if(cont<fgkSaturation){
414           fCentroid[jpad][jlin]+=cont*float(jjj);
415           fRMSCentroid[jpad][jlin]+=cont*TMath::Power((Float_t)jjj,2);
416           intCont+=cont;
417         }
418         jjj++;
419       }
420       if(intCont>0){ 
421         fCentroid[jpad][jlin]/=intCont;
422         fRMSCentroid[jpad][jlin]=TMath::Sqrt(fRMSCentroid[jpad][jlin]/intCont-fCentroid[jpad][jlin]*fCentroid[jpad][jlin]);
423       }
424       else{ 
425         fCentroid[jpad][jlin]=0.;
426         fRMSCentroid[jpad][jlin]=0.;
427         fGoodInj[jpad][jlin]=0;
428       }
429       if(fRMSCentroid[jpad][jlin]==0) fGoodInj[jpad][jlin]=0;
430     }
431   }
432 }
433 //______________________________________________________________________
434 void AliITSOnlineSDDInjectors::PrintInjectorStatus(){
435   //
436   for(Int_t jpad=0;jpad<kInjPads;jpad++){
437     printf("Line%d-Anode%d: %d %d %d\n",jpad,GetAnodeNumber(jpad),fGoodInj[jpad][0],fGoodInj[jpad][1],fGoodInj[jpad][2]);
438   }
439 }
440 //______________________________________________________________________
441 void AliITSOnlineSDDInjectors::PrintCentroids(){
442   //
443   for(Int_t jpad=0;jpad<kInjPads;jpad++){
444     printf("Line%d-Anode%d: %f+-%f %f+-%f %f+-%f\n",jpad,GetAnodeNumber(jpad),fCentroid[jpad][0],fRMSCentroid[jpad][0],fCentroid[jpad][1],fRMSCentroid[jpad][1],fCentroid[jpad][2],fRMSCentroid[jpad][2]);
445   }
446 }
447 //______________________________________________________________________
448 void AliITSOnlineSDDInjectors::WriteToASCII(Int_t evNumb, UInt_t timeStamp, Int_t optAppend){
449   //
450   Char_t outfilnam[100];
451   sprintf(outfilnam,"SDDinj_ddl%02dc%02d_sid%d.data",fDDL,fCarlos,fSide);  
452   FILE* outf;
453   if(optAppend==0){ 
454     outf=fopen(outfilnam,"w");
455     fprintf(outf,"%d\n",fPolOrder);
456   }
457   else outf=fopen(outfilnam,"a");
458   fprintf(outf,"%d   %d   ",evNumb,timeStamp);
459   for(Int_t ic=0;ic<fPolOrder+1;ic++){
460     fprintf(outf,"%G ",fParam[ic]);
461   }
462   fprintf(outf,"\n");
463   fclose(outf);  
464 }