]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TPC/AliTPCcalibDB.cxx
Renaming of measured field map class
[u/mrichter/AliRoot.git] / TPC / AliTPCcalibDB.cxx
CommitLineData
c5bbaa2c 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 //
1ac191a6 23// Then request the calibration data ////
f5344549 24//
25//
1ac191a6 26// Calibration data:
8cd9634d 27// 0.) Altro mapping
28// Simulation - not yet
29// Reconstruction - AliTPCclustererMI::Digits2Clusters(AliRawReader* rawReader)
30//
1ac191a6 31// 1.) pad by pad calibration - AliTPCCalPad
f5344549 32//
1ac191a6 33// a.) fPadGainFactor
34// Simulation: AliTPCDigitizer::ExecFast - Multiply by gain
35// Reconstruction : AliTPCclustererMI::Digits2Clusters - Divide by gain
f5344549 36//
1ac191a6 37// b.) fPadNoise -
38// Simulation: AliTPCDigitizer::ExecFast
39// Reconstruction: AliTPCclustererMI::FindClusters(AliTPCCalROC * noiseROC)
8cd9634d 40// Noise depending cut on clusters charge (n sigma)
f5344549 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()
8cd9634d 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//
96305e49 73// 3.) cluster error, shape and Q parameterization
74//
75//
8cd9634d 76//
c5bbaa2c 77///////////////////////////////////////////////////////////////////////////////
78
418bbcaf 79#include <iostream>
80#include <fstream>
81
c5bbaa2c 82
83#include <AliCDBManager.h>
c5bbaa2c 84#include <AliCDBEntry.h>
85#include <AliLog.h>
3ac615eb 86#include <AliMagF.h>
6507bc02 87#include <AliMagFCheb.h>
c5bbaa2c 88
89#include "AliTPCcalibDB.h"
d6834f5f 90#include "AliTPCAltroMapping.h"
418bbcaf 91#include "AliTPCExB.h"
c5bbaa2c 92
93#include "AliTPCCalROC.h"
94#include "AliTPCCalPad.h"
54472e4f 95#include "AliTPCSensorTempArray.h"
bf85fe4d 96#include "AliGRPObject.h"
418bbcaf 97#include "AliTPCTransform.h"
d6834f5f 98
418bbcaf 99class AliCDBStorage;
100class AliTPCCalDet;
86df2b3a 101//
102//
103
86df2b3a 104#include "TFile.h"
105#include "TKey.h"
106
107#include "TObjArray.h"
108#include "TObjString.h"
109#include "TString.h"
110#include "AliTPCCalPad.h"
0fe7645c 111#include "AliTPCCalibPulser.h"
86df2b3a 112#include "AliTPCCalibPedestal.h"
113#include "AliTPCCalibCE.h"
3ac615eb 114#include "AliTPCExBFirst.h"
bf85fe4d 115#include "AliTPCTempMap.h"
da6c0bc9 116#include "AliTPCCalibVdrift.h"
86df2b3a 117
118
119
c5bbaa2c 120
121ClassImp(AliTPCcalibDB)
122
123AliTPCcalibDB* AliTPCcalibDB::fgInstance = 0;
124Bool_t AliTPCcalibDB::fgTerminated = kFALSE;
3ac615eb 125TObjArray AliTPCcalibDB::fgExBArray; // array of ExB corrections
c5bbaa2c 126
127
128//_ singleton implementation __________________________________________________
129AliTPCcalibDB* AliTPCcalibDB::Instance()
130{
131 //
132 // Singleton implementation
133 // Returns an instance of this class, it is created if neccessary
134 //
135
136 if (fgTerminated != kFALSE)
137 return 0;
138
139 if (fgInstance == 0)
140 fgInstance = new AliTPCcalibDB();
141
142 return fgInstance;
143}
144
145void AliTPCcalibDB::Terminate()
146{
147 //
148 // Singleton implementation
149 // Deletes the instance of this class and sets the terminated flag, instances cannot be requested anymore
150 // This function can be called several times.
151 //
152
153 fgTerminated = kTRUE;
154
155 if (fgInstance != 0)
156 {
157 delete fgInstance;
158 fgInstance = 0;
159 }
160}
161
162//_____________________________________________________________________________
e4dce695 163AliTPCcalibDB::AliTPCcalibDB():
9389f9a4 164 TObject(),
e4dce695 165 fRun(-1),
f5344549 166 fTransform(0),
481f877b 167 fExB(0),
e4dce695 168 fPadGainFactor(0),
9f6e9f81 169 fDedxGainFactor(0),
e4dce695 170 fPadTime0(0),
e4dce695 171 fPadNoise(0),
172 fPedestals(0),
173 fTemperature(0),
d6834f5f 174 fMapping(0),
96305e49 175 fParam(0),
bf85fe4d 176 fClusterParam(0),
da6c0bc9 177 fGRPArray(100000), //! array of GRPs - per run - JUST for calibration studies
0231c65f 178 fGRPMaps(100000), //! array of GRPs - per run - JUST for calibration studies
da6c0bc9 179 fGoofieArray(100000), //! array of GOOFIE values -per run - Just for calibration studies
e2914767 180 fVoltageArray(100000),
da6c0bc9 181 fTemperatureArray(100000), //! array of temperature sensors - per run - Just for calibration studies
182 fVdriftArray(100000), //! array of v drift interfaces
bf85fe4d 183 fRunList(100000) //! run list - indicates try to get the run param
184
c5bbaa2c 185{
186 //
187 // constructor
188 //
54472e4f 189 //
c5bbaa2c 190 Update(); // temporary
191}
192
9389f9a4 193AliTPCcalibDB::AliTPCcalibDB(const AliTPCcalibDB& ):
194 TObject(),
195 fRun(-1),
196 fTransform(0),
197 fExB(0),
198 fPadGainFactor(0),
9f6e9f81 199 fDedxGainFactor(0),
9389f9a4 200 fPadTime0(0),
201 fPadNoise(0),
202 fPedestals(0),
203 fTemperature(0),
204 fMapping(0),
9389f9a4 205 fParam(0),
bf85fe4d 206 fClusterParam(0),
207 fGRPArray(0), //! array of GRPs - per run - JUST for calibration studies
0231c65f 208 fGRPMaps(0), //! array of GRPs - per run - JUST for calibration studies
bf85fe4d 209 fGoofieArray(0), //! array of GOOFIE values -per run - Just for calibration studies
e2914767 210 fVoltageArray(0),
bf85fe4d 211 fTemperatureArray(0), //! array of temperature sensors - per run - Just for calibration studies
da6c0bc9 212 fVdriftArray(0), //! array of v drift interfaces
bf85fe4d 213 fRunList(0) //! run list - indicates try to get the run param
9389f9a4 214{
215 //
216 // Copy constructor invalid -- singleton implementation
217 //
218 Error("copy constructor","invalid -- singleton implementation");
219}
220
221AliTPCcalibDB& AliTPCcalibDB::operator= (const AliTPCcalibDB& )
222{
223//
224// Singleton implementation - no assignment operator
225//
226 Error("operator =", "assignment operator not implemented");
227 return *this;
228}
229
230
231
c5bbaa2c 232//_____________________________________________________________________________
233AliTPCcalibDB::~AliTPCcalibDB()
234{
235 //
236 // destructor
237 //
68751c2c 238
239 // don't delete anything, CDB cache is active!
240 //if (fPadGainFactor) delete fPadGainFactor;
241 //if (fPadTime0) delete fPadTime0;
68751c2c 242 //if (fPadNoise) delete fPadNoise;
c5bbaa2c 243}
244
245
246//_____________________________________________________________________________
247AliCDBEntry* AliTPCcalibDB::GetCDBEntry(const char* cdbPath)
248{
249 //
250 // Retrieves an entry with path <cdbPath> from the CDB.
251 //
252 char chinfo[1000];
253
68751c2c 254 AliCDBEntry* entry = AliCDBManager::Instance()->Get(cdbPath, fRun);
c5bbaa2c 255 if (!entry)
256 {
257 sprintf(chinfo,"AliTPCcalibDB: Failed to get entry:\t%s ", cdbPath);
258 AliError(chinfo);
259 return 0;
260 }
261 return entry;
262}
263
264
265//_____________________________________________________________________________
266void AliTPCcalibDB::SetRun(Long64_t run)
267{
268 //
269 // Sets current run number. Calibration data is read from the corresponding file.
270 //
271 if (fRun == run)
272 return;
273 fRun = run;
274 Update();
275}
276
277
278
279void AliTPCcalibDB::Update(){
280 //
281 AliCDBEntry * entry=0;
68751c2c 282
283 Bool_t cdbCache = AliCDBManager::Instance()->GetCacheFlag(); // save cache status
284 AliCDBManager::Instance()->SetCacheFlag(kTRUE); // activate CDB cache
285
c5bbaa2c 286 //
287 entry = GetCDBEntry("TPC/Calib/PadGainFactor");
288 if (entry){
68751c2c 289 //if (fPadGainFactor) delete fPadGainFactor;
c5bbaa2c 290 entry->SetOwner(kTRUE);
291 fPadGainFactor = (AliTPCCalPad*)entry->GetObject();
292 }
293 //
9f6e9f81 294 entry = GetCDBEntry("TPC/Calib/GainFactorDedx");
295 if (entry){
296 entry->SetOwner(kTRUE);
297 fDedxGainFactor = (AliTPCCalPad*)entry->GetObject();
298 }
299 //
c5bbaa2c 300 entry = GetCDBEntry("TPC/Calib/PadTime0");
301 if (entry){
68751c2c 302 //if (fPadTime0) delete fPadTime0;
c5bbaa2c 303 entry->SetOwner(kTRUE);
304 fPadTime0 = (AliTPCCalPad*)entry->GetObject();
305 }
306 //
c5bbaa2c 307 //
308 entry = GetCDBEntry("TPC/Calib/PadNoise");
309 if (entry){
68751c2c 310 //if (fPadNoise) delete fPadNoise;
c5bbaa2c 311 entry->SetOwner(kTRUE);
312 fPadNoise = (AliTPCCalPad*)entry->GetObject();
313 }
8477f500 314
315 entry = GetCDBEntry("TPC/Calib/Pedestals");
316 if (entry){
317 //if (fPedestals) delete fPedestals;
318 entry->SetOwner(kTRUE);
319 fPedestals = (AliTPCCalPad*)entry->GetObject();
320 }
321
54472e4f 322 entry = GetCDBEntry("TPC/Calib/Temperature");
323 if (entry){
324 //if (fTemperature) delete fTemperature;
325 entry->SetOwner(kTRUE);
326 fTemperature = (AliTPCSensorTempArray*)entry->GetObject();
327 }
328
8477f500 329 entry = GetCDBEntry("TPC/Calib/Parameters");
330 if (entry){
54472e4f 331 //if (fPadNoise) delete fPadNoise;
8477f500 332 entry->SetOwner(kTRUE);
a778f7e3 333 fParam = (AliTPCParam*)(entry->GetObject()->Clone());
8477f500 334 }
335
96305e49 336 entry = GetCDBEntry("TPC/Calib/ClusterParam");
337 if (entry){
338 //if (fPadNoise) delete fPadNoise;
339 entry->SetOwner(kTRUE);
340 fClusterParam = (AliTPCClusterParam*)(entry->GetObject()->Clone());
341 }
342
d6834f5f 343 entry = GetCDBEntry("TPC/Calib/Mapping");
344 if (entry){
345 //if (fPadNoise) delete fPadNoise;
346 entry->SetOwner(kTRUE);
347 TObjArray * array = dynamic_cast<TObjArray*>(entry->GetObject());
348 if (array && array->GetEntriesFast()==6){
349 fMapping = new AliTPCAltroMapping*[6];
350 for (Int_t i=0; i<6; i++){
351 fMapping[i] = dynamic_cast<AliTPCAltroMapping*>(array->At(i));
352 }
353 }
354 }
355
356
357
3ac615eb 358 //entry = GetCDBEntry("TPC/Calib/ExB");
359 //if (entry) {
360 // entry->SetOwner(kTRUE);
361 // fExB=dynamic_cast<AliTPCExB*>(entry->GetObject()->Clone());
362 //}
363 //
364 // ExB - calculate during initialization
365 // -
f4d5fd21 366 fExB = GetExB(-5,kTRUE);
367 //
f5344549 368 if (!fTransform) {
369 fTransform=new AliTPCTransform();
370 }
8477f500 371
c5bbaa2c 372 //
68751c2c 373 AliCDBManager::Instance()->SetCacheFlag(cdbCache); // reset original CDB cache
374
c5bbaa2c 375}
e4dce695 376
86df2b3a 377
378
379void AliTPCcalibDB::CreateObjectList(const Char_t *filename, TObjArray *calibObjects)
380{
418bbcaf 381//
382// Create calibration objects and read contents from OCDB
383//
86df2b3a 384 if ( calibObjects == 0x0 ) return;
385 ifstream in;
386 in.open(filename);
387 if ( !in.is_open() ){
388 fprintf(stderr,"Error: cannot open list file '%s'", filename);
389 return;
390 }
391
392 AliTPCCalPad *calPad=0x0;
393
394 TString sFile;
395 sFile.ReadFile(in);
396 in.close();
397
398 TObjArray *arrFileLine = sFile.Tokenize("\n");
399
400 TIter nextLine(arrFileLine);
401
402 TObjString *sObjLine=0x0;
2c632057 403 while ( (sObjLine = (TObjString*)nextLine()) ){
86df2b3a 404 TString sLine(sObjLine->GetString());
405
406 TObjArray *arrNextCol = sLine.Tokenize("\t");
407
408 TObjString *sObjType = (TObjString*)(arrNextCol->At(0));
409 TObjString *sObjFileName = (TObjString*)(arrNextCol->At(1));
410
411 if ( !sObjType || ! sObjFileName ) continue;
412 TString sType(sObjType->GetString());
413 TString sFileName(sObjFileName->GetString());
414 printf("%s\t%s\n",sType.Data(),sFileName.Data());
415
416 TFile *fIn = TFile::Open(sFileName);
417 if ( !fIn ){
418 fprintf(stderr,"File not found: '%s'", sFileName.Data());
419 continue;
420 }
421
422 if ( sType == "CE" ){
423 AliTPCCalibCE *ce = (AliTPCCalibCE*)fIn->Get("AliTPCCalibCE");
424
425 calPad = new AliTPCCalPad((TObjArray*)ce->GetCalPadT0());
426 calPad->SetNameTitle("CETmean","CETmean");
427 calibObjects->Add(calPad);
428
429 calPad = new AliTPCCalPad((TObjArray*)ce->GetCalPadQ());
430 calPad->SetNameTitle("CEQmean","CEQmean");
431 calibObjects->Add(calPad);
432
433 calPad = new AliTPCCalPad((TObjArray*)ce->GetCalPadRMS());
434 calPad->SetNameTitle("CETrms","CETrms");
435 calibObjects->Add(calPad);
436
437 } else if ( sType == "Pulser") {
0fe7645c 438 AliTPCCalibPulser *sig = (AliTPCCalibPulser*)fIn->Get("AliTPCCalibPulser");
86df2b3a 439
440 calPad = new AliTPCCalPad((TObjArray*)sig->GetCalPadT0());
441 calPad->SetNameTitle("PulserTmean","PulserTmean");
442 calibObjects->Add(calPad);
443
444 calPad = new AliTPCCalPad((TObjArray*)sig->GetCalPadQ());
445 calPad->SetNameTitle("PulserQmean","PulserQmean");
446 calibObjects->Add(calPad);
447
448 calPad = new AliTPCCalPad((TObjArray*)sig->GetCalPadRMS());
449 calPad->SetNameTitle("PulserTrms","PulserTrms");
450 calibObjects->Add(calPad);
451
452 } else if ( sType == "Pedestals") {
453 AliTPCCalibPedestal *ped = (AliTPCCalibPedestal*)fIn->Get("AliTPCCalibPedestal");
454
455 calPad = new AliTPCCalPad((TObjArray*)ped->GetCalPadPedestal());
456 calPad->SetNameTitle("Pedestals","Pedestals");
457 calibObjects->Add(calPad);
458
459 calPad = new AliTPCCalPad((TObjArray*)ped->GetCalPadRMS());
460 calPad->SetNameTitle("Noise","Noise");
461 calibObjects->Add(calPad);
462
463 } else {
464 fprintf(stderr,"Undefined Type: '%s'",sType.Data());
465
466 }
467 delete fIn;
468 }
469}
470
471
472
473void AliTPCcalibDB::MakeTree(const char * fileName, TObjArray * array, const char * mapFileName, AliTPCCalPad* outlierPad, Float_t ltmFraction) {
474 //
475 // Write a tree with all available information
418bbcaf 476 // if mapFileName is specified, the Map information are also written to the tree
86df2b3a 477 // pads specified in outlierPad are not used for calculating statistics
478 // - the same function as AliTPCCalPad::MakeTree -
479 //
480 AliTPCROC* tpcROCinstance = AliTPCROC::Instance();
481
482 TObjArray* mapIROCs = 0;
483 TObjArray* mapOROCs = 0;
484 TVectorF *mapIROCArray = 0;
485 TVectorF *mapOROCArray = 0;
486 Int_t mapEntries = 0;
487 TString* mapNames = 0;
488
489 if (mapFileName) {
490 TFile mapFile(mapFileName, "read");
491
492 TList* listOfROCs = mapFile.GetListOfKeys();
493 mapEntries = listOfROCs->GetEntries()/2;
494 mapIROCs = new TObjArray(mapEntries*2);
495 mapOROCs = new TObjArray(mapEntries*2);
496 mapIROCArray = new TVectorF[mapEntries];
497 mapOROCArray = new TVectorF[mapEntries];
498
499 mapNames = new TString[mapEntries];
500 for (Int_t ivalue = 0; ivalue < mapEntries; ivalue++) {
418bbcaf 501 TString nameROC(((TKey*)(listOfROCs->At(ivalue*2)))->GetName());
502 nameROC.Remove(nameROC.Length()-4, 4);
503 mapIROCs->AddAt((AliTPCCalROC*)mapFile.Get((nameROC + "IROC").Data()), ivalue);
504 mapOROCs->AddAt((AliTPCCalROC*)mapFile.Get((nameROC + "OROC").Data()), ivalue);
505 mapNames[ivalue].Append(nameROC);
86df2b3a 506 }
507
508 for (Int_t ivalue = 0; ivalue < mapEntries; ivalue++) {
509 mapIROCArray[ivalue].ResizeTo(tpcROCinstance->GetNChannels(0));
510 mapOROCArray[ivalue].ResizeTo(tpcROCinstance->GetNChannels(36));
511
512 for (UInt_t ichannel = 0; ichannel < tpcROCinstance->GetNChannels(0); ichannel++)
513 (mapIROCArray[ivalue])[ichannel] = ((AliTPCCalROC*)(mapIROCs->At(ivalue)))->GetValue(ichannel);
514 for (UInt_t ichannel = 0; ichannel < tpcROCinstance->GetNChannels(36); ichannel++)
515 (mapOROCArray[ivalue])[ichannel] = ((AliTPCCalROC*)(mapOROCs->At(ivalue)))->GetValue(ichannel);
516 }
517
518 } // if (mapFileName)
519
520 TTreeSRedirector cstream(fileName);
521 Int_t arrayEntries = array->GetEntries();
522
523 TString* names = new TString[arrayEntries];
524 for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++)
525 names[ivalue].Append(((AliTPCCalPad*)array->At(ivalue))->GetName());
526
527 for (UInt_t isector = 0; isector < tpcROCinstance->GetNSectors(); isector++) {
528 //
529 // get statistic for given sector
530 //
531 TVectorF median(arrayEntries);
532 TVectorF mean(arrayEntries);
533 TVectorF rms(arrayEntries);
534 TVectorF ltm(arrayEntries);
535 TVectorF ltmrms(arrayEntries);
536 TVectorF medianWithOut(arrayEntries);
537 TVectorF meanWithOut(arrayEntries);
538 TVectorF rmsWithOut(arrayEntries);
539 TVectorF ltmWithOut(arrayEntries);
540 TVectorF ltmrmsWithOut(arrayEntries);
541
542 TVectorF *vectorArray = new TVectorF[arrayEntries];
543 for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++)
544 vectorArray[ivalue].ResizeTo(tpcROCinstance->GetNChannels(isector));
545
546 for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++) {
547 AliTPCCalPad* calPad = (AliTPCCalPad*) array->At(ivalue);
548 AliTPCCalROC* calROC = calPad->GetCalROC(isector);
549 AliTPCCalROC* outlierROC = 0;
550 if (outlierPad) outlierROC = outlierPad->GetCalROC(isector);
551 if (calROC) {
552 median[ivalue] = calROC->GetMedian();
553 mean[ivalue] = calROC->GetMean();
554 rms[ivalue] = calROC->GetRMS();
555 Double_t ltmrmsValue = 0;
556 ltm[ivalue] = calROC->GetLTM(&ltmrmsValue, ltmFraction);
557 ltmrms[ivalue] = ltmrmsValue;
558 if (outlierROC) {
559 medianWithOut[ivalue] = calROC->GetMedian(outlierROC);
560 meanWithOut[ivalue] = calROC->GetMean(outlierROC);
561 rmsWithOut[ivalue] = calROC->GetRMS(outlierROC);
562 ltmrmsValue = 0;
563 ltmWithOut[ivalue] = calROC->GetLTM(&ltmrmsValue, ltmFraction, outlierROC);
564 ltmrmsWithOut[ivalue] = ltmrmsValue;
565 }
566 }
567 else {
568 median[ivalue] = 0.;
569 mean[ivalue] = 0.;
570 rms[ivalue] = 0.;
571 ltm[ivalue] = 0.;
572 ltmrms[ivalue] = 0.;
573 medianWithOut[ivalue] = 0.;
574 meanWithOut[ivalue] = 0.;
575 rmsWithOut[ivalue] = 0.;
576 ltmWithOut[ivalue] = 0.;
577 ltmrmsWithOut[ivalue] = 0.;
578 }
579 }
580
581 //
582 // fill vectors of variable per pad
583 //
584 TVectorF *posArray = new TVectorF[8];
585 for (Int_t ivalue = 0; ivalue < 8; ivalue++)
586 posArray[ivalue].ResizeTo(tpcROCinstance->GetNChannels(isector));
587
588 Float_t posG[3] = {0};
589 Float_t posL[3] = {0};
590 Int_t ichannel = 0;
591 for (UInt_t irow = 0; irow < tpcROCinstance->GetNRows(isector); irow++) {
592 for (UInt_t ipad = 0; ipad < tpcROCinstance->GetNPads(isector, irow); ipad++) {
593 tpcROCinstance->GetPositionLocal(isector, irow, ipad, posL);
594 tpcROCinstance->GetPositionGlobal(isector, irow, ipad, posG);
595 posArray[0][ichannel] = irow;
596 posArray[1][ichannel] = ipad;
597 posArray[2][ichannel] = posL[0];
598 posArray[3][ichannel] = posL[1];
599 posArray[4][ichannel] = posG[0];
600 posArray[5][ichannel] = posG[1];
601 posArray[6][ichannel] = (Int_t)(ipad - (Double_t)(tpcROCinstance->GetNPads(isector, irow))/2);
602 posArray[7][ichannel] = ichannel;
603
604 // loop over array containing AliTPCCalPads
605 for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++) {
606 AliTPCCalPad* calPad = (AliTPCCalPad*) array->At(ivalue);
607 AliTPCCalROC* calROC = calPad->GetCalROC(isector);
608 if (calROC)
609 (vectorArray[ivalue])[ichannel] = calROC->GetValue(irow, ipad);
610 else
611 (vectorArray[ivalue])[ichannel] = 0;
612 }
613 ichannel++;
614 }
615 }
616
617 cstream << "calPads" <<
618 "sector=" << isector;
619
620 for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++) {
621 cstream << "calPads" <<
622 (Char_t*)((names[ivalue] + "_Median=").Data()) << median[ivalue] <<
623 (Char_t*)((names[ivalue] + "_Mean=").Data()) << mean[ivalue] <<
624 (Char_t*)((names[ivalue] + "_RMS=").Data()) << rms[ivalue] <<
625 (Char_t*)((names[ivalue] + "_LTM=").Data()) << ltm[ivalue] <<
626 (Char_t*)((names[ivalue] + "_RMS_LTM=").Data()) << ltmrms[ivalue];
627 if (outlierPad) {
628 cstream << "calPads" <<
629 (Char_t*)((names[ivalue] + "_Median_OutlierCutted=").Data()) << medianWithOut[ivalue] <<
630 (Char_t*)((names[ivalue] + "_Mean_OutlierCutted=").Data()) << meanWithOut[ivalue] <<
631 (Char_t*)((names[ivalue] + "_RMS_OutlierCutted=").Data()) << rmsWithOut[ivalue] <<
632 (Char_t*)((names[ivalue] + "_LTM_OutlierCutted=").Data()) << ltmWithOut[ivalue] <<
633 (Char_t*)((names[ivalue] + "_RMS_LTM_OutlierCutted=").Data()) << ltmrmsWithOut[ivalue];
634 }
635 }
636
637 for (Int_t ivalue = 0; ivalue < arrayEntries; ivalue++) {
638 cstream << "calPads" <<
639 (Char_t*)((names[ivalue] + ".=").Data()) << &vectorArray[ivalue];
640 }
641
642 if (mapFileName) {
643 for (Int_t ivalue = 0; ivalue < mapEntries; ivalue++) {
644 if (isector < 36)
645 cstream << "calPads" <<
646 (Char_t*)((mapNames[ivalue] + ".=").Data()) << &mapIROCArray[ivalue];
647 else
648 cstream << "calPads" <<
649 (Char_t*)((mapNames[ivalue] + ".=").Data()) << &mapOROCArray[ivalue];
650 }
651 }
652
653 cstream << "calPads" <<
654 "row.=" << &posArray[0] <<
655 "pad.=" << &posArray[1] <<
656 "lx.=" << &posArray[2] <<
657 "ly.=" << &posArray[3] <<
658 "gx.=" << &posArray[4] <<
659 "gy.=" << &posArray[5] <<
660 "rpad.=" << &posArray[6] <<
661 "channel.=" << &posArray[7];
662
663 cstream << "calPads" <<
664 "\n";
665
666 delete[] posArray;
667 delete[] vectorArray;
668 }
669
670
671 delete[] names;
672 if (mapFileName) {
673 delete mapIROCs;
674 delete mapOROCs;
675 delete[] mapIROCArray;
676 delete[] mapOROCArray;
677 delete[] mapNames;
678 }
679}
3ac615eb 680
681
682
683void AliTPCcalibDB::RegisterExB(Int_t index, Float_t bz, Bool_t bdelete){
684 //
685 // Register static ExB correction map
686 // index - registration index - used for visualization
687 // bz - bz field in kGaus
688
689 Float_t factor = bz/(-5.); // default b filed in Cheb with minus sign
690
6507bc02 691 AliMagF* bmap = new AliMagFCheb("MapsExB","MapsExB", 2, factor, 10., AliMagFCheb::k5kG,kTRUE,"$(ALICE_ROOT)/data/maps/mfchebKGI_sym.root");
3ac615eb 692
693 AliTPCExBFirst *exb = new AliTPCExBFirst(bmap,0.88*2.6400e+04,50,50,50);
694 AliTPCExB::SetInstance(exb);
695
696 if (bdelete){
697 delete bmap;
698 }else{
699 AliTPCExB::RegisterField(index,bmap);
700 }
701 if (index>=fgExBArray.GetEntries()) fgExBArray.Expand((index+1)*2+11);
702 fgExBArray.AddAt(exb,index);
703}
704
705
706AliTPCExB* AliTPCcalibDB::GetExB(Float_t bz, Bool_t deleteB) {
707 //
708 // bz filed in KGaus not in tesla
709 // Get ExB correction map
710 // if doesn't exist - create it
711 //
712 Int_t index = TMath::Nint(5+bz);
713 if (index>fgExBArray.GetEntries()) fgExBArray.Expand((index+1)*2+11);
714 if (!fgExBArray.At(index)) AliTPCcalibDB::RegisterExB(index,bz,deleteB);
715 return (AliTPCExB*)fgExBArray.At(index);
716}
717
718
719void AliTPCcalibDB::SetExBField(Float_t bz){
720 //
721 // Set magnetic filed for ExB correction
722 //
723 fExB = GetExB(bz,kFALSE);
724}
bf85fe4d 725
726
727
728void AliTPCcalibDB::GetRunInformations( Int_t run){
729 //
730 // - > Don't use it for reconstruction - Only for Calibration studies
731 //
732 AliCDBEntry * entry = 0;
733 if (run>= fRunList.GetSize()){
734 fRunList.Set(run*2+1);
da6c0bc9 735 fGRPArray.Expand(run*2+1);
0231c65f 736 fGRPMaps.Expand(run*2+1);
e2914767 737 fGoofieArray.Expand(run*2+1);
738 fVoltageArray.Expand(run*2+1);
da6c0bc9 739 fTemperatureArray.Expand(run*2+1);
740 fVdriftArray.Expand(run*2+1);
bf85fe4d 741 }
742 if (fRunList[run]>0) return;
743 entry = AliCDBManager::Instance()->Get("GRP/GRP/Data",run);
0231c65f 744 if (entry) {
745 AliGRPObject * grpRun = dynamic_cast<AliGRPObject*>(entry->GetObject());
746 if (!grpRun){
747 TMap* map = dynamic_cast<TMap*>(entry->GetObject());
748 if (map){
e2914767 749 //grpRun = new AliGRPObject;
750 //grpRun->ReadValuesFromMap(map);
751 grpRun = MakeGRPObjectFromMap(map);
752
0231c65f 753 fGRPMaps.AddAt(map,run);
754 }
755 }
756 fGRPArray.AddAt(grpRun,run);
757 }
bf85fe4d 758 entry = AliCDBManager::Instance()->Get("TPC/Calib/Goofie",run);
759 if (entry) fGoofieArray.AddAt(entry->GetObject(),run);
e2914767 760 //
761 entry = AliCDBManager::Instance()->Get("TPC/Calib/HighVoltage",run);
762 if (entry) fVoltageArray.AddAt(entry->GetObject(),run);
763 //
bf85fe4d 764 entry = AliCDBManager::Instance()->Get("TPC/Calib/Temperature",run);
765 if (entry) fTemperatureArray.AddAt(entry->GetObject(),run);
766 fRunList[run]=1; // sign as used
da6c0bc9 767
768 AliDCSSensor * press = GetPressureSensor(run);
769 AliTPCSensorTempArray * temp = GetTemperatureSensor(run);
770 if (press && temp){
771 AliTPCCalibVdrift * vdrift = new AliTPCCalibVdrift(temp, press,0);
772 fVdriftArray.AddAt(vdrift,run);
773 }
bf85fe4d 774}
775
776
777Float_t AliTPCcalibDB::GetGain(Int_t sector, Int_t row, Int_t pad){
778 //
779 //
780 AliTPCCalPad *calPad = Instance()->fDedxGainFactor;;
781 if (!calPad) return 0;
782 return calPad->GetCalROC(sector)->GetValue(row,pad);
783}
784
8de77f00 785
786AliGRPObject *AliTPCcalibDB::GetGRP(Int_t run){
787 //
788 // Get GRP object for given run
789 //
790 AliGRPObject * grpRun = dynamic_cast<AliGRPObject *>((Instance()->fGRPArray).At(run));
791 if (!grpRun) {
792 Instance()->GetRunInformations(run);
793 grpRun = dynamic_cast<AliGRPObject *>(Instance()->fGRPArray.At(run));
794 if (!grpRun) return 0;
795 }
796 return grpRun;
797}
798
0231c65f 799TMap * AliTPCcalibDB::GetGRPMap(Int_t run){
800 //
801 //
802 //
803 TMap * grpRun = dynamic_cast<TMap *>((Instance()->fGRPMaps).At(run));
804 if (!grpRun) {
805 Instance()->GetRunInformations(run);
806 grpRun = dynamic_cast<TMap *>(Instance()->fGRPMaps.At(run));
807 if (!grpRun) return 0;
808 }
809 return grpRun;
810}
8de77f00 811
812
da6c0bc9 813AliDCSSensor * AliTPCcalibDB::GetPressureSensor(Int_t run, Int_t type){
bf85fe4d 814 //
0231c65f 815 // Get Pressure sensor
816 //
817 //
818 // First try to get if trom map - if existing (Old format of data storing)
bf85fe4d 819 //
0231c65f 820 TMap *map = GetGRPMap(run);
821 if (map){
822 AliDCSSensor * sensor = 0;
823 TObject *osensor=0;
824 if (type==0) osensor = ((*map)("fCavernPressure"));
825 if (type==1) osensor = ((*map)("fP2Pressure"));
826 sensor =dynamic_cast<AliDCSSensor *>(osensor);
827 if (sensor) return sensor;
828 }
829 //
830 // If not map try to get it from the GRPObject
831 //
832 AliGRPObject * grpRun = dynamic_cast<AliGRPObject *>(fGRPArray.At(run));
bf85fe4d 833 if (!grpRun) {
834 GetRunInformations(run);
efdbb95a 835 grpRun = dynamic_cast<AliGRPObject *>(fGRPArray.At(run));
bf85fe4d 836 if (!grpRun) return 0;
837 }
838 AliDCSSensor * sensor = grpRun->GetCavernAtmosPressure();
da6c0bc9 839 if (type==1) sensor = grpRun->GetSurfaceAtmosPressure();
840 return sensor;
bf85fe4d 841}
842
843AliTPCSensorTempArray * AliTPCcalibDB::GetTemperatureSensor(Int_t run){
844 //
845 // Get temperature sensor array
846 //
847 AliTPCSensorTempArray * tempArray = (AliTPCSensorTempArray *)fTemperatureArray.At(run);
848 if (!tempArray) {
849 GetRunInformations(run);
850 tempArray = (AliTPCSensorTempArray *)fTemperatureArray.At(run);
851 }
852 return tempArray;
853}
854
855AliDCSSensorArray * AliTPCcalibDB::GetGoofieSensors(Int_t run){
856 //
857 // Get temperature sensor array
858 //
859 AliDCSSensorArray * goofieArray = (AliDCSSensorArray *)fGoofieArray.At(run);
860 if (!goofieArray) {
861 GetRunInformations(run);
862 goofieArray = (AliDCSSensorArray *)fGoofieArray.At(run);
863 }
864 return goofieArray;
865}
866
e2914767 867AliDCSSensorArray * AliTPCcalibDB::GetVoltageSensors(Int_t run){
868 //
869 // Get temperature sensor array
870 //
871 AliDCSSensorArray * voltageArray = (AliDCSSensorArray *)fVoltageArray.At(run);
872 if (!voltageArray) {
873 GetRunInformations(run);
874 voltageArray = (AliDCSSensorArray *)fVoltageArray.At(run);
875 }
876 return voltageArray;
877}
878
da6c0bc9 879AliTPCCalibVdrift * AliTPCcalibDB::GetVdrift(Int_t run){
880 //
881 // Get the interface to the the vdrift
882 //
883 AliTPCCalibVdrift * vdrift = (AliTPCCalibVdrift*)fVdriftArray.At(run);
884 if (!vdrift) {
885 GetRunInformations(run);
886 vdrift= (AliTPCCalibVdrift*)fVdriftArray.At(run);
887 }
888 return vdrift;
889}
890
bf85fe4d 891
e2914767 892Float_t AliTPCcalibDB::GetChamberHighVoltage(Int_t timeStamp, Int_t run, Int_t sector) {
893 //
894 // return the chamber HV for given run and time: 0-35 IROC, 36-72 OROC
895 //
896 TTimeStamp stamp(timeStamp);
897 AliDCSSensorArray* voltageArray = AliTPCcalibDB::Instance()->GetVoltageSensors(run);
898 if (!voltageArray) return 0;
899 AliDCSSensor *sensor = voltageArray->GetSensor((sector+1)*3);
900 if (!sensor) return 0;
901 return sensor->GetValue(stamp);
902}
bf85fe4d 903
da6c0bc9 904Float_t AliTPCcalibDB::GetPressure(Int_t timeStamp, Int_t run, Int_t type){
bf85fe4d 905 //
906 // GetPressure for given time stamp and runt
907 //
908 TTimeStamp stamp(timeStamp);
da6c0bc9 909 AliDCSSensor * sensor = Instance()->GetPressureSensor(run,type);
bf85fe4d 910 if (!sensor) return 0;
bf85fe4d 911 return sensor->GetValue(stamp);
912}
913
7f7847fe 914Float_t AliTPCcalibDB::GetValueGoofie(Int_t timeStamp, Int_t run, Int_t type){
915 //
916 // GetPressure for given time stamp and runt
917 //
918 TTimeStamp stamp(timeStamp);
919 AliDCSSensorArray* goofieArray = AliTPCcalibDB::Instance()->GetGoofieSensors(run);
920 if (!goofieArray) return 0;
921 AliDCSSensor *sensor = goofieArray->GetSensor(type);
922 return sensor->GetValue(stamp);
923}
924
925
926
927
928
929
f0269955 930Bool_t AliTPCcalibDB::GetTemperatureFit(Int_t timeStamp, Int_t run, Int_t side,TVectorD& fit){
931 //
932 //
933 //
934 TTimeStamp tstamp(timeStamp);
64b48395 935 AliTPCSensorTempArray* tempArray = Instance()->GetTemperatureSensor(run);
f0269955 936 if (! tempArray) return kFALSE;
937 AliTPCTempMap * tempMap = new AliTPCTempMap(tempArray);
938 TLinearFitter * fitter = tempMap->GetLinearFitter(3,side,tstamp);
939 if (fitter){
940 fitter->Eval();
941 fitter->GetParameters(fit);
942 }
943 delete fitter;
944 delete tempMap;
945 if (!fitter) return kFALSE;
946 return kTRUE;
947}
948
64b48395 949Float_t AliTPCcalibDB::GetTemperature(Int_t timeStamp, Int_t run, Int_t side){
950 //
951 //
952 //
12e42756 953 TVectorD vec(5);
64b48395 954 if (side==0) {
955 GetTemperatureFit(timeStamp,run,0,vec);
956 return vec[0];
957 }
958 if (side==1){
959 GetTemperatureFit(timeStamp,run,0,vec);
960 return vec[0];
961 }
57dc06f2 962 return 0;
64b48395 963}
bf85fe4d 964
965
da6c0bc9 966Double_t AliTPCcalibDB::GetPTRelative(UInt_t timeSec, Int_t run, Int_t side){
967 //
968 // Get relative P/T
969 // time - absolute time
970 // run - run number
971 // side - 0 - A side 1-C side
972 AliTPCCalibVdrift * vdrift = Instance()->GetVdrift(run);
973 if (!vdrift) return 0;
974 return vdrift->GetPTRelative(timeSec,side);
975}
976
bf85fe4d 977
978void AliTPCcalibDB::ProcessEnv(const char * runList){
979 //
980 // Example test function - how to use the environment variables
981 // runList - ascii file with run numbers
982 // output - dcsTime.root file with tree
983
984 ifstream in;
985 in.open(runList);
986 Int_t irun=0;
987 TTreeSRedirector *pcstream = new TTreeSRedirector("dcsTime.root");
988 while(in.good()) {
989 in >> irun;
990 if (irun==0) continue;
991 printf("Processing run %d\n",irun);
992 AliDCSSensor * sensorPressure = AliTPCcalibDB::Instance()->GetPressureSensor(irun);
993 if (!sensorPressure) continue;
994 AliTPCSensorTempArray * tempArray = AliTPCcalibDB::Instance()->GetTemperatureSensor(irun);
995 AliTPCTempMap * tempMap = new AliTPCTempMap(tempArray);
996 AliDCSSensorArray* goofieArray = AliTPCcalibDB::Instance()->GetGoofieSensors(irun);
997 //
998 Int_t startTime = sensorPressure->GetStartTime();
999 Int_t endTime = sensorPressure->GetEndTime();
1000 Int_t dtime = TMath::Max((endTime-startTime)/20,10*60);
1001 for (Int_t itime=startTime; itime<endTime; itime+=dtime){
1002 //
1003 TTimeStamp tstamp(itime);
1004 Float_t valuePressure = sensorPressure->GetValue(tstamp);
1005
1006 TLinearFitter * fitter = 0;
1007 TVectorD vecTemp[10];
1008 if (itime<tempArray->GetStartTime().GetSec() || itime>tempArray->GetEndTime().GetSec()){
1009 }else{
1010 for (Int_t itype=0; itype<5; itype++)
1011 for (Int_t iside=0; iside<2; iside++){
1012 fitter= tempMap->GetLinearFitter(itype,iside,tstamp);
1013 if (!fitter) continue;
1014 fitter->Eval(); fitter->GetParameters(vecTemp[itype+iside*5]);
1015 delete fitter;
1016 }
1017 }
1018
1019 TVectorD vecGoofie, vecEntries, vecMean, vecMedian,vecRMS;
1020 if (goofieArray){
1021 vecGoofie.ResizeTo(goofieArray->NumSensors());
1022 ProcessGoofie(goofieArray, vecEntries ,vecMedian, vecMean, vecRMS);
1023 //
1024 for (Int_t isensor=0; isensor<goofieArray->NumSensors();isensor++){
1025 AliDCSSensor *gsensor = goofieArray->GetSensor(isensor);
1026 if (gsensor){
1027 vecGoofie[isensor] = gsensor->GetValue(tstamp);
1028 }
1029 }
1030 }
1031
1032
1033 //tempMap->GetLinearFitter(0,0,itime);
1034 (*pcstream)<<"dcs"<<
1035 "run="<<irun<<
1036 "time="<<itime<<
1037 "goofie.="<<&vecGoofie<<
1038 "goofieE.="<<&vecEntries<<
1039 "goofieMean.="<<&vecMean<<
1040 "goofieMedian.="<<&vecMedian<<
1041 "goofieRMS.="<<&vecRMS<<
1042 "press="<<valuePressure<<
1043 "temp00.="<<&vecTemp[0]<<
1044 "temp10.="<<&vecTemp[1]<<
1045 "temp20.="<<&vecTemp[2]<<
1046 "temp30.="<<&vecTemp[3]<<
1047 "temp40.="<<&vecTemp[4]<<
1048 "temp01.="<<&vecTemp[5]<<
1049 "temp11.="<<&vecTemp[6]<<
1050 "temp21.="<<&vecTemp[7]<<
1051 "temp31.="<<&vecTemp[8]<<
1052 "temp41.="<<&vecTemp[9]<<
1053 "\n";
1054 }
1055 }
1056 delete pcstream;
1057}
1058
1059
1060void AliTPCcalibDB::ProcessGoofie( AliDCSSensorArray* goofieArray, TVectorD & vecEntries, TVectorD & vecMedian, TVectorD &vecMean, TVectorD &vecRMS){
1061 /*
1062
1063 1 TPC_ANODE_I_A00_STAT
1064 2 TPC_DVM_CO2
1065 3 TPC_DVM_DriftVelocity
1066 4 TPC_DVM_FCageHV
1067 5 TPC_DVM_GainFar
1068 6 TPC_DVM_GainNear
1069 7 TPC_DVM_N2
1070 8 TPC_DVM_NumberOfSparks
1071 9 TPC_DVM_PeakAreaFar
1072 10 TPC_DVM_PeakAreaNear
1073 11 TPC_DVM_PeakPosFar
1074 12 TPC_DVM_PeakPosNear
1075 13 TPC_DVM_PickupHV
1076 14 TPC_DVM_Pressure
1077 15 TPC_DVM_T1_Over_P
1078 16 TPC_DVM_T2_Over_P
1079 17 TPC_DVM_T_Over_P
1080 18 TPC_DVM_TemperatureS1
1081 */
1082 //
1083 //
1084 // TVectorD vecMedian; TVectorD vecEntries; TVectorD vecMean; TVectorD vecRMS;
1085 Double_t kEpsilon=0.0000000001;
1086 Double_t kBig=100000000000.;
1087 Int_t nsensors = goofieArray->NumSensors();
1088 vecEntries.ResizeTo(nsensors);
1089 vecMedian.ResizeTo(nsensors);
1090 vecMean.ResizeTo(nsensors);
1091 vecRMS.ResizeTo(nsensors);
1092 TVectorF values;
1093 for (Int_t isensor=0; isensor<goofieArray->NumSensors();isensor++){
1094 AliDCSSensor *gsensor = goofieArray->GetSensor(isensor);
1095 if (gsensor && gsensor->GetGraph()){
1096 Int_t npoints = gsensor->GetGraph()->GetN();
1097 // filter zeroes
1098 values.ResizeTo(npoints);
1099 Int_t nused =0;
1100 for (Int_t ipoint=0; ipoint<npoints; ipoint++){
1101 if (TMath::Abs(gsensor->GetGraph()->GetY()[ipoint])>kEpsilon &&
1102 TMath::Abs(gsensor->GetGraph()->GetY()[ipoint])<kBig ){
1103 values[nused]=gsensor->GetGraph()->GetY()[ipoint];
1104 nused++;
1105 }
1106 }
1107 //
1108 vecEntries[isensor]= nused;
1109 if (nused>1){
1110 vecMedian[isensor] = TMath::Median(nused,values.GetMatrixArray());
1111 vecMean[isensor] = TMath::Mean(nused,values.GetMatrixArray());
1112 vecRMS[isensor] = TMath::RMS(nused,values.GetMatrixArray());
1113 }
1114 }
1115 }
1116}
1117
e2914767 1118
1119
1120AliGRPObject * AliTPCcalibDB::MakeGRPObjectFromMap(TMap *map){
1121 //
1122 // Function to covert old GRP run information from TMap to GRPObject
1123 //
1124 // TMap * map = AliTPCcalibDB::GetGRPMap(52406);
1125 if (!map) return 0;
1126 AliDCSSensor * sensor = 0;
1127 TObject *osensor=0;
1128 osensor = ((*map)("fP2Pressure"));
1129 sensor =dynamic_cast<AliDCSSensor *>(osensor);
1130 //
1131 if (!sensor) return 0;
1132 //
1133 AliDCSSensor * sensor2 = new AliDCSSensor(*sensor);
1134 osensor = ((*map)("fCavernPressure"));
1135 TGraph * gr = new TGraph(2);
1136 gr->GetX()[0]= -100000.;
1137 gr->GetX()[1]= 1000000.;
1138 gr->GetY()[0]= atof(osensor->GetName());
1139 gr->GetY()[1]= atof(osensor->GetName());
1140 sensor2->SetGraph(gr);
1141 sensor2->SetFit(0);
1142
1143
1144 AliGRPObject *grpRun = new AliGRPObject;
1145 grpRun->ReadValuesFromMap(map);
1146 grpRun->SetCavernAtmosPressure(sensor2);
1147 grpRun->SetSurfaceAtmosPressure(sensor);
1148 return grpRun;
1149}
1150
1151
1152