1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 ////////////////////////////////////////////////////////////////////////////
18 // === Calibration class for gain calibration using tracks ===
22 // A 6-parametric parabolic function
24 // G(x, y) = p0 + p1*x + p2*y + p3*x^2 + p4*y^2 + p5 * x*y
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.
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:
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
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.
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.
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.
68 // The visualization methods CreateFitCalPad() and CreateFitCalROC()
69 // are straight forward to use.
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)
78 ////////////////////////////////////////////////////////////////////////////
83 #include "TTreeStream.h"
85 #include "AliTPCParamSR.h"
86 #include "AliTPCClusterParam.h"
87 #include "AliTrackPointArray.h"
89 #include "AliTPCcalibTracksGain.h"
92 #include <TLinearFitter.h>
93 #include <TTreeStream.h>
95 #include <TCollection.h>
96 #include <TIterator.h>
102 #include "AliMathBase.h"
104 #include "AliTPCROC.h"
105 #include "AliTPCParamSR.h"
106 #include "AliTPCCalROC.h"
107 #include "AliTPCCalPad.h"
109 #include "AliTracker.h"
111 #include "AliESDtrack.h"
112 #include "AliESDfriend.h"
113 #include "AliESDfriendTrack.h"
114 #include "AliTPCseed.h"
115 #include "AliTPCclusterMI.h"
116 #include "AliTPCcalibTracksCuts.h"
117 #include "AliTPCFitPad.h"
119 // REMOVE ALL OF THIS
121 #include "AliESDEvent.h"
125 TFile f("TPCCalibTracksGain.root")
127 gSystem->Load("libPWG1.so")
133 TString * str = comp.FitPlane("Cl.fQ/dedxQ.fElements[0]","Cl.fY++Cl.fX","Cl.fDetector<36",chi2,vec,mat)
137 ClassImp(AliTPCcalibTracksGain)
139 const Bool_t AliTPCcalibTracksGain::fgkUseTotalCharge = kTRUE;
140 const Double_t AliTPCcalibTracksGain::fgkM = 25.;
141 const char* AliTPCcalibTracksGain::fgkDebugStreamFileName = "TPCCalibTracksGain.root";
142 AliTPCParamSR* AliTPCcalibTracksGain::fgTPCparam = new AliTPCParamSR();
144 AliTPCcalibTracksGain::AliTPCcalibTracksGain() :
157 // Default constructor.
161 AliTPCcalibTracksGain::AliTPCcalibTracksGain(const AliTPCcalibTracksGain& obj) :
168 fDebugCalPadRaw = new AliTPCCalPad(*(obj.fDebugCalPadRaw));
169 fDebugCalPadCorr = new AliTPCCalPad(*(obj.fDebugCalPadCorr));
170 fSimpleFitter = new AliTPCFitPad(*(obj.fSimpleFitter));
171 fSqrtFitter = new AliTPCFitPad(*(obj.fSqrtFitter));
172 fLogFitter = new AliTPCFitPad(*(obj.fLogFitter));
173 fZFitter = new TLinearFitter(*(obj.fZFitter));
174 fPrevIter = new AliTPCcalibTracksGain(*(obj.fPrevIter));
175 fCuts = new AliTPCcalibTracksCuts(*(obj.fCuts));
178 AliTPCcalibTracksGain& AliTPCcalibTracksGain::operator=(const AliTPCcalibTracksGain& rhs) {
180 // Assignment operator.
184 TNamed::operator=(rhs);
185 fDebugCalPadRaw = new AliTPCCalPad(*(rhs.fDebugCalPadRaw));
186 fDebugCalPadCorr = new AliTPCCalPad(*(rhs.fDebugCalPadCorr));
187 fSimpleFitter = new AliTPCFitPad(*(rhs.fSimpleFitter));
188 fSqrtFitter = new AliTPCFitPad(*(rhs.fSqrtFitter));
189 fLogFitter = new AliTPCFitPad(*(rhs.fLogFitter));
190 fZFitter = new TLinearFitter(*(rhs.fZFitter));
191 fPrevIter = new AliTPCcalibTracksGain(*(rhs.fPrevIter));
192 fCuts = new AliTPCcalibTracksCuts(*(rhs.fCuts));
197 AliTPCcalibTracksGain::AliTPCcalibTracksGain(const char* name, const char* title, AliTPCcalibTracksCuts* cuts, AliTPCcalibTracksGain* prevIter) :
213 //TH1::AddDirectory(kFALSE);
214 G__SetCatchException(0);
217 fPrevIter = prevIter;
219 fSimpleFitter = new AliTPCFitPad(6, "hyp5", "");
220 fSqrtFitter = new AliTPCFitPad(6, "hyp5", "");
221 fLogFitter = new AliTPCFitPad(6, "hyp5", "");
223 fZFitter = new TLinearFitter(2, "hyp1", "");
224 // workaround for TLinearFitter
225 Double_t workaround = 3.141592;
226 fZFitter->AddPoint(&workaround, 31.41592);
227 fZFitter->ClearPoints();
229 // just for debugging
232 fDebugCalPadRaw = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction");
233 fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction");
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;
243 AliTPCcalibTracksGain::~AliTPCcalibTracksGain() {
248 if (fSimpleFitter) delete fSimpleFitter;
249 if (fSqrtFitter) delete fSqrtFitter;
250 if (fLogFitter) delete fLogFitter;
252 if (fZFitter) delete fZFitter;
255 //fDebugStream->GetFile()->Close();
256 printf("Deleting debug stream object\n");
260 if (fDebugCalPadRaw) delete fDebugCalPadRaw;
261 if (fDebugCalPadCorr) delete fDebugCalPadCorr;
264 void AliTPCcalibTracksGain::AddInfo(TChain* chain, char* fileName) {
266 // Add some parameters from a previous run (AliTPCcalibTracksGain object contained
267 // in root file fileName) to the chain.
268 // Note: The parameters are *not* added to this class, you need to do it later by retrieving
269 // the parameters from the chain and passing them to the constructor!
272 TFile paramFile(fileName);
273 if (paramFile.IsZombie()) {
274 printf("File %s not found. Continuing without z dependence parametrisation.\n", fileName);
278 AliTPCcalibTracksGain *prevIter = (AliTPCcalibTracksGain*)paramFile.Get("calibTracksGain");
280 //TVectorD* param = new TVectorD(2);
281 //prevIter->fZFitter->GetParameters(*param);
282 //chain->GetUserInfo()->AddLast((TObject*)param);
283 chain->GetUserInfo()->AddLast((TObject*)prevIter);
285 printf("No calibTracksGain object found. Continuing without z dependence parametrisation.\n");
288 Int_t AliTPCcalibTracksGain::AcceptTrack(AliTPCseed* track) {
290 // Decides whether to accept a track or not.
291 // Tracks are discarded, if due to edge effects, the number of clusters
292 // is too low, the ratio of the number of clusters and the findable clusters is too low
293 // or the transverse momentum is too low.
294 // The corresponding cut values are specified in the fCuts member.
297 if (track->GetNumberOfClusters() < fCuts->GetMinClusters()) return 1;
298 if ((TMath::Abs(track->GetY() / track->GetX()) > fCuts->GetEdgeYXCutNoise())
299 && (TMath::Abs(track->GetTgl()) < fCuts->GetEdgeThetaCutNoise())) return 2;
300 if (track->GetNumberOfClusters() / (track->GetNFoundable()+1.) < fCuts->GetMinRatio()) return 3;
301 if (TMath::Abs(track->GetSigned1Pt()) > fCuts->GetMax1pt()) return 4;
303 //if (track->GetPt() < 50.) return kFALSE;
307 /*Bool_t AliTPCcalibTracksGain::AcceptCluster(AliTPCclusterMI* cluster) {
309 // Decides whether to accept a cluster or not.
312 // cluster type < 0: edge cluster
313 // cluster type = 0: "golden" (i.e. good) cluster
314 // cluster type > 0: overlapping cluster
315 if (cluster->GetType() != 0) { Info("AcceptCluster", "Cluster not accepted (type %d)", cluster->GetType()); return kFALSE;}
317 // remove edge clusters
323 void AliTPCcalibTracksGain::Process(AliTPCseed* seed) {
325 // Main method to be called when a new seed is supposed to be processed
326 // and be used for gain calibration. Its quality is checked before it
331 //fTrackPt->Fill(seed->GetSignedPt());
332 Int_t status = AcceptTrack(seed);
333 if (status != 0) { /*cout << "Track not accepted (reason " << status << ")" << endl;*/ return; }
338 Long64_t AliTPCcalibTracksGain::Merge(TCollection *list) {
340 // Merge() merges the results of all AliTPCcalibTracksGain objects contained in
341 // list, thus allowing a distributed computation of several files, e.g. on PROOF.
342 // The merged results are stored in the data members of the AliTPCcalibTracksGain
343 // object used for calling the Merge method.
344 // The return value is 0 /*the total number of tracks used for calibration*/ if the merge
345 // is successful, otherwise it is -1.
348 if (!list || list->IsEmpty()) return -1;
350 // reset the data members first
351 if (fSimpleFitter) delete fSimpleFitter;
352 if (fSqrtFitter) delete fSqrtFitter;
353 if (fLogFitter) delete fLogFitter;
354 if (fZFitter) delete fZFitter;
355 fSimpleFitter = new AliTPCFitPad(6, "hyp5", "");
356 fSqrtFitter = new AliTPCFitPad(6, "hyp5", "");
357 fLogFitter = new AliTPCFitPad(6, "hyp5", "");
358 fZFitter = new TLinearFitter(2, "hyp1", "");
359 // workaround for TLinearFitter
360 Double_t workaround = 3.141592;
361 fZFitter->AddPoint(&workaround, 31.41592);
362 fZFitter->ClearPoints();
364 // this will be gone for the a new ROOT version > v5-17-05
365 for (UInt_t i = 0; i < 36; i++) {
366 fNShortClusters[i] = 0;
367 fNMediumClusters[i] = 0;
368 fNLongClusters[i] = 0;
371 // just for debugging
372 if (fDebugCalPadRaw) delete fDebugCalPadRaw;
373 if (fDebugCalPadCorr) delete fDebugCalPadCorr;
374 fDebugCalPadRaw = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction");
375 fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction");
379 TIterator* iter = list->MakeIterator();
380 AliTPCcalibTracksGain* cal = 0;
382 while ((cal = (AliTPCcalibTracksGain*)iter->Next())) {
383 if (!cal->InheritsFrom(AliTPCcalibTracksGain::Class())) {
384 Error("Merge","Attempt to add object of class %s to a %s", cal->ClassName(), this->ClassName());
392 void AliTPCcalibTracksGain::Add(AliTPCcalibTracksGain* cal) {
394 // Adds another AliTPCcalibTracksGain object to this object.
397 fSimpleFitter->Add(cal->fSimpleFitter);
398 fSqrtFitter->Add(cal->fSqrtFitter);
399 fLogFitter->Add(cal->fLogFitter);
400 fZFitter->Add(cal->fZFitter);
402 // this will be gone for the a new ROOT version > v5-17-05
403 for (UInt_t iSegment = 0; iSegment < 36; iSegment++) {
404 fNShortClusters[iSegment] += cal->fNShortClusters[iSegment];
405 fNMediumClusters[iSegment] += cal->fNMediumClusters[iSegment];
406 fNLongClusters[iSegment] += cal->fNLongClusters[iSegment];
409 // just for debugging, remove me
410 fTotalTracks += cal->fTotalTracks;
411 fAcceptedTracks += cal->fAcceptedTracks;
412 fDebugCalPadRaw->Add(cal->fDebugCalPadRaw);
413 fDebugCalPadCorr->Add(cal->fDebugCalPadCorr);
415 // Let's see later what to do with fCuts and fDebugStream
418 void AliTPCcalibTracksGain::AddTrack(AliTPCseed* seed) {
420 // The clusters making up the track (seed) are added to various fit functions.
421 // See AddCluster(...) for more detail.
424 if (!fDebugStream) fDebugStream = new TTreeSRedirector(fgkDebugStreamFileName);
427 AliTPCcalibTracksGain::PreProcess preProc(seed);
428 for (Int_t iCluster = 0; iCluster < 159; iCluster++) {
429 AliTPCclusterMI* cluster = seed->GetClusterPointer(iCluster);
430 if (cluster && preProc.IsClusterAccepted(iCluster)) AddCluster(cluster, preProc);
434 void AliTPCcalibTracksGain::AddCluster(AliTPCclusterMI* cluster, AliTPCcalibTracksGain::PreProcess& preProc) {
436 // Adds cluster to the appropriate fitter for later analysis.
437 // The charge used for the fit is the maximum charge for this specific cluster or the
438 // accumulated charge per cluster, depending on the value of fgkUseTotalCharge.
439 // Depending on the pad size where the cluster is registered, the value will be put in
440 // the appropriate fitter. Furthermore, for each pad size three different types of fitters
441 // are used. The fit functions are the same for all fitters (parabolic functions), but the value
442 // added to each fitter is different. The simple fitter gets the charge plugged in as is, the sqrt fitter
443 // gets the square root of the charge, and the log fitter gets fgkM*(1+q/fgkM), where q is the original charge
445 // The preProc object is used for passing information which was gained by preprocessing the seed to which the
446 // cluster belongs. It is used for correcting the charge due to various effects, e.g. its dependence
447 // on the track length over each pad.
451 Error("AddCluster", "Cluster not valid.");
457 Int_t padType = GetPadType(cluster->GetX());
458 Double_t centerPad[2] = {0};
459 // this line is for using the center of the region with the same pad size as origin for the fit function,
460 // comment out the appropriate lines in AliTPCCalPadRegion::GetPadRegionCenterLocal() and here if you
461 // want the origin at lx=ly=0.
462 AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad);
464 xx[0] = cluster->GetX() - centerPad[0];
465 xx[1] = cluster->GetY() - centerPad[1];
467 //xx[0] = cluster->GetX(); // if you want the origin of the fit func at lx=ly=0
468 //xx[1] = cluster->GetY(); // if you want the origin of the fit func at lx=ly=0
469 xx[2] = xx[0] * xx[0];
470 xx[3] = xx[1] * xx[1];
471 xx[4] = xx[0] * xx[1];
473 Int_t segment = cluster->GetDetector() % 36;
474 Double_t q = fgkUseTotalCharge ? ((Double_t)(cluster->GetQ())) : ((Double_t)(cluster->GetMax())); // note: no normalization to pad size!
475 //cerr << "AngleTrackPadrow(" << segment << ", " << padType << ") == " << preProc.GetAngleTrackPadrow(segment, padType) * TMath::RadToDeg() << endl;
476 //cerr << "AngleTrackBeam (" << segment << ", " << padType << ") == " << preProc.GetAngleTrackBeam(segment, padType) * TMath:: RadToDeg() << endl;
477 //cerr << "Correction factor == " << TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))*TMath::Sin(preProc.GetAngleTrackBeam(segment, padType)))/GetPadLength(cluster->GetX()) << endl;
479 // just for debugging
482 GetRowPad(cluster->GetX(), cluster->GetY(), row, pad);
483 fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->GetValue(row, pad));
485 // correct charge by normalising to mean charge per track
486 //q = TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))*TMath::Sin(preProc.GetAngleTrackBeam(segment, padType)))*q/(GetPadLength(cluster->GetX()) /* * preProc.GetMeanCharge(segment, padType) */);
487 //q *= TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))) / (/*GetPadLength(cluster->GetX()) * */preProc.GetMeanCharge(segment, padType));
488 q /= preProc.GetMeanCharge(segment, padType);
489 //q /= (1 + 0.36 * TMath::Abs(1/TMath::Tan(preProc.GetAngleTrackPadrow(segment, padType))));
491 // correct charge for dependency on z distance using previous iteration
494 fPrevIter->fZFitter->GetParameters(param);
495 q /= param[0] + param[1] * (TMath::Abs(cluster->GetZ()) - TMath::Abs(preProc.GetMeanZ(segment, padType)));
498 // just for debugging
499 fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->GetValue(row, pad));
501 Double_t sqrtQ = TMath::Sqrt(q);
502 Double_t logQ = fgkM * TMath::Log(1 + q / fgkM);
503 fSimpleFitter->GetFitter(segment, padType)->AddPoint(xx, q);
504 fSqrtFitter->GetFitter(segment, padType)->AddPoint(xx, sqrtQ);
505 fLogFitter->GetFitter(segment, padType)->AddPoint(xx, logQ);
507 Double_t zz = TMath::Abs(cluster->GetZ()) - TMath::Abs(preProc.GetMeanZ(segment, padType));
508 fZFitter->AddPoint(&zz, q);
510 // this will be gone for the a new ROOT version > v5-17-05
511 if (padType == kShortPads)
512 fNShortClusters[segment]++;
513 else if (padType == kMediumPads)
514 fNMediumClusters[segment]++;
515 else if (padType == kLongPads)
516 fNLongClusters[segment]++;
519 void AliTPCcalibTracksGain::Evaluate(Bool_t robust, Double_t frac) {
521 // Evaluates all fitters contained in this object.
522 // If the robust option is set to kTRUE a robust fit is performed with frac as
523 // the minimal fraction of good points (see TLinearFitter::EvalRobust for details).
524 // Beware: Robust fitting is much slower!
527 fSimpleFitter->Evaluate(robust, frac);
528 fSqrtFitter->Evaluate(robust, frac);
529 fLogFitter->Evaluate(robust, frac);
530 if (robust) fZFitter->EvalRobust(frac);
531 else fZFitter->Eval();
534 Int_t AliTPCcalibTracksGain::Evaluate(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD* fitParam, TVectorD* fitError, Double_t* redChi2, Bool_t robust, Double_t frac) {
536 // Evaluate the tracks for obtaining the calibration information.
537 // segment specifies the segment (IROC & OROC) for which the fitter shall be evaluated (it can take values from
538 // 0 to 35; segment == i means IROC# i and OROC# (i+36) are meant).
539 // padType is one of kShortPads, kMediumPads, kLongPads.
540 // fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
541 // fitParam should be a TVectorD object with 6 elements where the fit parameters will be written to,
542 // the same is valid for fitError, which will contain the errors of course.
543 // redChi2 is a pointer to an Int_t value which will contain the reduced chi^2 of the fit.
544 // If fitParam, fitError or redChi2 is a null pointer, the corresponding value is not calculated.
545 // If the robust option is set to kTRUE a robust fit is performed with frac as
546 // the minimal fraction of good points (see TLinearFitter::EvalRobust for details).
547 // Beware: Robust fitting is much slower!
548 // Evaluate() returns the number of clusters in the specified padType.
551 TLinearFitter* fitter = GetFitter(segment, padType, fitType);
553 // this will be gone for a new ROOT version > v5-17-05
555 // UInt_t NClusters = fSimpleFitter->GetFitter(segment, padType)->GetNpoints();
558 NClusters = fNShortClusters[segment];
561 NClusters = fNMediumClusters[segment];
564 NClusters = fNLongClusters[segment];
568 if (robust) fitter->EvalRobust(frac);
571 if (redChi2) *redChi2 = fitter->GetChisquare()/(NClusters - 6);
572 if (fitParam) fitter->GetParameters(*fitParam);
574 fitter->GetErrors(*fitError);
575 *fitError *= (redChi2) ? (TMath::Sqrt(*redChi2)) : (TMath::Sqrt(fitter->GetChisquare()/(NClusters - 6)));
581 AliTPCCalPad* AliTPCcalibTracksGain::CreateFitCalPad(UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
583 for (UInt_t iSector = 0; iSector < 72; iSector++)
584 tpc.Add(CreateFitCalROC(iSector, fitType, undoTransformation, normalizeToPadSize));
585 return new AliTPCCalPad(&tpc);
588 AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
591 GetParameters(sector % 36, 0, fitType, par);
592 return CreateFitCalROC(sector, 0, par, fitType, undoTransformation, normalizeToPadSize);
595 GetParameters(sector % 36, 1, fitType, par);
596 AliTPCCalROC* roc1 = CreateFitCalROC(sector, 1, par, fitType, undoTransformation, normalizeToPadSize);
597 GetParameters(sector % 36, 2, fitType, par);
598 AliTPCCalROC* roc2 = CreateFitCalROC(sector, 2, par, fitType, undoTransformation, normalizeToPadSize);
599 AliTPCCalROC* roc3 = CreateCombinedCalROC(roc1, roc2);
606 AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t padType, TVectorD &fitParam, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
608 // This function is essentially a copy of AliTPCCalROC::CreateGlobalFitCalROC(...), with the
609 // modifications, that the center of the region of same pad size is used as the origin
610 // of the fit function instead of the center of the ROC.
611 // The possibility of a linear fit is removed as well because it is not needed.
612 // Only values for pads with the given pad size are calculated, the rest is 0.
613 // Set undoTransformation for undoing the transformation that was applied to the
614 // charge values before they were put into the fitter (thus allowing comparison to the original
615 // charge values). For fitType use 0 for the simple fitter, 1 for the sqrt fitter, 2 for the log fitter.
616 // If normalizeToPadSize is true, the values are normalized to the pad size.
617 // Please be aware, that you even need to specify the fitType if you want to normalize to the pad size without
618 // undoing the transformation (because normalizing involves undoing the trafo first, then normalizing, then
619 // applying the trafo again).
620 // Please note: The normalization to the pad size is a simple linear scaling with the pad length, which
621 // actually doesn't describe reality!
625 Double_t centerPad[2] = {0};
626 Float_t localXY[3] = {0};
627 AliTPCROC* tpcROC = AliTPCROC::Instance();
628 if ((padType == 0 && sector >= tpcROC->GetNInnerSector()) || (padType > 0 && sector < tpcROC->GetNInnerSector()) || sector >= tpcROC->GetNSector())
630 AliTPCCalROC* ROCfitted = new AliTPCCalROC(sector);
631 //tpcROC->GetPositionLocal(sector, ROCfitted->GetNrows()/2, ROCfitted->GetNPads(ROCfitted->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
637 endRow = ROCfitted->GetNrows();
645 endRow = ROCfitted->GetNrows();
649 AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad);
651 for (UInt_t irow = startRow; irow < endRow; irow++) {
652 for (UInt_t ipad = 0; ipad < ROCfitted->GetNPads(irow); ipad++) {
653 tpcROC->GetPositionLocal(sector, irow, ipad, localXY); // calculate position localXY by pad and row number
654 dlx = localXY[0] - centerPad[0];
655 dly = localXY[1] - centerPad[1];
656 value = fitParam[0] + fitParam[1]*dlx + fitParam[2]*dly + fitParam[3]*dlx*dlx + fitParam[4]*dly*dly + fitParam[5]*dlx*dly;
658 // Let q' = value be the transformed value without any pad size corrections,
659 // let T be the transformation and let l be the pad size
660 // 1) don't undo transformation, don't normalize: return q'
661 // 2) undo transformation, don't normalize: return T^{-1} q'
662 // 3) undo transformation, normalize: return (T^{-1} q') / l
663 // 4) don't undo transformation, normalize: return T((T^{-1} q') / l)
664 if (!undoTransformation && !normalizeToPadSize) {/* value remains unchanged */} // (1)
665 else { // (2), (3), (4)
668 case 0: /* value remains unchanged */ break;
669 case 1: value = value * value; break;
670 case 2: value = (TMath::Exp(value / fgkM) - 1) * fgkM; break;
671 default: Error("CreateFitCalROC", "Wrong fit type."); break;
673 if (normalizeToPadSize) value /= GetPadLength(localXY[0]); // (3)
675 if (!undoTransformation && normalizeToPadSize) { // (4)
678 case 0: /* value remains unchanged */ break;
679 case 1: value = TMath::Sqrt(value); break;
680 case 2: value = fgkM * TMath::Log(1 + value / fgkM); break;
681 default: Error("CreateFitCalROC", "Wrong fit type."); break;
684 ROCfitted->SetValue(irow, ipad, value);
690 AliTPCCalROC* AliTPCcalibTracksGain::CreateCombinedCalROC(const AliTPCCalROC* roc1, const AliTPCCalROC* roc2) {
692 // Combines the medium pad size values of roc1 with the long pad size values of roc2 into a new
693 // AliTPCCalROC. Returns a null pointer if any one of the ROCs is an IROC; issues a warning message
694 // if the sectors of roc1 and roc2 don't match, but still continue and use the sector of roc1 as the
695 // sector of the new ROC.
698 if (!roc1 || !roc2) return 0;
699 if ((Int_t)(roc1->GetSector()) < fgTPCparam->GetNInnerSector()) return 0;
700 if ((Int_t)(roc2->GetSector()) < fgTPCparam->GetNInnerSector()) return 0;
701 if (roc1->GetSector() != roc2->GetSector()) Warning("CreateCombinedCalROC", "Sector number mismatch.");
702 AliTPCCalROC* roc = new AliTPCCalROC(roc1->GetSector());
704 for (UInt_t iRow = 0; iRow < 64; iRow++) {
705 for (UInt_t iPad = 0; iPad < roc->GetNPads(iRow); iPad++)
706 roc->SetValue(iRow, iPad, roc1->GetValue(iRow, iPad));
708 for (UInt_t iRow = 64; iRow < roc->GetNrows(); iRow++) {
709 for (UInt_t iPad = 0; iPad < roc->GetNPads(iRow); iPad++)
710 roc->SetValue(iRow, iPad, roc2->GetValue(iRow, iPad));
715 void AliTPCcalibTracksGain::GetParameters(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitParam) {
717 // Puts the fit parameters for the specified segment (IROC & OROC), padType and fitType
718 // into the fitParam TVectorD (which should contain 6 elements).
719 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
720 // Note: The fitter has to be evaluated first!
723 GetFitter(segment, padType, fitType)->GetParameters(fitParam);
726 void AliTPCcalibTracksGain::GetErrors(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitError) {
728 // Puts the fit parameter errors for the specified segment (IROC & OROC), padType and fitType
729 // into the fitParam TVectorD (which should contain 6 elements).
730 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
731 // Note: The fitter has to be evaluated first!
734 GetFitter(segment, padType, fitType)->GetErrors(fitError);
735 fitError *= TMath::Sqrt(GetRedChi2(segment, padType, fitType));
738 Double_t AliTPCcalibTracksGain::GetRedChi2(UInt_t segment, UInt_t padType, UInt_t fitType) {
740 // Returns the reduced chi^2 value for the specified segment, padType and fitType.
741 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
742 // Note: The fitter has to be evaluated first!
748 NClusters = fNShortClusters[segment];
751 NClusters = fNMediumClusters[segment];
754 NClusters = fNLongClusters[segment];
757 return GetFitter(segment, padType, fitType)->GetChisquare()/(NClusters - 6);
760 void AliTPCcalibTracksGain::GetCovarianceMatrix(UInt_t segment, UInt_t padType, UInt_t fitType, TMatrixD& covMatrix) {
762 // Returns the covariance matrix for the specified segment, padType, fitType.
763 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
766 GetFitter(segment, padType, fitType)->GetCovarianceMatrix(covMatrix);
769 TLinearFitter* AliTPCcalibTracksGain::GetFitter(UInt_t segment, UInt_t padType, UInt_t fitType) {
771 // Returns the TLinearFitter object for the specified segment, padType, fitType.
772 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
777 return fSimpleFitter->GetFitter(segment, padType);
779 return fSqrtFitter->GetFitter(segment, padType);
781 return fLogFitter->GetFitter(segment, padType);
786 Double_t AliTPCcalibTracksGain::GetPadLength(Double_t lx) {
788 // The function returns 0.75 for an IROC, 1. for an OROC at medium pad size position,
789 // 1.5 for an OROC at long pad size position, -1 if out of bounds.
792 Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2;
793 Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2;
794 Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2;
795 Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2;
796 Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2;
797 Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2;
800 if (lx >= irocLow && lx <= irocUp) return 0.75;
801 // if OROC medium pads
802 if (lx >= orocLow1 && lx <= orocUp1) return 1.;
804 if (lx >= orocLow2 && lx <= orocUp2) return 1.5;
809 Int_t AliTPCcalibTracksGain::GetPadType(Double_t lx) {
811 // The function returns 0 for an IROC, 1 for an OROC at medium pad size position,
812 // 2 for an OROC at long pad size position, -1 if out of bounds.
815 if (GetPadLength(lx) == 0.75) return 0;
816 else if (GetPadLength(lx) == 1.) return 1;
817 else if (GetPadLength(lx) == 1.5) return 2;
821 // ONLY FOR DEBUGGING PURPOSES - REMOVE ME WHEN NOT NEEDED ANYMORE
822 Bool_t AliTPCcalibTracksGain::GetRowPad(Double_t lx, Double_t ly, Int_t& row, Int_t& pad) {
824 // Calculate the row and pad number when the local coordinates are given.
825 // Returns kFALSE if the position is out of range, otherwise return kTRUE.
826 // WARNING: This function is preliminary and probably isn't very accurate!!
829 Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2;
830 //Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2;
831 Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2;
832 //Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2;
833 Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2;
834 //Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2;
836 if (GetPadType(lx) == 0) {
837 row = (Int_t)((lx - irocLow) / fgTPCparam->GetInnerPadPitchLength());
838 pad = (Int_t)((ly + fgTPCparam->GetYInner(row)) / fgTPCparam->GetInnerPadPitchWidth());
839 } else if (GetPadType(lx) == 1) {
840 row = (Int_t)((lx - orocLow1) / fgTPCparam->GetOuter1PadPitchLength());
841 pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth());
842 } else if (GetPadType(lx) == 2) {
843 row = fgTPCparam->GetNRowUp1() + (Int_t)((lx - orocLow2) / fgTPCparam->GetOuter2PadPitchLength());
844 pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth());
850 void AliTPCcalibTracksGain::DumpTrack(AliTPCseed* track) {
852 // Dump track information to the debug stream
855 (*fDebugStream) << "Track" <<
856 "Track.=" << track << // track information
859 for (Int_t ipad = 0; ipad < 3; ipad++) {
860 GetDedx(track, ipad, rows);
864 Bool_t AliTPCcalibTracksGain::GetDedx(AliTPCseed* track, Int_t padType, Int_t* rows) {
866 // GetDedx for given sector for given track
867 // padType - type of pads
870 Int_t firstRow = 0, lastRow = 0;
873 const Float_t ktany = TMath::Tan(TMath::DegToRad() * 10);
874 const Float_t kedgey = 4.;
877 lastRow = fgTPCparam->GetNRowLow();
881 firstRow = fgTPCparam->GetNRowLow();
882 lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1();
886 firstRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1();
887 lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp();
890 minRow = (lastRow - firstRow) / 2;
894 Int_t nclustersNE = 0; // number of not edge clusters
895 Int_t lastSector = -1;
896 Float_t amplitudeQ[100];
897 Float_t amplitudeM[100];
901 static TLinearFitter fitY(2, "pol1");
902 static TLinearFitter fitZ(2, "pol1");
903 static TVectorD parY(2);
904 static TVectorD parZ(2);
909 for (Int_t iCluster = firstRow; iCluster < lastRow; iCluster++) {
910 AliTPCclusterMI* cluster = track->GetClusterPointer(iCluster);
912 Int_t detector = cluster->GetDetector() ;
913 if (lastSector == -1) lastSector = detector;
914 if (lastSector != detector) continue;
915 amplitudeQ[nclusters] = cluster->GetQ();
916 amplitudeM[nclusters] = cluster->GetMax();
917 rowIn[nclusters] = iCluster;
919 Double_t dx = cluster->GetX() - xcenter;
920 Double_t y = cluster->GetY();
921 Double_t z = cluster->GetZ();
922 fitY.AddPoint(&dx, y);
923 fitZ.AddPoint(&dx, z);
930 if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) nclustersNE++;
934 if (nclusters < minRow / 2) return kFALSE;
935 if (nclustersNE < minRow / 2) return kFALSE;
936 for (Int_t i = 0; i < 6; i++) meanPos[i] /= Double_t(nclusters);
939 fitY.GetParameters(parY);
940 fitZ.GetParameters(parZ);
942 // calculate truncated mean
944 TMath::Sort(nclusters, amplitudeQ, index, kFALSE);
949 for (Int_t i = 0; i < 5; i++) {
958 for (Int_t i = 0; i < nclusters; i++) {
959 Int_t rowSorted = rowIn[index[i]];
960 AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
962 if (TMath::Abs(cluster->GetY()) > cluster->GetX()*ktany - kedgey) continue; //don't take edge clusters
964 if (inonEdge < nclustersNE * 0.5) {
966 dedxQ[0] += amplitudeQ[index[i]];
967 dedxM[0] += amplitudeM[index[i]];
969 if (inonEdge < nclustersNE * 0.6) {
971 dedxQ[1] += amplitudeQ[index[i]];
972 dedxM[1] += amplitudeM[index[i]];
974 if (inonEdge < nclustersNE * 0.7) {
976 dedxQ[2] += amplitudeQ[index[i]];
977 dedxM[2] += amplitudeM[index[i]];
979 if (inonEdge < nclustersNE * 0.8) {
981 dedxQ[3] += amplitudeQ[index[i]];
982 dedxM[3] += amplitudeM[index[i]];
984 if (inonEdge < nclustersNE * 0.9) {
986 dedxQ[4] += amplitudeQ[index[i]];
987 dedxM[4] += amplitudeM[index[i]];
990 for (Int_t i = 0; i < 5; i++) {
991 dedxQ[i] /= ndedx[i];
992 dedxM[i] /= ndedx[i];
996 for (Int_t i = 0; i < nclusters; i++) {
997 Int_t rowSorted = rowIn[index[i]];
998 AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
1000 printf("Problem\n");
1003 if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) inonEdge++;
1004 Float_t dedge = cluster->GetX()*ktany - TMath::Abs(cluster->GetY());
1005 Float_t fraction = Float_t(i) / Float_t(nclusters);
1006 Float_t fraction2 = Float_t(inonEdge) / Float_t(nclustersNE);
1007 Float_t momenta = track->GetP();
1008 Float_t mdedx = track->GetdEdx();
1010 (*fDebugStream) << "dEdx" <<
1011 "Cl.=" << cluster << // cluster of interest
1012 "P=" << momenta << // track momenta
1013 "dedx=" << mdedx << // mean dedx - corrected for angle
1014 "IPad=" << padType << // pad type 0..2
1015 "xc=" << xcenter << // x center of chamber
1016 "dedxQ.=" << &dedxQ << // dedxQ - total charge
1017 "dedxM.=" << &dedxM << // dedxM - maximal charge
1018 "fraction=" << fraction << // fraction - order in statistic (0,1)
1019 "fraction2=" << fraction2 << // fraction - order in statistic (0,1)
1020 "dedge=" << dedge << // distance to the edge
1021 "parY.=" << &parY << // line fit
1022 "parZ.=" << &parZ << // line fit
1023 "meanPos.=" << &meanPos << // mean position (dx, dx^2, y,y^2, z, z^2)
1029 AliTPCcalibTracksGain::PreProcess::PreProcess(AliTPCseed* seed) :
1033 // Constructor. Preprocesses the track contained in seed. After that
1034 // all relevant values gained from preprocessing can be accessed using
1035 // the getter methods.
1036 // For each pad region a line fit using the clusters of this region is made
1037 // for obtaining the angle between track and padrow.
1038 // The mean charge for the clusters of each pad region is calculated.
1039 // For all these calculations inappropriate clusters are not used
1040 // and are accordingly marked (which can be found out with IsClusterAccepted).
1043 // initialize data members and constants
1044 fAngleTrackPadrow = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1045 fAngleTrackBeam = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1046 fMeanCharge = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1047 fMeanZ = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1048 for (UInt_t i = 0; i < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); i++) {
1052 for (UInt_t i = 0; i < 159; i++) fAcceptedClusters[i] = kFALSE;
1053 const Double_t kSmallNumber = 1E-20;
1054 const Double_t kTan10 = TMath::Tan(10*TMath::DegToRad());
1055 const Double_t kCos10 = TMath::Cos(10*TMath::DegToRad());
1057 Int_t nClusters[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()]; // this will be gone for a new ROOT version > v5-17-05
1058 for (UInt_t i = 0; i < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); i++) nClusters[i] = 0; // this will be gone for a new ROOT version > v5-17-05
1059 Int_t nAllClusters[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
1060 for (UInt_t i = 0; i < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); i++) nAllClusters[i] = 0;
1062 Double_t clusterCharges[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()][100];
1063 Int_t clusterIndices[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()][100];
1064 Int_t clusterRows [AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()][100];
1065 for (Int_t iCluster = 0; iCluster < 159; iCluster++) {
1066 AliTPCclusterMI* cluster = fSeed->GetClusterPointer(iCluster);
1067 // check if cluster is good cluster
1069 Int_t segment = cluster->GetDetector() % 36;
1070 Int_t padType = (iCluster < AliTPCcalibTracksGain::fgTPCparam->GetNRowLow()) ? 0 : ((iCluster < fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1()) ? 1 : 2);
1071 Int_t index = segment + AliTPCFitPad::GetNSegments() * padType;
1072 nAllClusters[index]++;
1074 // cluster type < 0: edge cluster
1075 // cluster type = 0: "golden" (i.e. good) cluster
1076 // cluster type > 0: overlapping cluster
1077 // if (cluster->GetType() != 0) continue;
1079 // add up z positions for later calculation of mean z position
1080 fMeanZ[index] += cluster->GetZ();
1082 // remove edge clusters (only keep those farther away than 3 cm from the edge)
1083 Double_t edgeDistance = (cluster->GetX() * kTan10 - TMath::Abs(cluster->GetY())); //* kCos10; // the cos is for the shortest distance
1084 if (edgeDistance < 3.) continue;
1086 // put cluster charges and their row position in arrays for each pad region and count them
1087 clusterCharges[index][nClusters[index]] = AliTPCcalibTracksGain::fgkUseTotalCharge ? cluster->GetQ() : cluster->GetMax();
1088 clusterRows[index][nClusters[index]] = iCluster;
1093 // order clusters according to their charge (in each pad region)
1094 //for (UInt_t index = 0; index < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); index++)
1095 // TMath::Sort(nClusters[index], clusterCharges[index], clusterIndices[index], kFALSE);
1097 AliTPCFitPad localXYfitters(2, "pol1", ""); // used for determining the angle between XY projection of track and Y axis (padrow) - local c.s.
1098 AliTPCFitPad localXZfitters(2, "pol1", ""); // used for determining the angle between XZ projection of track and Z axis (beam) - local c.s.
1100 Int_t minRows[3] = {0};
1101 minRows[0] = AliTPCcalibTracksGain::fgTPCparam->GetNRowLow();
1102 minRows[1] = AliTPCcalibTracksGain::fgTPCparam->GetNRowUp1();
1103 minRows[2] = AliTPCcalibTracksGain::fgTPCparam->GetNRowUp() - AliTPCcalibTracksGain::fgTPCparam->GetNRowUp1();
1104 // the minimum number of rows occupied by clusters in a pad region should be a quarter of the available rows
1105 for (Int_t i = 0; i < 3; minRows[i++] /= 4);
1107 for (UInt_t iSegment = 0; iSegment < AliTPCFitPad::GetNSegments(); iSegment++) {
1108 for (UInt_t iPadType = 0; iPadType < AliTPCFitPad::GetNPadTypes(); iPadType++) {
1109 Int_t index = iSegment + AliTPCFitPad::GetNSegments() * iPadType;
1111 // remove pad regions with too few rows occupied by clusters
1112 if (nAllClusters[index] < minRows[iPadType]) continue;
1113 // calculate mean z position
1114 fMeanZ[index] /= nAllClusters[index];
1115 // order clusters according to their charge (in each pad region)
1116 TMath::Sort(nClusters[index], clusterCharges[index], clusterIndices[index], kFALSE);
1118 for (Int_t i = 0; i < nClusters[index]; i++) {
1119 Int_t iCluster = clusterRows[index][clusterIndices[index][i]];
1120 AliTPCclusterMI* cluster = fSeed->GetClusterPointer(iCluster);
1121 // keep only the lower 70% of the clusters ordered according to their charge
1122 Double_t fraction = (Double_t)i / (Double_t)(nClusters[index]);
1123 if (fraction > 0.7) break;
1125 fAcceptedClusters[iCluster] = kTRUE;
1126 // put cluster data into fitters (I should move this before the fraction cut, because the charge values don't matter - the problem is the number of points -> additional counter)
1127 Double_t x = cluster->GetX(); // maybe it's better for fitter stability to use difference from pad region center instead
1128 localXYfitters.GetFitter(iSegment, iPadType)->AddPoint(&x, cluster->GetY());
1129 localXZfitters.GetFitter(iSegment, iPadType)->AddPoint(&x, cluster->GetZ());
1130 // add up charges for later calculation of mean charges
1131 fMeanCharge[index] += AliTPCcalibTracksGain::fgkUseTotalCharge ? cluster->GetQ() : cluster->GetMax();
1133 // calculate mean charges
1134 if (nClusters[index] != 0) fMeanCharge[index] /= (Double_t)(nClusters[index]);
1138 // evaluate fitters and set corresponding angles or default values, respectively
1139 for (UInt_t iSegment = 0; iSegment < AliTPCFitPad::GetNSegments(); iSegment++) {
1140 for (UInt_t iPadType = 0; iPadType < AliTPCFitPad::GetNPadTypes(); iPadType++) {
1141 UInt_t index = iSegment + AliTPCFitPad::GetNSegments() * iPadType;
1142 // evaluate XY fitters
1143 TLinearFitter* fitter = localXYfitters.GetFitterSimple(iSegment, iPadType);
1144 if (fitter && nClusters[index] >= 2 && fitter->Eval() == 0) { // this will be gone for a new ROOT version > v5-17-05 and replaced by (fitter && fitter->GetNPoints() >= 2 && fitter->Eval() == 0)
1145 Double_t slope = fitter->GetParameter(1);
1146 if (TMath::Abs(slope) < kSmallNumber)
1147 fAngleTrackPadrow[index] = TMath::Sign(TMath::Pi()/2, slope); // default value for small slopes
1149 fAngleTrackPadrow[index] = TMath::ATan(1/slope);
1151 else fAngleTrackPadrow[index] = TMath::Pi()/2; // default value if not enough data points in fitter
1152 // evaluate XZ fitters
1153 fitter = localXZfitters.GetFitterSimple(iSegment, iPadType);
1154 if (fitter && nClusters[index] >= 2 && fitter->Eval() == 0) { // this will be gone for a new ROOT version > v5-17-05 and replaced by (fitter && fitter->GetNPoints() >= 2 && fitter->Eval() == 0)
1155 Double_t slope = fitter->GetParameter(1);
1156 if (TMath::Abs(slope) < kSmallNumber)
1157 fAngleTrackBeam[index] = TMath::Sign(TMath::Pi()/2, slope); // default value for small slopes
1159 fAngleTrackBeam[index] = TMath::ATan(1/slope);
1161 else fAngleTrackBeam[index] = TMath::Pi()/2; // default value if not enough data points in fitter, should be pi/2 for cosmics, something like pi/4 for pp
1166 AliTPCcalibTracksGain::PreProcess::~PreProcess() {
1171 delete[] fAngleTrackPadrow;
1172 delete[] fAngleTrackBeam;
1173 delete[] fMeanCharge;
1177 // REMOVE ME, just for debugging
1178 void AliTPCcalibTracksGain::testSeed(char* file, Int_t entry, Int_t tr) {
1179 // read a single AliTPCseed from AliESDs.root and AliESDfriends.root (with new AliRoot)
1181 TTree* tree = (TTree*)(f.Get("esdTree"));
1182 tree->SetBranchStatus("*",1);
1183 AliESDEvent* fESDevent = new AliESDEvent();
1184 fESDevent->ReadFromTree(tree);
1185 tree->GetEntry(entry);
1186 AliESDfriend* fESDfriend = (AliESDfriend*)fESDevent->FindListObject("AliESDfriend");
1187 tree->SetBranchAddress("ESDfriend.",&fESDfriend);
1188 fESDevent->SetESDfriend(fESDfriend);
1189 AliESDtrack *esdTrack = (AliESDtrack*) fESDevent->GetTrack(tr);
1190 AliESDfriendTrack *friendtrack = (AliESDfriendTrack*) esdTrack->GetFriendTrack();
1191 AliTPCseed *seed = 0; TObject *cobject = 0;
1192 for (Int_t i = 0; ; i++){ cobject = friendtrack->GetCalibObject(i); if (!cobject) break; seed = dynamic_cast<AliTPCseed*>(cobject); if (seed) break;}
1194 AliTPCcalibTracksGain::PreProcess preProc(seed);
1195 for (Int_t iCluster = 0; iCluster < 159; iCluster++) {
1196 AliTPCclusterMI* cluster = seed->GetClusterPointer(iCluster);
1198 Int_t padType = AliTPCcalibTracksGain::GetPadType(cluster->GetX());
1199 Int_t segment = cluster->GetDetector() % 36;
1200 cout << "AngleTrackPadrow(" << segment << ", " << padType << ") == " << preProc.GetAngleTrackPadrow(segment, padType) * TMath::RadToDeg() << endl;
1201 cout << "AngleTrackBeam (" << segment << ", " << padType << ") == " << preProc.GetAngleTrackBeam(segment, padType) * TMath:: RadToDeg() << endl;
1202 cout << "Correction factor == " << TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))*TMath::Sin(preProc.GetAngleTrackBeam(segment, padType)))/AliTPCcalibTracksGain::GetPadLength(cluster->GetX()) << endl;