]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONGain.cxx
Coverity inspired fix
[u/mrichter/AliRoot.git] / MUON / AliMUONGain.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, 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
16 // $Id$
17
18 #include "AliMUONGain.h"
19 #include "AliMUONPedestal.h"
20 #include "AliMUONErrorCounter.h"
21 #include "AliMUON2DMap.h"
22 #include "AliMUONVCalibParam.h"
23 #include "AliMUONVStore.h"
24 #include "AliMpIntPair.h"
25
26 #include <TString.h>
27 #include <THashList.h>
28 #include <TTimeStamp.h>
29 #include <TTree.h>
30 #include <TFile.h>
31 #include <TF1.h>
32 #include <TGraphErrors.h>
33 #include <TMath.h>
34 #include <Riostream.h>
35
36 #include <sstream>
37 #include <cstdio>
38
39 #define  NFITPARAMS 4
40
41 //-----------------------------------------------------------------------------
42 /// \class AliMUONGain
43 ///
44 /// Implementation of calibration computing
45 ///
46 /// add
47 /// 
48 ///
49 /// \author Alberto Baldisseri, JL Charvet 
50 //-----------------------------------------------------------------------------
51
52
53
54
55 // functions
56
57 namespace {
58   
59   //______________________________________________________________________________
60   Double_t funcLin (const Double_t *x, const Double_t *par)
61   {
62     /// Linear function
63     return par[0] + par[1]*x[0];
64   }
65   
66   //______________________________________________________________________________
67   Double_t funcParabolic (const Double_t *x, const Double_t *par)
68   {
69     /// Parabolic function
70     return par[0]*x[0]*x[0];
71   }
72   
73   //______________________________________________________________________________
74   Double_t funcCalib (const Double_t *x, const Double_t *par)  
75   {
76     /// Calibration function
77     Double_t xLim= par[3];
78     
79     if(x[0] <= xLim) return par[0] + par[1]*x[0];
80     
81     Double_t yLim = par[0]+ par[1]*xLim;
82     return yLim + par[1]*(x[0] - xLim) + par[2]*(x[0] - xLim)*(x[0] - xLim);
83   }
84   
85 }
86
87 /// \cond CLASSIMP
88 ClassImp(AliMUONGain)
89 /// \endcond
90
91 //______________________________________________________________________________
92 AliMUONGain::AliMUONGain()
93 : AliMUONPedestal(),
94 fInjCharge(0), 
95 fRootDataFileName(),
96 fnInit(1),
97 fnEntries(11),
98 fnbpf1(6),
99 fPrintLevel(0), 
100 fPlotLevel(0)
101 {
102 /// Default constructor
103
104 }
105   
106 //______________________________________________________________________________
107 AliMUONGain::~AliMUONGain()
108 {
109 /// Destructor
110 }
111
112 //______________________________________________________________________________
113 TString AliMUONGain::WriteDummyHeader(void) 
114 {
115 ///
116
117   ostringstream stream;
118   stream<<"//DUMMY FILE (to prevent Shuttle failure)"<< endl;
119   stream<<"//================================================" << endl;
120   stream<<"//       MUONTRKGAINda: Calibration run  " << endl;
121   stream<<"//================================================" << endl;
122   stream<<"//   * Run           : " << fRunNumber << endl; 
123   stream<<"//   * Date          : " << fDate->AsString("l") <<endl;
124   stream<<"//   * DAC           : " << fInjCharge << endl;
125   stream<<"//-------------------------------------------------" << endl;
126
127   return TString(stream.str().c_str());
128 }
129
130 //______________________________________________________________________________
131 void AliMUONGain::MakePedStoreForGain(TString shuttleFile)
132 {
133 /// Store Pedmean and sigma to pedestal-like ascii file
134
135   ofstream fileout;
136   TString tempstring;
137   TString flatFile;
138   TString outputFile;
139   
140   // Store pedestal map in root file
141   TTree* tree = 0x0;
142
143   // write dummy ascii file -> Shuttle
144   if(fIndex<fnEntries)
145     {  
146       FILE *pfilew=0;
147       pfilew = fopen (shuttleFile,"w");
148
149       fprintf(pfilew,"//DUMMY FILE (to prevent Shuttle failure)\n");
150       fprintf(pfilew,"//================================================\n");
151       fprintf(pfilew,"//       MUONTRKGAINda: Calibration run  \n");
152       fprintf(pfilew,"//=================================================\n");
153       fprintf(pfilew,"//   * Run           : %d \n",fRunNumber); 
154       fprintf(pfilew,"//   * Date          : %s \n",fDate->AsString("l"));
155       fprintf(pfilew,"//   * DAC           : %d \n",fInjCharge);
156       fprintf(pfilew,"//-------------------------------------------------\n");
157       fclose(pfilew);
158     }
159
160
161
162   Finalize();
163   MakeControlHistos();
164   if(fPrintLevel>0)
165     {
166       // compute and store mean DAC values (like pedestals)
167       flatFile = Form("%s.ped",fPrefixDA.Data());
168       outputFile=flatFile;
169       cout << "\n" << fPrefixDA.Data() << " : Flat file  generated  : " << flatFile.Data() << "\n";
170       if (!outputFile.IsNull())  
171       {
172         ofstream out(outputFile.Data());
173         MakeASCIIoutput(out);
174         out.close();
175       }      
176     }
177
178   TString mode("UPDATE");
179
180   if (fIndex==1) {
181     mode = "RECREATE";
182   }
183   TFile* histoFile = new TFile(fRootDataFileName.Data(), mode.Data(), "MUON Tracking Gains");
184
185   // second argument should be the injected charge, taken from config crocus file
186   // put also info about run number could be usefull
187   AliMpIntPair* pair   = new AliMpIntPair(fRunNumber,fInjCharge );
188
189   if (mode.CompareTo("UPDATE") == 0) {
190     tree = (TTree*)histoFile->Get("t");
191     tree->SetBranchAddress("run",&pair);
192     tree->SetBranchAddress("ped",&fPedestalStore);
193
194   } else {
195     tree = new TTree("t","Pedestal tree");
196     tree->Branch("run", "AliMpIntPair",&pair);
197     tree->Branch("ped", "AliMUON2DMap",&fPedestalStore);
198     tree->SetBranchAddress("run",&pair);
199     tree->SetBranchAddress("ped",&fPedestalStore);
200
201   }
202
203   tree->Fill();
204   tree->Write("t", TObject::kOverwrite); // overwrite the tree
205   histoFile->Close();
206
207   delete pair;
208 }
209
210 //______________________________________________________________________________
211 TString AliMUONGain::WriteGainHeader(Int_t nInit, Int_t nEntries, Int_t nbpf2, Int_t *numrun, Double_t *injCharge) 
212 {
213 /// Header of the calibration output file
214
215   ostringstream stream;
216
217
218   stream<<"//=======================================================" << endl;
219   stream<<"//      Calibration file calculated by " << fPrefixDA.Data() <<endl;
220   stream<<"//=======================================================" << endl;
221   stream<<"//   * Run           : " << fRunNumber << endl; 
222   stream<<"//   * Date          : " << fDate->AsString("l") <<endl;
223   stream<<"//   * Statictics    : " << fNEvents << endl;
224   if(fConfig)
225   stream<<"//   * # of MANUS    : " << fNManuConfig << " read in the Det. config. " << endl;
226   stream<<"//   * # of MANUS    : " << fNManu << " read in raw data " << endl;
227   stream<<"//   * # of MANUS    : " << fNChannel/64 << " written in calibration file " << endl;
228   stream<<"//   * # of channels : " << fNChannel << endl;
229   stream<<"//-------------------------------------------------------" << endl;
230
231   if(nInit==0)
232     stream<<"//  "<< nEntries <<" DAC values  fit: "<< fnbpf1 << " pts (1st order) " << nbpf2 << " pts (2nd order)" << endl;
233   if(nInit==1)
234     stream<<"//  "<< nEntries <<" DAC values  fit: "<< fnbpf1 << " pts (1st order) " << nbpf2 << " pts (2nd order) DAC=0 excluded" << endl;
235   stream<<"//   *  nInit = " << nInit << "  *  f1nbp = " << fnbpf1 << "  *  f2nbp = " <<  nbpf2 << endl; 
236
237   stream<<"//   RUN     DAC   " << endl;
238   stream<<"//-----------------" << endl;
239   for (Int_t i = 0; i < nEntries; ++i) {
240         stream<<Form("//   %d    %5.0f \n",numrun[i],injCharge[i]);
241   }
242   stream<<"//=======================================" << endl;
243   stream<<"// BP MANU CH.   a1      a2     thres. q " << endl;
244   stream<<"//=======================================" << endl;
245
246   return TString(stream.str().c_str());
247 }
248
249 //______________________________________________________________________________
250 TString AliMUONGain::WriteGainData(Int_t BP, Int_t Manu, Int_t ch, Double_t p1, Double_t p2, Int_t threshold, Int_t q) 
251 {
252 /// Write calibration parameters per channel
253
254   ostringstream stream("");
255   stream << Form("%4i %5i %2i %7.4f %10.3e %4i %2x\n",BP,Manu,ch,p1,p2,threshold,q);
256   return TString(stream.str().c_str());
257
258 }
259
260 //_______________________________________________________________________________
261 void AliMUONGain::MakeGainStore(TString shuttleFile)
262 {
263   /// Store gains in ASCII files
264   ofstream fileout;
265   ofstream filcouc;
266   TString tempstring;   
267   TString filename; 
268
269   Double_t goodA1Min =  0.5;
270   Double_t goodA1Max =  2.;
271 //   Double_t goodA2Min = -0.5E-03;
272 //   Double_t goodA2Max =  1.E-03;
273   Double_t goodA2Min = -0.5E-01; // changed 28/10/2009 (JLC) <=> enlarged condition on a2
274   Double_t goodA2Max =  1.E-01;
275   // Table for uncalibrated  buspatches and manus
276   THashList* uncalBuspatchManuTable = new THashList(1000,2);
277
278   Int_t numrun[11];
279
280   // open file MUONTRKda_gain_data.root
281   // read again the pedestal for the calibration runs (11 runs)
282   // need the injection charge from config file (to be done)
283   // For each channel make a TGraphErrors (mean, sigma) vs injected charge
284   // Fit with a polynomial fct
285   // store the result in a flat file.
286
287   if(fIndex==0)cout << " Root data file = " << fRootDataFileName.Data() << endl;  
288   TFile*  histoFile = new TFile(fRootDataFileName.Data());
289
290   AliMUON2DMap* map[11];
291   AliMUONVCalibParam* ped[11];
292   AliMpIntPair* run[11];
293
294   //read back from root file
295   TTree* tree = (TTree*)histoFile->Get("t");
296   Int_t nEntries = tree->GetEntries();
297
298   Int_t nbpf2 = nEntries - (fnInit + fnbpf1) + 1; // nb pts used for 2nd order fit
299
300   // read back info
301   for (Int_t i = 0; i < nEntries; ++i) {
302     map[i] = 0x0;
303     run[i] = 0x0;
304     tree->SetBranchAddress("ped",&map[i]);
305     tree->SetBranchAddress("run",&run[i]);
306     tree->GetEvent(i);
307     //        std::cout << map[i] << " " << run[i] << std::endl;
308   }
309   // RunNumber extracted from Root data fil
310   if(fIndex==0)fRunNumber=(UInt_t)run[nEntries-1]->GetFirst();
311   //     sscanf(getenv("DATE_RUN_NUMBER"),"%d",&gAliRunNumber);
312
313   Double_t pedMean[11];
314   Double_t pedSigma[11];
315   for ( Int_t i=0 ; i<11 ; i++) {pedMean[i]=0.;pedSigma[i]=1.;};
316   Double_t injCharge[11];
317   Double_t injChargeErr[11];
318   for ( Int_t i=0 ; i<11 ; i++) {injCharge[i]=0.;injChargeErr[i]=1.;};
319
320   // some print
321   cout<<"\n ********  MUONTRKGAINda for Gain computing (Last Run = " << fRunNumber << ") ********\n" << endl;
322   cout<<" * Date          : " << fDate->AsString("l") << "\n" << endl;
323   cout << " Entries = " << nEntries << " DAC values \n" << endl; 
324   for (Int_t i = 0; i < nEntries; ++i) {
325     cout<< " Run = " << run[i]->GetFirst() << "    DAC = " << run[i]->GetSecond() << endl;
326     numrun[i] = run[i]->GetFirst();
327     injCharge[i] = run[i]->GetSecond();
328     injChargeErr[i] = 0.01*injCharge[i];
329     if(injChargeErr[i] <= 1.) injChargeErr[i]=1.;
330   }
331   cout << "" << endl;
332
333   //  print out in .log file
334
335   (*fFilcout)<<"\n\n//=================================================" << endl;
336   (*fFilcout)<<"//    MUONTRKGAINda: Gain Computing  Run = " << fRunNumber << endl;
337   (*fFilcout)<<"//    RootDataFile  = "<< fRootDataFileName.Data() << endl;
338   (*fFilcout)<<"//=================================================" << endl;
339   (*fFilcout)<<"//* Date          : " << fDate->AsString("l") << "\n" << endl;
340
341
342
343   // why 2 files ? (Ch. F.)  => second file contains detailed results
344     FILE *pfilen = 0;
345     if(fPrintLevel>1)
346       {
347         filename=Form("%s.param",fPrefixDA.Data());
348         cout << " Second fit parameter file        = " << filename.Data() << "\n";
349         pfilen = fopen (filename.Data(),"w");
350
351         fprintf(pfilen,"//===================================================================\n");
352         fprintf(pfilen,"//  BP MANU CH. par[0]     [1]     [2]     [3]      xlim          P(chi2) p1        P(chi2)2  p2\n");
353         fprintf(pfilen,"//===================================================================\n");
354         fprintf(pfilen,"//   * Run           : %d \n",fRunNumber); 
355         fprintf(pfilen,"//===================================================================\n");
356       }
357
358
359   // file outputs for gain
360
361   ofstream pfilew;
362   pfilew.open(shuttleFile.Data());
363   // Write Header Data of the .par file
364   pfilew << WriteGainHeader(fnInit,nEntries,nbpf2,numrun,injCharge);
365
366   // print mean and sigma values in file
367   FILE *pfilep = 0;
368   if(fPrintLevel>1)
369     {
370       filename=Form("%s.peak",fPrefixDA.Data());
371       cout << " File containing Peak mean values = " << filename << "\n";
372       pfilep = fopen (filename,"w");
373
374       fprintf(pfilep,"//==============================================================================================================================\n");
375       fprintf(pfilep,"//   * Run           : %d \n",fRunNumber); 
376       fprintf(pfilep,"//==============================================================================================================================\n");
377       fprintf(pfilep,"// BP  MANU  CH.    Ped.     <0>      <1>      <2>      <3>      <4>      <5>      <6>      <7>      <8>      <9>     <10> \n"); 
378       fprintf(pfilep,"//==============================================================================================================================\n");
379       fprintf(pfilep,"//                 DAC= %9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f  fC\n",injCharge[0],injCharge[1],injCharge[2],injCharge[3],injCharge[4],injCharge[5],injCharge[6],injCharge[7],injCharge[8],injCharge[9],injCharge[10]);
380       fprintf(pfilep,"//                      %9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f\n",injChargeErr[0],injChargeErr[1],injChargeErr[2],injChargeErr[3],injChargeErr[4],injChargeErr[5],injChargeErr[6],injChargeErr[7],injChargeErr[8],injChargeErr[9],injChargeErr[10]);
381       fprintf(pfilep,"//==============================================================================================================================\n");
382     }
383
384   Double_t chi2    = 0.;
385   Double_t chi2P2  = 0.;
386   Double_t prChi2  = 0; 
387   Double_t prChi2P2 =0;
388   Double_t a0=0.,a1=1.,a2=0.;
389   Int_t busPatchId ;
390   Int_t manuId     ;
391   Int_t channelId ;
392   Int_t threshold = 0;
393   Int_t q = 0;
394   Int_t p1 =0;
395   Int_t p2 =0;
396   Double_t gain=10.; // max value (= bad value)
397   Double_t capa=0.2; // internal capacitor (pF)
398
399   //  plot out 
400
401   TFile* gainFile = 0x0;
402   TTree* tg = 0x0;
403   if(fPlotLevel>0)
404     {
405       fHistoFileName=Form("%s.root",fPrefixDA.Data());
406       gainFile = new TFile(fHistoFileName.Data(),"RECREATE","MUON Tracking gains");
407       tg = new TTree("tg","TTree avec class Manu_DiMu");
408
409       tg->Branch("bp",&busPatchId, "busPatchId/I");
410       tg->Branch("manu",&manuId, "manuId/I");
411       tg->Branch("channel",&channelId, "channelId/I");
412
413       tg->Branch("a0",&a0, "a0/D");
414       tg->Branch("a1",&a1, "a1/D");
415       tg->Branch("a2",&a2, "a2/D");
416       tg->Branch("Pchi2",&prChi2, "prChi2/D");
417       tg->Branch("Pchi2_2",&prChi2P2, "prChi2P2/D");
418       tg->Branch("Threshold",&threshold, "threshold/I");
419       tg->Branch("q",&q, "q/I");
420       tg->Branch("p1",&p1, "p1/I");
421       tg->Branch("p2",&p2, "p2/I");
422       tg->Branch("gain",&gain, "gain/D");
423     }
424
425   char graphName[256];
426
427   // iterates over the first pedestal run
428   TIter next(map[0]->CreateIterator());
429   AliMUONVCalibParam* p;
430
431   Int_t    nmanu         = 0;
432   Int_t    nGoodChannel   = 0;
433   Int_t    nBadChannel   = 0;
434   Int_t    noFitChannel   = 0;
435   Int_t    nplot=0;
436   Double_t sumProbChi2   = 0.;
437   Double_t sumA1         = 0.;
438   Double_t sumProbChi2P2 = 0.;
439   Double_t sumA2         = 0.;
440
441   Double_t x[11], xErr[11], y[11], yErr[11];
442   Double_t xp[11], xpErr[11], yp[11], ypErr[11];
443
444   Int_t uncalcountertotal=0 ;
445   Int_t unparabolicfit=0;
446
447   while ( ( p = dynamic_cast<AliMUONVCalibParam*>(next() ) ) )
448     {
449       ped[0]  = p;
450       unparabolicfit=0;
451
452       busPatchId = p->ID0();
453       manuId     = p->ID1();
454
455       // read back pedestal from the other runs for the given (bupatch, manu)
456       for (Int_t i = 1; i < nEntries; ++i) {
457         ped[i] = static_cast<AliMUONVCalibParam*>(map[i]->FindObject(busPatchId, manuId));
458       }
459
460       // compute for each channel the gain parameters
461       for ( channelId = 0; channelId < ped[0]->Size() ; ++channelId ) 
462         {
463
464           Int_t n = 0;
465           for (Int_t i = 0; i < nEntries; ++i) {
466
467             if (!ped[i]) continue; //shouldn't happen.
468             pedMean[i]      = ped[i]->ValueAsDouble(channelId, 0);
469             pedSigma[i]     = ped[i]->ValueAsDouble(channelId, 1);
470
471             if (pedMean[i] < 0) continue; // not connected
472
473             if (pedSigma[i] <= 0) pedSigma[i] = 1.; // should not happen.
474             n++;
475           }
476
477           // print_peak_mean_values
478           if(fPrintLevel>1)
479             {
480
481               fprintf(pfilep,"%4i%5i%5i%10.3f",busPatchId,manuId,channelId,0.);
482               fprintf(pfilep,"%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f%9.1f \n",pedMean[0],pedMean[1],pedMean[2],pedMean[3],pedMean[4],pedMean[5],pedMean[6],pedMean[7],pedMean[8],pedMean[9],pedMean[10]);
483               fprintf(pfilep,"                   sig= %9.3f%9.3f%9.3f%9.3f%9.3f%9.3f%9.3f%9.3f%9.3f%9.3f%9.3f \n",pedSigma[0],pedSigma[1],pedSigma[2],pedSigma[3],pedSigma[4],pedSigma[5],pedSigma[6],pedSigma[7],pedSigma[8],pedSigma[9],pedSigma[10]);
484             }
485
486           // makegain 
487
488
489           // Fit Method:  Linear fit over gAlinbpf1 points + parabolic fit  over nbpf2  points) 
490           // nInit=1 : 1st pt DAC=0 excluded
491
492           // 1. - linear fit over gAlinbpf1 points
493
494           Double_t par[4] = {0.,0.5,0.,ADCMax()};
495           Int_t nbs   = nEntries - fnInit;
496           if(nbs < fnbpf1)fnbpf1=nbs;
497
498           Int_t fitproceed=1;
499           Int_t nbpf2Dynamic=nbpf2;
500           Int_t adcLimit=4090; // when RMS < 0.5 (in other cases mean values forced to 4095, see DA_PED)
501           for (Int_t j = 0; j < nbs; ++j)
502             {
503               Int_t k = j + fnInit;
504               x[j]    = pedMean[k];
505               if(x[j]<=0.){fitproceed=0; break;}
506               //              if(x[j]>= ADCMax())
507               if(x[j]>= adcLimit)
508                 {
509                   if(j < nbs-1){fitproceed=0; break;}
510                   else { nbpf2Dynamic=nbpf2-1; break;}
511                 }
512               xErr[j] = pedSigma[k];
513               y[j]    = injCharge[k];
514               yErr[j] = injChargeErr[k];
515
516             }
517
518           TGraphErrors *graphErr;
519           if(!fitproceed) { p1=0; p2=0; noFitChannel++;}
520
521           if(fitproceed)
522             {
523                       
524               TF1 *f1 = new TF1("f1",funcLin,0.,ADCMax(),2);
525               graphErr = new TGraphErrors(fnbpf1, x, y, xErr, yErr);
526
527               f1->SetParameters(0,0);
528
529               graphErr->Fit("f1","RQ");
530
531               chi2 = f1->GetChisquare();
532               f1->GetParameters(par);
533
534               delete graphErr;
535               graphErr=0;
536               delete f1;
537
538               prChi2 = TMath::Prob(chi2, fnbpf1 - 2);
539
540               Double_t xLim = pedMean[fnInit + fnbpf1 - 1];
541               Double_t yLim = par[0]+par[1] * xLim;
542
543               a0 = par[0];
544               a1 = par[1];
545
546               // 2. - Translation : new origin (xLim, yLim) + parabolic fit over nbf2 points
547               //checking:         if(busPatchId ==1841 && manuId==4)nbpf2Dynamic=2;
548               if(nbpf2Dynamic > 2)
549                 {
550                   for (Int_t j = 0; j < nbpf2Dynamic; j++)
551                     {
552                       Int_t k  = j + (fnInit + fnbpf1) - 1;
553                       xp[j]    = pedMean[k] - xLim;
554                       xpErr[j] = pedSigma[k];
555
556                       yp[j]    = injCharge[k] - yLim - par[1]*xp[j];
557                       ypErr[j] = injChargeErr[k];
558                     }
559
560                   TF1 *f2 = new TF1("f2",funcParabolic,0.,ADCMax(),1);
561                   graphErr = new TGraphErrors(nbpf2Dynamic, xp, yp, xpErr, ypErr);
562
563                   graphErr->Fit(f2,"RQ");
564                   chi2P2 = f2->GetChisquare();
565                   f2->GetParameters(par);
566
567                   delete graphErr;
568                   graphErr=0;
569                   delete f2;
570
571                   prChi2P2 = TMath::Prob(chi2P2, nbpf2Dynamic-1);
572                   a2 = par[0];
573                 }
574               else 
575                 { 
576                   unparabolicfit++;
577                   (*fFilcout) << " Warning : BP = " << busPatchId << " Manu = " << manuId <<  " Channel = " << channelId <<": parabolic fit not possible (nbpf2=" <<  nbpf2Dynamic  << ") => a2=0 and linear fit OK" << std::endl;
578                   if(unparabolicfit==1) std::cout << " Warning : BP = " << busPatchId << " Manu = " << manuId <<  ": no parabolic fit for some channels (nbpf2=" <<  nbpf2Dynamic  << "), linear fit is OK (see .log for details)" << std::endl;
579                   a2=0. ; prChi2P2=0. ;
580                 }
581
582               par[0] = a0;
583               par[1] = a1;
584               par[2] = a2;
585               par[3] = xLim;
586
587               if(prChi2>0.999999)prChi2=0.999999 ; if(prChi2P2>0.999999)prChi2P2=0.9999999; // avoiding Pr(Chi2)=1 value
588               p1 = TMath::Nint(floor(prChi2*15))+1;    // round down value : floor(2.8)=2.
589               p2 = TMath::Nint(floor(prChi2P2*15))+1;
590               q  = p1*16 + p2;  // fit quality 
591
592               Double_t x0 = -par[0]/par[1]; // value of x corresponding to à 0 fC 
593               threshold = TMath::Nint(ceil(par[3]-x0)); // linear if x < threshold
594
595               if(fPrintLevel>1)
596                 {
597                   fprintf(pfilen,"%4i %4i %2i",busPatchId,manuId,channelId);
598                   fprintf(pfilen," %6.2f %6.4f %10.3e %4.2f %4i          %8.6f %8.6f   %x          %8.6f  %8.6f   %x\n",
599                           par[0], par[1], par[2], par[3], threshold, prChi2, floor(prChi2*15), p1,  prChi2P2, floor(prChi2P2*15),p2);
600                 }
601
602
603               // tests
604               if(par[1]< goodA1Min ||  par[1]> goodA1Max) p1=0;
605               if(par[2]< goodA2Min ||  par[2]> goodA2Max) p2=0;
606
607             } // fitproceed
608
609           if(fitproceed && p1>0 && p2>0) 
610             {
611               nGoodChannel++;
612               sumProbChi2   += prChi2;
613               sumA1         += par[1];
614               sumProbChi2P2   += prChi2P2;
615               sumA2         += par[2];
616             }
617           else // bad calibration
618             {
619               nBadChannel++;
620               q=0;  
621               par[1]=0.5; a1=0.5; p1=0;
622               par[2]=0.;  a2=0.;  p2=0;
623               threshold=ADCMax();       
624
625               // bad calibration counter
626               char bpmanuname[256];
627               AliMUONErrorCounter* uncalcounter;
628
629               snprintf(bpmanuname,256,"bp%dmanu%d",busPatchId,manuId);
630               if (!(uncalcounter = (AliMUONErrorCounter*)uncalBuspatchManuTable->FindObject(bpmanuname)))
631                 {
632                   // New buspatch_manu name
633                   uncalcounter= new AliMUONErrorCounter (busPatchId,manuId);
634                   uncalcounter->SetName(bpmanuname);
635                   uncalBuspatchManuTable->Add(uncalcounter);
636                 }
637               else
638                 {
639                   // Existing buspatch_manu name
640                   uncalcounter->Increment();
641                 }
642               //                            uncalcounter->Print_uncal()
643               uncalcountertotal ++;
644             }
645           gain=1./(par[1]*capa); // mv/fC
646
647           if(fPlotLevel>0)
648             {if(fPlotLevel>1)
649                 {
650                   //                  if(q==0  and  nplot < 100)
651                   //      if(p1>1 && p2==0  and  nplot < 100)
652                   //                        if(p1>10 && p2>10  and  nplot < 100)
653                   //    if(p1>=1 and p1<=2  and  nplot < 100)
654 //                if((p1==1 || p2==1) and  nplot < 100)
655                             if(nbpf2Dynamic<nbpf2  and  nplot < 100)
656                     {
657                       nplot++;
658                       //              cout << " nplot = " << nplot << endl;
659                       TF1 *f2Calib = new TF1("f2Calib",funcCalib,0.,ADCMax(),NFITPARAMS);
660
661                       graphErr = new TGraphErrors(nEntries,pedMean,injCharge,pedSigma,injChargeErr);
662
663                       snprintf(graphName,256,"BusPatch_%d_Manu_%d_Ch_%d",busPatchId, manuId,channelId);
664
665                       graphErr->SetTitle(graphName);
666                       graphErr->SetMarkerColor(3);
667                       graphErr->SetMarkerStyle(12);
668                       graphErr->Write(graphName);
669
670                       snprintf(graphName,256,"f2_BusPatch_%d_Manu_%d_Ch_%d",busPatchId, manuId,channelId);
671                       f2Calib->SetTitle(graphName);
672                       f2Calib->SetLineColor(4);
673                       f2Calib->SetParameters(par);
674                       f2Calib->Write(graphName);
675
676                       delete graphErr;
677                       graphErr=0;
678                       delete f2Calib;
679                     }
680                 }
681               tg->Fill();
682             }
683           pfilew << WriteGainData(busPatchId,manuId,channelId,par[1],par[2],threshold,q);
684         }
685       nmanu++;
686       Int_t step=500;
687       if(nmanu % step == 0)std::cout << " Nb manu = " << nmanu << std::endl;
688     }
689
690   //      print in logfile
691   if (uncalBuspatchManuTable->GetSize())
692     {
693       uncalBuspatchManuTable->Sort();  // use compare
694       TIterator* iter = uncalBuspatchManuTable->MakeIterator();
695       AliMUONErrorCounter* uncalcounter;
696       (*fFilcout) << "\n List of problematic BusPatch and Manu " << endl;
697       (*fFilcout) << " ========================================" << endl;
698       (*fFilcout) << "        BP       Manu        Nb Channel  " << endl ;
699       (*fFilcout) << " ========================================" << endl;
700       while((uncalcounter = (AliMUONErrorCounter*) iter->Next()))
701         {
702           (*fFilcout) << "\t" << uncalcounter->BusPatch() << "\t " << uncalcounter->ManuId() << "\t\t"   << uncalcounter->Events() << endl;
703         }
704       (*fFilcout) << " ========================================" << endl;
705
706       (*fFilcout) << " Number of bad calibrated Manu    = " << uncalBuspatchManuTable->GetSize() << endl ;
707       (*fFilcout) << " Number of bad calibrated channel = " << uncalcountertotal << endl;
708         
709     }
710
711
712   (*fFilcout) << "\n Nb of channels in raw data = " << nmanu*64 << " (" << nmanu << " Manu)" <<  endl;
713   (*fFilcout) << " Nb of calibrated channel   = " << nGoodChannel << " (" << goodA1Min << "<a1<" << goodA1Max 
714               << " and " << goodA2Min << "<a2<" << goodA2Max << ") " << endl;
715   (*fFilcout) << " Nb of uncalibrated channel = " << nBadChannel << " (" << noFitChannel << " unfitted)" << endl;
716
717   cout << "\n Nb of channels in raw data = " << nmanu*64 << " (" << nmanu << " Manu)" <<  endl;
718   cout << " Nb of calibrated channel   = " << nGoodChannel << " (" << goodA1Min << "<a1<" << goodA1Max 
719        << " and " << goodA2Min << "<a2<" << goodA2Max << ") " << endl;
720   cout << " Nb of uncalibrated channel = " << nBadChannel << " (" << noFitChannel << " unfitted)" << endl;
721
722   Double_t meanA1         = sumA1/(nGoodChannel);
723   Double_t meanProbChi2   = sumProbChi2/(nGoodChannel);
724   Double_t meanA2         = sumA2/(nGoodChannel);
725   Double_t meanProbChi2P2 = sumProbChi2P2/(nGoodChannel);
726
727   Double_t capaManu = 0.2; // pF
728   (*fFilcout) << "\n linear fit   : <a1> = " << meanA1 << "\t  <gain>  = " <<  1./(meanA1*capaManu) 
729               << " mV/fC (capa= " << capaManu << " pF)" << endl;
730   (*fFilcout) <<   "        Prob(chi2)>  = " <<  meanProbChi2 << endl;
731   (*fFilcout) << "\n parabolic fit: <a2> = " << meanA2  << endl;
732   (*fFilcout) <<   "        Prob(chi2)>  = " <<  meanProbChi2P2 << "\n" << endl;
733
734   cout << "\n  <gain>  = " <<  1./(meanA1*capaManu) 
735        << " mV/fC (capa= " << capaManu << " pF)" 
736        <<  "  Prob(chi2)>  = " <<  meanProbChi2 << endl;
737   
738   pfilew.close();
739
740   if(fPlotLevel>0){tg->Write();histoFile->Close();}
741   if(fPrintLevel>1){fclose(pfilep); fclose(pfilen);}
742 }