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 ////////////////////////////////////////////////////////////////////////////
19 // Gain calibration using tracks
22 // 1.) Inner TPC gain alignement - (parabolic) parameterization (inside of one sector)
23 // 2.) Angular and z-position correction (parabolic) parameterization
24 // 3.) Sector gain alignment
26 // Following histograms are accumulated
27 // a.) Simple 1D histograms per chamber
28 // b.) Profile histograms per chamber - local x dependence
29 // c.) 2D Profile histograms - local x - fi dependence
31 // To get the gain map - the simple solution - use the histograms - is not enough
32 // The resulting mean amplitude map depends strongly on the track topology
33 // These dependence can be reduced, taking into account angular effect, and diffusion effect
34 // Using proper fit modeles
39 // === Calibration class for gain calibration using tracks ===
43 // A 6-parametric parabolic function
45 // G(x, y) = p0 + p1*x + p2*y + p3*x^2 + p4*y^2 + p5 * x*y
47 // is fitted to the maximum charge values or total charge values of
48 // all the clusters contained in the tracks that are added to this
49 // object. This fit is performed for each read out chamber, in fact even
50 // for each type of pad sizes (thus for one segment, which consists of
51 // an IROC and an OROC, there are three fitters used, corresponding to
52 // the three pad sizes). The coordinate origin is at the center of the
53 // particular pad size region on each ROC.
55 // Because of the Landau nature of the charge deposition we use
56 // different "types" of fitters instead of one to minimize the effect
57 // of the long Landau tail. The difference between the fitters is only
58 // the charge value, that is put into them, i.e. the charge is subject
59 // to a transformation. At this point we use three different fit types:
61 // a) simple: the charge is put in as it is
62 // b) sqrt: the square root of the charge is put into the fitter
63 // c) log: fgkM * Log(1+q/fgkM) is put into the fitter, with
64 // q being the untransformed charge and fgkM=25
66 // The results of the fits may be visualized and further used by
67 // creating an AliTPCCalROC or AliTPCCalPad. You may specify to undo
68 // the transformation and/or to normalize to the pad size.
70 // Not every track you add to this object is actually used for
71 // calibration. There are some cuts and conditions to exclude bad
72 // tracks, e.g. a pt cut to cut out tracks with too much charge
73 // deposition or a cut on edge clusters which are not fully
74 // registered and don't give a usable signal.
76 // 2) Interface / usage
77 // ====================
78 // For each track to be added you need to call Process().
79 // This method expects an AliTPCseed, which contains the necessary
80 // cluster information. At the moment of writing this information
81 // is stored in an AliESDfriend corresponding to an AliESD.
82 // You may also call AddTrack() if you don't want the cuts and
83 // other quality conditions to kick in (thus forcing the object to
84 // accept the track) or AddCluster() for adding single clusters.
85 // Call one of the Evaluate functions to evaluate the fitter(s) and
86 // to retrieve the fit parameters, erros and so on. You can also
87 // do this later on by using the different Getters.
89 // The visualization methods CreateFitCalPad() and CreateFitCalROC()
90 // are straight forward to use.
92 // Note: If you plan to write this object to a ROOT file, make sure
93 // you evaluate all the fitters *before* writing, because due
94 // to a bug in the fitter component writing fitters doesn't
95 // work properly (yet). Be aware that you cannot re-evaluate
96 // the fitters after loading this object from file.
97 // (This will be gone for a new ROOT version > v5-17-05)
100 // In order to debug some numerical algorithm all data data which are used for
101 // fitters can be stored in the debug streamers. In case of fitting roblems the
102 // errors and tendencies can be checked.
110 ////////////////////////////////////////////////////////////////////////////
114 gSystem->Load("libANALYSIS");
115 gSystem->Load("libSTAT");
116 gSystem->Load("libTPCcalib");
118 TFile fcalib("CalibObjects.root");
119 TObjArray * array = (TObjArray*)fcalib.Get("TPCCalib");
120 AliTPCcalibTracksGain * gain = ( AliTPCcalibTracksGain *)array->FindObject("calibTracksGain");
123 // Angular and drift correction
125 AliTPCClusterParam *param = new AliTPCClusterParam;param->SetInstance(param);
126 gain->UpdateClusterParam(param);
127 TF2 fdrty("fdrty","AliTPCClusterParam::SQnorm(0,0,x,y,0)",0,1,0,1)
130 // Make visual Tree - compare with Kr calibration
132 AliTPCCalPad * gain010 = gain->CreateFitCalPad(0,kTRUE,0); gain010->SetName("CGain010");
133 AliTPCCalPad * gain110 = gain->CreateFitCalPad(1,kTRUE,0); gain110->SetName("CGain110");
134 AliTPCCalPad * gain210 = gain->CreateFitCalPad(2,kTRUE,0); gain210->SetName("CGain210");
135 TFile fkr("/u/miranov/GainMap.root");
136 AliTPCCalPad *gainKr = fkr.Get("GainMap"); fkr->SetName("KrGain");
138 AliTPCPreprocessorOnline * preprocesor = new AliTPCPreprocessorOnline;
139 preprocesor->AddComponent(gain010);
140 preprocesor->AddComponent(gain110);
141 preprocesor->AddComponent(gain210);
142 preprocesor->AddComponent(gainKr);
143 preprocesor->DumpToFile("cosmicGain.root");
147 // Simple session using the debug streamers
150 gSystem->AddIncludePath("-I$ALICE_ROOT/TPC/macros");
151 gROOT->LoadMacro("$ALICE_ROOT/TPC/macros/AliXRDPROOFtoolkit.cxx+")
152 AliXRDPROOFtoolkit tool;
154 TChain * chain0 = tool.MakeChain("gain.txt","dEdx",0,1000000);
155 TChain * chain1 = tool.MakeChain("gain.txt","Track",0,1000000);
156 TChain * chain2 = tool.MakeChain("gain.txt","TrackG",0,1000000);
161 chain2->SetAlias("k1","1/0.855");
162 chain2->SetAlias("k0","1/0.9928");
163 chain2->SetAlias("k2","1/1.152");
171 #include <TPDGCode.h>
174 #include "TMatrixD.h"
175 #include "TTreeStream.h"
177 #include "AliTPCParamSR.h"
178 #include "AliTPCClusterParam.h"
179 #include "AliTrackPointArray.h"
181 #include "AliTPCcalibTracksGain.h"
184 #include <TLinearFitter.h>
185 #include <TTreeStream.h>
187 #include <TCollection.h>
188 #include <TIterator.h>
189 #include <TProfile.h>
190 #include <TProfile2D.h>
192 #include <TStatToolkit.h>
198 #include "AliMathBase.h"
200 #include "AliTPCROC.h"
201 #include "AliTPCParamSR.h"
202 #include "AliTPCCalROC.h"
203 #include "AliTPCCalPad.h"
204 #include "AliTPCClusterParam.h"
206 #include "AliTracker.h"
208 #include "AliESDtrack.h"
209 #include "AliESDfriend.h"
210 #include "AliESDfriendTrack.h"
211 #include "AliTPCseed.h"
212 #include "AliTPCclusterMI.h"
213 #include "AliTPCcalibTracksCuts.h"
214 #include "AliTPCFitPad.h"
215 #include "TStatToolkit.h"
221 #include "AliESDEvent.h"
225 TFile f("TPCCalibTracksGain.root")
227 gSystem->Load("libPWG1.so")
233 TString * str = comp.FitPlane("Cl.fQ/dedxQ.fElements[0]","Cl.fY++Cl.fX","Cl.fDetector<36",chi2,vec,mat)
237 ClassImp(AliTPCcalibTracksGain)
239 const Bool_t AliTPCcalibTracksGain::fgkUseTotalCharge = kTRUE;
240 const Double_t AliTPCcalibTracksGain::fgkM = 25.;
241 const char* AliTPCcalibTracksGain::fgkDebugStreamFileName = "TPCCalibTracksGain.root";
242 AliTPCParamSR* AliTPCcalibTracksGain::fgTPCparam = new AliTPCParamSR();
244 AliTPCcalibTracksGain::AliTPCcalibTracksGain() :
246 fCuts(0), // cuts that are used for sieving the tracks used for calibration
247 fGainMap(0), // gain map to be applied
249 // Simple Array of histograms
251 fArrayQM(0), // Qmax normalized
252 fArrayQT(0), // Qtot normalized
253 fProfileArrayQM(0), // Qmax normalized versus local X
254 fProfileArrayQT(0), // Qtot normalized versus local X
255 fProfileArrayQM2D(0), // Qmax normalized versus local X and phi
256 fProfileArrayQT2D(0), // Qtot normalized versus local X and phi
260 fSimpleFitter(0), // simple fitter for short pads
261 fSqrtFitter(0), // sqrt fitter for medium pads
262 fLogFitter(0), // log fitter for long pads
264 fFitter0M(0), // fitting of the atenuation, angular correction, and mean chamber gain
265 fFitter1M(0), // fitting of the atenuation, angular correction, and mean chamber gain
266 fFitter2M(0), // fitting of the atenuation, angular correction, and mean chamber gain
267 fFitter0T(0), // fitting of the atenuation, angular correction, and mean chamber gain
268 fFitter1T(0), // fitting of the atenuation, angular correction, and mean chamber gain
269 fFitter2T(0), // fitting of the atenuation, angular correction, and mean chamber gain
271 fDFitter0M(0), // fitting of the atenuation, angular correction
272 fDFitter1M(0), // fitting of the atenuation, angular correction
273 fDFitter2M(0), // fitting of the atenuation, angular correction
274 fDFitter0T(0), // fitting of the atenuation, angular correction
275 fDFitter1T(0), // fitting of the atenuation, angular correction
276 fDFitter2T(0), // fitting of the atenuation, angular correction
278 fSingleSectorFitter(0), // just for debugging
282 fTotalTracks(0), // just for debugging
283 fAcceptedTracks(0), // just for debugging
284 fDebugCalPadRaw(0), // just for debugging
285 fDebugCalPadCorr(0) // just for debugging
289 // Default constructor.
293 AliTPCcalibTracksGain::AliTPCcalibTracksGain(const AliTPCcalibTracksGain& obj) :
294 AliTPCcalibBase(obj),
295 fCuts(obj.fCuts), // cuts that are used for sieving the tracks used for calibration
296 fGainMap(new AliTPCCalPad(*(obj.fGainMap))), // gain map to be applied
297 fArrayQM(0), // Qmax normalized
298 fArrayQT(0), // Qtot normalized
302 fProfileArrayQM(obj.fProfileArrayQM), // Qmax normalized versus local X
303 fProfileArrayQT(obj.fProfileArrayQT), // Qtot normalized versus local X
304 fProfileArrayQM2D(obj.fProfileArrayQM2D), // Qmax normalized versus local X and phi
305 fProfileArrayQT2D(obj.fProfileArrayQT2D), // Qtot normalized versus local X and phi
309 fSimpleFitter(obj.fSimpleFitter), // simple fitter for short pads
310 fSqrtFitter(obj.fSqrtFitter), // sqrt fitter for medium pads
311 fLogFitter(obj.fLogFitter), // log fitter for long pads
312 fFitter0M(obj.fFitter0M),
313 fFitter1M(obj.fFitter1M),
314 fFitter2M(obj.fFitter2M),
315 fFitter0T(obj.fFitter0T),
316 fFitter1T(obj.fFitter1T),
317 fFitter2T(obj.fFitter2T),
319 fDFitter0M(obj.fDFitter0M),
320 fDFitter1M(obj.fDFitter1M),
321 fDFitter2M(obj.fDFitter2M),
322 fDFitter0T(obj.fDFitter0T),
323 fDFitter1T(obj.fDFitter1T),
324 fDFitter2T(obj.fDFitter2T),
325 fSingleSectorFitter(obj.fSingleSectorFitter), // just for debugging
329 fTotalTracks(obj.fTotalTracks), // just for debugging
330 fAcceptedTracks(obj.fAcceptedTracks), // just for debugging
331 fDebugCalPadRaw(obj.fDebugCalPadRaw), // just for debugging
332 fDebugCalPadCorr(obj.fDebugCalPadCorr) // just for debugging
340 AliTPCcalibTracksGain& AliTPCcalibTracksGain::operator=(const AliTPCcalibTracksGain& rhs) {
342 // Assignment operator.
346 TNamed::operator=(rhs);
347 fDebugCalPadRaw = new AliTPCCalPad(*(rhs.fDebugCalPadRaw));
348 fDebugCalPadCorr = new AliTPCCalPad(*(rhs.fDebugCalPadCorr));
349 fSimpleFitter = new AliTPCFitPad(*(rhs.fSimpleFitter));
350 fSqrtFitter = new AliTPCFitPad(*(rhs.fSqrtFitter));
351 fLogFitter = new AliTPCFitPad(*(rhs.fLogFitter));
352 fSingleSectorFitter = new AliTPCFitPad(*(rhs.fSingleSectorFitter));
353 fCuts = new AliTPCcalibTracksCuts(*(rhs.fCuts));
354 fGainMap = new AliTPCCalPad(*(rhs.fGainMap));
359 AliTPCcalibTracksGain::AliTPCcalibTracksGain(const char* name, const char* title, AliTPCcalibTracksCuts* cuts, TNamed* /*debugStreamPrefix*/, AliTPCcalibTracksGain* prevIter) :
361 fCuts(0), // cuts that are used for sieving the tracks used for calibration
362 fGainMap(0), // gain map to be applied
363 fArrayQM(0), // Qmax normalized
364 fArrayQT(0), // Qtot normalized
368 fProfileArrayQM(0), // Qmax normalized versus local X
369 fProfileArrayQT(0), // Qtot normalized versus local X
370 fProfileArrayQM2D(0), // Qmax normalized versus local X and phi
371 fProfileArrayQT2D(0), // Qtot normalized versus local X and phi
375 fSimpleFitter(0), // simple fitter for short pads
376 fSqrtFitter(0), // sqrt fitter for medium pads
377 fLogFitter(0), // log fitter for long pads
378 fFitter0M(0), // fitting of the atenuation, angular correction, and mean chamber gain
379 fFitter1M(0), // fitting of the atenuation, angular correction, and mean chamber gain
380 fFitter2M(0), // fitting of the atenuation, angular correction, and mean chamber gain
381 fFitter0T(0), // fitting of the atenuation, angular correction, and mean chamber gain
382 fFitter1T(0), // fitting of the atenuation, angular correction, and mean chamber gain
383 fFitter2T(0), // fitting of the atenuation, angular correction, and mean chamber gain
385 fDFitter0M(0), // fitting of the atenuation, angular correction
386 fDFitter1M(0), // fitting of the atenuation, angular correction
387 fDFitter2M(0), // fitting of the atenuation, angular correction
388 fDFitter0T(0), // fitting of the atenuation, angular correction
389 fDFitter1T(0), // fitting of the atenuation, angular correction
390 fDFitter2T(0), // fitting of the atenuation, angular correction
391 fSingleSectorFitter(0), // just for debugging
395 fTotalTracks(0), // just for debugging
396 fAcceptedTracks(0), // just for debugging
397 fDebugCalPadRaw(0), // just for debugging
398 fDebugCalPadCorr(0) // just for debugging
404 this->SetNameTitle(name, title);
407 // Fitter initialization
409 fSimpleFitter = new AliTPCFitPad(8, "hyp7", "");
410 fSqrtFitter = new AliTPCFitPad(8, "hyp7", "");
411 fLogFitter = new AliTPCFitPad(8, "hyp7", "");
412 fSingleSectorFitter = new AliTPCFitPad(8, "hyp7", "");
414 fFitter0M = new TLinearFitter(45,"hyp44");
415 fFitter1M = new TLinearFitter(45,"hyp44");
416 fFitter2M = new TLinearFitter(45,"hyp44");
417 fFitter0T = new TLinearFitter(45,"hyp44");
418 fFitter1T = new TLinearFitter(45,"hyp44");
419 fFitter2T = new TLinearFitter(45,"hyp44");
421 fDFitter0M = new TLinearFitter(10,"hyp9");
422 fDFitter1M = new TLinearFitter(10,"hyp9");
423 fDFitter2M = new TLinearFitter(10,"hyp9");
424 fDFitter0T = new TLinearFitter(10,"hyp9");
425 fDFitter1T = new TLinearFitter(10,"hyp9");
426 fDFitter2T = new TLinearFitter(10,"hyp9");
429 fFitter0M->StoreData(kFALSE);
430 fFitter1M->StoreData(kFALSE);
431 fFitter2M->StoreData(kFALSE);
432 fFitter0T->StoreData(kFALSE);
433 fFitter1T->StoreData(kFALSE);
434 fFitter2T->StoreData(kFALSE);
436 fDFitter0M->StoreData(kFALSE);
437 fDFitter1M->StoreData(kFALSE);
438 fDFitter2M->StoreData(kFALSE);
439 fDFitter0T->StoreData(kFALSE);
440 fDFitter1T->StoreData(kFALSE);
441 fDFitter2T->StoreData(kFALSE);
444 // Add profile histograms -JUST for visualization - Not used for real calibration
447 fArrayQM=new TObjArray(73); // Qmax normalized
448 fArrayQT=new TObjArray(73); // Qtot normalized
449 fProfileArrayQM = new TObjArray(37); // Qmax normalized versus local X
450 fProfileArrayQT = new TObjArray(37); // Qtot normalized versus local X
451 fProfileArrayQM2D = new TObjArray(37); // Qmax normalized versus local X and phi
452 fProfileArrayQT2D = new TObjArray(37); // Qtot normalized versus local X and phi
454 for (Int_t i=0; i<73; i++){
455 sprintf(hname,"QM_%d",i);
456 fArrayQM->AddAt(new TH1F(hname,hname,200,0,1000),i);
457 sprintf(hname,"QT_%d",i);
458 fArrayQT->AddAt(new TH1F(hname,hname,200,0,1000),i);
461 for (Int_t i=0; i<37;i++){
462 sprintf(hname,"QMvsx_%d",i);
463 fProfileArrayQM->AddAt(new TProfile(hname,hname,50,89,250),i);
464 sprintf(hname,"QTvsx_%d",i);
465 fProfileArrayQT->AddAt(new TProfile(hname,hname,50,89,250),i);
466 sprintf(hname,"QM2D_%d",i);
467 fProfileArrayQM2D->AddAt(new TProfile2D(hname,hname,50,89,250,10,-0.15,0.15),i);
468 sprintf(hname,"QT2D_%d",i);
469 fProfileArrayQT2D->AddAt(new TProfile2D(hname,hname,50,89,250,10,-0.15,0.15),i);
472 // just for debugging -counters
476 fDebugCalPadRaw = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction");
477 fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction");
478 // this will be gone for the a new ROOT version > v5-17-05
479 for (UInt_t i = 0; i < 36; i++) {
480 fNShortClusters[i] = 0;
481 fNMediumClusters[i] = 0;
482 fNLongClusters[i] = 0;
486 AliTPCcalibTracksGain::~AliTPCcalibTracksGain() {
491 Info("Destructor","");
492 if (fSimpleFitter) delete fSimpleFitter;
493 if (fSqrtFitter) delete fSqrtFitter;
494 if (fLogFitter) delete fLogFitter;
495 if (fSingleSectorFitter) delete fSingleSectorFitter;
497 if (fDebugCalPadRaw) delete fDebugCalPadRaw;
498 if (fDebugCalPadCorr) delete fDebugCalPadCorr;
501 void AliTPCcalibTracksGain::Terminate(){
503 // Evaluate fitters and close the debug stream.
504 // Also move or copy the debug stream, if a debugStreamPrefix is provided.
508 AliTPCcalibBase::Terminate();
513 void AliTPCcalibTracksGain::Process(AliTPCseed* seed) {
515 // Main method to be called when a new seed is supposed to be processed
516 // and be used for gain calibration. Its quality is checked before it
522 if (!fCuts->AcceptTrack(seed)) return;
526 static Bool_t doinit= kTRUE;
528 fSimpleFitter = new AliTPCFitPad(8, "hyp7", "");
529 fSqrtFitter = new AliTPCFitPad(8, "hyp7", "");
530 fLogFitter = new AliTPCFitPad(8, "hyp7", "");
531 fSingleSectorFitter = new AliTPCFitPad(8, "hyp7", "");
533 fFitter0M = new TLinearFitter(45,"hyp44");
534 fFitter1M = new TLinearFitter(45,"hyp44");
535 fFitter2M = new TLinearFitter(45,"hyp44");
536 fFitter0T = new TLinearFitter(45,"hyp44");
537 fFitter1T = new TLinearFitter(45,"hyp44");
538 fFitter2T = new TLinearFitter(45,"hyp44");
540 fDFitter0M = new TLinearFitter(10,"hyp9");
541 fDFitter1M = new TLinearFitter(10,"hyp9");
542 fDFitter2M = new TLinearFitter(10,"hyp9");
543 fDFitter0T = new TLinearFitter(10,"hyp9");
544 fDFitter1T = new TLinearFitter(10,"hyp9");
545 fDFitter2T = new TLinearFitter(10,"hyp9");
554 Long64_t AliTPCcalibTracksGain::Merge(TCollection *list) {
556 // Merge() merges the results of all AliTPCcalibTracksGain objects contained in
557 // list, thus allowing a distributed computation of several files, e.g. on PROOF.
558 // The merged results are merged with the data members of the AliTPCcalibTracksGain
559 // object used for calling the Merge method.
560 // The return value is 0 /*the total number of tracks used for calibration*/ if the merge
561 // is successful, otherwise it is -1.
564 if (!list || list->IsEmpty()) return -1;
566 if (!fSimpleFitter) fSimpleFitter = new AliTPCFitPad(8, "hyp7", "");
567 if (!fSqrtFitter) fSqrtFitter = new AliTPCFitPad(8, "hyp7", "");
568 if (!fLogFitter) fLogFitter = new AliTPCFitPad(8, "hyp7", "");
569 if (!fSingleSectorFitter) fSingleSectorFitter = new AliTPCFitPad(8, "hyp7", "");
572 // just for debugging
573 if (!fDebugCalPadRaw) fDebugCalPadRaw = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction");
574 if (!fDebugCalPadCorr) fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction");
576 TIterator* iter = list->MakeIterator();
577 AliTPCcalibTracksGain* cal = 0;
579 while ((cal = (AliTPCcalibTracksGain*)iter->Next())) {
580 if (!cal->InheritsFrom(AliTPCcalibTracksGain::Class())) {
581 Error("Merge","Attempt to add object of class %s to a %s", cal->ClassName(), this->ClassName());
590 Float_t AliTPCcalibTracksGain::GetGain(AliTPCclusterMI* cl){
592 // Return local gain at cluster position
595 if(!fGainMap) return factor;
597 AliTPCCalROC * roc = fGainMap->GetCalROC(cl->GetDetector());
598 Int_t irow = cl->GetRow();
600 if (irow < 63) { // IROC
601 factor = roc->GetValue(irow, TMath::Nint(cl->GetPad()));
603 factor = roc->GetValue(irow - 63, TMath::Nint(cl->GetPad()));
606 if (factor<0.1) factor=0.1;
611 Float_t AliTPCcalibTracksGain::GetMaxNorm(AliTPCclusterMI * cl){
613 // Get normalized amplituded if the gain map provided
615 return cl->GetMax()/GetGain(cl);
619 Float_t AliTPCcalibTracksGain::GetQNorm(AliTPCclusterMI * cl){
621 // Get normalized amplituded if the gain map provided
623 return cl->GetQ()/GetGain(cl);
628 void AliTPCcalibTracksGain::Add(AliTPCcalibTracksGain* cal) {
630 // Adds another AliTPCcalibTracksGain object to this object.
633 fSimpleFitter->Add(cal->fSimpleFitter);
634 fSqrtFitter->Add(cal->fSqrtFitter);
635 fLogFitter->Add(cal->fLogFitter);
636 fSingleSectorFitter->Add(cal->fSingleSectorFitter);
640 if (cal->fFitter0M->GetNpoints()>0) fFitter0M->Add(cal->fFitter0M);
641 if (cal->fFitter1M->GetNpoints()>0) fFitter1M->Add(cal->fFitter1M);
642 if (cal->fFitter2M->GetNpoints()>0) fFitter2M->Add(cal->fFitter2M);
643 if (cal->fFitter0T->GetNpoints()>0) fFitter0T->Add(cal->fFitter0T);
644 if (cal->fFitter1T->GetNpoints()>0) fFitter1T->Add(cal->fFitter1T);
645 if (cal->fFitter2T->GetNpoints()>0) fFitter2T->Add(cal->fFitter2T);
647 if (cal->fDFitter0M->GetNpoints()>0) fDFitter0M->Add(cal->fDFitter0M);
648 if (cal->fDFitter1M->GetNpoints()>0) fDFitter1M->Add(cal->fDFitter1M);
649 if (cal->fDFitter2M->GetNpoints()>0) fDFitter2M->Add(cal->fDFitter2M);
650 if (cal->fDFitter0T->GetNpoints()>0) fDFitter0T->Add(cal->fDFitter0T);
651 if (cal->fDFitter1T->GetNpoints()>0) fDFitter1T->Add(cal->fDFitter1T);
652 if (cal->fDFitter2T->GetNpoints()>0) fDFitter2T->Add(cal->fDFitter2T);
657 for (Int_t i=0; i<73; i++){
659 his = (TH1F*)fArrayQM->At(i);
660 hism = (TH1F*)cal->fArrayQM->At(i);
661 if (his && hism) his->Add(hism);
662 his = (TH1F*)fArrayQT->At(i);
663 hism = (TH1F*)cal->fArrayQT->At(i);
664 if (his && hism) his->Add(hism);
668 for (Int_t i=0; i<37; i++){
670 his = (TProfile*)fProfileArrayQM->At(i);
671 hism = (TProfile*)cal->fProfileArrayQM->At(i);
672 if (his && hism) his->Add(hism);
673 his = (TProfile*)fProfileArrayQT->At(i);
674 hism = (TProfile*)cal->fProfileArrayQT->At(i);
675 if (his && hism) his->Add(hism);
679 for (Int_t i=0; i<37; i++){
680 TProfile2D *his,*hism;
681 his = (TProfile2D*)fProfileArrayQM2D->At(i);
682 hism = (TProfile2D*)cal->fProfileArrayQM2D->At(i);
683 if (his && hism) his->Add(hism);
684 his = (TProfile2D*)fProfileArrayQT2D->At(i);
685 hism = (TProfile2D*)cal->fProfileArrayQT2D->At(i);
686 if (his && hism) his->Add(hism);
689 // this will be gone for the a new ROOT version > v5-17-05
690 for (UInt_t iSegment = 0; iSegment < 36; iSegment++) {
691 fNShortClusters[iSegment] += cal->fNShortClusters[iSegment];
692 fNMediumClusters[iSegment] += cal->fNMediumClusters[iSegment];
693 fNLongClusters[iSegment] += cal->fNLongClusters[iSegment];
696 // just for debugging, remove me
697 fTotalTracks += cal->fTotalTracks;
698 fAcceptedTracks += cal->fAcceptedTracks;
699 fDebugCalPadRaw->Add(cal->fDebugCalPadRaw);
700 fDebugCalPadCorr->Add(cal->fDebugCalPadCorr);
704 void AliTPCcalibTracksGain::AddTrack(AliTPCseed* seed) {
706 // The clusters making up the track (seed) are added to various fit functions.
707 // See AddCluster(...) for more detail.
712 // simple histograming part
713 for (Int_t i=0; i<159; i++){
714 AliTPCclusterMI* cluster = seed->GetClusterPointer(i);
715 if (cluster) AddCluster(cluster);
719 void AliTPCcalibTracksGain::AddCluster(AliTPCclusterMI* cluster){
721 // Adding cluster information to the simple histograms
722 // No correction, fittings are applied
725 Float_t kThreshold=5;
726 if (cluster->GetX()<=0) return;
727 if (cluster->GetQ()<=kThreshold) return;
730 Int_t sector = cluster->GetDetector();
733 if (his) his->Fill(GetQNorm(cluster));
735 if (his) his->Fill(GetQNorm(cluster));
737 if (his) his->Fill(GetMaxNorm(cluster));
739 if (his) his->Fill(GetMaxNorm(cluster));
743 prof = GetProfileQT(sector);
744 if (prof) prof->Fill(cluster->GetX(),GetQNorm(cluster));
745 prof = GetProfileQT(-1);
746 if (prof) prof->Fill(cluster->GetX(),GetQNorm(cluster));
747 prof = GetProfileQM(sector);
748 if (prof) prof->Fill(cluster->GetX(),GetMaxNorm(cluster));
749 prof = GetProfileQM(-1);
750 if (prof) prof->Fill(cluster->GetX(),GetMaxNorm(cluster));
752 Float_t phi = cluster->GetY()/cluster->GetX();
754 prof2 = GetProfileQT2D(sector);
755 if (prof2) prof2->Fill(cluster->GetX(),phi,GetQNorm(cluster));
756 prof2 = GetProfileQT2D(-1);
757 if (prof2) prof2->Fill(cluster->GetX(),phi,GetQNorm(cluster));
758 prof2 = GetProfileQM2D(sector);
759 if (prof2) prof2->Fill(cluster->GetX(),phi,GetMaxNorm(cluster));
760 prof2 = GetProfileQM2D(-1);
761 if (prof2) prof2->Fill(cluster->GetX(),phi,GetMaxNorm(cluster));
768 void AliTPCcalibTracksGain::AddCluster(AliTPCclusterMI* cluster, Float_t /*momenta*/, Float_t/* mdedx*/, Int_t padType,
769 Float_t xcenter, TVectorD& dedxQ, TVectorD& /*dedxM*/, Float_t /*fraction*/, Float_t fraction2, Float_t dedge,
770 TVectorD& /*parY*/, TVectorD& /*parZ*/, TVectorD& meanPos) {
772 // Adds cluster to the appropriate fitter for later analysis.
773 // The charge used for the fit is the maximum charge for this specific cluster or the
774 // accumulated charge per cluster, depending on the value of fgkUseTotalCharge.
775 // Depending on the pad size where the cluster is registered, the value will be put in
776 // the appropriate fitter. Furthermore, for each pad size three different types of fitters
777 // are used. The fit functions are the same for all fitters (parabolic functions), but the value
778 // added to each fitter is different. The simple fitter gets the charge plugged in as is, the sqrt fitter
779 // gets the square root of the charge, and the log fitter gets fgkM*(1+q/fgkM), where q is the original charge
783 Float_t kfraction = 0.7;
787 // Where to put selection on threshold?
788 // Defined by the Q/dEdxT variable - see debug streamer:
790 // Debug stream variables: (Where tu cut ?)
791 // chain0->Draw("Cl.fQ/dedxQ.fElements[1]>>his(100,0,3)","fraction2<0.6&&dedge>3","",1000000);
793 // chain0->Draw("Cl.fMax/dedxM.fElements[1]>>his(100,0,3)","fraction2<0.6&&dedge>3","",1000000)
795 // chain0->Draw("Cl.fQ/dedxQ.fElements[2]>>his(100,0,3)","fraction2<0.7&&dedge>3","",1000000)
797 // chain0->Draw("Cl.fMax/dedxM.fElements[2]>>his(100,0,3)","fraction2<0.7&&dedge>3","",1000000)
799 // chain0->Draw("Cl.fQ/dedxQ.fElements[3]>>his(100,0,3)","fraction2<0.8&&dedge>3","",1000000)
802 // chain0->Draw("Cl.fQ/dedxQ.fElements[4]>>his(100,0,3)","fraction2<0.9&&dedge>3","",1000000)
805 // Fraction choosen 0.7
808 Error("AddCluster", "Cluster not valid.");
812 if (dedge < kedge) return;
813 if (fraction2 > kfraction) return;
815 //Int_t padType = GetPadType(cluster->GetX());
817 //Double_t centerPad[2] = {0};
818 //AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad);
819 //xx[0] = cluster->GetX() - centerPad[0];
820 //xx[1] = cluster->GetY() - centerPad[1];
821 xx[0] = cluster->GetX() - xcenter;
822 xx[1] = cluster->GetY();
823 xx[2] = xx[0] * xx[0];
824 xx[3] = xx[1] * xx[1];
825 xx[4] = xx[0] * xx[1];
826 xx[5] = TMath::Abs(cluster->GetZ()) - TMath::Abs(meanPos[4]);
827 xx[6] = xx[5] * xx[5];
829 // Update profile histograms
835 Int_t segment = cluster->GetDetector() % 36;
836 Double_t q = fgkUseTotalCharge ? ((Double_t)(GetQNorm(cluster))) : ((Double_t)(GetMaxNorm(cluster))); // note: no normalization to pad size!
838 // just for debugging
841 GetRowPad(cluster->GetX(), cluster->GetY(), row, pad);
842 fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->GetValue(row, pad));
844 // correct charge by normalising to mean charge per track
847 // just for debugging
848 fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->GetValue(row, pad));
850 Double_t sqrtQ = TMath::Sqrt(q);
851 Double_t logQ = fgkM * TMath::Log(1 + q / fgkM);
852 TLinearFitter * fitter =0;
854 fitter = fSimpleFitter->GetFitter(segment, padType);
855 fitter->AddPoint(xx, q);
857 fitter = fSqrtFitter->GetFitter(segment, padType);
858 fitter->AddPoint(xx, sqrtQ);
860 fitter = fLogFitter->GetFitter(segment, padType);
861 fitter->AddPoint(xx, logQ);
863 fitter=fSingleSectorFitter->GetFitter(0, padType);
864 fitter->AddPoint(xx, q);
866 // this will be gone for the a new ROOT version > v5-17-05
867 if (padType == kShortPads)
868 fNShortClusters[segment]++;
869 if (padType == kMediumPads)
870 fNMediumClusters[segment]++;
871 if (padType == kLongPads)
872 fNLongClusters[segment]++;
875 void AliTPCcalibTracksGain::Evaluate(Bool_t robust, Double_t frac) {
877 // Evaluates all fitters contained in this object.
878 // If the robust option is set to kTRUE a robust fit is performed with frac as
879 // the minimal fraction of good points (see TLinearFitter::EvalRobust for details).
880 // Beware: Robust fitting is much slower!
883 fSimpleFitter->Evaluate(robust, frac);
884 fSqrtFitter->Evaluate(robust, frac);
885 fLogFitter->Evaluate(robust, frac);
886 fSingleSectorFitter->Evaluate(robust, frac);
902 AliTPCCalPad* AliTPCcalibTracksGain::CreateFitCalPad(UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
904 // Creates the calibration object AliTPCcalPad using fitted parameterization
907 for (UInt_t iSector = 0; iSector < 72; iSector++)
908 tpc.Add(CreateFitCalROC(iSector, fitType, undoTransformation, normalizeToPadSize));
909 return new AliTPCCalPad(&tpc);
912 AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
914 // Create the AliTPCCalROC with the values per pad
915 // sector - sector of interest
921 GetParameters(sector % 36, 0, fitType, par);
922 return CreateFitCalROC(sector, 0, par, fitType, undoTransformation, normalizeToPadSize);
925 GetParameters(sector % 36, 1, fitType, par);
926 AliTPCCalROC* roc1 = CreateFitCalROC(sector, 1, par, fitType, undoTransformation, normalizeToPadSize);
927 GetParameters(sector % 36, 2, fitType, par);
928 AliTPCCalROC* roc2 = CreateFitCalROC(sector, 2, par, fitType, undoTransformation, normalizeToPadSize);
929 AliTPCCalROC* roc3 = CreateCombinedCalROC(roc1, roc2);
936 AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t padType, TVectorD &fitParam, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
938 // This function is essentially a copy of AliTPCCalROC::CreateGlobalFitCalROC(...), with the
939 // modifications, that the center of the region of same pad size is used as the origin
940 // of the fit function instead of the center of the ROC.
941 // The possibility of a linear fit is removed as well because it is not needed.
942 // Only values for pads with the given pad size are calculated, the rest is 0.
943 // Set undoTransformation for undoing the transformation that was applied to the
944 // charge values before they were put into the fitter (thus allowing comparison to the original
945 // charge values). For fitType use 0 for the simple fitter, 1 for the sqrt fitter, 2 for the log fitter.
946 // If normalizeToPadSize is true, the values are normalized to the pad size.
947 // Please be aware, that you even need to specify the fitType if you want to normalize to the pad size without
948 // undoing the transformation (because normalizing involves undoing the trafo first, then normalizing, then
949 // applying the trafo again).
950 // Please note: The normalization to the pad size is a simple linear scaling with the pad length, which
951 // actually doesn't describe reality!
955 Double_t centerPad[2] = {0};
956 Float_t localXY[3] = {0};
957 AliTPCROC* tpcROC = AliTPCROC::Instance();
958 if ((padType == 0 && sector >= tpcROC->GetNInnerSector()) || (padType > 0 && sector < tpcROC->GetNInnerSector()) || sector >= tpcROC->GetNSector())
960 AliTPCCalROC* lROCfitted = new AliTPCCalROC(sector);
961 //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
967 endRow = lROCfitted->GetNrows();
975 endRow = lROCfitted->GetNrows();
979 AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad);
981 for (UInt_t irow = startRow; irow < endRow; irow++) {
982 for (UInt_t ipad = 0; ipad < lROCfitted->GetNPads(irow); ipad++) {
983 tpcROC->GetPositionLocal(sector, irow, ipad, localXY); // calculate position localXY by pad and row number
984 dlx = localXY[0] - centerPad[0];
985 dly = localXY[1] - centerPad[1];
986 value = fitParam[0] + fitParam[1]*dlx + fitParam[2]*dly + fitParam[3]*dlx*dlx + fitParam[4]*dly*dly + fitParam[5]*dlx*dly;
988 // Let q' = value be the transformed value without any pad size corrections,
989 // let T be the transformation and let l be the pad size
990 // 1) don't undo transformation, don't normalize: return q'
991 // 2) undo transformation, don't normalize: return T^{-1} q'
992 // 3) undo transformation, normalize: return (T^{-1} q') / l
993 // 4) don't undo transformation, normalize: return T((T^{-1} q') / l)
994 if (!undoTransformation && !normalizeToPadSize) {/* value remains unchanged */} // (1)
995 else { // (2), (3), (4)
998 case 0: /* value remains unchanged */ break;
999 case 1: value = value * value; break;
1000 case 2: value = (TMath::Exp(value / fgkM) - 1) * fgkM; break;
1001 default: Error("CreateFitCalROC", "Wrong fit type."); break;
1003 if (normalizeToPadSize) value /= GetPadLength(localXY[0]); // (3)
1005 if (!undoTransformation && normalizeToPadSize) { // (4)
1008 case 0: /* value remains unchanged */ break;
1009 case 1: value = TMath::Sqrt(value); break;
1010 case 2: value = fgkM * TMath::Log(1 + value / fgkM); break;
1011 default: Error("CreateFitCalROC", "Wrong fit type."); break;
1014 lROCfitted->SetValue(irow, ipad, value);
1020 AliTPCCalROC* AliTPCcalibTracksGain::CreateCombinedCalROC(const AliTPCCalROC* roc1, const AliTPCCalROC* roc2) {
1022 // Combines the medium pad size values of roc1 with the long pad size values of roc2 into a new
1023 // AliTPCCalROC. Returns a null pointer if any one of the ROCs is an IROC; issues a warning message
1024 // if the sectors of roc1 and roc2 don't match, but still continue and use the sector of roc1 as the
1025 // sector of the new ROC.
1028 if (!roc1 || !roc2) return 0;
1029 if ((Int_t)(roc1->GetSector()) < fgTPCparam->GetNInnerSector()) return 0;
1030 if ((Int_t)(roc2->GetSector()) < fgTPCparam->GetNInnerSector()) return 0;
1031 if (roc1->GetSector() != roc2->GetSector()) Warning("CreateCombinedCalROC", "Sector number mismatch.");
1032 AliTPCCalROC* roc = new AliTPCCalROC(roc1->GetSector());
1034 for (UInt_t iRow = 0; iRow < 64; iRow++) {
1035 for (UInt_t iPad = 0; iPad < roc->GetNPads(iRow); iPad++)
1036 roc->SetValue(iRow, iPad, roc1->GetValue(iRow, iPad));
1038 for (UInt_t iRow = 64; iRow < roc->GetNrows(); iRow++) {
1039 for (UInt_t iPad = 0; iPad < roc->GetNPads(iRow); iPad++)
1040 roc->SetValue(iRow, iPad, roc2->GetValue(iRow, iPad));
1045 Bool_t AliTPCcalibTracksGain::GetParameters(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitParam) {
1047 // Puts the fit parameters for the specified segment (IROC & OROC), padType and fitType
1048 // into the fitParam TVectorD (which should contain 8 elements).
1049 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
1050 // Note: The fitter has to be evaluated first!
1052 TLinearFitter * fitter = GetFitter(segment, padType, fitType);
1055 fitter->GetParameters(fitParam);
1058 Error("AliTPCcalibTracksGain::GetParameters",
1059 Form("Fitter%d_%d_%d not availble", segment, padType, fitType));
1065 void AliTPCcalibTracksGain::GetErrors(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitError) {
1067 // Puts the fit parameter errors for the specified segment (IROC & OROC), padType and fitType
1068 // into the fitError TVectorD (which should contain 8 elements).
1069 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
1070 // Note: The fitter has to be evaluated first!
1073 GetFitter(segment, padType, fitType)->GetErrors(fitError);
1074 fitError *= TMath::Sqrt(GetRedChi2(segment, padType, fitType));
1077 Double_t AliTPCcalibTracksGain::GetRedChi2(UInt_t segment, UInt_t padType, UInt_t fitType) {
1079 // Returns the reduced chi^2 value for the specified segment, padType and fitType.
1080 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
1081 // Note: The fitter has to be evaluated first!
1084 // this will be gone for the a new ROOT version > v5-17-05
1085 Int_t lNClusters = 0;
1088 lNClusters = fNShortClusters[segment];
1091 lNClusters = fNMediumClusters[segment];
1094 lNClusters = fNLongClusters[segment];
1097 return GetFitter(segment, padType, fitType)->GetChisquare()/(lNClusters - 8);
1100 void AliTPCcalibTracksGain::GetCovarianceMatrix(UInt_t segment, UInt_t padType, UInt_t fitType, TMatrixD& covMatrix) {
1102 // Returns the covariance matrix for the specified segment, padType, fitType.
1103 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
1106 GetFitter(segment, padType, fitType)->GetCovarianceMatrix(covMatrix);
1109 TLinearFitter* AliTPCcalibTracksGain::GetFitter(UInt_t segment, UInt_t padType, UInt_t fitType) {
1111 // Returns the TLinearFitter object for the specified segment, padType, fitType.
1112 // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
1117 return fSimpleFitter->GetFitter(segment, padType);
1119 return fSqrtFitter->GetFitter(segment, padType);
1121 return fLogFitter->GetFitter(segment, padType);
1123 return fSingleSectorFitter->GetFitter(0, padType);
1128 Double_t AliTPCcalibTracksGain::GetPadLength(Double_t lx) {
1130 // The function returns 0.75 for an IROC, 1. for an OROC at medium pad size position,
1131 // 1.5 for an OROC at long pad size position, -1 if out of bounds.
1134 Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2;
1135 Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2;
1136 Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2;
1137 Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2;
1138 Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2;
1139 Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2;
1142 if (lx >= irocLow && lx <= irocUp) return 0.75;
1143 // if OROC medium pads
1144 if (lx >= orocLow1 && lx <= orocUp1) return 1.;
1145 // if OROC long pads
1146 if (lx >= orocLow2 && lx <= orocUp2) return 1.5;
1151 Int_t AliTPCcalibTracksGain::GetPadType(Double_t lx) {
1153 // The function returns 0 for an IROC, 1 for an OROC at medium pad size position,
1154 // 2 for an OROC at long pad size position, -1 if out of bounds.
1157 if (GetPadLength(lx) == 0.75) return 0;
1158 else if (GetPadLength(lx) == 1.) return 1;
1159 else if (GetPadLength(lx) == 1.5) return 2;
1163 // ONLY FOR DEBUGGING PURPOSES - REMOVE ME WHEN NOT NEEDED ANYMORE
1164 Bool_t AliTPCcalibTracksGain::GetRowPad(Double_t lx, Double_t ly, Int_t& row, Int_t& pad) {
1166 // Calculate the row and pad number when the local coordinates are given.
1167 // Returns kFALSE if the position is out of range, otherwise return kTRUE.
1168 // WARNING: This function is preliminary and probably isn't very accurate!!
1171 Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2;
1172 //Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2;
1173 Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2;
1174 //Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2;
1175 Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2;
1176 //Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2;
1178 if (GetPadType(lx) == 0) {
1179 row = (Int_t)((lx - irocLow) / fgTPCparam->GetInnerPadPitchLength());
1180 pad = (Int_t)((ly + fgTPCparam->GetYInner(row)) / fgTPCparam->GetInnerPadPitchWidth());
1181 } else if (GetPadType(lx) == 1) {
1182 row = (Int_t)((lx - orocLow1) / fgTPCparam->GetOuter1PadPitchLength());
1183 pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth());
1184 } else if (GetPadType(lx) == 2) {
1185 row = fgTPCparam->GetNRowUp1() + (Int_t)((lx - orocLow2) / fgTPCparam->GetOuter2PadPitchLength());
1186 pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth());
1192 void AliTPCcalibTracksGain::DumpTrack(AliTPCseed* track) {
1194 // Dump track information to the debug stream
1204 TVectorD meanPos[3];
1207 for (Int_t ipad = 0; ipad < 3; ipad++) {
1208 dedxM[ipad].ResizeTo(5);
1209 dedxQ[ipad].ResizeTo(5);
1210 parY[ipad].ResizeTo(3);
1211 parZ[ipad].ResizeTo(3);
1212 meanPos[ipad].ResizeTo(6);
1213 Bool_t isOK = GetDedx(track, ipad, rows, sector[ipad], npoints[ipad], dedxM[ipad], dedxQ[ipad], parY[ipad], parZ[ipad], meanPos[ipad]);
1215 AddTracklet(sector[ipad],ipad, dedxQ[ipad], dedxM[ipad], parY[ipad], parZ[ipad], meanPos[ipad] );
1219 TTreeSRedirector * cstream = GetDebugStreamer();
1221 (*cstream) << "Track" <<
1222 "Track.=" << track << // track information
1227 if ( GetStreamLevel()>1 && count>1){
1228 (*cstream) << "TrackG" <<
1229 "Track.=" << track << // track information
1231 // info for pad type 0
1232 "sector0="<<sector[0]<<
1233 "npoints0="<<npoints[0]<<
1234 "dedxM0.="<<&dedxM[0]<<
1235 "dedxQ0.="<<&dedxQ[0]<<
1236 "parY0.="<<&parY[0]<<
1237 "parZ0.="<<&parZ[0]<<
1238 "meanPos0.="<<&meanPos[0]<<
1240 // info for pad type 1
1241 "sector1="<<sector[1]<<
1242 "npoints1="<<npoints[1]<<
1243 "dedxM1.="<<&dedxM[1]<<
1244 "dedxQ1.="<<&dedxQ[1]<<
1245 "parY1.="<<&parY[1]<<
1246 "parZ1.="<<&parZ[1]<<
1247 "meanPos1.="<<&meanPos[1]<<
1249 // info for pad type 2
1250 "sector2="<<sector[2]<<
1251 "npoints2="<<npoints[2]<<
1252 "dedxM2.="<<&dedxM[2]<<
1253 "dedxQ2.="<<&dedxQ[2]<<
1254 "parY2.="<<&parY[2]<<
1255 "parZ2.="<<&parZ[2]<<
1256 "meanPos2.="<<&meanPos[2]<<
1263 Bool_t AliTPCcalibTracksGain::GetDedx(AliTPCseed* track, Int_t padType, Int_t* /*rows*/,
1264 Int_t §or, Int_t& npoints,
1265 TVectorD &dedxM, TVectorD &dedxQ,
1266 TVectorD &parY, TVectorD &parZ, TVectorD&meanPos)
1269 // GetDedx for given sector for given track
1270 // padType - type of pads
1273 static TLinearFitter fitY(2, "pol1");
1274 static TLinearFitter fitZ(2, "pol1");
1275 fitY.StoreData(kFALSE);
1276 fitZ.StoreData(kFALSE);
1279 Int_t firstRow = 0, lastRow = 0;
1281 Float_t xcenter = 0;
1282 const Float_t ktany = TMath::Tan(TMath::DegToRad() * 10);
1283 const Float_t kedgey = 4.;
1286 lastRow = fgTPCparam->GetNRowLow();
1290 firstRow = fgTPCparam->GetNRowLow();
1291 lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1();
1295 firstRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1();
1296 lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp();
1299 minRow = (lastRow - firstRow) / 2;
1302 Int_t nclusters = 0;
1303 Int_t nclustersNE = 0; // number of not edge clusters
1304 Int_t lastSector = -1;
1305 Float_t amplitudeQ[100];
1306 Float_t amplitudeM[100];
1314 for (Int_t iCluster = firstRow; iCluster < lastRow; iCluster++) {
1315 AliTPCclusterMI* cluster = track->GetClusterPointer(iCluster);
1317 Int_t detector = cluster->GetDetector() ;
1318 if (lastSector == -1) lastSector = detector;
1319 if (lastSector != detector) continue;
1320 amplitudeQ[nclusters] = GetQNorm(cluster);
1321 amplitudeM[nclusters] = GetMaxNorm(cluster);
1322 rowIn[nclusters] = iCluster;
1324 Double_t dx = cluster->GetX() - xcenter;
1325 Double_t y = cluster->GetY();
1326 Double_t z = cluster->GetZ();
1327 fitY.AddPoint(&dx, y);
1328 fitZ.AddPoint(&dx, z);
1335 if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) nclustersNE++;
1339 if (nclusters < minRow / 2) return kFALSE;
1340 if (nclustersNE < minRow / 2) return kFALSE;
1341 for (Int_t i = 0; i < 6; i++) meanPos[i] /= Double_t(nclusters);
1344 fitY.GetParameters(parY);
1345 fitZ.GetParameters(parZ);
1347 // calculate truncated mean
1349 TMath::Sort(nclusters, amplitudeQ, index, kFALSE);
1354 for (Int_t i = 0; i < 5; i++) {
1363 for (Int_t i = 0; i < nclusters; i++) {
1364 Int_t rowSorted = rowIn[index[i]];
1365 AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
1367 if (TMath::Abs(cluster->GetY()) > cluster->GetX()*ktany - kedgey) continue; //don't take edge clusters
1369 if (inonEdge < nclustersNE * 0.5) {
1371 dedxQ[0] += amplitudeQ[index[i]];
1372 dedxM[0] += amplitudeM[index[i]];
1374 if (inonEdge < nclustersNE * 0.6) {
1376 dedxQ[1] += amplitudeQ[index[i]];
1377 dedxM[1] += amplitudeM[index[i]];
1379 if (inonEdge < nclustersNE * 0.7) {
1381 dedxQ[2] += amplitudeQ[index[i]];
1382 dedxM[2] += amplitudeM[index[i]];
1384 if (inonEdge < nclustersNE * 0.8) {
1386 dedxQ[3] += amplitudeQ[index[i]];
1387 dedxM[3] += amplitudeM[index[i]];
1389 if (inonEdge < nclustersNE * 0.9) {
1391 dedxQ[4] += amplitudeQ[index[i]];
1392 dedxM[4] += amplitudeM[index[i]];
1395 for (Int_t i = 0; i < 5; i++) {
1396 dedxQ[i] /= ndedx[i];
1397 dedxM[i] /= ndedx[i];
1399 TTreeSRedirector * cstream = GetDebugStreamer();
1401 Float_t momenta = track->GetP();
1402 Float_t mdedx = track->GetdEdx();
1403 for (Int_t i = 0; i < nclusters; i++) {
1404 Int_t rowSorted = rowIn[index[i]];
1405 AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
1407 printf("Problem\n");
1410 if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) inonEdge++;
1411 Float_t dedge = cluster->GetX()*ktany - TMath::Abs(cluster->GetY());
1412 Float_t fraction = Float_t(i) / Float_t(nclusters);
1413 Float_t fraction2 = Float_t(inonEdge) / Float_t(nclustersNE);
1415 AddCluster(cluster, momenta, mdedx, padType, xcenter, dedxQ, dedxM, fraction, fraction2, dedge, parY, parZ, meanPos);
1416 Float_t gain = GetGain(cluster);
1417 if (cstream) (*cstream) << "dEdx" <<
1418 "Cl.=" << cluster << // cluster of interest
1419 "gain="<<gain<< // gain at cluster position
1420 "P=" << momenta << // track momenta
1421 "dedx=" << mdedx << // mean dedx - corrected for angle
1422 "IPad=" << padType << // pad type 0..2
1423 "xc=" << xcenter << // x center of chamber
1424 "dedxQ.=" << &dedxQ << // dedxQ - total charge
1425 "dedxM.=" << &dedxM << // dedxM - maximal charge
1426 "fraction=" << fraction << // fraction - order in statistic (0,1)
1427 "fraction2=" << fraction2 << // fraction - order in statistic (0,1)
1428 "dedge=" << dedge << // distance to the edge
1429 "parY.=" << &parY << // line fit
1430 "parZ.=" << &parZ << // line fit
1431 "meanPos.=" << &meanPos << // mean position (dx, dx^2, y,y^2, z, z^2)
1435 if (cstream) (*cstream) << "dEdxT" <<
1436 "P=" << momenta << // track momenta
1437 "npoints="<<inonEdge<< // number of points
1438 "sector="<<lastSector<< // sector number
1439 "dedx=" << mdedx << // mean dedx - corrected for angle
1440 "IPad=" << padType << // pad type 0..2
1441 "xc=" << xcenter << // x center of chamber
1442 "dedxQ.=" << &dedxQ << // dedxQ - total charge
1443 "dedxM.=" << &dedxM << // dedxM - maximal charge
1444 "parY.=" << &parY << // line fit
1445 "parZ.=" << &parZ << // line fit
1446 "meanPos.=" << &meanPos << // mean position (dx, dx^2, y,y^2, z, z^2)
1449 sector = lastSector;
1454 void AliTPCcalibTracksGain::AddTracklet(UInt_t sector, UInt_t padType,TVectorD &dedxQ, TVectorD &dedxM,TVectorD& parY, TVectorD& parZ, TVectorD& meanPos){
1456 // Add measured point - dedx to the fitter
1459 //chain->SetAlias("dr","(250-abs(meanPos.fElements[4]))/250");
1460 //chain->SetAlias("tz","(0+abs(parZ.fElements[1]))");
1461 //chain->SetAlias("ty","(0+abs(parY.fElements[1]))");
1462 //chain->SetAlias("corrg","sqrt((1+ty^2)*(1+tz^2))");
1463 //expession fast - TString *strq0 = toolkit.FitPlane(chain,"dedxQ.fElements[2]","dr++ty++tz++dr*ty++dr*tz++ty*tz++ty^2++tz^2","IPad==0",chi2,npoints,param,covar,0,100000);
1467 // z and angular part
1470 xxx[0] = (250.-TMath::Abs(meanPos[4]))/250.;
1471 xxx[1] = TMath::Abs(parY[1]);
1472 xxx[2] = TMath::Abs(parZ[1]);
1473 xxx[3] = xxx[0]*xxx[1];
1474 xxx[4] = xxx[0]*xxx[2];
1475 xxx[5] = xxx[1]*xxx[2];
1476 xxx[6] = xxx[0]*xxx[0];
1477 xxx[7] = xxx[1]*xxx[1];
1478 xxx[8] = xxx[2]*xxx[2];
1482 Int_t tsector = sector%36;
1483 for (Int_t i=0;i<35;i++){
1484 xxx[9+i]=(i==tsector)?1:0;
1486 TLinearFitter *fitterM = fFitter0M;
1487 if (padType==1) fitterM=fFitter1M;
1488 if (padType==2) fitterM=fFitter2M;
1489 fitterM->AddPoint(xxx,dedxM[1]);
1491 TLinearFitter *fitterT = fFitter0T;
1492 if (padType==1) fitterT = fFitter1T;
1493 if (padType==2) fitterT = fFitter2T;
1494 fitterT->AddPoint(xxx,dedxQ[1]);
1496 TLinearFitter *dfitterM = fDFitter0M;
1497 if (padType==1) dfitterM=fDFitter1M;
1498 if (padType==2) dfitterM=fDFitter2M;
1499 dfitterM->AddPoint(xxx,dedxM[1]);
1501 TLinearFitter *dfitterT = fDFitter0T;
1502 if (padType==1) dfitterT = fDFitter1T;
1503 if (padType==2) dfitterT = fDFitter2T;
1504 dfitterT->AddPoint(xxx,dedxQ[1]);
1508 TGraph *AliTPCcalibTracksGain::CreateAmpGraph(Int_t ipad, Bool_t qmax){
1510 // create the amplitude graph
1511 // The normalized amplitudes are extrapolated to the 0 angle (y,z) and 0 drift length
1516 if (ipad==0) fFitter0M->GetParameters(vec);
1517 if (ipad==1) fFitter1M->GetParameters(vec);
1518 if (ipad==2) fFitter2M->GetParameters(vec);
1520 if (ipad==0) fFitter0T->GetParameters(vec);
1521 if (ipad==1) fFitter1T->GetParameters(vec);
1522 if (ipad==2) fFitter2T->GetParameters(vec);
1527 for (Int_t i=0;i<35;i++){
1529 amp[i]=vec[10+i]+vec[0];
1532 Float_t mean = TMath::Mean(36,amp);
1533 for (Int_t i=0;i<36;i++){
1535 amp[i]=(amp[i]-mean)/mean;
1537 TGraph *gr = new TGraph(36,sec,amp);
1542 void AliTPCcalibTracksGain::UpdateClusterParam(AliTPCClusterParam* clparam){
1544 // SetQ normalization parameters
1546 // void SetQnorm(Int_t ipad, Int_t itype, TVectorD * norm);
1557 fDFitter0T->GetParameters(vec);
1558 clparam->SetQnorm(0,0,&vec);
1559 fDFitter1T->GetParameters(vec);
1560 clparam->SetQnorm(1,0,&vec);
1561 fDFitter2T->GetParameters(vec);
1562 clparam->SetQnorm(2,0,&vec);
1564 fDFitter0M->GetParameters(vec);
1565 clparam->SetQnorm(0,1,&vec);
1566 fDFitter1M->GetParameters(vec);
1567 clparam->SetQnorm(1,1,&vec);
1568 fDFitter2M->GetParameters(vec);
1569 clparam->SetQnorm(2,1,&vec);
1575 void AliTPCcalibTracksGain::Analyze(){
1583 TVectorD * AliTPCcalibTracksGain::MakeQPosNorm(TTree * chain0, Int_t ipad, Bool_t isMax, Int_t maxPoints, Int_t verbose){
1586 // chain0 - the tree with information -Debug stream
1590 // isMax - kFALSE - total charge param
1591 // kTRUE - Max charge param
1593 // maxPoints - number of points for fit
1602 // Make Q normalization as function of following parameters
1603 // 1 - dp - relative pad position
1604 // 2 - dt - relative time position
1605 // 3 - di - drift length (norm to 1);
1606 // 4 - dq0 - Tot/Max charge
1607 // 5 - dq1 - Max/Tot charge
1608 // 6 - sy - sigma y - shape
1609 // 7 - sz - sigma z - shape
1611 // Coeficient of Taylor expansion fitted
1612 // Fit parameters returned as TVectorD
1613 // Fit parameters to be used in corresponding correction function
1614 // in AliTPCclusterParam
1617 TStatToolkit toolkit;
1622 TCut cutA("dedge>3&&fraction2<0.7");
1623 chain0->SetAlias("dp","((Cl.fPad-int(Cl.fPad)-0.5)/0.5)");
1624 chain0->SetAlias("dt","((Cl.fTimeBin-int(Cl.fTimeBin)-0.5)/0.5)");
1625 chain0->SetAlias("di","(sqrt(1.-abs(Cl.fZ)/250.))");
1626 chain0->SetAlias("dq0","(0.2*(Cl.fQ+2)/(Cl.fMax+2))");
1627 chain0->SetAlias("dq1","(5*(Cl.fMax+2)/(Cl.fQ+2))");
1628 chain0->SetAlias("sy","(0.32/sqrt(0.01^2+Cl.fSigmaY2))");
1629 chain0->SetAlias("sz","(0.32/sqrt(0.01^2+Cl.fSigmaZ2))");
1632 fstring+="dp++"; //1
1633 fstring+="dt++"; //2
1634 fstring+="dp*dp++"; //3
1635 fstring+="dt*dt++"; //4
1636 fstring+="dt*dt*dt++"; //5
1637 fstring+="dp*dt++"; //6
1638 fstring+="dp*dt*dt++"; //7
1639 fstring+="(dq0)++"; //8
1640 fstring+="(dq1)++"; //9
1643 fstring+="dp*dp*(di)++"; //10
1644 fstring+="dt*dt*(di)++"; //11
1645 fstring+="dp*dp*sy++"; //12
1646 fstring+="dt*sz++"; //13
1647 fstring+="dt*dt*sz++"; //14
1648 fstring+="dt*dt*dt*sz++"; //15
1650 fstring+="dp*dp*1*sy*sz++"; //16
1651 fstring+="dt*sy*sz++"; //17
1652 fstring+="dt*dt*sy*sz++"; //18
1653 fstring+="dt*dt*dt*sy*sz++"; //19
1655 fstring+="dp*dp*(dq0)++"; //20
1656 fstring+="dt*1*(dq0)++"; //21
1657 fstring+="dt*dt*(dq0)++"; //22
1658 fstring+="dt*dt*dt*(dq0)++"; //23
1660 fstring+="dp*dp*(dq1)++"; //24
1661 fstring+="dt*(dq1)++"; //25
1662 fstring+="dt*dt*(dq1)++"; //26
1663 fstring+="dt*dt*dt*(dq1)++"; //27
1666 if (isMax) var = "Cl.fMax/gain/dedxM.fElements[2]";
1667 if (!isMax) var = "Cl.fQ/gain/dedxQ.fElements[2]";
1668 TString cutP="IPad==";
1671 TString *strq0 = toolkit.FitPlane(chain0,var.Data(),fstring.Data(), cutP.Data()+cutA, chi2,npoints,fitParam,covMatrix,-1,0,maxPoints);
1675 printf("Chi2/npoints = %f",TMath::Sqrt(chi2/npoints));
1676 printf("\nFit function\n:%s\n",strq0->Data());
1678 TVectorD *vec = new TVectorD(fitParam);
1682 void AliTPCcalibTracksGain::MakeQPosNormAll(TTree * chain, AliTPCClusterParam * param, Int_t maxPoints, Int_t verbose){
1684 // Fill the content of the of the AliTPCclusterParam
1685 // with fitted values of corrections
1687 param->fPosQTnorm[0] = MakeQPosNorm(chain,0,kTRUE,100000,kTRUE);
1688 param->fPosQTnorm[1] = MakeQPosNorm(chain,1,kTRUE,100000,kTRUE);
1689 param->fPosQTnorm[2] = MakeQPosNorm(chain,1,kTRUE,100000,kTRUE);
1691 param->fPosQMnorm[0] = MakeQPosNorm(chain,0,kFALSE,100000,kTRUE);
1692 param->fPosQMnorm[1] = MakeQPosNorm(chain,1,kFALSE,100000,kTRUE);
1693 param->fPosQMnorm[2] = MakeQPosNorm(chain,2,kFALSE,100000,kTRUE);
1700 Position correction fit:
1702 TStatToolkit toolkit;
1708 TCut cutA("dedge>3&&fraction2<0.7");
1709 chain0->SetAlias("dp","((Cl.fPad-int(Cl.fPad)-0.5)/0.5)");
1710 chain0->SetAlias("dt","((Cl.fTimeBin-int(Cl.fTimeBin)-0.5)/0.5)");
1711 chain0->SetAlias("di","(sqrt(1.-abs(Cl.fZ)/250.))");
1712 chain0->SetAlias("dq0","(0.2*(Cl.fQ+2)/(Cl.fMax+2))");
1713 chain0->SetAlias("dq1","(5*(Cl.fMax+2)/(Cl.fQ+2))");
1714 chain0->SetAlias("sy","(0.2/sqrt(0.01^2+Cl.fSigmaY2))");
1715 chain0->SetAlias("sz","(0.2/sqrt(0.01^2+Cl.fSigmaZ2))");
1719 fstring+="dp++"; //1
1720 fstring+="dt++"; //2
1721 fstring+="dp*dp++"; //3
1722 fstring+="dt*dt++"; //4
1723 fstring+="dt*dt*dt++"; //5
1724 fstring+="dp*dt++"; //6
1725 fstring+="dp*dt*dt++"; //7
1726 fstring+="(dq0)++"; //8
1727 fstring+="(dq1)++"; //9
1730 fstring+="dp*dp*(di)++"; //10
1731 fstring+="dt*dt*(di)++"; //11
1732 fstring+="dp*dp*sy++"; //12
1733 fstring+="dt*sz++"; //13
1734 fstring+="dt*dt*sz++"; //14
1735 fstring+="dt*dt*dt*sz++"; //15
1737 fstring+="dp*dp*1*sy*sz++"; //16
1738 fstring+="dt*sy*sz++"; //17
1739 fstring+="dt*dt*sy*sz++"; //18
1740 fstring+="dt*dt*dt*sy*sz++"; //19
1742 fstring+="dp*dp*(dq0)++"; //20
1743 fstring+="dt*1*(dq0)++"; //21
1744 fstring+="dt*dt*(dq0)++"; //22
1745 fstring+="dt*dt*dt*(dq0)++"; //23
1747 fstring+="dp*dp*(dq1)++"; //24
1748 fstring+="dt*(dq1)++"; //25
1749 fstring+="dt*dt*(dq1)++"; //26
1750 fstring+="dt*dt*dt*(dq1)++"; //27
1753 TString *strq0 = toolkit.FitPlane(chain0,"Cl.fMax/gain/dedxM.fElements[2]",fstring->Data(), "IPad==0"+cutA, chi2,npoints,fitParam,covMatrix,-1,0,200000);
1754 TString *strqt0 = toolkit.FitPlane(chain0,"Cl.fQ/gain/dedxQ.fElements[2]",fstring->Data(), "IPad==0"+cutA, chi2,npoints,fitParam,covMatrix,-1,0,200000);
1756 chain0->SetAlias("qcorM0",strq0->Data());
1757 chain0->SetAlias("qcorT0",strqt0->Data());
1758 //chain0->SetAlias("mmqcorM0","min(max(qcorM0,0.75),1.15)");
1759 chain0->Draw("(Cl.fMax/gain/dedxM.fElements[2]):min(max(qcorM0,0.75),1.15)","IPad==0"+cutA,"prof",100000)
1764 sigma fit with shape 0.2257
1768 qmax sigma fit 0.2702
1769 qmax sigma fit+ratio 0.2638