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