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