1 // Object holding the Energy loss fit 'correction'
3 // These are generated from Monte-Carlo or real ESDs.
5 #include "AliFMDCorrELossFit.h"
6 #include "AliForwardUtil.h"
9 #include <TVirtualPad.h>
18 Double_t AliFMDCorrELossFit::ELossFit::fgMaxRelError = .12;
19 Double_t AliFMDCorrELossFit::ELossFit::fgLeastWeight = 1e-5;
20 Double_t AliFMDCorrELossFit::ELossFit::fgMaxChi2nu = 20;
22 //____________________________________________________________________
23 AliFMDCorrELossFit::ELossFit::ELossFit()
45 // Default constructor
49 //____________________________________________________________________
50 AliFMDCorrELossFit::ELossFit::ELossFit(Int_t quality, const TF1& f)
51 : fN(f.GetNpar() > AliForwardUtil::ELossFitter::kN ?
52 Int_t(f.GetParameter(AliForwardUtil::ELossFitter::kN)) :
55 fChi2(f.GetChisquare()),
56 fC(f.GetParameter(AliForwardUtil::ELossFitter::kC)),
57 fDelta(f.GetParameter(AliForwardUtil::ELossFitter::kDelta)),
58 fXi(f.GetParameter(AliForwardUtil::ELossFitter::kXi)),
59 fSigma(f.GetParameter(AliForwardUtil::ELossFitter::kSigma)),
60 fSigmaN(f.GetParameter(AliForwardUtil::ELossFitter::kSigmaN)),
62 fEC(f.GetParError(AliForwardUtil::ELossFitter::kC)),
63 fEDelta(f.GetParError(AliForwardUtil::ELossFitter::kDelta)),
64 fEXi(f.GetParError(AliForwardUtil::ELossFitter::kXi)),
65 fESigma(f.GetParError(AliForwardUtil::ELossFitter::kSigma)),
66 fESigmaN(f.GetParError(AliForwardUtil::ELossFitter::kSigmaN)),
74 // Construct from a function
77 // quality Quality flag
81 fA = new Double_t[fN];
82 fEA = new Double_t[fN];
83 for (Int_t i = 0; i < fN-1; i++) {
84 fA[i] = f.GetParameter(AliForwardUtil::ELossFitter::kA+i);
85 fEA[i] = f.GetParError(AliForwardUtil::ELossFitter::kA+i);
91 //____________________________________________________________________
92 AliFMDCorrELossFit::ELossFit::ELossFit(Int_t quality,UShort_t n,
93 Double_t chi2, UShort_t nu,
94 Double_t c, Double_t ec,
95 Double_t delta, Double_t edelta,
96 Double_t xi, Double_t exi,
97 Double_t sigma, Double_t esigma,
98 Double_t sigman, Double_t esigman,
99 const Double_t* a,const Double_t* ea)
121 // Constructor with full parameter set
124 // quality Quality flag
125 // n @f$ N@f$ - Number of fitted peaks
126 // chi2 @f$ \chi^2 @f$
127 // nu @f$ \nu @f$ - number degrees of freedom
128 // c @f$ C@f$ - scale constant
129 // ec @f$ \delta C@f$ - error on @f$ C@f$
130 // delta @f$ \Delta@f$ - Most probable value
131 // edelta @f$ \delta\Delta@f$ - error on @f$\Delta@f$
132 // xi @f$ \xi@f$ - width
133 // exi @f$ \delta\xi@f$ - error on @f$\xi@f$
134 // sigma @f$ \sigma@f$ - Width of Gaussian
135 // esigma @f$ \delta\sigma@f$ - error on @f$\sigma@f$
136 // sigman @f$ \sigma_n@f$ - Noise width
137 // esigman @f$ \delta\sigma_n@f$ - error on @f$\sigma_n@f$
138 // a Array of @f$ N-1@f$ weights @f$ a_i@f$ for
140 // ea Array of @f$ N-1@f$ error on the weights @f$ a_i@f$ for
144 fA = new Double_t[fN];
145 fEA = new Double_t[fN];
146 for (Int_t i = 0; i < fN-1; i++) {
153 //____________________________________________________________________
154 AliFMDCorrELossFit::ELossFit::ELossFit(const ELossFit& o)
169 fESigmaN(o.fESigmaN),
171 fQuality(o.fQuality),
180 // o Object to copy from
183 fA = new Double_t[fN];
184 fEA = new Double_t[fN];
185 for (Int_t i = 0; i < fN-1; i++) {
193 //____________________________________________________________________
194 AliFMDCorrELossFit::ELossFit&
195 AliFMDCorrELossFit::ELossFit::operator=(const ELossFit& o)
198 // Assignment operator
201 // o Object to assign from
204 // Reference to this object
206 if (&o == this) return *this;
219 fESigmaN = o.fESigmaN;
220 fQuality = o.fQuality;
224 if (fA) delete [] fA;
225 if (fEA) delete [] fEA;
229 if (fN <= 0) return *this;
230 fA = new Double_t[fN];
231 fEA = new Double_t[fN];
232 for (Int_t i = 0; i < fN; i++) {
240 //____________________________________________________________________
241 AliFMDCorrELossFit::ELossFit::~ELossFit()
244 if (fEA) delete[] fEA;
248 //____________________________________________________________________
250 AliFMDCorrELossFit::ELossFit::FindMaxWeight(Double_t maxRelError,
251 Double_t leastWeight,
255 // Find the maximum weight to use. The maximum weight is the
256 // largest i for which
258 // - @f$ i \leq \max{N}@f$
259 // - @f$ a_i > \min{a}@f$
260 // - @f$ \delta a_i/a_i > \delta_{max}@f$
263 // maxRelError @f$ \min{a}@f$
264 // leastWeight @f$ \delta_{max}@f$
265 // maxN @f$ \max{N}@f$
268 // The largest index @f$ i@f$ for which the above
269 // conditions hold. Will never return less than 1.
271 Int_t n = TMath::Min(maxN, UShort_t(fN-1));
273 // fN is one larger than we have data
274 for (Int_t i = 0; i < n-1; i++, m++) {
275 if (fA[i] < leastWeight) break;
276 if (fEA[i] / fA[i] > maxRelError) break;
281 //____________________________________________________________________
283 AliFMDCorrELossFit::ELossFit::Evaluate(Double_t x,
289 // f_N(x;\Delta,\xi,\sigma') =
290 // \sum_{i=1}^{n} a_i f(x;\Delta_i,\xi_i,\sigma_i')
293 // (see AliForwardUtil::NLandauGaus) for the maximum @f$ N @f$
294 // that fulfills the requirements
297 // x Where to evaluate
298 // maxN @f$ \max{N}@f$
301 // @f$ f_N(x;\Delta,\xi,\sigma')@f$
303 return AliForwardUtil::NLandauGaus(x, fDelta, fXi, fSigma, fSigmaN,
304 TMath::Min(maxN, UShort_t(fN)), fA);
307 //____________________________________________________________________
309 AliFMDCorrELossFit::ELossFit::EvaluateWeighted(Double_t x,
315 // f_W(x;\Delta,\xi,\sigma') =
316 // \frac{\sum_{i=1}^{n} i a_i f_i(x;\Delta,\xi,\sigma')}{
317 // f_N(x;\Delta,\xi,\sigma')} =
318 // \frac{\sum_{i=1}^{n} i a_i f(x;\Delta_i,\xi_i,\sigma_i')}{
319 // \sum_{i=1}^{n} a_i f(x;\Delta_i,\xi_i,\sigma_i')}
321 // where @f$ n@f$ fulfills the requirements (see FindMaxWeight).
323 // If the denominator is zero, then 1 is returned.
325 // See also AliForwardUtil::ILandauGaus and AliForwardUtil::NLandauGaus
326 // for more information on the evaluated functions.
329 // x Where to evaluate
330 // maxN @f$ \max{N}@f$
333 // @f$ f_W(x;\Delta,\xi,\sigma')@f$.
335 UShort_t n = TMath::Min(maxN, UShort_t(fN-1));
338 for (Int_t i = 1; i <= n; i++) {
339 Double_t a = (i == 1 ? 1 : fA[i-1]);
340 if (fA[i-1] < 0) break;
341 Double_t f = AliForwardUtil::ILandauGaus(x,fDelta,fXi,fSigma,fSigmaN,i);
345 if (den <= 0) return 1;
350 #define OUTPAR(N,V,E) \
351 std::setprecision(9) << \
352 std::setw(12) << N << ": " << \
353 std::setw(14) << V << " +/- " << \
354 std::setw(14) << E << " (" << \
355 std::setprecision(-1) << \
356 std::setw(5) << 100*(V>0?E/V:1) << "%)\n"
359 //____________________________________________________________________
361 AliFMDCorrELossFit::ELossFit::Compare(const TObject* o) const
364 // Compare to another ELossFit object.
366 // - +1, if this quality is better (larger) than other objects quality
367 // - -1, if this quality is worse (smaller) than other objects quality
368 // - +1, if this @f$|\chi^2/\nu-1|@f$ is smaller than the same for other
369 // - -1, if this @f$|\chi^2/\nu-1|@f$ is larger than the same for other
373 // o Other object to compare to
375 const ELossFit* other = static_cast<const ELossFit*>(o);
376 if (this->fQuality < other->fQuality) return -1;
377 if (this->fQuality > other->fQuality) return +1;
378 Double_t chi2nu = (fNu == 0 ? 1000 : fChi2 / fNu);
379 Double_t oChi2nu = (other->fNu == 0 ? 1000 : other->fChi2 / other->fNu);
380 if (TMath::Abs(chi2nu-1) < TMath::Abs(oChi2nu-1)) return +1;
381 if (TMath::Abs(chi2nu-1) > TMath::Abs(oChi2nu-1)) return -1;
385 //____________________________________________________________________
387 AliFMDCorrELossFit::ELossFit::Print(Option_t*) const
390 // Information to standard output
395 std::cout << GetName() << ":\n"
396 << " chi^2/nu = " << fChi2 << "/" << fNu << " = "
397 << (fNu == 0 ? 999 : fChi2 / fNu) << "\n"
398 << " Quality: " << fQuality << "\n"
399 << " NParticles: " << fN << " (" << FindMaxWeight() << ")\n"
400 << OUTPAR("Delta", fDelta, fEDelta)
401 << OUTPAR("xi", fXi, fEXi)
402 << OUTPAR("sigma", fSigma, fESigma)
403 << OUTPAR("sigma_n", fSigmaN, fESigmaN);
404 for (Int_t i = 0; i < fN-1; i++)
405 std::cout << OUTPAR(Form("a%d", i+2), fA[i], fEA[i]);
406 std::cout << std::flush;
409 //____________________________________________________________________
411 AliFMDCorrELossFit::ELossFit::GetName() const
414 // Get the name of this object
420 return Form("FMD%d%c_etabin%03d", fDet, fRing, fBin);
423 //____________________________________________________________________
425 AliFMDCorrELossFit::ELossFit::Browse(TBrowser* b)
428 // Browse this object
433 Draw(b ? b->GetDrawOption() : "comp");
438 //____________________________________________________________________
440 AliFMDCorrELossFit::ELossFit::Draw(Option_t* option)
447 // - COMP Draw components too
452 if (opt.Contains("COMP")) {
453 opt.ReplaceAll("COMP","");
456 if (!opt.Contains("SAME")) {
461 TF1* tot = AliForwardUtil::MakeNLandauGaus(1,
466 tot->SetLineColor(kBlack);
467 tot->SetLineWidth(2);
468 tot->SetLineStyle(1);
469 tot->SetTitle(GetName());
470 Double_t max = tot->GetMaximum();
472 if (!opt.Contains("SAME")) {
473 TH1* frame = new TH1F(GetName(),
474 Form("FMD%d%c, eta bin %d",fDet,fRing,fBin),
476 frame->SetMinimum(max/10000);
477 frame->SetMaximum(max*1.4);
478 frame->SetXTitle("#Delta / #Delta_{mip}");
482 tot->DrawCopy(opt.Data());
492 Int_t maxW = FindMaxWeight();
493 for (Int_t i=1; i <= fN; i++) {
494 TF1* f = AliForwardUtil::MakeILandauGaus((i == 1 ? 1 : fA[i-2]),
499 f->SetLineStyle(i > maxW ? 2 : 1);
500 min = TMath::Min(f->GetMaximum(), min);
501 f->DrawCopy(opt.Data());
505 tot->GetHistogram()->SetMaximum(max);
506 tot->GetHistogram()->SetMinimum(min);
507 tot->GetHistogram()->GetYaxis()->SetRangeUser(min, max);
513 //____________________________________________________________________
514 #define CHECKPAR(V,E,T) ((V > 0) && (E / V < T))
516 //____________________________________________________________________
518 AliFMDCorrELossFit::ELossFit::GetLowerBound(Double_t f) const
525 //____________________________________________________________________
527 AliFMDCorrELossFit::ELossFit::GetLowerBound(Double_t f,
528 Bool_t includeSigma) const
532 // Delta - f * (xi + sigma)
533 return fDelta - f * (fXi + (includeSigma ? fSigma : 0));
536 //____________________________________________________________________
538 AliFMDCorrELossFit::ELossFit::CalculateQuality(Double_t maxChi2nu,
539 Double_t maxRelError,
540 Double_t leastWeight)
543 // Calculate the quality
546 if (fNu > 0 && fChi2 / fNu < maxChi2nu) qual += 4;;
547 if (CHECKPAR(fDelta, fEDelta, maxRelError)) qual++;
548 if (CHECKPAR(fXi, fEXi, maxRelError)) qual++;
549 if (CHECKPAR(fSigma, fESigma, maxRelError)) qual++;
550 if (CHECKPAR(fSigmaN, fESigmaN, maxRelError)) qual++;
551 qual += FindMaxWeight(1.5*maxRelError, leastWeight, fN);
555 //____________________________________________________________________
556 AliFMDCorrELossFit::AliFMDCorrELossFit()
563 // Default constructor
565 fRings.SetOwner(kTRUE);
566 fEtaAxis.SetTitle("#eta");
567 fEtaAxis.SetName("etaAxis");
568 fRings.SetName("rings");
571 //____________________________________________________________________
572 AliFMDCorrELossFit::AliFMDCorrELossFit(const AliFMDCorrELossFit& o)
575 fEtaAxis(o.fEtaAxis.GetNbins(),o.fEtaAxis.GetXmin(),o.fEtaAxis.GetXmax()),
582 // o Object to copy from
584 fEtaAxis.SetTitle("#eta");
585 fEtaAxis.SetName("etaAxis");
588 //____________________________________________________________________
589 AliFMDCorrELossFit::~AliFMDCorrELossFit()
597 //____________________________________________________________________
599 AliFMDCorrELossFit::operator=(const AliFMDCorrELossFit& o)
602 // Assignment operator
605 // o Object to assign from
608 // Reference to this object
610 if (&o == this) return *this;
613 SetEtaAxis(o.fEtaAxis.GetNbins(), o.fEtaAxis.GetXmin(), o.fEtaAxis.GetXmax());
617 //____________________________________________________________________
619 AliFMDCorrELossFit::FindEtaBin(Double_t eta) const
622 // Find the eta bin corresponding to the given eta
628 // Bin (in @f$[1,N_{bins}]@f$) corresponding to the given
629 // eta, or 0 if out of range.
631 if (TMath::Abs(fEtaAxis.GetXmin() - fEtaAxis.GetXmax()) < 1e-6
632 || fEtaAxis.GetNbins() == 0) {
633 AliWarning("No eta axis defined");
636 Int_t bin = const_cast<TAxis&>(fEtaAxis).FindBin(eta);
637 if (bin <= 0 || bin > fEtaAxis.GetNbins()) return 0;
641 //____________________________________________________________________
643 AliFMDCorrELossFit::SetFit(UShort_t d, Char_t r, Int_t etaBin, ELossFit* fit)
646 // Set the fit parameters from a function
651 // etaBin Eta (bin number, 1->nBins)
652 // f ELoss fit result - note, the object will take ownership
654 TObjArray* ringArray = GetOrMakeRingArray(d, r);
656 AliError(Form("Failed to make ring array for FMD%d%c", d, r));
659 if (etaBin <= 0 || etaBin >= fEtaAxis.GetNbins()+1) {
660 AliError(Form("bin=%d is out of range [%d,%d]",
661 etaBin, 1, fEtaAxis.GetNbins()));
664 // AliInfo(Form("Adding fit %p at %3d", fit, etaBin));
665 ringArray->AddAtAndExpand(fit, etaBin);
669 //____________________________________________________________________
671 AliFMDCorrELossFit::SetFit(UShort_t d, Char_t r, Double_t eta, ELossFit* fit)
674 // Set the fit parameters from a function
680 // f ELoss fit result - note, the object will take ownership
682 Int_t bin = FindEtaBin(eta);
684 AliError(Form("eta=%f is out of range [%f,%f]",
685 eta, fEtaAxis.GetXmin(), fEtaAxis.GetXmax()));
689 return SetFit(d, r, bin, fit);
691 //____________________________________________________________________
693 AliFMDCorrELossFit::SetFit(UShort_t d, Char_t r,
695 Int_t quality,UShort_t n,
696 Double_t chi2, UShort_t nu,
697 Double_t c, Double_t ec,
698 Double_t delta, Double_t edelta,
699 Double_t xi, Double_t exi,
700 Double_t sigma, Double_t esigma,
701 Double_t sigman, Double_t esigman,
702 Double_t* a, Double_t* ea)
705 // Set the fit parameters from a function
711 // quality Quality flag
712 // n @f$ N@f$ - Number of fitted peaks
713 // chi2 @f$ \chi^2 @f$
714 // nu @f$ \nu @f$ - number degrees of freedom
715 // c @f$ C@f$ - scale constant
716 // ec @f$ \delta C@f$ - error on @f$ C@f$
717 // delta @f$ \Delta@f$ - most probable value
718 // edelta @f$ \delta\Delta@f$ - error on @f$\Delta@f$
719 // xi @f$ \xi@f$ - Landau width
720 // exi @f$ \delta\xi@f$ - error on @f$\xi@f$
721 // sigma @f$ \sigma@f$ - Gaussian width
722 // esigma @f$ \delta\sigma@f$ - error on @f$\sigma@f$
723 // sigman @f$ \sigma_n@f$ - Noise width
724 // esigman @f$ \delta\sigma_n@f$ - error on @f$\sigma_n@f$
725 // a Array of @f$ N-1@f$ weights @f$ a_i@f$ for
727 // ea Array of @f$ N-1@f$ errors on weights @f$ a_i@f$ for
730 ELossFit* e = new ELossFit(quality, n,
738 if (!SetFit(d, r, eta, e)) {
744 //____________________________________________________________________
746 AliFMDCorrELossFit::SetFit(UShort_t d, Char_t r, Double_t eta,
747 Int_t quality, const TF1& f)
750 // Set the fit parameters from a function
756 // quality Quality flag
757 // f Function from fit
759 ELossFit* e = new ELossFit(quality, f);
760 if (!SetFit(d, r, eta, e)) {
766 //____________________________________________________________________
767 AliFMDCorrELossFit::ELossFit*
768 AliFMDCorrELossFit::GetFit(UShort_t d, Char_t r, Int_t etabin) const
771 // Get the fit corresponding to the specified parameters
776 // etabin Eta bin (1 based)
779 // Fit parameters or null in case of problems
781 TObjArray* ringArray = GetRingArray(d, r);
782 if (!ringArray) return 0;
783 if (etabin <= 0 || etabin >= fEtaAxis.GetNbins()) return 0;
784 if (etabin > ringArray->GetEntriesFast()) return 0;
785 else if (etabin >= ringArray->GetEntriesFast()) etabin--;
786 else if (!ringArray->At(etabin)) etabin++;
787 return static_cast<ELossFit*>(ringArray->At(etabin));
789 //____________________________________________________________________
790 AliFMDCorrELossFit::ELossFit*
791 AliFMDCorrELossFit::GetFit(UShort_t d, Char_t r, Double_t eta) const
794 // Find the fit corresponding to the specified parameters
802 // Fit parameters or null in case of problems
804 Int_t etabin = FindEtaBin(eta);
805 return GetFit(d, r, etabin);
808 //____________________________________________________________________
809 AliFMDCorrELossFit::ELossFit*
810 AliFMDCorrELossFit::FindFit(UShort_t d, Char_t r, Int_t etabin) const
813 // Find the fit corresponding to the specified parameters
818 // etabin Eta bin (1 based)
821 // Fit parameters or null in case of problems
823 TObjArray* ringArray = GetRingArray(d, r);
825 AliError(Form("Failed to make ring array for FMD%d%c", d, r));
828 if (etabin <= 0 || etabin >= fEtaAxis.GetNbins()) {
829 // AliError(Form("Eta bin=%3d out of bounds [%d,%d] for FMD%d%c",
830 // etabin, 1, fEtaAxis.GetNbins(), d, r));
833 if (etabin > ringArray->GetEntriesFast()) {
834 // AliError(Form("Eta bin=%3d out of bounds [%d,%d] for FMD%d%c",
835 // etabin, 1, ringArray->GetEntriesFast(), d, r));
838 else if (etabin >= ringArray->GetEntriesFast()) {
839 // AliWarning(Form("Eta bin=%3d out of bounds by +1 [%d,%d] for FMD%d%c, "
840 // "trying %3d", etabin, 1, ringArray->GetEntriesFast(), d, r,
844 else if (!ringArray->At(etabin)) {
845 // AliWarning(Form("Eta bin=%d has no fit for FMD%d%c, trying %03d",
846 // etabin, d, r, etabin+1));
849 return static_cast<ELossFit*>(ringArray->At(etabin));
851 //____________________________________________________________________
852 AliFMDCorrELossFit::ELossFit*
853 AliFMDCorrELossFit::FindFit(UShort_t d, Char_t r, Double_t eta) const
856 // Find the fit corresponding to the specified parameters
864 // Fit parameters or null in case of problems
866 Int_t etabin = FindEtaBin(eta);
867 return FindFit(d, r, etabin);
869 //____________________________________________________________________
871 AliFMDCorrELossFit::GetRingArray(UShort_t d, Char_t r) const
874 // Get the ring array corresponding to the specified ring
881 // Pointer to ring array, or null in case of problems
885 case 1: idx = 0; break;
886 case 2: idx = (r == 'i' || r == 'I') ? 1 : 2; break;
887 case 3: idx = (r == 'o' || r == 'I') ? 3 : 4; break;
889 if (idx < 0 || idx >= fRings.GetEntriesFast()) return 0;
890 return static_cast<TObjArray*>(fRings.At(idx));
892 //____________________________________________________________________
894 AliFMDCorrELossFit::GetOrMakeRingArray(UShort_t d, Char_t r)
897 // Get the ring array corresponding to the specified ring
904 // Pointer to ring array, or newly created container
908 case 1: idx = 0; break;
909 case 2: idx = (r == 'i' || r == 'I') ? 1 : 2; break;
910 case 3: idx = (r == 'o' || r == 'I') ? 3 : 4; break;
912 if (idx < 0) return 0;
913 if (idx >= fRings.GetEntriesFast() || !fRings.At(idx)) {
914 TObjArray* a = new TObjArray(0);
915 // TOrdCollection* a = new TOrdCollection(fEtaAxis.GetNbins());
916 a->SetName(Form("FMD%d%c", d, r));
918 fRings.AddAtAndExpand(a, idx);
920 return static_cast<TObjArray*>(fRings.At(idx));
923 //____________________________________________________________________
925 AliFMDCorrELossFit::GetLowerBound(UShort_t d, Char_t r, Int_t etabin,
928 ELossFit* fit = GetFit(d, r, etabin);
929 if (!fit) return -1024;
930 return fit->GetLowerBound(f);
932 //____________________________________________________________________
934 AliFMDCorrELossFit::GetLowerBound(UShort_t d, Char_t r, Double_t eta,
937 Int_t bin = FindEtaBin(eta);
938 if (bin <= 0) return -1024;
939 return GetLowerBound(d, r, Int_t(bin), f);
941 //____________________________________________________________________
943 AliFMDCorrELossFit::GetLowerBound(UShort_t d, Char_t r, Int_t etabin,
944 Double_t f, Bool_t showErrors,
945 Bool_t includeSigma) const
947 ELossFit* fit = GetFit(d, r, etabin);
950 AliWarning(Form("No fit for FMD%d%c @ etabin=%d", d, r, etabin));
954 return fit->GetLowerBound(f, includeSigma);
957 //____________________________________________________________________
959 AliFMDCorrELossFit::GetLowerBound(UShort_t d, Char_t r, Double_t eta,
960 Double_t f, Bool_t showErrors,
961 Bool_t includeSigma) const
963 Int_t bin = FindEtaBin(eta);
966 AliError(Form("eta=%f out of bounds for FMD%d%c", eta, d, r));
969 return GetLowerBound(d, r, bin, f, showErrors, includeSigma);
972 //____________________________________________________________________
974 TH1D* MakeHist(const TAxis& axis, const char* name, const char* title,
977 TH1D* h = new TH1D(Form("%s_%s", name, title),
978 Form("%s %s", name, title),
979 axis.GetNbins(), axis.GetXmin(), axis.GetXmax());
981 h->SetMarkerStyle(20);
982 h->SetMarkerColor(color);
983 h->SetMarkerSize(0.5);
984 h->SetFillColor(color);
985 h->SetFillStyle(3001);
986 h->SetLineColor(color);
993 #define IDX2RING(I) (i == 0 || i == 1 || i == 3 ? 'I' : 'O')
994 #define IDX2DET(I) (i == 0 ? 1 : (i == 1 || i == 2 ? 2 : 3))
995 //____________________________________________________________________
997 AliFMDCorrELossFit::GetStacks(Bool_t err, Bool_t rel, UShort_t maxN) const
999 // Get a list of THStacks
1000 Int_t nRings = fRings.GetEntriesFast();
1001 Int_t nPad = 6+maxN-1; // 7 regular params, and maxN-1 weights
1019 TList* stacks = new TList;
1020 stacks->AddAt(sChi2nu= new THStack("chi2", "#chi^{2}/#nu"), kChi2nu);
1021 stacks->AddAt(sC = new THStack("c", "C"), kC);
1022 stacks->AddAt(sDelta = new THStack("delta", "#Delta_{mp}"), kDelta);
1023 stacks->AddAt(sXi = new THStack("xi", "#xi"), kXi);
1024 stacks->AddAt(sSigma = new THStack("sigma", "#sigma"), kSigma);
1025 //stacks->AddAt(sigman= new THStack("sigman", "#sigma_{n}"), 5);
1026 stacks->AddAt(n = new THStack("n", "N"), kN);
1027 for (Int_t i = 1; i <= maxN; i++) {
1028 stacks->AddAt(new THStack(Form("a_%02d", i+1), Form("a_{%d}", i+1)), kN+i);
1036 for (Int_t i = 0; i < nRings; i++) {
1037 if (!fRings.At(i)) continue;
1038 TObjArray* a = static_cast<TObjArray*>(fRings.At(i));
1039 Int_t nFits = a->GetEntriesFast();
1040 Int_t color = AliForwardUtil::RingColor(IDX2DET(i), IDX2RING(i));
1042 TH1D* hChi = MakeHist(fEtaAxis,a->GetName(), "chi2", color);
1043 TH1D* hC = MakeHist(fEtaAxis,a->GetName(), "c", color);
1044 TH1D* hDelta = MakeHist(fEtaAxis,a->GetName(), "delta", color);
1045 TH1D* hXi = MakeHist(fEtaAxis,a->GetName(), "xi", color);
1046 TH1D* hSigma = MakeHist(fEtaAxis,a->GetName(), "sigma", color);
1047 // TH1D* hSigmaN = MakeHist(fEtaAxis,a->GetName(), "sigman", color);
1048 TH1D* hN = MakeHist(fEtaAxis,a->GetName(), "n", color);
1050 const char* ho = (rel || !err ? "hist" : "e");
1051 sChi2nu->Add(hChi, "hist"); // 0
1052 sC ->Add(hC, ho); // 1
1053 sDelta ->Add(hDelta, ho); // 2
1054 sXi ->Add(hXi, ho); // 3
1055 sSigma ->Add(hSigma, ho); // 4
1056 // sigman->Add(hSigmaN,ho); // 5
1057 n ->Add(hN, "hist"); // 5
1058 hChi->SetFillColor(color);
1059 hChi->SetFillStyle(3001);
1060 hN->SetFillColor(color);
1061 hN->SetFillStyle(3001);
1063 for (Int_t k = 1; k <= maxN; k++) {
1064 hA[k-1] = MakeHist(fEtaAxis,a->GetName(), Form("a%02d",k+1), color);
1065 static_cast<THStack*>(stacks->At(kN+k))->Add(hA[k-1], ho);
1068 for (Int_t j = 0; j < nFits; j++) {
1069 ELossFit* f = static_cast<ELossFit*>(a->At(j));
1073 Int_t nW = f->FindMaxWeight();
1074 Double_t vChi2nu = (f->fNu <= 0 ? 0 : f->fChi2 / f->fNu);
1075 Double_t vC = (rel ? (f->fC >0 ?f->fEC /f->fC :0)
1077 Double_t vDelta = (rel ? (f->fDelta >0 ?f->fEDelta /f->fDelta :0)
1079 Double_t vXi = (rel ? (f->fXi >0 ?f->fEXi /f->fXi :0)
1081 Double_t vSigma = (rel ? (f->fSigma >0 ?f->fESigma /f->fSigma :0)
1083 // Double_t sigman = (rel ? (f->fSigmaN>0 ?f->fESigmaN/f->fSigmaN :0)
1085 hChi ->SetBinContent(b, vChi2nu);
1086 hN ->SetBinContent(b, nW);
1087 hC ->SetBinContent(b, vC);
1088 hDelta ->SetBinContent(b, vDelta);
1089 hXi ->SetBinContent(b, vXi);
1090 hSigma ->SetBinContent(b, vSigma);
1091 if (vChi2nu > 1e-12) {
1092 min[kChi2nu] = TMath::Min(min[kChi2nu], vChi2nu);
1093 max[kChi2nu] = TMath::Max(max[kChi2nu], vChi2nu);
1096 min[kC] = TMath::Min(min[kC], vC);
1097 max[kC] = TMath::Max(max[kC], vC);
1099 if (vDelta > 1e-12) {
1100 min[kDelta] = TMath::Min(min[kDelta], vDelta);
1101 max[kDelta] = TMath::Max(max[kDelta], vDelta);
1104 min[kXi] = TMath::Min(min[kXi], vXi);
1105 max[kXi] = TMath::Max(max[kXi], vXi);
1107 if (vSigma > 1e-12) {
1108 min[kSigma] = TMath::Min(min[kSigma], vSigma);
1109 max[kSigma] = TMath::Max(max[kSigma], vSigma);
1112 min[kN] = TMath::Min(min[kN], Double_t(nW));
1113 max[kN] = TMath::Max(max[kN], Double_t(nW));
1115 // hSigmaN->SetBinContent(b, sigman);
1117 hC ->SetBinError(b, f->fEC);
1118 hDelta ->SetBinError(b, f->fEDelta);
1119 hXi ->SetBinError(b, f->fEXi);
1120 hSigma ->SetBinError(b, f->fESigma);
1121 // hSigmaN->SetBinError(b, f->fESigmaN);
1123 for (Int_t k = 0; k < f->fN-1 && k < maxN; k++) {
1124 Double_t vA = (rel ? (f->fA[k] > 0 ? f->fEA[k] / f->fA[k] : 0)
1126 hA[k]->SetBinContent(b, vA);
1127 if (!rel) hA[k]->SetBinError(b, f->fEA[k]);
1129 min[kN+1+k] = TMath::Min(min[kN+1+k], vA);
1130 max[kN+1+k] = TMath::Max(max[kN+1+k], vA);
1138 //____________________________________________________________________
1140 AliFMDCorrELossFit::Draw(Option_t* option)
1146 // option Options. Possible values are
1147 // - err Plot error bars
1149 TString opt(Form("nostack %s", option));
1151 Bool_t rel = (opt.Contains("relative"));
1152 Bool_t err = (opt.Contains("error"));
1153 if (rel) opt.ReplaceAll("relative","");
1154 if (err) opt.ReplaceAll("error","");
1157 Int_t nRings = fRings.GetEntriesFast();
1158 for (Int_t i = 0; i < nRings; i++) {
1159 if (!fRings.At(i)) continue;
1160 TObjArray* a = static_cast<TObjArray*>(fRings.At(i));
1161 Int_t nFits = a->GetEntriesFast();
1163 for (Int_t j = 0; j < nFits; j++) {
1164 ELossFit* fit = static_cast<ELossFit*>(a->At(j));
1166 maxN = TMath::Max(maxN, UShort_t(fit->fN));
1169 // AliInfo(Form("Maximum N is %d", maxN));
1170 Int_t nPad = 6+maxN-1; // 7 regular params, and maxN-1 weights
1171 TVirtualPad* pad = gPad;
1172 pad->Divide(2, (nPad+1)/2, 0.1, 0, 0);
1174 TList* stacks = GetStacks(err, rel, maxN);
1176 Int_t nPad2 = (nPad+1) / 2;
1177 for (Int_t i = 0; i < nPad; i++) {
1178 Int_t iPad = 1 + i/nPad2 + 2 * (i % nPad2);
1179 TVirtualPad* p = pad->cd(iPad);
1180 p->SetLeftMargin(.15);
1185 if (rel && i != 0 && i != 6 && i != 5 && i != 4) p->SetLogy();
1188 THStack* stack = static_cast<THStack*>(stacks->At(i));
1190 // Double_t powMax = TMath::Log10(max[i]);
1191 // Double_t powMin = min[i] <= 0 ? powMax : TMath::Log10(min[i]);
1192 // if (powMax-powMin > 2. && min[i] != 0) p->SetLogy();
1194 // stack->SetMinimum(min[i]);
1195 // stack->SetMaximum(max[i]);
1196 stack->Draw(opt.Data());
1198 TString tit(stack->GetTitle());
1199 if (rel && i != 0 && i != 6)
1200 tit = Form("#delta %s/%s", tit.Data(), tit.Data());
1201 TH1* hist = stack->GetHistogram();
1202 TAxis* yaxis = hist->GetYaxis();
1203 yaxis->SetTitle(tit.Data());
1204 yaxis->SetTitleSize(0.15);
1205 yaxis->SetLabelSize(0.08);
1206 yaxis->SetTitleOffset(0.35);
1207 yaxis->SetTitleFont(132);
1208 yaxis->SetLabelFont(132);
1209 yaxis->SetNdivisions(5);
1212 TAxis* xaxis = stack->GetHistogram()->GetXaxis();
1213 xaxis->SetTitle("#eta");
1214 xaxis->SetTitleSize(0.15);
1215 xaxis->SetLabelSize(0.08);
1216 xaxis->SetTitleOffset(0.35);
1217 xaxis->SetTitleFont(132);
1218 xaxis->SetLabelFont(132);
1219 xaxis->SetNdivisions(10);
1221 stack->Draw(opt.Data());
1226 //____________________________________________________________________
1228 AliFMDCorrELossFit::Print(Option_t* option) const
1231 // Print this object.
1235 // - R Print recursive
1238 TString opt(option);
1240 Int_t nRings = fRings.GetEntriesFast();
1241 bool recurse = opt.Contains("R");
1243 std::cout << "Low cut in fit range: " << fLowCut << "\n"
1244 << "Eta axis: " << fEtaAxis.GetNbins()
1245 << " bins, range [" << fEtaAxis.GetXmin() << ","
1246 << fEtaAxis.GetXmax() << "]" << std::endl;
1248 for (Int_t i = 0; i < nRings; i++) {
1249 if (!fRings.At(i)) continue;
1250 TObjArray* a = static_cast<TObjArray*>(fRings.At(i));
1251 Int_t nFits = a->GetEntriesFast();
1253 std::cout << a->GetName() << " [" << nFits << " entries]"
1254 << (recurse ? ":\n" : "\t");
1255 Int_t min = fEtaAxis.GetNbins()+1;
1257 for (Int_t j = 0; j < nFits; j++) {
1258 if (!a->At(j)) continue;
1260 min = TMath::Min(j, min);
1261 max = TMath::Max(j, max);
1264 std::cout << "Bin # " << j << "\t";
1265 ELossFit* fit = static_cast<ELossFit*>(a->At(j));
1270 std::cout << " bin range: " << std::setw(3) << min
1271 << "-" << std::setw(3) << max << " " << std::setw(3)
1272 << (max-min+1) << " bins" << std::endl;
1276 //____________________________________________________________________
1278 AliFMDCorrELossFit::Browse(TBrowser* b)
1281 // Browse this object
1292 //____________________________________________________________________