]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ITS/AliITSOnlineSDDInjectors.cxx
From P. Gonzales: Adding Dalitz task, updates accordingly
[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 <TFile.h>
16 #include "AliITSOnlineSDDInjectors.h"
17 #include "AliLog.h"
18 #include <TH2F.h>
19 #include <TF1.h>
20 #include <TGraphErrors.h>
21 #include <TMath.h>
22
23 /* $Id$ */
24
25 ///////////////////////////////////////////////////////////////////
26 //                                                               //
27 // Implementation of the class used for SDD injector analysis    //
28 // Origin: F.Prino, Torino, prino@to.infn.it                     //
29 //                                                               //
30 ///////////////////////////////////////////////////////////////////
31
32 ClassImp(AliITSOnlineSDDInjectors)
33
34 const Float_t AliITSOnlineSDDInjectors::fgkSaturation = 1008.;
35 const Float_t AliITSOnlineSDDInjectors::fgkDefaultLThreshold = 5.;
36 const Float_t AliITSOnlineSDDInjectors::fgkDefaultHThreshold = 25.;
37 const Float_t AliITSOnlineSDDInjectors::fgkDefaultMinSpeed = 5.5;
38 const Float_t AliITSOnlineSDDInjectors::fgkDefaultMaxSpeed = 9.0;
39 const Float_t AliITSOnlineSDDInjectors::fgkDefaultMaxErr = 1.5;
40 const Int_t   AliITSOnlineSDDInjectors::fgkDefaultPolDegree = 3;
41 const Float_t AliITSOnlineSDDInjectors::fgkDefaultTimeStep = 50.;
42 const UShort_t AliITSOnlineSDDInjectors::fgkDefaultTbMin[kInjLines] = {10,50,100};
43 const UShort_t AliITSOnlineSDDInjectors::fgkDefaultTbMax[kInjLines] = {20,70,120};
44
45 //______________________________________________________________________
46 AliITSOnlineSDDInjectors::AliITSOnlineSDDInjectors():AliITSOnlineSDD(),fHisto(),fTbZero(0.),fRMSTbZero(0.),fNEvents(0),fParam(),fPolDegree(0),fActualPolDegree(0),fMinDriftSpeed(0.),fMaxDriftSpeed(0.),fMaxDriftSpeedErr(0.),fLowThreshold(0.),fHighThreshold(0.),fFirstPadForFit(0),fLastPadForFit(0),fPadStatusCutForFit(0),fTimeStep(0.),fUseTimeZeroSignal(kFALSE)
47 {
48   // default constructor
49   SetPositions();
50   SetDefaults();
51   SetTimeStep(fgkDefaultTimeStep);
52 }
53 //______________________________________________________________________
54 AliITSOnlineSDDInjectors::AliITSOnlineSDDInjectors(Int_t nddl, Int_t ncarlos, Int_t sid):AliITSOnlineSDD(nddl,ncarlos,sid),fHisto(),fTbZero(0.),fRMSTbZero(0.),fNEvents(0),fParam(),fPolDegree(0),fActualPolDegree(0),fMinDriftSpeed(0.),fMaxDriftSpeed(0.),fMaxDriftSpeedErr(0.),fLowThreshold(0.),fHighThreshold(0.),fFirstPadForFit(0),fLastPadForFit(0),fPadStatusCutForFit(0),fTimeStep(0.),fUseTimeZeroSignal(kFALSE)
55
56 // standard constructor
57   SetPositions();
58   SetDefaults();
59   SetTimeStep(fgkDefaultTimeStep);
60 }
61 //______________________________________________________________________
62 AliITSOnlineSDDInjectors::~AliITSOnlineSDDInjectors(){
63   // Destructor
64   // fHisto should not be deleted here because it points to an histo created 
65   // by the external code which calls the method AnalyzeEvent
66   // if(fHisto) delete fHisto;  
67   if(fParam) delete [] fParam;
68 }
69 //______________________________________________________________________
70 void AliITSOnlineSDDInjectors::SetDefaults(){
71   for(Int_t i=0;i<kInjLines;i++) {
72     SetInjLineRange(i,fgkDefaultTbMin[i],fgkDefaultTbMax[i]);
73     SetUseLine(i,kTRUE);
74   }
75   SetThresholds(fgkDefaultLThreshold,fgkDefaultHThreshold);
76   SetPolDegree(fgkDefaultPolDegree);
77   SetMinDriftSpeed(fgkDefaultMinSpeed);
78   SetMaxDriftSpeed(fgkDefaultMaxSpeed);
79   SetMaxDriftSpeedErr(fgkDefaultMaxErr);
80   SetFitLimits(1,kInjPads-2); // exclude first and last pad
81   SetPadStatusCutForFit();
82 }
83 //______________________________________________________________________
84 void AliITSOnlineSDDInjectors::SetPositions(){
85   // 
86   Double_t xLinFromCenterUm[kInjLines]={31860.,17460.,660.};
87   Double_t xAnodeFromCenterUm=35085;
88   for(Int_t i=0;i<kInjLines;i++){
89     fPosition[i]=xAnodeFromCenterUm-xLinFromCenterUm[i];
90     fPosition[i]/=10000.; // from microns to cm
91   }
92 }
93 //______________________________________________________________________
94 void AliITSOnlineSDDInjectors::Reset(){
95   //
96   for(Int_t i=0;i<kInjPads;i++){ 
97     fDriftSpeed[i]=0.;
98     fDriftSpeedErr[i]=0.;
99   }
100   for(Int_t i=0;i<kInjPads;i++){
101     for(Int_t j=0;j<kInjLines;j++){
102       fGoodInj[i][j]=0;
103       fCentroid[i][j]=0.;
104       fRMSCentroid[i][j]=0.;
105     }
106   }
107 }
108 //______________________________________________________________________
109 void AliITSOnlineSDDInjectors::AnalyzeEvent(TH2F* his){
110   //
111   AddEvent(his);
112   FitDriftSpeedVsAnode();
113 }
114 //______________________________________________________________________
115 void AliITSOnlineSDDInjectors::AddEvent(TH2F* his){
116   // Add the drift speed from current event to the average value
117   if(fNEvents==0){
118     for(Int_t i=0;i<kInjPads;i++){ 
119       fSumDriftSpeed[i]=0.;
120       fSumSqDriftSpeed[i]=0.;
121       fSumPadStatus[i]=0;
122       fSumPadStatusCut[i]=0;
123       fNEventsInPad[i]=0;
124     }
125   }
126   Reset();
127   fHisto=his;
128   FindGoodInjectors();
129   FindCentroids();
130   CalcTimeBinZero();
131   for(Int_t j=0;j<kInjPads;j++){ 
132     CalcDriftSpeed(j);
133     Int_t padStatus=GetInjPadStatus(j);
134     fSumPadStatus[j]+=padStatus;
135     if(padStatus>fPadStatusCutForFit){
136       fSumDriftSpeed[j]+=fDriftSpeed[j];
137       fSumSqDriftSpeed[j]+=fDriftSpeed[j]*fDriftSpeed[j];
138       fSumPadStatusCut[j]+=padStatus;
139       fNEventsInPad[j]++;
140     }
141   }
142   ++fNEvents;
143 }
144 //______________________________________________________________________
145 Double_t AliITSOnlineSDDInjectors::GetRMSDriftSpeed(Int_t ipad) const {
146   // 
147   if(fNEventsInPad[ipad]<=1) return 0.;
148   Double_t mean=fSumDriftSpeed[ipad]/(Double_t)fNEventsInPad[ipad];
149   Double_t diff=fSumSqDriftSpeed[ipad]/(Double_t)fNEventsInPad[ipad]-mean*mean;
150   if(diff<0.) diff=0.;
151   return TMath::Sqrt(diff);
152 }
153
154 //______________________________________________________________________
155 void AliITSOnlineSDDInjectors::FitMeanDriftSpeedVsAnode(){
156   // Calculates
157   if(fNEvents==0) return;
158   for(Int_t i=0;i<kInjPads;i++){ 
159     fDriftSpeed[i]=GetMeanDriftSpeed(i);
160     Int_t padStatusCut=(Int_t)(GetMeanPadStatusCut(i)+0.5);
161     for(Int_t ilin=0; ilin<kInjLines ; ilin++) fGoodInj[i][ilin]=(padStatusCut&1<<ilin)>>ilin;
162     if(fNEventsInPad[i]>1){
163       Double_t rms=GetRMSDriftSpeed(i);
164       if(rms>0.) fDriftSpeedErr[i]=rms/TMath::Sqrt(fNEventsInPad[i]);
165     }else{
166       for(Int_t ilin=0; ilin<kInjLines ; ilin++) fGoodInj[i][ilin]=0;
167     }
168   }
169   FitDriftSpeedVsAnode();
170   for(Int_t i=0;i<kInjPads;i++){ 
171     Int_t padStatus=(Int_t)(GetMeanPadStatusCut(i)+0.5);
172     for(Int_t ilin=0; ilin<kInjLines ; ilin++) fGoodInj[i][ilin]=(padStatus&1<<ilin)>>ilin;
173   }
174 }
175 //______________________________________________________________________
176 TGraphErrors* AliITSOnlineSDDInjectors::GetTimeVsDistGraph(Int_t jpad) const{
177   // 
178   const Int_t kPts=kInjLines+1;
179   Float_t x[kPts],y[kPts],ex[kPts],ey[kPts];
180   x[0]=0.;
181   ex[0]=0.;
182   y[0]=fTbZero;
183   ey[0]=0.;
184   for(Int_t i=0;i<kInjLines;i++){
185     x[i+1]=fPosition[i];
186     ex[i+1]=0.;
187     y[i+1]=fCentroid[jpad][i];
188     ey[i+1]=fRMSCentroid[jpad][i];
189   }
190   TGraphErrors *g=new TGraphErrors(4,x,y,ex,ey);
191   return g;
192 }
193
194 //______________________________________________________________________
195 TGraphErrors* AliITSOnlineSDDInjectors::GetDriftSpeedGraph() const{
196   // 
197   Int_t ipt=0;
198   TGraphErrors *g=new TGraphErrors(0);
199   for(Int_t i=0;i<kInjPads;i++){
200     if(fDriftSpeed[i]>0){ 
201       g->SetPoint(ipt,GetAnodeNumber(i),fDriftSpeed[i]);
202       g->SetPointError(ipt,0,fDriftSpeedErr[i]);
203       ipt++;
204     }
205   }
206   return g;
207 }
208 //______________________________________________________________________
209 TGraphErrors* AliITSOnlineSDDInjectors::GetSelectedDriftSpeedGraph(Int_t minAcceptStatus) const{
210   // TGraphErrors with only pads with status of injector >= minAcceptStatus
211   Int_t ipt=0;
212   TGraphErrors *g=new TGraphErrors(0);
213   for(Int_t i=0;i<kInjPads;i++){
214     Int_t padStatus = GetInjPadStatus(i);
215     if(fDriftSpeed[i]>0 && padStatus >= minAcceptStatus ){
216       g->SetPoint(ipt,GetAnodeNumber(i),fDriftSpeed[i]);
217       g->SetPointError(ipt,0,fDriftSpeedErr[i]);
218       ipt++;
219     }
220   }
221   return g;
222 }
223 //______________________________________________________________________
224 void AliITSOnlineSDDInjectors::CalcTimeBinZero(){
225   // Get time zero from trigger signal
226   Double_t tzero=0.,intCont=0.,rmsPeak=0.;
227   Bool_t isTbUsed[256];
228   Int_t nTbUsed=0;
229   for(Int_t i=0;i<256;i++) isTbUsed[i]=0;
230   for(Int_t ian=0;ian<fgkNAnodes;ian++){
231     for(Int_t itb=1;itb<fTbMin[0];itb++){
232       Double_t cont=fHisto->GetBinContent(itb,ian+1);
233       Double_t contm1=fHisto->GetBinContent(itb+1,ian+1);
234       Double_t contp1=fHisto->GetBinContent(itb-1,ian+1);
235       if(cont>fLowThreshold){
236         if(contm1>fHighThreshold || cont>fHighThreshold || contp1>fHighThreshold){
237           tzero+=cont*float(itb);
238           rmsPeak+=cont*float(itb)*float(itb);
239           intCont+=cont;
240           if(!isTbUsed[itb]){
241             isTbUsed[itb]=1;
242             ++nTbUsed;
243           }
244         }
245       }
246     }
247   }
248   if(intCont>0){ 
249     fTbZero=tzero/intCont;
250     fRMSTbZero=TMath::Sqrt(rmsPeak/intCont-fTbZero*fTbZero);
251   }
252   if(nTbUsed==1) fRMSTbZero=0.5; 
253 }
254
255 //______________________________________________________________________
256 void AliITSOnlineSDDInjectors::FitDriftSpeedVsAnode(){
257   // fits the anode dependence of drift speed
258
259   Float_t rangeForMax[2]={78.,178.};
260   PolyFit(fPolDegree);
261   fActualPolDegree=fPolDegree;
262   if(fPolDegree==3){
263     Double_t deltasq=fParam[2]*fParam[2]-3*fParam[1]*fParam[3];
264     Double_t zero1=-999.;
265     Double_t zero2=-999.;
266     if(deltasq>=0. && TMath::Abs(fParam[3])>0.){
267       Double_t delta=TMath::Sqrt(deltasq);
268       zero1=(-fParam[2]+delta)/3./fParam[3];
269       zero2=(-fParam[2]-delta)/3./fParam[3];
270     }
271     Bool_t twoZeroes=kFALSE;
272     Bool_t oneZero=kFALSE;
273     if(zero1>0. && zero1<256. && zero2>0. && zero2<256.) twoZeroes=kTRUE;
274     if(zero1>rangeForMax[0] && zero1<rangeForMax[1]) oneZero=kTRUE;
275     if(zero2>rangeForMax[0] && zero2<rangeForMax[1]) oneZero=kTRUE;
276     if(!oneZero || twoZeroes){
277       PolyFit(2);
278       Double_t xmax=-999.;
279       if(fParam[2]<0.) xmax=-fParam[1]/2./fParam[2];
280       if(xmax>rangeForMax[0] && xmax<rangeForMax[1]){
281         fActualPolDegree=2;
282       }else{
283         Double_t averSpeed=0.;
284         Double_t sumWei=0.;
285         Int_t nUsedPts=0;
286         for(Int_t jpad=fFirstPadForFit; jpad<=fLastPadForFit; jpad++){
287           if(fDriftSpeed[jpad]>0 && GetInjPadStatus(jpad)>fPadStatusCutForFit){
288             Double_t wei=1./fDriftSpeedErr[jpad]/fDriftSpeedErr[jpad];
289             averSpeed+=wei*fDriftSpeed[jpad];
290             sumWei+=wei;
291             nUsedPts++;
292           }
293         }
294         if(sumWei>0.) averSpeed/=sumWei;
295         if(nUsedPts<fPolDegree+1) averSpeed=0;
296         fParam[0]=averSpeed;
297         for(Int_t i=1; i < fPolDegree+1; i++) fParam[i]=0.;
298         fActualPolDegree=0;
299       }
300     }
301   }
302 }
303 //______________________________________________________________________
304 void AliITSOnlineSDDInjectors::PolyFit(Int_t degree){
305   // fits the anode dependence of drift speed with a polynomial function
306   const Int_t kNn=degree+1;
307   const Int_t kDimens=fPolDegree+1;
308
309   Double_t **mat = new Double_t*[kNn];
310   for(Int_t i=0; i < kNn; i++) mat[i] = new Double_t[kNn];
311   Double_t *vect = new Double_t[kNn];
312
313   for(Int_t k1=0;k1<kNn;k1++){
314     vect[k1]=0;
315     for(Int_t k2=0;k2<kNn;k2++){
316       mat[k1][k2]=0;
317     }
318   }
319   Int_t npts = 0;
320   for(Int_t k1=0;k1<kNn;k1++){
321     for(Int_t jpad=fFirstPadForFit; jpad<=fLastPadForFit; jpad++){
322       Double_t x=(Double_t)GetAnodeNumber(jpad);
323       if(fDriftSpeed[jpad]>0 && GetInjPadStatus(jpad)>fPadStatusCutForFit){
324         vect[k1]+=fDriftSpeed[jpad]*TMath::Power(x,k1)/TMath::Power(fDriftSpeedErr[jpad],2);    
325         if(k1==0) npts++;
326         for(Int_t k2=0;k2<kNn;k2++){
327           mat[k1][k2]+=TMath::Power(x,k1+k2)/TMath::Power(fDriftSpeedErr[jpad],2);
328         }
329       }
330     }
331   }
332   if(npts<fPolDegree+1){ 
333     if(fParam) delete [] fParam;
334     fParam=new Double_t[kDimens];
335     for(Int_t i=0; i<kDimens;i++)fParam[i]=0;
336   }else{
337     Int_t *iPivot = new Int_t[kNn];
338     Int_t *indxR = new Int_t[kNn];
339     Int_t *indxC = new Int_t[kNn];
340     for(Int_t i=0;i<kNn;i++) iPivot[i]=0;
341     Int_t iCol=-1,iRow=-1;
342     for(Int_t i=0;i<kNn;i++){
343       Double_t big=0.;
344       for(Int_t j=0;j<kNn;j++){
345         if(iPivot[j]!=1){
346           for(Int_t k=0;k<kNn;k++){
347             if(iPivot[k]==0){
348               if(TMath::Abs(mat[j][k])>=big){
349                 big=TMath::Abs(mat[j][k]);
350                 iRow=j;
351                 iCol=k;
352               }
353             }
354           }
355         }
356       }
357       iPivot[iCol]++;
358       Double_t aux;
359       if(iRow!=iCol){
360         for(Int_t l=0;l<kNn;l++){
361           aux=mat[iRow][l];
362           mat[iRow][l]=mat[iCol][l];
363           mat[iCol][l]=aux;
364         }
365         aux=vect[iRow];
366         vect[iRow]=vect[iCol];
367         vect[iCol]=aux;
368       }
369       indxR[i]=iRow;
370       indxC[i]=iCol;
371       if(mat[iCol][iCol]==0) break;
372       Double_t pivinv=1./mat[iCol][iCol];
373       mat[iCol][iCol]=1;
374       for(Int_t l=0;l<kNn;l++) mat[iCol][l]*=pivinv;
375       vect[iCol]*=pivinv;
376       for(Int_t m=0;m<kNn;m++){
377         if(m!=iCol){
378           aux=mat[m][iCol];
379           mat[m][iCol]=0;
380           for(Int_t n=0;n<kNn;n++) mat[m][n]-=mat[iCol][n]*aux;
381           vect[m]-=vect[iCol]*aux;
382         }
383       }    
384     }
385     delete [] iPivot;
386     delete [] indxR;
387     delete [] indxC;
388     
389   
390     if(fParam) delete [] fParam;
391     fParam=new Double_t[kDimens];
392     for(Int_t i=0; i<kNn;i++)fParam[i]=vect[i];
393     if(degree<fPolDegree) for(Int_t i=kNn; i<kDimens;i++)fParam[i]=0.;
394   }
395
396   for(Int_t i=0; i < kNn; i++) delete [] mat[i];
397   delete [] mat;
398   delete [] vect;
399 }
400 //______________________________________________________________________
401 void AliITSOnlineSDDInjectors::CalcDriftSpeed(Int_t jpad){
402   // 
403   Double_t sumY=0,sumX=0,sumXX=0,sumYY=0.,sumXY=0,sumWEI=0.;
404   Int_t npt=0;
405   Double_t y[kInjLines],ey[kInjLines];
406   Double_t tzero=0,erry=0;
407   for(Int_t i=0;i<kInjLines;i++){ 
408     y[i]=fCentroid[jpad][i];
409     ey[i]=fRMSCentroid[jpad][i];
410   }
411   for(Int_t i=0;i<kInjLines;i++){
412     if(!fUseLine[i]) continue;
413     if(fGoodInj[jpad][i] && ey[i]!=0){
414       sumY+=y[i]/ey[i]/ey[i];
415       sumX+=fPosition[i]/ey[i]/ey[i];
416       sumXX+=fPosition[i]*fPosition[i]/ey[i]/ey[i];
417       sumYY+=y[i]*y[i]/ey[i]/ey[i];
418       sumXY+=fPosition[i]*y[i]/ey[i]/ey[i];
419       sumWEI+=1./ey[i]/ey[i];
420       tzero=fTbZero/ey[i]/ey[i];
421       erry=ey[i]/ey[i]/ey[i];
422       npt++;
423     }
424   }
425   Double_t slope=0.,eslope=0.;
426   if(npt==1){
427     slope=(sumY-tzero)/sumX;
428     eslope=erry/sumX;
429   }
430   if(npt>1){ 
431     if(fUseTimeZeroSignal){
432       sumY+=fTbZero/fRMSTbZero/fRMSTbZero;
433       sumX+=0.;
434       sumXX+=0.;
435       sumYY+=fTbZero*fTbZero/fRMSTbZero/fRMSTbZero;
436       sumXY+=0.;
437       sumWEI+=1./fRMSTbZero/fRMSTbZero;
438     }
439     slope=(sumWEI*sumXY-sumY*sumX)/(sumWEI*sumXX-sumX*sumX);
440     eslope=TMath::Sqrt(sumWEI/(sumWEI*sumXX-sumX*sumX));
441   }
442
443   Double_t vel=0,evel=0;
444   if(slope!=0. && fTimeStep>0.){
445     vel=1./slope*10000./fTimeStep;// micron/ns
446     evel=eslope/slope/slope*10000./fTimeStep;// micron/ns
447   }
448   if(vel>fMaxDriftSpeed||vel<fMinDriftSpeed || evel>fMaxDriftSpeedErr){ 
449     vel=0.;
450     evel=0.;
451   }
452   fDriftSpeed[jpad]=vel;
453   fDriftSpeedErr[jpad]=evel;
454 }
455 //______________________________________________________________________
456 Int_t AliITSOnlineSDDInjectors::GetAnodeNumber(Int_t iInjPad) const{
457   // Injectors location along anodes:
458   // Side left  (UP)   - channel 0: injectors on anodes 0,7,15,...,247,255 
459   // Side right (DOWN) - channel 1: injectors on anodes 0,8,16,...,248,255 
460   Int_t ian=-1;
461   if(iInjPad>=kInjPads) return ian;
462   if(fSide==1){  // right side
463     ian=iInjPad*8;
464     if(iInjPad==32) ian--;
465   }else{         // left side
466     ian=iInjPad*8-1;
467     if(iInjPad==0) ian=0;
468   }
469   return ian;
470 }
471 //______________________________________________________________________
472 Int_t AliITSOnlineSDDInjectors::GetInjPadNumberFromAnode(Int_t nAnode) const{
473   //
474   Int_t iInjPad=-1;
475   if(fSide==1){  // right side
476     if(nAnode%8==0) iInjPad=nAnode/8;
477     if(nAnode==255) iInjPad=32;
478   }else{         // left side
479     if(nAnode%8==7) iInjPad=1+nAnode/8;
480     if(nAnode==0) iInjPad=0;
481   }
482   if(nAnode>=256) iInjPad=-1;
483   return iInjPad;
484 }
485 //______________________________________________________________________
486 Int_t AliITSOnlineSDDInjectors::GetInjPadStatus(Int_t jpad) const{
487   // returns an integer value with status of injector lines for given pad/anode
488   // status=7  -->  111  all injector are good
489   // status=6  -->  110  1st line (close to anodes) is bad, other two are good
490   // ....
491   // status=1  -->  001  only 1st line (close to anodes) good
492   // status=0  -->  000  all lines are bad
493   Int_t istatus=0;
494   if(jpad>=0 && jpad<kInjPads){
495     for(Int_t jlin=0;jlin<kInjLines;jlin++) istatus+=fGoodInj[jpad][jlin]<<jlin;
496   }
497   return istatus;
498 }
499 //______________________________________________________________________
500 void AliITSOnlineSDDInjectors::FindGoodInjectors(){
501   // 
502   for(Int_t jpad=0;jpad<kInjPads;jpad++){
503     Int_t ian=GetAnodeNumber(jpad);
504     for(Int_t jlin=0;jlin<kInjLines;jlin++){
505       for(Int_t jjj=fTbMin[jlin];jjj<fTbMax[jlin];jjj++){
506         Float_t c1=fHisto->GetBinContent(jjj,ian+1);
507         Float_t c2=fHisto->GetBinContent(jjj+1,ian+1);
508         //      Float_t c3=fHisto->GetBinContent(jjj+2,ian+1);
509         if(c1>fLowThreshold && c2>fLowThreshold){ 
510           if(c1>fHighThreshold || c2>fHighThreshold){
511             fGoodInj[jpad][jlin]=1;
512             break;
513           }
514         }
515       }
516     }
517   }
518 }
519 //______________________________________________________________________
520 void AliITSOnlineSDDInjectors::FindCentroids(){
521   // 
522   for(Int_t jpad=0;jpad<kInjPads;jpad++){
523     Int_t ian=GetAnodeNumber(jpad);
524     for(Int_t jlin=0;jlin<kInjLines;jlin++){
525       if(!fGoodInj[jpad][jlin]) continue;
526       Double_t maxcont=0;
527       Int_t ilmax=-1;
528       for(Int_t jjj=fTbMin[jlin];jjj<fTbMax[jlin];jjj++){
529         Double_t cont=fHisto->GetBinContent(jjj,ian+1);
530         if(cont>maxcont){
531           maxcont=cont;
532           ilmax=jjj;
533         }
534       }
535       Double_t intCont=0;
536       Int_t jjj=ilmax;
537       while(1){
538         Double_t cont=fHisto->GetBinContent(jjj,ian+1);
539         if(cont<fLowThreshold) break;
540         if(cont<fgkSaturation){
541           fCentroid[jpad][jlin]+=cont*(Double_t)jjj;
542           fRMSCentroid[jpad][jlin]+=cont*(Double_t)jjj*(Double_t)jjj;
543           intCont+=cont;
544         }
545         jjj--;
546       }
547       jjj=ilmax+1;
548       while(1){
549         Double_t cont=fHisto->GetBinContent(jjj,ian+1);
550         if(cont<fLowThreshold) break;
551         if(cont<fgkSaturation){
552           fCentroid[jpad][jlin]+=cont*float(jjj);
553           fRMSCentroid[jpad][jlin]+=cont*(Double_t)jjj*(Double_t)jjj;
554           intCont+=cont;
555         }
556         jjj++;
557       }
558       if(intCont>0){ 
559         fCentroid[jpad][jlin]/=intCont;
560         fRMSCentroid[jpad][jlin]=TMath::Sqrt(fRMSCentroid[jpad][jlin]/intCont-fCentroid[jpad][jlin]*fCentroid[jpad][jlin])/TMath::Sqrt(intCont);
561       }
562       else{ 
563         fCentroid[jpad][jlin]=0.;
564         fRMSCentroid[jpad][jlin]=0.;
565         fGoodInj[jpad][jlin]=0;
566       }
567       if(fRMSCentroid[jpad][jlin]==0) fGoodInj[jpad][jlin]=0;
568     }
569   }
570 }
571 //______________________________________________________________________
572 void AliITSOnlineSDDInjectors::PrintInjectorStatus(){
573   //
574   for(Int_t jpad=0;jpad<kInjPads;jpad++){
575     printf("Line%d-Anode%d: %d %d %d\n",jpad,GetAnodeNumber(jpad),fGoodInj[jpad][0],fGoodInj[jpad][1],fGoodInj[jpad][2]);
576   }
577 }
578 //______________________________________________________________________
579 void AliITSOnlineSDDInjectors::PrintCentroids(){
580   //
581   for(Int_t jpad=0;jpad<kInjPads;jpad++){
582     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]);
583   }
584 }
585 //______________________________________________________________________
586 void AliITSOnlineSDDInjectors::WriteToASCII(Int_t evNumb, UInt_t timeStamp, Int_t optAppend){
587   //
588   Char_t outfilnam[100];
589   sprintf(outfilnam,"SDDinj_ddl%02dc%02d_sid%d.data",fDDL,fCarlos,fSide);  
590   FILE* outf;
591   if(optAppend==0){ 
592     outf=fopen(outfilnam,"w");
593     fprintf(outf,"%d\n",fActualPolDegree);
594   }
595   else outf=fopen(outfilnam,"a");
596   fprintf(outf,"%d   %d   ",evNumb,timeStamp);
597   for(Int_t ic=0;ic<fPolDegree+1;ic++){
598     fprintf(outf,"%G ",fParam[ic]);
599   }
600   fprintf(outf,"\n");
601   fclose(outf);  
602 }
603 //______________________________________________________________________
604 TH1F* AliITSOnlineSDDInjectors::GetMeanDriftSpeedVsPadHisto() const{
605   Char_t hisnam[20];
606   sprintf(hisnam,"hdrsp%02dc%02ds%d",fDDL,fCarlos,fSide);
607   TH1F* h=new TH1F(hisnam,"",kInjPads,-0.5,kInjPads-0.5);
608   if(fNEvents>0){
609     for(Int_t i=0;i<kInjPads;i++){ 
610       h->SetBinContent(i+1,GetMeanDriftSpeed(i));    
611       Double_t rms=GetRMSDriftSpeed(i);
612       Double_t err=0.;
613       if(rms>0.) err=rms/TMath::Sqrt(fNEventsInPad[i]);
614       h->SetBinError(i+1,err);
615     }
616   }
617   return h;
618 }
619 //______________________________________________________________________
620 Bool_t AliITSOnlineSDDInjectors::WriteToROOT(TFile *fil) const {
621   //
622   if(fil==0){ 
623     AliWarning("Invalid pointer to ROOT file");
624     return kFALSE;    
625   }  
626   Char_t hisnam[20];
627   fil->cd();
628   sprintf(hisnam,"hdrsp%02dc%02ds%d",fDDL,fCarlos,fSide);
629   TH1F hdsp(hisnam,"",kInjPads,-0.5,kInjPads-0.5);
630   if(fNEvents==0){
631     AliWarning("Zero analyzed events");
632     return kFALSE;    
633   }  
634     
635   for(Int_t i=0;i<kInjPads;i++){ 
636     hdsp.SetBinContent(i+1,GetMeanDriftSpeed(i));    
637     Double_t rms=GetRMSDriftSpeed(i);
638     Double_t err=0.;
639     if(rms>0.) err=rms/TMath::Sqrt(fNEventsInPad[i]);
640     hdsp.SetBinError(i+1,err);
641   }
642   hdsp.Write();
643   return kTRUE;    
644 }
645 //______________________________________________________________________
646 void AliITSOnlineSDDInjectors::WriteInjectorStatusToASCII(){
647   // dump status of injectors encoded into UInt_t
648   // 5 bits (value 0-31) to store number of pads with given status
649   Char_t outfilnam[100];
650   sprintf(outfilnam,"SDDinj_ddl%02dc%02d_sid%d.data",fDDL,fCarlos,fSide);  
651   FILE* outf=fopen(outfilnam,"a");
652   Int_t n[8]={0,0,0,0,0,0,0,0};
653   for(Int_t jpad=fFirstPadForFit; jpad<=fLastPadForFit; jpad++){
654     Int_t statusPad=GetInjPadStatus(jpad);
655     ++n[statusPad];
656   }
657   UInt_t statusInj=0;
658   statusInj+=(n[7]&0x1F)<<25; // bits 25-29: n. of pads with status 7
659   statusInj+=(n[6]&0x1F)<<20; // bits 20-24: n. of pads with status 6
660   statusInj+=(n[5]&0x1F)<<15; // bits 15-19: n. of pads with status 5
661   statusInj+=(n[4]&0x1F)<<10; // bits 10-14: n. of pads with status 4
662   statusInj+=(n[3]&0x1F)<<5;  // bits  5- 9: n. of pads with status 3
663   statusInj+=(n[2]&0x1F);     // bits  0- 4: n. of pads with status 2
664
665   fprintf(outf,"-99 %u\n",statusInj); // -99 used in preprocessor to find line
666                                       // with injector status info
667   fclose(outf);  
668   
669 }