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 ///////////////////////////////////////////////////////////////////////////////
26 #include "AliTPCSensorTempArray.h"
27 #include "TLinearFitter.h"
31 #include "AliTPCTempMap.h"
34 ClassImp(AliTPCTempMap)
36 const char kStringFEsimulation[] = "FEsimulation.txt";
38 //_____________________________________________________________________________
39 AliTPCTempMap::AliTPCTempMap(AliTPCSensorTempArray *sensorDCS):
42 fStringFEsimulation(kStringFEsimulation)
45 // AliTPCTempMap default constructor
52 //_____________________________________________________________________________
53 AliTPCTempMap::AliTPCTempMap(const AliTPCTempMap &c):
56 fStringFEsimulation(c.fStringFEsimulation)
59 // AliTPCTempMap copy constructor
64 //_____________________________________________________________________________
65 AliTPCTempMap::~AliTPCTempMap()
68 // AliTPCTempMap destructor
73 //_____________________________________________________________________________
74 AliTPCTempMap &AliTPCTempMap::operator=(const AliTPCTempMap &c)
77 // Assignment operator
80 if (this != &c) ((AliTPCTempMap &) c).Copy(*this);
85 //_____________________________________________________________________________
86 void AliTPCTempMap::Copy(TObject &c) const
96 //_____________________________________________________________________________
98 Double_t AliTPCTempMap::GetTempGradientY(UInt_t timeSec, Int_t side){
100 // Extract Linear Vertical Temperature Gradient [K/cm] within the TPC on
103 // Values based on TemperatureSensors within the TPC ( type: 3 (TPC) )
105 // FIXME: Also return residual-distribution, covariance Matrix
106 // or simply chi2 for validity check?
107 // -> better use GetLinearFitter - function in this case!
109 TLinearFitter *fitter = new TLinearFitter(3,"x0++x1++x2");
113 Int_t nsensors = ft->NumSensors();
114 for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
115 AliTPCSensorTemp *entry = (AliTPCSensorTemp*)ft->GetSensorNum(isensor);
117 if (entry->GetType()==3 && entry->GetSide()==side) { // take SensorType:TPC
122 Double_t y = entry->GetValue(timeSec); // get temperature value
123 fitter->AddPoint(x,y,1); // add values to LinearFitter
129 fitter->GetParameters(param);
131 fitter->~TLinearFitter();
133 return param[2]; // return vertical (Y) tempGradient in [K/cm]
137 //_____________________________________________________________________________
139 TLinearFitter *AliTPCTempMap::GetLinearFitter(Int_t type, Int_t side, UInt_t timeSec)
142 // Creates a TlinearFitter object for the desired region of the TPC
143 // (via choosen type and side of TPC temperature sensors) at a given
144 // timeSec (in secounds) after start time
145 // type: 0 ... ReadOutChambers (ROC)
146 // 1 ... OuterContainmentVessel (OFC)
147 // 2 ... InnerContainmentVessel (IFC) + ThermalScreener (TS)
148 // 3 ... Within the TPC (DriftVolume) (TPC)
149 // 4 ... Only InnerContainmentVessel (IFC)
150 // side: Can be choosen for type 0 and 3 (otherwise it will be ignored in
151 // in order to get all temperature sensors of interest)
152 // 0 ... Shaft Side (A)
153 // 1 ... Muon Side (C)
156 TLinearFitter *fitter = new TLinearFitter(3);
157 Double_t *x = new Double_t[3];
160 if (type == 1 || type == 2 || type == 4) {
161 fitter->SetFormula("x0++x1++TMath::Sin(x2)"); // returns Z,Y gradient
163 fitter->SetFormula("x0++x1++x2"); // returns X,Y gradient
167 Int_t nsensors = ft->NumSensors();
168 for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
169 AliTPCSensorTemp *entry = (AliTPCSensorTemp*)ft->GetSensorNum(isensor);
171 if (type==0 || type==3) { // 'side' information used
172 if (entry->GetType()==type && entry->GetSide()==side) {
176 y = entry->GetValue(timeSec); // get temperature value
177 fitter->AddPoint(x,y,1); // add values to LinearFitter
180 } else if (type==2) { // in case of IFC also usage of TS values
181 if ((entry->GetType()==2) || (entry->GetType()==5)) {
184 x[2]=entry->GetPhi();
185 y = entry->GetValue(timeSec);
186 fitter->AddPoint(x,y,1);
190 if (entry->GetType()==type) {
193 x[2]=entry->GetPhi();
194 y = entry->GetValue(timeSec);
195 fitter->AddPoint(x,y,1);
198 } else if (type==4) { // ONLY IFC
199 if (entry->GetType()==2) {
202 x[2]=entry->GetPhi();
203 y = entry->GetValue(timeSec);
204 fitter->AddPoint(x,y,1);
209 fitter->Eval(); // Evaluates fitter
215 // returns TLinearFitter object where Chi2, Fitparameters and residuals can
216 // be extracted via usual memberfunctions
217 // example: fitter->GetParameters(param)
218 // In case of type IFC or OFC, the parameters are the gradients in
219 // Z and Y direction (see fitformula)
220 // Caution: Parameters are [K/cm] except Y at IFC,OFC ([K/radius])
223 //_____________________________________________________________________________
225 TGraph2D *AliTPCTempMap::GetTempMapsViaSensors(Int_t type, Int_t side, UInt_t timeSec)
228 // Creates a TGraph2D object for the desired region of the TPC
229 // (via choosen type and side of TPC temperature sensors) at a given
230 // timeSec (in secounds) after start time
231 // type: 0 ... ReadOutChambers (ROC)
232 // 1 ... OuterContainmentVessel (OFC)
233 // 2 ... InnerContainmentVessel (IFC) + ThermalScreener (TS)
234 // 3 ... Within the TPC (DriftVolume) (TPC)
235 // side: Can be choosen for type 0 and 3 (otherwise it will be ignored in
236 // in order to get all temperature sensors of interest)
237 // 0 ... Shaft Side (A)
238 // 1 ... Muon Side (C)
241 TGraph2D *graph2D = new TGraph2D();
246 Int_t nsensors = ft->NumSensors();
249 for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
250 AliTPCSensorTemp *entry = (AliTPCSensorTemp*)ft->GetSensorNum(isensor);
252 Double_t x, y, z, r, phi, tempValue;
257 phi = entry->GetPhi();
258 tempValue = entry->GetValue(timeSec);
260 if (type==0 || type==3) { // 'side' information used
261 if (entry->GetType()==type && entry->GetSide()==side) {
262 graph2D->SetPoint(i,x,y,tempValue);
265 } else if (type==2) { // in case of IFC also usage of TS values
266 if (entry->GetType()==2 || entry->GetType()==5) {
267 graph2D->SetPoint(i,z,phi,tempValue);
271 if (entry->GetType()==type) {
272 graph2D->SetPoint(i,z,phi,tempValue);
278 if (type==0 || type==3) {
279 graph2D->GetXaxis()->SetTitle("X[cm]");
280 graph2D->GetYaxis()->SetTitle("Y[cm]");
281 if (type==0 && side==0) {
282 graph2D->SetTitle("ROC A - Endplate Shaft Side");
283 } else if (type==0 && side==1) {
284 graph2D->SetTitle("ROC C - Endplate Muon Side");
285 } else if (type==3 && side==0) {
286 graph2D->SetTitle("TPC A - Inside the TPC Shaft Side");
287 } else if (type==3 && side==1) {
288 graph2D->SetTitle("TPC C - Inside the TPC Muon Side");
290 } else if (type==1 || type==2) {
291 graph2D->GetXaxis()->SetTitle("Z[cm]");
292 graph2D->GetYaxis()->SetTitle("Phi[RAD]");
294 graph2D->SetTitle("Outer Containment Vessel");
295 } else if (type==2) {
296 graph2D->SetTitle("InnerContainmentVessel + ThermalScreeners");
300 if (!graph2D->GetN()) {
301 printf("Returned TGraph2D is empty: check type and side values\n");
304 graph2D->GetXaxis()->SetLabelOffset(0.0);
305 graph2D->GetYaxis()->SetLabelOffset(0.005);
306 graph2D->GetZaxis()->SetLabelOffset(-0.04);
309 return graph2D; // returns TGgraph2D object
314 //_____________________________________________________________________________
316 TGraph *AliTPCTempMap::MakeGraphGradient(Int_t axis, Int_t side, Int_t nPoints)
319 // Make graph from start time to end time of TempGradient in axis direction
320 // axis: 0 ... horizontal Temperature Gradient (X)
321 // 1 ... vertical Temperature Gradient (Y)
322 // 2 ... longitudenal Temperature Gradient (Z) (side is ignored)
323 // z gradient value based on OFC temperature sensors
324 // Caution!: better z gradient values through difference between
325 // param[0] A- and param[0] C-side !
326 // side for X and Y gradient:
327 // 0 ... Shaft Side (A)
328 // 1 ... Muon Side (C)
332 TLinearFitter *fitter = new TLinearFitter(3);
334 UInt_t fStartTime = ft->AliTPCSensorTempArray::GetStartTime();
335 UInt_t fEndTime = ft->AliTPCSensorTempArray::GetEndTime();
337 UInt_t stepTime = (fEndTime-fStartTime)/nPoints;
339 Double_t *x = new Double_t[nPoints];
340 Double_t *y = new Double_t[nPoints];
341 for (Int_t ip=0; ip<nPoints; ip++) {
342 x[ip] = fStartTime+ip*stepTime;
343 if (axis==2) {// Gradient in Z direction (based on OFC tempSensors)
344 fitter = GetLinearFitter(1, side, ip*stepTime);
345 } else {// Gradient in X or Y direction (based on TPC tempSensors)
346 fitter = GetLinearFitter(3, side, ip*stepTime);
348 fitter->GetParameters(param);
349 // multiplied by 500 since TempGradient is in [K/cm]
350 // (TPC diameter and length ~500cm)
351 if (axis==1) { // Y axis
352 y[ip] = param[2]*500;
354 y[ip] = param[1]*500;
358 TGraph *graph = new TGraph(nPoints,x,y);
360 fitter->~TLinearFitter();
364 graph->GetXaxis()->SetTimeDisplay(1);
365 graph->GetXaxis()->SetLabelOffset(0.02);
366 graph->GetXaxis()->SetTimeFormat("#splitline{%d/%m}{%H:%M}");
371 //_____________________________________________________________________________
373 Double_t AliTPCTempMap::GetTemperature(Double_t x, Double_t y, Double_t z, UInt_t timeSec)
376 // Returns estimated Temperature at given position (x,y,z) at given time
377 // (timeSec) after starttime
378 // Method: so far just a linear interpolation between Linar fits of
379 // the TPC temperature sensors
380 // FIXME: 'Educated Fit' through FiniteElement Simulation results!
381 // FIXXME: Return 0? if x,y,z out of range
384 TVectorD paramA(3), paramC(3);
385 TLinearFitter *fitterA = new TLinearFitter(3);
386 TLinearFitter *fitterC = new TLinearFitter(3);
388 fitterA = GetLinearFitter(3, 0, timeSec);
389 fitterA->GetParameters(paramA);
390 fitterC = GetLinearFitter(3, 1, timeSec);
391 fitterC->GetParameters(paramC);
393 Double_t fvalA = paramA[0]+paramA[1]*x+paramA[2]*y;
394 Double_t fvalC = paramC[0]+paramC[1]*x+paramC[2]*y;
396 Double_t k = (fvalA-fvalC)/(2*247);
397 Double_t tempValue = fvalC+(fvalA-fvalC)/2+k*z;
399 fitterA->~TLinearFitter();
400 fitterC->~TLinearFitter();