]>
Commit | Line | Data |
---|---|---|
10757ee9 | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
7 | * Permission to use, copy, modify and distribute this software and its * | |
8 | * documentation strictly for non-commercial purposes is hereby granted * | |
9 | * without fee, provided that the above copyright notice appears in all * | |
10 | * copies and that both the copyright notice and this permission notice * | |
11 | * appear in the supporting documentation. The authors make no claims * | |
12 | * about the suitability of this software for any purpose. It is * | |
13 | * provided "as is" without express or implied warranty. * | |
14 | **************************************************************************/ | |
15 | ||
16 | //////////////////////////////////////////////////////////////////////////// | |
17 | // | |
18 | // === Calibration class for gain calibration using tracks === | |
19 | // | |
20 | // 1) Genereal idea | |
21 | // ================ | |
22 | // A 6-parametric parabolic function | |
23 | // | |
24 | // G(x, y) = p0 + p1*x + p2*y + p3*x^2 + p4*y^2 + p5 * x*y | |
25 | // | |
26 | // is fitted to the maximum charge values or total charge values of | |
27 | // all the clusters contained in the tracks that are added to this | |
28 | // object. This fit is performed for each read out chamber, in fact even | |
29 | // for each type of pad sizes (thus for one segment, which consists of | |
30 | // an IROC and an OROC, there are three fitters used, corresponding to | |
31 | // the three pad sizes). The coordinate origin is at the center of the | |
32 | // particular pad size region on each ROC. | |
33 | // | |
34 | // Because of the Landau nature of the charge deposition we use | |
35 | // different "types" of fitters instead of one to minimize the effect | |
36 | // of the long Landau tail. The difference between the fitters is only | |
37 | // the charge value, that is put into them, i.e. the charge is subject | |
38 | // to a transformation. At this point we use three different fit types: | |
39 | // | |
40 | // a) simple: the charge is put in as it is | |
41 | // b) sqrt: the square root of the charge is put into the fitter | |
42 | // c) log: fgkM * Log(1+q/fgkM) is put into the fitter, with | |
43 | // q being the untransformed charge and fgkM=25 | |
44 | // | |
45 | // The results of the fits may be visualized and further used by | |
46 | // creating an AliTPCCalROC or AliTPCCalPad. You may specify to undo | |
47 | // the transformation and/or to normalize to the pad size. | |
48 | // | |
49 | // Not every track you add to this object is actually used for | |
50 | // calibration. There are some cuts and conditions to exclude bad | |
51 | // tracks, e.g. a pt cut to cut out tracks with too much charge | |
52 | // deposition or a cut on edge clusters which are not fully | |
53 | // registered and don't give a usable signal. | |
54 | // | |
55 | // 2) Interface / usage | |
56 | // ==================== | |
57 | // For each track to be added you need to call Process(). | |
58 | // This method expects an AliTPCseed, which contains the necessary | |
59 | // cluster information. At the moment of writing this information | |
60 | // is stored in an AliESDfriend corresponding to an AliESD. | |
61 | // You may also call AddTrack() if you don't want the cuts and | |
62 | // other quality conditions to kick in (thus forcing the object to | |
63 | // accept the track) or AddCluster() for adding single clusters. | |
64 | // Call one of the Evaluate functions to evaluate the fitter(s) and | |
65 | // to retrieve the fit parameters, erros and so on. You can also | |
66 | // do this later on by using the different Getters. | |
67 | // | |
68 | // The visualization methods CreateFitCalPad() and CreateFitCalROC() | |
69 | // are straight forward to use. | |
70 | // | |
71 | // Note: If you plan to write this object to a ROOT file, make sure | |
72 | // you evaluate all the fitters *before* writing, because due | |
73 | // to a bug in the fitter component writing fitters doesn't | |
74 | // work properly (yet). Be aware that you cannot re-evaluate | |
75 | // the fitters after loading this object from file. | |
76 | // (This will be gone for a new ROOT version > v5-17-05) | |
77 | // | |
78 | //////////////////////////////////////////////////////////////////////////// | |
79 | ||
80 | #include <TPDGCode.h> | |
81 | #include <TStyle.h> | |
82 | #include "TSystem.h" | |
83 | #include "TMatrixD.h" | |
84 | #include "TTreeStream.h" | |
85 | #include "TF1.h" | |
86 | #include "AliTPCParamSR.h" | |
87 | #include "AliTPCClusterParam.h" | |
88 | #include "AliTrackPointArray.h" | |
89 | #include "TCint.h" | |
90 | #include "AliTPCcalibTracksGain.h" | |
91 | #include <TH1.h> | |
92 | #include <TH3F.h> | |
93 | #include <TLinearFitter.h> | |
94 | #include <TTreeStream.h> | |
95 | #include <TFile.h> | |
96 | #include <TCollection.h> | |
97 | #include <TIterator.h> | |
98 | ||
99 | // | |
100 | // AliRoot includes | |
101 | // | |
102 | #include "AliMagF.h" | |
103 | #include "AliMathBase.h" | |
104 | // | |
105 | #include "AliTPCROC.h" | |
106 | #include "AliTPCParamSR.h" | |
107 | #include "AliTPCCalROC.h" | |
108 | #include "AliTPCCalPad.h" | |
109 | // | |
110 | #include "AliTracker.h" | |
111 | #include "AliESD.h" | |
112 | #include "AliESDtrack.h" | |
113 | #include "AliESDfriend.h" | |
114 | #include "AliESDfriendTrack.h" | |
115 | #include "AliTPCseed.h" | |
116 | #include "AliTPCclusterMI.h" | |
117 | #include "AliTPCcalibTracksCuts.h" | |
118 | #include "AliTPCFitPad.h" | |
119 | ||
120 | // REMOVE ALL OF THIS | |
121 | #include <TTree.h> | |
122 | #include "AliESDEvent.h" | |
123 | ||
124 | /* | |
125 | ||
126 | TFile f("TPCCalibTracksGain.root") | |
127 | ||
128 | gSystem->Load("libPWG1.so") | |
129 | AliTreeDraw comp | |
130 | comp.SetTree(dEdx) | |
131 | Double_t chi2; | |
132 | TVectorD vec(3) | |
133 | TMatrixD mat(3,3) | |
134 | TString * str = comp.FitPlane("Cl.fQ/dedxQ.fElements[0]","Cl.fY++Cl.fX","Cl.fDetector<36",chi2,vec,mat) | |
135 | ||
136 | */ | |
137 | ||
138 | ClassImp(AliTPCcalibTracksGain) | |
139 | ||
140 | const Bool_t AliTPCcalibTracksGain::fgkUseTotalCharge = kTRUE; | |
141 | const Double_t AliTPCcalibTracksGain::fgkM = 25.; | |
142 | const char* AliTPCcalibTracksGain::fgkDebugStreamFileName = "TPCCalibTracksGain.root"; | |
143 | AliTPCParamSR* AliTPCcalibTracksGain::fgTPCparam = new AliTPCParamSR(); | |
144 | ||
145 | AliTPCcalibTracksGain::AliTPCcalibTracksGain() : | |
146 | TNamed(), | |
147 | fDebugCalPadRaw(0), | |
148 | fDebugCalPadCorr(0), | |
149 | fDebugStream(0), | |
150 | fSimpleFitter(0), | |
151 | fSqrtFitter(0), | |
152 | fLogFitter(0), | |
153 | fSingleSectorFitter(0), | |
154 | fPrevIter(0), | |
155 | fDebugStreamPrefix(0), | |
156 | fCuts(0) | |
157 | { | |
158 | // | |
159 | // Default constructor. | |
160 | // | |
161 | } | |
162 | ||
163 | AliTPCcalibTracksGain::AliTPCcalibTracksGain(const AliTPCcalibTracksGain& obj) : | |
164 | TNamed(obj) | |
165 | { | |
166 | // | |
167 | // Copy constructor. | |
168 | // | |
169 | ||
170 | fDebugCalPadRaw = new AliTPCCalPad(*(obj.fDebugCalPadRaw)); | |
171 | fDebugCalPadCorr = new AliTPCCalPad(*(obj.fDebugCalPadCorr)); | |
172 | fSimpleFitter = new AliTPCFitPad(*(obj.fSimpleFitter)); | |
173 | fSqrtFitter = new AliTPCFitPad(*(obj.fSqrtFitter)); | |
174 | fLogFitter = new AliTPCFitPad(*(obj.fLogFitter)); | |
175 | fSingleSectorFitter = new AliTPCFitPad(*(obj.fSingleSectorFitter)); | |
176 | fPrevIter = new AliTPCcalibTracksGain(*(obj.fPrevIter)); | |
177 | fDebugStreamPrefix = new TObjString(*(obj.fDebugStreamPrefix)); | |
178 | fCuts = new AliTPCcalibTracksCuts(*(obj.fCuts)); | |
179 | } | |
180 | ||
181 | AliTPCcalibTracksGain& AliTPCcalibTracksGain::operator=(const AliTPCcalibTracksGain& rhs) { | |
182 | // | |
183 | // Assignment operator. | |
184 | // | |
185 | ||
186 | if (this != &rhs) { | |
187 | TNamed::operator=(rhs); | |
188 | fDebugCalPadRaw = new AliTPCCalPad(*(rhs.fDebugCalPadRaw)); | |
189 | fDebugCalPadCorr = new AliTPCCalPad(*(rhs.fDebugCalPadCorr)); | |
190 | fSimpleFitter = new AliTPCFitPad(*(rhs.fSimpleFitter)); | |
191 | fSqrtFitter = new AliTPCFitPad(*(rhs.fSqrtFitter)); | |
192 | fLogFitter = new AliTPCFitPad(*(rhs.fLogFitter)); | |
193 | fSingleSectorFitter = new AliTPCFitPad(*(rhs.fSingleSectorFitter)); | |
194 | fPrevIter = new AliTPCcalibTracksGain(*(rhs.fPrevIter)); | |
195 | fDebugStreamPrefix = new TObjString(*(rhs.fDebugStreamPrefix)); | |
196 | fCuts = new AliTPCcalibTracksCuts(*(rhs.fCuts)); | |
197 | } | |
198 | return *this; | |
199 | } | |
200 | ||
201 | AliTPCcalibTracksGain::AliTPCcalibTracksGain(const char* name, const char* title, AliTPCcalibTracksCuts* cuts, TNamed* debugStreamPrefix, AliTPCcalibTracksGain* prevIter) : | |
202 | TNamed(name, title), | |
203 | fDebugCalPadRaw(0), | |
204 | fDebugCalPadCorr(0), | |
205 | fDebugStream(0), | |
206 | fSimpleFitter(0), | |
207 | fSqrtFitter(0), | |
208 | fLogFitter(0), | |
209 | fSingleSectorFitter(0), | |
210 | fPrevIter(0), | |
211 | fDebugStreamPrefix(0), | |
212 | fCuts(0) | |
213 | { | |
214 | // | |
215 | // Constructor. | |
216 | // | |
217 | ||
218 | G__SetCatchException(0); | |
219 | ||
220 | fCuts = cuts; | |
221 | if (debugStreamPrefix) fDebugStreamPrefix = new TObjString(debugStreamPrefix->GetTitle()); | |
222 | fPrevIter = prevIter; | |
223 | ||
224 | fSimpleFitter = new AliTPCFitPad(8, "hyp7", ""); | |
225 | fSqrtFitter = new AliTPCFitPad(8, "hyp7", ""); | |
226 | fLogFitter = new AliTPCFitPad(8, "hyp7", ""); | |
227 | fSingleSectorFitter = new AliTPCFitPad(8, "hyp7", ""); | |
228 | ||
229 | // just for debugging | |
230 | fTotalTracks = 0; | |
231 | fAcceptedTracks = 0; | |
232 | fDebugCalPadRaw = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction"); | |
233 | fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction"); | |
234 | ||
235 | // this will be gone for the a new ROOT version > v5-17-05 | |
236 | for (UInt_t i = 0; i < 36; i++) { | |
237 | fNShortClusters[i] = 0; | |
238 | fNMediumClusters[i] = 0; | |
239 | fNLongClusters[i] = 0; | |
240 | } | |
241 | } | |
242 | ||
243 | AliTPCcalibTracksGain::~AliTPCcalibTracksGain() { | |
244 | // | |
245 | // Destructor. | |
246 | // | |
247 | ||
248 | Info("Destructor",""); | |
249 | if (fSimpleFitter) delete fSimpleFitter; | |
250 | if (fSqrtFitter) delete fSqrtFitter; | |
251 | if (fLogFitter) delete fLogFitter; | |
252 | if (fSingleSectorFitter) delete fSingleSectorFitter; | |
253 | ||
254 | ||
255 | if (fDebugStream) { | |
256 | //fDebugStream->GetFile()->Close(); | |
257 | printf("Deleting debug stream object\n"); | |
258 | delete fDebugStream; | |
259 | } | |
260 | ||
261 | if (fDebugStreamPrefix) delete fDebugStreamPrefix; | |
262 | ||
263 | if (fDebugCalPadRaw) delete fDebugCalPadRaw; | |
264 | if (fDebugCalPadCorr) delete fDebugCalPadCorr; | |
265 | } | |
266 | ||
267 | void AliTPCcalibTracksGain::Terminate(){ | |
268 | // | |
269 | // Evaluate fitters and close the debug stream. | |
270 | // Also move or copy the debug stream, if a debugStreamPrefix is provided. | |
271 | // | |
272 | ||
273 | Evaluate(); | |
274 | if (fDebugStream) { | |
275 | delete fDebugStream; | |
276 | fDebugStream = 0; | |
277 | } | |
278 | ||
279 | if (fDebugStreamPrefix) { | |
280 | TString debugStreamPrefix = fDebugStreamPrefix->GetString(); | |
281 | TString destFile(""); | |
282 | destFile += debugStreamPrefix; | |
283 | destFile += "/"; | |
284 | destFile += gSystem->HostName(); | |
285 | destFile += "_TPCCalibTracksGain.root"; | |
286 | if (debugStreamPrefix.BeginsWith("root://")) { | |
287 | TFile::Cp("TPCCalibTracksGain.root", destFile.Data()); | |
288 | } else { | |
289 | TString command("mv TPCCalibTracksGain.root "); | |
290 | command += destFile; | |
291 | gSystem->Exec(command.Data()); | |
292 | } | |
293 | } | |
294 | } | |
295 | ||
296 | void AliTPCcalibTracksGain::AddInfo(TChain* chain, char* debugStreamPrefix, char* prevIterFileName) { | |
297 | // | |
298 | // Add some parameters to the chain. | |
299 | // debugStreamPrefix: If specified, contains the location (either normal or xrootd directory) | |
300 | // where the debug stream is moved (normal directory) or copied to (xrootd). | |
301 | // prevIterFileName: If specified, contains an AliTPCcalibTracksGain object from a previous run | |
302 | // for doing an iterative calibration procedure (right now unused). | |
303 | // Note: The parameters are *not* added to this class, you need to do it later by retrieving | |
304 | // the parameters from the chain and passing them to the constructor! | |
305 | // | |
306 | ||
307 | if (debugStreamPrefix) { | |
308 | TNamed* objDebugStreamPrefix = new TNamed("debugStreamPrefix", debugStreamPrefix); | |
309 | chain->GetUserInfo()->AddLast((TObject*)objDebugStreamPrefix); | |
310 | } | |
311 | ||
312 | if (prevIterFileName) { | |
313 | TFile paramFile(prevIterFileName); | |
314 | if (paramFile.IsZombie()) { | |
315 | printf("File %s not found. Continuing without previous iteration.\n", prevIterFileName); | |
316 | return; | |
317 | } | |
318 | ||
319 | AliTPCcalibTracksGain *prevIter = (AliTPCcalibTracksGain*)paramFile.Get("calibTracksGain"); | |
320 | if (prevIter) { | |
321 | chain->GetUserInfo()->AddLast((TObject*)prevIter); | |
322 | } else | |
323 | printf("No calibTracksGain object found. Continuing without previous iteration.\n"); | |
324 | } | |
325 | } | |
326 | ||
327 | Bool_t AliTPCcalibTracksGain::AcceptTrack(AliTPCseed* track) { | |
328 | // | |
329 | // Decides whether to accept a track or not depending on track parameters and cuts | |
330 | // contained as AliTPCcalibTracksCuts object fCuts. | |
331 | // Tracks are discarded if the number of clusters is too low or the transverse | |
332 | // momentum is too low. | |
333 | // The corresponding cut values are specified in the fCuts member. | |
334 | // | |
335 | ||
336 | if (track->GetNumberOfClusters() < fCuts->GetMinClusters()) return kFALSE; | |
337 | //if ((TMath::Abs(track->GetY() / track->GetX()) > fCuts->GetEdgeYXCutNoise()) | |
338 | // && (TMath::Abs(track->GetTgl()) < fCuts->GetEdgeThetaCutNoise())) return kFALSE; | |
339 | //if (track->GetNumberOfClusters() / (track->GetNFoundable()+1.) < fCuts->GetMinRatio()) return kFALSE; | |
340 | if (TMath::Abs(track->GetSigned1Pt()) > fCuts->GetMax1pt()) return kFALSE; | |
341 | ||
342 | //if (track->GetPt() < 50.) return kFALSE; | |
343 | return kTRUE; | |
344 | } | |
345 | ||
346 | void AliTPCcalibTracksGain::Process(AliTPCseed* seed) { | |
347 | // | |
348 | // Main method to be called when a new seed is supposed to be processed | |
349 | // and be used for gain calibration. Its quality is checked before it | |
350 | // is added. | |
351 | // | |
352 | ||
353 | fTotalTracks++; | |
354 | if (!AcceptTrack(seed)) return; | |
355 | fAcceptedTracks++; | |
356 | AddTrack(seed); | |
357 | } | |
358 | ||
359 | Long64_t AliTPCcalibTracksGain::Merge(TCollection *list) { | |
360 | // | |
361 | // Merge() merges the results of all AliTPCcalibTracksGain objects contained in | |
362 | // list, thus allowing a distributed computation of several files, e.g. on PROOF. | |
363 | // The merged results are merged with the data members of the AliTPCcalibTracksGain | |
364 | // object used for calling the Merge method. | |
365 | // The return value is 0 /*the total number of tracks used for calibration*/ if the merge | |
366 | // is successful, otherwise it is -1. | |
367 | // | |
368 | ||
369 | if (!list || list->IsEmpty()) return -1; | |
370 | ||
371 | if (!fSimpleFitter) fSimpleFitter = new AliTPCFitPad(8, "hyp7", ""); | |
372 | if (!fSqrtFitter) fSqrtFitter = new AliTPCFitPad(8, "hyp7", ""); | |
373 | if (!fLogFitter) fLogFitter = new AliTPCFitPad(8, "hyp7", ""); | |
374 | if (!fSingleSectorFitter) fSingleSectorFitter = new AliTPCFitPad(8, "hyp7", ""); | |
375 | ||
376 | // this will be gone for the a new ROOT version > v5-17-05 | |
377 | for (UInt_t i = 0; i < 36; i++) { | |
378 | fNShortClusters[i] = 0; | |
379 | fNMediumClusters[i] = 0; | |
380 | fNLongClusters[i] = 0; | |
381 | } | |
382 | ||
383 | // just for debugging | |
384 | if (fDebugCalPadRaw) delete fDebugCalPadRaw; | |
385 | if (fDebugCalPadCorr) delete fDebugCalPadCorr; | |
386 | fDebugCalPadRaw = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction"); | |
387 | fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction"); | |
388 | fTotalTracks = 0; | |
389 | fAcceptedTracks = 0; | |
390 | ||
391 | TIterator* iter = list->MakeIterator(); | |
392 | AliTPCcalibTracksGain* cal = 0; | |
393 | ||
394 | while ((cal = (AliTPCcalibTracksGain*)iter->Next())) { | |
395 | if (!cal->InheritsFrom(AliTPCcalibTracksGain::Class())) { | |
396 | Error("Merge","Attempt to add object of class %s to a %s", cal->ClassName(), this->ClassName()); | |
397 | return -1; | |
398 | } | |
399 | Add(cal); | |
400 | } | |
401 | return 0; | |
402 | } | |
403 | ||
404 | void AliTPCcalibTracksGain::Add(AliTPCcalibTracksGain* cal) { | |
405 | // | |
406 | // Adds another AliTPCcalibTracksGain object to this object. | |
407 | // | |
408 | ||
409 | fSimpleFitter->Add(cal->fSimpleFitter); | |
410 | fSqrtFitter->Add(cal->fSqrtFitter); | |
411 | fLogFitter->Add(cal->fLogFitter); | |
412 | fSingleSectorFitter->Add(cal->fSingleSectorFitter); | |
413 | ||
414 | // this will be gone for the a new ROOT version > v5-17-05 | |
415 | for (UInt_t iSegment = 0; iSegment < 36; iSegment++) { | |
416 | fNShortClusters[iSegment] += cal->fNShortClusters[iSegment]; | |
417 | fNMediumClusters[iSegment] += cal->fNMediumClusters[iSegment]; | |
418 | fNLongClusters[iSegment] += cal->fNLongClusters[iSegment]; | |
419 | } | |
420 | ||
421 | // just for debugging, remove me | |
422 | fTotalTracks += cal->fTotalTracks; | |
423 | fAcceptedTracks += cal->fAcceptedTracks; | |
424 | fDebugCalPadRaw->Add(cal->fDebugCalPadRaw); | |
425 | fDebugCalPadCorr->Add(cal->fDebugCalPadCorr); | |
426 | ||
427 | // Let's see later what to do with fCuts, fDebugStream and fDebugStreamPrefix, | |
428 | // we'll probably won't merge them. | |
429 | } | |
430 | ||
431 | void AliTPCcalibTracksGain::AddTrack(AliTPCseed* seed) { | |
432 | // | |
433 | // The clusters making up the track (seed) are added to various fit functions. | |
434 | // See AddCluster(...) for more detail. | |
435 | // | |
436 | ||
437 | if (!fDebugStream) fDebugStream = new TTreeSRedirector(fgkDebugStreamFileName); | |
438 | DumpTrack(seed); | |
439 | } | |
440 | ||
441 | void AliTPCcalibTracksGain::AddCluster(AliTPCclusterMI* cluster, Float_t momenta, Float_t mdedx, Int_t padType, | |
442 | Float_t xcenter, TVectorD dedxQ, TVectorD dedxM, Float_t fraction, Float_t fraction2, Float_t dedge, | |
443 | TVectorD parY, TVectorD parZ, TVectorD meanPos) { | |
444 | // | |
445 | // Adds cluster to the appropriate fitter for later analysis. | |
446 | // The charge used for the fit is the maximum charge for this specific cluster or the | |
447 | // accumulated charge per cluster, depending on the value of fgkUseTotalCharge. | |
448 | // Depending on the pad size where the cluster is registered, the value will be put in | |
449 | // the appropriate fitter. Furthermore, for each pad size three different types of fitters | |
450 | // are used. The fit functions are the same for all fitters (parabolic functions), but the value | |
451 | // added to each fitter is different. The simple fitter gets the charge plugged in as is, the sqrt fitter | |
452 | // gets the square root of the charge, and the log fitter gets fgkM*(1+q/fgkM), where q is the original charge | |
453 | // and fgkM==25. | |
454 | // | |
455 | ||
456 | if (!cluster) { | |
457 | Error("AddCluster", "Cluster not valid."); | |
458 | return; | |
459 | } | |
460 | ||
461 | if (dedge < 3.) return; | |
462 | if (fraction2 > 0.7) return; | |
463 | ||
464 | //Int_t padType = GetPadType(cluster->GetX()); | |
465 | Double_t xx[7]; | |
466 | //Double_t centerPad[2] = {0}; | |
467 | //AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad); | |
468 | //xx[0] = cluster->GetX() - centerPad[0]; | |
469 | //xx[1] = cluster->GetY() - centerPad[1]; | |
470 | xx[0] = cluster->GetX() - xcenter; | |
471 | xx[1] = cluster->GetY(); | |
472 | xx[2] = xx[0] * xx[0]; | |
473 | xx[3] = xx[1] * xx[1]; | |
474 | xx[4] = xx[0] * xx[1]; | |
475 | xx[5] = TMath::Abs(cluster->GetZ()) - TMath::Abs(meanPos[4]); | |
476 | xx[6] = xx[5] * xx[5]; | |
477 | ||
478 | Int_t segment = cluster->GetDetector() % 36; | |
479 | Double_t q = fgkUseTotalCharge ? ((Double_t)(cluster->GetQ())) : ((Double_t)(cluster->GetMax())); // note: no normalization to pad size! | |
480 | ||
481 | // just for debugging | |
482 | Int_t row = 0; | |
483 | Int_t pad = 0; | |
484 | GetRowPad(cluster->GetX(), cluster->GetY(), row, pad); | |
485 | fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->GetValue(row, pad)); | |
486 | ||
487 | // correct charge by normalising to mean charge per track | |
488 | q /= dedxQ[2]; | |
489 | ||
490 | // just for debugging | |
491 | fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->GetValue(row, pad)); | |
492 | ||
493 | Double_t sqrtQ = TMath::Sqrt(q); | |
494 | Double_t logQ = fgkM * TMath::Log(1 + q / fgkM); | |
495 | fSimpleFitter->GetFitter(segment, padType)->AddPoint(xx, q); | |
496 | fSqrtFitter->GetFitter(segment, padType)->AddPoint(xx, sqrtQ); | |
497 | fLogFitter->GetFitter(segment, padType)->AddPoint(xx, logQ); | |
498 | fSingleSectorFitter->GetFitter(0, padType)->AddPoint(xx, q); | |
499 | ||
500 | // this will be gone for the a new ROOT version > v5-17-05 | |
501 | if (padType == kShortPads) | |
502 | fNShortClusters[segment]++; | |
503 | else if (padType == kMediumPads) | |
504 | fNMediumClusters[segment]++; | |
505 | else if (padType == kLongPads) | |
506 | fNLongClusters[segment]++; | |
507 | } | |
508 | ||
509 | void AliTPCcalibTracksGain::Evaluate(Bool_t robust, Double_t frac) { | |
510 | // | |
511 | // Evaluates all fitters contained in this object. | |
512 | // If the robust option is set to kTRUE a robust fit is performed with frac as | |
513 | // the minimal fraction of good points (see TLinearFitter::EvalRobust for details). | |
514 | // Beware: Robust fitting is much slower! | |
515 | // | |
516 | ||
517 | fSimpleFitter->Evaluate(robust, frac); | |
518 | fSqrtFitter->Evaluate(robust, frac); | |
519 | fLogFitter->Evaluate(robust, frac); | |
520 | fSingleSectorFitter->Evaluate(robust, frac); | |
521 | } | |
522 | ||
523 | AliTPCCalPad* AliTPCcalibTracksGain::CreateFitCalPad(UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) { | |
524 | // | |
525 | // Creates the calibration object AliTPCcalPad using fitted parameterization | |
526 | // | |
527 | TObjArray tpc(72); | |
528 | for (UInt_t iSector = 0; iSector < 72; iSector++) | |
529 | tpc.Add(CreateFitCalROC(iSector, fitType, undoTransformation, normalizeToPadSize)); | |
530 | return new AliTPCCalPad(&tpc); | |
531 | } | |
532 | ||
533 | AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) { | |
534 | // | |
535 | // Create the AliTPCCalROC with the values per pad | |
536 | // sector - sector of interest | |
537 | // fitType - | |
538 | // | |
539 | ||
540 | TVectorD par(8); | |
541 | if (sector < 36) { | |
542 | GetParameters(sector % 36, 0, fitType, par); | |
543 | return CreateFitCalROC(sector, 0, par, fitType, undoTransformation, normalizeToPadSize); | |
544 | } | |
545 | else { | |
546 | GetParameters(sector % 36, 1, fitType, par); | |
547 | AliTPCCalROC* roc1 = CreateFitCalROC(sector, 1, par, fitType, undoTransformation, normalizeToPadSize); | |
548 | GetParameters(sector % 36, 2, fitType, par); | |
549 | AliTPCCalROC* roc2 = CreateFitCalROC(sector, 2, par, fitType, undoTransformation, normalizeToPadSize); | |
550 | AliTPCCalROC* roc3 = CreateCombinedCalROC(roc1, roc2); | |
551 | delete roc1; | |
552 | delete roc2; | |
553 | return roc3; | |
554 | } | |
555 | } | |
556 | ||
557 | AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t padType, TVectorD &fitParam, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) { | |
558 | // | |
559 | // This function is essentially a copy of AliTPCCalROC::CreateGlobalFitCalROC(...), with the | |
560 | // modifications, that the center of the region of same pad size is used as the origin | |
561 | // of the fit function instead of the center of the ROC. | |
562 | // The possibility of a linear fit is removed as well because it is not needed. | |
563 | // Only values for pads with the given pad size are calculated, the rest is 0. | |
564 | // Set undoTransformation for undoing the transformation that was applied to the | |
565 | // charge values before they were put into the fitter (thus allowing comparison to the original | |
566 | // charge values). For fitType use 0 for the simple fitter, 1 for the sqrt fitter, 2 for the log fitter. | |
567 | // If normalizeToPadSize is true, the values are normalized to the pad size. | |
568 | // Please be aware, that you even need to specify the fitType if you want to normalize to the pad size without | |
569 | // undoing the transformation (because normalizing involves undoing the trafo first, then normalizing, then | |
570 | // applying the trafo again). | |
571 | // Please note: The normalization to the pad size is a simple linear scaling with the pad length, which | |
572 | // actually doesn't describe reality! | |
573 | // | |
574 | ||
575 | Float_t dlx, dly; | |
576 | Double_t centerPad[2] = {0}; | |
577 | Float_t localXY[3] = {0}; | |
578 | AliTPCROC* tpcROC = AliTPCROC::Instance(); | |
579 | if ((padType == 0 && sector >= tpcROC->GetNInnerSector()) || (padType > 0 && sector < tpcROC->GetNInnerSector()) || sector >= tpcROC->GetNSector()) | |
580 | return 0; | |
581 | AliTPCCalROC* lROCfitted = new AliTPCCalROC(sector); | |
582 | //tpcROC->GetPositionLocal(sector, lROCfitted->GetNrows()/2, lROCfitted->GetNPads(lROCfitted->GetNrows()/2)/2, centerPad); // use this instead of the switch statement if you want to calculate the center of the ROC and not the center of the regions with the same pad size | |
583 | UInt_t startRow = 0; | |
584 | UInt_t endRow = 0; | |
585 | switch (padType) { | |
586 | case kShortPads: | |
587 | startRow = 0; | |
588 | endRow = lROCfitted->GetNrows(); | |
589 | break; | |
590 | case kMediumPads: | |
591 | startRow = 0; | |
592 | endRow = 64; | |
593 | break; | |
594 | case kLongPads: | |
595 | startRow = 64; | |
596 | endRow = lROCfitted->GetNrows(); | |
597 | break; | |
598 | } | |
599 | ||
600 | AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad); | |
601 | Double_t value = 0; | |
602 | for (UInt_t irow = startRow; irow < endRow; irow++) { | |
603 | for (UInt_t ipad = 0; ipad < lROCfitted->GetNPads(irow); ipad++) { | |
604 | tpcROC->GetPositionLocal(sector, irow, ipad, localXY); // calculate position localXY by pad and row number | |
605 | dlx = localXY[0] - centerPad[0]; | |
606 | dly = localXY[1] - centerPad[1]; | |
607 | value = fitParam[0] + fitParam[1]*dlx + fitParam[2]*dly + fitParam[3]*dlx*dlx + fitParam[4]*dly*dly + fitParam[5]*dlx*dly; | |
608 | ||
609 | // Let q' = value be the transformed value without any pad size corrections, | |
610 | // let T be the transformation and let l be the pad size | |
611 | // 1) don't undo transformation, don't normalize: return q' | |
612 | // 2) undo transformation, don't normalize: return T^{-1} q' | |
613 | // 3) undo transformation, normalize: return (T^{-1} q') / l | |
614 | // 4) don't undo transformation, normalize: return T((T^{-1} q') / l) | |
615 | if (!undoTransformation && !normalizeToPadSize) {/* value remains unchanged */} // (1) | |
616 | else { // (2), (3), (4) | |
617 | //calculate T^{-1} | |
618 | switch (fitType) { | |
619 | case 0: /* value remains unchanged */ break; | |
620 | case 1: value = value * value; break; | |
621 | case 2: value = (TMath::Exp(value / fgkM) - 1) * fgkM; break; | |
622 | default: Error("CreateFitCalROC", "Wrong fit type."); break; | |
623 | } | |
624 | if (normalizeToPadSize) value /= GetPadLength(localXY[0]); // (3) | |
625 | } | |
626 | if (!undoTransformation && normalizeToPadSize) { // (4) | |
627 | // calculate T | |
628 | switch (fitType) { | |
629 | case 0: /* value remains unchanged */ break; | |
630 | case 1: value = TMath::Sqrt(value); break; | |
631 | case 2: value = fgkM * TMath::Log(1 + value / fgkM); break; | |
632 | default: Error("CreateFitCalROC", "Wrong fit type."); break; | |
633 | } | |
634 | } | |
635 | lROCfitted->SetValue(irow, ipad, value); | |
636 | } | |
637 | } | |
638 | return lROCfitted; | |
639 | } | |
640 | ||
641 | AliTPCCalROC* AliTPCcalibTracksGain::CreateCombinedCalROC(const AliTPCCalROC* roc1, const AliTPCCalROC* roc2) { | |
642 | // | |
643 | // Combines the medium pad size values of roc1 with the long pad size values of roc2 into a new | |
644 | // AliTPCCalROC. Returns a null pointer if any one of the ROCs is an IROC; issues a warning message | |
645 | // if the sectors of roc1 and roc2 don't match, but still continue and use the sector of roc1 as the | |
646 | // sector of the new ROC. | |
647 | // | |
648 | ||
649 | if (!roc1 || !roc2) return 0; | |
650 | if ((Int_t)(roc1->GetSector()) < fgTPCparam->GetNInnerSector()) return 0; | |
651 | if ((Int_t)(roc2->GetSector()) < fgTPCparam->GetNInnerSector()) return 0; | |
652 | if (roc1->GetSector() != roc2->GetSector()) Warning("CreateCombinedCalROC", "Sector number mismatch."); | |
653 | AliTPCCalROC* roc = new AliTPCCalROC(roc1->GetSector()); | |
654 | ||
655 | for (UInt_t iRow = 0; iRow < 64; iRow++) { | |
656 | for (UInt_t iPad = 0; iPad < roc->GetNPads(iRow); iPad++) | |
657 | roc->SetValue(iRow, iPad, roc1->GetValue(iRow, iPad)); | |
658 | } | |
659 | for (UInt_t iRow = 64; iRow < roc->GetNrows(); iRow++) { | |
660 | for (UInt_t iPad = 0; iPad < roc->GetNPads(iRow); iPad++) | |
661 | roc->SetValue(iRow, iPad, roc2->GetValue(iRow, iPad)); | |
662 | } | |
663 | return roc; | |
664 | } | |
665 | ||
666 | void AliTPCcalibTracksGain::GetParameters(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitParam) { | |
667 | // | |
668 | // Puts the fit parameters for the specified segment (IROC & OROC), padType and fitType | |
669 | // into the fitParam TVectorD (which should contain 8 elements). | |
670 | // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter. | |
671 | // Note: The fitter has to be evaluated first! | |
672 | // | |
673 | ||
674 | GetFitter(segment, padType, fitType)->GetParameters(fitParam); | |
675 | } | |
676 | ||
677 | void AliTPCcalibTracksGain::GetErrors(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitError) { | |
678 | // | |
679 | // Puts the fit parameter errors for the specified segment (IROC & OROC), padType and fitType | |
680 | // into the fitError TVectorD (which should contain 8 elements). | |
681 | // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter. | |
682 | // Note: The fitter has to be evaluated first! | |
683 | // | |
684 | ||
685 | GetFitter(segment, padType, fitType)->GetErrors(fitError); | |
686 | fitError *= TMath::Sqrt(GetRedChi2(segment, padType, fitType)); | |
687 | } | |
688 | ||
689 | Double_t AliTPCcalibTracksGain::GetRedChi2(UInt_t segment, UInt_t padType, UInt_t fitType) { | |
690 | // | |
691 | // Returns the reduced chi^2 value for the specified segment, padType and fitType. | |
692 | // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter. | |
693 | // Note: The fitter has to be evaluated first! | |
694 | // | |
695 | ||
696 | // this will be gone for the a new ROOT version > v5-17-05 | |
697 | Int_t lNClusters = 0; | |
698 | switch (padType) { | |
699 | case kShortPads: | |
700 | lNClusters = fNShortClusters[segment]; | |
701 | break; | |
702 | case kMediumPads: | |
703 | lNClusters = fNMediumClusters[segment]; | |
704 | break; | |
705 | case kLongPads: | |
706 | lNClusters = fNLongClusters[segment]; | |
707 | break; | |
708 | } | |
709 | return GetFitter(segment, padType, fitType)->GetChisquare()/(lNClusters - 8); | |
710 | } | |
711 | ||
712 | void AliTPCcalibTracksGain::GetCovarianceMatrix(UInt_t segment, UInt_t padType, UInt_t fitType, TMatrixD& covMatrix) { | |
713 | // | |
714 | // Returns the covariance matrix for the specified segment, padType, fitType. | |
715 | // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter. | |
716 | // | |
717 | ||
718 | GetFitter(segment, padType, fitType)->GetCovarianceMatrix(covMatrix); | |
719 | } | |
720 | ||
721 | TLinearFitter* AliTPCcalibTracksGain::GetFitter(UInt_t segment, UInt_t padType, UInt_t fitType) { | |
722 | // | |
723 | // Returns the TLinearFitter object for the specified segment, padType, fitType. | |
724 | // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter. | |
725 | // | |
726 | ||
727 | switch (fitType) { | |
728 | case kSimpleFitter: | |
729 | return fSimpleFitter->GetFitter(segment, padType); | |
730 | case kSqrtFitter: | |
731 | return fSqrtFitter->GetFitter(segment, padType); | |
732 | case kLogFitter: | |
733 | return fLogFitter->GetFitter(segment, padType); | |
734 | case 3: | |
735 | return fSingleSectorFitter->GetFitter(0, padType); | |
736 | } | |
737 | return 0; | |
738 | } | |
739 | ||
740 | Double_t AliTPCcalibTracksGain::GetPadLength(Double_t lx) { | |
741 | // | |
742 | // The function returns 0.75 for an IROC, 1. for an OROC at medium pad size position, | |
743 | // 1.5 for an OROC at long pad size position, -1 if out of bounds. | |
744 | // | |
745 | ||
746 | Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2; | |
747 | Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2; | |
748 | Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2; | |
749 | Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2; | |
750 | Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2; | |
751 | Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2; | |
752 | ||
753 | // if IROC | |
754 | if (lx >= irocLow && lx <= irocUp) return 0.75; | |
755 | // if OROC medium pads | |
756 | if (lx >= orocLow1 && lx <= orocUp1) return 1.; | |
757 | // if OROC long pads | |
758 | if (lx >= orocLow2 && lx <= orocUp2) return 1.5; | |
759 | // if out of bounds | |
760 | return -1; | |
761 | } | |
762 | ||
763 | Int_t AliTPCcalibTracksGain::GetPadType(Double_t lx) { | |
764 | // | |
765 | // The function returns 0 for an IROC, 1 for an OROC at medium pad size position, | |
766 | // 2 for an OROC at long pad size position, -1 if out of bounds. | |
767 | // | |
768 | ||
769 | if (GetPadLength(lx) == 0.75) return 0; | |
770 | else if (GetPadLength(lx) == 1.) return 1; | |
771 | else if (GetPadLength(lx) == 1.5) return 2; | |
772 | return -1; | |
773 | } | |
774 | ||
775 | // ONLY FOR DEBUGGING PURPOSES - REMOVE ME WHEN NOT NEEDED ANYMORE | |
776 | Bool_t AliTPCcalibTracksGain::GetRowPad(Double_t lx, Double_t ly, Int_t& row, Int_t& pad) { | |
777 | // | |
778 | // Calculate the row and pad number when the local coordinates are given. | |
779 | // Returns kFALSE if the position is out of range, otherwise return kTRUE. | |
780 | // WARNING: This function is preliminary and probably isn't very accurate!! | |
781 | // | |
782 | ||
783 | Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2; | |
784 | //Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2; | |
785 | Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2; | |
786 | //Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2; | |
787 | Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2; | |
788 | //Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2; | |
789 | ||
790 | if (GetPadType(lx) == 0) { | |
791 | row = (Int_t)((lx - irocLow) / fgTPCparam->GetInnerPadPitchLength()); | |
792 | pad = (Int_t)((ly + fgTPCparam->GetYInner(row)) / fgTPCparam->GetInnerPadPitchWidth()); | |
793 | } else if (GetPadType(lx) == 1) { | |
794 | row = (Int_t)((lx - orocLow1) / fgTPCparam->GetOuter1PadPitchLength()); | |
795 | pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth()); | |
796 | } else if (GetPadType(lx) == 2) { | |
797 | row = fgTPCparam->GetNRowUp1() + (Int_t)((lx - orocLow2) / fgTPCparam->GetOuter2PadPitchLength()); | |
798 | pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth()); | |
799 | } | |
800 | else return kFALSE; | |
801 | return kTRUE; | |
802 | } | |
803 | ||
804 | void AliTPCcalibTracksGain::DumpTrack(AliTPCseed* track) { | |
805 | // | |
806 | // Dump track information to the debug stream | |
807 | // | |
808 | ||
809 | (*fDebugStream) << "Track" << | |
810 | "Track.=" << track << // track information | |
811 | "\n"; | |
812 | Int_t rows[200]; | |
813 | for (Int_t ipad = 0; ipad < 3; ipad++) { | |
814 | GetDedx(track, ipad, rows); | |
815 | } | |
816 | } | |
817 | ||
818 | Bool_t AliTPCcalibTracksGain::GetDedx(AliTPCseed* track, Int_t padType, Int_t* rows) { | |
819 | // | |
820 | // GetDedx for given sector for given track | |
821 | // padType - type of pads | |
822 | // | |
823 | ||
824 | Int_t firstRow = 0, lastRow = 0; | |
825 | Int_t minRow = 100; | |
826 | Float_t xcenter = 0; | |
827 | const Float_t ktany = TMath::Tan(TMath::DegToRad() * 10); | |
828 | const Float_t kedgey = 4.; | |
829 | if (padType == 0) { | |
830 | firstRow = 0; | |
831 | lastRow = fgTPCparam->GetNRowLow(); | |
832 | xcenter = 108.47; | |
833 | } | |
834 | if (padType == 1) { | |
835 | firstRow = fgTPCparam->GetNRowLow(); | |
836 | lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1(); | |
837 | xcenter = 166.60; | |
838 | } | |
839 | if (padType == 2) { | |
840 | firstRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1(); | |
841 | lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp(); | |
842 | xcenter = 222.6; | |
843 | } | |
844 | minRow = (lastRow - firstRow) / 2; | |
845 | // | |
846 | // | |
847 | Int_t nclusters = 0; | |
848 | Int_t nclustersNE = 0; // number of not edge clusters | |
849 | Int_t lastSector = -1; | |
850 | Float_t amplitudeQ[100]; | |
851 | Float_t amplitudeM[100]; | |
852 | Int_t rowIn[100]; | |
853 | Int_t index[100]; | |
854 | // | |
855 | static TLinearFitter fitY(2, "pol1"); | |
856 | static TLinearFitter fitZ(2, "pol1"); | |
857 | static TVectorD parY(2); | |
858 | static TVectorD parZ(2); | |
859 | fitY.ClearPoints(); | |
860 | fitZ.ClearPoints(); | |
861 | TVectorD meanPos(6); | |
862 | ||
863 | for (Int_t iCluster = firstRow; iCluster < lastRow; iCluster++) { | |
864 | AliTPCclusterMI* cluster = track->GetClusterPointer(iCluster); | |
865 | if (cluster) { | |
866 | Int_t detector = cluster->GetDetector() ; | |
867 | if (lastSector == -1) lastSector = detector; | |
868 | if (lastSector != detector) continue; | |
869 | amplitudeQ[nclusters] = cluster->GetQ(); | |
870 | amplitudeM[nclusters] = cluster->GetMax(); | |
871 | rowIn[nclusters] = iCluster; | |
872 | nclusters++; | |
873 | Double_t dx = cluster->GetX() - xcenter; | |
874 | Double_t y = cluster->GetY(); | |
875 | Double_t z = cluster->GetZ(); | |
876 | fitY.AddPoint(&dx, y); | |
877 | fitZ.AddPoint(&dx, z); | |
878 | meanPos[0] += dx; | |
879 | meanPos[1] += dx; | |
880 | meanPos[2] += y; | |
881 | meanPos[3] += y*y; | |
882 | meanPos[4] += z; | |
883 | meanPos[5] += z*z; | |
884 | if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) nclustersNE++; | |
885 | } | |
886 | } | |
887 | ||
888 | if (nclusters < minRow / 2) return kFALSE; | |
889 | if (nclustersNE < minRow / 2) return kFALSE; | |
890 | for (Int_t i = 0; i < 6; i++) meanPos[i] /= Double_t(nclusters); | |
891 | fitY.Eval(); | |
892 | fitZ.Eval(); | |
893 | fitY.GetParameters(parY); | |
894 | fitZ.GetParameters(parZ); | |
895 | // | |
896 | // calculate truncated mean | |
897 | // | |
898 | TMath::Sort(nclusters, amplitudeQ, index, kFALSE); | |
899 | ||
900 | TVectorD dedxQ(5); | |
901 | TVectorD dedxM(5); | |
902 | Float_t ndedx[5]; | |
903 | for (Int_t i = 0; i < 5; i++) { | |
904 | dedxQ[i] = 0; | |
905 | dedxM[i] = 0; | |
906 | ndedx[i] = 0; | |
907 | } | |
908 | // | |
909 | // dedx calculation | |
910 | // | |
911 | Int_t inonEdge = 0; | |
912 | for (Int_t i = 0; i < nclusters; i++) { | |
913 | Int_t rowSorted = rowIn[index[i]]; | |
914 | AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted); | |
915 | ||
916 | if (TMath::Abs(cluster->GetY()) > cluster->GetX()*ktany - kedgey) continue; //don't take edge clusters | |
917 | inonEdge++; | |
918 | if (inonEdge < nclustersNE * 0.5) { | |
919 | ndedx[0]++; | |
920 | dedxQ[0] += amplitudeQ[index[i]]; | |
921 | dedxM[0] += amplitudeM[index[i]]; | |
922 | } | |
923 | if (inonEdge < nclustersNE * 0.6) { | |
924 | ndedx[1]++; | |
925 | dedxQ[1] += amplitudeQ[index[i]]; | |
926 | dedxM[1] += amplitudeM[index[i]]; | |
927 | } | |
928 | if (inonEdge < nclustersNE * 0.7) { | |
929 | ndedx[2]++; | |
930 | dedxQ[2] += amplitudeQ[index[i]]; | |
931 | dedxM[2] += amplitudeM[index[i]]; | |
932 | } | |
933 | if (inonEdge < nclustersNE * 0.8) { | |
934 | ndedx[3]++; | |
935 | dedxQ[3] += amplitudeQ[index[i]]; | |
936 | dedxM[3] += amplitudeM[index[i]]; | |
937 | } | |
938 | if (inonEdge < nclustersNE * 0.9) { | |
939 | ndedx[4]++; | |
940 | dedxQ[4] += amplitudeQ[index[i]]; | |
941 | dedxM[4] += amplitudeM[index[i]]; | |
942 | } | |
943 | } | |
944 | for (Int_t i = 0; i < 5; i++) { | |
945 | dedxQ[i] /= ndedx[i]; | |
946 | dedxM[i] /= ndedx[i]; | |
947 | } | |
948 | ||
949 | inonEdge = 0; | |
950 | for (Int_t i = 0; i < nclusters; i++) { | |
951 | Int_t rowSorted = rowIn[index[i]]; | |
952 | AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted); | |
953 | if (!cluster) { | |
954 | printf("Problem\n"); | |
955 | continue; | |
956 | } | |
957 | if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) inonEdge++; | |
958 | Float_t dedge = cluster->GetX()*ktany - TMath::Abs(cluster->GetY()); | |
959 | Float_t fraction = Float_t(i) / Float_t(nclusters); | |
960 | Float_t fraction2 = Float_t(inonEdge) / Float_t(nclustersNE); | |
961 | Float_t momenta = track->GetP(); | |
962 | Float_t mdedx = track->GetdEdx(); | |
963 | ||
964 | AddCluster(cluster, momenta, mdedx, padType, xcenter, dedxQ, dedxM, fraction, fraction2, dedge, parY, parZ, meanPos); | |
965 | ||
966 | (*fDebugStream) << "dEdx" << | |
967 | "Cl.=" << cluster << // cluster of interest | |
968 | "P=" << momenta << // track momenta | |
969 | "dedx=" << mdedx << // mean dedx - corrected for angle | |
970 | "IPad=" << padType << // pad type 0..2 | |
971 | "xc=" << xcenter << // x center of chamber | |
972 | "dedxQ.=" << &dedxQ << // dedxQ - total charge | |
973 | "dedxM.=" << &dedxM << // dedxM - maximal charge | |
974 | "fraction=" << fraction << // fraction - order in statistic (0,1) | |
975 | "fraction2=" << fraction2 << // fraction - order in statistic (0,1) | |
976 | "dedge=" << dedge << // distance to the edge | |
977 | "parY.=" << &parY << // line fit | |
978 | "parZ.=" << &parZ << // line fit | |
979 | "meanPos.=" << &meanPos << // mean position (dx, dx^2, y,y^2, z, z^2) | |
980 | "\n"; | |
981 | } | |
982 | return kTRUE; | |
983 | } |