]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/AliTPCcalibDB.cxx
Adding histograms for absolute z residuals
[u/mrichter/AliRoot.git] / TPC / AliTPCcalibDB.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
17 ///////////////////////////////////////////////////////////////////////////////
18 //                                                                           //
19 // Class providing the calibration parameters by accessing the CDB           //
20 //                                                                           //
21 // Request an instance with AliTPCcalibDB::Instance()                        //
22 // If a new event is processed set the event number with SetRun              //
23 // Then request the calibration data                                         ////
24 //
25 //
26 // Calibration data:
27 // 0.)  Altro mapping
28 //          Simulation      - not yet 
29 //          Reconstruction  - AliTPCclustererMI::Digits2Clusters(AliRawReader* rawReader)
30 //
31 // 1.)  pad by pad calibration -  AliTPCCalPad
32 //      
33 //      a.) fPadGainFactor
34 //          Simulation: AliTPCDigitizer::ExecFast - Multiply by gain
35 //          Reconstruction : AliTPCclustererMI::Digits2Clusters - Divide by gain  
36 //
37 //      b.) fPadNoise -
38 //          Simulation:        AliTPCDigitizer::ExecFast
39 //          Reconstruction:    AliTPCclustererMI::FindClusters(AliTPCCalROC * noiseROC)
40 //                             Noise depending cut on clusters charge (n sigma)
41 //      c.) fPedestal:
42 //          Simulation:     Not used yet - To be impleneted - Rounding to the nearest integer
43 //          Reconstruction: Used in AliTPCclustererMI::Digits2Clusters(AliRawReader* rawReader) 
44 //                          if data taken without zero suppression  
45 //                          Currently switch in  fRecoParam->GetCalcPedestal();
46 //      
47 //      d.) fPadTime0
48 //          Simulation:      applied in the AliTPC::MakeSector - adding offset
49 //          Reconstruction:  AliTPCTransform::Transform() - remove offset
50 //                           AliTPCTransform::Transform() - to be called
51 //                           in AliTPCtracker::Transform()      
52 //
53 // 
54 // 2.)  Space points transformation:
55 //
56 //      a.) General coordinate tranformation - AliTPCtransform (see $ALICE_ROOT/TPC/AliTPCtransform.cxx)
57 //          Created on fly - use the other calibration components
58 //                 Unisochronity  - (substract time0 - pad by pad)
59 //                 Drift velocity - Currently common drift velocity - functionality of AliTPCParam
60 //                 ExB effect    
61 //          Simulation     - Not used directly (the effects are applied one by one (see AliTPC::MakeSector)
62 //          Reconstruction - 
63 //                           AliTPCclustererMI::AddCluster
64 //                           AliTPCtrackerMI::Transform
65 //      b.) ExB effect calibration - 
66 //             classes (base class AliTPCExB, implementation- AliTPCExBExact.h  AliTPCExBFirst.h)
67 //             a.a) Simulation:   applied in the AliTPC::MakeSector - 
68 //                                calib->GetExB()->CorrectInverse(dxyz0,dxyz1);
69 //             a.b) Reconstruction -  
70 //                  
71 //                  in AliTPCtransform::Correct() - called calib->GetExB()->Correct(dxyz0,dxyz1)
72 //
73 //  3.)   cluster error, shape and Q parameterization
74 //
75 //
76 //
77 ///////////////////////////////////////////////////////////////////////////////
78
79 #include <iostream>
80 #include <fstream>
81
82
83 #include <AliCDBManager.h>
84 #include <AliCDBEntry.h>
85 #include <AliCDBId.h>
86 #include <AliLog.h>
87 #include <AliMagF.h>
88 #include <AliSplineFit.h>
89
90 #include "AliTPCcalibDB.h"
91 #include "AliTPCdataQA.h"
92 #include "AliTPCcalibDButil.h"
93 #include "AliTPCAltroMapping.h"
94 #include "AliTPCExB.h"
95
96 #include "AliTPCCalROC.h"
97 #include "AliTPCCalPad.h"
98 #include "AliTPCSensorTempArray.h"
99 #include "AliGRPObject.h"
100 #include "AliTPCTransform.h"
101
102 class AliCDBStorage;
103 class AliTPCCalDet;
104 //
105 //
106
107 #include "TFile.h"
108 #include "TKey.h"
109 #include "TGraphErrors.h"
110
111 #include "TObjArray.h"
112 #include "TObjString.h"
113 #include "TString.h"
114 #include "TDirectory.h"
115 #include "AliTPCCalPad.h"
116 #include "AliTPCCalibPulser.h"
117 #include "AliTPCCalibPedestal.h"
118 #include "AliTPCCalibCE.h"
119 #include "AliTPCExBFirst.h"
120 #include "AliTPCTempMap.h"
121 #include "AliTPCCalibVdrift.h"
122 #include "AliTPCCalibRaw.h"
123 #include "AliTPCParam.h"
124
125 #include "AliTPCPreprocessorOnline.h"
126
127
128 ClassImp(AliTPCcalibDB)
129
130 AliTPCcalibDB* AliTPCcalibDB::fgInstance = 0;
131 Bool_t AliTPCcalibDB::fgTerminated = kFALSE;
132 TObjArray    AliTPCcalibDB::fgExBArray;    // array of ExB corrections
133
134
135 //_ singleton implementation __________________________________________________
136 AliTPCcalibDB* AliTPCcalibDB::Instance()
137 {
138   //
139   // Singleton implementation
140   // Returns an instance of this class, it is created if neccessary
141   //
142   
143   if (fgTerminated != kFALSE)
144     return 0;
145
146   if (fgInstance == 0)
147     fgInstance = new AliTPCcalibDB();
148   
149   return fgInstance;
150 }
151
152 void AliTPCcalibDB::Terminate()
153 {
154   //
155   // Singleton implementation
156   // Deletes the instance of this class and sets the terminated flag, instances cannot be requested anymore
157   // This function can be called several times.
158   //
159   
160   fgTerminated = kTRUE;
161   
162   if (fgInstance != 0)
163   {
164     delete fgInstance;
165     fgInstance = 0;
166   }
167 }
168
169 //_____________________________________________________________________________
170 AliTPCcalibDB::AliTPCcalibDB():
171   TObject(),
172   fRun(-1),
173   fTransform(0),
174   fExB(0),
175   fPadGainFactor(0),
176   fDedxGainFactor(0),
177   fPadTime0(0),
178   fPadNoise(0),
179   fPedestals(0),
180   fCalibRaw(0),
181   fDataQA(0),
182   fALTROConfigData(0),
183   fPulserData(0),
184   fCEData(0),
185   fTemperature(0),
186   fMapping(0),
187   fParam(0),
188   fClusterParam(0),
189   fTimeGainSplines(0),
190   fTimeGainSplinesArray(100000),
191   fGRPArray(100000),            //! array of GRPs  -  per run  - JUST for calibration studies
192   fGRPMaps(100000),            //! array of GRPs  -  per run  - JUST for calibration studies
193   fGoofieArray(100000),         //! array of GOOFIE values -per run - Just for calibration studies
194   fVoltageArray(100000),
195   fTemperatureArray(100000),    //! array of temperature sensors - per run - Just for calibration studies
196   fVdriftArray(100000),                 //! array of v drift interfaces
197   fDriftCorrectionArray(100000),  //! array of drift correction
198   fRunList(100000),              //! run list - indicates try to get the run param 
199   fDButil(0)
200 {
201   //
202   // constructor
203   //  
204   //
205   Update();    // temporary
206 }
207
208 AliTPCcalibDB::AliTPCcalibDB(const AliTPCcalibDB& ):
209   TObject(),
210   fRun(-1),
211   fTransform(0),
212   fExB(0),
213   fPadGainFactor(0),
214   fDedxGainFactor(0),
215   fPadTime0(0),
216   fPadNoise(0),
217   fPedestals(0),
218   fCalibRaw(0),
219   fDataQA(0),
220   fALTROConfigData(0),
221   fPulserData(0),
222   fCEData(0),
223   fTemperature(0),
224   fMapping(0),
225   fParam(0),
226   fClusterParam(0),
227   fTimeGainSplines(0),
228   fTimeGainSplinesArray(100000),
229   fGRPArray(0),          //! array of GRPs  -  per run  - JUST for calibration studies
230   fGRPMaps(0),          //! array of GRPs  -  per run  - JUST for calibration studies
231   fGoofieArray(0),        //! array of GOOFIE values -per run - Just for calibration studies
232   fVoltageArray(0),
233   fTemperatureArray(0),   //! array of temperature sensors - per run - Just for calibration studies
234   fVdriftArray(0),         //! array of v drift interfaces
235   fDriftCorrectionArray(0),         //! array of v drift interfaces
236   fRunList(0),              //! run list - indicates try to get the run param 
237   fDButil(0)
238 {
239   //
240   // Copy constructor invalid -- singleton implementation
241   //
242    Error("copy constructor","invalid -- singleton implementation");
243 }
244
245 AliTPCcalibDB& AliTPCcalibDB::operator= (const AliTPCcalibDB& )
246 {
247 //
248 // Singleton implementation - no assignment operator
249 //
250   Error("operator =", "assignment operator not implemented");
251   return *this;
252 }
253
254
255
256 //_____________________________________________________________________________
257 AliTPCcalibDB::~AliTPCcalibDB() 
258 {
259   //
260   // destructor
261   //
262   
263   // don't delete anything, CDB cache is active!
264   //if (fPadGainFactor) delete fPadGainFactor;
265   //if (fPadTime0) delete fPadTime0;
266   //if (fPadNoise) delete fPadNoise;
267 }
268
269
270 //_____________________________________________________________________________
271 AliCDBEntry* AliTPCcalibDB::GetCDBEntry(const char* cdbPath)
272 {
273   // 
274   // Retrieves an entry with path <cdbPath> from the CDB.
275   //
276   char chinfo[1000];
277     
278   AliCDBEntry* entry = AliCDBManager::Instance()->Get(cdbPath, fRun); 
279   if (!entry) 
280   { 
281     sprintf(chinfo,"AliTPCcalibDB: Failed to get entry:\t%s ", cdbPath);
282     AliError(chinfo); 
283     return 0; 
284   }
285   return entry;
286 }
287
288
289 //_____________________________________________________________________________
290 void AliTPCcalibDB::SetRun(Long64_t run)
291 {
292   //
293   // Sets current run number. Calibration data is read from the corresponding file. 
294   //  
295   if (fRun == run)
296     return;  
297         fRun = run;
298   Update();
299 }
300   
301
302
303 void AliTPCcalibDB::Update(){
304         //
305   AliCDBEntry * entry=0;
306   Bool_t cdbCache = AliCDBManager::Instance()->GetCacheFlag(); // save cache status
307   AliCDBManager::Instance()->SetCacheFlag(kTRUE); // activate CDB cache
308   fDButil = new AliTPCcalibDButil;   
309   //
310   entry          = GetCDBEntry("TPC/Calib/PadGainFactor");
311   if (entry){
312     //if (fPadGainFactor) delete fPadGainFactor;
313     entry->SetOwner(kTRUE);
314     fPadGainFactor = (AliTPCCalPad*)entry->GetObject();
315   }
316   //
317   entry          = GetCDBEntry("TPC/Calib/TimeGain");
318   if (entry){
319     //if (fTimeGainSplines) delete fTimeGainSplines;
320     entry->SetOwner(kTRUE);
321     fTimeGainSplines = (TObjArray*)entry->GetObject();
322   }
323   //
324   entry          = GetCDBEntry("TPC/Calib/GainFactorDedx");
325   if (entry){
326     entry->SetOwner(kTRUE);
327     fDedxGainFactor = (AliTPCCalPad*)entry->GetObject();
328   }
329   //
330   entry          = GetCDBEntry("TPC/Calib/PadTime0");
331   if (entry){
332     //if (fPadTime0) delete fPadTime0;
333     entry->SetOwner(kTRUE);
334     fPadTime0 = (AliTPCCalPad*)entry->GetObject();
335   }
336   //
337   //
338   entry          = GetCDBEntry("TPC/Calib/PadNoise");
339   if (entry){
340     //if (fPadNoise) delete fPadNoise;
341     entry->SetOwner(kTRUE);
342     fPadNoise = (AliTPCCalPad*)entry->GetObject();
343   }
344
345   entry          = GetCDBEntry("TPC/Calib/Pedestals");
346   if (entry){
347     //if (fPedestals) delete fPedestals;
348     entry->SetOwner(kTRUE);
349     fPedestals = (AliTPCCalPad*)entry->GetObject();
350   }
351
352   entry          = GetCDBEntry("TPC/Calib/Temperature");
353   if (entry){
354     //if (fTemperature) delete fTemperature;
355     entry->SetOwner(kTRUE);
356     fTemperature = (AliTPCSensorTempArray*)entry->GetObject();
357   }
358
359   entry          = GetCDBEntry("TPC/Calib/Parameters");
360   if (entry){
361     //if (fPadNoise) delete fPadNoise;
362     entry->SetOwner(kTRUE);
363     fParam = (AliTPCParam*)(entry->GetObject()->Clone());
364   }
365
366   entry          = GetCDBEntry("TPC/Calib/ClusterParam");
367   if (entry){
368     entry->SetOwner(kTRUE);
369     fClusterParam = (AliTPCClusterParam*)(entry->GetObject()->Clone());
370   }
371
372   //ALTRO configuration data
373   entry          = GetCDBEntry("TPC/Calib/AltroConfig");
374   if (entry){
375     entry->SetOwner(kTRUE);
376     fALTROConfigData=(TObjArray*)(entry->GetObject());
377   }
378   
379   //Calibration Pulser data
380   entry          = GetCDBEntry("TPC/Calib/Pulser");
381   if (entry){
382     entry->SetOwner(kTRUE);
383     fPulserData=(TObjArray*)(entry->GetObject());
384   }
385   
386   //CE data
387   entry          = GetCDBEntry("TPC/Calib/CE");
388   if (entry){
389     entry->SetOwner(kTRUE);
390     fCEData=(TObjArray*)(entry->GetObject());
391   }
392   //RAW calibration data
393   entry          = GetCDBEntry("TPC/Calib/Raw");
394   if (entry){
395     entry->SetOwner(kTRUE);
396     TObjArray *arr=(TObjArray*)(entry->GetObject());
397     if (arr) fCalibRaw=(AliTPCCalibRaw*)arr->At(0);
398   }
399   //QA calibration data
400   entry          = GetCDBEntry("TPC/Calib/QA");
401   if (entry){
402     entry->SetOwner(kTRUE);
403     fDataQA=dynamic_cast<AliTPCdataQA*>(entry->GetObject());
404   }
405   
406   entry          = GetCDBEntry("TPC/Calib/Mapping");
407   if (entry){
408     //if (fPadNoise) delete fPadNoise;
409     entry->SetOwner(kTRUE);
410     TObjArray * array = dynamic_cast<TObjArray*>(entry->GetObject());
411     if (array && array->GetEntriesFast()==6){
412       fMapping = new AliTPCAltroMapping*[6];
413       for (Int_t i=0; i<6; i++){
414         fMapping[i] =  dynamic_cast<AliTPCAltroMapping*>(array->At(i));
415       }
416     }
417   }
418
419
420
421   //entry          = GetCDBEntry("TPC/Calib/ExB");
422   //if (entry) {
423   //  entry->SetOwner(kTRUE);
424   //  fExB=dynamic_cast<AliTPCExB*>(entry->GetObject()->Clone());
425   //}
426   //
427   // ExB  - calculate during initialization - in simulation /reconstruction
428   //      - not invoked here anymore
429   //fExB =  GetExB(-5,kTRUE);
430      //
431   if (!fTransform) {
432     fTransform=new AliTPCTransform(); 
433     fTransform->SetCurrentRun(AliCDBManager::Instance()->GetRun());
434   }
435
436   //
437   AliCDBManager::Instance()->SetCacheFlag(cdbCache); // reset original CDB cache
438 }
439
440
441
442 void AliTPCcalibDB::CreateObjectList(const Char_t *filename, TObjArray *calibObjects)
443 {
444 //
445 // Create calibration objects and read contents from OCDB
446 //
447    if ( calibObjects == 0x0 ) return;
448    ifstream in;
449    in.open(filename);
450    if ( !in.is_open() ){
451       fprintf(stderr,"Error: cannot open list file '%s'", filename);
452       return;
453    }
454    
455    AliTPCCalPad *calPad=0x0;
456    
457    TString sFile;
458    sFile.ReadFile(in);
459    in.close();
460    
461    TObjArray *arrFileLine = sFile.Tokenize("\n");
462    
463    TIter nextLine(arrFileLine);
464    
465    TObjString *sObjLine=0x0;
466    while ( (sObjLine = (TObjString*)nextLine()) ){
467       TString sLine(sObjLine->GetString());
468       
469       TObjArray *arrNextCol = sLine.Tokenize("\t");
470       
471       TObjString *sObjType     = (TObjString*)(arrNextCol->At(0));
472       TObjString *sObjFileName = (TObjString*)(arrNextCol->At(1));
473       
474       if ( !sObjType || ! sObjFileName ) continue;
475       TString sType(sObjType->GetString());
476       TString sFileName(sObjFileName->GetString());
477       printf("%s\t%s\n",sType.Data(),sFileName.Data());
478       
479       TFile *fIn = TFile::Open(sFileName);
480       if ( !fIn ){
481          fprintf(stderr,"File not found: '%s'", sFileName.Data());
482          continue;
483       }
484       
485       if ( sType == "CE" ){
486          AliTPCCalibCE *ce = (AliTPCCalibCE*)fIn->Get("AliTPCCalibCE");
487          
488          calPad = new AliTPCCalPad((TObjArray*)ce->GetCalPadT0());         
489          calPad->SetNameTitle("CETmean","CETmean");
490          calibObjects->Add(calPad);
491          
492          calPad = new AliTPCCalPad((TObjArray*)ce->GetCalPadQ());         
493          calPad->SetNameTitle("CEQmean","CEQmean");
494          calibObjects->Add(calPad);        
495          
496          calPad = new AliTPCCalPad((TObjArray*)ce->GetCalPadRMS());
497          calPad->SetNameTitle("CETrms","CETrms");
498          calibObjects->Add(calPad);         
499                   
500       } else if ( sType == "Pulser") {
501          AliTPCCalibPulser *sig = (AliTPCCalibPulser*)fIn->Get("AliTPCCalibPulser");
502          
503          calPad = new AliTPCCalPad((TObjArray*)sig->GetCalPadT0());         
504          calPad->SetNameTitle("PulserTmean","PulserTmean");
505          calibObjects->Add(calPad);
506          
507          calPad = new AliTPCCalPad((TObjArray*)sig->GetCalPadQ());         
508          calPad->SetNameTitle("PulserQmean","PulserQmean");
509          calibObjects->Add(calPad);        
510          
511          calPad = new AliTPCCalPad((TObjArray*)sig->GetCalPadRMS());
512          calPad->SetNameTitle("PulserTrms","PulserTrms");
513          calibObjects->Add(calPad);         
514       
515       } else if ( sType == "Pedestals") {
516          AliTPCCalibPedestal *ped = (AliTPCCalibPedestal*)fIn->Get("AliTPCCalibPedestal");
517          
518          calPad = new AliTPCCalPad((TObjArray*)ped->GetCalPadPedestal());         
519          calPad->SetNameTitle("Pedestals","Pedestals");
520          calibObjects->Add(calPad);
521          
522          calPad = new AliTPCCalPad((TObjArray*)ped->GetCalPadRMS());         
523          calPad->SetNameTitle("Noise","Noise");
524          calibObjects->Add(calPad);        
525      
526       } else {
527          fprintf(stderr,"Undefined Type: '%s'",sType.Data());
528          
529       }
530       delete fIn;
531    }
532 }
533
534
535
536 void AliTPCcalibDB::MakeTree(const char * fileName, TObjArray * array, const char * mapFileName, AliTPCCalPad* outlierPad, Float_t ltmFraction) {
537   //
538   // Write a tree with all available information
539   // if mapFileName is specified, the Map information are also written to the tree
540   // pads specified in outlierPad are not used for calculating statistics
541   //  - the same function as AliTPCCalPad::MakeTree - 
542   //
543    AliTPCROC* tpcROCinstance = AliTPCROC::Instance();
544
545    TObjArray* mapIROCs = 0;
546    TObjArray* mapOROCs = 0;
547    TVectorF *mapIROCArray = 0;
548    TVectorF *mapOROCArray = 0;
549    Int_t mapEntries = 0;
550    TString* mapNames = 0;
551    
552    if (mapFileName) {
553       TFile mapFile(mapFileName, "read");
554       
555       TList* listOfROCs = mapFile.GetListOfKeys();
556       mapEntries = listOfROCs->GetEntries()/2;
557       mapIROCs = new TObjArray(mapEntries*2);
558       mapOROCs = new TObjArray(mapEntries*2);
559       mapIROCArray = new TVectorF[mapEntries];
560       mapOROCArray = new TVectorF[mapEntries];
561       
562       mapNames = new TString[mapEntries];
563       for (Int_t ivalue = 0; ivalue < mapEntries; ivalue++) {
564         TString nameROC(((TKey*)(listOfROCs->At(ivalue*2)))->GetName());
565          nameROC.Remove(nameROC.Length()-4, 4);
566          mapIROCs->AddAt((AliTPCCalROC*)mapFile.Get((nameROC + "IROC").Data()), ivalue);
567          mapOROCs->AddAt((AliTPCCalROC*)mapFile.Get((nameROC + "OROC").Data()), ivalue);
568          mapNames[ivalue].Append(nameROC);
569       }
570       
571       for (Int_t ivalue = 0; ivalue < mapEntries; ivalue++) {
572          mapIROCArray[ivalue].ResizeTo(tpcROCinstance->GetNChannels(0));
573          mapOROCArray[ivalue].ResizeTo(tpcROCinstance->GetNChannels(36));
574       
575          for (UInt_t ichannel = 0; ichannel < tpcROCinstance->GetNChannels(0); ichannel++)
576             (mapIROCArray[ivalue])[ichannel] = ((AliTPCCalROC*)(mapIROCs->At(ivalue)))->GetValue(ichannel);
577          for (UInt_t ichannel = 0; ichannel < tpcROCinstance->GetNChannels(36); ichannel++)
578             (mapOROCArray[ivalue])[ichannel] = ((AliTPCCalROC*)(mapOROCs->At(ivalue)))->GetValue(ichannel);
579       }
580
581    } //  if (mapFileName)
582   
583    TTreeSRedirector cstream(fileName);
584    Int_t arrayEntries = array->GetEntries();
585    
586    TString* names = new TString[arrayEntries];
587    for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++)
588       names[ivalue].Append(((AliTPCCalPad*)array->At(ivalue))->GetName());
589
590    for (UInt_t isector = 0; isector < tpcROCinstance->GetNSectors(); isector++) {
591       //
592       // get statistic for given sector
593       //
594       TVectorF median(arrayEntries);
595       TVectorF mean(arrayEntries);
596       TVectorF rms(arrayEntries);
597       TVectorF ltm(arrayEntries);
598       TVectorF ltmrms(arrayEntries);
599       TVectorF medianWithOut(arrayEntries);
600       TVectorF meanWithOut(arrayEntries);
601       TVectorF rmsWithOut(arrayEntries);
602       TVectorF ltmWithOut(arrayEntries);
603       TVectorF ltmrmsWithOut(arrayEntries);
604       
605       TVectorF *vectorArray = new TVectorF[arrayEntries];
606       for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++)
607          vectorArray[ivalue].ResizeTo(tpcROCinstance->GetNChannels(isector));
608       
609       for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++) {
610          AliTPCCalPad* calPad = (AliTPCCalPad*) array->At(ivalue);
611          AliTPCCalROC* calROC = calPad->GetCalROC(isector);
612          AliTPCCalROC* outlierROC = 0;
613          if (outlierPad) outlierROC = outlierPad->GetCalROC(isector);
614          if (calROC) {
615             median[ivalue] = calROC->GetMedian();
616             mean[ivalue] = calROC->GetMean();
617             rms[ivalue] = calROC->GetRMS();
618             Double_t ltmrmsValue = 0;
619             ltm[ivalue] = calROC->GetLTM(&ltmrmsValue, ltmFraction);
620             ltmrms[ivalue] = ltmrmsValue;
621             if (outlierROC) {
622                medianWithOut[ivalue] = calROC->GetMedian(outlierROC);
623                meanWithOut[ivalue] = calROC->GetMean(outlierROC);
624                rmsWithOut[ivalue] = calROC->GetRMS(outlierROC);
625                ltmrmsValue = 0;
626                ltmWithOut[ivalue] = calROC->GetLTM(&ltmrmsValue, ltmFraction, outlierROC);
627                ltmrmsWithOut[ivalue] = ltmrmsValue;
628             }
629          }
630          else {
631             median[ivalue] = 0.;
632             mean[ivalue] = 0.;
633             rms[ivalue] = 0.;
634             ltm[ivalue] = 0.;
635             ltmrms[ivalue] = 0.;
636             medianWithOut[ivalue] = 0.;
637             meanWithOut[ivalue] = 0.;
638             rmsWithOut[ivalue] = 0.;
639             ltmWithOut[ivalue] = 0.;
640             ltmrmsWithOut[ivalue] = 0.;
641          }
642       }
643       
644       //
645       // fill vectors of variable per pad
646       //
647       TVectorF *posArray = new TVectorF[8];
648       for (Int_t ivalue = 0; ivalue < 8; ivalue++)
649          posArray[ivalue].ResizeTo(tpcROCinstance->GetNChannels(isector));
650
651       Float_t posG[3] = {0};
652       Float_t posL[3] = {0};
653       Int_t ichannel = 0;
654       for (UInt_t irow = 0; irow < tpcROCinstance->GetNRows(isector); irow++) {
655          for (UInt_t ipad = 0; ipad < tpcROCinstance->GetNPads(isector, irow); ipad++) {
656             tpcROCinstance->GetPositionLocal(isector, irow, ipad, posL);
657             tpcROCinstance->GetPositionGlobal(isector, irow, ipad, posG);
658             posArray[0][ichannel] = irow;
659             posArray[1][ichannel] = ipad;
660             posArray[2][ichannel] = posL[0];
661             posArray[3][ichannel] = posL[1];
662             posArray[4][ichannel] = posG[0];
663             posArray[5][ichannel] = posG[1];
664             posArray[6][ichannel] = (Int_t)(ipad - (Double_t)(tpcROCinstance->GetNPads(isector, irow))/2);
665             posArray[7][ichannel] = ichannel;
666             
667             // loop over array containing AliTPCCalPads
668             for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++) {
669                AliTPCCalPad* calPad = (AliTPCCalPad*) array->At(ivalue);
670                AliTPCCalROC* calROC = calPad->GetCalROC(isector);
671                if (calROC)
672                   (vectorArray[ivalue])[ichannel] = calROC->GetValue(irow, ipad);
673                else
674                   (vectorArray[ivalue])[ichannel] = 0;
675             }
676             ichannel++;
677          }
678       }
679       
680       cstream << "calPads" <<
681          "sector=" << isector;
682       
683       for  (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++) {
684          cstream << "calPads" <<
685             (Char_t*)((names[ivalue] + "_Median=").Data()) << median[ivalue] <<
686             (Char_t*)((names[ivalue] + "_Mean=").Data()) << mean[ivalue] <<
687             (Char_t*)((names[ivalue] + "_RMS=").Data()) << rms[ivalue] <<
688             (Char_t*)((names[ivalue] + "_LTM=").Data()) << ltm[ivalue] <<
689             (Char_t*)((names[ivalue] + "_RMS_LTM=").Data()) << ltmrms[ivalue];
690          if (outlierPad) {
691             cstream << "calPads" <<
692                (Char_t*)((names[ivalue] + "_Median_OutlierCutted=").Data()) << medianWithOut[ivalue] <<
693                (Char_t*)((names[ivalue] + "_Mean_OutlierCutted=").Data()) << meanWithOut[ivalue] <<
694                (Char_t*)((names[ivalue] + "_RMS_OutlierCutted=").Data()) << rmsWithOut[ivalue] <<
695                (Char_t*)((names[ivalue] + "_LTM_OutlierCutted=").Data()) << ltmWithOut[ivalue] <<
696                (Char_t*)((names[ivalue] + "_RMS_LTM_OutlierCutted=").Data()) << ltmrmsWithOut[ivalue];
697          }
698       }
699
700       for  (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++) {
701          cstream << "calPads" <<
702             (Char_t*)((names[ivalue] + ".=").Data()) << &vectorArray[ivalue];
703       }
704
705       if (mapFileName) {
706          for  (Int_t ivalue = 0; ivalue < mapEntries; ivalue++) {
707             if (isector < 36)
708                cstream << "calPads" <<
709                   (Char_t*)((mapNames[ivalue] + ".=").Data()) << &mapIROCArray[ivalue];
710             else
711                cstream << "calPads" <<
712                   (Char_t*)((mapNames[ivalue] + ".=").Data()) << &mapOROCArray[ivalue];
713          }
714       }
715
716       cstream << "calPads" <<
717          "row.=" << &posArray[0] <<
718          "pad.=" << &posArray[1] <<
719          "lx.=" << &posArray[2] <<
720          "ly.=" << &posArray[3] <<
721          "gx.=" << &posArray[4] <<
722          "gy.=" << &posArray[5] <<
723          "rpad.=" << &posArray[6] <<
724          "channel.=" << &posArray[7];
725          
726       cstream << "calPads" <<
727          "\n";
728
729       delete[] posArray;
730       delete[] vectorArray;
731    }
732    
733
734    delete[] names;
735    if (mapFileName) {
736       delete mapIROCs;
737       delete mapOROCs;
738       delete[] mapIROCArray;
739       delete[] mapOROCArray;
740       delete[] mapNames;
741    }
742 }
743
744
745
746 void AliTPCcalibDB::RegisterExB(Int_t index, Float_t bz, Bool_t bdelete){
747   //
748   // Register static ExB correction map
749   // index - registration index - used for visualization
750   // bz    - bz field in kGaus
751
752   //  Float_t factor =  bz/(-5.);  // default b filed in Cheb with minus sign
753   Float_t factor =  bz/(5.);  // default b filed in Cheb with minus sign
754                               // was chenged in the Revision ???? (Ruben can you add here number)
755   
756   AliMagF*   bmap = new AliMagF("MapsExB","MapsExB", factor,TMath::Sign(1.f,factor),AliMagF::k5kG);
757   
758   AliTPCExBFirst *exb  = new  AliTPCExBFirst(bmap,0.88*2.6400e+04,50,50,50);
759   AliTPCExB::SetInstance(exb);
760   
761   if (bdelete){
762     delete bmap;
763   }else{
764     AliTPCExB::RegisterField(index,bmap);
765   }
766   if (index>=fgExBArray.GetEntries()) fgExBArray.Expand((index+1)*2+11);
767   fgExBArray.AddAt(exb,index);
768 }
769
770
771 AliTPCExB*    AliTPCcalibDB::GetExB(Float_t bz, Bool_t deleteB) {
772   //
773   // bz filed in KGaus not in tesla
774   // Get ExB correction map
775   // if doesn't exist - create it
776   //
777   Int_t index = TMath::Nint(5+bz);
778   if (index>fgExBArray.GetEntries()) fgExBArray.Expand((index+1)*2+11);
779   if (!fgExBArray.At(index)) AliTPCcalibDB::RegisterExB(index,bz,deleteB);
780   return (AliTPCExB*)fgExBArray.At(index);
781 }
782
783
784 void  AliTPCcalibDB::SetExBField(Float_t bz){
785   //
786   // Set magnetic filed for ExB correction
787   //
788   fExB = GetExB(bz,kFALSE);
789 }
790
791 void  AliTPCcalibDB::SetExBField(const AliMagF*   bmap){
792   //
793   // Set magnetic field for ExB correction
794   //
795   AliTPCExBFirst *exb  = new  AliTPCExBFirst(bmap,0.88*2.6400e+04,50,50,50);
796   AliTPCExB::SetInstance(exb);
797   fExB=exb;
798 }
799
800
801
802
803
804 void AliTPCcalibDB::UpdateRunInformations( Int_t run, Bool_t force){
805   //
806   // - > Don't use it for reconstruction - Only for Calibration studies
807   //
808   if (run<0) return;
809   if (fRunList[run]>0 &&force==kFALSE) return;
810   AliCDBEntry * entry = 0;
811   if (run>= fRunList.GetSize()){
812     fRunList.Set(run*2+1);
813     fGRPArray.Expand(run*2+1);
814     fGRPMaps.Expand(run*2+1);
815     fGoofieArray.Expand(run*2+1);
816     fVoltageArray.Expand(run*2+1); 
817     fTemperatureArray.Expand(run*2+1);
818     fVdriftArray.Expand(run*2+1);
819     fDriftCorrectionArray.Expand(run*2+1);
820     fTimeGainSplinesArray.Expand(run*2+1);
821   }
822
823   fRunList[run]=1;  // sign as used
824
825   //
826   entry = AliCDBManager::Instance()->Get("GRP/GRP/Data",run);
827   if (entry)  {
828     AliGRPObject * grpRun = dynamic_cast<AliGRPObject*>(entry->GetObject());
829     if (!grpRun){
830       TMap* map = dynamic_cast<TMap*>(entry->GetObject());
831       if (map){
832         //grpRun = new AliGRPObject; 
833         //grpRun->ReadValuesFromMap(map);
834         grpRun =  MakeGRPObjectFromMap(map);
835
836         fGRPMaps.AddAt(map,run);
837       }
838     }
839     fGRPArray.AddAt(grpRun,run);
840   }
841   entry = AliCDBManager::Instance()->Get("TPC/Calib/Goofie",run);
842   if (entry){
843     fGoofieArray.AddAt(entry->GetObject(),run);
844   }
845   //
846   entry = AliCDBManager::Instance()->Get("TPC/Calib/HighVoltage",run);
847   if (entry)  {
848     fVoltageArray.AddAt(entry->GetObject(),run);
849   }
850   //
851   entry = AliCDBManager::Instance()->Get("TPC/Calib/TimeGain",run);
852   if (entry)  {
853     fTimeGainSplinesArray.AddAt(entry->GetObject(),run);
854   }
855   //
856   entry = AliCDBManager::Instance()->Get("TPC/Calib/TimeDrift",run);
857   if (entry)  {
858     fDriftCorrectionArray.AddAt(entry->GetObject(),run);
859   }
860   //
861   entry = AliCDBManager::Instance()->Get("TPC/Calib/Temperature",run);
862   if (entry)  {
863     fTemperatureArray.AddAt(entry->GetObject(),run);
864   }
865   //apply fDButil filters
866
867   fDButil->UpdateFromCalibDB();
868   if (fTemperature) fDButil->FilterTemperature(fTemperature);
869
870   AliDCSSensor * press = GetPressureSensor(run,0);
871   AliTPCSensorTempArray * temp = GetTemperatureSensor(run);
872   Bool_t accept=kTRUE;
873   if (temp) {
874     accept = fDButil->FilterTemperature(temp)>0.1;
875   }
876   if (press) {
877     const Double_t kMinP=950.;
878     const Double_t kMaxP=1050.;
879     const Double_t kMaxdP=10.;
880     const Double_t kSigmaCut=4.;
881     fDButil->FilterSensor(press,kMinP,kMaxP,kMaxdP,kSigmaCut);
882     if (press->GetFit()==0) accept=kFALSE;
883   }
884   if (press && temp &&accept){
885     AliTPCCalibVdrift * vdrift = new AliTPCCalibVdrift(temp, press,0);
886     fVdriftArray.AddAt(vdrift,run);
887   }
888   fDButil->FilterCE(120., 3., 4.,0);
889   fDButil->FilterTracks(run, 10.,0);
890 }
891
892
893 Float_t AliTPCcalibDB::GetGain(Int_t sector, Int_t row, Int_t pad){
894   //
895   //
896   AliTPCCalPad *calPad = Instance()->fDedxGainFactor;;
897   if (!calPad) return 0;
898   return calPad->GetCalROC(sector)->GetValue(row,pad);
899 }
900
901 AliSplineFit* AliTPCcalibDB::GetVdriftSplineFit(const char* name, Int_t run){
902   //
903   //
904   //
905   TObjArray *arr=GetTimeVdriftSplineRun(run);
906   if (!arr) return 0;
907   return dynamic_cast<AliSplineFit*>(arr->FindObject(name));
908 }
909
910 AliSplineFit* AliTPCcalibDB::CreateVdriftSplineFit(const char* graphName, Int_t run){
911   //
912   // create spline fit from the drift time graph in TimeDrift
913   //
914   TObjArray *arr=GetTimeVdriftSplineRun(run);
915   if (!arr) return 0;
916   TGraph *graph=dynamic_cast<TGraph*>(arr->FindObject(graphName));
917   if (!graph) return 0;
918   AliSplineFit *fit = new AliSplineFit();
919   fit->SetGraph(graph);
920   fit->SetMinPoints(graph->GetN()+1);
921   fit->InitKnots(graph,2,0,0.001);
922   fit->SplineFit(0);
923   return fit;
924 }
925
926 AliGRPObject *AliTPCcalibDB::GetGRP(Int_t run){
927   //
928   // Get GRP object for given run 
929   //
930   AliGRPObject * grpRun = dynamic_cast<AliGRPObject *>((Instance()->fGRPArray).At(run));
931   if (!grpRun) {
932     Instance()->UpdateRunInformations(run);
933     grpRun = dynamic_cast<AliGRPObject *>(Instance()->fGRPArray.At(run));
934     if (!grpRun) return 0; 
935   }
936   return grpRun;
937 }
938
939 TMap *  AliTPCcalibDB::GetGRPMap(Int_t run){
940   //
941   //
942   //
943   TMap * grpRun = dynamic_cast<TMap *>((Instance()->fGRPMaps).At(run));
944   if (!grpRun) {
945     Instance()->UpdateRunInformations(run);
946     grpRun = dynamic_cast<TMap *>(Instance()->fGRPMaps.At(run));
947     if (!grpRun) return 0; 
948   }
949   return grpRun;
950 }
951
952
953 AliDCSSensor * AliTPCcalibDB::GetPressureSensor(Int_t run, Int_t type){
954   //
955   // Get Pressure sensor
956   // run  = run number
957   // type = 0 - Cavern pressure
958   //        1 - Suface pressure
959   // First try to get if trom map - if existing  (Old format of data storing)
960   //
961
962
963   TMap *map = GetGRPMap(run);  
964   if (map){
965     AliDCSSensor * sensor = 0;
966     TObject *osensor=0;
967     if (type==0) osensor = ((*map)("fCavernPressure"));
968     if (type==1) osensor = ((*map)("fP2Pressure"));
969     sensor =dynamic_cast<AliDCSSensor *>(osensor); 
970     if (sensor) return sensor;
971   }
972   //
973   // If not map try to get it from the GRPObject
974   //
975   AliGRPObject * grpRun = dynamic_cast<AliGRPObject *>(fGRPArray.At(run)); 
976   if (!grpRun) {
977     UpdateRunInformations(run);
978     grpRun = dynamic_cast<AliGRPObject *>(fGRPArray.At(run));
979     if (!grpRun) return 0; 
980   }
981   AliDCSSensor * sensor = grpRun->GetCavernAtmosPressure();
982   if (type==1) sensor = grpRun->GetSurfaceAtmosPressure();
983   return sensor; 
984 }
985
986 AliTPCSensorTempArray * AliTPCcalibDB::GetTemperatureSensor(Int_t run){
987   //
988   // Get temperature sensor array
989   //
990   AliTPCSensorTempArray * tempArray = (AliTPCSensorTempArray *)fTemperatureArray.At(run);
991   if (!tempArray) {
992     UpdateRunInformations(run);
993     tempArray = (AliTPCSensorTempArray *)fTemperatureArray.At(run);
994   }
995   return tempArray;
996 }
997
998
999 TObjArray * AliTPCcalibDB::GetTimeGainSplinesRun(Int_t run){
1000   //
1001   // Get temperature sensor array
1002   //
1003   TObjArray * gainSplines = (TObjArray *)fTimeGainSplinesArray.At(run);
1004   if (!gainSplines) {
1005     UpdateRunInformations(run);
1006     gainSplines = (TObjArray *)fTimeGainSplinesArray.At(run);
1007   }
1008   return gainSplines;
1009 }
1010
1011 TObjArray * AliTPCcalibDB::GetTimeVdriftSplineRun(Int_t run){
1012   //
1013   // Get drift spline array
1014   //
1015   TObjArray * driftSplines = (TObjArray *)fDriftCorrectionArray.At(run);
1016   if (!driftSplines) {
1017     UpdateRunInformations(run);
1018     driftSplines = (TObjArray *)fDriftCorrectionArray.At(run);
1019   }
1020   return driftSplines;
1021 }
1022
1023 AliDCSSensorArray * AliTPCcalibDB::GetVoltageSensors(Int_t run){
1024   //
1025   // Get temperature sensor array
1026   //
1027   AliDCSSensorArray * voltageArray = (AliDCSSensorArray *)fVoltageArray.At(run);
1028   if (!voltageArray) {
1029     UpdateRunInformations(run);
1030     voltageArray = (AliDCSSensorArray *)fVoltageArray.At(run);
1031   }
1032   return voltageArray;
1033 }
1034
1035 AliDCSSensorArray * AliTPCcalibDB::GetGoofieSensors(Int_t run){
1036   //
1037   // Get temperature sensor array
1038   //
1039   AliDCSSensorArray * goofieArray = (AliDCSSensorArray *)fGoofieArray.At(run);
1040   if (!goofieArray) {
1041     UpdateRunInformations(run);
1042     goofieArray = (AliDCSSensorArray *)fGoofieArray.At(run);
1043   }
1044   return goofieArray;
1045 }
1046
1047
1048
1049 AliTPCCalibVdrift *     AliTPCcalibDB::GetVdrift(Int_t run){
1050   //
1051   // Get the interface to the the vdrift 
1052   //
1053   AliTPCCalibVdrift  * vdrift = (AliTPCCalibVdrift*)fVdriftArray.At(run);
1054   if (!vdrift) {
1055     UpdateRunInformations(run);
1056     vdrift= (AliTPCCalibVdrift*)fVdriftArray.At(run);
1057   }
1058   return vdrift;
1059 }
1060
1061 Float_t AliTPCcalibDB::GetCEdriftTime(Int_t run, Int_t sector, Double_t timeStamp, Int_t *entries)
1062 {
1063   //
1064   // GetCE drift time information for 'sector'
1065   // sector 72 is the mean drift time of the A-Side
1066   // sector 73 is the mean drift time of the C-Side
1067   // it timestamp==-1 return mean value
1068   //
1069   AliTPCcalibDB::Instance()->SetRun(run);
1070   TGraph *gr=AliTPCcalibDB::Instance()->GetCErocTgraph(sector);
1071   if (!gr||sector<0||sector>73) {
1072     if (entries) *entries=0;
1073     return 0.;
1074   }
1075   Float_t val=0.;
1076   if (timeStamp==-1.){
1077     val=gr->GetMean(2);
1078   }else{
1079     for (Int_t ipoint=0;ipoint<gr->GetN();++ipoint){
1080       Double_t x,y;
1081       gr->GetPoint(ipoint,x,y);
1082       if (x<timeStamp) continue;
1083       val=y;
1084       break;
1085     }
1086   }
1087   return val;
1088 }
1089   
1090 Float_t AliTPCcalibDB::GetCEchargeTime(Int_t run, Int_t sector, Double_t timeStamp, Int_t *entries)
1091 {
1092   //
1093   // GetCE mean charge for 'sector'
1094   // it timestamp==-1 return mean value
1095   //
1096   AliTPCcalibDB::Instance()->SetRun(run);
1097   TGraph *gr=AliTPCcalibDB::Instance()->GetCErocQgraph(sector);
1098   if (!gr||sector<0||sector>71) {
1099     if (entries) *entries=0;
1100     return 0.;
1101   }
1102   Float_t val=0.;
1103   if (timeStamp==-1.){
1104     val=gr->GetMean(2);
1105   }else{
1106     for (Int_t ipoint=0;ipoint<gr->GetN();++ipoint){
1107       Double_t x,y;
1108       gr->GetPoint(ipoint,x,y);
1109       if (x<timeStamp) continue;
1110       val=y;
1111       break;
1112     }
1113   }
1114   return val;
1115 }
1116
1117 Float_t AliTPCcalibDB::GetDCSSensorValue(AliDCSSensorArray *arr, Int_t timeStamp, const char * sensorName, Int_t sigDigits)
1118 {
1119   //
1120   // Get Value for a DCS sensor 'sensorName', run 'run' at time 'timeStamp'
1121   //
1122   Float_t val=0;
1123   const TString sensorNameString(sensorName);
1124   AliDCSSensor *sensor = arr->GetSensor(sensorNameString);
1125   if (!sensor) return val;
1126   //use the dcs graph if possible
1127   TGraph *gr=sensor->GetGraph();
1128   if (gr){
1129     for (Int_t ipoint=0;ipoint<gr->GetN();++ipoint){
1130       Double_t x,y;
1131       gr->GetPoint(ipoint,x,y);
1132       Int_t time=TMath::Nint(sensor->GetStartTime()+x*3600); //time in graph is hours
1133       if (time<timeStamp) continue;
1134       val=y;
1135       break;
1136     }
1137     //if val is still 0, test if if the requested time if within 5min of the first/last
1138     //data point. If this is the case return the firs/last entry
1139     //the timestamps might not be syncronised for all calibration types, sometimes a 'pre'
1140     //and 'pos' period is requested. Especially to the HV this is not the case!
1141     //first point
1142     if (val==0 ){
1143       Double_t x,y;
1144       gr->GetPoint(0,x,y);
1145       Int_t time=TMath::Nint(sensor->GetStartTime()+x*3600); //time in graph is hours
1146       if ((time-timeStamp)<5*60) val=y;
1147     }
1148     //last point
1149     if (val==0 ){
1150       Double_t x,y;
1151       gr->GetPoint(gr->GetN()-1,x,y);
1152       Int_t time=TMath::Nint(sensor->GetStartTime()+x*3600); //time in graph is hours
1153       if ((timeStamp-time)<5*60) val=y;
1154     }
1155   } else {
1156     val=sensor->GetValue(timeStamp);
1157   }
1158   if (sigDigits>=0){
1159     val=(Float_t)TMath::Floor(val * TMath::Power(10., sigDigits) + .5) / TMath::Power(10., sigDigits);
1160   }
1161   return val;
1162 }
1163
1164 Float_t AliTPCcalibDB::GetDCSSensorMeanValue(AliDCSSensorArray *arr, const char * sensorName, Int_t sigDigits)
1165 {
1166   //
1167   // Get mean Value for a DCS sensor 'sensorName' during run 'run'
1168   //
1169   Float_t val=0;
1170   const TString sensorNameString(sensorName);
1171   AliDCSSensor *sensor = arr->GetSensor(sensorNameString);
1172   if (!sensor) return val;
1173
1174   //use dcs graph if it exists
1175   TGraph *gr=sensor->GetGraph();
1176   if (gr){
1177     val=gr->GetMean(2);
1178   } else {
1179     //if we don't have the dcs graph, try to get some meaningful information
1180     if (!sensor->GetFit()) return val;
1181     Int_t nKnots=sensor->GetFit()->GetKnots();
1182     Double_t tMid=(sensor->GetEndTime()-sensor->GetStartTime())/2.;
1183     for (Int_t iKnot=0;iKnot<nKnots;++iKnot){
1184       if (sensor->GetFit()->GetX()[iKnot]>tMid/3600.) break;
1185       val=(Float_t)sensor->GetFit()->GetY0()[iKnot];
1186     }
1187   }
1188   if (sigDigits>=0){
1189     val/=10;
1190     val=(Float_t)TMath::Floor(val * TMath::Power(10., sigDigits) + .5) / TMath::Power(10., sigDigits);
1191     val*=10;
1192   }
1193   return val;
1194 }
1195
1196 Float_t AliTPCcalibDB::GetChamberHighVoltage(Int_t run, Int_t sector, Int_t timeStamp, Int_t sigDigits) {
1197   //
1198   // return the chamber HV for given run and time: 0-35 IROC, 36-72 OROC
1199   // if timeStamp==-1 return mean value
1200   //
1201   Float_t val=0;
1202   TString sensorName="";
1203   TTimeStamp stamp(timeStamp);
1204   AliDCSSensorArray* voltageArray = AliTPCcalibDB::Instance()->GetVoltageSensors(run);
1205   if (!voltageArray || (sector<0) || (sector>71)) return val;
1206   Char_t sideName='A';
1207   if ((sector/18)%2==1) sideName='C';
1208   if (sector<36){
1209     //IROC
1210     sensorName=Form("TPC_ANODE_I_%c%02d_VMEAS",sideName,sector%18);
1211   }else{
1212     //OROC
1213     sensorName=Form("TPC_ANODE_O_%c%02d_0_VMEAS",sideName,sector%18);
1214   }
1215   if (timeStamp==-1){
1216     val=AliTPCcalibDB::GetDCSSensorMeanValue(voltageArray, sensorName.Data(),sigDigits);
1217   } else {
1218     val=AliTPCcalibDB::GetDCSSensorValue(voltageArray, timeStamp, sensorName.Data(),sigDigits);
1219   }
1220   return val;
1221 }
1222 Float_t AliTPCcalibDB::GetSkirtVoltage(Int_t run, Int_t sector, Int_t timeStamp, Int_t sigDigits)
1223 {
1224   //
1225   // Get the skirt voltage for 'run' at 'timeStamp' and 'sector': 0-35 IROC, 36-72 OROC
1226   // type corresponds to the following: 0 - IROC A-Side; 1 - IROC C-Side; 2 - OROC A-Side; 3 - OROC C-Side
1227   // if timeStamp==-1 return the mean value for the run
1228   //
1229   Float_t val=0;
1230   TString sensorName="";
1231   TTimeStamp stamp(timeStamp);
1232   AliDCSSensorArray* voltageArray = AliTPCcalibDB::Instance()->GetVoltageSensors(run);
1233   if (!voltageArray || (sector<0) || (sector>71)) return val;
1234   Char_t sideName='A';
1235   if ((sector/18)%2==1) sideName='C';
1236   sensorName=Form("TPC_SKIRT_%c_VMEAS",sideName);
1237   if (timeStamp==-1){
1238     val=AliTPCcalibDB::GetDCSSensorMeanValue(voltageArray, sensorName.Data(),sigDigits);
1239   } else {
1240     val=AliTPCcalibDB::GetDCSSensorValue(voltageArray, timeStamp, sensorName.Data(),sigDigits);
1241   }
1242   return val;
1243 }
1244
1245 Float_t AliTPCcalibDB::GetCoverVoltage(Int_t run, Int_t sector, Int_t timeStamp, Int_t sigDigits)
1246 {
1247   //
1248   // Get the cover voltage for run 'run' at time 'timeStamp'
1249   // type corresponds to the following: 0 - IROC A-Side; 1 - IROC C-Side; 2 - OROC A-Side; 3 - OROC C-Side
1250   // if timeStamp==-1 return the mean value for the run
1251   //
1252   Float_t val=0;
1253   TString sensorName="";
1254   TTimeStamp stamp(timeStamp);
1255   AliDCSSensorArray* voltageArray = AliTPCcalibDB::Instance()->GetVoltageSensors(run);
1256   if (!voltageArray || (sector<0) || (sector>71)) return val;
1257   Char_t sideName='A';
1258   if ((sector/18)%2==1) sideName='C';
1259   if (sector<36){
1260     //IROC
1261     sensorName=Form("TPC_COVER_I_%c_VMEAS",sideName);
1262   }else{
1263     //OROC
1264     sensorName=Form("TPC_COVER_O_%c_VMEAS",sideName);
1265   }
1266   if (timeStamp==-1){
1267     val=AliTPCcalibDB::GetDCSSensorMeanValue(voltageArray, sensorName.Data(),sigDigits);
1268   } else {
1269     val=AliTPCcalibDB::GetDCSSensorValue(voltageArray, timeStamp, sensorName.Data(),sigDigits);
1270   }
1271   return val;
1272 }
1273
1274 Float_t AliTPCcalibDB::GetGGoffsetVoltage(Int_t run, Int_t sector, Int_t timeStamp, Int_t sigDigits)
1275 {
1276   //
1277   // Get the GG offset voltage for run 'run' at time 'timeStamp'
1278   // type corresponds to the following: 0 - IROC A-Side; 1 - IROC C-Side; 2 - OROC A-Side; 3 - OROC C-Side
1279   // if timeStamp==-1 return the mean value for the run
1280   //
1281   Float_t val=0;
1282   TString sensorName="";
1283   TTimeStamp stamp(timeStamp);
1284   AliDCSSensorArray* voltageArray = AliTPCcalibDB::Instance()->GetVoltageSensors(run);
1285   if (!voltageArray || (sector<0) || (sector>71)) return val;
1286   Char_t sideName='A';
1287   if ((sector/18)%2==1) sideName='C';
1288   if (sector<36){
1289     //IROC
1290     sensorName=Form("TPC_GATE_I_%c_OFF_VMEAS",sideName);
1291   }else{
1292     //OROC
1293     sensorName=Form("TPC_GATE_O_%c_OFF_VMEAS",sideName);
1294   }
1295   if (timeStamp==-1){
1296     val=AliTPCcalibDB::GetDCSSensorMeanValue(voltageArray, sensorName.Data(),sigDigits);
1297   } else {
1298     val=AliTPCcalibDB::GetDCSSensorValue(voltageArray, timeStamp, sensorName.Data(),sigDigits);
1299   }
1300   return val;
1301 }
1302
1303 Float_t AliTPCcalibDB::GetGGnegVoltage(Int_t run, Int_t sector, Int_t timeStamp, Int_t sigDigits)
1304 {
1305   //
1306   // Get the GG offset voltage for run 'run' at time 'timeStamp'
1307   // type corresponds to the following: 0 - IROC A-Side; 1 - IROC C-Side; 2 - OROC A-Side; 3 - OROC C-Side
1308   // if timeStamp==-1 return the mean value for the run
1309   //
1310   Float_t val=0;
1311   TString sensorName="";
1312   TTimeStamp stamp(timeStamp);
1313   AliDCSSensorArray* voltageArray = AliTPCcalibDB::Instance()->GetVoltageSensors(run);
1314   if (!voltageArray || (sector<0) || (sector>71)) return val;
1315   Char_t sideName='A';
1316   if ((sector/18)%2==1) sideName='C';
1317   if (sector<36){
1318     //IROC
1319     sensorName=Form("TPC_GATE_I_%c_NEG_VMEAS",sideName);
1320   }else{
1321     //OROC
1322     sensorName=Form("TPC_GATE_O_%c_NEG_VMEAS",sideName);
1323   }
1324   if (timeStamp==-1){
1325     val=AliTPCcalibDB::GetDCSSensorMeanValue(voltageArray, sensorName.Data(),sigDigits);
1326   } else {
1327     val=AliTPCcalibDB::GetDCSSensorValue(voltageArray, timeStamp, sensorName.Data(),sigDigits);
1328   }
1329   return val;
1330 }
1331
1332 Float_t AliTPCcalibDB::GetGGposVoltage(Int_t run, Int_t sector, Int_t timeStamp, Int_t sigDigits)
1333 {
1334   //
1335   // Get the GG offset voltage for run 'run' at time 'timeStamp'
1336   // type corresponds to the following: 0 - IROC A-Side; 1 - IROC C-Side; 2 - OROC A-Side; 3 - OROC C-Side
1337   // if timeStamp==-1 return the mean value for the run
1338   //
1339   Float_t val=0;
1340   TString sensorName="";
1341   TTimeStamp stamp(timeStamp);
1342   AliDCSSensorArray* voltageArray = AliTPCcalibDB::Instance()->GetVoltageSensors(run);
1343   if (!voltageArray || (sector<0) || (sector>71)) return val;
1344   Char_t sideName='A';
1345   if ((sector/18)%2==1) sideName='C';
1346   if (sector<36){
1347     //IROC
1348     sensorName=Form("TPC_GATE_I_%c_POS_VMEAS",sideName);
1349   }else{
1350     //OROC
1351     sensorName=Form("TPC_GATE_O_%c_POS_VMEAS",sideName);
1352   }
1353   if (timeStamp==-1){
1354     val=AliTPCcalibDB::GetDCSSensorMeanValue(voltageArray, sensorName.Data(),sigDigits);
1355   } else {
1356     val=AliTPCcalibDB::GetDCSSensorValue(voltageArray, timeStamp, sensorName.Data(),sigDigits);
1357   }
1358   return val;
1359 }
1360
1361 Float_t AliTPCcalibDB::GetPressure(Int_t timeStamp, Int_t run, Int_t type){
1362   //
1363   // GetPressure for given time stamp and runt
1364   //
1365   TTimeStamp stamp(timeStamp);
1366   AliDCSSensor * sensor = Instance()->GetPressureSensor(run,type);
1367   if (!sensor) return 0;
1368   return sensor->GetValue(stamp);
1369 }
1370
1371 Float_t AliTPCcalibDB::GetL3Current(Int_t run, Int_t statType){
1372   //
1373   // return L3 current
1374   // stat type is: AliGRPObject::Stats: kMean = 0, kTruncMean = 1, kMedian = 2, kSDMean = 3, kSDMedian = 4
1375   //
1376   Float_t current=-1;
1377   AliGRPObject *grp=AliTPCcalibDB::GetGRP(run);
1378   if (grp) current=grp->GetL3Current((AliGRPObject::Stats)statType);
1379   return current;
1380 }
1381
1382 Float_t AliTPCcalibDB::GetBz(Int_t run){
1383   //
1384   // calculate BZ in T from L3 current
1385   //
1386   Float_t bz=-1;
1387   Float_t current=AliTPCcalibDB::GetL3Current(run);
1388   if (current>-1) bz=5*current/30000.*.1;
1389   return bz;
1390 }
1391
1392 Char_t  AliTPCcalibDB::GetL3Polarity(Int_t run) {
1393   //
1394   // get l3 polarity from GRP
1395   //
1396   Char_t pol=-100;
1397   AliGRPObject *grp=AliTPCcalibDB::GetGRP(run);
1398   if (grp) pol=grp->GetL3Polarity();
1399   return pol;
1400 }
1401
1402 TString AliTPCcalibDB::GetRunType(Int_t run){
1403   //
1404   // return run type from grp
1405   //
1406
1407 //   TString type("UNKNOWN");
1408   AliGRPObject *grp=AliTPCcalibDB::GetGRP(run);
1409   if (grp) return grp->GetRunType();
1410   return "UNKNOWN";
1411 }
1412
1413 Float_t AliTPCcalibDB::GetValueGoofie(Int_t timeStamp, Int_t run, Int_t type){
1414   //
1415   // GetPressure for given time stamp and runt
1416   //
1417   TTimeStamp stamp(timeStamp);
1418   AliDCSSensorArray* goofieArray = AliTPCcalibDB::Instance()->GetGoofieSensors(run);
1419   if (!goofieArray) return 0;
1420   AliDCSSensor *sensor = goofieArray->GetSensor(type);
1421   return sensor->GetValue(stamp);
1422 }
1423
1424
1425
1426
1427
1428
1429 Bool_t  AliTPCcalibDB::GetTemperatureFit(Int_t timeStamp, Int_t run, Int_t side,TVectorD& fit){
1430   //
1431   //
1432   //
1433   TTimeStamp tstamp(timeStamp);
1434   AliTPCSensorTempArray* tempArray  = Instance()->GetTemperatureSensor(run);
1435   if (! tempArray) return kFALSE;
1436   AliTPCTempMap * tempMap = new AliTPCTempMap(tempArray);
1437   TLinearFitter * fitter = tempMap->GetLinearFitter(3,side,tstamp);
1438   if (fitter){
1439     fitter->Eval(); 
1440     fitter->GetParameters(fit);
1441   }
1442   delete fitter;
1443   delete tempMap;
1444   if (!fitter) return kFALSE;
1445   return kTRUE;
1446 }
1447
1448 Float_t AliTPCcalibDB::GetTemperature(Int_t timeStamp, Int_t run, Int_t side){
1449   //
1450   //
1451   //
1452   TVectorD vec(5);
1453   if (side==0) {
1454     GetTemperatureFit(timeStamp,run,0,vec);
1455     return vec[0];
1456   }
1457   if (side==1){
1458     GetTemperatureFit(timeStamp,run,0,vec);
1459     return vec[0];
1460   }
1461   return 0;
1462 }
1463
1464
1465 Double_t AliTPCcalibDB::GetPTRelative(UInt_t timeSec, Int_t run, Int_t side){
1466   //
1467   // Get relative P/T 
1468   // time - absolute time
1469   // run  - run number
1470   // side - 0 - A side   1-C side
1471   AliTPCCalibVdrift * vdrift =  Instance()->GetVdrift(run);
1472   if (!vdrift) return 0;
1473   return vdrift->GetPTRelative(timeSec,side);
1474 }
1475
1476 AliGRPObject * AliTPCcalibDB::MakeGRPObjectFromMap(TMap *map){
1477   //
1478   // Function to covert old GRP run information from TMap to GRPObject
1479   //
1480   //  TMap * map = AliTPCcalibDB::GetGRPMap(52406);
1481   if (!map) return 0;
1482   AliDCSSensor * sensor = 0;
1483   TObject *osensor=0;
1484   osensor = ((*map)("fP2Pressure"));
1485   sensor  =dynamic_cast<AliDCSSensor *>(osensor); 
1486   //
1487   if (!sensor) return 0;
1488   //
1489   AliDCSSensor * sensor2 = new AliDCSSensor(*sensor);
1490   osensor = ((*map)("fCavernPressure"));
1491   TGraph * gr = new TGraph(2);
1492   gr->GetX()[0]= -100000.;
1493   gr->GetX()[1]= 1000000.;
1494   gr->GetY()[0]= atof(osensor->GetName());
1495   gr->GetY()[1]= atof(osensor->GetName());
1496   sensor2->SetGraph(gr);
1497   sensor2->SetFit(0);
1498   
1499
1500   AliGRPObject *grpRun = new AliGRPObject; 
1501   grpRun->ReadValuesFromMap(map);
1502   grpRun->SetCavernAtmosPressure(sensor2);
1503   grpRun->SetSurfaceAtmosPressure(sensor);
1504   return grpRun;
1505 }
1506
1507 Bool_t AliTPCcalibDB::CreateGUITree(Int_t run, const char* filename)
1508 {
1509   //
1510   // Create a gui tree for run number 'run'
1511   //
1512
1513   if (!AliCDBManager::Instance()->GetDefaultStorage()){
1514     AliLog::Message(AliLog::kError, "Default Storage not set. Cannot create Calibration Tree!",
1515                     MODULENAME(), "AliTPCcalibDB", FUNCTIONNAME(), __FILE__, __LINE__);
1516     return kFALSE;
1517   }
1518   //db instance
1519   AliTPCcalibDB *db=AliTPCcalibDB::Instance();
1520   // retrieve cal pad objects
1521   db->SetRun(run);
1522   db->CreateGUITree(filename);
1523 }
1524
1525 Bool_t AliTPCcalibDB::CreateGUITree(const char* filename){
1526   //
1527   //
1528   //
1529   if (!AliCDBManager::Instance()->GetDefaultStorage()){
1530     AliError("Default Storage not set. Cannot create calibration Tree!");
1531     return kFALSE;
1532   }
1533   
1534   AliTPCPreprocessorOnline prep;
1535   //noise and pedestals
1536   if (GetPedestals()) prep.AddComponent(new AliTPCCalPad(*(GetPedestals())));
1537   if (GetPadNoise() ) prep.AddComponent(new AliTPCCalPad(*(GetPadNoise())));
1538   //pulser data
1539   if (GetPulserTmean()) prep.AddComponent(new AliTPCCalPad(*(GetPulserTmean())));
1540   if (GetPulserTrms() ) prep.AddComponent(new AliTPCCalPad(*(GetPulserTrms())));
1541   if (GetPulserQmean()) prep.AddComponent(new AliTPCCalPad(*(GetPulserQmean())));
1542   //CE data
1543   if (GetCETmean()) prep.AddComponent(new AliTPCCalPad(*(GetCETmean())));
1544   if (GetCETrms() ) prep.AddComponent(new AliTPCCalPad(*(GetCETrms())));
1545   if (GetCEQmean()) prep.AddComponent(new AliTPCCalPad(*(GetCEQmean())));
1546   //Altro data
1547   if (GetALTROAcqStart() ) prep.AddComponent(new AliTPCCalPad(*(GetALTROAcqStart() )));
1548   if (GetALTROZsThr()    ) prep.AddComponent(new AliTPCCalPad(*(GetALTROZsThr()    )));
1549   if (GetALTROFPED()     ) prep.AddComponent(new AliTPCCalPad(*(GetALTROFPED()     )));
1550   if (GetALTROAcqStop()  ) prep.AddComponent(new AliTPCCalPad(*(GetALTROAcqStop()  )));
1551   if (GetALTROMasked()   ) prep.AddComponent(new AliTPCCalPad(*(GetALTROMasked()   )));
1552   //QA
1553   AliTPCdataQA *dataQA=GetDataQA();
1554   if (dataQA) {
1555     if (dataQA->GetNLocalMaxima())
1556       prep.AddComponent(new AliTPCCalPad(*(dataQA->GetNLocalMaxima())));
1557     if (dataQA->GetMaxCharge())
1558       prep.AddComponent(new AliTPCCalPad(*(dataQA->GetMaxCharge())));
1559     if (dataQA->GetMeanCharge())
1560       prep.AddComponent(new AliTPCCalPad(*(dataQA->GetMeanCharge())));
1561     if (dataQA->GetNoThreshold())
1562       prep.AddComponent(new AliTPCCalPad(*(dataQA->GetNoThreshold())));
1563     if (dataQA->GetNTimeBins())
1564       prep.AddComponent(new AliTPCCalPad(*(dataQA->GetNTimeBins())));
1565     if (dataQA->GetNPads())
1566       prep.AddComponent(new AliTPCCalPad(*(dataQA->GetNPads())));
1567     if (dataQA->GetTimePosition())
1568       prep.AddComponent(new AliTPCCalPad(*(dataQA->GetTimePosition())));
1569   }
1570   
1571   //
1572   TString file(filename);
1573   if (file.IsNull()) file=Form("guiTreeRun_%d.root",fRun);
1574   prep.DumpToFile(file.Data());
1575   return kTRUE;
1576 }
1577
1578 Bool_t AliTPCcalibDB::CreateRefFile(Int_t run, const char* filename)
1579 {
1580   //
1581   // Create a gui tree for run number 'run'
1582   //
1583   
1584   if (!AliCDBManager::Instance()->GetDefaultStorage()){
1585     AliLog::Message(AliLog::kError, "Default Storage not set. Cannot create Calibration Tree!",
1586                     MODULENAME(), "AliTPCcalibDB", FUNCTIONNAME(), __FILE__, __LINE__);
1587     return kFALSE;
1588   }
1589   TString file(filename);
1590   if (file.IsNull()) file=Form("RefCalPads_%d.root",run);
1591   TDirectory *currDir=gDirectory;
1592   //db instance
1593   AliTPCcalibDB *db=AliTPCcalibDB::Instance();
1594   // retrieve cal pad objects
1595   db->SetRun(run);
1596   //open file
1597   TFile f(file.Data(),"recreate");
1598   //noise and pedestals
1599   db->GetPedestals()->Write("Pedestals");
1600   db->GetPadNoise()->Write("PadNoise");
1601   //pulser data
1602   db->GetPulserTmean()->Write("PulserTmean");
1603   db->GetPulserTrms()->Write("PulserTrms");
1604   db->GetPulserQmean()->Write("PulserQmean");
1605   //CE data
1606   db->GetCETmean()->Write("CETmean");
1607   db->GetCETrms()->Write("CETrms");
1608   db->GetCEQmean()->Write("CEQmean");
1609   //Altro data
1610   db->GetALTROAcqStart() ->Write("ALTROAcqStart");
1611   db->GetALTROZsThr()    ->Write("ALTROZsThr");
1612   db->GetALTROFPED()     ->Write("ALTROFPED");
1613   db->GetALTROAcqStop()  ->Write("ALTROAcqStop");
1614   db->GetALTROMasked()   ->Write("ALTROMasked");
1615   //
1616   f.Close();
1617   currDir->cd();
1618   return kTRUE;
1619 }
1620
1621
1622
1623 Double_t AliTPCcalibDB::GetVDriftCorrectionTime(Int_t timeStamp, Int_t run, Int_t /*side*/, Int_t mode){
1624   //
1625   // Get time dependent drift velocity correction
1626   // multiplication factor        vd = vdnom *(1+vdriftcorr)
1627   // Arguments:
1628   // mode determines the algorith how to combine the Laser Track, LaserCE and physics tracks
1629   // timestamp - timestamp
1630   // run       - run number
1631   // side      - the drift velocity per side (possible for laser and CE)
1632   //
1633   // Notice - Extrapolation outside of calibration range  - using constant function
1634   //
1635   Double_t result;
1636   // mode 1  automatic mode - according to the distance to the valid calibration
1637   //                        -  
1638   Double_t deltaP=0,  driftP=0,  wP  = 0.;
1639   Double_t deltaLT=0, driftLT=0, wLT = 0.;
1640   Double_t deltaCE=0, driftCE=0, wCE = 0.;
1641   driftP  = fDButil->GetVDriftTPC(deltaP,run,timeStamp); 
1642   driftCE = fDButil->GetVDriftTPCCE(deltaCE, run,timeStamp,36000,2);
1643   driftLT = fDButil->GetVDriftTPCLaserTracks(deltaLT,run,timeStamp,36000,2);
1644   deltaP   = TMath::Abs(deltaP);
1645   deltaLT  = TMath::Abs(deltaLT);
1646   deltaCE  = TMath::Abs(deltaCE);
1647   if (mode==1) {
1648     const Double_t kEpsilon=0.0000000001;
1649     Double_t meanDist= (deltaP+deltaLT+deltaCE)*0.3;
1650     if (meanDist<1.) return driftLT;
1651     wP  = meanDist/(deltaP +0.005*meanDist);
1652     wLT = meanDist/(deltaLT+0.005*meanDist);
1653     wCE = meanDist/(deltaCE+0.001*meanDist);
1654     if (TMath::Abs(driftCE)<kEpsilon) wCE=0;  // invalid calibration
1655     result = (driftP*wP+driftLT*wLT+driftCE*wCE)/(wP+wLT+wCE);
1656   }
1657
1658   return result;
1659 }
1660
1661 Double_t AliTPCcalibDB::GetTime0CorrectionTime(Int_t timeStamp, Int_t run, Int_t /*side*/, Int_t mode){
1662   //
1663   // Get time dependent time 0 (trigger delay in cm) correction
1664   // additive correction        time0 = time0+ GetTime0CorrectionTime
1665   // Value etracted combining the vdrift correction using laser tracks and CE and the physics track matchin
1666   // Arguments:
1667   // mode determines the algorith how to combine the Laser Track and physics tracks
1668   // timestamp - timestamp
1669   // run       - run number
1670   // side      - the drift velocity per side (possible for laser and CE)
1671   //
1672   // Notice - Extrapolation outside of calibration range  - using constant function
1673   //
1674   Double_t result=0;
1675   if (mode==1) result=fDButil->GetTriggerOffsetTPC(run,timeStamp);    
1676   result  *=fParam->GetZLength();
1677
1678   return result;
1679
1680 }
1681
1682
1683
1684
1685 Double_t AliTPCcalibDB::GetVDriftCorrectionGy(Int_t timeStamp, Int_t run, Int_t side, Int_t /*mode*/){
1686   //
1687   // Get global y correction drift velocity correction factor
1688   // additive factor        vd = vdnom*(1+GetVDriftCorrectionGy *gy)
1689   // Value etracted combining the vdrift correction using laser tracks and CE
1690   // Arguments:
1691   // mode determines the algorith how to combine the Laser Track, LaserCE
1692   // timestamp - timestamp
1693   // run       - run number
1694   // side      - the drift velocity gy correction per side (CE and Laser tracks)
1695   //
1696   // Notice - Extrapolation outside of calibration range  - using constant function
1697   // 
1698   if (run<=0 && fTransform) run = fTransform->GetCurrentRunNumber();
1699   UpdateRunInformations(run,kFALSE);
1700   TObjArray *array =AliTPCcalibDB::Instance()->GetTimeVdriftSplineRun(run);
1701   if (!array) return 0;
1702   TGraphErrors *laserA= (TGraphErrors*)array->FindObject("GRAPH_MEAN_GLOBALYGRADIENT_LASER_ALL_A");
1703   TGraphErrors *laserC= (TGraphErrors*)array->FindObject("GRAPH_MEAN_GLOBALYGRADIENT_LASER_ALL_C");
1704   
1705   Double_t result=0;
1706   if (laserA && laserC){
1707    result= (laserA->Eval(timeStamp)+laserC->Eval(timeStamp))*0.5;
1708   }
1709   if (laserA && side==0){
1710     result = (laserA->Eval(timeStamp));
1711   }
1712   if (laserC &&side==1){
1713     result = (laserC->Eval(timeStamp));
1714   }
1715   return -result/250.; //normalized before
1716 }
1717