1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 ///////////////////////////////////////////////////////////////////////////////
19 // TPC calibration class for temperature maps and tendencies //
20 // (based on TPC Temperature Sensors and FiniteElement Simulation) //
22 // Authors: Stefan Rossegger, Haavard Helstrup //
24 // Note: Obvioulsy some changes by Marian, but when ??? //
26 ///////////////////////////////////////////////////////////////////////////////
28 #include "AliTPCSensorTempArray.h"
29 #include "TLinearFitter.h"
32 #include "TTimeStamp.h"
34 #include "AliTPCTempMap.h"
37 ClassImp(AliTPCTempMap)
39 const char kStringFEsimulation[] = "FEsimulation.txt";
41 //_____________________________________________________________________________
42 AliTPCTempMap::AliTPCTempMap(AliTPCSensorTempArray *sensorDCS):
45 fStringFEsimulation(kStringFEsimulation)
48 // AliTPCTempMap default constructor
51 fTempArray = sensorDCS;
55 //_____________________________________________________________________________
56 AliTPCTempMap::AliTPCTempMap(const AliTPCTempMap &c):
58 fTempArray(c.fTempArray),
59 fStringFEsimulation(c.fStringFEsimulation)
62 // AliTPCTempMap copy constructor
67 //_____________________________________________________________________________
68 AliTPCTempMap::~AliTPCTempMap()
71 // AliTPCTempMap destructor
76 //_____________________________________________________________________________
77 AliTPCTempMap &AliTPCTempMap::operator=(const AliTPCTempMap &c)
80 // Assignment operator
83 if (this != &c) ((AliTPCTempMap &) c).Copy(*this);
88 //_____________________________________________________________________________
89 void AliTPCTempMap::Copy(TObject &c) const
99 //_____________________________________________________________________________
101 Double_t AliTPCTempMap::GetTempGradientY(UInt_t timeSec, Int_t side){
103 // Extract Linear Vertical Temperature Gradient [K/cm] within the TPC on
106 // Values based on TemperatureSensors within the TPC ( type: 3 (TPC) )
108 // FIXME: Also return residual-distribution, covariance Matrix
109 // or simply chi2 for validity check?
110 // -> better use GetLinearFitter - function in this case!
112 TLinearFitter *fitter = new TLinearFitter(3,"x0++x1++x2");
116 Int_t nsensors = fTempArray->NumSensors();
117 for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
118 AliTPCSensorTemp *entry = (AliTPCSensorTemp*)fTempArray->GetSensorNum(isensor);
120 if (entry->GetType()==3 && entry->GetSide()==side) { // take SensorType:TPC
125 Double_t y = fTempArray->GetValue(timeSec,isensor); // get temperature value
126 if (IsOK(y)) fitter->AddPoint(x,y,1); // add values to LinearFitter
132 fitter->GetParameters(param);
134 fitter->~TLinearFitter();
136 return param[2]; // return vertical (Y) tempGradient in [K/cm]
140 //_____________________________________________________________________________
141 TLinearFitter *AliTPCTempMap::GetLinearFitter(Int_t type, Int_t side, TTimeStamp &stamp)
144 // absolute time stamp used
145 // see AliTPCTempMap::GetLinearFitter(Int_t type, Int_t side, UInt_t timeSec) for details
147 Int_t timeSec = stamp.GetSec()-fTempArray->GetStartTime().GetSec();
148 return GetLinearFitter(type,side,timeSec);
151 //_____________________________________________________________________________
152 TLinearFitter *AliTPCTempMap::GetLinearFitter(Int_t type, Int_t side, UInt_t timeSec)
155 // Creates a TlinearFitter object for the desired region of the TPC
156 // (via choosen type and side of TPC temperature sensors) at a given
157 // timeSec (in secounds) after start time
158 // type: 0 ... ReadOutChambers (ROC)
159 // 1 ... OuterContainmentVessel (OFC)
160 // 2 ... InnerContainmentVessel (IFC) + ThermalScreener (TS)
161 // 3 ... Within the TPC (DriftVolume) (TPC)
162 // 4 ... Only InnerContainmentVessel (IFC)
163 // side: Can be choosen for type 0 and 3 (otherwise it will be ignored in
164 // in order to get all temperature sensors of interest)
165 // 0 ... Shaft Side (A)
166 // 1 ... Muon Side (C)
169 TLinearFitter *fitter = new TLinearFitter(3);
170 Double_t *x = new Double_t[3];
172 const Float_t kMaxDelta=0.5;
174 if (type == 1 || type == 2 || type == 4) {
175 fitter->SetFormula("x0++x1++TMath::Sin(x2)"); // returns Z,Y gradient
177 fitter->SetFormula("x0++x1++x2"); // returns X,Y gradient
181 Int_t nsensors = fTempArray->NumSensors();
184 for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
185 AliTPCSensorTemp *entry = (AliTPCSensorTemp*)fTempArray->GetSensorNum(isensor);
186 if (entry->GetType()==type && entry->GetSide()==side){
187 Float_t temperature= fTempArray->GetValue(timeSec,isensor); // get temperature value
188 if (IsOK(temperature)) {temps[i]=temperature; i++;}
191 Float_t medianTemp = TMath::Median(i, temps);
193 Float_t rmsTemp = TMath::RMS(i, temps);
197 for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
198 AliTPCSensorTemp *entry = (AliTPCSensorTemp*)fTempArray->GetSensorNum(isensor);
200 if (type==0 || type==3) { // 'side' information used
201 if (entry->GetType()==type && entry->GetSide()==side) {
205 y = fTempArray->GetValue(timeSec,isensor); // get temperature value
206 if (TMath::Abs(y-medianTemp)>kMaxDelta+4.*rmsTemp) continue;
207 if (IsOK(y)) fitter->AddPoint(x,y,1); // add values to LinearFitter
210 } else if (type==2) { // in case of IFC also usage of TS values
211 if ((entry->GetType()==2) || (entry->GetType()==5)) {
214 x[2]=entry->GetPhi();
215 y = fTempArray->GetValue(timeSec,isensor);
216 if (TMath::Abs(y-medianTemp)>kMaxDelta+4.*rmsTemp) continue;
217 if (IsOK(y)) fitter->AddPoint(x,y,1);
221 if (entry->GetType()==type) {
224 x[2]=entry->GetPhi();
225 y = fTempArray->GetValue(timeSec,isensor);
226 if (TMath::Abs(y-medianTemp)>kMaxDelta+4.*rmsTemp) continue;
227 if (IsOK(y)) fitter->AddPoint(x,y,1);
230 } else if (type==4) { // ONLY IFC
231 if (entry->GetType()==2) {
234 x[2]=entry->GetPhi();
235 y = fTempArray->GetValue(timeSec,isensor);
236 if (TMath::Abs(y-medianTemp)>kMaxDelta+4.*rmsTemp) continue;
237 if (IsOK(y)) fitter->AddPoint(x,y,1);
243 //fitter->EvalRobust(0.9); // Evaluates fitter
249 // returns TLinearFitter object where Chi2, Fitparameters and residuals can
250 // be extracted via usual memberfunctions
251 // example: fitter->GetParameters(param)
252 // In case of type IFC or OFC, the parameters are the gradients in
253 // Z and Y direction (see fitformula)
254 // Caution: Parameters are [K/cm] except Y at IFC,OFC ([K/radius])
257 //_____________________________________________________________________________
259 TGraph2D *AliTPCTempMap::GetTempMapsViaSensors(Int_t type, Int_t side, UInt_t timeSec)
262 // Creates a TGraph2D object for the desired region of the TPC
263 // (via choosen type and side of TPC temperature sensors) at a given
264 // timeSec (in secounds) after start time
265 // type: 0 ... ReadOutChambers (ROC)
266 // 1 ... OuterContainmentVessel (OFC)
267 // 2 ... InnerContainmentVessel (IFC) + ThermalScreener (TS)
268 // 3 ... Within the TPC (DriftVolume) (TPC)
269 // side: Can be choosen for type 0 and 3 (otherwise it will be ignored in
270 // in order to get all temperature sensors of interest)
275 TGraph2D *graph2D = new TGraph2D();
279 Int_t nsensors = fTempArray->NumSensors();
280 for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
281 AliTPCSensorTemp *entry = (AliTPCSensorTemp*)fTempArray->GetSensorNum(isensor);
283 Double_t x, y, z, r, phi, tempValue;
288 phi = entry->GetPhi();
289 tempValue = fTempArray->GetValue(timeSec,isensor);
290 // printf("%d type %d: x=%lf y=%lf temp=%lf\n",isensor,entry->GetType(),x,y, tempValue);
291 if (type==0 || type==3) { // 'side' information used
292 if (entry->GetType()==type && entry->GetSide()==side) {
293 graph2D->SetPoint(i,x,y,tempValue);
296 } else if (type==2) { // in case of IFC also usage of TS values
297 if (entry->GetType()==2 || entry->GetType()==5) {
298 graph2D->SetPoint(i,z,phi,tempValue);
302 if (entry->GetType()==type) {
303 graph2D->SetPoint(i,z,phi,tempValue);
309 if (type==0 || type==3) {
310 graph2D->GetXaxis()->SetTitle("X[cm]");
311 graph2D->GetYaxis()->SetTitle("Y[cm]");
312 if (type==0 && side==0) {
313 graph2D->SetTitle("ROC A side");
314 } else if (type==0 && side==1) {
315 graph2D->SetTitle("ROC C side");
316 } else if (type==3 && side==0) {
317 graph2D->SetTitle("TPC A side (Inside the TPC)");
318 } else if (type==3 && side==1) {
319 graph2D->SetTitle("TPC C side (Inside the TPC)");
321 } else if (type==1 || type==2) {
322 graph2D->GetXaxis()->SetTitle("Z[cm]");
323 graph2D->GetYaxis()->SetTitle("Phi[RAD]");
325 graph2D->SetTitle("Outer Containment Vessel");
326 } else if (type==2) {
327 graph2D->SetTitle("Inner Containment Vessel");
331 if (!graph2D->GetN()) {
332 printf("Returned TGraph2D is empty: check type and side values\n");
335 graph2D->GetXaxis()->SetLabelOffset(0.0);
336 graph2D->GetYaxis()->SetLabelOffset(0.005);
337 graph2D->GetZaxis()->SetLabelOffset(-0.04);
340 return graph2D; // returns TGgraph2D object
345 //_____________________________________________________________________________
347 TGraph *AliTPCTempMap::MakeGraphGradient(Int_t axis, Int_t side, Int_t nPoints)
350 // Make graph from start time to end time of TempGradient in axis direction
351 // axis: 0 ... horizontal Temperature Gradient (X)
352 // 1 ... vertical Temperature Gradient (Y)
353 // 2 ... longitudenal Temperature Gradient (Z) (side is ignored)
354 // z gradient value based on OFC temperature sensors
355 // Caution!: better z gradient values through difference between
356 // param[0] A- and param[0] C-side !
357 // side for X and Y gradient:
358 // 0 ... Shaft Side (A)
359 // 1 ... Muon Side (C)
363 TLinearFitter *fitter = new TLinearFitter(3);
365 UInt_t fStartTime = fTempArray->AliTPCSensorTempArray::GetStartTime();
366 UInt_t fEndTime = fTempArray->AliTPCSensorTempArray::GetEndTime();
368 UInt_t stepTime = (fEndTime-fStartTime)/nPoints;
370 Double_t *x = new Double_t[nPoints];
371 Double_t *y = new Double_t[nPoints];
372 for (Int_t ip=0; ip<nPoints; ip++) {
373 x[ip] = fStartTime+ip*stepTime;
374 if (axis==2) {// Gradient in Z direction (based on OFC tempSensors)
375 fitter = GetLinearFitter(1, side, ip*stepTime);
376 } else {// Gradient in X or Y direction (based on TPC tempSensors)
377 fitter = GetLinearFitter(3, side, ip*stepTime);
379 fitter->GetParameters(param);
380 // multiplied by 500 since TempGradient is in [K/cm]
381 // (TPC diameter and length ~500cm)
382 if (axis==1) { // Y axis
383 y[ip] = param[2]*500;
385 y[ip] = param[1]*500;
389 TGraph *graph = new TGraph(nPoints,x,y);
391 fitter->~TLinearFitter();
395 graph->GetXaxis()->SetTimeDisplay(1);
396 graph->GetXaxis()->SetLabelOffset(0.02);
397 graph->GetXaxis()->SetTimeFormat("#splitline{%d/%m}{%H:%M}");
403 //_____________________________________________________________________________
404 Double_t AliTPCTempMap::GetTemperature(Double_t x, Double_t y, Double_t z, TTimeStamp &stamp)
407 // absolute time stamp used
408 // see also Double_t AliTPCTempMap::GetTemperature(Double_t x, Double_t y, Double_t z, UInt_t timeSec) for details
411 Int_t timeSec = stamp.GetSec()-fTempArray->GetStartTime().GetSec();
412 return GetTemperature(x, y, z, timeSec);
415 //_____________________________________________________________________________
417 Double_t AliTPCTempMap::GetTemperature(Double_t x, Double_t y, Double_t z, UInt_t timeSec)
420 // Returns estimated Temperature at given position (x,y,z[cm]) at given time
421 // (timeSec) after starttime
422 // Method: so far just a linear interpolation between Linar fits of
423 // the TPC temperature sensors
424 // FIXME: 'Educated Fit' through FiniteElement Simulation results!
425 // FIXXME: Return 0? if x,y,z out of range
428 TVectorD paramA(3), paramC(3);
429 TLinearFitter *fitterA = new TLinearFitter(3);
430 TLinearFitter *fitterC = new TLinearFitter(3);
432 fitterA = GetLinearFitter(3, 0, timeSec);
433 fitterA->GetParameters(paramA);
434 fitterC = GetLinearFitter(3, 1, timeSec);
435 fitterC->GetParameters(paramC);
437 Double_t fvalA = paramA[0]+paramA[1]*x+paramA[2]*y;
438 Double_t fvalC = paramC[0]+paramC[1]*x+paramC[2]*y;
440 Double_t k = (fvalA-fvalC)/(2*247);
441 Double_t tempValue = fvalC+(fvalA-fvalC)/2+k*z;
443 fitterA->~TLinearFitter();
444 fitterC->~TLinearFitter();
451 Bool_t AliTPCTempMap::IsOK(Float_t value){
453 // checks if value is within a certain range
455 const Float_t kMinT=15;
456 const Float_t kMaxT=25;
457 return (value>kMinT && value<kMaxT);