2 // Class to do the energy correction of FMD ESD data
4 #include "AliFMDEnergyFitter.h"
5 #include "AliForwardCorrectionManager.h"
13 #include <TClonesArray.h>
14 #include <TFitResult.h>
20 ClassImp(AliFMDEnergyFitter)
22 ; // This is for Emacs
25 const char* fgkEDistFormat = "%s_etabin%03d";
29 //____________________________________________________________________
30 AliFMDEnergyFitter::AliFMDEnergyFitter()
42 fUseIncreasingBins(true),
49 //____________________________________________________________________
50 AliFMDEnergyFitter::AliFMDEnergyFitter(const char* title)
51 : TNamed("fmdEnergyFitter", title),
62 fUseIncreasingBins(true),
68 fEtaAxis.SetName("etaAxis");
69 fEtaAxis.SetTitle("#eta");
70 fRingHistos.Add(new RingHistos(1, 'I'));
71 fRingHistos.Add(new RingHistos(2, 'I'));
72 fRingHistos.Add(new RingHistos(2, 'O'));
73 fRingHistos.Add(new RingHistos(3, 'I'));
74 fRingHistos.Add(new RingHistos(3, 'O'));
77 //____________________________________________________________________
78 AliFMDEnergyFitter::AliFMDEnergyFitter(const AliFMDEnergyFitter& o)
82 fNParticles(o.fNParticles),
83 fMinEntries(o.fMinEntries),
84 fFitRangeBinWidth(o.fFitRangeBinWidth),
86 fDoMakeObject(o.fDoMakeObject),
90 fUseIncreasingBins(o.fUseIncreasingBins),
91 fMaxRelParError(o.fMaxRelParError),
92 fMaxChi2PerNDF(o.fMaxChi2PerNDF),
93 fMinWeight(o.fMinWeight),
96 TIter next(&o.fRingHistos);
98 while ((obj = next())) fRingHistos.Add(obj);
101 //____________________________________________________________________
102 AliFMDEnergyFitter::~AliFMDEnergyFitter()
104 fRingHistos.Delete();
107 //____________________________________________________________________
109 AliFMDEnergyFitter::operator=(const AliFMDEnergyFitter& o)
111 TNamed::operator=(o);
114 fNParticles = o.fNParticles;
115 fMinEntries = o.fMinEntries;
116 fFitRangeBinWidth= o.fFitRangeBinWidth;
118 fDoMakeObject = o.fDoMakeObject;
119 fEtaAxis.Set(o.fEtaAxis.GetNbins(),o.fEtaAxis.GetXmin(),o.fEtaAxis.GetXmax());
121 fMaxRelParError= o.fMaxRelParError;
122 fMaxChi2PerNDF = o.fMaxChi2PerNDF;
123 fMinWeight = o.fMinWeight;
125 fRingHistos.Delete();
126 TIter next(&o.fRingHistos);
128 while ((obj = next())) fRingHistos.Add(obj);
133 //____________________________________________________________________
134 AliFMDEnergyFitter::RingHistos*
135 AliFMDEnergyFitter::GetRingHistos(UShort_t d, Char_t r) const
139 case 1: idx = 0; break;
140 case 2: idx = 1 + (r == 'I' || r == 'i' ? 0 : 1); break;
141 case 3: idx = 3 + (r == 'I' || r == 'i' ? 0 : 1); break;
143 if (idx < 0 || idx >= fRingHistos.GetEntries()) return 0;
145 return static_cast<RingHistos*>(fRingHistos.At(idx));
148 //____________________________________________________________________
150 AliFMDEnergyFitter::Init(const TAxis& eAxis)
152 if (fEtaAxis.GetNbins() == 0 ||
153 TMath::Abs(fEtaAxis.GetXmax() - fEtaAxis.GetXmin()) < 1e-7)
155 TIter next(&fRingHistos);
157 while ((o = static_cast<RingHistos*>(next())))
158 o->Init(fEtaAxis, fMaxE, fNEbins, fUseIncreasingBins);
160 //____________________________________________________________________
162 AliFMDEnergyFitter::SetEtaAxis(const TAxis& eAxis)
164 SetEtaAxis(eAxis.GetNbins(),eAxis.GetXmin(),eAxis.GetXmax());
166 //____________________________________________________________________
168 AliFMDEnergyFitter::SetEtaAxis(Int_t nBins, Double_t etaMin, Double_t etaMax)
170 fEtaAxis.Set(nBins,etaMin,etaMax);
173 //____________________________________________________________________
175 AliFMDEnergyFitter::Accumulate(const AliESDFMD& input,
178 for(UShort_t d = 1; d <= 3; d++) {
179 Int_t nRings = (d == 1 ? 1 : 2);
180 for (UShort_t q = 0; q < nRings; q++) {
181 Char_t r = (q == 0 ? 'I' : 'O');
182 UShort_t nsec = (q == 0 ? 20 : 40);
183 UShort_t nstr = (q == 0 ? 512 : 256);
185 RingHistos* histos = GetRingHistos(d, r);
187 for(UShort_t s = 0; s < nsec; s++) {
188 for(UShort_t t = 0; t < nstr; t++) {
189 Float_t mult = input.Multiplicity(d,r,s,t);
191 // Keep dead-channel information.
192 if(mult == AliESDFMD::kInvalidMult || mult > 10 || mult <= 0)
195 // Get the pseudo-rapidity
196 Double_t eta1 = input.Eta(d,r,s,t);
197 Int_t ieta = fEtaAxis.FindBin(eta1);
198 if (ieta < 1 || ieta > fEtaAxis.GetNbins()) continue;
200 histos->Fill(empty, ieta-1, mult);
210 //____________________________________________________________________
212 AliFMDEnergyFitter::Fit(const TList* dir)
214 if (!fDoFits) return;
216 TList* d = static_cast<TList*>(dir->FindObject(GetName()));
222 // +fNParticles-1 for weights
223 Int_t nStack = kN+fNParticles;
224 THStack* stack[nStack];
225 stack[0] = new THStack("chi2", "#chi^{2}/#nu");
226 stack[kC +1] = new THStack("c", "Constant");
227 stack[kDelta +1] = new THStack("delta", "#Delta_{p}");
228 stack[kXi +1] = new THStack("xi", "#xi");
229 stack[kSigma +1] = new THStack("sigma", "#sigma");
230 stack[kSigmaN+1] = new THStack("sigman", "#sigma_{n}");
231 stack[kN +1] = new THStack("n", "# Particles");
232 for (Int_t i = 2; i <= fNParticles; i++)
233 stack[kN+i] = new THStack(Form("a%d", i), Form("a_{%d}", i));
234 for (Int_t i = 0; i < nStack; i++)
237 TIter next(&fRingHistos);
239 while ((o = static_cast<RingHistos*>(next()))) {
240 TObjArray* l = o->Fit(d, fEtaAxis, fLowCut, fNParticles,
241 fMinEntries, fFitRangeBinWidth,
242 fMaxRelParError, fMaxChi2PerNDF);
244 for (Int_t i = 0; i < l->GetEntriesFast(); i++) {
245 stack[i % nStack]->Add(static_cast<TH1*>(l->At(i)));
249 if (!fDoMakeObject) return;
251 MakeCorrectionsObject(d);
254 //____________________________________________________________________
256 AliFMDEnergyFitter::MakeCorrectionsObject(TList* d)
258 AliForwardCorrectionManager& mgr = AliForwardCorrectionManager::Instance();
260 AliFMDCorrELossFit* obj = new AliFMDCorrELossFit;
261 obj->SetEtaAxis(fEtaAxis);
262 obj->SetLowCut(fLowCut);
264 TIter next(&fRingHistos);
266 while ((o = static_cast<RingHistos*>(next()))) {
267 o->FindBestFits(d, *obj, fEtaAxis, fMaxRelParError,
268 fMaxChi2PerNDF, fMinWeight);
271 TString oName(mgr.GetObjectName(AliForwardCorrectionManager::kELossFits));
272 TString fileName(mgr.GetFilePath(AliForwardCorrectionManager::kELossFits));
273 AliInfo(Form("Object %s created in output - should be extracted and copied "
274 "to %s", oName.Data(), fileName.Data()));
275 d->Add(obj, oName.Data());
278 //____________________________________________________________________
280 AliFMDEnergyFitter::DefineOutput(TList* dir)
282 TList* d = new TList;
283 d->SetName(GetName());
286 TIter next(&fRingHistos);
288 while ((o = static_cast<RingHistos*>(next()))) {
292 //____________________________________________________________________
294 AliFMDEnergyFitter::SetDebug(Int_t dbg)
297 TIter next(&fRingHistos);
299 while ((o = static_cast<RingHistos*>(next())))
303 //____________________________________________________________________
305 AliFMDEnergyFitter::Print(Option_t*) const
307 char ind[gROOT->GetDirLevel()+1];
308 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
309 ind[gROOT->GetDirLevel()] = '\0';
310 std::cout << ind << "AliFMDEnergyFitter: " << GetName() << '\n'
311 << ind << " Low cut: " << fLowCut << " E/E_mip\n"
312 << ind << " Max(particles): " << fNParticles << '\n'
313 << ind << " Min(entries): " << fMinEntries << '\n'
314 << ind << " Fit range: "
315 << fFitRangeBinWidth << " bins\n"
316 << ind << " Make fits: "
317 << (fDoFits ? "yes\n" : "no\n")
318 << ind << " Make object: "
319 << (fDoMakeObject ? "yes\n" : "no\n")
320 << ind << " Max E/E_mip: " << fMaxE << '\n'
321 << ind << " N bins: " << fNEbins << '\n'
322 << ind << " Increasing bins: "
323 << (fUseIncreasingBins ?"yes\n" : "no\n")
324 << ind << " max(delta p/p): " << fMaxRelParError << '\n'
325 << ind << " max(chi^2/nu): " << fMaxChi2PerNDF << '\n'
326 << ind << " min(a_i): " << fMinWeight << std::endl;
329 //====================================================================
330 AliFMDEnergyFitter::RingHistos::RingHistos()
331 : AliForwardUtil::RingHistos(),
336 fFits("AliFMDCorrELossFit::ELossFit"),
340 //____________________________________________________________________
341 AliFMDEnergyFitter::RingHistos::RingHistos(UShort_t d, Char_t r)
342 : AliForwardUtil::RingHistos(d,r),
347 fFits("AliFMDCorrELossFit::ELossFit"),
350 fEtaEDists.SetName("EDists");
352 //____________________________________________________________________
353 AliFMDEnergyFitter::RingHistos::RingHistos(const RingHistos& o)
354 : AliForwardUtil::RingHistos(o),
359 fFits("AliFMDCorrELossFit::ELossFit"),
363 TIter next(&o.fEtaEDists);
365 while ((obj = next())) fEtaEDists.Add(obj->Clone());
368 fList->SetName(fName);
369 TIter next2(o.fList);
370 while ((obj = next2())) fList->Add(obj->Clone());
374 //____________________________________________________________________
375 AliFMDEnergyFitter::RingHistos&
376 AliFMDEnergyFitter::RingHistos::operator=(const RingHistos& o)
378 AliForwardUtil::RingHistos::operator=(o);
380 if (fEDist) delete fEDist;
381 if (fEmpty) delete fEmpty;
383 if (fList) fList->Delete();
386 fEDist = static_cast<TH1D*>(o.fEDist->Clone());
387 fEmpty = static_cast<TH1D*>(o.fEmpty->Clone());
389 TIter next(&o.fEtaEDists);
391 while ((obj = next())) fEtaEDists.Add(obj->Clone());
395 fList->SetName(fName);
396 TIter next2(o.fList);
397 while ((obj = next2())) fList->Add(obj->Clone());
402 //____________________________________________________________________
403 AliFMDEnergyFitter::RingHistos::~RingHistos()
405 if (fEDist) delete fEDist;
409 //____________________________________________________________________
411 AliFMDEnergyFitter::RingHistos::Fill(Bool_t empty, Int_t ieta, Double_t mult)
419 if (ieta < 0 || ieta >= fEtaEDists.GetEntries()) return;
421 TH1D* h = static_cast<TH1D*>(fEtaEDists.At(ieta));
427 //__________________________________________________________________
429 AliFMDEnergyFitter::RingHistos::MakeIncreasingAxis(Int_t n, Double_t min,
432 // Service function to define a logarithmic axis.
435 // min Minimum of axis
436 // max Maximum of axis
438 Double_t dx = (max-min) / n;
441 for (i = 1; i < n+1; i++) {
442 Double_t dI = float(i)/n;
443 Double_t next = bins[i-1] + dx + dI * dI * dx;
445 if (next > max) break;
451 //____________________________________________________________________
453 AliFMDEnergyFitter::RingHistos::Make(Int_t ieta,
461 TString name = Form(fgkEDistFormat, fName.Data(), ieta);
462 TString title = Form("#DeltaE/#DeltaE_{mip} for %s %+5.3f#leq#eta<%+5.3f "
463 "(#eta bin %d)", fName.Data(), emin, emax, ieta);
465 h = new TH1D(name.Data(), title.Data(), nDeBins, 0, deMax);
467 TArrayD deAxis = MakeIncreasingAxis(nDeBins, 0, deMax);
468 h = new TH1D(name.Data(), title.Data(), deAxis.fN-1, deAxis.fArray);
472 h->SetXTitle("#DeltaE/#DeltaE_{mip}");
473 h->SetFillColor(Color());
474 h->SetMarkerColor(Color());
475 h->SetLineColor(Color());
476 h->SetFillStyle(3001);
479 fEtaEDists.AddAt(h, ieta-1);
481 //____________________________________________________________________
482 TH1D* AliFMDEnergyFitter::RingHistos::MakePar(const char* name,
484 const TAxis& eta) const
486 TH1D* h = new TH1D(Form("%s_%s", fName.Data(), name),
487 Form("%s for %s", title, fName.Data()),
488 eta.GetNbins(), eta.GetXmin(), eta.GetXmax());
489 h->SetXTitle("#eta");
492 h->SetFillColor(Color());
493 h->SetMarkerColor(Color());
494 h->SetLineColor(Color());
495 h->SetFillStyle(3001);
500 //____________________________________________________________________
502 AliFMDEnergyFitter::RingHistos::MakeTotal(const char* name,
510 Double_t xlow = eta.GetBinLowEdge(low);
511 Double_t xhigh = eta.GetBinUpEdge(high);
512 TH1D* h = new TH1D(Form("%s_%s", fName.Data(), name),
513 Form("%s for %s", title, fName.Data()),
515 h->SetBinContent(1, val);
516 h->SetBinError(1, err);
517 h->SetXTitle("#eta");
521 h->SetMarkerColor(Color());
522 h->SetLineColor(Color());
530 //____________________________________________________________________
532 AliFMDEnergyFitter::RingHistos::Init(const TAxis& eAxis,
533 Double_t maxDE, Int_t nDEbins,
536 fEDist = new TH1D(Form("%s_edist", fName.Data()),
537 Form("#DeltaE/#DeltaE_{mip} for %s", fName.Data()),
539 fEmpty = new TH1D(Form("%s_empty", fName.Data()),
540 Form("#DeltaE/#DeltaE_{mip} for %s (empty events)",
541 fName.Data()), 200, 0, 6);
544 // fEtaEDists.Expand(eAxis.GetNbins());
545 for (Int_t i = 1; i <= eAxis.GetNbins(); i++) {
546 Double_t min = eAxis.GetBinLowEdge(i);
547 Double_t max = eAxis.GetBinUpEdge(i);
548 Make(i, min, max, maxDE, nDEbins, useIncrBin);
550 fList->Add(&fEtaEDists);
552 //____________________________________________________________________
554 AliFMDEnergyFitter::RingHistos::Fit(TList* dir,
560 Double_t relErrorCut,
561 Double_t chi2nuCut) const
563 // Get our ring list from the output container
564 TList* l = GetOutputList(dir);
567 // Get the energy distributions from the output container
568 TList* dists = static_cast<TList*>(l->FindObject("EDists"));
570 AliWarning(Form("Didn't find %s_EtaEDists in %s",
571 fName.Data(), l->GetName()));
576 // Container of the fit results histograms
577 TObjArray* pars = new TObjArray(3+nParticles+1);
578 pars->SetName("FitResults");
581 // Result objects stored in separate list on the output
589 TH1* hA[nParticles-1];
590 pars->Add(hChi2 = MakePar("chi2", "#chi^{2}/#nu", eta));
591 pars->Add(hC = MakePar("c", "Constant", eta));
592 pars->Add(hDelta = MakePar("delta", "#Delta_{p}", eta));
593 pars->Add(hXi = MakePar("xi", "#xi", eta));
594 pars->Add(hSigma = MakePar("sigma", "#sigma", eta));
595 pars->Add(hSigmaN = MakePar("sigman", "#sigma_{n}", eta));
596 pars->Add(hN = MakePar("n", "N", eta));
597 for (UShort_t i = 1; i < nParticles; i++)
598 pars->Add(hA[i-1] = MakePar(Form("a%d",i+1), Form("a_{%d}",i+1), eta));
601 Int_t nDists = dists->GetEntries();
604 for (Int_t i = 0; i < nDists; i++) {
605 TH1D* dist = static_cast<TH1D*>(dists->At(i));
606 // Ignore empty histograms altoghether
607 if (!dist || dist->GetEntries() <= 0) continue;
609 // Scale to the bin-width
610 dist->Scale(1., "width");
612 // Normalize peak to 1
613 Double_t max = dist->GetMaximum();
614 if (max <= 0) continue;
617 // Check that we have enough entries
618 if (dist->GetEntries() <= minEntries) {
619 AliWarning(Form("Histogram at %3d (%s) has too few entries (%d <= %d)",
620 i, dist->GetName(), Int_t(dist->GetEntries()),
626 TF1* res = FitHist(dist,lowCut,nParticles,minusBins,
627 relErrorCut,chi2nuCut);
629 // dist->GetListOfFunctions()->Add(res);
632 low = TMath::Min(low,i+1);
633 high = TMath::Max(high,i+1);
635 // Get the reduced chi square
636 Double_t chi2 = res->GetChisquare();
637 Int_t ndf = res->GetNDF();
639 // Store results of best fit in output histograms
640 res->SetLineWidth(4);
641 hChi2 ->SetBinContent(i+1, ndf > 0 ? chi2 / ndf : 0);
642 hC ->SetBinContent(i+1, res->GetParameter(kC));
643 hDelta ->SetBinContent(i+1, res->GetParameter(kDelta));
644 hXi ->SetBinContent(i+1, res->GetParameter(kXi));
645 hSigma ->SetBinContent(i+1, res->GetParameter(kSigma));
646 hSigmaN ->SetBinContent(i+1, res->GetParameter(kSigmaN));
647 hN ->SetBinContent(i+1, res->GetParameter(kN));
649 hC ->SetBinError(i+1, res->GetParError(kC));
650 hDelta ->SetBinError(i+1, res->GetParError(kDelta));
651 hXi ->SetBinError(i+1, res->GetParError(kXi));
652 hSigma ->SetBinError(i+1, res->GetParError(kSigma));
653 hSigmaN->SetBinError(i+1, res->GetParError(kSigmaN));
654 hN ->SetBinError(i+1, res->GetParError(kN));
656 for (UShort_t j = 0; j < nParticles-1; j++) {
657 hA[j]->SetBinContent(i+1, res->GetParameter(kA+j));
658 hA[j]->SetBinError(i+1, res->GetParError(kA+j));
662 // Fit the full-ring histogram
663 TH1* total = GetOutputHist(l, Form("%s_edist", fName.Data()));
664 if (total && total->GetEntries() >= minEntries) {
666 // Scale to the bin-width
667 total->Scale(1., "width");
669 // Normalize peak to 1
670 Double_t max = total->GetMaximum();
671 if (max > 0) total->Scale(1/max);
673 TF1* res = FitHist(total,lowCut,nParticles,minusBins,
674 relErrorCut,chi2nuCut);
676 // Make histograms for the result of this fit
677 Double_t chi2 = res->GetChisquare();
678 Int_t ndf = res->GetNDF();
679 pars->Add(MakeTotal("t_chi2", "#chi^{2}/#nu", eta, low, high,
680 ndf > 0 ? chi2/ndf : 0, 0));
681 pars->Add(MakeTotal("t_c", "Constant", eta, low, high,
682 res->GetParameter(kC),
683 res->GetParError(kC)));
684 pars->Add(MakeTotal("t_delta", "#Delta_{p}", eta, low, high,
685 res->GetParameter(kDelta),
686 res->GetParError(kDelta)));
687 pars->Add(MakeTotal("t_xi", "#xi", eta, low, high,
688 res->GetParameter(kXi),
689 res->GetParError(kXi)));
690 pars->Add(MakeTotal("t_sigma", "#sigma", eta, low, high,
691 res->GetParameter(kSigma),
692 res->GetParError(kSigma)));
693 pars->Add(MakeTotal("t_sigman", "#sigma_{n}", eta, low, high,
694 res->GetParameter(kSigmaN),
695 res->GetParError(kSigmaN)));
696 pars->Add(MakeTotal("t_n", "N", eta, low, high,
697 res->GetParameter(kN),0));
698 for (UShort_t j = 0; j < nParticles-1; j++)
699 pars->Add(MakeTotal(Form("t_a%d",j+2),
700 Form("a_{%d}",j+2), eta, low, high,
701 res->GetParameter(kA+j),
702 res->GetParError(kA+j)));
706 // Clean up list of histogram. Histograms with no entries or
707 // no functions are deleted. We have to do this using the TObjLink
708 // objects stored in the list since ROOT cannot guaranty the validity
709 // of iterators when removing from a list - tsck. Should just implement
711 TObjLink* lnk = dists->FirstLink();
713 TH1* h = static_cast<TH1*>(lnk->GetObject());
715 if (h->GetEntries() <= 0) {
716 // AliWarning(Form("No entries in %s - removing", h->GetName()));
719 else if (h->GetListOfFunctions()->GetEntries() <= 0) {
720 // AliWarning(Form("No fuctions associated with %s - removing",
725 TObjLink* keep = lnk->Next();
736 //____________________________________________________________________
738 AliFMDEnergyFitter::RingHistos::FitHist(TH1* dist,
742 Double_t relErrorCut,
743 Double_t chi2nuCut) const
745 Double_t maxRange = 10;
747 // Create a fitter object
748 AliForwardUtil::ELossFitter f(lowCut, maxRange, minusBins);
752 // If we are only asked to fit a single particle, return this fit,
754 if (nParticles == 1) {
755 TF1* r = f.Fit1Particle(dist, 0);
760 // Fit from 2 upto n particles
761 for (Int_t i = 2; i <= nParticles; i++) f.FitNParticle(dist, i, 0);
764 // Now, we need to select the best fit
765 Int_t nFits = f.fFitResults.GetEntriesFast();
767 for (Int_t i = nFits-1; i >= 0; i--) {
769 TF1* ff = static_cast<TF1*>(f.fFunctions.At(i));
770 // ff->SetLineColor(Color());
771 ff->SetRange(0, maxRange);
772 dist->GetListOfFunctions()->Add(new TF1(*ff));
773 if (CheckResult(static_cast<TFitResult*>(f.fFitResults.At(i)),
774 relErrorCut, chi2nuCut)) {
777 // f.fFitResults.At(i)->Print("V");
780 // If all else fails, use the 1 particle fit
781 TF1* ret = static_cast<TF1*>(f.fFunctions.At(0));
783 // Find the fit with the most valid particles
784 for (Int_t i = nFits-1; i > 0; i--) {
785 if (!good[i]) continue;
787 AliInfo(Form("Choosing fit with n=%d", i+1));
788 f.fFitResults.At(i)->Print();
793 // Give a warning if we're using fall-back
794 if (ret == f.fFunctions.At(0)) {
795 AliWarning("Choosing fall-back 1 particle fit");
797 // Copy our result and return (the functions are owned by the fitter)
798 TF1* fret = new TF1(*ret);
802 //____________________________________________________________________
804 AliFMDEnergyFitter::RingHistos::CheckResult(TFitResult* r,
805 Double_t relErrorCut,
806 Double_t chi2nuCut) const
808 if (fDebug > 10) r->Print();
809 TString n = r->GetName();
810 n.ReplaceAll("TFitResult-", "");
811 Double_t chi2 = r->Chi2();
812 Int_t ndf = r->Ndf();
813 // Double_t prob = r.Prob();
816 // Check that the reduced chi square isn't larger than 5
817 if (ndf <= 0 || chi2 / ndf > chi2nuCut) {
819 AliWarning(Form("%s: chi^2/ndf=%12.5f/%3d=%12.5f>%12.5f",
820 n.Data(), chi2, ndf, (ndf<0 ? 0 : chi2/ndf),
825 // Check each parameter
826 UShort_t nPar = r->NPar();
827 for (UShort_t i = 0; i < nPar; i++) {
828 if (i == kN) continue; // Skip the number parameter
830 // Get value and error and check value
831 Double_t v = r->Parameter(i);
832 Double_t e = r->ParError(i);
833 if (v == 0) continue;
835 // Calculate the relative error and check it
837 Double_t cut = relErrorCut * (i < kN ? 1 : 2);
840 AliWarning(Form("%s: Delta %s/%s=%9.5f/%9.5f=%5.1f%%>%5.1f%%",
841 n.Data(), r->ParName(i).c_str(),
842 r->ParName(i).c_str(), e, v,
843 100*(v == 0 ? 0 : e/v),
849 // Check if we have scale parameters
852 // Check that the last particle has a significant contribution
853 Double_t lastScale = r->Parameter(nPar-1);
854 if (lastScale <= 1e-7) {
856 AliWarning(Form("%s: %s=%9.6f<1e-7",
857 n.Data(), r->ParName(nPar-1).c_str(), lastScale)); }
865 //__________________________________________________________________
867 AliFMDEnergyFitter::RingHistos::FindBestFits(TList* d,
868 AliFMDCorrELossFit& obj,
870 Double_t relErrorCut,
872 Double_t minWeightCut)
874 // Get our ring list from the output container
875 TList* l = GetOutputList(d);
878 // Get the energy distributions from the output container
879 TList* dists = static_cast<TList*>(l->FindObject("EDists"));
881 AliWarning(Form("Didn't find %s_EtaEDists in %s",
882 fName.Data(), l->GetName()));
886 Int_t nBin = eta.GetNbins();
888 for (Int_t b = 1; b <= nBin; b++) {
889 TString n(Form(fgkEDistFormat, fName.Data(), b));
890 TH1D* dist = static_cast<TH1D*>(dists->FindObject(n));
891 // Ignore empty histograms altoghether
892 if (!dist || dist->GetEntries() <= 0) continue;
894 AliFMDCorrELossFit::ELossFit* best = FindBestFit(dist,
901 // Double_t eta = fAxis->GetBinCenter(b);
902 obj.SetFit(fDet, fRing, b, new AliFMDCorrELossFit::ELossFit(*best));
906 //__________________________________________________________________
907 AliFMDCorrELossFit::ELossFit*
908 AliFMDEnergyFitter::RingHistos::FindBestFit(TH1* dist,
909 Double_t relErrorCut,
911 Double_t minWeightCut)
913 TList* funcs = dist->GetListOfFunctions();
918 // Info("FindBestFit", "%s", dist->GetName());
919 while ((func = static_cast<TF1*>(next()))) {
920 AliFMDCorrELossFit::ELossFit* fit =
921 new(fFits[i++]) AliFMDCorrELossFit::ELossFit(0,*func);
922 fit->CalculateQuality(chi2nuCut, relErrorCut, minWeightCut);
926 return static_cast<AliFMDCorrELossFit::ELossFit*>(fFits.At(0));
930 //____________________________________________________________________
932 AliFMDEnergyFitter::RingHistos::Output(TList* dir)
934 fList = DefineOutputList(dir);
937 //____________________________________________________________________