]>
Commit | Line | Data |
---|---|---|
fb3d369e | 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 to calculate TRD dEdx | |
18 | // xx | |
19 | // xx | |
20 | // xx | |
21 | // xx | |
22 | // | |
23 | // Xianguo Lu | |
24 | // lu@physi.uni-heidelberg.de | |
25 | // Xianguo.Lu@cern.ch | |
26 | // | |
27 | // | |
28 | ||
29 | ||
30 | #include "TF1.h" | |
31 | #include "TFile.h" | |
32 | #include "TH1D.h" | |
33 | #include "TH2D.h" | |
d1d15abc | 34 | #include "THn.h" |
fb3d369e | 35 | #include "THnSparse.h" |
36 | #include "TMath.h" | |
37 | #include "TMatrixD.h" | |
38 | #include "TMinuit.h" | |
39 | #include "TObjArray.h" | |
40 | #include "TRandom3.h" | |
41 | #include "TStopwatch.h" | |
42 | #include "TVectorD.h" | |
43 | ||
44 | #include "TTreeStream.h" | |
45 | ||
46 | #include "AliCDBId.h" | |
47 | #include "AliCDBMetaData.h" | |
48 | #include "AliCDBStorage.h" | |
49 | #include "AliESDEvent.h" | |
50 | #include "AliESDfriendTrack.h" | |
51 | #include "AliESDtrack.h" | |
d0037ea4 | 52 | #include "AliTRDcalibDB.h" |
53 | #include "AliTRDCalROC.h" | |
fb3d369e | 54 | #include "AliTRDtrackV1.h" |
55 | ||
d0037ea4 | 56 | |
fb3d369e | 57 | #include "AliTRDdEdxUtils.h" |
58 | ||
59 | #define EPSILON 1e-12 | |
60 | ||
d1d15abc | 61 | THnF * AliTRDdEdxUtils::fgHistGain=0x0; |
62 | THnF * AliTRDdEdxUtils::fgHistT0=0x0; | |
63 | THnF * AliTRDdEdxUtils::fgHistVd=0x0; | |
fb3d369e | 64 | TObjArray * AliTRDdEdxUtils::fgHistPHQ=new TObjArray(8); |
65 | ||
66 | TString AliTRDdEdxUtils::fgCalibFile; | |
67 | TObjArray * AliTRDdEdxUtils::fgObjGain = 0x0; | |
68 | TObjArray * AliTRDdEdxUtils::fgObjT0 = 0x0; | |
69 | TObjArray * AliTRDdEdxUtils::fgObjVd = 0x0; | |
70 | TObjArray * AliTRDdEdxUtils::fgObjPHQ = 0x0; | |
71 | ||
72 | Int_t AliTRDdEdxUtils::fgNchamber = -999; | |
73 | Double_t AliTRDdEdxUtils::fgChamberQ[6]; | |
74 | Double_t AliTRDdEdxUtils::fgChamberTmean[6]; | |
75 | ||
76 | Double_t AliTRDdEdxUtils::fgTrackTmean = -999; | |
77 | ||
d0037ea4 | 78 | Bool_t AliTRDdEdxUtils::fgPadGainOn = kTRUE; |
9a8b0e85 | 79 | Bool_t AliTRDdEdxUtils::fgExBOn = kTRUE; |
d0037ea4 | 80 | Double_t AliTRDdEdxUtils::fgQScale = 45; |
9a8b0e85 | 81 | Double_t AliTRDdEdxUtils::fgQ0Frac = 0.3; |
82 | Double_t AliTRDdEdxUtils::fgQ1Frac = 0.5; | |
83 | Double_t AliTRDdEdxUtils::fgTimeBinCountCut = 0.0; | |
84 | Int_t AliTRDdEdxUtils::fgCalibTPCnclsCut = 70; | |
85 | ||
fb3d369e | 86 | //=================================================================================== |
87 | // Math and Histogram | |
88 | //=================================================================================== | |
89 | void AliTRDdEdxUtils::GetCDFCuts(const TH1D *hh, const Int_t ncut, Double_t cuts[], const Double_t cdfs[], const Double_t thres) | |
90 | { | |
91 | // | |
92 | //counts of hh is sorted | |
93 | // | |
94 | ||
95 | for(Int_t ii=0; ii<ncut; ii++){ | |
96 | cuts[ii] = -999; | |
97 | } | |
98 | ||
99 | Int_t nsel = 0; | |
100 | const Int_t nbin = hh->GetNbinsX(); | |
101 | Double_t datas[nbin]; | |
102 | for(Int_t ii=1; ii<=nbin; ii++){ | |
103 | const Double_t res = hh->GetBinContent(ii); | |
104 | if(res<thres){ | |
105 | continue; | |
106 | } | |
107 | ||
108 | datas[nsel] = res; | |
109 | nsel++; | |
110 | } | |
111 | if(!nsel) | |
112 | return; | |
113 | ||
114 | Int_t id[nsel]; | |
115 | TMath::Sort(nsel, datas, id, kFALSE); | |
116 | ||
117 | for(Int_t ii=0; ii<ncut; ii++){ | |
118 | const Double_t icdf = cdfs[ii]; | |
119 | if(icdf<0 || icdf>1){ | |
120 | printf("AliTRDdEdxUtils::GetCDFCuts error cdfs[%d] %15f out of range!\n", ii, icdf); exit(1); | |
121 | } | |
122 | cuts[ii] = datas[id[Int_t(icdf*nsel)]]; | |
123 | } | |
124 | } | |
125 | ||
126 | Double_t AliTRDdEdxUtils::GetMeanRMS(const Double_t nn, const Double_t sum, const Double_t w2s, Double_t * grms, Double_t * gerr) | |
127 | { | |
128 | // | |
129 | //calculate mean (with error) and rms from sum, w2s, nn | |
130 | //if nn=0, mean, error, and rms all = 0 | |
131 | // | |
132 | ||
133 | Double_t tmean = 0, trms = 0, terr = 0; | |
134 | ||
135 | if(nn>EPSILON){ | |
136 | tmean = sum/nn; | |
137 | ||
138 | const Double_t arg = w2s/nn-tmean*tmean; | |
139 | if(TMath::Abs(arg)<EPSILON){ | |
140 | trms = 0; | |
141 | } | |
142 | else{ | |
143 | if( arg <0 ){ | |
144 | printf("AliTRDdEdxUtils::GetMeanRMS error negative sqrt argument!! %e -- %e %e %f\n", arg, w2s, sum, nn); exit(1); | |
145 | } | |
146 | ||
147 | trms = TMath::Sqrt(arg); | |
148 | } | |
149 | ||
150 | terr = trms/TMath::Sqrt(nn); | |
151 | } | |
152 | ||
153 | if(grms){ | |
154 | (*grms) = trms; | |
155 | } | |
156 | ||
157 | if(gerr){ | |
158 | (*gerr) = terr; | |
159 | } | |
160 | ||
161 | return tmean; | |
162 | } | |
163 | ||
164 | Double_t AliTRDdEdxUtils::TruncatedMean(const Int_t nx, const Double_t xdata[], const Double_t lowfrac, const Double_t highfrac, Double_t * grms, Double_t * gerr, Double_t *wws) | |
165 | { | |
166 | // | |
167 | //calculate truncated mean | |
168 | //return <x*w>_{low-high according to x} | |
169 | // | |
170 | ||
171 | /* | |
172 | //test-> | |
173 | for(Int_t ii=0; ii<nx; ii++){ | |
174 | printf("test %d/%d %f\n", ii, nx, xdata[ii]); | |
175 | } | |
176 | //<--test | |
177 | */ | |
178 | ||
179 | Int_t index[nx]; | |
180 | TMath::Sort(nx, xdata, index, kFALSE); | |
181 | ||
182 | Int_t nused = 0; | |
183 | Double_t sum = 0; | |
184 | Double_t w2s = 0; | |
185 | const Int_t istart = Int_t (nx*lowfrac); | |
186 | const Int_t istop = Int_t (nx*highfrac); | |
187 | ||
188 | //=,< correct, because when low=0, high=1 it is correct | |
189 | for(Int_t ii=istart; ii<istop; ii++){ | |
190 | Double_t weight = 1; | |
191 | if(wws){ | |
192 | weight = wws[index[ii]]; | |
193 | } | |
194 | const Double_t sx = xdata[index[ii]]*weight; | |
195 | ||
196 | sum += sx; | |
197 | w2s += sx*sx; | |
198 | ||
199 | nused++; | |
200 | //printf("test in loop %d/%d %f %f %f\n", ii, nused, sx, sum, w2s); | |
201 | ||
202 | } | |
203 | ||
204 | return GetMeanRMS(nused, sum, w2s, grms, gerr); | |
205 | } | |
206 | ||
207 | Double_t AliTRDdEdxUtils::TruncatedMean(const TH1 *hh, const Double_t lowfrac, const Double_t highfrac, Double_t * grms, Double_t * gerr) | |
208 | { | |
209 | // | |
210 | //do truncation on histogram | |
211 | // | |
212 | //if hh is scaled, be sure Sumw2 is called before scaling!! then mean, rms and err will all be correct | |
213 | ||
214 | //with under-/over-flow | |
215 | Double_t npreTrunc = 0; | |
216 | for(Int_t itmp=0; itmp<=hh->GetNbinsX()+1; itmp++){ | |
217 | const Double_t be = hh->GetBinError(itmp); | |
218 | const Double_t bc = hh->GetBinContent(itmp); | |
219 | if(be<EPSILON){ | |
220 | if(bc>EPSILON){ | |
221 | printf("AliTRDdEdxUtils::TruncatedMean (hist) error %e %e %d\n", bc, be, itmp); exit(1); | |
222 | } | |
223 | continue; | |
224 | } | |
225 | npreTrunc += bc*bc/be/be; | |
226 | } | |
227 | ||
228 | const Double_t nstart = npreTrunc*lowfrac; | |
229 | const Double_t nstop = npreTrunc*highfrac; | |
230 | ||
231 | //with Double_t this should also handle normalized hist | |
232 | Double_t ntot = 0; | |
233 | Double_t nused = 0; | |
234 | Double_t sum = 0; | |
235 | Double_t w2s = 0; | |
236 | for(Int_t itmp=0; itmp<=hh->GetNbinsX()+1; itmp++){ | |
237 | const Double_t be = hh->GetBinError(itmp); | |
238 | const Double_t bc = hh->GetBinContent(itmp); | |
239 | if(be<EPSILON){ | |
240 | if(bc>EPSILON){ | |
241 | printf("AliTRDdEdxUtils::TruncatedMean (hist) error %e %e %d\n", bc, be, itmp); exit(1); | |
242 | } | |
243 | continue; | |
244 | } | |
245 | const Double_t weight = bc*bc/be/be; | |
246 | ntot+=weight; | |
247 | //<= correct, because when high=1, nstop has to be included | |
248 | if(ntot>nstart && ntot<=nstop){ | |
249 | ||
250 | const Double_t val = hh->GetBinCenter(itmp); | |
251 | sum += weight*val; | |
252 | w2s += weight*val*val; | |
253 | ||
254 | nused += weight; | |
255 | ||
256 | //printf("test %d %f %f --- %f %f -- %f %f\n", itmp, weight, val, sum, w2s, nused, nsample); | |
257 | } | |
258 | else if(ntot>nstop){ | |
259 | if(itmp>=hh->GetNbinsX()){ | |
260 | printf("AliTRDdEdxUtils::TruncatedMean warning hist range too small %s %f %f %d %d, %15f %15f %15f; nused w2s sum set to 0\n", hh->GetName(), hh->GetBinLowEdge(1), hh->GetBinLowEdge(itmp), itmp, hh->GetNbinsX(), hh->GetBinContent(hh->GetNbinsX())/hh->Integral(0,hh->GetNbinsX()+1), hh->GetBinContent(hh->GetNbinsX()), hh->Integral(0,hh->GetNbinsX()+1)); //exit(1); | |
261 | nused = 0; | |
262 | w2s = sum = 0; | |
263 | } | |
264 | break; | |
265 | } | |
266 | } | |
267 | ||
268 | return GetMeanRMS(nused, sum, w2s, grms, gerr); | |
269 | } | |
270 | ||
271 | void AliTRDdEdxUtils::FitSlicesY(const TH2D *hh, TH1D *&hnor, TH1D *&hmpv, TH1D *&hwid, TH1D *&hres, const Double_t thres, const Double_t lowfrac, const Double_t highfrac) | |
272 | { | |
273 | // | |
274 | //fit slices of hh using truncation | |
275 | // | |
276 | ||
277 | const Int_t x0 = hh->GetXaxis()->GetFirst(); | |
278 | const Int_t x1 = hh->GetXaxis()->GetLast(); | |
279 | const Int_t y0 = hh->GetYaxis()->GetFirst(); | |
280 | const Int_t y1 = hh->GetYaxis()->GetLast(); | |
281 | ||
282 | const Int_t nx = hh->GetNbinsX(); | |
283 | const Int_t ny = hh->GetNbinsY(); | |
284 | const Double_t xmin = hh->GetXaxis()->GetXmin(); | |
285 | const Double_t xmax = hh->GetXaxis()->GetXmax(); | |
286 | const Double_t ymin = hh->GetYaxis()->GetXmin(); | |
287 | const Double_t ymax = hh->GetYaxis()->GetXmax(); | |
288 | ||
289 | hnor = new TH1D(Form("%s_amp",hh->GetName()), "", nx, xmin, xmax); | |
290 | hmpv = new TH1D(Form("%s_mpv",hh->GetName()), "", nx, xmin, xmax); | |
291 | hwid = new TH1D(Form("%s_wid",hh->GetName()), "", nx, xmin, xmax); | |
292 | hres = new TH1D(Form("%s_res",hh->GetName()), "", nx, xmin, xmax); | |
293 | ||
294 | for(Int_t ix=x0; ix<=x1; ix++){ | |
295 | //to speed up | |
296 | const Double_t rawcount = hh->Integral(ix,ix,0, ny+1); | |
297 | if(rawcount<EPSILON){ | |
298 | continue; | |
299 | } | |
300 | ||
301 | TH1D *htmp = new TH1D(Form("FitSlicesY_%s_%d", hh->GetName(), ix),"",ny, ymin, ymax); | |
302 | Double_t ntot = 0; | |
303 | for(Int_t iy=y0; iy<=y1; iy++){ | |
304 | const Double_t be = hh->GetBinError(ix,iy); | |
305 | const Double_t bc = hh->GetBinContent(ix, iy); | |
306 | ||
307 | if(be<EPSILON){ | |
308 | if(bc>EPSILON){ | |
309 | printf("AliTRDdEdxUtils::FitSlicesY error %d %d %e %e\n", ix, iy, be, bc); exit(1); | |
310 | } | |
311 | continue; | |
312 | } | |
313 | ||
314 | htmp->SetBinContent(iy, bc); | |
315 | htmp->SetBinError(iy, be); | |
316 | ||
317 | ntot += (bc/be)*(bc/be); | |
318 | ||
319 | //if(be) printf("test %d %d : %f %f %f\n", ix, iy, bc, be, pow(bc/be,2)); | |
320 | } | |
321 | ||
322 | hnor->SetBinContent(ix, ntot); | |
323 | hnor->SetBinError( ix, 0); | |
324 | ||
325 | if(ntot<thres || htmp->GetRMS()<EPSILON){ | |
326 | delete htmp; | |
327 | continue; | |
328 | } | |
329 | ||
330 | //test htmp->Draw(); | |
331 | Double_t trms = -999, terr = -999; | |
332 | const Double_t tmean = TruncatedMean(htmp, lowfrac, highfrac, &trms, &terr); | |
333 | ||
334 | hmpv->SetBinContent(ix, tmean); | |
335 | hmpv->SetBinError( ix, terr); | |
336 | ||
337 | hwid->SetBinContent(ix, trms); | |
338 | hwid->SetBinError( ix, 0); | |
339 | ||
340 | hres->SetBinContent(ix, tmean>EPSILON ? trms/tmean:0); | |
341 | hres->SetBinError( ix, 0); | |
342 | ||
343 | delete htmp; | |
344 | } | |
345 | ||
346 | TH1 *hhs[]={hnor, hmpv, hwid, hres}; | |
347 | const TString yt[]={"N", "MPV", "#sigma", "#sigma/MPV"}; | |
348 | const Int_t nh = sizeof(hhs)/sizeof(TH1*); | |
349 | for(Int_t ii=0; ii<nh; ii++){ | |
350 | hhs[ii]->SetYTitle(Form("%s of %s", yt[ii].Data(), hh->GetYaxis()->GetTitle())); | |
351 | hhs[ii]->SetXTitle(hh->GetXaxis()->GetTitle()); | |
352 | hhs[ii]->GetYaxis()->SetTitleOffset(hh->GetYaxis()->GetTitleOffset()); | |
353 | hhs[ii]->SetTitle(hh->GetTitle()); | |
354 | } | |
355 | } | |
356 | ||
357 | //=================================================================================== | |
358 | // TRD Analysis Fast Tool | |
359 | //=================================================================================== | |
360 | ||
361 | Int_t AliTRDdEdxUtils::GetNtracklet(const AliESDEvent *esd) | |
362 | { | |
363 | // | |
364 | //number of trd tracklet in one esd event | |
365 | // | |
366 | const Int_t ntrk0 = esd->GetNumberOfTracks(); | |
367 | Int_t ntrdv1=0; | |
368 | for(Int_t ii=0; ii<ntrk0; ii++){ | |
369 | ntrdv1 += esd->GetTrack(ii)->GetTRDntracklets(); | |
370 | } | |
371 | return ntrdv1; | |
372 | } | |
373 | ||
374 | AliTRDtrackV1 * AliTRDdEdxUtils::GetTRDtrackV1(const AliESDtrack * esdtrack) | |
375 | { | |
376 | // | |
377 | //Get TRD friend track | |
378 | // | |
379 | ||
380 | AliESDfriendTrack * friendtrk = (AliESDfriendTrack *)esdtrack->GetFriendTrack(); | |
381 | if(!friendtrk){ | |
382 | //printf("xlulog AliAnalysisTaskCosmicTRD::GetTRDtrack no friend!!\n"); exit(1); | |
383 | return 0x0; | |
384 | } | |
385 | ||
386 | TObject *calibObject=0x0; | |
387 | AliTRDtrackV1 * trdtrack=0x0; | |
388 | for(Int_t l=0; (calibObject=friendtrk->GetCalibObject(l)); l++) { | |
389 | if( (trdtrack=dynamic_cast<AliTRDtrackV1*>(calibObject)) ) | |
390 | break; | |
391 | } | |
392 | ||
393 | return trdtrack; | |
394 | } | |
395 | ||
396 | Bool_t AliTRDdEdxUtils::IsInSameStack(const AliTRDtrackV1 *trdtrack) | |
397 | { | |
398 | // | |
399 | // to check if all tracklets are in the same stack, useful in cosmic | |
400 | // | |
401 | ||
402 | TVectorD secs(18), stks(5); | |
403 | ||
404 | for(Int_t ilayer = 0; ilayer < 6; ilayer++){ | |
405 | AliTRDseedV1 *tracklet=trdtrack->GetTracklet(ilayer); | |
406 | if(!tracklet) | |
407 | continue; | |
408 | ||
409 | const Int_t det = tracklet->GetDetector(); | |
410 | const Int_t isector = AliTRDgeometry::GetSector(det); | |
411 | const Int_t istack = AliTRDgeometry::GetStack(det); | |
412 | ||
413 | secs[isector] = 1; | |
414 | stks[istack] = 1; | |
415 | } | |
416 | ||
417 | if(secs.Sum()!=1 || stks.Sum()!=1){ | |
418 | return kFALSE; | |
419 | } | |
420 | else | |
421 | return kTRUE; | |
422 | } | |
423 | ||
424 | Bool_t AliTRDdEdxUtils::GetFirstSectorStackMomentum(const AliTRDtrackV1 *trdtrack, Int_t & isec, Int_t & istk, Double_t & mom) | |
425 | { | |
426 | // | |
427 | //as function name | |
428 | // | |
429 | isec = istk = -999; | |
430 | mom = -999; | |
431 | ||
432 | for(Int_t ilayer = 0; ilayer < 6; ilayer++){ | |
433 | AliTRDseedV1 *tracklet=trdtrack->GetTracklet(ilayer); | |
434 | if(!tracklet) | |
435 | continue; | |
436 | ||
437 | const Int_t det = tracklet->GetDetector(); | |
438 | isec = AliTRDgeometry::GetSector(det); | |
439 | istk = AliTRDgeometry::GetStack(det); | |
440 | ||
441 | mom = tracklet->GetMomentum(); | |
442 | ||
443 | break; | |
444 | } | |
445 | ||
446 | if(isec<0) | |
447 | return kFALSE; | |
448 | else | |
449 | return kTRUE; | |
450 | } | |
451 | ||
452 | //=================================================================================== | |
453 | // Calibration | |
454 | //=================================================================================== | |
455 | Double_t AliTRDdEdxUtils::GetCalibTPCscale(const Int_t tpcncls, const Double_t tpcsig) | |
456 | { | |
457 | // | |
458 | //the scale used in calibration | |
459 | // | |
460 | ||
461 | if(tpcncls < CalibTPCnclsCut()) | |
462 | return -999; | |
463 | ||
464 | if(tpcsig<EPSILON) | |
465 | return -999; | |
466 | ||
467 | return tpcsig/120; | |
468 | ||
469 | } | |
470 | ||
471 | Int_t AliTRDdEdxUtils::GetPHQIterator(const Bool_t kinvq, const Double_t mag, const Int_t charge) | |
472 | { | |
473 | // | |
474 | //iterator for calib obj and hist | |
475 | // | |
476 | return kinvq*4 + (mag>0)*2 + (charge>0); | |
477 | } | |
478 | ||
26733ed4 | 479 | TObjArray * AliTRDdEdxUtils::GetObjPHQ() |
480 | { | |
481 | // | |
482 | //return fgObjPHQ, initialized if null | |
483 | // | |
484 | ||
485 | if(!fgObjPHQ){ | |
486 | fgObjPHQ = new TObjArray(8); | |
487 | } | |
488 | ||
489 | return fgObjPHQ; | |
490 | } | |
491 | ||
fb3d369e | 492 | TObjArray * AliTRDdEdxUtils::GetObjPHQ(const Bool_t kinvq, const Double_t mag, const Int_t charge) |
493 | { | |
494 | // | |
495 | //return calib obj | |
496 | // | |
497 | if(!fgObjPHQ){ | |
26733ed4 | 498 | printf("AliTRDdEdxUtils::GetObjPHQ(kinvq, mag, charge) error fgObjPHQ null!!\n"); exit(1); |
fb3d369e | 499 | } |
500 | ||
501 | return (TObjArray*) fgObjPHQ->At(GetPHQIterator(kinvq, mag, charge)); | |
502 | } | |
503 | ||
d1d15abc | 504 | THnF * AliTRDdEdxUtils::GetHistPHQ(const Bool_t kinvq, const Double_t mag, const Int_t charge) |
fb3d369e | 505 | { |
506 | // | |
507 | //return calib hist | |
508 | // | |
d1d15abc | 509 | return (THnF*) fgHistPHQ->At(GetPHQIterator(kinvq, mag, charge)); |
fb3d369e | 510 | } |
511 | ||
512 | TString AliTRDdEdxUtils::GetPHQName(const Bool_t kobj, const Int_t iter) | |
513 | { | |
514 | // | |
515 | //get name of calib obj/hist of PHQ | |
516 | // | |
517 | return Form("TRDCalib%sPHQ%d", kobj?"Obj":"Hist", iter); | |
518 | } | |
519 | ||
520 | void AliTRDdEdxUtils::DeleteCalibObj() | |
521 | { | |
522 | // | |
523 | //delete calib obj | |
524 | // | |
525 | delete fgObjGain; | |
526 | delete fgObjT0; | |
527 | delete fgObjVd; | |
528 | ||
529 | fgObjGain = 0x0; | |
530 | fgObjT0 = 0x0; | |
531 | fgObjVd = 0x0; | |
532 | ||
533 | if(fgObjPHQ){ | |
534 | fgObjPHQ->SetOwner(); | |
535 | delete fgObjPHQ; | |
536 | fgObjPHQ = 0x0; | |
537 | } | |
538 | } | |
539 | ||
540 | Bool_t AliTRDdEdxUtils::GenerateDefaultPHQOCDB(const TString path) | |
541 | { | |
542 | // | |
543 | //generate default OCDB object PHQ, do like | |
544 | //AliTRDdEdxUtils::GenerateDefaultPHQOCDB("local://./") | |
545 | // | |
546 | ||
547 | TObjArray * arr8 = new TObjArray(8); | |
548 | arr8->SetOwner(); | |
549 | ||
550 | for(Int_t ii=0; ii<8; ii++){ | |
551 | TObjArray * arr1 = new TObjArray(1); | |
552 | arr1->SetOwner(); | |
553 | arr1->SetName(GetPHQName(1, ii)); | |
554 | ||
555 | const Int_t nbins = NTRDtimebin(); | |
556 | TVectorD * vec = new TVectorD(nbins); | |
557 | for(Int_t jj=0; jj<nbins; jj++){ | |
558 | (*vec)[jj] = 1; | |
559 | } | |
560 | arr1->Add(vec); | |
561 | arr8->Add(arr1); | |
562 | } | |
563 | ||
564 | AliCDBMetaData *metaData= new AliCDBMetaData(); | |
565 | metaData->SetObjectClassName("TObjArray"); | |
566 | metaData->SetResponsible("Raphaelle Bailhache and Xianguo Lu"); | |
567 | ||
568 | AliCDBId id1("TRD/Calib/PHQ", 0, 999999999); | |
569 | AliCDBStorage * gStorage = AliCDBManager::Instance()->GetStorage(path); | |
570 | gStorage->Put(arr8, id1, metaData); | |
571 | ||
572 | delete metaData; | |
573 | delete arr8; | |
574 | ||
575 | return kTRUE; | |
576 | } | |
577 | ||
578 | void AliTRDdEdxUtils::IniCalibObj() | |
579 | { | |
580 | // | |
581 | //set CalibObj from file, clone to static calib obj | |
582 | // | |
583 | ||
584 | DeleteCalibObj(); | |
585 | ||
586 | TFile *cfile=new TFile(fgCalibFile); | |
587 | if(!cfile->IsOpen()){ | |
588 | printf("AliTRDdEdxUtils::IniCalibObj error fgCalibFile not open! %s\n", fgCalibFile.Data());exit(1); | |
589 | } | |
590 | ||
591 | printf("\nAliTRDdEdxUtils::IniCalibObj file: %s\n", fgCalibFile.Data()); | |
592 | ||
593 | //--- | |
594 | const TString objnames[] ={"TRDCalibObjGain", "TRDCalibObjT0", "TRDCalibObjVd"}; | |
595 | TObjArray ** gobjs[]={ &fgObjGain, &fgObjT0, &fgObjVd}; | |
596 | ||
597 | const Int_t nobj = sizeof(objnames)/sizeof(TString); | |
598 | for(Int_t iobj=0; iobj<nobj; iobj++){ | |
599 | TObjArray *tmpo=0x0; | |
600 | cfile->GetObject(objnames[iobj], tmpo); | |
601 | if(!tmpo){ | |
602 | printf("AliTRDdEdxUtils::IniCalibObj error obj %s not found!\n", objnames[iobj].Data()); exit(1); | |
603 | } | |
604 | ||
605 | (*gobjs[iobj])=(TObjArray*)tmpo->Clone(); | |
606 | (*gobjs[iobj])->SetOwner(); | |
607 | } | |
608 | ||
609 | fgObjPHQ = new TObjArray(8); | |
610 | for(Int_t iter=0; iter<8; iter++){ | |
611 | const TString objn = GetPHQName(1, iter); | |
612 | TObjArray *tmpo=0x0; | |
613 | cfile->GetObject(objn, tmpo); | |
614 | if(!tmpo){ | |
615 | printf("AliTRDdEdxUtils::IniCalibObj error obj %s not found!\n", objn.Data()); exit(1); | |
616 | } | |
617 | ||
618 | TObjArray *obji=(TObjArray*) tmpo->Clone(); | |
619 | obji->SetOwner(); | |
620 | fgObjPHQ->AddAt(obji, iter); | |
621 | } | |
622 | ||
623 | //--- | |
624 | ||
625 | cfile->Close(); | |
626 | delete cfile; | |
627 | } | |
628 | ||
629 | void AliTRDdEdxUtils::DeleteCalibHist() | |
630 | { | |
631 | // | |
632 | //delete calib hist | |
633 | // | |
634 | delete fgHistGain; | |
635 | delete fgHistT0; | |
636 | delete fgHistVd; | |
637 | ||
638 | fgHistGain = 0x0; | |
639 | fgHistT0 = 0x0; | |
640 | fgHistVd = 0x0; | |
641 | ||
642 | //fgHistPHQ owns the hists | |
643 | fgHistPHQ->SetOwner(); | |
644 | fgHistPHQ->Clear(); | |
645 | } | |
646 | ||
647 | void AliTRDdEdxUtils::IniCalibHist(TList *list, const Bool_t kPHQonly) | |
648 | { | |
649 | // | |
650 | //initialize calib hist, list should not own the hist, or list->Clear/delete hist should not be called | |
651 | // | |
652 | ||
653 | DeleteCalibHist(); | |
654 | ||
655 | Int_t nbin[2]; | |
656 | const Double_t xmin[2]={0, 0}; | |
657 | Double_t xmax[2]; | |
658 | ||
659 | nbin[0]=NTRDtimebin(); nbin[1]= 11250; xmax[0]=nbin[0]; xmax[1]=20; | |
660 | for(Int_t iter=0; iter<8; iter++){ | |
661 | const TString hn = GetPHQName(0, iter); | |
d1d15abc | 662 | THnF *hi = new THnF(hn, "", 2, nbin, xmin, xmax); |
fb3d369e | 663 | //fgHistPHQ owns the hists |
664 | fgHistPHQ->AddAt(hi, iter); | |
665 | list->Add(hi); | |
666 | } | |
667 | ||
668 | if(kPHQonly) | |
669 | return; | |
670 | ||
d1d15abc | 671 | nbin[0]=NTRDchamber(); nbin[1]= 11250; xmax[0]=nbin[0]; xmax[1]=20; fgHistGain = new THnF("TRDCalibHistGain", "", 2, nbin, xmin, xmax); |
672 | nbin[0]=NTRDchamber(); nbin[1]= 11250; xmax[0]=nbin[0]; xmax[1]=AliTRDseedV1::kNtb; fgHistT0 = new THnF("TRDCalibHistT0", "", 2, nbin, xmin, xmax); | |
673 | nbin[0]=NTRDchamber(); nbin[1]= 11250; xmax[0]=nbin[0]; xmax[1]=AliTRDseedV1::kNtb; fgHistVd = new THnF("TRDCalibHistVd", "", 2, nbin, xmin, xmax); | |
fb3d369e | 674 | |
675 | list->Add(fgHistGain); | |
676 | list->Add(fgHistT0); | |
677 | list->Add(fgHistVd); | |
678 | } | |
679 | ||
680 | Bool_t AliTRDdEdxUtils::ReadCalibHist(const TString filename, const TString listname) | |
681 | { | |
682 | // | |
683 | //used in AliTRDPreprocessorOffline | |
684 | //read in calib hist from file, only for PHQ | |
685 | // | |
686 | DeleteCalibHist(); | |
687 | ||
688 | //maybe already open by others... don't close | |
689 | TFile fcalib(filename); | |
690 | ||
691 | TObjArray * array = (TObjArray*)fcalib.Get(listname); | |
692 | ||
693 | for(Int_t iter=0; iter<8; iter++){ | |
694 | const TString hn = GetPHQName(0, iter); | |
d1d15abc | 695 | THnF * tmph=0x0; |
fb3d369e | 696 | if(array){ |
d1d15abc | 697 | tmph = (THnF *) array->FindObject(hn); |
fb3d369e | 698 | } |
699 | else{ | |
d1d15abc | 700 | tmph = (THnF *) fcalib.Get(hn); |
fb3d369e | 701 | } |
702 | if(!tmph){ | |
703 | printf("AliTRDdEdxUtils::ReadCalibHist warning calib hist not found! %s %s\n", filename.Data(), listname.Data()); | |
704 | fcalib.ls(); | |
879b7730 | 705 | if(array){ |
706 | array->ls(); | |
707 | } | |
fb3d369e | 708 | return kFALSE; |
709 | } | |
d1d15abc | 710 | THnF *hi = (THnF*)tmph->Clone(); |
fb3d369e | 711 | fgHistPHQ->AddAt(hi, iter); |
712 | } | |
713 | ||
714 | return kTRUE; | |
715 | } | |
716 | ||
d1d15abc | 717 | void AliTRDdEdxUtils::FillCalibHist(const Int_t ncls, const TVectorD *arrayQ, const TVectorD *arrayX, THnF * hcalib, const Double_t scale) |
fb3d369e | 718 | { |
719 | // | |
720 | //fill calibration hist | |
721 | // | |
722 | if(!hcalib){printf("AliTRDdEdxUtils::FillCalibHist errro hcalib null!!\n"); exit(1);} | |
723 | ||
724 | for(Int_t ii=0; ii<ncls; ii++){ | |
725 | const Double_t dq = (*arrayQ)[ii]; | |
726 | const Double_t xx = (*arrayX)[ii]; | |
727 | ||
728 | const Double_t qmax = hcalib->GetAxis(1)->GetXmax() -0.5 * hcalib->GetAxis(1)->GetBinWidth(1); | |
729 | const Double_t xmin = hcalib->GetAxis(0)->GetXmin(); | |
730 | const Double_t xmax = hcalib->GetAxis(0)->GetXmax(); | |
731 | ||
732 | if(xx>=xmax || xx<xmin){ | |
733 | printf("AliTRDdEdxUtils::FillCalibHist error x overflow or underflow! %s %15f %15f %15f\n", hcalib->GetName(), xx, xmin, xmax); exit(1); | |
734 | } | |
735 | ||
736 | const Double_t var[]={xx, TMath::Min(dq, qmax)/scale}; | |
737 | hcalib->Fill(var); | |
738 | } | |
739 | } | |
740 | ||
741 | void AliTRDdEdxUtils::FillCalibHist(const AliTRDtrackV1 *trdv1, const Bool_t kinvq, const Double_t mag, const Int_t charge, const Double_t scale) | |
742 | { | |
743 | // | |
744 | //get cluster Q and fill calib hist, if kinvq = kTRUE, 1/Q is filled | |
745 | // | |
746 | ||
d1d15abc | 747 | THnF * hcalib = AliTRDdEdxUtils::GetHistPHQ(kinvq, mag, charge); |
fb3d369e | 748 | |
749 | TVectorD arrayQ(200), arrayX(200); | |
750 | const Int_t ncls = AliTRDdEdxUtils::GetArrayClusterQ(kinvq, &arrayQ, &arrayX, trdv1); | |
751 | FillCalibHist(ncls, &arrayQ, &arrayX, hcalib, kinvq ? 1/scale : scale); | |
752 | ||
753 | static Int_t kprint = 100; | |
754 | if(kprint<0){ | |
755 | printf("\nAliTRDdEdxUtils::FillCalibHist summary: \n"); | |
756 | printf("\nkinvq= %d;\n", kinvq); | |
757 | for(Int_t iq=0; iq<ncls; iq++){ | |
758 | printf("arrayX[%3d] = %15.0f; arrayQ[%3d] = %15f;\n", iq, arrayX[iq], iq, arrayQ[iq]); | |
759 | } | |
760 | printf("\n"); | |
761 | } | |
762 | kprint++; | |
763 | } | |
764 | ||
765 | Int_t AliTRDdEdxUtils::ApplyCalib(const Int_t nc0, TVectorD *arrayQ, TVectorD *arrayX, const TObjArray *cobj) | |
766 | { | |
767 | // | |
768 | //apply calibration on arrayQ | |
769 | // | |
770 | if(!cobj){ printf("AliTRDdEdxUtils::ApplyCalib error gain array null!!\n"); exit(1);} | |
771 | ||
772 | TVectorD tmpq(arrayQ->GetNrows()); | |
773 | TVectorD tmpx(arrayX->GetNrows()); | |
774 | Int_t ncls = 0; | |
775 | ||
776 | const TVectorD * gain = (TVectorD*) cobj->At(0); | |
777 | for(Int_t ii=0; ii<nc0; ii++){ | |
778 | const Double_t dq = (*arrayQ)[ii]; | |
779 | const Int_t xx = (Int_t)(*arrayX)[ii]; | |
780 | const Double_t gg = (*gain)[xx]; | |
781 | ||
782 | if(gg<EPSILON){ | |
783 | continue; | |
784 | } | |
785 | ||
786 | tmpq[ncls] = dq*gg; | |
787 | tmpx[ncls] = xx; | |
788 | ncls++; | |
789 | } | |
790 | ||
791 | (*arrayQ)=tmpq; | |
792 | (*arrayX)=tmpx; | |
793 | ||
794 | return ncls; | |
795 | } | |
796 | ||
797 | void AliTRDdEdxUtils::GetPHCountMeanRMS(const TH1D *hnor, TH1D *&hmean) | |
798 | { | |
799 | // | |
800 | //calculate from the ph calib hist the (mean-3sigma) ph-count in the chamber, save in the TH1D output | |
801 | // | |
802 | const Int_t ndet = 540; | |
803 | TObjArray *obj=new TObjArray(ndet); | |
804 | obj->SetOwner(); | |
805 | for(Int_t ii=0; ii<ndet; ii++){ | |
806 | obj->Add(new TVectorD(AliTRDseedV1::kNtb)); | |
807 | } | |
808 | ||
809 | //ibin = binlowedge of bin(ibin+1) = the number fills this bin | |
810 | for(Int_t ibin=0; ibin<hnor->GetNbinsX(); ibin++){ | |
811 | const Double_t stat = hnor->GetBinContent(ibin+1); | |
812 | if(stat<EPSILON){ | |
813 | continue; | |
814 | } | |
815 | ||
816 | const Int_t idet = ToDetector(ibin); | |
817 | const Int_t itb = ToTimeBin(ibin); | |
818 | TVectorD *vec=(TVectorD *)obj->At(idet); | |
819 | (*vec)[itb] = stat; | |
820 | } | |
821 | ||
822 | hmean = new TH1D(Form("%sdetmean", hnor->GetName()), "", hnor->GetNbinsX(), hnor->GetXaxis()->GetXmin(), hnor->GetXaxis()->GetXmax()); | |
823 | for(Int_t ibin=0; ibin<hnor->GetNbinsX(); ibin++){ | |
824 | const Int_t idet = ToDetector(ibin); | |
825 | const TVectorD *vec=(TVectorD *)obj->At(idet); | |
826 | ||
827 | Int_t nonzero = 0; | |
828 | for(Int_t ii=0; ii<vec->GetNrows(); ii++){ | |
829 | if((*vec)[ii]>EPSILON){ | |
830 | nonzero++; | |
831 | } | |
832 | } | |
833 | ||
834 | Double_t mean = 0; | |
835 | const Double_t lowfrac = 0.6; | |
836 | //if there are too many 0's, reject this chamber by settig mean=rms=0 | |
837 | if(nonzero> (AliTRDseedV1::kNtb*(1-lowfrac)) ){ | |
838 | //only highest (1-lowfrac)*31 timebins are used to estimate the mean and rms! important! otherwise the 0' will make rms very large! | |
839 | mean = TruncatedMean(AliTRDseedV1::kNtb, vec->GetMatrixArray(), lowfrac, 1); | |
840 | } | |
841 | ||
842 | hmean->SetBinContent(ibin+1, mean); | |
843 | } | |
844 | ||
845 | delete obj; | |
846 | } | |
847 | ||
848 | void AliTRDdEdxUtils::CalibOutput(const TList *lin, Int_t run) | |
849 | { | |
850 | // | |
851 | //produce calibration objects | |
852 | // | |
853 | ||
854 | TString objnames("TRDCalibHistGain TRDCalibHistT0 TRDCalibHistVd "); | |
855 | for(Int_t iter=0; iter<8; iter++){ | |
856 | objnames+= GetPHQName(0, iter)+" "; | |
857 | } | |
858 | ||
859 | TList * lout = new TList; | |
860 | lout->SetOwner(); | |
861 | ||
862 | TTreeSRedirector *calibStream = new TTreeSRedirector(Form("TRDCalibStream_%010d.root", run)); | |
863 | ||
864 | const Int_t nh=lin->GetEntries(); | |
865 | for(Int_t ii=0; ii<nh; ii++){ | |
d1d15abc | 866 | const THnF *hh=(THnF*)lin->At(ii); |
fb3d369e | 867 | const TString hname = hh->GetName(); |
868 | if(!objnames.Contains(hname)) | |
869 | continue; | |
870 | ||
871 | TObjArray * cobj0 = GetCalibObj(hh, run, lout, calibStream); | |
872 | lout->Add(cobj0); | |
873 | } | |
874 | ||
875 | //lout->ls(); | |
876 | ||
877 | //============================================================= | |
878 | //============================================================= | |
879 | ||
880 | TFile *fout=new TFile(Form("TRDCalibObj_%010d.root", run),"recreate"); | |
881 | fout->cd(); | |
882 | const Int_t nout=lout->GetEntries(); | |
883 | for(Int_t ii=0; ii<nout; ii++){ | |
884 | const TString oname = lout->At(ii)->GetName(); | |
885 | if(oname.Contains("Obj")){ | |
886 | TObjArray * cobj = (TObjArray*) lout->At(ii); | |
887 | cobj->Write(oname, TObjArray::kSingleKey); | |
888 | } | |
889 | } | |
890 | fout->Save(); | |
891 | fout->Close(); | |
892 | delete fout; | |
893 | ||
894 | fout=new TFile(Form("TRDCalibList_%010d.root", run),"recreate"); | |
895 | fout->cd(); | |
896 | lin->Write(); | |
897 | lout->Write(); | |
898 | fout->Save(); | |
899 | fout->Close(); | |
900 | delete fout; | |
901 | ||
902 | delete calibStream; | |
903 | ||
904 | /* | |
905 | http://root.cern.ch/root/html/TH1.html | |
906 | When an histogram is created, a reference to it is automatically added to the list of in-memory objects for the current file or directory. This default behaviour can be changed by: | |
907 | ||
908 | h->SetDirectory(0); for the current histogram h | |
909 | TH1::AddDirectory(kFALSE); sets a global switch disabling the reference | |
910 | ||
911 | When the histogram is deleted, the reference to it is removed from the list of objects in memory. When a file is closed, all histograms in memory associated with this file are automatically deleted. | |
912 | */ | |
913 | delete lout; | |
914 | } | |
915 | ||
d1d15abc | 916 | TObjArray* AliTRDdEdxUtils::GetCalibObj(const THnF *hh, Int_t run, TList *lout, TTreeSRedirector *calibStream) |
fb3d369e | 917 | { |
918 | // | |
919 | //produce calibration objects | |
920 | // | |
921 | ||
922 | const TString hname = hh->GetName(); | |
923 | const Bool_t kinvq = TString(hname(hname.First('Q')+1,1)).Atoi()&4; | |
924 | ||
925 | //---------------------------------------- | |
926 | // Define nbin, tag, cobj0 | |
927 | //---------------------------------------- | |
928 | Int_t nbin =-999; | |
929 | if(hname.Contains("Gain") || hname.Contains("T0") || hname.Contains("Vd")){ | |
930 | nbin = NTRDchamber(); | |
931 | } | |
932 | else if(hname.Contains("PHQ")){ | |
933 | nbin = NTRDtimebin(); | |
934 | } | |
935 | else{ | |
936 | printf("AliTRDdEdxUtils::GetCalibObj error wrong hname!! %s\n", hname.Data()); exit(1); | |
937 | } | |
938 | ||
939 | TString tag(hname); | |
940 | tag.ReplaceAll("Hist","Obj"); | |
941 | ||
942 | TObjArray * cobj0 = new TObjArray(1); | |
943 | cobj0->SetOwner(); | |
944 | cobj0->SetName(tag); | |
945 | cobj0->Add(new TVectorD(nbin)); | |
946 | ||
947 | //---------------------------------------- | |
948 | // Define lowFrac, highFrac | |
949 | //---------------------------------------- | |
950 | Double_t lowFrac = -999, highFrac = -999; | |
951 | if(hname.Contains("Gain") || (hname.Contains("PHQ") && !kinvq) ){ | |
952 | lowFrac = 0.01; highFrac = Q0Frac(); | |
953 | } | |
954 | else if(hname.Contains("PHQ") && kinvq){ | |
955 | lowFrac = Q1Frac(); highFrac = 0.99; | |
956 | } | |
957 | else{ | |
958 | lowFrac = 0.01; | |
959 | highFrac = 0.99; | |
960 | } | |
961 | ||
962 | //---------------------------------------- | |
963 | // Get analysis result | |
964 | //---------------------------------------- | |
965 | TH1::AddDirectory(kFALSE);//important! | |
966 | TH1D *hnor=0x0, *hmpv=0x0, *hres=0x0, *hwid=0x0, *htrdphmean = 0x0;//if(!lout), these have to be deleted | |
967 | TH2D *hpj = hh->Projection(1,0); | |
968 | FitSlicesY(hpj, hnor, hmpv, hwid, hres, 0, lowFrac, highFrac); | |
969 | if(hname.Contains("PHQ")){ | |
970 | GetPHCountMeanRMS(hnor, htrdphmean); | |
971 | if(lout){ | |
972 | lout->Add(htrdphmean); | |
973 | } | |
974 | } | |
975 | delete hpj; | |
976 | ||
977 | if(lout){ | |
978 | lout->Add(hnor); | |
979 | lout->Add(hmpv); | |
980 | lout->Add(hwid); | |
981 | lout->Add(hres); | |
982 | } | |
983 | ||
984 | //---------------------------------------- | |
985 | // Define Counter | |
986 | //---------------------------------------- | |
987 | TVectorD *countDet=0x0; | |
988 | TObjArray *countSSL=0x0; | |
989 | ||
990 | if(hname.Contains("PHQ") && !kinvq){ | |
991 | countDet=new TVectorD(540); | |
992 | countSSL=new TObjArray(90);//SectorStackLayer | |
993 | countSSL->SetOwner(); | |
994 | for(Int_t ii=0; ii<90; ii++){ | |
995 | countSSL->Add(new TVectorD(6)); | |
996 | } | |
997 | } | |
998 | ||
999 | //---------------------------------------- | |
1000 | // Fill cobj0 | |
1001 | //---------------------------------------- | |
1002 | ||
1003 | //ibin = binlowedge of bin(ibin+1) = the number fills this bin | |
1004 | for(Int_t ibin=0; ibin<nbin; ibin++){ | |
1005 | Double_t gnor = hnor->GetBinContent(ibin+1); | |
1006 | Double_t gmpv = hmpv->GetBinContent(ibin+1); | |
1007 | Double_t gwid = hwid->GetBinContent(ibin+1); | |
1008 | Double_t gres = hres->GetBinContent(ibin+1); | |
1009 | ||
1010 | //--- set additional cut by kpass | |
1011 | Bool_t kpass = kTRUE; | |
1012 | Double_t gtrdphmean = -999; | |
1013 | if(htrdphmean){ | |
1014 | gtrdphmean = htrdphmean->GetBinContent(ibin+1); | |
1015 | //chamber no statistics (e.g. too many 0's), not usual, not seen in run 143237 | |
1016 | if(gtrdphmean<EPSILON){ | |
1017 | kpass = kFALSE; | |
1018 | } | |
1019 | if(gnor<TimeBinCountCut()*gtrdphmean){ | |
1020 | kpass = kFALSE; | |
1021 | } | |
1022 | } | |
1023 | ||
1024 | //--- set calibration constant p0 | |
1025 | Double_t p0= 0; | |
1026 | ||
1027 | //reason for gmpv=0: | |
1028 | //1)gnor<=3; truncation in hist: (0, 0.6*ntot=1.8 with ntot=3]={1}, in hist entries can pile up so that ntot=2, or 3, and (ntot>nstart && ntot<=nstop) is skipped; | |
1029 | //2)TruncatedMean(hist) out of range (only for Q0, not Q1). | |
1030 | ||
1031 | if(gmpv>EPSILON && kpass){ | |
1032 | if(tag.Contains("T0")){ | |
1033 | p0 = gmpv; | |
1034 | } | |
1035 | else{ | |
1036 | p0 = 1/gmpv; | |
1037 | } | |
1038 | //printf("outcalibobj%s %d %15.6e\n", tag.Data(), ibin, p0); | |
1039 | } | |
1040 | ||
1041 | (*( (TVectorD*)cobj0->At(0) ))[ibin] = p0; | |
1042 | ||
1043 | //--- save optional record | |
1044 | if(p0>EPSILON && countDet && countSSL){ | |
1045 | const Int_t idet = ToDetector(ibin); | |
1046 | (*countDet)[idet]=1; | |
1047 | ||
1048 | const Int_t isector = ToSector(ibin); | |
1049 | const Int_t istack = ToStack(ibin); | |
1050 | const Int_t ilayer = ToLayer(ibin); | |
1051 | TVectorD * vecsectorstack = (TVectorD*)countSSL->At(istack*18+isector); | |
1052 | (*vecsectorstack)[ilayer]=1; | |
1053 | } | |
1054 | ||
1055 | if(calibStream){ | |
1056 | (*calibStream)<<tag<< | |
1057 | "run="<<run<< | |
1058 | "p0="<<p0<< | |
1059 | ||
1060 | "nor="<<gnor<< | |
1061 | "mpv="<<gmpv<< | |
1062 | "wid="<<gwid<< | |
1063 | "res="<<gres<< | |
1064 | "gtrdphmean="<<gtrdphmean<< | |
1065 | ||
1066 | "ibin="<<ibin<< | |
1067 | "\n"; | |
1068 | } | |
1069 | } | |
1070 | ||
1071 | //---------------------------------------- | |
1072 | // Status Report | |
1073 | //---------------------------------------- | |
1074 | if(countDet && countSSL){ | |
1075 | TVectorD count2Dstack(90); | |
1076 | for(Int_t ii=0; ii<90; ii++){ | |
1077 | TVectorD * vecsectorstack = (TVectorD*)countSSL->At(ii); | |
1078 | const Int_t nlayer = (Int_t)vecsectorstack->Sum(); | |
1079 | if(nlayer==6){ | |
1080 | count2Dstack[ii]=1; | |
1081 | } | |
1082 | } | |
1083 | ||
1084 | printf("\nAliTRDdEdxUtils::GetCalibObj Summary run: %d name: %s entries: %.0f ndetector: %03.0f n2dstack %02.0f\n\n", run, hname.Data(), hh->GetEntries(), countDet->Sum(), count2Dstack.Sum()); | |
1085 | } | |
1086 | ||
1087 | //---------------------------------------- | |
1088 | // Clean Up | |
1089 | //---------------------------------------- | |
1090 | ||
1091 | TH1D **hhs[]={&hnor, &hmpv, &hwid, &hres, &htrdphmean}; | |
1092 | const Int_t nhh=sizeof(hhs)/sizeof(TH1D**); | |
1093 | for(Int_t ihh=0; ihh<nhh; ihh++){ | |
1094 | if(!lout){ | |
1095 | delete (*hhs[ihh]); | |
1096 | } | |
1097 | } | |
1098 | ||
1099 | delete countDet; | |
1100 | delete countSSL; | |
1101 | ||
1102 | //---------------------------------------- | |
1103 | ||
1104 | return cobj0; | |
1105 | } | |
1106 | ||
1107 | //=================================================================================== | |
1108 | // dEdx calculation | |
1109 | //=================================================================================== | |
fb3d369e | 1110 | Double_t AliTRDdEdxUtils::ToyCook(const Bool_t kinvq, Int_t &ncluster, TVectorD *arrayQ, TVectorD *arrayX, const TObjArray *cobj) |
1111 | { | |
1112 | // | |
1113 | //template for cookdedx | |
1114 | // | |
1115 | if(cobj){ | |
1116 | if(arrayQ && arrayX){ | |
1117 | ncluster = ApplyCalib(ncluster, arrayQ, arrayX, cobj); | |
1118 | } | |
1119 | else{ | |
1120 | printf("AliTRDdEdxUtils::ToyCook arrayQ arrayX null, applycalib can not be applied!\n"); exit(1); | |
1121 | } | |
1122 | } | |
1123 | ||
1124 | Double_t lowFrac =-999, highFrac = -999; | |
1125 | if(kinvq){ | |
1126 | lowFrac = Q1Frac(); highFrac = 0.99; | |
1127 | } | |
1128 | else{ | |
1129 | lowFrac = 0.01; highFrac = Q0Frac(); | |
1130 | } | |
1131 | ||
1132 | Double_t meanQ = TruncatedMean(ncluster, arrayQ->GetMatrixArray(), lowFrac, highFrac); | |
1133 | if(kinvq){ | |
1134 | if(meanQ>EPSILON){ | |
1135 | meanQ = 1/meanQ; | |
1136 | } | |
1137 | } | |
1138 | ||
1139 | return meanQ; | |
1140 | } | |
1141 | ||
1142 | Double_t AliTRDdEdxUtils::CombineddEdx(const Bool_t kinvq, Int_t &concls, TVectorD *coarrayQ, TVectorD *coarrayX, const Int_t tpcncls, const TVectorD *tpcarrayQ, const TVectorD *tpcarrayX, const Int_t trdncls, const TVectorD *trdarrayQ, const TVectorD *trdarrayX) | |
1143 | { | |
1144 | // | |
1145 | //combine tpc and trd dedx | |
1146 | // | |
1147 | ||
1148 | for(Int_t iq=0; iq<tpcncls; iq++){ | |
1149 | (*coarrayQ)[iq]=(*tpcarrayQ)[iq]; | |
1150 | if(tpcarrayX && trdarrayX && coarrayX){ | |
1151 | (*coarrayX)[iq]=(*tpcarrayX)[iq]; | |
1152 | } | |
1153 | } | |
1154 | for(Int_t iq=0; iq<trdncls; iq++){ | |
1155 | (*coarrayQ)[tpcncls+iq]=(*trdarrayQ)[iq]; | |
1156 | if(tpcarrayX && trdarrayX && coarrayX){ | |
1157 | (*coarrayX)[tpcncls+iq]=159+(*trdarrayX)[iq]; | |
1158 | } | |
1159 | } | |
1160 | ||
1161 | concls=trdncls+tpcncls; | |
1162 | ||
1163 | const Double_t coQ = ToyCook(kinvq, concls, coarrayQ, coarrayX); | |
1164 | ||
1165 | return coQ; | |
1166 | } | |
1167 | ||
1168 | ||
1169 | //=================================================================================== | |
1170 | // dEdx Getter and Setter | |
1171 | //=================================================================================== | |
1172 | Double_t AliTRDdEdxUtils::GetAngularCorrection(const AliTRDseedV1 *seed) | |
1173 | { | |
1174 | // | |
1175 | //return angular normalization factor | |
1176 | // | |
1177 | ||
1178 | return TMath::Sqrt(1+seed->GetYref(1)*seed->GetYref(1)+seed->GetZref(1)*seed->GetZref(1)); | |
1179 | } | |
1180 | ||
d0037ea4 | 1181 | Double_t AliTRDdEdxUtils::GetPadGain(const Int_t det, const Int_t icol, const Int_t irow) |
1182 | { | |
1183 | // | |
1184 | //get pad calibration | |
1185 | // | |
1186 | AliTRDcalibDB* calibration = AliTRDcalibDB::Instance(); | |
1187 | if (!calibration) { | |
1188 | printf("AliTRDdEdxUtils::GetPadCalib No AliTRDcalibDB instance available\n"); exit(1); | |
1189 | } | |
1190 | AliTRDCalROC * calGainFactorROC = calibration->GetGainFactorROC(det); | |
1191 | if(!calGainFactorROC){ | |
1192 | printf("AliTRDdEdxUtils::GetPadCalib no calGainFactorROC!\n"); exit(1); | |
1193 | } | |
1194 | ||
1195 | Double_t padgain = -999; | |
1196 | if( icol >= 0 && | |
1197 | icol < calGainFactorROC->GetNcols() && | |
1198 | irow >=0 && | |
1199 | irow < calGainFactorROC->GetNrows()){ | |
1200 | padgain = calGainFactorROC->GetValue(icol, irow); | |
1201 | if(padgain<EPSILON){ | |
1202 | printf("AliTRDdEdxUtils::GetPadGain padgain 0! %f %f -- %d %d %d -- %d %d\n", padgain, EPSILON, det, icol, irow, calGainFactorROC->GetNcols(), calGainFactorROC->GetNrows()); exit(1); | |
1203 | } | |
1204 | } | |
1205 | else{ | |
1206 | //printf("\nAliTRDdEdxUtils::GetPadGain warning!! indices out of range %d %d %d -- %d %d\n\n", det, icol, irow, calGainFactorROC->GetNcols(), calGainFactorROC->GetNrows() ); | |
1207 | } | |
1208 | ||
1209 | return padgain; | |
1210 | } | |
1211 | ||
1212 | Double_t AliTRDdEdxUtils::GetRNDClusterQ(AliTRDcluster *cl) | |
1213 | { | |
1214 | // | |
1215 | //get cluter q from GetRawQ, apply baseline and Kr pad-calibration | |
1216 | // | |
1217 | ||
1218 | const Int_t det = cl->GetDetector(); | |
1219 | const Int_t pad3col = cl->GetPadCol(); | |
1220 | const Int_t padrow = cl->GetPadRow(); | |
1221 | ||
1222 | const Double_t baseline = 10; | |
1223 | ||
1224 | Double_t rndqsum = 0; | |
1225 | for(Int_t ii=0; ii<7; ii++){ | |
25d9c307 | 1226 | if(cl->GetSignals()[ii] < EPSILON){//bad pad marked by electronics |
1227 | continue; | |
1228 | } | |
d0037ea4 | 1229 | |
25d9c307 | 1230 | const Int_t icol = pad3col+(ii-3); |
1231 | const Double_t padgain = GetPadGain(det, icol, padrow); | |
1232 | if(padgain<0){//indices out of range, pad3col near boundary case | |
d0037ea4 | 1233 | continue; |
1234 | } | |
1235 | ||
25d9c307 | 1236 | const Double_t rndsignal = (cl->GetSignals()[ii] - baseline)/(IsPadGainOn()? padgain : 1); |
d0037ea4 | 1237 | |
1238 | //sum it anyway even if signal below baseline, as long as the total is positive | |
1239 | rndqsum += rndsignal; | |
1240 | } | |
1241 | ||
1242 | return rndqsum; | |
1243 | } | |
1244 | ||
fb3d369e | 1245 | Double_t AliTRDdEdxUtils::GetClusterQ(const Bool_t kinvq, const AliTRDseedV1 * seed, const Int_t itb) |
1246 | { | |
1247 | // | |
1248 | //get cluster charge | |
1249 | // | |
1250 | Double_t dq = 0; | |
d0037ea4 | 1251 | AliTRDcluster *cl = 0x0; |
fb3d369e | 1252 | |
25d9c307 | 1253 | //GetRNDClusterQ(cl)>0 ensures that the total sum of q is above baseline*NsignalPhysical. |
d0037ea4 | 1254 | cl = seed->GetClusters(itb); if(cl && GetRNDClusterQ(cl)>0 ) dq+= GetRNDClusterQ(cl);//cl->GetRawQ(); |
1255 | cl = seed->GetClusters(itb+AliTRDseedV1::kNtb); if(cl && GetRNDClusterQ(cl)>0 ) dq+= GetRNDClusterQ(cl);//cl->GetRawQ(); | |
fb3d369e | 1256 | |
1257 | dq /= GetAngularCorrection(seed); | |
1258 | ||
d0037ea4 | 1259 | dq /= QScale(); |
fb3d369e | 1260 | |
1261 | if(kinvq){ | |
1262 | if(dq>EPSILON){ | |
1263 | dq = 1/dq; | |
1264 | } | |
1265 | } | |
1266 | ||
1267 | return dq; | |
1268 | } | |
1269 | ||
1270 | Int_t AliTRDdEdxUtils::GetArrayClusterQ(const Bool_t kinvq, TVectorD *arrayQ, TVectorD *arrayX, const AliTRDtrackV1 *trdtrack, Int_t timeBin0, Int_t timeBin1, Int_t tstep) | |
1271 | { | |
1272 | // | |
1273 | //return nclustter | |
1274 | //(if kinvq, return 1/q array), size of array must be larger than 31*6 | |
1275 | // | |
1276 | if(!arrayQ || arrayQ->GetNrows()< (AliTRDseedV1::kNtb*AliTRDtrackV1::kNplane)){ | |
1277 | printf("AliTRDdEdxUtils::GetArrayClusterQ error arrayQ null or size too small! %d\n", arrayQ? arrayQ->GetNrows() : -999); exit(1); | |
1278 | } | |
879b7730 | 1279 | if(!arrayX || arrayX->GetNrows()< (AliTRDseedV1::kNtb*AliTRDtrackV1::kNplane)){ |
fb3d369e | 1280 | printf("AliTRDdEdxUtils::GetArrayClusterQ error arrayX null or size too small! %d\n", arrayX? arrayX->GetNrows() : -999); exit(1); |
1281 | } | |
1282 | ||
1283 | const Int_t mintb = 0; | |
1284 | const Int_t maxtb = AliTRDseedV1::kNtb-1; | |
1285 | if(timeBin0<mintb) timeBin0=mintb; | |
1286 | if(timeBin1>maxtb) timeBin1=maxtb; | |
1287 | if(tstep<=0) tstep=1; | |
1288 | ||
1289 | //============ | |
1290 | Int_t tbN=0; | |
1291 | Double_t tbQ[200]; | |
1292 | Int_t tbBin[200]; | |
1293 | ||
1294 | for(Int_t ichamber=0; ichamber < AliTRDtrackV1::kNplane; ichamber++){ | |
1295 | const AliTRDseedV1 * seed = trdtrack->GetTracklet(ichamber); | |
1296 | if(!seed) | |
1297 | continue; | |
1298 | ||
1299 | const Int_t det = seed->GetDetector(); | |
1300 | ||
1301 | for(Int_t itb=timeBin0; itb<=timeBin1; itb+=tstep){ | |
1302 | const Double_t dq = GetClusterQ(kinvq, seed, itb); | |
1303 | if(dq<EPSILON) | |
1304 | continue; | |
1305 | ||
1306 | const Int_t gtb = det * AliTRDseedV1::kNtb + itb; | |
1307 | ||
1308 | tbQ[tbN]=dq; | |
1309 | tbBin[tbN]=gtb; | |
1310 | tbN++; | |
1311 | } | |
1312 | } | |
1313 | ||
1314 | Int_t ncls = 0; | |
1315 | for(Int_t iq=0; iq<tbN; iq++){ | |
1316 | if(tbQ[iq]<EPSILON) | |
1317 | continue; | |
1318 | ||
1319 | (*arrayQ)[ncls] = tbQ[iq]; | |
1320 | (*arrayX)[ncls] = tbBin[iq]; | |
1321 | ||
1322 | ncls++; | |
1323 | } | |
1324 | ||
879b7730 | 1325 | static Int_t kprint = 100; |
fb3d369e | 1326 | if(kprint<0){ |
1327 | printf("\nAliTRDdEdxUtils::GetArrayClusterQ raw cluster-Q\n"); | |
1328 | for(Int_t iq=0; iq<ncls; iq++){ | |
1329 | const Int_t ichamber = ToLayer((*arrayX)[iq]); | |
1330 | const AliTRDseedV1 * seed = trdtrack->GetTracklet(ichamber); | |
1331 | if(!seed){ | |
1332 | printf("error seed null!!\n"); exit(1); | |
1333 | } | |
1334 | const Double_t rawq = (*arrayQ)[iq] * 45. * GetAngularCorrection(seed); | |
1335 | printf("esdid=%d; chamber=%d; timebin=%d; rawq= %.3f; myq[%d]= %e;\n", trdtrack->GetESDid(), ichamber, ToTimeBin((*arrayX)[iq]), rawq, iq, (*arrayQ)[iq]); | |
1336 | } | |
1337 | printf("\n"); | |
1338 | } | |
879b7730 | 1339 | kprint++; |
fb3d369e | 1340 | |
1341 | return ncls; | |
1342 | } | |
1343 | ||
1344 | Int_t AliTRDdEdxUtils::UpdateArrayX(const Int_t ncls, TVectorD* arrayX) | |
1345 | { | |
1346 | // | |
1347 | //arrayX det*Ntb+itb -> itb | |
1348 | // | |
1349 | ||
1350 | TVectorD countChamber(6); | |
1351 | for(Int_t ii = 0; ii<ncls; ii++){ | |
1352 | const Int_t xx = (Int_t)(*arrayX)[ii]; | |
1353 | const Int_t idet = ToDetector(xx); | |
1354 | ||
1355 | const Double_t ich = AliTRDgeometry::GetLayer(idet); | |
1356 | const Double_t itb = ToTimeBin(xx); | |
1357 | (*arrayX)[ii] = ich*AliTRDseedV1::kNtb+itb; | |
1358 | ||
1359 | countChamber[ich] = 1; | |
1360 | } | |
1361 | ||
1362 | const Double_t nch = countChamber.Sum(); | |
1363 | return (Int_t) nch; | |
1364 | } | |
1365 | ||
d1d15abc | 1366 | void AliTRDdEdxUtils::SetChamberQT(const AliTRDtrackV1 *trdtrack, const Int_t kcalib, THnF * hgain, THnF * ht0, THnF * hvd) |
fb3d369e | 1367 | { |
1368 | // | |
1369 | //CookdEdx at TRD track level, use chamber info, related calibrations: chamber-gain; T0, Vd based on raw PH distribution | |
1370 | // | |
1371 | ||
1372 | static Int_t kprint = 100; | |
1373 | ||
1374 | fgNchamber = 0; | |
1375 | for(Int_t ichamber=0; ichamber < AliTRDtrackV1::kNplane; ichamber++){ | |
1376 | //initialize output, default values: 0, so that summation and weighting will automatically discard default quantities | |
1377 | fgChamberQ[ichamber] = fgChamberTmean[ichamber] = 0; | |
1378 | ||
1379 | const AliTRDseedV1 *seed = trdtrack->GetTracklet(ichamber); | |
1380 | if (!seed) | |
1381 | continue; | |
1382 | ||
1383 | const Int_t idet = seed->GetDetector(); | |
1384 | ||
1385 | //------------------------------------------------------------------------- | |
1386 | ||
1387 | Double_t qsum = 0, qtsum = 0, w2sum = 0; | |
1388 | for(Int_t itb=0; itb<AliTRDseedV1::kNtb; itb++){ | |
1389 | const Double_t dq = GetClusterQ(0, seed, itb); | |
1390 | if(dq<EPSILON) | |
1391 | continue; | |
1392 | ||
1393 | qsum += dq; | |
1394 | qtsum += dq*itb; | |
1395 | w2sum += dq*itb*itb; | |
1396 | } | |
1397 | if(qsum<EPSILON) | |
1398 | continue; | |
1399 | ||
1400 | //------------------------------------------------------------------------- | |
1401 | ||
1402 | Double_t tbm, tbr = 0; | |
1403 | tbm = GetMeanRMS(qsum, qtsum, w2sum, &tbr); | |
1404 | ||
1405 | qsum /= 1.25e3/45.; | |
1406 | ||
1407 | if(hgain){ | |
1408 | const Double_t var[]={idet, qsum}; | |
1409 | hgain->Fill(var); | |
1410 | } | |
1411 | if(ht0){ | |
1412 | const Double_t var[]={idet, tbm}; | |
1413 | ht0->Fill(var); | |
1414 | } | |
1415 | if(hvd){ | |
1416 | const Double_t var[]={idet, tbr}; | |
1417 | hvd->Fill(var); | |
1418 | } | |
1419 | ||
1420 | Double_t gain = 1, t0 = 0, vd = 1; | |
1421 | if(kcalib){ | |
1422 | if(!fgObjGain) {printf("AliTRDdEdxUtils::SetChamberQT error Gain array null!!\n"); exit(1);} | |
1423 | if(! fgObjT0) {printf("AliTRDdEdxUtils::SetChamberQT error T0 array null!!\n"); exit(1);} | |
1424 | if(! fgObjVd) {printf("AliTRDdEdxUtils::SetChamberQT error Vd array null!!\n"); exit(1);} | |
1425 | ||
1426 | const TVectorD * gainvec = (TVectorD*) fgObjGain->At(0); gain = (*gainvec)[idet]; | |
1427 | const TVectorD * t0vec = (TVectorD*) fgObjT0->At(0); t0 = (* t0vec)[idet]; | |
1428 | const TVectorD * vdvec = (TVectorD*) fgObjVd->At(0); vd = (* vdvec)[idet]; | |
1429 | } | |
1430 | if(kprint<0){ | |
1431 | printf("\nAliTRDdEdxUtils::CookdEdxV2\n"); | |
1432 | printf("idet = %d;\n", idet); | |
1433 | printf("gain = %15f; t0 = %15f; vd = %15f;\n", gain, t0, vd); | |
1434 | printf("\n"); | |
1435 | } | |
1436 | ||
1437 | qsum *= gain; | |
1438 | tbm = (tbm-t0)*vd; | |
1439 | ||
1440 | if(qsum<EPSILON) | |
1441 | continue; | |
1442 | ||
1443 | //------------------------------------------------------------------------- | |
1444 | ||
1445 | //should have non-zero value, initialized with default 0 (except for calibrated tbm, may be very close to 0) | |
1446 | fgChamberQ[ichamber] = qsum; | |
1447 | fgChamberTmean[ichamber] = tbm; | |
1448 | fgNchamber++; | |
1449 | } | |
1450 | ||
1451 | if(kprint<0){ | |
1452 | printf("\nAliTRDdEdxUtils::CookdEdxV2 summary:\n"); | |
1453 | ||
1454 | printf("\nfgNchamber = %d\n", fgNchamber); | |
1455 | for(Int_t ich=0; ich<AliTRDtrackV1::kNplane; ich++){ | |
1456 | printf("fgChamberTmean[%d] = %15f; fgChamberQ[%d] = %15f;\n", ich, fgChamberTmean[ich], ich, fgChamberQ[ich]); | |
1457 | } | |
1458 | } | |
1459 | ||
1460 | fgTrackTmean = -999; | |
1461 | if(fgNchamber){ | |
1462 | fgTrackTmean = 0; | |
1463 | for(Int_t ich=0; ich<AliTRDtrackV1::kNplane; ich++){ | |
1464 | fgTrackTmean += fgChamberTmean[ich]; | |
1465 | } | |
1466 | fgTrackTmean /= fgNchamber; | |
1467 | } | |
1468 | ||
1469 | if(kprint<0){ | |
1470 | printf("\nAliTRDdEdxUtils::CookdEdxV2\n"); | |
1471 | printf("GetTrackTmean() %15f\n", GetTrackTmean()); | |
1472 | printf("\n"); | |
1473 | } | |
1474 | kprint++; | |
1475 | ||
1476 | return; | |
1477 | } | |
1478 | ||
1479 | ||
1480 | //=================================================================================== | |
1481 | // dEdx Parameterization | |
1482 | //=================================================================================== | |
1483 | ||
1484 | Double_t AliTRDdEdxUtils::Q0MeanTRDpp(const Double_t bg) | |
1485 | { | |
1486 | // | |
1487 | //truncated Mean Q_{xx} in TRD | |
1488 | // | |
1489 | ||
1490 | Double_t par[8]; | |
1491 | //03132012161150 | |
1492 | //opt: ppQ0 | |
1493 | par[0]= 2.397001e-01; | |
1494 | par[1]= 1.334697e+00; | |
1495 | par[2]= 6.967470e+00; | |
1496 | par[3]= 9.055289e-02; | |
1497 | par[4]= 9.388760e+00; | |
1498 | par[5]= 9.452742e-04; | |
1499 | par[6]= -1.866091e+00; | |
1500 | par[7]= 1.403545e+00; | |
1501 | ||
1502 | ///u/xlu/.task/CommondEdx/myAnaData/Optimum/check11/Merged/LHC10e_plot/Separation/see2.log:hhtype2Q0b2c2 scale 0.428543 at ltbg 0.650000 | |
1503 | return 0.428543*MeandEdxTR(&bg, par); | |
1504 | } | |
1505 | ||
1506 | Double_t AliTRDdEdxUtils::Q0MeanTRDPbPb(const Double_t bg) | |
1507 | { | |
1508 | // | |
1509 | //truncated Mean Q_{xx} in TRD | |
1510 | // | |
1511 | ||
1512 | Double_t par[8]; | |
1513 | ||
1514 | //03132012161259 | |
1515 | //opt: PbPbQ0 | |
1516 | par[0]= 1.844912e-01; | |
1517 | par[1]= 2.509702e+00; | |
1518 | par[2]= 6.744031e+00; | |
1519 | par[3]= 7.355123e-02; | |
1520 | par[4]= 1.166023e+01; | |
1521 | par[5]= 1.736186e-04; | |
1522 | par[6]= -1.716063e+00; | |
1523 | par[7]= 1.611366e+00; | |
1524 | ||
1525 | ///u/xlu/.task/CommondEdx/myAnaData/Optimum/check11/Merged/LHC10e_plot/Separation/see4.log:hhtype4Q0b2c2 scale 0.460994 at ltbg 0.650000 | |
1526 | return 0.460994*MeandEdxTR(&bg, par); | |
1527 | } | |
1528 | ||
1529 | Double_t AliTRDdEdxUtils::Q1MeanTRDpp(const Double_t bg) | |
1530 | { | |
1531 | // | |
1532 | //truncated Mean 1/(1/Q)_{xx} in TRD | |
1533 | // | |
1534 | ||
1535 | Double_t par[8]; | |
1536 | ||
1537 |