// Original Author: Loic Quertenmont #ifndef PLOT_FUNCTION #define PLOT_FUNCTION int Color [] = {1,4,2,8,6,9,3,7,5}; int Marker[] = {20,22,21,23,29,27,2, 30}; int Style [] = {1,2,5,7,9,10,11,12}; int GraphStyle [] = {20, 21, 22, 23, 24, 25, 26, 27}; // handfull function to get one TObject from a complex cirectory stucture in a file TObject* GetObjectFromPath(TDirectory* File, std::string Path, bool GetACopy=false) { size_t pos = Path.find("/"); if(pos < 256){ std::string firstPart = Path.substr(0,pos); std::string endPart = Path.substr(pos+1,Path.length()); TDirectory* TMP = (TDirectory*)File->Get(firstPart.c_str()); if(TMP!=NULL)return GetObjectFromPath(TMP,endPart,GetACopy); printf("BUG: %s\n",Path.c_str()); return NULL; }else{ if(GetACopy){ return (File->Get(Path.c_str()))->Clone(); }else{ return File->Get(Path.c_str()); } } } // similar to the above code TObject* GetObjectFromPath(TDirectory* Container, TDirectory* File, std::string Path, bool GetACopy=false){ TObject* toreturn = GetObjectFromPath(File,Path,GetACopy); if(TH1* th1 = dynamic_cast<TH1*>(toreturn))th1->SetDirectory(Container); return toreturn; } // create a directory/subdirectory on disk void MakeDirectories(std::string path){ system( (std::string("mkdir -p ") + path).c_str()); } // save a TCanvas on disk in a few different format (mind that 2D plots can be huge if saved in eps/C/pdf) void SaveCanvas(TCanvas* c, std::string path, std::string name, bool OnlyPPNG=false){ std::string tmppath = path; if(tmppath[tmppath.length()-1]!='/')tmppath += "_"; tmppath += name; std::string filepath; filepath = tmppath + ".png"; c->SaveAs(filepath.c_str()); if(OnlyPPNG)return; filepath = tmppath + ".eps"; c->SaveAs(filepath.c_str()); filepath = tmppath + ".C" ; c->SaveAs(filepath.c_str()); filepath = tmppath + ".pdf"; c->SaveAs(filepath.c_str()); } // function that add the TPaveText on the current canvas with the "CMS Preliminary...." on top of the Histograms. For split Lumi void DrawPreliminary(string Text, double SQRTS_, string LumiText, bool preliminary=true, double X=0.15, double Y=0.995, double W=0.82, double H=0.945){ TPaveText* T = new TPaveText(X,Y,W,H, "NDC"); T->SetTextFont(43); //give the font size in pixel (instead of fraction) T->SetTextSize(21); //font size T->SetFillColor(0); T->SetFillStyle(0); T->SetBorderSize(0); T->SetTextAlign(22); char tmp[2048]; char energy[128]; // if(SQRTS_==78.0 || SQRTS_==87.0){ // sprintf(energy, "#sqrt{s} = %1.0f+%1.0f TeV ",7.0,8.0); // }else if(SQRTS_>0.0){ // sprintf(energy, "#sqrt{s} = %1.0f TeV ",SQRTS_); // }else{ sprintf(energy, ""); // } if(preliminary){ if(Text!="" && !(SQRTS_==78.0 || SQRTS_==87.0)){ sprintf(tmp,"%s #bf{CMS Preliminary} %s%s",Text.c_str(), energy, LumiText.c_str()); }else{ sprintf(tmp,"#bf{CMS Preliminary} %s%s",energy, LumiText.c_str()); } }else{ if(Text!="" && !(SQRTS_==78.0 || SQRTS_==87.0)){ sprintf(tmp,"%s CMS %s%s",Text.c_str(), energy, LumiText.c_str()); }else{ T->SetTextSize(18); sprintf(tmp,"CMS %s%s",energy, LumiText.c_str()); } } T->AddText(tmp); T->Draw("same"); if(Text!="" && (SQRTS_==78.0 || SQRTS_==87.0)){ double h = fabs(Y-H); TPaveText* T2 = new TPaveText(X-0.02,H-0.35*h,W,H-1.35*h, "NDC"); T2->SetTextFont(43); //give the font size in pixel (instead of fraction) T2->SetTextSize(18); //font size T2->SetFillColor(0); T2->SetFillStyle(0); T2->SetFillStyle(0); T2->SetBorderSize(0); T2->SetTextAlign(12); sprintf(tmp,"%s",Text.c_str()); T2->AddText(tmp); T2->Draw("same"); } } // function that add the TPaveText on the current canvas with the "CMS Preliminary...." on top of the Histograms void DrawPreliminary(string Text, double SQRTS_, double Lumi, bool preliminary, double X=0.15, double Y=0.995, double W=0.82, double H=0.945){ TPaveText* T = new TPaveText(X,Y,W,H, "NDC"); T->SetTextFont(43); //give the font size in pixel (instead of fraction) T->SetTextSize(21); //font size T->SetFillColor(0); T->SetTextAlign(12); char tmp[2048]; char energy[128]; if(SQRTS_==78.0 || SQRTS_==87.0){ sprintf(energy, "#sqrt{s} = %1.0f+%1.0f TeV",7.0,8.0); }else if(SQRTS_>0.0){ sprintf(energy, "#sqrt{s} = %1.0f TeV",SQRTS_); }else{ sprintf(energy, ""); } char LumiText[1024]; if(preliminary){ if(Lumi<=0 ){ sprintf(LumiText,"#bf{CMS Preliminary} %s",energy); }else if(Lumi>0 ){ sprintf(LumiText,"#bf{CMS Preliminary} %s %1.1f fb ^{-1}",energy, Lumi*0.001); } }else{ if(Lumi<=0 ){ sprintf(LumiText,"CMS %s",energy); }else if(Lumi>0 ){ sprintf(LumiText,"CMS %s %1.1f fb ^{-1}",energy, Lumi*0.001); } } //if(Text!=""){ // sprintf(tmp,"%s - %s",Text.c_str(), LumiText); //}else{ // sprintf(tmp,"%s",LumiText); //} T->AddText(tmp); T->Draw("same"); if(Text!=""){ double h = fabs(Y-H); TPaveText* T2 = new TPaveText(X,H-0.6*h,W,H-1.6*h, "NDC"); T2->SetTextFont(43); //give the font size in pixel (instead of fraction) T2->SetTextSize(18); //font size T2->SetFillColor(0); T2->SetFillStyle(0); T2->SetTextAlign(12); sprintf(tmp,"%s",Text.c_str()); T2->AddText(tmp); T2->Draw("same"); } } void DrawPreliminary(double SQRTS_, double Lumi, double X=0.40, double Y=0.995, double W=0.82, double H=0.945){ DrawPreliminary("",SQRTS_, Lumi, X,Y,W,H); } // handfull function to draw the legend associated to a vector of histogram void DrawLegend (TObject** Histos, std::vector<std::string> legend, std::string Title, std::string Style_, double X=0.79, double Y=0.92, double W=0.20, double H=0.05) { int N = legend.size(); if(legend[0]!=""){ TLegend* leg; leg = new TLegend(X,Y,X-W,Y - N*H); leg->SetFillStyle(0); leg->SetBorderSize(0); leg->SetTextFont(43); //give the font size in pixel (instead of fraction) leg->SetTextSize(20); //font size // leg->SetTextAlign(11); if(Title!="")leg->SetHeader(Title.c_str()); if(Style_=="DataMC"){ for(int i=0;i<N;i++){ TH2D* temp = (TH2D*)Histos[i]->Clone(); temp->SetMarkerSize(1.3); if(i==0){ leg->AddEntry(temp, legend[i].c_str() ,"P"); }else{ leg->AddEntry(temp, legend[i].c_str() ,"L"); } } }else{ for(int i=0;i<N;i++){ TH2D* temp = (TH2D*)Histos[i]->Clone(); temp->SetMarkerSize(1.3); leg->AddEntry(temp, legend[i].c_str() ,Style_.c_str()); } } leg->Draw(); } } // draw the stat box void DrawStatBox(TObject** Histos, std::vector<std::string> legend, bool Mean, double X=0.15, double Y=0.93, double W=0.15, double H=0.03) { int N = legend.size(); char buffer[255]; if(Mean)H*=3; for(int i=0;i<N;i++){ TPaveText* stat = new TPaveText(X,Y-(i*H), X+W, Y-(i+1)*H, "NDC"); TH1* Histo = (TH1*)Histos[i]; sprintf(buffer,"Entries : %i\n",(int)Histo->GetEntries()); stat->AddText(buffer); if(Mean){ sprintf(buffer,"Mean : %6.2f\n",Histo->GetMean()); stat->AddText(buffer); sprintf(buffer,"RMS : %6.2f\n",Histo->GetRMS()); stat->AddText(buffer); } stat->SetFillColor(0); stat->SetLineColor(Color[i]); stat->SetTextColor(Color[i]); stat->SetBorderSize(0); stat->SetMargin(0.05); stat->SetTextAlign(12); stat->Draw(); } } // draw a TH2D histogram void DrawTH2D(TH2D** Histos, std::vector<std::string> legend, std::string Style_, std::string Xlegend, std::string Ylegend, double xmin, double xmax, double ymin, double ymax) { int N = legend.size(); for(int i=0;i<N;i++){ if(!Histos[i])continue; Histos[i]->SetTitle(""); Histos[i]->SetStats(kFALSE); Histos[i]->GetXaxis()->SetTitle(Xlegend.c_str()); Histos[i]->GetYaxis()->SetTitle(Ylegend.c_str()); Histos[i]->GetYaxis()->SetTitleOffset(1.60); if(xmin!=xmax)Histos[i]->SetAxisRange(xmin,xmax,"X"); if(ymin!=ymax)Histos[i]->SetAxisRange(ymin,ymax,"Y"); Histos[i]->SetMarkerStyle(Marker[i]); Histos[i]->SetMarkerColor(Color[i]); Histos[i]->SetMarkerSize(0.3); } char Buffer[256]; Histos[0]->Draw(Style_.c_str()); for(int i=1;i<N;i++){ sprintf(Buffer,"%s same",Style_.c_str()); Histos[i]->Draw(Buffer); } } // Draw a list of TH1 and superimposed them void DrawSuperposedHistos(TH1** Histos, std::vector<std::string> legend, std::string Style_, std::string Xlegend, std::string Ylegend, double xmin, double xmax, double ymin, double ymax, bool Normalize=false, bool same=false, bool lastBinOverflow=false, bool firstBinOverflow=false) { int N = legend.size(); double HistoMax = -1; int HistoHeighest = -1; for(int i=0;i<N;i++){ if(!Histos[i])continue; if(Normalize && Histos[i]->Integral()!=0)Histos[i]->Scale(1.0/Histos[i]->Integral()); Histos[i]->SetTitle(""); Histos[i]->SetStats(kFALSE); Histos[i]->GetXaxis()->SetTitle(Xlegend.c_str()); Histos[i]->GetYaxis()->SetTitle(Ylegend.c_str()); Histos[i]->GetXaxis()->SetTitleOffset(1.1); Histos[i]->GetYaxis()->SetTitleOffset(1.40); Histos[i]->GetXaxis()->SetNdivisions(505); Histos[i]->GetYaxis()->SetNdivisions(505); Histos[i]->GetXaxis()->SetTitleSize(0.05); if(xmin!=xmax)Histos[i]->SetAxisRange(xmin,xmax,"X"); if(ymin!=ymax)Histos[i]->SetAxisRange(ymin,ymax,"Y"); Histos[i]->SetFillColor(0); Histos[i]->SetMarkerStyle(Marker[i]); Histos[i]->SetMarkerColor(Color[i]); Histos[i]->SetMarkerSize(1.5); Histos[i]->SetLineColor(Color[i]); Histos[i]->SetLineWidth(2); if(lastBinOverflow) { if(xmin!=xmax) { int lastBin=Histos[i]->GetXaxis()->FindBin(xmax); double sum=0; double error=0; for(int b=lastBin; b<Histos[i]->GetNbinsX()+2; b++) {sum+=Histos[i]->GetBinContent(b); error+=Histos[i]->GetBinError(b)*Histos[i]->GetBinError(b);} Histos[i]->SetBinContent(lastBin, sum); Histos[i]->SetBinError(lastBin, sqrt(error)); } else { Histos[i]->SetBinContent(Histos[i]->GetNbinsX(), Histos[i]->GetBinContent(Histos[i]->GetNbinsX())+Histos[i]->GetBinContent(Histos[i]->GetNbinsX()+1)); double error=sqrt(pow(Histos[i]->GetBinError(Histos[i]->GetNbinsX()),2)+pow(Histos[i]->GetBinError(Histos[i]->GetNbinsX()+1),2)); Histos[i]->SetBinError(Histos[i]->GetNbinsX(), error); } } if(firstBinOverflow) { if(xmin!=xmax) { int firstBin=Histos[i]->GetXaxis()->FindBin(xmin); double sum=0; double error=0; for(int b=0; b<firstBin; b++) {sum+=Histos[i]->GetBinContent(b); error+=Histos[i]->GetBinError(b)*Histos[i]->GetBinError(b);} Histos[i]->SetBinContent(firstBin, sum); Histos[i]->SetBinError(firstBin, sqrt(error)); } else { Histos[i]->SetBinContent(1, Histos[i]->GetBinContent(1)+Histos[i]->GetBinContent(0)); double error=sqrt(pow(Histos[i]->GetBinError(1),2)+pow(Histos[i]->GetBinError(0),2)); Histos[i]->SetBinError(1, error); } } if(Style_=="DataMC" && i==0){ Histos[i]->SetFillColor(0); Histos[i]->SetMarkerStyle(20); Histos[i]->SetMarkerColor(1); Histos[i]->SetMarkerSize(1); Histos[i]->SetLineColor(1); Histos[i]->SetLineWidth(2); } if(Histos[i]->GetMaximum() >= HistoMax){ HistoMax = Histos[i]->GetMaximum(); HistoHeighest = i; } } char Buffer[256]; if(Style_=="DataMC"){ if(HistoHeighest==0){ Histos[HistoHeighest]->Draw("E1"); }else{ Histos[HistoHeighest]->Draw("HIST"); } for(int i=0;i<N;i++){ if(i==HistoHeighest)continue; if(i==0){ Histos[i]->Draw("same E1"); }else{ Histos[i]->Draw("same"); } } }else{ if(same) {sprintf(Buffer,"same %s",Style_.c_str()); Histos[HistoHeighest]->Draw(Buffer);} else Histos[HistoHeighest]->Draw(Style_.c_str()); for(int i=0;i<N;i++){ if(i==HistoHeighest)continue; if(Style_!=""){ sprintf(Buffer,"same %s",Style_.c_str()); }else{ sprintf(Buffer,"same"); } Histos[i]->Draw(Buffer); } } } // automatically determined what is the best axis ranges for a TH2D void Smart_SetAxisRange(TH2D* histo){ double Min=1E50; double Max=1E-50; for(int x=1;x<=histo->GetNbinsX();x++){ for(int y=1;y<=histo->GetNbinsY();y++){ double c = histo->GetBinContent(x,y); if(c<Min && c>0)Min=c; if(c>Max)Max=c; }} if(Max/Min<10 ){Max*= 5.0; Min/= 5.0;} else if(Max/Min<100){Max*=10.0; Min/=10.0;} histo->SetAxisRange(Min,Max,"Z"); } // return a TCUTG corresponding to the uncertainty on a xsection TCutG* GetErrorBand(string name, int N, double* Mass, double* Low, double* High, double MinLow, double MaxHigh){ TCutG* cutg = new TCutG(name.c_str(),2*N); cutg->SetFillColor(kGreen-7); double I=0; for(int i=0;i<N;i++){ if(High[i]<MinLow){continue;} double Min = std::max(Low[i],MinLow); cutg->SetPoint(I,Mass[i], Min); I++; } for(int i=0;i<N;i++){ if(Low[N-1-i] > MaxHigh){continue;} double Max = std::min(High[N-1-i],MaxHigh); cutg->SetPoint(I,Mass[N-1-i], Max); I++; } cutg->Set(I); return cutg; } std::string toLatexRounded(double value, double error=-1, double systError=-1) { using namespace std; if(value==0.0 && error==0.0)return string(""); double power = floor(log10(value)); if(power<=-3) {power=power+3; }else if(power>=2){power=power-2; }else {power=0;} value = value / pow(10,power); if(error>=0)error = error / pow(10,power); if(systError>=0)systError = systError / pow(10,power); int ValueFloating; if(systError<0){ ValueFloating = 1 + std::max(-1*log10(error),0.0); }else{ ValueFloating = 1 + std::max(-1*log10(systError), std::max(-1*log10(error),0.0)); } int ErrorFloating = ValueFloating; char tmpchar[255]; if(power!=0){ if(systError<0){ if(error<0){ sprintf(tmpchar,"$(%.*f)\\times 10^{%g}$",ValueFloating,value,power); }else{ sprintf(tmpchar,"$(%.*f\\pm%.*f)\\times 10^{%g}$",ValueFloating,value,ErrorFloating,error,power); } }else{ sprintf(tmpchar,"$(%.*f\\pm%.*f\\pm%.*f)\\times 10^{%g}$",ValueFloating,value,ErrorFloating,error,ErrorFloating,systError,power); } }else{ if(systError<0){ if(error<0){ sprintf(tmpchar,"$%.*f$",ValueFloating,value); }else{ sprintf(tmpchar,"$%.*f\\pm%.*f$",ValueFloating,value,ErrorFloating,error); } }else{ sprintf(tmpchar,"$%.*f\\pm%.*f\\pm%.*f$",ValueFloating,value,ErrorFloating,error,ErrorFloating,systError); } } return string(tmpchar); } #endif