The script to add the FMD analysis to the train
[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>
c5bbaa2c 87
88#include "AliTPCcalibDB.h"
d6834f5f 89#include "AliTPCAltroMapping.h"
418bbcaf 90#include "AliTPCExB.h"
c5bbaa2c 91
92#include "AliTPCCalROC.h"
93#include "AliTPCCalPad.h"
54472e4f 94#include "AliTPCSensorTempArray.h"
bf85fe4d 95#include "AliGRPObject.h"
418bbcaf 96#include "AliTPCTransform.h"
d6834f5f 97
418bbcaf 98class AliCDBStorage;
99class AliTPCCalDet;
86df2b3a 100//
101//
102
86df2b3a 103#include "TFile.h"
104#include "TKey.h"
105
106#include "TObjArray.h"
107#include "TObjString.h"
108#include "TString.h"
109#include "AliTPCCalPad.h"
0fe7645c 110#include "AliTPCCalibPulser.h"
86df2b3a 111#include "AliTPCCalibPedestal.h"
112#include "AliTPCCalibCE.h"
3ac615eb 113#include "AliTPCExBFirst.h"
bf85fe4d 114#include "AliTPCTempMap.h"
da6c0bc9 115#include "AliTPCCalibVdrift.h"
86df2b3a 116
117
118
c5bbaa2c 119
120ClassImp(AliTPCcalibDB)
121
122AliTPCcalibDB* AliTPCcalibDB::fgInstance = 0;
123Bool_t AliTPCcalibDB::fgTerminated = kFALSE;
3ac615eb 124TObjArray AliTPCcalibDB::fgExBArray; // array of ExB corrections
c5bbaa2c 125
126
127//_ singleton implementation __________________________________________________
128AliTPCcalibDB* AliTPCcalibDB::Instance()
129{
130 //
131 // Singleton implementation
132 // Returns an instance of this class, it is created if neccessary
133 //
134
135 if (fgTerminated != kFALSE)
136 return 0;
137
138 if (fgInstance == 0)
139 fgInstance = new AliTPCcalibDB();
140
141 return fgInstance;
142}
143
144void AliTPCcalibDB::Terminate()
145{
146 //
147 // Singleton implementation
148 // Deletes the instance of this class and sets the terminated flag, instances cannot be requested anymore
149 // This function can be called several times.
150 //
151
152 fgTerminated = kTRUE;
153
154 if (fgInstance != 0)
155 {
156 delete fgInstance;
157 fgInstance = 0;
158 }
159}
160
161//_____________________________________________________________________________
e4dce695 162AliTPCcalibDB::AliTPCcalibDB():
9389f9a4 163 TObject(),
e4dce695 164 fRun(-1),
f5344549 165 fTransform(0),
481f877b 166 fExB(0),
e4dce695 167 fPadGainFactor(0),
9f6e9f81 168 fDedxGainFactor(0),
e4dce695 169 fPadTime0(0),
e4dce695 170 fPadNoise(0),
171 fPedestals(0),
172 fTemperature(0),
d6834f5f 173 fMapping(0),
96305e49 174 fParam(0),
bf85fe4d 175 fClusterParam(0),
da6c0bc9 176 fGRPArray(100000), //! array of GRPs - per run - JUST for calibration studies
0231c65f 177 fGRPMaps(100000), //! array of GRPs - per run - JUST for calibration studies
da6c0bc9 178 fGoofieArray(100000), //! array of GOOFIE values -per run - Just for calibration studies
e2914767 179 fVoltageArray(100000),
da6c0bc9 180 fTemperatureArray(100000), //! array of temperature sensors - per run - Just for calibration studies
181 fVdriftArray(100000), //! array of v drift interfaces
bf85fe4d 182 fRunList(100000) //! run list - indicates try to get the run param
183
c5bbaa2c 184{
185 //
186 // constructor
187 //
54472e4f 188 //
c5bbaa2c 189 Update(); // temporary
190}
191
9389f9a4 192AliTPCcalibDB::AliTPCcalibDB(const AliTPCcalibDB& ):
193 TObject(),
194 fRun(-1),
195 fTransform(0),
196 fExB(0),
197 fPadGainFactor(0),
9f6e9f81 198 fDedxGainFactor(0),
9389f9a4 199 fPadTime0(0),
200 fPadNoise(0),
201 fPedestals(0),
202 fTemperature(0),
203 fMapping(0),
9389f9a4 204 fParam(0),
bf85fe4d 205 fClusterParam(0),
206 fGRPArray(0), //! array of GRPs - per run - JUST for calibration studies
0231c65f 207 fGRPMaps(0), //! array of GRPs - per run - JUST for calibration studies
bf85fe4d 208 fGoofieArray(0), //! array of GOOFIE values -per run - Just for calibration studies
e2914767 209 fVoltageArray(0),
bf85fe4d 210 fTemperatureArray(0), //! array of temperature sensors - per run - Just for calibration studies
da6c0bc9 211 fVdriftArray(0), //! array of v drift interfaces
bf85fe4d 212 fRunList(0) //! run list - indicates try to get the run param
9389f9a4 213{
214 //
215 // Copy constructor invalid -- singleton implementation
216 //
217 Error("copy constructor","invalid -- singleton implementation");
218}
219
220AliTPCcalibDB& AliTPCcalibDB::operator= (const AliTPCcalibDB& )
221{
222//
223// Singleton implementation - no assignment operator
224//
225 Error("operator =", "assignment operator not implemented");
226 return *this;
227}
228
229
230
c5bbaa2c 231//_____________________________________________________________________________
232AliTPCcalibDB::~AliTPCcalibDB()
233{
234 //
235 // destructor
236 //
68751c2c 237
238 // don't delete anything, CDB cache is active!
239 //if (fPadGainFactor) delete fPadGainFactor;
240 //if (fPadTime0) delete fPadTime0;
68751c2c 241 //if (fPadNoise) delete fPadNoise;
c5bbaa2c 242}
243
244
245//_____________________________________________________________________________
246AliCDBEntry* AliTPCcalibDB::GetCDBEntry(const char* cdbPath)
247{
248 //
249 // Retrieves an entry with path <cdbPath> from the CDB.
250 //
251 char chinfo[1000];
252
68751c2c 253 AliCDBEntry* entry = AliCDBManager::Instance()->Get(cdbPath, fRun);
c5bbaa2c 254 if (!entry)
255 {
256 sprintf(chinfo,"AliTPCcalibDB: Failed to get entry:\t%s ", cdbPath);
257 AliError(chinfo);
258 return 0;
259 }
260 return entry;
261}
262
263
264//_____________________________________________________________________________
265void AliTPCcalibDB::SetRun(Long64_t run)
266{
267 //
268 // Sets current run number. Calibration data is read from the corresponding file.
269 //
270 if (fRun == run)
271 return;
272 fRun = run;
273 Update();
274}
275
276
277
278void AliTPCcalibDB::Update(){
279 //
280 AliCDBEntry * entry=0;
68751c2c 281
282 Bool_t cdbCache = AliCDBManager::Instance()->GetCacheFlag(); // save cache status
283 AliCDBManager::Instance()->SetCacheFlag(kTRUE); // activate CDB cache
284
c5bbaa2c 285 //
286 entry = GetCDBEntry("TPC/Calib/PadGainFactor");
287 if (entry){
68751c2c 288 //if (fPadGainFactor) delete fPadGainFactor;
c5bbaa2c 289 entry->SetOwner(kTRUE);
290 fPadGainFactor = (AliTPCCalPad*)entry->GetObject();
291 }
292 //
9f6e9f81 293 entry = GetCDBEntry("TPC/Calib/GainFactorDedx");
294 if (entry){
295 entry->SetOwner(kTRUE);
296 fDedxGainFactor = (AliTPCCalPad*)entry->GetObject();
297 }
298 //
c5bbaa2c 299 entry = GetCDBEntry("TPC/Calib/PadTime0");
300 if (entry){
68751c2c 301 //if (fPadTime0) delete fPadTime0;
c5bbaa2c 302 entry->SetOwner(kTRUE);
303 fPadTime0 = (AliTPCCalPad*)entry->GetObject();
304 }
305 //
c5bbaa2c 306 //
307 entry = GetCDBEntry("TPC/Calib/PadNoise");
308 if (entry){
68751c2c 309 //if (fPadNoise) delete fPadNoise;
c5bbaa2c 310 entry->SetOwner(kTRUE);
311 fPadNoise = (AliTPCCalPad*)entry->GetObject();
312 }
8477f500 313
314 entry = GetCDBEntry("TPC/Calib/Pedestals");
315 if (entry){
316 //if (fPedestals) delete fPedestals;
317 entry->SetOwner(kTRUE);
318 fPedestals = (AliTPCCalPad*)entry->GetObject();
319 }
320
54472e4f 321 entry = GetCDBEntry("TPC/Calib/Temperature");
322 if (entry){
323 //if (fTemperature) delete fTemperature;
324 entry->SetOwner(kTRUE);
325 fTemperature = (AliTPCSensorTempArray*)entry->GetObject();
326 }
327
8477f500 328 entry = GetCDBEntry("TPC/Calib/Parameters");
329 if (entry){
54472e4f 330 //if (fPadNoise) delete fPadNoise;
8477f500 331 entry->SetOwner(kTRUE);
a778f7e3 332 fParam = (AliTPCParam*)(entry->GetObject()->Clone());
8477f500 333 }
334
96305e49 335 entry = GetCDBEntry("TPC/Calib/ClusterParam");
336 if (entry){
337 //if (fPadNoise) delete fPadNoise;
338 entry->SetOwner(kTRUE);
339 fClusterParam = (AliTPCClusterParam*)(entry->GetObject()->Clone());
340 }
341
d6834f5f 342 entry = GetCDBEntry("TPC/Calib/Mapping");
343 if (entry){
344 //if (fPadNoise) delete fPadNoise;
345 entry->SetOwner(kTRUE);
346 TObjArray * array = dynamic_cast<TObjArray*>(entry->GetObject());
347 if (array && array->GetEntriesFast()==6){
348 fMapping = new AliTPCAltroMapping*[6];
349 for (Int_t i=0; i<6; i++){
350 fMapping[i] = dynamic_cast<AliTPCAltroMapping*>(array->At(i));
351 }
352 }
353 }
354
355
356
3ac615eb 357 //entry = GetCDBEntry("TPC/Calib/ExB");
358 //if (entry) {
359 // entry->SetOwner(kTRUE);
360 // fExB=dynamic_cast<AliTPCExB*>(entry->GetObject()->Clone());
361 //}
362 //
363 // ExB - calculate during initialization
364 // -
f4d5fd21 365 fExB = GetExB(-5,kTRUE);
366 //
f5344549 367 if (!fTransform) {
368 fTransform=new AliTPCTransform();
bfec3eeb 369 fTransform->SetCurrentRun(AliCDBManager::Instance()->GetRun());
f5344549 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
f7a1cc68 691 AliMagF* bmap = new AliMagF("MapsExB","MapsExB", 2,factor,1., 10.,AliMagF::k5kG,"$(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
bfec3eeb 768 AliDCSSensor * press = GetPressureSensor(run,0);
da6c0bc9 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
bfec3eeb 816 // run = run number
817 // type = 0 - Cavern pressure
818 // 1 - Suface pressure
0231c65f 819 // First try to get if trom map - if existing (Old format of data storing)
bf85fe4d 820 //
bfec3eeb 821
822
0231c65f 823 TMap *map = GetGRPMap(run);
824 if (map){
825 AliDCSSensor * sensor = 0;
826 TObject *osensor=0;
827 if (type==0) osensor = ((*map)("fCavernPressure"));
828 if (type==1) osensor = ((*map)("fP2Pressure"));
829 sensor =dynamic_cast<AliDCSSensor *>(osensor);
830 if (sensor) return sensor;
831 }
832 //
833 // If not map try to get it from the GRPObject
834 //
835 AliGRPObject * grpRun = dynamic_cast<AliGRPObject *>(fGRPArray.At(run));
bf85fe4d 836 if (!grpRun) {
837 GetRunInformations(run);
efdbb95a 838 grpRun = dynamic_cast<AliGRPObject *>(fGRPArray.At(run));
bf85fe4d 839 if (!grpRun) return 0;
840 }
841 AliDCSSensor * sensor = grpRun->GetCavernAtmosPressure();
da6c0bc9 842 if (type==1) sensor = grpRun->GetSurfaceAtmosPressure();
843 return sensor;
bf85fe4d 844}
845
846AliTPCSensorTempArray * AliTPCcalibDB::GetTemperatureSensor(Int_t run){
847 //
848 // Get temperature sensor array
849 //
850 AliTPCSensorTempArray * tempArray = (AliTPCSensorTempArray *)fTemperatureArray.At(run);
851 if (!tempArray) {
852 GetRunInformations(run);
853 tempArray = (AliTPCSensorTempArray *)fTemperatureArray.At(run);
854 }
855 return tempArray;
856}
857
858AliDCSSensorArray * AliTPCcalibDB::GetGoofieSensors(Int_t run){
859 //
860 // Get temperature sensor array
861 //
862 AliDCSSensorArray * goofieArray = (AliDCSSensorArray *)fGoofieArray.At(run);
863 if (!goofieArray) {
864 GetRunInformations(run);
865 goofieArray = (AliDCSSensorArray *)fGoofieArray.At(run);
866 }
867 return goofieArray;
868}
869
e2914767 870AliDCSSensorArray * AliTPCcalibDB::GetVoltageSensors(Int_t run){
871 //
872 // Get temperature sensor array
873 //
874 AliDCSSensorArray * voltageArray = (AliDCSSensorArray *)fVoltageArray.At(run);
875 if (!voltageArray) {
876 GetRunInformations(run);
877 voltageArray = (AliDCSSensorArray *)fVoltageArray.At(run);
878 }
879 return voltageArray;
880}
881
da6c0bc9 882AliTPCCalibVdrift * AliTPCcalibDB::GetVdrift(Int_t run){
883 //
884 // Get the interface to the the vdrift
885 //
886 AliTPCCalibVdrift * vdrift = (AliTPCCalibVdrift*)fVdriftArray.At(run);
887 if (!vdrift) {
888 GetRunInformations(run);
889 vdrift= (AliTPCCalibVdrift*)fVdriftArray.At(run);
890 }
891 return vdrift;
892}
893
bf85fe4d 894
e2914767 895Float_t AliTPCcalibDB::GetChamberHighVoltage(Int_t timeStamp, Int_t run, Int_t sector) {
896 //
897 // return the chamber HV for given run and time: 0-35 IROC, 36-72 OROC
898 //
899 TTimeStamp stamp(timeStamp);
900 AliDCSSensorArray* voltageArray = AliTPCcalibDB::Instance()->GetVoltageSensors(run);
901 if (!voltageArray) return 0;
902 AliDCSSensor *sensor = voltageArray->GetSensor((sector+1)*3);
903 if (!sensor) return 0;
904 return sensor->GetValue(stamp);
905}
bf85fe4d 906
da6c0bc9 907Float_t AliTPCcalibDB::GetPressure(Int_t timeStamp, Int_t run, Int_t type){
bf85fe4d 908 //
909 // GetPressure for given time stamp and runt
910 //
911 TTimeStamp stamp(timeStamp);
da6c0bc9 912 AliDCSSensor * sensor = Instance()->GetPressureSensor(run,type);
bf85fe4d 913 if (!sensor) return 0;
bf85fe4d 914 return sensor->GetValue(stamp);
915}
916
7f7847fe 917Float_t AliTPCcalibDB::GetValueGoofie(Int_t timeStamp, Int_t run, Int_t type){
918 //
919 // GetPressure for given time stamp and runt
920 //
921 TTimeStamp stamp(timeStamp);
922 AliDCSSensorArray* goofieArray = AliTPCcalibDB::Instance()->GetGoofieSensors(run);
923 if (!goofieArray) return 0;
924 AliDCSSensor *sensor = goofieArray->GetSensor(type);
925 return sensor->GetValue(stamp);
926}
927
928
929
930
931
932
f0269955 933Bool_t AliTPCcalibDB::GetTemperatureFit(Int_t timeStamp, Int_t run, Int_t side,TVectorD& fit){
934 //
935 //
936 //
937 TTimeStamp tstamp(timeStamp);
64b48395 938 AliTPCSensorTempArray* tempArray = Instance()->GetTemperatureSensor(run);
f0269955 939 if (! tempArray) return kFALSE;
940 AliTPCTempMap * tempMap = new AliTPCTempMap(tempArray);
941 TLinearFitter * fitter = tempMap->GetLinearFitter(3,side,tstamp);
942 if (fitter){
943 fitter->Eval();
944 fitter->GetParameters(fit);
945 }
946 delete fitter;
947 delete tempMap;
948 if (!fitter) return kFALSE;
949 return kTRUE;
950}
951
64b48395 952Float_t AliTPCcalibDB::GetTemperature(Int_t timeStamp, Int_t run, Int_t side){
953 //
954 //
955 //
12e42756 956 TVectorD vec(5);
64b48395 957 if (side==0) {
958 GetTemperatureFit(timeStamp,run,0,vec);
959 return vec[0];
960 }
961 if (side==1){
962 GetTemperatureFit(timeStamp,run,0,vec);
963 return vec[0];
964 }
57dc06f2 965 return 0;
64b48395 966}
bf85fe4d 967
968
da6c0bc9 969Double_t AliTPCcalibDB::GetPTRelative(UInt_t timeSec, Int_t run, Int_t side){
970 //
971 // Get relative P/T
972 // time - absolute time
973 // run - run number
974 // side - 0 - A side 1-C side
975 AliTPCCalibVdrift * vdrift = Instance()->GetVdrift(run);
976 if (!vdrift) return 0;
977 return vdrift->GetPTRelative(timeSec,side);
978}
979
bf85fe4d 980
981void AliTPCcalibDB::ProcessEnv(const char * runList){
982 //
983 // Example test function - how to use the environment variables
984 // runList - ascii file with run numbers
985 // output - dcsTime.root file with tree
986
987 ifstream in;
988 in.open(runList);
989 Int_t irun=0;
990 TTreeSRedirector *pcstream = new TTreeSRedirector("dcsTime.root");
991 while(in.good()) {
992 in >> irun;
993 if (irun==0) continue;
994 printf("Processing run %d\n",irun);
995 AliDCSSensor * sensorPressure = AliTPCcalibDB::Instance()->GetPressureSensor(irun);
996 if (!sensorPressure) continue;
997 AliTPCSensorTempArray * tempArray = AliTPCcalibDB::Instance()->GetTemperatureSensor(irun);
998 AliTPCTempMap * tempMap = new AliTPCTempMap(tempArray);
999 AliDCSSensorArray* goofieArray = AliTPCcalibDB::Instance()->GetGoofieSensors(irun);
1000 //
1001 Int_t startTime = sensorPressure->GetStartTime();
1002 Int_t endTime = sensorPressure->GetEndTime();
1003 Int_t dtime = TMath::Max((endTime-startTime)/20,10*60);
1004 for (Int_t itime=startTime; itime<endTime; itime+=dtime){
1005 //
1006 TTimeStamp tstamp(itime);
1007 Float_t valuePressure = sensorPressure->GetValue(tstamp);
1008
1009 TLinearFitter * fitter = 0;
1010 TVectorD vecTemp[10];
1011 if (itime<tempArray->GetStartTime().GetSec() || itime>tempArray->GetEndTime().GetSec()){
1012 }else{
1013 for (Int_t itype=0; itype<5; itype++)
1014 for (Int_t iside=0; iside<2; iside++){
1015 fitter= tempMap->GetLinearFitter(itype,iside,tstamp);
1016 if (!fitter) continue;
1017 fitter->Eval(); fitter->GetParameters(vecTemp[itype+iside*5]);
1018 delete fitter;
1019 }
1020 }
1021
1022 TVectorD vecGoofie, vecEntries, vecMean, vecMedian,vecRMS;
1023 if (goofieArray){
1024 vecGoofie.ResizeTo(goofieArray->NumSensors());
1025 ProcessGoofie(goofieArray, vecEntries ,vecMedian, vecMean, vecRMS);
1026 //
1027 for (Int_t isensor=0; isensor<goofieArray->NumSensors();isensor++){
1028 AliDCSSensor *gsensor = goofieArray->GetSensor(isensor);
1029 if (gsensor){
1030 vecGoofie[isensor] = gsensor->GetValue(tstamp);
1031 }
1032 }
1033 }
1034
1035
1036 //tempMap->GetLinearFitter(0,0,itime);
1037 (*pcstream)<<"dcs"<<
1038 "run="<<irun<<
1039 "time="<<itime<<
1040 "goofie.="<<&vecGoofie<<
1041 "goofieE.="<<&vecEntries<<
1042 "goofieMean.="<<&vecMean<<
1043 "goofieMedian.="<<&vecMedian<<
1044 "goofieRMS.="<<&vecRMS<<
1045 "press="<<valuePressure<<
1046 "temp00.="<<&vecTemp[0]<<
1047 "temp10.="<<&vecTemp[1]<<
1048 "temp20.="<<&vecTemp[2]<<
1049 "temp30.="<<&vecTemp[3]<<
1050 "temp40.="<<&vecTemp[4]<<
1051 "temp01.="<<&vecTemp[5]<<
1052 "temp11.="<<&vecTemp[6]<<
1053 "temp21.="<<&vecTemp[7]<<
1054 "temp31.="<<&vecTemp[8]<<
1055 "temp41.="<<&vecTemp[9]<<
1056 "\n";
1057 }
1058 }
1059 delete pcstream;
1060}
1061
1062
1063void AliTPCcalibDB::ProcessGoofie( AliDCSSensorArray* goofieArray, TVectorD & vecEntries, TVectorD & vecMedian, TVectorD &vecMean, TVectorD &vecRMS){
1064 /*
1065
1066 1 TPC_ANODE_I_A00_STAT
1067 2 TPC_DVM_CO2
1068 3 TPC_DVM_DriftVelocity
1069 4 TPC_DVM_FCageHV
1070 5 TPC_DVM_GainFar
1071 6 TPC_DVM_GainNear
1072 7 TPC_DVM_N2
1073 8 TPC_DVM_NumberOfSparks
1074 9 TPC_DVM_PeakAreaFar
1075 10 TPC_DVM_PeakAreaNear
1076 11 TPC_DVM_PeakPosFar
1077 12 TPC_DVM_PeakPosNear
1078 13 TPC_DVM_PickupHV
1079 14 TPC_DVM_Pressure
1080 15 TPC_DVM_T1_Over_P
1081 16 TPC_DVM_T2_Over_P
1082 17 TPC_DVM_T_Over_P
1083 18 TPC_DVM_TemperatureS1
1084 */
1085 //
1086 //
1087 // TVectorD vecMedian; TVectorD vecEntries; TVectorD vecMean; TVectorD vecRMS;
1088 Double_t kEpsilon=0.0000000001;
1089 Double_t kBig=100000000000.;
1090 Int_t nsensors = goofieArray->NumSensors();
1091 vecEntries.ResizeTo(nsensors);
1092 vecMedian.ResizeTo(nsensors);
1093 vecMean.ResizeTo(nsensors);
1094 vecRMS.ResizeTo(nsensors);
1095 TVectorF values;
1096 for (Int_t isensor=0; isensor<goofieArray->NumSensors();isensor++){
1097 AliDCSSensor *gsensor = goofieArray->GetSensor(isensor);
1098 if (gsensor && gsensor->GetGraph()){
1099 Int_t npoints = gsensor->GetGraph()->GetN();
1100 // filter zeroes
1101 values.ResizeTo(npoints);
1102 Int_t nused =0;
1103 for (Int_t ipoint=0; ipoint<npoints; ipoint++){
1104 if (TMath::Abs(gsensor->GetGraph()->GetY()[ipoint])>kEpsilon &&
1105 TMath::Abs(gsensor->GetGraph()->GetY()[ipoint])<kBig ){
1106 values[nused]=gsensor->GetGraph()->GetY()[ipoint];
1107 nused++;
1108 }
1109 }
1110 //
1111 vecEntries[isensor]= nused;
1112 if (nused>1){
1113 vecMedian[isensor] = TMath::Median(nused,values.GetMatrixArray());
1114 vecMean[isensor] = TMath::Mean(nused,values.GetMatrixArray());
1115 vecRMS[isensor] = TMath::RMS(nused,values.GetMatrixArray());
1116 }
1117 }
1118 }
1119}
1120
e2914767 1121
1122
1123AliGRPObject * AliTPCcalibDB::MakeGRPObjectFromMap(TMap *map){
1124 //
1125 // Function to covert old GRP run information from TMap to GRPObject
1126 //
1127 // TMap * map = AliTPCcalibDB::GetGRPMap(52406);
1128 if (!map) return 0;
1129 AliDCSSensor * sensor = 0;
1130 TObject *osensor=0;
1131 osensor = ((*map)("fP2Pressure"));
1132 sensor =dynamic_cast<AliDCSSensor *>(osensor);
1133 //
1134 if (!sensor) return 0;
1135 //
1136 AliDCSSensor * sensor2 = new AliDCSSensor(*sensor);
1137 osensor = ((*map)("fCavernPressure"));
1138 TGraph * gr = new TGraph(2);
1139 gr->GetX()[0]= -100000.;
1140 gr->GetX()[1]= 1000000.;
1141 gr->GetY()[0]= atof(osensor->GetName());
1142 gr->GetY()[1]= atof(osensor->GetName());
1143 sensor2->SetGraph(gr);
1144 sensor2->SetFit(0);
1145
1146
1147 AliGRPObject *grpRun = new AliGRPObject;
1148 grpRun->ReadValuesFromMap(map);
1149 grpRun->SetCavernAtmosPressure(sensor2);
1150 grpRun->SetSurfaceAtmosPressure(sensor);
1151 return grpRun;
1152}
1153
1154
1155