Line data Source code
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 : /// \class AliTPCTempMap
18 : /// \brief TPC calibration class for temperature maps and tendencies
19 : ///
20 : /// (based on TPC Temperature Sensors and FiniteElement Simulation)
21 : ///
22 : /// Note: Obvioulsy some changes by Marian, but when ???
23 : ///
24 : /// \author Stefan Rossegger, Haavard Helstrup
25 :
26 : #include "AliTPCSensorTempArray.h"
27 : #include "TLinearFitter.h"
28 : #include "TString.h"
29 : #include "TGraph2D.h"
30 : #include "TTimeStamp.h"
31 :
32 : #include "AliTPCTempMap.h"
33 :
34 :
35 : /// \cond CLASSIMP
36 24 : ClassImp(AliTPCTempMap)
37 : /// \endcond
38 :
39 : const char kStringFEsimulation[] = "FEsimulation.txt";
40 :
41 : //_____________________________________________________________________________
42 : AliTPCTempMap::AliTPCTempMap(AliTPCSensorTempArray *sensorDCS):
43 0 : TNamed(),
44 0 : fTempArray(0),
45 0 : fStringFEsimulation(kStringFEsimulation)
46 0 : {
47 : /// AliTPCTempMap default constructor
48 :
49 0 : fTempArray = sensorDCS;
50 :
51 0 : }
52 :
53 : //_____________________________________________________________________________
54 : AliTPCTempMap::AliTPCTempMap(const AliTPCTempMap &c):
55 0 : TNamed(c),
56 0 : fTempArray(c.fTempArray),
57 0 : fStringFEsimulation(c.fStringFEsimulation)
58 0 : {
59 : /// AliTPCTempMap copy constructor
60 :
61 0 : }
62 :
63 : //_____________________________________________________________________________
64 : AliTPCTempMap::~AliTPCTempMap()
65 0 : {
66 : /// AliTPCTempMap destructor
67 :
68 0 : }
69 :
70 : //_____________________________________________________________________________
71 : AliTPCTempMap &AliTPCTempMap::operator=(const AliTPCTempMap &c)
72 : {
73 : /// Assignment operator
74 :
75 0 : if (this != &c) ((AliTPCTempMap &) c).Copy(*this);
76 0 : return *this;
77 :
78 : }
79 :
80 : //_____________________________________________________________________________
81 : void AliTPCTempMap::Copy(TObject &c) const
82 : {
83 : /// Copy function
84 :
85 0 : TObject::Copy(c);
86 :
87 0 : }
88 :
89 : //_____________________________________________________________________________
90 :
91 : Double_t AliTPCTempMap::GetTempGradientY(UInt_t timeSec, Int_t side){
92 : /// Extract Linear Vertical Temperature Gradient [K/cm] within the TPC on
93 : /// Shaft Side(A): 0
94 : /// Muon Side(C): 1
95 : /// Values based on TemperatureSensors within the TPC ( type: 3 (TPC) )
96 : ///
97 : /// FIXME: Also return residual-distribution, covariance Matrix
98 : /// or simply chi2 for validity check?
99 : /// -> better use GetLinearFitter - function in this case!
100 :
101 0 : TLinearFitter *fitter = new TLinearFitter(3,"x0++x1++x2");
102 0 : TVectorD param(3);
103 : Int_t i = 0;
104 :
105 0 : Int_t nsensors = fTempArray->NumSensors();
106 0 : for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
107 0 : AliTPCSensorTemp *entry = (AliTPCSensorTemp*)fTempArray->GetSensorNum(isensor);
108 :
109 0 : if (entry->GetType()==3 && entry->GetSide()==side) { // take SensorType:TPC
110 0 : Double_t x[3];
111 0 : x[0]=1;
112 0 : x[1]=entry->GetX();
113 0 : x[2]=entry->GetY();
114 0 : Double_t y = fTempArray->GetValue(timeSec,isensor); // get temperature value
115 0 : if (IsOK(y)) fitter->AddPoint(x,y,1); // add values to LinearFitter
116 0 : i++;
117 0 : }
118 :
119 : }
120 0 : fitter->Eval();
121 0 : fitter->GetParameters(param);
122 :
123 0 : fitter->~TLinearFitter();
124 :
125 0 : return param[2]; // return vertical (Y) tempGradient in [K/cm]
126 :
127 0 : }
128 :
129 : //_____________________________________________________________________________
130 : TLinearFitter *AliTPCTempMap::GetLinearFitter(Int_t type, Int_t side, TTimeStamp &stamp)
131 : {
132 : /// absolute time stamp used
133 : /// see AliTPCTempMap::GetLinearFitter(Int_t type, Int_t side, UInt_t timeSec) for details
134 :
135 0 : Int_t timeSec = stamp.GetSec()-fTempArray->GetStartTime().GetSec();
136 0 : return GetLinearFitter(type,side,timeSec);
137 : }
138 :
139 : //_____________________________________________________________________________
140 : TLinearFitter *AliTPCTempMap::GetLinearFitter(Int_t type, Int_t side, UInt_t timeSec)
141 : {
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)
154 :
155 0 : TLinearFitter *fitter = new TLinearFitter(3);
156 0 : Double_t x[3]={0};
157 : Double_t y = 0;
158 : const Float_t kMaxDelta=0.5;
159 :
160 0 : if (type == 1 || type == 2 || type == 4) {
161 0 : fitter->SetFormula("x0++x1++TMath::Sin(x2)"); // returns Z,Y gradient
162 0 : } else {
163 0 : fitter->SetFormula("x0++x1++x2"); // returns X,Y gradient
164 : }
165 :
166 : Int_t i = 0;
167 0 : Int_t nsensors = fTempArray->NumSensors();
168 :
169 0 : Float_t temps[1000];
170 0 : for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
171 0 : AliTPCSensorTemp *entry = (AliTPCSensorTemp*)fTempArray->GetSensorNum(isensor);
172 0 : if (entry->GetType()==type && entry->GetSide()==side){
173 0 : Float_t temperature= fTempArray->GetValue(timeSec,isensor); // get temperature value
174 0 : if (IsOK(temperature)) {temps[i]=temperature; i++;}
175 0 : }
176 : }
177 0 : Float_t medianTemp = TMath::Median(i, temps);
178 0 : if (i<3) return 0;
179 0 : Float_t rmsTemp = TMath::RMS(i, temps);
180 :
181 : i=0;
182 :
183 0 : for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
184 0 : AliTPCSensorTemp *entry = (AliTPCSensorTemp*)fTempArray->GetSensorNum(isensor);
185 :
186 0 : if (type==0 || type==3) { // 'side' information used
187 0 : if (entry->GetType()==type && entry->GetSide()==side) {
188 0 : x[0]=1;
189 0 : x[1]=entry->GetX();
190 0 : x[2]=entry->GetY();
191 0 : y = fTempArray->GetValue(timeSec,isensor); // get temperature value
192 0 : if (TMath::Abs(y-medianTemp)>kMaxDelta+4.*rmsTemp) continue;
193 0 : if (IsOK(y)) fitter->AddPoint(x,y,1); // add values to LinearFitter
194 0 : i++;
195 0 : }
196 0 : } else if (type==2) { // in case of IFC also usage of TS values
197 0 : if ((entry->GetType()==2) || (entry->GetType()==5)) {
198 0 : x[0]=1;
199 0 : x[1]=entry->GetZ();
200 0 : x[2]=entry->GetPhi();
201 0 : y = fTempArray->GetValue(timeSec,isensor);
202 0 : if (TMath::Abs(y-medianTemp)>kMaxDelta+4.*rmsTemp) continue;
203 0 : if (IsOK(y)) fitter->AddPoint(x,y,1);
204 0 : i++;
205 0 : }
206 0 : } else if (type==1){
207 0 : if (entry->GetType()==type) {
208 0 : x[0]=1;
209 0 : x[1]=entry->GetZ();
210 0 : x[2]=entry->GetPhi();
211 0 : y = fTempArray->GetValue(timeSec,isensor);
212 0 : if (TMath::Abs(y-medianTemp)>kMaxDelta+4.*rmsTemp) continue;
213 0 : if (IsOK(y)) fitter->AddPoint(x,y,1);
214 0 : i++;
215 0 : }
216 0 : } else if (type==4) { // ONLY IFC
217 0 : if (entry->GetType()==2) {
218 0 : x[0]=1;
219 0 : x[1]=entry->GetZ();
220 0 : x[2]=entry->GetPhi();
221 0 : y = fTempArray->GetValue(timeSec,isensor);
222 0 : if (TMath::Abs(y-medianTemp)>kMaxDelta+4.*rmsTemp) continue;
223 0 : if (IsOK(y)) fitter->AddPoint(x,y,1);
224 0 : i++;
225 0 : }
226 : }
227 0 : }
228 0 : fitter->Eval();
229 : //fitter->EvalRobust(0.9); // Evaluates fitter
230 :
231 :
232 : return fitter;
233 :
234 : // returns TLinearFitter object where Chi2, Fitparameters and residuals can
235 : // be extracted via usual memberfunctions
236 : // example: fitter->GetParameters(param)
237 : // In case of type IFC or OFC, the parameters are the gradients in
238 : // Z and Y direction (see fitformula)
239 : // Caution: Parameters are [K/cm] except Y at IFC,OFC ([K/radius])
240 0 : }
241 :
242 : //_____________________________________________________________________________
243 :
244 : TGraph2D *AliTPCTempMap::GetTempMapsViaSensors(Int_t type, Int_t side, UInt_t timeSec)
245 : {
246 : /// Creates a TGraph2D object for the desired region of the TPC
247 : /// (via choosen type and side of TPC temperature sensors) at a given
248 : /// timeSec (in secounds) after start time
249 : /// type: 0 ... ReadOutChambers (ROC)
250 : /// 1 ... OuterContainmentVessel (OFC)
251 : /// 2 ... InnerContainmentVessel (IFC) + ThermalScreener (TS)
252 : /// 3 ... Within the TPC (DriftVolume) (TPC)
253 : /// side: Can be choosen for type 0 and 3 (otherwise it will be ignored in
254 : /// in order to get all temperature sensors of interest)
255 : /// 0 ... A - side
256 : /// 1 ... C - side
257 :
258 0 : TGraph2D *graph2D = new TGraph2D();
259 :
260 : Int_t i = 0;
261 :
262 0 : Int_t nsensors = fTempArray->NumSensors();
263 0 : for (Int_t isensor=0; isensor<nsensors; isensor++) { // loop over all sensors
264 0 : AliTPCSensorTemp *entry = (AliTPCSensorTemp*)fTempArray->GetSensorNum(isensor);
265 :
266 : Double_t x, y, z, r, phi, tempValue;
267 0 : x = entry->GetX();
268 0 : y = entry->GetY();
269 0 : z = entry->GetZ();
270 0 : r = entry->GetR();
271 0 : phi = entry->GetPhi();
272 0 : tempValue = fTempArray->GetValue(timeSec,isensor);
273 : // printf("%d type %d: x=%lf y=%lf temp=%lf\n",isensor,entry->GetType(),x,y, tempValue);
274 0 : if (type==0 || type==3) { // 'side' information used
275 0 : if (entry->GetType()==type && entry->GetSide()==side) {
276 0 : graph2D->SetPoint(i,x,y,tempValue);
277 0 : i++;
278 0 : }
279 0 : } else if (type==2) { // in case of IFC also usage of TS values
280 0 : if (entry->GetType()==2 || entry->GetType()==5) {
281 0 : graph2D->SetPoint(i,z,phi,tempValue);
282 0 : i++;
283 0 : }
284 0 : } else if (type==1){
285 0 : if (entry->GetType()==type) {
286 0 : graph2D->SetPoint(i,z,phi,tempValue);
287 0 : i++;
288 0 : }
289 : }
290 : }
291 :
292 0 : if (type==0 || type==3) {
293 0 : graph2D->GetXaxis()->SetTitle("X[cm]");
294 0 : graph2D->GetYaxis()->SetTitle("Y[cm]");
295 0 : if (type==0 && side==0) {
296 0 : graph2D->SetTitle("ROC A side");
297 0 : } else if (type==0 && side==1) {
298 0 : graph2D->SetTitle("ROC C side");
299 0 : } else if (type==3 && side==0) {
300 0 : graph2D->SetTitle("TPC A side (Inside the TPC)");
301 0 : } else if (type==3 && side==1) {
302 0 : graph2D->SetTitle("TPC C side (Inside the TPC)");
303 0 : }
304 0 : } else if (type==1 || type==2) {
305 0 : graph2D->GetXaxis()->SetTitle("Z[cm]");
306 0 : graph2D->GetYaxis()->SetTitle("Phi[RAD]");
307 0 : if (type==1) {
308 0 : graph2D->SetTitle("Outer Containment Vessel");
309 0 : } else if (type==2) {
310 0 : graph2D->SetTitle("Inner Containment Vessel");
311 0 : }
312 : }
313 :
314 0 : if (!graph2D->GetN()) {
315 0 : printf("Returned TGraph2D is empty: check type and side values\n");
316 0 : }
317 :
318 0 : graph2D->GetXaxis()->SetLabelOffset(0.0);
319 0 : graph2D->GetYaxis()->SetLabelOffset(0.005);
320 0 : graph2D->GetZaxis()->SetLabelOffset(-0.04);
321 :
322 :
323 0 : return graph2D; // returns TGgraph2D object
324 :
325 0 : }
326 :
327 :
328 : //_____________________________________________________________________________
329 :
330 : TGraph *AliTPCTempMap::MakeGraphGradient(Int_t axis, Int_t side, Int_t nPoints)
331 : {
332 : /// Make graph from start time to end time of TempGradient in axis direction
333 : /// axis: 0 ... horizontal Temperature Gradient (X)
334 : /// 1 ... vertical Temperature Gradient (Y)
335 : /// 2 ... longitudenal Temperature Gradient (Z) (side is ignored)
336 : /// z gradient value based on OFC temperature sensors
337 : /// Caution!: better z gradient values through difference between
338 : /// param[0] A- and param[0] C-side !
339 : /// side for X and Y gradient:
340 : /// 0 ... Shaft Side (A)
341 : /// 1 ... Muon Side (C)
342 :
343 0 : TVectorD param(3);
344 0 : TLinearFitter *fitter = new TLinearFitter(3);
345 :
346 0 : UInt_t fStartTime = fTempArray->AliTPCSensorTempArray::GetStartTime();
347 0 : UInt_t fEndTime = fTempArray->AliTPCSensorTempArray::GetEndTime();
348 :
349 0 : UInt_t stepTime = (fEndTime-fStartTime)/nPoints;
350 :
351 0 : Double_t *x = new Double_t[nPoints];
352 0 : Double_t *y = new Double_t[nPoints];
353 0 : for (Int_t ip=0; ip<nPoints; ip++) {
354 0 : x[ip] = fStartTime+ip*stepTime;
355 0 : if (axis==2) {// Gradient in Z direction (based on OFC tempSensors)
356 0 : fitter = GetLinearFitter(1, side, ip*stepTime);
357 0 : } else {// Gradient in X or Y direction (based on TPC tempSensors)
358 0 : fitter = GetLinearFitter(3, side, ip*stepTime);
359 : }
360 0 : fitter->GetParameters(param);
361 : // multiplied by 500 since TempGradient is in [K/cm]
362 : // (TPC diameter and length ~500cm)
363 0 : if (axis==1) { // Y axis
364 0 : y[ip] = param[2]*500;
365 0 : } else { // X axis
366 0 : y[ip] = param[1]*500;
367 : }
368 : }
369 :
370 0 : TGraph *graph = new TGraph(nPoints,x,y);
371 :
372 0 : fitter->~TLinearFitter();
373 0 : delete [] x;
374 0 : delete [] y;
375 :
376 0 : graph->GetXaxis()->SetTimeDisplay(1);
377 0 : graph->GetXaxis()->SetLabelOffset(0.02);
378 0 : graph->GetXaxis()->SetTimeFormat("#splitline{%d/%m}{%H:%M}");
379 :
380 : return graph;
381 0 : }
382 :
383 :
384 : //_____________________________________________________________________________
385 : Double_t AliTPCTempMap::GetTemperature(Double_t x, Double_t y, Double_t z, TTimeStamp &stamp)
386 : {
387 : /// absolute time stamp used
388 : /// see also Double_t AliTPCTempMap::GetTemperature(Double_t x, Double_t y, Double_t z, UInt_t timeSec) for details
389 :
390 0 : Int_t timeSec = stamp.GetSec()-fTempArray->GetStartTime().GetSec();
391 0 : return GetTemperature(x, y, z, timeSec);
392 : }
393 :
394 : //_____________________________________________________________________________
395 :
396 : Double_t AliTPCTempMap::GetTemperature(Double_t x, Double_t y, Double_t z, UInt_t timeSec)
397 : {
398 : /// Returns estimated Temperature at given position (x,y,z[cm]) at given time
399 : /// (timeSec) after starttime
400 : /// Method: so far just a linear interpolation between Linar fits of
401 : /// the TPC temperature sensors
402 : /// FIXME: 'Educated Fit' through FiniteElement Simulation results!
403 : /// FIXXME: Return 0? if x,y,z out of range
404 :
405 0 : TVectorD paramA(3), paramC(3);
406 : TLinearFitter *fitterA = 0;
407 : TLinearFitter *fitterC = 0;
408 :
409 0 : fitterA = GetLinearFitter(3, 0, timeSec);
410 0 : fitterA->GetParameters(paramA);
411 0 : fitterC = GetLinearFitter(3, 1, timeSec);
412 0 : fitterC->GetParameters(paramC);
413 :
414 0 : Double_t fvalA = paramA[0]+paramA[1]*x+paramA[2]*y;
415 0 : Double_t fvalC = paramC[0]+paramC[1]*x+paramC[2]*y;
416 :
417 0 : Double_t k = (fvalA-fvalC)/(2*247);
418 0 : Double_t tempValue = fvalC+(fvalA-fvalC)/2+k*z;
419 :
420 0 : delete fitterA;
421 0 : delete fitterC;
422 :
423 : return tempValue;
424 :
425 0 : }
426 :
427 :
428 : Bool_t AliTPCTempMap::IsOK(Float_t value){
429 : /// checks if value is within a certain range
430 :
431 : const Float_t kMinT=15;
432 : const Float_t kMaxT=25;
433 0 : return (value>kMinT && value<kMaxT);
434 : }
|