17 #include <TLegendEntry.h>
21 #include <TParameter.h>
22 #include <TMultiGraph.h>
23 #include <TGraphAsymmErrors.h>
24 #include "RooUnfold.h"
25 #include "RooUnfoldResponse.h"
65 TFile*
file = TFile::Open(fileName,
"READ");
67 Error(
"GetTop",
"Failed to open %s", fileName.Data());
71 TString cName(Form(
"ForwardMult%s", results ?
"Results" :
"Sums"));
72 file->GetObject(cName, ret);
74 Error(
"GetTop",
"Failed to get collection %s from %s",
75 cName.Data(), fileName.Data());
90 TClass* cl,
Bool_t verbose=
true)
92 TObject* o = c->FindObject(name);
95 Warning(
"GetObject",
"%s not found in %s", name.Data(), c->GetName());
98 if (cl && !o->IsA()->InheritsFrom(cl)) {
100 Warning(
"GetCollection",
"%s is not a %s but a %s",
101 name.Data(), cl->GetName(), o->ClassName());
120 TCollection::Class(),
134 return static_cast<TH1*
>(
GetObject(c, name, TH1::Class(), verbose));
147 return static_cast<TH2*
>(
GetObject(c, name, TH2::Class(), verbose));
161 v = (!o ? 0 : o->GetUniqueID());
175 v = (!o ? 0 : o->GetUniqueID());
204 const Method methods[] = { {RooUnfold::kNone,
"None"},
206 {RooUnfold::kSVD,
"SVD"},
207 {RooUnfold::kBinByBin,
"BinByBin"},
208 {RooUnfold::kTUnfold,
"TUnfold"},
209 {RooUnfold::kInvert,
"Invert"},
210 {RooUnfold::kDagostini,
"Dagostini"},
211 {0xDeadBeef,
"unknown"} };
212 const Method* pMethod = methods;
213 while (pMethod->id != 0xDeadBeef) {
214 if (method.BeginsWith(pMethod->name, TString::kIgnoreCase)) {
215 method = pMethod->name;
220 if (pMethod->id == 0xDeadBeef)
221 Error(
"MethodId",
"Unknown unfolding method: %s", method.Data());
289 if (measuredFile.IsNull()) {
290 Error(
"Run",
"No measurements given");
296 if (!mTop || !cTop)
return;
309 if (sys == 0 || sNN == 0)
310 Warning(
"Run",
"System (%d) and/or collision energy (%d) unknown",
314 TFile* out = TFile::Open(
"forward_unfolded.root",
"RECREATE");
316 Error(
"Run",
"Failed to open output file");
323 if (mId == 0xDeadBeef)
return;
330 TString savPath(gROOT->GetMacroPath());
331 gROOT->SetMacroPath(Form(
"%s:$(ALICE_PHYSICS)/PWGLF/FORWARD/analysis2/scripts",
332 gROOT->GetMacroPath()));
334 if (!gROOT->GetClass(
"OtherPNch"))
335 gROOT->LoadMacro(
"OtherPNchData.C++");
336 gROOT->SetMacroPath(savPath);
339 const char* inputs[] = {
"symmetric",
"positive",
"negative", 0 };
340 const char** pinput = inputs;
344 if (mInput && cInput)
364 if (!trg.IsNull()) trg.Append(
" & ");
399 outMeth->SetUniqueID(mId);
406 TString tS = (sys == 1 ?
"pp" : sys == 2 ?
"PbPb" : sys == 3 ?
"pPb" :
"?");
407 TNamed* pS =
new TNamed(
"sys", tS.Data()); pS->SetUniqueID(sys);
411 if (sNN < 1000) tE = Form(
"%dGeV", sNN);
412 else if (sNN < 3000) tE = Form(
"%4.2fTeV",
float(sNN)/1000);
413 else tE = Form(
"%dTeV", sNN/1000);
414 TNamed* pE =
new TNamed(
"sNN", tE.Data()); pE->SetUniqueID(sNN);
445 kNClusterGt0 = 0x1000,
451 if ((trigger & kInel) != 0x0)
AppendAnd(tT,
"INEL");
452 if ((trigger & kInelGt0) != 0x0)
AppendAnd(tT,
"INEL>0");
453 if ((trigger & kNSD) != 0x0)
AppendAnd(tT,
"NSD");
454 if ((trigger & kV0AND) != 0x0)
AppendAnd(tT,
"V0AND");
455 if ((trigger & kA) != 0x0)
AppendAnd(tT,
"A");
456 if ((trigger & kB) != 0x0)
AppendAnd(tT,
"B");
457 if ((trigger & kC) != 0x0)
AppendAnd(tT,
"C");
458 if ((trigger & kE) != 0x0)
AppendAnd(tT,
"E");
459 if ((trigger & kMCNSD) != 0x0)
AppendAnd(tT,
"MCNSD");
460 if ((trigger & kNClusterGt0) != 0x0)
AppendAnd(tT,
"NCluster>0");
461 if ((trigger & kSatellite) != 0x0)
AppendAnd(tT,
"Satellite");
462 TNamed* pT =
new TNamed(
"trigger", tT.Data()); pT->SetUniqueID(trigger);
479 std::ofstream f(
"SummarizeUnfold.C");
480 f <<
"void SummarizeUnfold(const char* file=\"forward_unfolded.root\")\n"
482 <<
" const char* fwd=\"$ALICE_PHYSICS/PWGLF/FORWARD/analysis2\";\n"
483 <<
" gROOT->LoadMacro(Form(\"%s/DrawUnfoldedSummary.C\",fwd));\n"
484 <<
" DrawUnfoldedSummary(file);\n"
486 <<
"// EOF" << std::endl;
511 Printf(
" Processing %s ...", measured->GetName());
512 TDirectory* dir = out->mkdir(measured->GetName());
515 THStack* allMeasured =
new THStack(
"measured",
516 "Measured P(#it{N}_{ch})");
517 THStack* allTruth =
new THStack(
"truth",
518 "MC 'truth' P(#it{N}_{ch})");
519 THStack* allTruthA =
new THStack(
"truthAccepted",
520 "MC 'truth' accepted P(#it{N}_{ch})");
521 THStack* allUnfolded =
new THStack(
"unfolded",
522 "Unfolded P(#it{N}_{ch})");
523 THStack* allCorrected =
new THStack(
"corrected",
524 "Corrected P(#it{N}_{ch})");
525 THStack* allRatio = (sys != 1 ? 0 :
526 new THStack(
"ratios",
"Ratios to other"));
527 TMultiGraph* allALICE = (sys != 1 ? 0 :
528 new TMultiGraph(
"alice",
"ALICE Published"));
529 TMultiGraph* allCMS = (sys != 1 ? 0 :
530 new TMultiGraph(
"cms",
"CMS Published"));
533 static TRegexp regex(
"[pm][0-9]d[0-9]*_[pm][0-9]d[0-9]*");
534 TIter next(measured);
538 while ((o = next())) {
543 if (!o->IsA()->InheritsFrom(TCollection::Class()))
continue;
547 if (n.Index(regex) == kNPOS) {
556 THStack* binS =
ProcessBin(mBin, cBin, method, r, dir);
560 Bin2Stack(binS, i, allMeasured, allTruth, allTruthA,
561 allUnfolded, allCorrected, result);
565 Other2Stack(o->GetName(), i, sNN, allALICE, allCMS, alice, cms);
569 dir->Add(allMeasured);
572 dir->Add(allUnfolded);
573 dir->Add(allCorrected);
574 if (allALICE && allALICE->GetListOfGraphs()) {
575 if (allALICE->GetListOfGraphs()->GetEntries() > 0)
580 if (allCMS && allCMS->GetListOfGraphs()) {
581 if (allCMS->GetListOfGraphs()->GetEntries() > 0)
586 if (allRatio && allRatio->GetHists()) {
587 if (allRatio->GetHists()->GetEntries() > 0)
610 Printf(
" Processing %s ...", measured->GetName());
612 TH1* inRaw =
GetH1(measured,
"rawDist");
613 TH1* inTruth =
GetH1(corrections,
"truth");
614 TH1* inTruthA =
GetH1(corrections,
"truthAccepted");
615 TH1* inTrgVtx =
GetH1(corrections,
"triggerVertex");
616 TH2* inResp =
GetH2(corrections,
"response");
617 if (!inRaw || !inTruth || !inTruthA || !inTrgVtx || !inResp)
621 TDirectory* dir = out->mkdir(measured->GetName());
625 TH1* outRaw =
static_cast<TH1*
>(inRaw ->Clone(
"measured"));
626 TH1* outTruth =
static_cast<TH1*
>(inTruth ->Clone(
"truth"));
627 TH1* outTruthA =
static_cast<TH1*
>(inTruthA ->Clone(
"truthAccepted"));
628 TH1* outTrgVtx =
static_cast<TH1*
>(inTrgVtx ->Clone(
"triggerVertex"));
629 TH2* outResp =
static_cast<TH2*
>(inResp ->Clone(
"response"));
632 RooUnfoldResponse matrix(0, 0, inResp);
636 RooUnfold::Algorithm algo = (RooUnfold::Algorithm)method;
637 RooUnfold* unfolder = RooUnfold::New(algo, &matrix, inRaw, r);
638 unfolder->SetVerbose(0);
641 TH1* res = unfolder->Hreco();
642 res->SetDirectory(0);
645 TH1* outUnfold =
static_cast<TH1*
>(res->Clone(
"unfolded"));
646 TString tit(outUnfold->GetTitle());
647 tit.ReplaceAll(
"Unfold Reponse matrix",
"Unfolded P(#it{N}_{ch})");
648 outUnfold->SetTitle(tit);
652 TH1* outCorr =
static_cast<TH1*
>(outUnfold->Clone(
"corrected"));
653 outCorr->Divide(inTrgVtx);
654 tit.ReplaceAll(
"Unfolded",
"Corrected");
655 outCorr->SetTitle(tit);
658 TH1* hists[] = { outRaw, outUnfold, outCorr, 0 };
663 Double_t intg = h->Integral(1, h->GetXaxis()->GetXmax());
664 h->Scale(1. / intg,
"width");
670 TH1* ratioTrue =
static_cast<TH1*
>(outCorr->Clone(
"ratioCorrTruth"));
671 tit = ratioTrue->GetTitle();
672 tit.ReplaceAll(
"Corrected",
"Corrected/MC 'truth'");
673 ratioTrue->SetTitle(tit);
674 ratioTrue->Divide(outTruth);
675 ratioTrue->SetYTitle(
"P_{corrected}(#it{N}_{ch})/P_{truth}(#it{N}_{ch})");
677 TH1* ratioAcc =
static_cast<TH1*
>(outUnfold->Clone(
"ratioUnfAcc"));
678 tit = ratioAcc->GetTitle();
679 tit.ReplaceAll(
"Unfolded",
"Unfolded/MC selected");
680 ratioAcc->SetTitle(tit);
681 ratioAcc->Divide(outTruthA);
682 ratioAcc->SetYTitle(
"P_{unfolded}(#it{N}_{ch})/P_{MC}(#it{N}_{ch})");
686 tit = measured->GetName();
687 tit.ReplaceAll(
"m",
"-");
688 tit.ReplaceAll(
"p",
"+");
689 tit.ReplaceAll(
"d",
".");
690 tit.ReplaceAll(
"_",
"<#it{#eta}<");
691 THStack* stack =
new THStack(
"all", tit);
692 stack->Add(outTruth,
"E2");
693 stack->Add(outTruthA,
"E2");
694 stack->Add(outRaw,
"E1");
695 stack->Add(outUnfold,
"E1");
696 stack->Add(outCorr,
"E1");
700 outRaw ->SetDirectory(dir);
701 outTruth ->SetDirectory(dir);
702 outTruthA->SetDirectory(dir);
703 outTrgVtx->SetDirectory(dir);
704 outResp ->SetDirectory(dir);
705 outUnfold->SetDirectory(dir);
706 outCorr ->SetDirectory(dir);
708 outRaw ->SetMarkerStyle(20);
709 outTruth ->SetMarkerStyle(24);
710 outTruthA->SetMarkerStyle(24);
711 outTrgVtx->SetMarkerStyle(20);
712 outUnfold->SetMarkerStyle(20);
713 outCorr ->SetMarkerStyle(20);
715 outRaw ->SetMarkerSize(0.9);
716 outTruth ->SetMarkerSize(1.6);
717 outTruthA->SetMarkerSize(1.4);
718 outTrgVtx->SetMarkerSize(1.0);
719 outUnfold->SetMarkerSize(0.9);
720 outCorr ->SetMarkerSize(1.0);
736 outRaw ->SetFillStyle(0);
737 outTruth ->SetFillStyle(1001);
738 outTruthA->SetFillStyle(1001);
739 outTrgVtx->SetFillStyle(0);
740 outUnfold->SetFillStyle(0);
741 outCorr ->SetFillStyle(0);
743 outRaw ->SetLineColor(kBlack);
744 outTruth ->SetLineColor(kBlack);
745 outTruthA->SetLineColor(kBlack);
746 outTrgVtx->SetLineColor(kBlack);
747 outUnfold->SetLineColor(kBlack);
748 outCorr ->SetLineColor(kBlack);
752 l->AddEntry(outRaw,
"Raw",
"lp");
753 l->AddEntry(outTruth,
"MC 'truth'",
"fp");
754 l->AddEntry(outTruthA,
"MC 'truth' accepted",
"fp");
755 l->AddEntry(outUnfold,
"Unfolded",
"lp");
756 l->AddEntry(outCorr,
"Corrected",
"lp");
767 const Int_t nMarkers = 7;
768 const Int_t aClosed[] = { 20, 21, 22, 23, 29, 33, 34 };
769 const Int_t aOpen[] = { 24, 25, 26, 32, 30, 27, 28 };
770 const Float_t aSize[] = { 1.1, 1.0, 1.2, 1.2, 1.2, 1.2, 1.0 };
771 Int_t j = i % nMarkers;
776 factor = TMath::Power(10, i);
803 TIter next(bin->GetHists());
805 while ((h = static_cast<TH1*>(next()))) {
807 Int_t col = h->GetMarkerColor();
818 TH1* cln =
static_cast<TH1*
>(h->Clone(h->GetName()));
819 cln->SetDirectory(0);
820 cln->SetMarkerStyle(sty);
821 cln->SetMarkerSize(size);
826 TObject* tst = cln->FindObject(
"legend");
827 if (tst) cln->GetListOfFunctions()->Remove(tst);
829 tmp->Add(cln, next.GetOption());
834 if (i == 0) txt.Append(
" (#times1)");
835 else if (i == 1) txt.Append(
" (#times10)");
836 else txt.Append(Form(
" (#times10^{%d})", i));
837 THStack* stacks[] = { measured, truth, accepted, unfolded, corrected, 0 };
838 THStack** pstack = stacks;
845 TLegendEntry* e = leg->AddEntry(dummy, txt,
"p");
846 e->SetMarkerStyle(closed);
847 e->SetMarkerSize(1.2*size);
848 e->SetMarkerColor(kBlack);
851 e->SetLineColor(kBlack);
866 UShort_t sNN, TMultiGraph* allALICE, TMultiGraph* allCMS,
869 if (!allALICE && !allCMS)
return;
872 tmp.ReplaceAll(
"p",
"+");
873 tmp.ReplaceAll(
"m",
"-");
874 tmp.ReplaceAll(
"_",
" ");
875 tmp.ReplaceAll(
"d",
".");
877 if (!tokens || tokens->GetEntriesFast() < 2) {
878 Error(
"Other2Stack",
"Failed to decode eta range from %s", name.Data());
879 if (tokens) tokens->Delete();
882 Double_t eta1 =
static_cast<TObjString*
>(tokens->At(0))->String().Atof();
883 Double_t eta2 =
static_cast<TObjString*
>(tokens->At(1))->String().Atof();
886 if (TMath::Abs(eta2+eta1) > 1e-3) {
902 g->SetMarkerStyle(closed);
904 g->SetMarkerSize(size);
905 allALICE->Add(g,
"p same");
912 g->SetMarkerStyle(closed);
914 g->SetMarkerSize(size);
915 allCMS->Add(g,
"p same");
931 if (!all || !res || !(alice || cms))
return;
934 TGraph* gs[] = { (alice ? alice : cms), (alice ? cms : 0), 0 };
938 const char* n = (g == alice ?
"ALICE" :
"CMS");
940 TH1* r =
static_cast<TH1*
>(res->Clone(Form(
"ratio%s", n)));
942 tit.ReplaceAll(
"Corrected", Form(
"Ratio to %s", n));
944 r->SetMarkerColor(g->GetMarkerColor());
945 r->SetLineColor(g->GetLineColor());
947 TObject* tst = r->FindObject(
"legend");
948 if (tst) r->GetListOfFunctions()->Remove(tst);
950 for (
Int_t i = 1; i <= r->GetNbinsX(); i++) {
953 Double_t o = g->Eval(r->GetBinCenter(i));
955 r->SetBinContent(i, 0);
956 r->SetBinError(i, 0);
959 r->SetBinContent(i, (c - o) / o + off);
960 r->SetBinError(i, e / o);
969 txt.ReplaceAll(
"Corrected P(#it{N}_{ch}) in ",
"");
970 if (ib == 0) txt.Append(
" ");
972 else txt.Append(Form(
" (+%d)", off));
975 TLegendEntry* e = leg->AddEntry(dummy, txt,
"p");
976 e->SetMarkerStyle(res->GetMarkerStyle());
977 e->SetMarkerSize(res->GetMarkerSize());
978 e->SetMarkerColor(kBlack);
981 e->SetLineColor(kBlack);
995 TList* hists = stack->GetHists();
996 if (!hists)
return 0;
998 TObject* first = hists->First();
999 if (!first)
return 0;
1001 TH1* hist =
static_cast<TH1*
>(first);
1002 TList*
list = hist->GetListOfFunctions();
1003 TObject* o = list->FindObject(
"legend");
1004 if (o)
return static_cast<TLegend*
>(o);
1006 TLegend* l =
new TLegend(0.65, 0.65, 0.9, 0.9,
"",
"NDC");
1007 l->SetName(
"legend");
1008 l->SetBorderSize(0);
1024 TString oC = Form(
"OtherPNch::GetData(%hu,%f,%hu);",
1035 for (
Int_t j = 0; j < g->GetN(); j++) {
1036 g->SetPoint(j, g->GetX()[j], g->GetY()[j]*factor);
1037 g->SetPointError(j, g->GetEXlow()[j], g->GetEXhigh()[j],
1038 g->GetEYlow()[j]*factor, g->GetEYhigh()[j]*factor);
1047 const TString& measured=
"forward_multdists.root",
1048 const TString& corrections=
"")
1051 m.
Run(measured, corrections,
method, regParam);
void Run(const TString &measuredFile, const TString &corrFile, const TString &method="Bayes", Double_t regParam=4)
void Ratio2Stack(Int_t ib, TH1 *res, TGraph *alice, TGraph *cms, THStack *all)
void Bin2Stack(const THStack *bin, Int_t i, THStack *measured, THStack *truth, THStack *accepted, THStack *unfolded, THStack *corrected, TH1 *&result)
static TCollection * GetTop(const TString &fileName, Bool_t results=false)
static void GetParameter(TCollection *c, const TString &name, ULong_t &v)
static TH2 * GetH2(TCollection *c, const TString &name, Bool_t verbose=true)
static void GetParameter(TCollection *c, const TString &name, UShort_t &v)
static void AppendAnd(TString &trg, const TString &what)
void UnfoldMultDists(const TString &method="Bayes", Double_t regParam=1e-30, const TString &measured="forward_multdists.root", const TString &corrections="")
void Other2Stack(const TString &name, Int_t i, UShort_t sNN, TMultiGraph *allALICE, TMultiGraph *allCMS, TGraph *&alice, TGraph *&cms)
static TH1 * GetH1(TCollection *c, const TString &name, Bool_t verbose=true)
static TObject * GetObject(TCollection *c, const TString &name, TClass *cl, Bool_t verbose=true)
void SaveInformation(TDirectory *dir, const TString &method, Int_t mId, Double_t regParam, UShort_t sys, UShort_t sNN, UInt_t trigger, Double_t minIpZ, Double_t maxIpZ, Bool_t self) const
static void GetParameter(TCollection *c, const TString &name, Double_t &v)
TLegend * StackLegend(THStack *stack)
static TCollection * GetCollection(TCollection *c, const TString &name, Bool_t verbose=-true)
void ProcessType(TCollection *measured, TCollection *corrections, UInt_t method, Double_t regParam, TDirectory *out, UShort_t sys, UShort_t sNN)
static void BinAttributes(Int_t i, Int_t &open, Int_t &closed, Float_t &size, Double_t &factor)
THStack * ProcessBin(TCollection *measured, TCollection *corrections, UInt_t method, Double_t regParam, TDirectory *out)
TGraphAsymmErrors * GetOther(UShort_t type, Double_t eta, UShort_t sNN, Int_t factor)
static UInt_t MethodId(TString &method)