diff --git a/.gitignore b/.gitignore index ac06389597925..91a07dc52f335 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,11 @@ compile_commands.json documentation/doxygen/*.eps documentation/doxygen/*.pcm documentation/doxygen/*.jpg +documentation/doxygen/*.root +documentation/doxygen/*.csv +documentation/doxygen/*.png +documentation/doxygen/*.pdf +documentation/doxygen/*.dot # Pycache __pycache__ diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 7b5cfc3a25d57..fe15800460c21 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -273,10 +273,10 @@ set(gui_veto fit/fitpanel_playback.C geom/building.C geom/cheongwadae.C geom/geom*.C geom/lego.C geom/robot.C geom/south_gate.C geom/station*.C geom/tank.C geom/webdemo.C geom/web_cms.cxx gl/glViewerExercise.C gl/glViewerLOD.C gl/gviz3d.C gl/nucleus.C gl/viewer3DLocal.C gl/viewer3DMaster.C gui/*.C - hist/exec1.C - hist/exec2.C - hist/tprofile2polyRealistic.C - hist/tprofile2polyRealisticModuleError.C + hist/hist057_TExec_th1.C + hist/hist057_TExec_th2.C + hist/hist041_TProfile2Poly_realistic.C + hist/hist042_TProfile2Poly_module_error.C image/*.C graphics/psview.C graphics/gtime.C graphics/graph_edit_playback.C @@ -506,13 +506,13 @@ set(returncode_1 fit/fit2a.C graphics/tmathtext.C graphics/tmathtext2.C graphs/exclusiongraph.C graphs/graphstruct.C - hist/ContourList.C - hist/hbars.C - hist/th2polyBoxes.C - hist/statsEditing.C - hist/cumulative.C - hist/hlabels1.C - hist/hlabels2.C + hist/hist102_TH2_contour_list.C + hist/hist006_TH1_bar_charts.C + hist/hist037_TH2Poly_boxes.C + hist/hist060_Stats.C + hist/hist014_TH1_cumulative.C + hist/hist004_TH1_labels.C + hist/hist036_TH2_labels.C tree/h1analysis.C math/chi2test.C r/SimpleFitting.C) diff --git a/tutorials/hist/ContourList.C b/tutorials/hist/ContourList.C deleted file mode 100644 index 248d976aa6bd7..0000000000000 --- a/tutorials/hist/ContourList.C +++ /dev/null @@ -1,182 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Getting Contours From TH2D. -/// -/// #### Image produced by `.x ContourList.C` -/// The contours values are drawn next to each contour. -/// \macro_image -/// -/// #### Output produced by `.x ContourList.C` -/// It shows that 6 contours and 12 graphs were found. -/// \macro_output -/// -/// #### `ContourList.C` -/// \macro_code -/// -/// \authors Josh de Bever (CSI Medical Physics Group, The University of Western Ontario, London, Ontario, Canada), Olivier Couet - -Double_t SawTooth(Double_t x, Double_t WaveLen); - -TCanvas *ContourList(){ - - const Double_t PI = TMath::Pi(); - - TCanvas* c = new TCanvas("c","Contour List",0,0,600,600); - c->SetRightMargin(0.15); - c->SetTopMargin(0.15); - - Int_t i, j; - - Int_t nZsamples = 80; - Int_t nPhiSamples = 80; - - Double_t HofZwavelength = 4.0; // 4 meters - Double_t dZ = HofZwavelength/(Double_t)(nZsamples - 1); - Double_t dPhi = 2*PI/(Double_t)(nPhiSamples - 1); - - TArrayD z(nZsamples); - TArrayD HofZ(nZsamples); - TArrayD phi(nPhiSamples); - TArrayD FofPhi(nPhiSamples); - - // Discretized Z and Phi Values - for ( i = 0; i < nZsamples; i++) { - z[i] = (i)*dZ - HofZwavelength/2.0; - HofZ[i] = SawTooth(z[i], HofZwavelength); - } - - for(Int_t i=0; i < nPhiSamples; i++){ - phi[i] = (i)*dPhi; - FofPhi[i] = sin(phi[i]); - } - - // Create Histogram - TH2D *HistStreamFn = new TH2D("HstreamFn", - "#splitline{Histogram with negative and positive contents. Six contours are defined.}{It is plotted with options CONT LIST to retrieve the contours points in TGraphs}", - nZsamples, z[0], z[nZsamples-1], nPhiSamples, phi[0], phi[nPhiSamples-1]); - - // Load Histogram Data - for (Int_t i = 0; i < nZsamples; i++) { - for(Int_t j = 0; j < nPhiSamples; j++){ - HistStreamFn->SetBinContent(i,j, HofZ[i]*FofPhi[j]); - } - } - - gStyle->SetOptStat(0); - gStyle->SetTitleW(0.99); - gStyle->SetTitleH(0.08); - - Double_t contours[6]; - contours[0] = -0.7; - contours[1] = -0.5; - contours[2] = -0.1; - contours[3] = 0.1; - contours[4] = 0.4; - contours[5] = 0.8; - - HistStreamFn->SetContour(6, contours); - - // Draw contours as filled regions, and Save points - HistStreamFn->Draw("CONT Z LIST"); - c->Update(); // Needed to force the plotting and retrieve the contours in TGraphs - - // Get Contours - TObjArray *conts = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours"); - - if (!conts){ - printf("*** No Contours Were Extracted!\n"); - return nullptr; - } - - TList* contLevel = nullptr; - TGraph* curv = nullptr; - TGraph* gc = nullptr; - - Int_t nGraphs = 0; - Int_t TotalConts = conts->GetSize(); - - printf("TotalConts = %d\n", TotalConts); - - for(i = 0; i < TotalConts; i++){ - contLevel = (TList*)conts->At(i); - printf("Contour %d has %d Graphs\n", i, contLevel->GetSize()); - nGraphs += contLevel->GetSize(); - } - - nGraphs = 0; - - TCanvas* c1 = new TCanvas("c1","Contour List",610,0,600,600); - c1->SetTopMargin(0.15); - TH2F *hr = new TH2F("hr", - "#splitline{Negative contours are returned first (highest to lowest). Positive contours are returned from}{lowest to highest. On this plot Negative contours are drawn in red and positive contours in blue.}", - 2, -2, 2, 2, 0, 6.5); - - hr->Draw(); - Double_t xval0, yval0, zval0; - TLatex l; - l.SetTextSize(0.03); - char val[20]; - - for(i = 0; i < TotalConts; i++){ - contLevel = (TList*)conts->At(i); - if (i<3) zval0 = contours[2-i]; - else zval0 = contours[i]; - printf("Z-Level Passed in as: Z = %f\n", zval0); - - // Get first graph from list on curves on this level - curv = (TGraph*)contLevel->First(); - for(j = 0; j < contLevel->GetSize(); j++){ - curv->GetPoint(0, xval0, yval0); - if (zval0<0) curv->SetLineColor(kRed); - if (zval0>0) curv->SetLineColor(kBlue); - nGraphs ++; - printf("\tGraph: %d -- %d Elements\n", nGraphs,curv->GetN()); - - // Draw clones of the graphs to avoid deletions in case the 1st - // pad is redrawn. - gc = (TGraph*)curv->Clone(); - gc->Draw("C"); - - sprintf(val,"%g",zval0); - l.DrawLatex(xval0,yval0,val); - curv = (TGraph*)contLevel->After(curv); // Get Next graph - } - } - c1->Update(); - printf("\n\n\tExtracted %d Contours and %d Graphs \n", TotalConts, nGraphs ); - gStyle->SetTitleW(0.); - gStyle->SetTitleH(0.); - return c1; -} - - -Double_t SawTooth(Double_t x, Double_t WaveLen){ - -// This function is specific to a sawtooth function with period -// WaveLen, symmetric about x = 0, and with amplitude = 1. Each segment -// is 1/4 of the wavelength. -// -// | -// /\ | -// / \ | -// / \ | -// / \ -// /--------\--------/------------ -// |\ / -// | \ / -// | \ / -// | \/ -// - - Double_t y; - if ( (x < -WaveLen/2) || (x > WaveLen/2)) y = -99999999; // Error X out of bounds - if (x <= -WaveLen/4) { - y = x + 2.0; - } else if ((x > -WaveLen/4) && (x <= WaveLen/4)) { - y = -x ; - } else if (( x > WaveLen/4) && (x <= WaveLen/2)) { - y = x - 2.0; - } - return y; -} diff --git a/tutorials/hist/Fibonacci.C b/tutorials/hist/Fibonacci.C deleted file mode 100644 index 6ad4c31a8a970..0000000000000 --- a/tutorials/hist/Fibonacci.C +++ /dev/null @@ -1,157 +0,0 @@ - -/// \file -/// \ingroup tutorial_hist -/// \notebook -js -/// A TH2Poly build with Fibonacci numbers. -/// -/// In mathematics, the Fibonacci sequence is a suite of integer in which -/// every number is the sum of the two preceding one. -/// -/// The first 10 Fibonacci numbers are: -/// -/// 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ... -/// -/// This tutorial computes Fibonacci numbers and uses them to build a TH2Poly -/// producing the "Fibonacci spiral" created by drawing circular arcs connecting -/// the opposite corners of squares in the Fibonacci tiling. -/// -/// \macro_image -/// \macro_code -/// -/// \author Olivier Couet - -void Arc(int n, double a, double r, double *px, double *py); -void AddFibonacciBin(TH2Poly *h2pf, double N); - -void Fibonacci(int N=7) { - // N = number of Fibonacci numbers > 1 - - TCanvas *C = new TCanvas("C", "C", 800, 600); - C->SetFrameLineWidth(0); - - TH2Poly *h2pf = new TH2Poly(); // TH2Poly containing Fibonacci bins. - h2pf->SetTitle(Form("The first %d Fibonacci numbers",N)); - h2pf->SetMarkerColor(kRed-2); - h2pf->SetStats(0); - - double f0 = 0.; - double f1 = 1.; - double ft; - - AddFibonacciBin(h2pf, f1); - - for (int i=0; i<=N; i++) { - ft = f1; - f1 = f0 + f1; - f0 = ft; - AddFibonacciBin(h2pf, f1); - } - - h2pf->Draw("A COL L TEXT"); -} - -void Arc(int n, double a, double r, double *px, double *py) { - // Add points on a arc of circle from point 2 to n-2 - - double da = TMath::Pi()/(2*(n-2)); // Angle delta - - for (int i = 2; i<=n-2; i++) { - a = a+da; - px[i] = r*TMath::Cos(a) + px[0]; - py[i] = r*TMath::Sin(a) + py[0]; - } -} - -void AddFibonacciBin(TH2Poly *h2pf, double N) { - // Add to h2pf the bin corresponding to the Fibonacci number N - - double X1 = 0.; // - double Y1 = 0.; // Current Fibonacci - double X2 = 1.; // square position. - double Y2 = 1.; // - - static int MoveId = 0; - - static double T = 1.; //Current Top limit of the bins - static double B = 0.; //Current Bottom limit of the bins - static double L = 0.; //Current Left limit of the bins - static double R = 1.; //Current Right limit of the bins - - const int NP = 50; // Number of point to build the current bin - double px[NP]; // Bin's X positions - double py[NP]; // Bin's Y positions - - double pi2 = TMath::Pi()/2; - - switch (MoveId) { - case 1: - R = R+N; - X2 = R; - Y2 = T; - X1 = X2-N; - Y1 = Y2-N; - px[0] = X1; - py[0] = Y2; - px[1] = X1; - py[1] = Y1; - px[NP-1] = X2; - py[NP-1] = Y2; - Arc(NP,3*pi2,(double)N,px,py); - break; - - case 2: - T = T+N; - X2 = R; - Y2 = T; - X1 = X2-N; - Y1 = Y2-N; - px[0] = X1; - py[0] = Y1; - px[1] = X2; - py[1] = Y1; - px[NP-1] = X1; - py[NP-1] = Y2; - Arc(NP,0.,(double)N,px,py); - break; - - case 3: - L = L-N; - X1 = L; - Y1 = B; - X2 = X1+N; - Y2 = Y1+N; - px[0] = X2; - py[0] = Y1; - px[1] = X2; - py[1] = Y2; - px[NP-1] = X1; - py[NP-1] = Y1; - Arc(NP,pi2,(double)N,px,py); - break; - - case 4: - B = B-N; - X1 = L; - Y1 = B; - X2 = X1+N; - Y2 = Y1+N; - px[0] = X2; - py[0] = Y2; - px[1] = X1; - py[1] = Y2; - px[NP-1] = X2; - py[NP-1] = Y1; - Arc(NP,2*pi2,(double)N,px,py); - break; - } - - if (MoveId==0) h2pf->AddBin(X1,Y1,X2,Y2); // First bin is a square - else h2pf->AddBin(NP, px ,py); // Other bins have an arc of circle - - h2pf->Fill((X1+X2)/2.5, (Y1+Y2)/2.5, N); - - MoveId++; - if (MoveId==5) MoveId=1; -} - - diff --git a/tutorials/hist/FirstContour.C b/tutorials/hist/FirstContour.C deleted file mode 100644 index 4368f21644127..0000000000000 --- a/tutorials/hist/FirstContour.C +++ /dev/null @@ -1,63 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Make a contour plot and get the first contour in a TPolyMarker. -/// This macro generates a color contour plot by selecting entries -/// from an ntuple file. -/// The TGraph object corresponding to the first contour line is -/// accessed and displayed into a separate canvas. -/// -/// \macro_code -/// -/// \author Rene Brun - -void FirstContour() -{ - TString dir = gROOT->GetTutorialDir(); - dir.Append("/hsimple.C"); - dir.ReplaceAll("/./","/"); - if (!gInterpreter->IsLoaded(dir.Data())) gInterpreter->LoadMacro(dir.Data()); - TFile *file = (TFile*)gROOT->ProcessLineFast("hsimple(1)"); - if (!file) return; - TTree *ntuple = (TTree*)file->Get("ntuple"); - - TCanvas *c1 = new TCanvas("c1","Contours",10,10,800,600); - ntuple->Draw("py:px","px*px+py*py < 20", "contz,list"); - - //we must call Update to force the canvas to be painted. When - //painting the contour plot, the list of contours is generated - //and a reference to it added to the Root list of special objects - c1->Update(); - - TCanvas *c2 = new TCanvas("c2","First contour",100,100,800,600); - - - TObjArray *contours = - (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours"); - if (!contours) return; - TList *lcontour1 = (TList*)contours->At(0); - if (!lcontour1) return; - TGraph *gc1 = (TGraph*)lcontour1->First(); - if (!gc1) return; - if (gc1->GetN() < 10) return; - gc1->SetMarkerStyle(21); - gc1->Draw("alp"); - - //We make a TCutG object with the array obtained from this graph - TCutG *cutg = new TCutG("cutg",gc1->GetN(),gc1->GetX(),gc1->GetY()); - - //We create a polymarker object with npmax points. - const Int_t npmax = 50000; - TPolyMarker *pm = new TPolyMarker(npmax); - Int_t np = 0; - while(1) { - Double_t x = -4 +8*gRandom->Rndm(); - Double_t y = -4 +8*gRandom->Rndm(); - if (cutg->IsInside(x,y)) { - pm->SetPoint(np,x,y); - np++; - if (np == npmax) break; - } - } - pm->Draw(); -} diff --git a/tutorials/hist/candledecay.C b/tutorials/hist/candledecay.C deleted file mode 100644 index 5fc2270c8e3fd..0000000000000 --- a/tutorials/hist/candledecay.C +++ /dev/null @@ -1,38 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Candle Decay, illustrate a time development of a certain value. -/// -/// \macro_image -/// \macro_code -/// -/// \author Georg Troska - -void candledecay() -{ - auto c1 = new TCanvas("c1","Candle Decay",800,600); - c1->Divide(2,1); - auto rng = new TRandom(); - auto h1 = new TH2I("h1","Decay",1000,0,1000,20,0,20); - - float myRand; - for (int i = 0; i < 19; i++) { - for (int j = 0; j < 1000000; j++) { - myRand = rng->Gaus(350+i*8,20+2*i); - h1->Fill(myRand,i); - } - } - h1->SetBarWidth(3); - h1->SetFillStyle(0); - h1->SetFillColor(kGray); - h1->SetLineColor(kBlue); - h1->GetYaxis()->SetTitle("time"); - h1->GetXaxis()->SetTitle("probability density"); - - c1->cd(1); - h1->Draw("violiny(112000000)"); - c1->cd(2); - auto h2 = (TH2I*)h1->Clone("h2"); - h2->SetBarWidth(0.8); - h2->DrawCopy("candley2"); -} diff --git a/tutorials/hist/candleplotoption.C b/tutorials/hist/candleplotoption.C deleted file mode 100644 index ac1312a0969c1..0000000000000 --- a/tutorials/hist/candleplotoption.C +++ /dev/null @@ -1,44 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Example showing how to combine the various candle plot options. -/// -/// \macro_image -/// \macro_code -/// -/// \author Georg Troska - -void candleplotoption() -{ - TCanvas *c1 = new TCanvas("c1","Candle Presets",800,600); - c1->Divide(3,2); - - TRandom *rng = new TRandom(); - TH2I *h1 = new TH2I("h1","Sin",18,0,360,300,-1.5,1.5); - h1->GetXaxis()->SetTitle("Deg"); - float myRand; - for (int i = 0; i < 360; i+=10) { - for (int j = 0; j < 100; j++) { - myRand = rng->Gaus(sin(i*3.14/180),0.2); - h1->Fill(i,myRand); - } - } - for (int i = 1; i < 7; i++) { - c1->cd(i); - char str[16]; - sprintf(str,"candlex%d",i); - TH2I * myhist = (TH2I*)h1->DrawCopy(str); - myhist->SetTitle(str); - } - - TCanvas *c2 = new TCanvas("c2","Candle Individual",800,600); - c2->Divide(4,4); - char myopt[16][8] = {"0","1","11","21","31","30","111","311","301","1111","2321","12111","112111","212111","312111"}; - for (int i = 0; i < 15; i++) { - c2->cd(i+1); - char str[16]; - sprintf(str, "candlex(%s)",myopt[i]); - TH2I * myhist = (TH2I*)h1->DrawCopy(str); - myhist->SetTitle(str); - } -} diff --git a/tutorials/hist/candleplotstack.C b/tutorials/hist/candleplotstack.C deleted file mode 100644 index 1b75b3d6c166e..0000000000000 --- a/tutorials/hist/candleplotstack.C +++ /dev/null @@ -1,50 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Example showing how a THStack with candle plot option. -/// -/// \macro_image -/// \macro_code -/// -/// \authors Georg Troska, Olivier Couet - -void candleplotstack() -{ - gStyle->SetTimeOffset(0); - auto rng = new TRandom(); - auto dateBegin = new TDatime(2010,1,1,0,0,0); - auto dateEnd = new TDatime(2011,1,1,0,0,0); - int bins = 1000; - auto h1 = new TH2I("h1","Machine A",6,dateBegin->Convert(),dateEnd->Convert(),bins,0,1000); - auto h2 = new TH2I("h2","Machine B",6,dateBegin->Convert(),dateEnd->Convert(),bins,0,1000); - auto hsum = new TH2I("h4","Sum",6,dateBegin->Convert(),dateEnd->Convert(),bins,0,1000); - - float Rand; - for (int i = dateBegin->Convert(); i < dateEnd->Convert(); i+=86400*30) { - for (int j = 0; j < 1000; j++) { - Rand = rng->Gaus(500+sin(i/10000000.)*100,50); h1->Fill(i,Rand); hsum->Fill(i,Rand); - Rand = rng->Gaus(500+sin(i/12000000.)*100,50); h2->Fill(i,Rand); hsum->Fill(i,Rand); - } - } - - h2->SetLineColor(kRed); - hsum->SetFillColor(kGreen); - TCanvas *c1 = new TCanvas(); - - auto hs = new THStack("hs","Machine A+B"); - hs->Add(h1); - hs->Add(h2,"candle2"); - hs->Add(hsum, "violin1"); - hs->Draw("candle3"); - hs->GetXaxis()->SetNdivisions(410); - - gPad->SetGrid(1,0); - - hs->GetXaxis()->SetTimeDisplay(1); - hs->GetXaxis()->SetTimeFormat("%d/%m/%y"); - hs->GetXaxis()->SetNdivisions(-6); - hs->GetXaxis()->SetTitle("Date [day/month/year]"); - c1->Modified(); - - gPad->BuildLegend(0.75,0.75,0.95,0.95,""); -} diff --git a/tutorials/hist/candleplotwhiskers.C b/tutorials/hist/candleplotwhiskers.C deleted file mode 100644 index 8e709602316b2..0000000000000 --- a/tutorials/hist/candleplotwhiskers.C +++ /dev/null @@ -1,78 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Example of candle plot showing the whiskers definition. -/// -/// \macro_image -/// \macro_output -/// \macro_code -/// -/// \author Georg Troska - -void candleplotwhiskers() { - auto c1 = new TCanvas("c1","Candle Presets",700,800); - c1->Divide(1,2); - - auto rng = new TRandom(); - auto h1 = new TH2I("h1","Gaus",100,-5,5,1,0,1); - auto h2 = new TH1I("h2","Gaus",100,-5,5); - - h1->GetXaxis()->SetTitle("Standard deviation #sigma"); - h2->GetXaxis()->SetTitle("Standard deviation #sigma"); - h2->GetYaxis()->SetTitle("dN/d#sigma"); - - float myRand; - for (int i = 0; i < 100000; i++) { - myRand = rng->Gaus(0,1); - h1->Fill(myRand,0); - h2->Fill(myRand); - } - - Double_t *q = new Double_t[3]; - Double_t *p = new Double_t[3]; - q[0] = 0.; q[1] = 0.; q[2] = 0.; - p[0] = 0.25; p[1] = 0.5; p[2] = 0.75; - - h2->GetQuantiles(3,q,p); - cout << "Q1 (-25%): " << q[0] << " Median: " << q[1] << " Q3 (+25%): " << q[2] << endl; - double iqr = q[2]-q[0]; - auto mygaus_1_middle = new TF1("mygaus_1_middle","gaus",q[0],q[2]); - auto mygaus_1_left = new TF1("mygaus_1_left","gaus",q[0]-1.5*iqr,q[0]); - mygaus_1_left->SetLineColor(kGreen); - auto mygaus_1_right = new TF1("mygaus_1_right","gaus",q[2],q[2]+1.5*iqr); - mygaus_1_right->SetLineColor(kGreen); - c1->cd(1); - h1->SetLineWidth(3); - h1->SetFillStyle(0); - h1->Draw("candley2 scat"); - - c1->cd(2); - h2->Draw(""); - h2->Fit("mygaus_1_left","R"); - mygaus_1_left->Draw("same"); - auto l3 = new TLine(q[0]-1.5*iqr,0,q[0]-1.5*iqr,mygaus_1_left->Eval(q[0]-1.5*iqr)); - l3->SetLineColor(kGreen); l3->SetLineWidth(2); l3->Draw(""); - auto l1 = new TLine(q[0] ,0,q[0] ,mygaus_1_left->Eval(q[0])); - l1->SetLineWidth(2); l1->SetLineColor(kGreen); l1->Draw(""); - - h2->Fit("mygaus_1_right","R",""); - mygaus_1_right->Draw("same"); - auto l4 = new TLine(q[2]+1.5*iqr,0,q[2]+1.5*iqr,mygaus_1_left->Eval(q[2]+1.5*iqr)); - l4->SetLineColor(kGreen); l4->SetLineWidth(2); l4->Draw(""); - auto l5 = new TLine(q[2] ,0,q[2] ,mygaus_1_right->Eval(q[2])); - l5->SetLineWidth(2); l5->SetLineColor(kGreen); l5->Draw(""); - - h2->Fit("mygaus_1_middle","R"); - mygaus_1_middle->Draw("same"); - - //In principal one could calculate these values by h2->Integral() as well - TText t; - t.SetTextFont(42); - t.DrawText(0,mygaus_1_middle->Eval(0)/2,"50%"); - t.DrawText(-1.5,mygaus_1_middle->Eval(-1.5)/2,"24.65%"); - t.DrawText(+1,mygaus_1_middle->Eval(+1.5)/2,"24.65%"); - t.DrawText(q[0]-1.5*iqr,1000,Form("%.3f",q[0]-1.5*iqr))->SetTextAngle(90); - t.DrawText(q[2]+1.5*iqr,1000,Form("%.3f",q[2]+1.5*iqr))->SetTextAngle(90); - t.DrawText(q[0],1000,Form("%.3f",q[0]))->SetTextAngle(90); - t.DrawText(q[2],1000,Form("%.3f",q[2]))->SetTextAngle(90); -} diff --git a/tutorials/hist/draw2dopt.C b/tutorials/hist/draw2dopt.C deleted file mode 100644 index 82c22e91ba710..0000000000000 --- a/tutorials/hist/draw2dopt.C +++ /dev/null @@ -1,95 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Display the various 2-d drawing options -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -void draw2dopt() -{ - gStyle->SetOptStat(0); - gStyle->SetCanvasColor(33); - gStyle->SetFrameFillColor(18); - TF2 *f2 = new TF2("f2","xygaus + xygaus(5) + xylandau(10)",-4,4,-4,4); - Double_t params[] = {130,-1.4,1.8,1.5,1, 150,2,0.5,-2,0.5, 3600,-2,0.7,-3,0.3}; - f2->SetParameters(params); - auto h2 = new TH2F("h2","xygaus + xygaus(5) + xylandau(10)",20,-4,4,20,-4,4); - h2->SetFillColor(46); - h2->FillRandom("f2",40000); - TPaveLabel pl; - - //basic 2-d options - Float_t xMin=0.67, yMin=0.875, xMax=0.85, yMax=0.95; - Int_t cancolor = 17; - auto c2h = new TCanvas("c2h","2-d options",10,10,800,600); - c2h->Divide(2,2); - c2h->SetFillColor(cancolor); - c2h->cd(1); - h2->Draw(); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"SCAT","brNDC"); - c2h->cd(2); - h2->Draw("box"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"BOX","brNDC"); - c2h->cd(3); - h2->Draw("arr"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"ARR","brNDC"); - c2h->cd(4); - h2->Draw("colz"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"COLZ","brNDC"); - c2h->Update(); - - //text option - auto ctext = new TCanvas("ctext","text option",50,50,800,600); - gPad->SetGrid(); - ctext->SetFillColor(cancolor); - ctext->SetGrid(); - h2->Draw("text"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"TEXT","brNDC"); - ctext->Update(); - - //contour options - auto cont = new TCanvas("contours","contours",100,100,800,600); - cont->Divide(2,2); - gPad->SetGrid(); - cont->SetFillColor(cancolor); - cont->cd(1); - h2->Draw("contz"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"CONTZ","brNDC"); - cont->cd(2); - gPad->SetGrid(); - h2->Draw("cont1"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"CONT1","brNDC"); - cont->cd(3); - gPad->SetGrid(); - h2->Draw("cont2"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"CONT2","brNDC"); - cont->cd(4); - gPad->SetGrid(); - h2->Draw("cont3"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"CONT3","brNDC"); - cont->Update(); - - //lego options - auto lego = new TCanvas("lego","lego options",150,150,800,600); - lego->Divide(2,2); - lego->SetFillColor(cancolor); - lego->cd(1); - h2->Draw("lego"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"LEGO","brNDC"); - lego->cd(2); - h2->Draw("lego1"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"LEGO1","brNDC"); - lego->cd(3); - gPad->SetTheta(61); gPad->SetPhi(-82); - h2->Draw("surf1pol"); pl.DrawPaveLabel(xMin,yMin,xMax+0.05,yMax,"SURF1POL","brNDC"); - lego->cd(4); - gPad->SetTheta(21); gPad->SetPhi(-90); - h2->Draw("surf1cyl"); pl.DrawPaveLabel(xMin,yMin,xMax+0.05,yMax,"SURF1CYL","brNDC"); - lego->Update(); - - //surface options - auto surf = new TCanvas("surfopt","surface options",200,200,800,600); - surf->Divide(2,2); - surf->SetFillColor(cancolor); - surf->cd(1); - h2->Draw("surf1"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"SURF1","brNDC"); - surf->cd(2); - h2->Draw("surf2z"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"SURF2Z","brNDC"); - surf->cd(3); - h2->Draw("surf3"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"SURF3","brNDC"); - surf->cd(4); - h2->Draw("surf4"); pl.DrawPaveLabel(xMin,yMin,xMax,yMax,"SURF4","brNDC"); - surf->Update(); -} diff --git a/tutorials/hist/fillrandom.C b/tutorials/hist/fillrandom.C deleted file mode 100644 index 619979c093371..0000000000000 --- a/tutorials/hist/fillrandom.C +++ /dev/null @@ -1,63 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Fill a 1-D histogram from a parametric function. -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -void fillrandom(int plot=1) { - gBenchmark->Start("fillrandom"); - - // A function (any dimension) or a formula may reference - // an already defined formula - auto form1 = new TFormula("form1","abs(sin(x)/x)"); - auto sqroot = new TF1("sqroot","x*gaus(0) + [3]*form1",0,10); - sqroot->SetLineColor(4); - sqroot->SetLineWidth(6); - sqroot->SetParameters(10,4,1,20); - - // Create a one dimensional histogram (one float per bin) - // and fill it following the distribution in function sqroot. - auto h1f = new TH1F("h1f","Test random numbers",200,0,10); - h1f->FillRandom("sqroot",10000); - - // Open a ROOT file and save the formula, function and histogram - TFile myfile("fillrandom.root","RECREATE"); - form1->Write(); - sqroot->Write(); - h1f->Write(); - - // Produce a plot if requested - if (plot) { - TCanvas *c1 = new TCanvas("c1","The FillRandom example",200,10,700,900); - - auto pad1 = new TPad("pad1","The pad with the function",0.05,0.50,0.95,0.95); - auto pad2 = new TPad("pad2","The pad with the histogram",0.05,0.05,0.95,0.45); - pad1->Draw(); - pad2->Draw(); - pad1->cd(); - - pad1->SetGridx(); - pad1->SetGridy(); - pad1->GetFrame()->SetBorderMode(-1); - pad1->GetFrame()->SetBorderSize(5); - - sqroot->Draw(); - auto lfunction = new TPaveLabel(5,39,9.8,46,"The sqroot function"); - lfunction->Draw(); - c1->Update(); - - pad2->cd(); - pad2->GetFrame()->SetBorderMode(-1); - pad2->GetFrame()->SetBorderSize(5); - - h1f->SetFillColor(45); - h1f->Draw(); - c1->Update(); - } - - gBenchmark->Show("fillrandom"); -} diff --git a/tutorials/hist/hbars.C b/tutorials/hist/hbars.C deleted file mode 100644 index e5d0e8d949fa1..0000000000000 --- a/tutorials/hist/hbars.C +++ /dev/null @@ -1,73 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Example of bar charts with 1-d histograms. -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -TCanvas *hbars() -{ - // Try to open first the file cernstaff.root in tutorials/tree directory - TString filedir = gROOT->GetTutorialDir(); - filedir += TString("/tree/"); - TString filename = "cernstaff.root"; - bool fileNotFound = gSystem->AccessPathName(filename); // note opposite return code - - // If file is not found try to generate it using the macro tree/cernbuild.C - if (fileNotFound) { - TString macroName = filedir + "cernbuild.C"; - if (!gInterpreter->IsLoaded(macroName)) gInterpreter->LoadMacro(macroName); - gROOT->ProcessLineFast("cernbuild()"); - } - TFile * f = TFile::Open(filename); - if (!f) { - Error("hbars", "file cernstaff.root not found"); - return nullptr; - } - TTree *T = (TTree*)f->Get("T"); - if (!T) { - Error("hbars", "Tree T is not present in file %s", f->GetName()); - return nullptr; - } - T->SetFillColor(45); - TCanvas *c1 = new TCanvas("c1","histograms with bars",700,800); - c1->SetFillColor(42); - c1->Divide(1,2); - - // Horizontal bar chart - c1->cd(1); - gPad->SetGrid(); - gPad->SetLogx(); - gPad->SetFrameFillColor(33); - T->Draw("Nation","","hbar2"); - - // Vertical bar chart - c1->cd(2); - gPad->SetGrid(); - gPad->SetFrameFillColor(33); - T->Draw("Division>>hDiv","","goff"); - TH1F *hDiv = (TH1F*)gDirectory->Get("hDiv"); - hDiv->SetStats(0); - TH1F *hDivFR = (TH1F*)hDiv->Clone("hDivFR"); - T->Draw("Division>>hDivFR","Nation==\"FR\"","goff"); - hDiv->SetBarWidth(0.45); - hDiv->SetBarOffset(0.1); - hDiv->SetFillColor(49); - TH1 *h1 = hDiv->DrawCopy("bar2"); - hDivFR->SetBarWidth(0.4); - hDivFR->SetBarOffset(0.55); - hDivFR->SetFillColor(50); - TH1 *h2 = hDivFR->DrawCopy("bar2,same"); - - TLegend *legend = new TLegend(0.55,0.65,0.76,0.82); - legend->AddEntry(h1,"All nations","f"); - legend->AddEntry(h2,"French only","f"); - legend->Draw(); - - c1->cd(); - delete f; - return c1; -} diff --git a/tutorials/hist/hist000_TH1_first.C b/tutorials/hist/hist000_TH1_first.C new file mode 100644 index 0000000000000..bb3275f84e929 --- /dev/null +++ b/tutorials/hist/hist000_TH1_first.C @@ -0,0 +1,39 @@ +/// \file +/// \ingroup tutorial_hist +/// Hello World example for TH1 +/// +/// Shows how to create, fill and write a histogram to a ROOT file. +/// +/// \macro_code +/// \macro_output +/// +/// \date November 2024 +/// \author Giacomo Parolini (CERN) + +void hist000_TH1_first() +{ + // Open the file to write the histogram to + auto outFile = std::unique_ptr(TFile::Open("outfile.root", "RECREATE")); + + // Create the histogram object + // There are several constructors you can use (\see TH1). In this example we use the + // simplest one, accepting a number of bins and a range. + int nBins = 30; + double rangeMin = 0.0; + double rangeMax = 10.0; + TH1D histogram("histogram", "My first ROOT histogram", nBins, rangeMin, rangeMax); + + // Fill the histogram. In this simple example we use a fake set of data. + // The 'D' in TH1D stands for 'double', so we fill the histogram with doubles. + // In general you should prefer TH1D over TH1F unless you have a very specific reason + // to do otherwise. + const std::array values{1, 2, 3, 3, 3, 4, 3, 2, 1, 0}; + for (double val : values) { + histogram.Fill(val); + } + + // Write the histogram to `outFile`. + outFile->WriteObject(&histogram, histogram.GetName()); + + // When the TFile goes out of scope it will close itself and write its contents to disk. +} diff --git a/tutorials/hist/hist001_TH1_fillrandom.C b/tutorials/hist/hist001_TH1_fillrandom.C new file mode 100644 index 0000000000000..b5e249becf9cc --- /dev/null +++ b/tutorials/hist/hist001_TH1_fillrandom.C @@ -0,0 +1,27 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Fill a 1D histogram with random values using predefined functions +/// +/// \macro_image +/// \macro_code +/// +/// \date November 2024 +/// \author Giacomo Parolini + +void hist001_TH1_fillrandom() +{ + // Create a one dimensional histogram and fill it with a gaussian distribution + int nBins = 200; + double rangeMin = 0.0; + double rangeMax = 10.0; + TH1D h1d("h1d", "Test random numbers", nBins, rangeMin, rangeMax); + + // "gaus" is a predefined ROOT function. Here we are filling the histogram with + // 10000 values sampled from that distribution. + h1d.FillRandom("gaus", 10000); + + // Open a ROOT file and save the histogram + auto myfile = std::unique_ptr(TFile::Open("fillrandom.root", "RECREATE")); + myfile->WriteObject(&h1d, h1d.GetName()); +} diff --git a/tutorials/hist/hist002_TH1_fillrandom_userfunc.C b/tutorials/hist/hist002_TH1_fillrandom_userfunc.C new file mode 100644 index 0000000000000..12fa25043390c --- /dev/null +++ b/tutorials/hist/hist002_TH1_fillrandom_userfunc.C @@ -0,0 +1,43 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Fill a 1D histogram from a user-defined parametric function. +/// +/// \macro_image +/// \macro_code +/// +/// \date November 2024 +/// \author Rene Brun, Giacomo Parolini + +void hist002_TH1_fillrandom_userfunc() +{ + // Create a user-defined formula. + // A function (any dimension) or a formula may reference an already defined formula + TFormula form1("form1", "abs(sin(x)/x)"); + + // Create a 1D function using the formula defined above and the predefined "gaus" formula. + double rangeMin = 0.0; + double rangeMax = 10.0; + TF1 sqroot("sqroot", "x*gaus(0) + [3]*form1", rangeMin, rangeMax); + sqroot.SetLineColor(4); + sqroot.SetLineWidth(6); + // Set parameters to the functions "gaus" and "form1". + double gausScale = 10.0; // [0] + double gausMean = 4.0; // [1] + double gausVar = 1.0; // [2] + double form1Scale = 20.0; // [3] + sqroot.SetParameters(gausScale, gausMean, gausVar, form1Scale); + + // Create a one dimensional histogram and fill it following the distribution in function sqroot. + int nBins = 200; + TH1D h1d("h1d", "Test random numbers", nBins, rangeMin, rangeMax); + + // Use our user-defined function to fill the histogram with random values sampled from it. + h1d.FillRandom("sqroot", 10000); + + // Open a ROOT file and save the formula, function and histogram + auto myFile = std::unique_ptr(TFile::Open("fillrandom.root", "RECREATE")); + myFile->WriteObject(&form1, form1.GetName()); + myFile->WriteObject(&sqroot, sqroot.GetName()); + myFile->WriteObject(&h1d, h1d.GetName()); +} diff --git a/tutorials/hist/hist003_TH1_draw.C b/tutorials/hist/hist003_TH1_draw.C new file mode 100644 index 0000000000000..4d24b87359203 --- /dev/null +++ b/tutorials/hist/hist003_TH1_draw.C @@ -0,0 +1,70 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Draw a 1D histogram to a canvas. +/// +/// \note When using graphics inside a ROOT macro the objects must be created with `new`. +/// +/// \macro_image +/// \macro_code +/// +/// \date November 2024 +/// \author Rene Brun, Giacomo Parolini + +void hist003_TH1_draw() +{ + // Create and fill the histogram. + // See hist002_TH1_fillrandom_userfunc.C for more information about this section. + auto *form1 = new TFormula("form1", "abs(sin(x)/x)"); + double rangeMin = 0.0; + double rangeMax = 10.0; + auto *sqroot = new TF1("sqroot", "x*gaus(0) + [3]*form1", rangeMin, rangeMax); + sqroot->SetLineColor(4); + sqroot->SetLineWidth(6); + sqroot->SetParameters(10.0, 4.0, 1.0, 20.0); + + int nBins = 200; + auto *h1d = new TH1D("h1d", "Test random numbers", nBins, rangeMin, rangeMax); + + h1d->FillRandom("sqroot", 10000); + + // Create a canvas and draw the histogram + int topX = 200; + int topY = 10; + int width = 700; + int height = 900; + auto *c1 = new TCanvas("c1", "The FillRandom example", topX, topY, width, height); + + // Split the canvas into two sections to plot both the function and the histogram + // The TPad's constructor accepts the relative coordinates (0 to 1) of the pad's boundaries + auto *pad1 = new TPad("pad1", "The pad with the function", 0.05, 0.50, 0.95, 0.95); + auto *pad2 = new TPad("pad2", "The pad with the histogram", 0.05, 0.05, 0.95, 0.45); + + // Draw the two pads + pad1->Draw(); + pad2->Draw(); + + // Select pad1 to draw the next objects into + pad1->cd(); + pad1->SetGridx(); + pad1->SetGridy(); + pad1->GetFrame()->SetBorderMode(-1); + pad1->GetFrame()->SetBorderSize(5); + + // Draw the function in pad1 + sqroot->Draw(); + // Add a label to the function. + // TPaveLabel's constructor accepts the pixel coordinates and the label string. + auto *lfunction = new TPaveLabel(5, 39, 9.8, 46, "The sqroot function"); + lfunction->Draw(); + c1->Update(); + + // Select pad2 to draw the next objects into + pad2->cd(); + pad2->GetFrame()->SetBorderMode(-1); + pad2->GetFrame()->SetBorderSize(5); + + h1d->SetFillColor(45); + h1d->Draw(); + c1->Update(); +} diff --git a/tutorials/hist/hist004_TH1_labels.C b/tutorials/hist/hist004_TH1_labels.C new file mode 100644 index 0000000000000..04975827032c1 --- /dev/null +++ b/tutorials/hist/hist004_TH1_labels.C @@ -0,0 +1,56 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// 1D histograms with alphanumeric labels. +/// +/// A TH1 can have named bins that are filled with the method overload TH1::Fill(const char*, double) +/// +/// \macro_image +/// \macro_code +/// +/// \date November 2024 +/// \author Rene Brun + +void hist004_TH1_labels() +{ + // Create the histogram + const std::array people{"Jean", "Pierre", "Marie", "Odile", "Sebastien", "Fons", "Rene", + "Nicolas", "Xavier", "Greg", "Bjarne", "Anton", "Otto", "Eddy", + "Peter", "Pasha", "Philippe", "Suzanne", "Jeff", "Valery"}; + // Start with an arbitrary amount of bins and an arbitrary range, but this will be extended thanks to SetCanExtend(). + int nBins = 3; + double rangeMin = 0.0; + double rangeMax = 3.0; + auto *h = new TH1D("h", "test", nBins, rangeMin, rangeMax); + // Disable the default stats box when drawing this histogram + h->SetStats(0); + h->SetFillColor(38); + // Allow both axes to extend past the initial range we gave in the constructor + h->SetCanExtend(TH1::kAllAxes); + // Fill the Y axis with arbitrary values, a random amount per bin + TRandom3 rng; + for (int i = 0; i < 5000; i++) { + int r = rng.Rndm() * 20; + // `Fill()` called with a const char* as the first argument will add a value to the bin with that name, + // creating it if it doesn't exist yet. + h->Fill(people[r], 1); + } + // Remove empty bins + h->LabelsDeflate(); + + auto *c1 = new TCanvas("c1", "demo bin labels", 10, 10, 900, 500); + // Enable the grid in the plot + c1->SetGrid(); + c1->SetTopMargin(0.15); + + // Draw the histogram + h->Draw(); + + // Draw a boxed text + // "brNDC" = coordinates draw bottom-right shadow and pass the coordinates in normalized device coordinates + auto *pt = new TPaveText(0.7, 0.85, 0.98, 0.98, "brNDC"); + pt->SetFillColor(18); + pt->SetTextAlign(12); + pt->AddText("Use the axis Context Menu LabelsOption"); + pt->Draw(); +} diff --git a/tutorials/hist/hist005_TH1_palettecolor.C b/tutorials/hist/hist005_TH1_palettecolor.C new file mode 100644 index 0000000000000..dd585cca8d3dd --- /dev/null +++ b/tutorials/hist/hist005_TH1_palettecolor.C @@ -0,0 +1,69 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Palette coloring for TH1 +/// +/// Palette coloring for histogram is activated thanks to the options `PFC` +/// (Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color). +/// When one of these options is given to `TH1::Draw` the histogram gets its color +/// from the current color palette defined by `gStyle->SetPalette(...)`. The color +/// is determined according to the number of objects having palette coloring in +/// the current pad. +/// +/// In this example five histograms are displayed with palette coloring for lines and +/// and marker. The histograms are drawn with markers and error bars and one can see +/// the color of each histogram is picked inside the default palette `kBird`. +/// +/// \macro_image +/// \macro_code +/// +/// \date November 2024 +/// \author Olivier Couet + +void hist005_TH1_palettecolor() +{ + auto *canvas = new TCanvas(); + + // Disable drawing the title of the canvas + gStyle->SetOptTitle(kFALSE); + // Disable drawing the stats box + gStyle->SetOptStat(0); + + auto *h1 = new TH1D("h1", "Histogram drawn with full circles", 100, -4, 4); + auto *h2 = new TH1D("h2", "Histogram drawn with full squares", 100, -4, 4); + auto *h3 = new TH1D("h3", "Histogram drawn with full triangles up", 100, -4, 4); + auto *h4 = new TH1D("h4", "Histogram drawn with full triangles down", 100, -4, 4); + auto *h5 = new TH1D("h5", "Histogram drawn with empty circles", 100, -4, 4); + + // Use Mersenne-Twister random number generator + TRandom3 rng; + for (int i = 0; i < 25000; i++) { + // "Rannor" fills the two parameters we pass with RANdom numbers picked from a NORmal distribution. + // In this case we ignore the second value. + double val, ignored; + rng.Rannor(val, ignored); + // Fill() called with 2 arguments adds the given value (first arg) with the specified weight (second arg) + h1->Fill(val, 10.); + h2->Fill(val, 8.); + h3->Fill(val, 6.); + h4->Fill(val, 4.); + h5->Fill(val, 2.); + } + + // Set different styles for the various histograms + h1->SetMarkerStyle(kFullCircle); + h2->SetMarkerStyle(kFullSquare); + h3->SetMarkerStyle(kFullTriangleUp); + h4->SetMarkerStyle(kFullTriangleDown); + h5->SetMarkerStyle(kOpenCircle); + + // Draw all histograms overlapped in the same canvas (thanks to the "SAME" option) + h1->Draw("PLC PMC"); + h2->Draw("SAME PLC PMC"); + h3->Draw("SAME PLC PMC"); + h4->Draw("SAME PLC PMC"); + h5->Draw("SAME PLC PMC"); + + // Build a legend from the objects drawn in the pad, using their description that we specified when constructing them + gPad->BuildLegend(); +} diff --git a/tutorials/hist/hist006_TH1_bar_charts.C b/tutorials/hist/hist006_TH1_bar_charts.C new file mode 100644 index 0000000000000..a852550f2eddc --- /dev/null +++ b/tutorials/hist/hist006_TH1_bar_charts.C @@ -0,0 +1,91 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Draw 1D histograms as bar charts +/// +/// \macro_image +/// \macro_code +/// +/// \date November 2024 +/// \author Rene Brun + +void hist006_TH1_bar_charts() +{ + // Try to open first the file cernstaff.root in tutorials/tree directory + TString filedir = gROOT->GetTutorialDir(); + filedir += TString("/tree/"); + TString filename = "cernstaff.root"; + // Note that `AccessPathName` returns 0 (false) on success! + bool fileNotFound = gSystem->AccessPathName(filename); + + // If the file is not found try to generate it using the macro tree/cernbuild.C + if (fileNotFound) { + TString macroName = filedir + "cernbuild.C"; + if (!gInterpreter->IsLoaded(macroName)) gInterpreter->LoadMacro(macroName); + gROOT->ProcessLineFast("cernbuild()"); + } + + auto file = std::unique_ptr(TFile::Open(filename, "READ")); + if (!file) { + Error("hbars", "file cernstaff.root not found"); + return; + } + + // Retrieve the TTree named "T" contained in the file + auto tree = file->Get("T"); + if (!tree) { + Error("hbars", "Tree T is not present in file %s", file->GetName()); + return; + } + tree->SetFillColor(45); + + // Create the canvas to draw on + TCanvas *c1 = new TCanvas("c1","histograms with bars", 700, 800); + c1->SetFillColor(42); + // Divide it vertically in 2 sections + int ndivsX = 1; + int ndivsY = 2; + c1->Divide(ndivsX, ndivsY); + + // Horizontal bar chart + auto *curPad = c1->cd(1); // select top section. Section 1 is the first sub-section. + curPad->SetGrid(); + curPad->SetLogx(); + curPad->SetFrameFillColor(33); + // Use the "hbar2" option to draw the tree as a horizontal bar chart + tree->Draw("Nation","","hbar2"); + + // Vertical bar chart + curPad = c1->cd(2); + curPad->SetGrid(); + curPad->SetFrameFillColor(33); + // This line makes the TTree draw its "Division" branch to a new histogram called "hDiv". + // We use "goff" because we don't want to really draw it to screen but we are only interested + // in generating the histogram from it (which we'll display ourselves later). + tree->Draw("Division>>hDiv","","goff"); + // Retrieve the generated histogram + TH1F *hDiv = file->Get("hDiv"); + hDiv->SetStats(0); + // Clone the histogram into a new one called "hDivFR". + TH1F *hDivFR = static_cast(hDiv->Clone("hDivFR")); + // Overwrite the contents of the newly-cloned histogram to only keep the entries matching our + // selection (second argument of TTree::Draw()). + tree->Draw("Division>>hDivFR","Nation==\"FR\"","goff"); + + // Now draw both histograms side-by-side ("same" option) as vertical bar charts ("bar2" option) + hDiv->SetBarWidth(0.45); + hDiv->SetBarOffset(0.1); + hDiv->SetFillColor(49); + TH1 *h1 = hDiv->DrawCopy("bar2"); + hDivFR->SetBarWidth(0.4); + hDivFR->SetBarOffset(0.55); + hDivFR->SetFillColor(50); + TH1 *h2 = hDivFR->DrawCopy("bar2,same"); + + TLegend *legend = new TLegend(0.55,0.65,0.76,0.82); + legend->AddEntry(h1,"All nations","f"); + legend->AddEntry(h2,"French only","f"); + legend->Draw(); + + c1->cd(); +} diff --git a/tutorials/hist/hist007_TH1_liveupdate.C b/tutorials/hist/hist007_TH1_liveupdate.C new file mode 100644 index 0000000000000..d38bcaf217c6a --- /dev/null +++ b/tutorials/hist/hist007_TH1_liveupdate.C @@ -0,0 +1,64 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook -js +/// Histograms filled and drawn in a loop. +/// Simple example illustrating how to use the C++ interpreter +/// to fill histograms in a loop and show the graphics results +/// +/// \macro_image +/// \macro_code +/// +/// \date November 2024 +/// \author Rene Brun + +void hist007_TH1_liveupdate() +{ + TCanvas *c1 = new TCanvas("c1", "Live update of histograms", 200, 10, 600, 400); + c1->SetGrid(); + + // Create some histograms. + auto *total = new TH1D("total", "This is the total distribution", 100, -4, 4); + auto *main = new TH1D("main", "Main contributor", 100, -4, 4); + auto *s1 = new TH1D("s1", "This is the first signal", 100, -4, 4); + auto *s2 = new TH1D("s2", "This is the second signal", 100, -4, 4); + total->Sumw2(); // store the sum of squares of weights + // set some style properties + total->SetMarkerStyle(21); // shape of the markers (\see EMarkerStyle) + total->SetMarkerSize(0.7); + main->SetFillColor(16); + s1->SetFillColor(42); + s2->SetFillColor(46); + TSlider *slider = nullptr; + + // Fill histograms randomly + TRandom3 rng; + const int kUPDATE = 500; + for (int i = 0; i < 10000; i++) { + float xmain = rng.Gaus(-1, 1.5); + float xs1 = rng.Gaus(-0.5, 0.5); + float xs2 = rng.Landau(1, 0.15); + main->Fill(xmain); + s1->Fill(xs1, 0.3); + s2->Fill(xs2, 0.2); + total->Fill(xmain); + total->Fill(xs1, 0.3); + total->Fill(xs2, 0.2); + if (i && (i % kUPDATE) == 0) { + if (i == kUPDATE) { + total->Draw("e1p"); + main->Draw("same"); + s1->Draw("same"); + s2->Draw("same"); + c1->Update(); + slider = new TSlider("slider", "test", 4.2, 0, 4.6, total->GetMaximum(), 38); + slider->SetFillColor(46); + } + if (slider) + slider->SetRange(0., 1. * i / 10000.); + c1->Modified(); + c1->Update(); + } + } + slider->SetRange(0., 1.); + c1->Modified(); +} diff --git a/tutorials/hist/ZoomHistogram.C b/tutorials/hist/hist008_TH1_zoom.C similarity index 54% rename from tutorials/hist/ZoomHistogram.C rename to tutorials/hist/hist008_TH1_zoom.C index e0da1203dac65..e0746c940dac2 100644 --- a/tutorials/hist/ZoomHistogram.C +++ b/tutorials/hist/hist008_TH1_zoom.C @@ -11,23 +11,32 @@ /// \macro_image /// \macro_code /// +/// \date November 2024 /// \author Advait Dhingra -void ZoomHistogram() +void hist008_TH1_zoom() { + // Create and fill a histogram TH1F *orig = new TH1F("Normal Histogram", "Normal Histogram", 100, 0, 100); - for (int i = 0; i < 100; ++i) { - Double_t x = gRandom->Gaus(50, 10); - orig->Fill(x); + TRandom3 rng; + for (int i = 0; i < 1000; ++i) { + double x = rng.Gaus(50, 10); + orig->Fill(x); } - TH1F *zoom = (TH1F *)orig->Clone("zoom"); + // Clone the histogram into one called "zoom" + TH1F *zoom = static_cast(orig->Clone("zoom")); zoom->SetTitle("Zoomed-in Histogram"); + // "Zoom" in the histogram by setting a new range to the X axis zoom->GetXaxis()->SetRangeUser(50, 100); + // Draw both histograms to a canvas TCanvas *c1 = new TCanvas("c1", "Histogram", 1500, 700); - c1->Divide(2, 1); + // split the canvas horizontally in 2 + int nsubdivX = 2; + int nsubdivY = 1; + c1->Divide(nsubdivX, nsubdivY); c1->cd(1); orig->Draw(); diff --git a/tutorials/hist/NormalizeHistogram.C b/tutorials/hist/hist009_TH1_normalize.C similarity index 72% rename from tutorials/hist/NormalizeHistogram.C rename to tutorials/hist/hist009_TH1_normalize.C index 65c211a22a13d..1c572bc5ca677 100644 --- a/tutorials/hist/NormalizeHistogram.C +++ b/tutorials/hist/hist009_TH1_normalize.C @@ -10,29 +10,24 @@ /// \macro_image /// \macro_code /// +/// \date November 2024 /// \author Advait Dhingra -#include "TH2F.h" -#include "TRandom.h" -#include "TCanvas.h" - -void NormalizeHistogram() +void hist009_TH1_normalize() { - - std::array binsx{0, 5, 10, 20, 50, 100}; - TH1F *orig = new TH1F("orig", "Original histogram before normalization", binsx.size() - 1, &binsx[0]); + const std::array binsx{0, 5, 10, 20, 50, 100}; + TH1D *orig = new TH1D("orig", "Original histogram before normalization", binsx.size() - 1, binsx.data()); gStyle->SetTitleFontSize(0.06); - TRandom2 rand; - // Filling histogram with random entries - for (int i = 0; i < 100'000; ++i) { + TRandom2 rand; + for (int i = 0; i < 100000; ++i) { double r = rand.Rndm() * 100; orig->Fill(r); } - TH1F *norm = (TH1F *)orig->Clone("norm"); + TH1D *norm = static_cast(orig->Clone("norm")); norm->SetTitle("Normalized Histogram"); // Normalizing the Histogram by scaling by 1 / the integral and taking width into account diff --git a/tutorials/hist/hist010_TH1_two_scales.C b/tutorials/hist/hist010_TH1_two_scales.C new file mode 100644 index 0000000000000..3cd330b3c75b9 --- /dev/null +++ b/tutorials/hist/hist010_TH1_two_scales.C @@ -0,0 +1,47 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Example of macro illustrating how to superimpose two histograms +/// with different scales in the "same" pad. +/// +/// \macro_image +/// \macro_code +/// +/// \date November 2024 +/// \author Rene Brun + +void hist010_TH1_two_scales() +{ + TCanvas *c1 = new TCanvas("c1", "hists with different scales", 600, 400); + + // create/fill draw h1 + gStyle->SetOptStat(kFALSE); + TH1D *h1 = new TH1D("h1", "my histogram", 100, -3, 3); + TRandom3 rng; + for (int i = 0; i < 10000; i++) + h1->Fill(rng.Gaus(0, 1)); + h1->Draw(); + c1->Update(); + + // create hint1 filled with the bins integral of h1 + TH1D *hint1 = new TH1D("hint1", "h1 bins integral", 100, -3, 3); + double sum = 0; + for (int i = 1; i <= 100; i++) { + sum += h1->GetBinContent(i); + hint1->SetBinContent(i, sum); + } + + // scale hint1 to the pad coordinates + double rightmax = 1.1 * hint1->GetMaximum(); + double scale = gPad->GetUymax() / rightmax; + hint1->SetLineColor(kRed); + hint1->Scale(scale); + hint1->Draw("same"); + + // draw an axis on the right side + TGaxis *axis = + new TGaxis(gPad->GetUxmax(), gPad->GetUymin(), gPad->GetUxmax(), gPad->GetUymax(), 0, rightmax, 510, "+L"); + axis->SetLineColor(kRed); + axis->SetLabelColor(kRed); + axis->Draw(); +} diff --git a/tutorials/hist/legendautoplaced.C b/tutorials/hist/hist011_TH1_legend_autoplaced.C similarity index 57% rename from tutorials/hist/legendautoplaced.C rename to tutorials/hist/hist011_TH1_legend_autoplaced.C index d05670e0ba763..31b059ba2435f 100644 --- a/tutorials/hist/legendautoplaced.C +++ b/tutorials/hist/hist011_TH1_legend_autoplaced.C @@ -10,32 +10,38 @@ /// \macro_image /// \macro_code /// +/// \date November 2024 /// \author Olivier Couet -void legendautoplaced() +void hist011_TH1_legend_autoplaced() { - auto c4 = new TCanvas("c", "c", 600,500); - auto hpx = new TH1D("hpx","This is the hpx distribution",100,-4.,4.); + auto *c4 = new TCanvas("c", "c", 600, 500); + + // Create a dummy histogram + auto *hpx = new TH1D("hpx", "This is the hpx distribution", 100, -4., 4.); hpx->FillRandom("gaus", 50000); hpx->Draw("E"); hpx->GetYaxis()->SetTitle("Y Axis title"); - hpx->GetYaxis()->SetTitleOffset(1.3); hpx->GetYaxis()->CenterTitle(true); + hpx->GetYaxis()->SetTitleOffset(1.3); + hpx->GetYaxis()->CenterTitle(true); hpx->GetXaxis()->SetTitle("X Axis title"); hpx->GetXaxis()->CenterTitle(true); - auto h1 = new TH1D("h1","A green histogram",100,-2.,2.); + // Create another dummy histogram + auto *h1 = new TH1D("h1", "A green histogram", 100, -2., 2.); h1->FillRandom("gaus", 10000); h1->SetLineColor(kGreen); h1->Draw("same"); - auto g = new TGraph(); - g->SetPoint(0, -3.5, 100 ); - g->SetPoint(1, -3.0, 300 ); - g->SetPoint(2, -2.0, 1000 ); - g->SetPoint(3, 1.0, 800 ); - g->SetPoint(4, 0.0, 200 ); - g->SetPoint(5, 3.0, 200 ); - g->SetPoint(6, 3.0, 700 ); + // Create a dummy graph + auto *g = new TGraph(); + g->SetPoint(0, -3.5, 100); + g->SetPoint(1, -3.0, 300); + g->SetPoint(2, -2.0, 1000); + g->SetPoint(3, 1.0, 800); + g->SetPoint(4, 0.0, 200); + g->SetPoint(5, 3.0, 200); + g->SetPoint(6, 3.0, 700); g->Draw("L"); g->SetTitle("This is a TGraph"); g->SetLineColor(kRed); diff --git a/tutorials/hist/hksimple.C b/tutorials/hist/hist012_TH1_hksimple.C similarity index 58% rename from tutorials/hist/hksimple.C rename to tutorials/hist/hist012_TH1_hksimple.C index 07f28a1ac2b02..d8f26137bec65 100644 --- a/tutorials/hist/hksimple.C +++ b/tutorials/hist/hist012_TH1_hksimple.C @@ -6,12 +6,13 @@ /// \macro_image /// \macro_code /// +/// \date November 2022 /// \author Victor Perevovchikov void canvasRefresh(TCanvas *c1) { for (Int_t j = 0; j < 3; j++) - c1->GetPad(j+1)->Modified(); + c1->GetPad(j + 1)->Modified(); c1->Modified(); c1->Update(); @@ -19,29 +20,29 @@ void canvasRefresh(TCanvas *c1) gSystem->ProcessEvents(); } -void hksimple() +void hist012_TH1_hksimple() { -// Create a new canvas. - TCanvas* c1 = new TCanvas("c1","Dynamic Filling Example",200,10,600,900); + // Create a new canvas. + TCanvas *c1 = new TCanvas("c1", "Dynamic Filling Example", 200, 10, 600, 900); -// Create a normal histogram and two TH1K histograms + // Create a normal histogram and two TH1K histograms TH1 *hpx[3]; - hpx[0] = new TH1F("hp0","Normal histogram",1000,-4,4); - hpx[1] = new TH1K("hk1","Nearest Neighbour of order 3",1000,-4,4); - hpx[2] = new TH1K("hk2","Nearest Neighbour of order 16",1000,-4,4,16); - c1->Divide(1,3); + hpx[0] = new TH1F("hp0", "Normal histogram", 1000, -4, 4); + hpx[1] = new TH1K("hk1", "Nearest Neighbour of order 3", 1000, -4, 4); + hpx[2] = new TH1K("hk2", "Nearest Neighbour of order 16", 1000, -4, 4, 16); + c1->Divide(1, 3); for (Int_t j = 0; j < 3; j++) { c1->cd(j + 1); hpx[j]->SetFillColor(48); hpx[j]->Draw(); } -// Fill histograms randomly + // Fill histograms randomly gRandom->SetSeed(12345); Float_t px, py, pz; const Int_t kUPDATE = 10; for (Int_t i = 0; i <= 300; i++) { - gRandom->Rannor(px,py); + gRandom->Rannor(px, py); for (Int_t j = 0; j < 3; j++) hpx[j]->Fill(px); if (i && (i % kUPDATE) == 0) diff --git a/tutorials/hist/hist013_TH1_rebin.C b/tutorials/hist/hist013_TH1_rebin.C new file mode 100644 index 0000000000000..483959664194a --- /dev/null +++ b/tutorials/hist/hist013_TH1_rebin.C @@ -0,0 +1,64 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook -js +/// Rebin a variable bin-width histogram. +/// +/// This tutorial illustrates how to: +/// - create a variable bin-width histogram with a binning such +/// that the population per bin is about the same. +/// - rebin a variable bin-width histogram into another one. +/// +/// \macro_image +/// \macro_code +/// +/// \date July 2016 +/// \author Rene Brun + +#include "TH1.h" +#include "TCanvas.h" +void hist013_TH1_rebin() +{ + // create a fix bin histogram + TH1F *h = new TH1F("h", "test rebin", 100, -3, 3); + Int_t nentries = 1000; + h->FillRandom("gaus", nentries); + Double_t xbins[1001]; + Int_t k = 0; + TAxis *axis = h->GetXaxis(); + for (Int_t i = 1; i <= 100; i++) { + Int_t y = (Int_t)h->GetBinContent(i); + if (y <= 0) + continue; + Double_t dx = axis->GetBinWidth(i) / y; + Double_t xmin = axis->GetBinLowEdge(i); + for (Int_t j = 0; j < y; j++) { + xbins[k] = xmin + j * dx; + k++; + } + } + xbins[k] = axis->GetXmax(); + // create a variable bin-width histogram out of fix bin histogram + // new rebinned histogram should have about 10 entries per bin + TH1F *hnew = new TH1F("hnew", "rebinned", k, xbins); + hnew->FillRandom("gaus", 10 * nentries); + + // rebin hnew keeping only 50% of the bins + Double_t xbins2[501]; + Int_t kk = 0; + for (Int_t j = 0; j < k; j += 2) { + xbins2[kk] = xbins[j]; + kk++; + } + xbins2[kk] = xbins[k]; + TH1F *hnew2 = (TH1F *)hnew->Rebin(kk, "hnew2", xbins2); + + // draw the 3 histograms + TCanvas *c1 = new TCanvas("c1", "c1", 800, 1000); + c1->Divide(1, 3); + c1->cd(1); + h->Draw(); + c1->cd(2); + hnew->Draw(); + c1->cd(3); + hnew2->Draw(); +} diff --git a/tutorials/hist/cumulative.C b/tutorials/hist/hist014_TH1_cumulative.C similarity index 76% rename from tutorials/hist/cumulative.C rename to tutorials/hist/hist014_TH1_cumulative.C index 18b9f13bde27e..d7b747a420a15 100644 --- a/tutorials/hist/cumulative.C +++ b/tutorials/hist/hist014_TH1_cumulative.C @@ -6,6 +6,7 @@ /// \macro_image /// \macro_code /// +/// \date July 2016 /// \author M. Schiller #include @@ -16,21 +17,21 @@ #include "TCanvas.h" #include "TRandom.h" -TCanvas *cumulative() +TCanvas *hist014_TH1_cumulative() { - TH1* h = new TH1D("h", "h", 100, -5., 5.); + TH1 *h = new TH1D("h", "h", 100, -5., 5.); gRandom->SetSeed(); h->FillRandom("gaus", 1u << 16); // get the cumulative of h - TH1* hc = h->GetCumulative(); + TH1 *hc = h->GetCumulative(); // check that c has the "right" contents - Double_t* integral = h->GetIntegral(); + Double_t *integral = h->GetIntegral(); for (Int_t i = 1; i <= hc->GetNbinsX(); ++i) { assert(std::abs(integral[i] * h->GetEntries() - hc->GetBinContent(i)) < 1e-7); } // draw histogram together with its cumulative distribution - TCanvas* c = new TCanvas; - c->Divide(1,2); + TCanvas *c = new TCanvas; + c->Divide(1, 2); c->cd(1); h->Draw(); c->cd(2); diff --git a/tutorials/hist/h1ReadAndDraw.C b/tutorials/hist/hist015_TH1_read_and_draw.C similarity index 67% rename from tutorials/hist/h1ReadAndDraw.C rename to tutorials/hist/hist015_TH1_read_and_draw.C index 1463629ac65db..3ac9c6b50dcfe 100644 --- a/tutorials/hist/h1ReadAndDraw.C +++ b/tutorials/hist/hist015_TH1_read_and_draw.C @@ -9,6 +9,7 @@ /// \macro_image /// \macro_code /// +/// \date August 2021 /// \author Rene Brun #include "TInterpreter.h" @@ -23,7 +24,7 @@ #include "TSystem.h" #include "TInterpreter.h" -void h1ReadAndDraw() +void hist015_TH1_read_and_draw() { // Fetch and open the hsimple.root File TFile *example = TFile::Open(gROOT->GetTutorialDir() + "/hsimple.root"); @@ -33,20 +34,16 @@ void h1ReadAndDraw() TH1 *hpx = nullptr; // pointer to base class TH1 is enough example->GetObject("hpx", hpx); - TCanvas *c1 = new TCanvas("c1","Histogram Drawing Options",200,10,700,900); - TPad *pad1 = new TPad("pad1", - "The pad with the function",0.03,0.62,0.50,0.92); - TPad *pad2 = new TPad("pad2", - "The pad with the histogram",0.51,0.62,0.98,0.92); - TPad *pad3 = new TPad("pad3", - "The pad with the histogram",0.03,0.02,0.97,0.57); + TCanvas *c1 = new TCanvas("c1", "Histogram Drawing Options", 200, 10, 700, 900); + TPad *pad1 = new TPad("pad1", "The pad with the function", 0.03, 0.62, 0.50, 0.92); + TPad *pad2 = new TPad("pad2", "The pad with the histogram", 0.51, 0.62, 0.98, 0.92); + TPad *pad3 = new TPad("pad3", "The pad with the histogram", 0.03, 0.02, 0.97, 0.57); pad1->Draw(); pad2->Draw(); pad3->Draw(); // Draw a global picture title - TPaveLabel *title = new TPaveLabel(0.1,0.94,0.9,0.98, - "Drawing options for one dimensional histograms"); + TPaveLabel *title = new TPaveLabel(0.1, 0.94, 0.9, 0.98, "Drawing options for one dimensional histograms"); title->SetTextFont(52); title->Draw(); @@ -55,17 +52,16 @@ void h1ReadAndDraw() pad1->GetFrame()->SetFillColor(18); hpx->SetFillColor(45); hpx->DrawCopy(); - TPaveLabel *label1 = new TPaveLabel(-3.5,700,-1,800,"Default option"); + TPaveLabel *label1 = new TPaveLabel(-3.5, 700, -1, 800, "Default option"); label1->Draw(); // Draw hpx as a lego. Clicking on the lego area will show // a "transparent cube" to guide you rotating the lego in real time. pad2->cd(); hpx->DrawCopy("lego1"); - TPaveLabel *label2 = new TPaveLabel(-0.72,0.74,-0.22,0.88,"option Lego1"); + TPaveLabel *label2 = new TPaveLabel(-0.72, 0.74, -0.22, 0.88, "option Lego1"); label2->Draw(); - TPaveLabel *label2a = new TPaveLabel(-0.93,-1.08,0.25,-0.92, - "Click on lego to rotate"); + TPaveLabel *label2a = new TPaveLabel(-0.93, -1.08, 0.25, -0.92, "Click on lego to rotate"); label2a->Draw(); // Draw hpx with its errors and a marker. @@ -74,14 +70,14 @@ void h1ReadAndDraw() pad3->SetGridy(); hpx->SetMarkerStyle(21); hpx->Draw("e1p"); - TPaveLabel *label3 = new TPaveLabel(2,600,3.5,650,"option e1p"); + TPaveLabel *label3 = new TPaveLabel(2, 600, 3.5, 650, "option e1p"); label3->Draw(); // The following illustrates how to add comments using a PaveText. // Attributes of text/lines/boxes added to a PaveText can be modified. // The AddText function returns a pointer to the added object. - TPaveText *pave = new TPaveText(-3.78,500,-1.2,750); - TText *t1=pave->AddText("You can move"); + TPaveText *pave = new TPaveText(-3.78, 500, -1.2, 750); + TText *t1 = pave->AddText("You can move"); t1->SetTextColor(4); t1->SetTextSize(0.05); pave->AddText("Title and Stats pads"); diff --git a/tutorials/hist/hist016_TH1_different_scales_canvas.C b/tutorials/hist/hist016_TH1_different_scales_canvas.C new file mode 100644 index 0000000000000..ab99df6ba169b --- /dev/null +++ b/tutorials/hist/hist016_TH1_different_scales_canvas.C @@ -0,0 +1,62 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Example of a canvas showing two histograms with different scales. +/// The second histogram is drawn in a transparent pad +/// +/// \macro_image +/// \macro_code +/// +/// \date November 2022 +/// \author Rene Brun + +void hist016_TH1_different_scales_canvas() +{ + TCanvas *c1 = new TCanvas("c1", "transparent pad", 200, 10, 700, 500); + TPad *pad1 = new TPad("pad1", "", 0, 0, 1, 1); + TPad *pad2 = new TPad("pad2", "", 0, 0, 1, 1); + pad2->SetFillStyle(4000); // will be transparent + pad1->Draw(); + pad1->cd(); + + TH1F *h1 = new TH1F("h1", "h1", 100, -3, 3); + TH1F *h2 = new TH1F("h2", "h2", 100, -3, 3); + TRandom r; + for (Int_t i = 0; i < 100000; i++) { + Double_t x1 = r.Gaus(-1, 0.5); + Double_t x2 = r.Gaus(1, 1.5); + if (i < 1000) + h1->Fill(x1); + h2->Fill(x2); + } + h1->Draw(); + pad1->Update(); // this will force the generation of the "stats" box + TPaveStats *ps1 = (TPaveStats *)h1->GetListOfFunctions()->FindObject("stats"); + ps1->SetX1NDC(0.4); + ps1->SetX2NDC(0.6); + pad1->Modified(); + c1->cd(); + + // compute the pad range with suitable margins + Double_t ymin = 0; + Double_t ymax = 2000; + Double_t dy = (ymax - ymin) / 0.8; // 10 per cent margins top and bottom + Double_t xmin = -3; + Double_t xmax = 3; + Double_t dx = (xmax - xmin) / 0.8; // 10 per cent margins left and right + pad2->Range(xmin - 0.1 * dx, ymin - 0.1 * dy, xmax + 0.1 * dx, ymax + 0.1 * dy); + pad2->Draw(); + pad2->cd(); + h2->SetLineColor(kRed); + h2->Draw("][sames"); + pad2->Update(); + TPaveStats *ps2 = (TPaveStats *)h2->GetListOfFunctions()->FindObject("stats"); + ps2->SetX1NDC(0.65); + ps2->SetX2NDC(0.85); + ps2->SetTextColor(kRed); + + // draw axis on the right side of the pad + TGaxis *axis = new TGaxis(xmax, ymin, xmax, ymax, ymin, ymax, 50510, "+L"); + axis->SetLabelColor(kRed); + axis->Draw(); +} diff --git a/tutorials/hist/hist017_TH1_smooth.C b/tutorials/hist/hist017_TH1_smooth.C new file mode 100644 index 0000000000000..d7b1d2bd6c6e7 --- /dev/null +++ b/tutorials/hist/hist017_TH1_smooth.C @@ -0,0 +1,70 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Histogram smoothing. +/// +/// \macro_image +/// \macro_code +/// +/// \date July 2016 +/// \author Rene Brun + +int ipad = 1; +TCanvas *c1 = 0; + +void smooth_hist(const char *fname, double xmin, double xmax, int n1, int n2) +{ + + std::cout << "smoothing a " << fname << " histogram" << std::endl; + + TH1D *h1 = new TH1D("h1", "h1", 100, xmin, xmax); + TH1D *h2 = new TH1D("h2", "h2", 100, xmin, xmax); + h1->FillRandom(fname, n1); + + TH1D *h1_s = new TH1D(*h1); + h1_s->SetName("h1_s"); + h1_s->Smooth(); + + h2->FillRandom(fname, n2); + + double p1 = h1->Chi2Test(h2, ""); + double p2 = h1_s->Chi2Test(h2, "UU"); + if (p2 < p1) + Error("testSmooth", "TH1::Smooth is not working correctly - a worst chi2 is obtained"); + + std::cout << " chi2 test non-smoothed histo " << p1 << std::endl; + std::cout << " chi2 test smoothed histo " << p2 << std::endl; + + double a1 = h1->AndersonDarlingTest(h2); + double a2 = h1_s->AndersonDarlingTest(h2); + + std::cout << " AD test non-smoothed histo " << a1 << std::endl; + std::cout << " AD test smoothed histo " << a2 << std::endl; + + double k1 = h1->KolmogorovTest(h2); + double k2 = h1_s->KolmogorovTest(h2); + + std::cout << " KS test non-smoothed histo " << k1 << std::endl; + std::cout << " KS test smoothed histo " << k2 << std::endl; + + c1->cd(ipad++); + h1->Draw("E"); + h1_s->SetLineColor(kRed); + h1_s->Draw("same"); + h2->Scale(double(n1) / n2); + h2->SetLineColor(kGreen); + h2->Draw("same"); +} + +void hist017_TH1_smooth(int n1 = 1000, int n2 = 1000000) +{ + + TH1::AddDirectory(false); + + c1 = new TCanvas(); + c1->Divide(1, 3); + + smooth_hist("gaus", -5, 5, n1, n2); + smooth_hist("landau", -5, 15, n1, n2); + smooth_hist("expo", -5, 0, n1, n2); +} diff --git a/tutorials/hist/h2_cut.C b/tutorials/hist/hist018_TH2_cutg.C similarity index 94% rename from tutorials/hist/h2_cut.C rename to tutorials/hist/hist018_TH2_cutg.C index 2154d1ac48134..13a56caecb0e2 100644 --- a/tutorials/hist/h2_cut.C +++ b/tutorials/hist/hist018_TH2_cutg.C @@ -8,9 +8,10 @@ /// \macro_image /// \macro_code /// +/// \date January 2023 /// \author Sergey Linev -void h2_cut() +void hist018_TH2_cutg() { const int n = 6; Float_t x[6] = { 1, 2, 1, -1, -2, -1 }; diff --git a/tutorials/hist/h2proj.C b/tutorials/hist/hist019_TH2_projection.C similarity index 66% rename from tutorials/hist/h2proj.C rename to tutorials/hist/hist019_TH2_projection.C index ce0fb11a5b5f5..99af2539fb243 100644 --- a/tutorials/hist/h2proj.C +++ b/tutorials/hist/hist019_TH2_projection.C @@ -8,32 +8,33 @@ /// \macro_image /// \macro_code /// +/// \date January 2023 /// \author Olivier Couet TH2F *h2; -TH1D * projh2X; -TH1D * projh2Y; +TH1D *projh2X; +TH1D *projh2Y; TPad *right_pad, *top_pad; -void h2proj() +void hist019_TH2_projection() { - auto c1 = new TCanvas("c1", "c1",900,900); + auto c1 = new TCanvas("c1", "c1", 900, 900); gStyle->SetOptStat(0); - TPad *center_pad = new TPad("center_pad", "center_pad",0.0,0.0,0.6,0.6); + TPad *center_pad = new TPad("center_pad", "center_pad", 0.0, 0.0, 0.6, 0.6); center_pad->Draw(); - right_pad = new TPad("right_pad", "right_pad",0.55,0.0,1.0,0.6); + right_pad = new TPad("right_pad", "right_pad", 0.55, 0.0, 1.0, 0.6); right_pad->Draw(); - top_pad = new TPad("top_pad", "top_pad",0.0,0.55,0.6,1.0); + top_pad = new TPad("top_pad", "top_pad", 0.0, 0.55, 0.6, 1.0); top_pad->Draw(); - h2 = new TH2F("h2","",40,-4,4,40,-20,20); + h2 = new TH2F("h2", "", 40, -4, 4, 40, -20, 20); Float_t px, py; for (Int_t i = 0; i < 25000; i++) { - gRandom->Rannor(px,py); - h2->Fill(px,5*py); + gRandom->Rannor(px, py); + h2->Fill(px, 5 * py); } projh2X = h2->ProjectionX(); projh2Y = h2->ProjectionY(); @@ -43,21 +44,21 @@ void h2proj() h2->Draw("COL"); top_pad->cd(); - projh2X->SetFillColor(kBlue+1); + projh2X->SetFillColor(kBlue + 1); projh2X->Draw("bar"); right_pad->cd(); - projh2Y->SetFillColor(kBlue-2); + projh2Y->SetFillColor(kBlue - 2); projh2Y->Draw("hbar"); c1->cd(); TLatex t; t.SetTextFont(42); t.SetTextSize(0.02); - t.DrawLatex(0.6,0.88,"This example demonstrates how to display"); - t.DrawLatex(0.6,0.85,"a histogram and its two projections."); + t.DrawLatex(0.6, 0.88, "This example demonstrates how to display"); + t.DrawLatex(0.6, 0.85, "a histogram and its two projections."); - auto ex = new TExec("zoom","ZoomExec()"); + auto ex = new TExec("zoom", "ZoomExec()"); h2->GetListOfFunctions()->Add(ex); } diff --git a/tutorials/hist/hist020_TH2_draw.C b/tutorials/hist/hist020_TH2_draw.C new file mode 100644 index 0000000000000..7dc5f09a46991 --- /dev/null +++ b/tutorials/hist/hist020_TH2_draw.C @@ -0,0 +1,115 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Display the various 2-d drawing options +/// +/// \macro_image +/// \macro_code +/// +/// \date June 2022 +/// \author Rene Brun + +void hist020_TH2_draw() +{ + gStyle->SetOptStat(0); + gStyle->SetCanvasColor(33); + gStyle->SetFrameFillColor(18); + TF2 *f2 = new TF2("f2", "xygaus + xygaus(5) + xylandau(10)", -4, 4, -4, 4); + Double_t params[] = {130, -1.4, 1.8, 1.5, 1, 150, 2, 0.5, -2, 0.5, 3600, -2, 0.7, -3, 0.3}; + f2->SetParameters(params); + auto h2 = new TH2F("h2", "xygaus + xygaus(5) + xylandau(10)", 20, -4, 4, 20, -4, 4); + h2->SetFillColor(46); + h2->FillRandom("f2", 40000); + TPaveLabel pl; + + // basic 2-d options + Float_t xMin = 0.67, yMin = 0.875, xMax = 0.85, yMax = 0.95; + Int_t cancolor = 17; + auto c2h = new TCanvas("c2h", "2-d options", 10, 10, 800, 600); + c2h->Divide(2, 2); + c2h->SetFillColor(cancolor); + c2h->cd(1); + h2->Draw(); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "SCAT", "brNDC"); + c2h->cd(2); + h2->Draw("box"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "BOX", "brNDC"); + c2h->cd(3); + h2->Draw("arr"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "ARR", "brNDC"); + c2h->cd(4); + h2->Draw("colz"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "COLZ", "brNDC"); + c2h->Update(); + + // text option + auto ctext = new TCanvas("ctext", "text option", 50, 50, 800, 600); + gPad->SetGrid(); + ctext->SetFillColor(cancolor); + ctext->SetGrid(); + h2->Draw("text"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "TEXT", "brNDC"); + ctext->Update(); + + // contour options + auto cont = new TCanvas("contours", "contours", 100, 100, 800, 600); + cont->Divide(2, 2); + gPad->SetGrid(); + cont->SetFillColor(cancolor); + cont->cd(1); + h2->Draw("contz"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "CONTZ", "brNDC"); + cont->cd(2); + gPad->SetGrid(); + h2->Draw("cont1"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "CONT1", "brNDC"); + cont->cd(3); + gPad->SetGrid(); + h2->Draw("cont2"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "CONT2", "brNDC"); + cont->cd(4); + gPad->SetGrid(); + h2->Draw("cont3"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "CONT3", "brNDC"); + cont->Update(); + + // lego options + auto lego = new TCanvas("lego", "lego options", 150, 150, 800, 600); + lego->Divide(2, 2); + lego->SetFillColor(cancolor); + lego->cd(1); + h2->Draw("lego"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "LEGO", "brNDC"); + lego->cd(2); + h2->Draw("lego1"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "LEGO1", "brNDC"); + lego->cd(3); + gPad->SetTheta(61); + gPad->SetPhi(-82); + h2->Draw("surf1pol"); + pl.DrawPaveLabel(xMin, yMin, xMax + 0.05, yMax, "SURF1POL", "brNDC"); + lego->cd(4); + gPad->SetTheta(21); + gPad->SetPhi(-90); + h2->Draw("surf1cyl"); + pl.DrawPaveLabel(xMin, yMin, xMax + 0.05, yMax, "SURF1CYL", "brNDC"); + lego->Update(); + + // surface options + auto surf = new TCanvas("surfopt", "surface options", 200, 200, 800, 600); + surf->Divide(2, 2); + surf->SetFillColor(cancolor); + surf->cd(1); + h2->Draw("surf1"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "SURF1", "brNDC"); + surf->cd(2); + h2->Draw("surf2z"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "SURF2Z", "brNDC"); + surf->cd(3); + h2->Draw("surf3"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "SURF3", "brNDC"); + surf->cd(4); + h2->Draw("surf4"); + pl.DrawPaveLabel(xMin, yMin, xMax, yMax, "SURF4", "brNDC"); + surf->Update(); +} diff --git a/tutorials/hist/hist021_TH2_reverse_axis.C b/tutorials/hist/hist021_TH2_reverse_axis.C new file mode 100644 index 0000000000000..6de1404e4b99b --- /dev/null +++ b/tutorials/hist/hist021_TH2_reverse_axis.C @@ -0,0 +1,56 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Example showing an histogram with reverse axis. +/// +/// \macro_image +/// \macro_code +/// +/// \date July 2016 +/// \author Olivier Couet + +void ReverseXAxis(TH1 *h); +void ReverseYAxis(TH1 *h); + +void hist021_TH2_reverse_axis() +{ + TH2F *hpxpy = new TH2F("hpxpy", "py vs px", 40, -4, 4, 40, -4, 4); + Float_t px, py; + TRandom r; + for (Int_t i = 0; i < 25000; i++) { + r.Rannor(px, py); + hpxpy->Fill(px, py); + } + TCanvas *c1 = new TCanvas("c1"); + hpxpy->Draw("colz"); + ReverseXAxis(hpxpy); + ReverseYAxis(hpxpy); +} + +void ReverseXAxis(TH1 *h) +{ + // Remove the current axis + h->GetXaxis()->SetLabelOffset(999); + h->GetXaxis()->SetTickLength(0); + + // Redraw the new axis + gPad->Update(); + TGaxis *newaxis = new TGaxis(gPad->GetUxmax(), gPad->GetUymin(), gPad->GetUxmin(), gPad->GetUymin(), + h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax(), 510, "-"); + newaxis->SetLabelOffset(-0.03); + newaxis->Draw(); +} + +void ReverseYAxis(TH1 *h) +{ + // Remove the current axis + h->GetYaxis()->SetLabelOffset(999); + h->GetYaxis()->SetTickLength(0); + + // Redraw the new axis + gPad->Update(); + TGaxis *newaxis = new TGaxis(gPad->GetUxmin(), gPad->GetUymax(), gPad->GetUxmin() - 0.001, gPad->GetUymin(), + h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax(), 510, "+"); + newaxis->SetLabelOffset(-0.03); + newaxis->Draw(); +} diff --git a/tutorials/hist/movepalette.C b/tutorials/hist/hist022_TH2_palette.C similarity index 59% rename from tutorials/hist/movepalette.C rename to tutorials/hist/hist022_TH2_palette.C index 6d3ac69b89cfa..e5d27ebfe1b56 100644 --- a/tutorials/hist/movepalette.C +++ b/tutorials/hist/hist022_TH2_palette.C @@ -10,33 +10,38 @@ /// \macro_image /// \macro_code /// +/// \date October 2024 /// \author Olivier Couet -void movepalette() +void hist022_TH2_palette() { - auto c = new TCanvas("", "",0,0,1100,550); - c->Divide(2,1); + auto c = new TCanvas("", "", 0, 0, 1100, 550); + c->Divide(2, 1); gStyle->SetOptStat(0); - auto h1 = new TH2D("h1","h1",40,-4,4,40,-20,20); - auto h2 = new TH2D("h2","h2",40,-4,4,40,-20,20); + auto h1 = new TH2D("h1", "h1", 40, -4, 4, 40, -20, 20); + auto h2 = new TH2D("h2", "h2", 40, -4, 4, 40, -20, 20); float px, py; for (int i = 0; i < 25000; i++) { - gRandom->Rannor(px,py); h1->Fill(px,5*py); - gRandom->Rannor(px,py); h2->Fill(px,5*py); + gRandom->Rannor(px, py); + h1->Fill(px, 5 * py); + gRandom->Rannor(px, py); + h2->Fill(px, 5 * py); } TPad *p1 = (TPad *)c->cd(1); TPad *p2 = (TPad *)c->cd(2); p1->SetRightMargin(0.15); - auto palette1 = new TPaletteAxis(4.05,-15,4.5,15,h1); + auto palette1 = new TPaletteAxis(4.05, -15, 4.5, 15, h1); h1->GetListOfFunctions()->Add(palette1); p2->SetBottomMargin(0.2); - auto palette2 = new TPaletteAxis(-3.,-25,3.,-23,h2); + auto palette2 = new TPaletteAxis(-3., -25, 3., -23, h2); h2->GetListOfFunctions()->Add(palette2); - p1->cd(); h1->Draw("colz"); - p2->cd(); h2->Draw("colz"); + p1->cd(); + h1->Draw("colz"); + p2->cd(); + h2->Draw("colz"); } \ No newline at end of file diff --git a/tutorials/hist/hist023_THStack_simple.C b/tutorials/hist/hist023_THStack_simple.C new file mode 100644 index 0000000000000..a0658b8363cc1 --- /dev/null +++ b/tutorials/hist/hist023_THStack_simple.C @@ -0,0 +1,71 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Example of stacked histograms: class THStack. +/// +/// \macro_image +/// \macro_code +/// +/// \date December 2022 +/// \author Rene Brun + +void hist023_THStack_simple() +{ + auto hs = new THStack("hs", "Stacked 1D histograms"); + // create three 1-d histograms + auto h1st = new TH1F("h1st", "test hstack", 100, -4, 4); + h1st->FillRandom("gaus", 20000); + h1st->SetFillColor(kRed); + h1st->SetMarkerStyle(21); + h1st->SetMarkerColor(kRed); + hs->Add(h1st); + auto h2st = new TH1F("h2st", "test hstack", 100, -4, 4); + h2st->FillRandom("gaus", 15000); + h2st->SetFillColor(kBlue); + h2st->SetMarkerStyle(21); + h2st->SetMarkerColor(kBlue); + hs->Add(h2st); + auto h3st = new TH1F("h3st", "test hstack", 100, -4, 4); + h3st->FillRandom("gaus", 10000); + h3st->SetFillColor(kGreen); + h3st->SetMarkerStyle(21); + h3st->SetMarkerColor(kGreen); + hs->Add(h3st); + + auto cst = new TCanvas("cst", "stacked hists", 10, 10, 700, 700); + cst->Divide(2, 2); + // in top left pad, draw the stack with defaults + cst->cd(1); + hs->Draw(); + // in top right pad, draw the stack in non-stack mode + // and errors option + cst->cd(2); + gPad->SetGrid(); + hs->Draw("nostack,e1p"); + // in bottom left, draw in stack mode with "lego1" option + cst->cd(3); + gPad->SetFrameFillColor(17); + gPad->SetTheta(3.77); + gPad->SetPhi(2.9); + hs->Draw("lego1"); + + cst->cd(4); + // create two 2-D histograms and draw them in stack mode + gPad->SetFrameFillColor(17); + auto a = new THStack("a", "Stacked 2D histograms"); + auto f1 = new TF2("f1", "xygaus + xygaus(5) + xylandau(10)", -4, 4, -4, 4); + Double_t params1[] = {130, -1.4, 1.8, 1.5, 1, 150, 2, 0.5, -2, 0.5, 3600, -2, 0.7, -3, 0.3}; + f1->SetParameters(params1); + auto h2sta = new TH2F("h2sta", "h2sta", 20, -4, 4, 20, -4, 4); + h2sta->SetFillColor(38); + h2sta->FillRandom("f1", 4000); + auto f2 = new TF2("f2", "xygaus + xygaus(5)", -4, 4, -4, 4); + Double_t params2[] = {100, -1.4, 1.9, 1.1, 2, 80, 2, 0.7, -2, 0.5}; + f2->SetParameters(params2); + auto h2stb = new TH2F("h2stb", "h2stb", 20, -4, 4, 20, -4, 4); + h2stb->SetFillColor(46); + h2stb->FillRandom("f2", 3000); + a->Add(h2sta); + a->Add(h2stb); + a->Draw(); +} diff --git a/tutorials/hist/hstackpads.C b/tutorials/hist/hist024_THStack_pads.C similarity index 95% rename from tutorials/hist/hstackpads.C rename to tutorials/hist/hist024_THStack_pads.C index 03fdbcfea3378..dc431c1d6b75c 100644 --- a/tutorials/hist/hstackpads.C +++ b/tutorials/hist/hist024_THStack_pads.C @@ -9,9 +9,10 @@ /// \macro_image /// \macro_code /// +/// \date June 2024 /// \author Sergey Linev -void hstackpads() +void hist024_THStack_pads() { auto hs = new THStack("hs", "Stacked 1D histograms"); diff --git a/tutorials/hist/thstack2palettecolor.C b/tutorials/hist/hist025_THStack_2d_palette_color.C similarity index 59% rename from tutorials/hist/thstack2palettecolor.C rename to tutorials/hist/hist025_THStack_2d_palette_color.C index e424311945c86..4bf27d223d970 100644 --- a/tutorials/hist/thstack2palettecolor.C +++ b/tutorials/hist/hist025_THStack_2d_palette_color.C @@ -14,21 +14,22 @@ /// \macro_image /// \macro_code /// +/// \date November 2022 /// \author Olivier Couet -void thstack2palettecolor() +void hist025_THStack_2d_palette_color() { gStyle->SetPalette(1); - auto h1 = new TH2F("h1","h1",20,0,6,20,-4,4); - auto h2 = new TH2F("h2","h2",20,0,6,20,-4,4); - auto h3 = new TH2F("h3","h3",20,0,6,20,-4,4); - auto h4 = new TH2F("h4","h4",20,0,6,20,-4,4); - auto h5 = new TH2F("h5","h5",20,0,6,20,-4,4); - h2->Fill(2.,0.,5); - h3->Fill(3.,0.,10); - h4->Fill(4.,0.,15); - h5->Fill(5.,0.,20); - auto hs = new THStack("hs","Test of palette colored lego stack"); + auto h1 = new TH2F("h1", "h1", 20, 0, 6, 20, -4, 4); + auto h2 = new TH2F("h2", "h2", 20, 0, 6, 20, -4, 4); + auto h3 = new TH2F("h3", "h3", 20, 0, 6, 20, -4, 4); + auto h4 = new TH2F("h4", "h4", 20, 0, 6, 20, -4, 4); + auto h5 = new TH2F("h5", "h5", 20, 0, 6, 20, -4, 4); + h2->Fill(2., 0., 5); + h3->Fill(3., 0., 10); + h4->Fill(4., 0., 15); + h5->Fill(5., 0., 20); + auto hs = new THStack("hs", "Test of palette colored lego stack"); hs->Add(h1); hs->Add(h2); hs->Add(h3); diff --git a/tutorials/hist/thstackcolorscheme.C b/tutorials/hist/hist026_THStack_color_scheme.C similarity index 56% rename from tutorials/hist/thstackcolorscheme.C rename to tutorials/hist/hist026_THStack_color_scheme.C index 29cdacd0370dc..fee1a46e3ff1d 100644 --- a/tutorials/hist/thstackcolorscheme.C +++ b/tutorials/hist/hist026_THStack_color_scheme.C @@ -8,47 +8,48 @@ /// \macro_image /// \macro_code /// +/// \date October 2024 /// \author Olivier Couet -void thstackcolorscheme() +void hist026_THStack_color_scheme() { auto c1 = new TCanvas(); - auto hs = new THStack("hs","Stacked 1D histograms colored using 6-colors scheme"); + auto hs = new THStack("hs", "Stacked 1D histograms colored using 6-colors scheme"); // Create six 1-d histograms and add them in the stack - auto h1st = new TH1F("h1st","A",100,-4,4); - h1st->FillRandom("gaus",20000); + auto h1st = new TH1F("h1st", "A", 100, -4, 4); + h1st->FillRandom("gaus", 20000); h1st->SetFillColor(kP6Blue); hs->Add(h1st); - auto h2st = new TH1F("h2st","B",100,-4,4); - h2st->FillRandom("gaus",15000); + auto h2st = new TH1F("h2st", "B", 100, -4, 4); + h2st->FillRandom("gaus", 15000); h2st->SetFillColor(kP6Yellow); hs->Add(h2st); - auto h3st = new TH1F("h3st","C",100,-4,4); - h3st->FillRandom("gaus",10000); + auto h3st = new TH1F("h3st", "C", 100, -4, 4); + h3st->FillRandom("gaus", 10000); h3st->SetFillColor(kP6Red); hs->Add(h3st); - auto h4st = new TH1F("h4st","D",100,-4,4); - h4st->FillRandom("gaus",10000); + auto h4st = new TH1F("h4st", "D", 100, -4, 4); + h4st->FillRandom("gaus", 10000); h4st->SetFillColor(kP6Grape); hs->Add(h4st); - auto h5st = new TH1F("h5st","E",100,-4,4); - h5st->FillRandom("gaus",10000); + auto h5st = new TH1F("h5st", "E", 100, -4, 4); + h5st->FillRandom("gaus", 10000); h5st->SetFillColor(kP6Gray); hs->Add(h5st); - auto h6st = new TH1F("h6st","F",100,-4,4); - h6st->FillRandom("gaus",10000); + auto h6st = new TH1F("h6st", "F", 100, -4, 4); + h6st->FillRandom("gaus", 10000); h6st->SetFillColor(kP6Violet); hs->Add(h6st); // draw the stack with colors hs->Draw(); - TLegend *l = gPad->BuildLegend(.8,.55,1.,.9,"","F"); + TLegend *l = gPad->BuildLegend(.8, .55, 1., .9, "", "F"); l->SetLineWidth(0); l->SetFillStyle(0); diff --git a/tutorials/hist/thstackpalettecolor.C b/tutorials/hist/hist027_THStack_palette_color.C similarity index 67% rename from tutorials/hist/thstackpalettecolor.C rename to tutorials/hist/hist027_THStack_palette_color.C index d7c4327c19628..0089cbd2ea1a3 100644 --- a/tutorials/hist/thstackpalettecolor.C +++ b/tutorials/hist/hist027_THStack_palette_color.C @@ -14,25 +14,26 @@ /// \macro_image /// \macro_code /// +/// \date December 2018 /// \author Olivier Couet -void thstackpalettecolor() +void hist027_THStack_palette_color() { - auto hs = new THStack("hs","Stacked 1D histograms colored using kOcean palette"); + auto hs = new THStack("hs", "Stacked 1D histograms colored using kOcean palette"); gStyle->SetPalette(kOcean); // Create three 1-d histograms and add them in the stack - auto h1st = new TH1F("h1st","test hstack",100,-4,4); - h1st->FillRandom("gaus",20000); + auto h1st = new TH1F("h1st", "test hstack", 100, -4, 4); + h1st->FillRandom("gaus", 20000); hs->Add(h1st); - auto h2st = new TH1F("h2st","test hstack",100,-4,4); - h2st->FillRandom("gaus",15000); + auto h2st = new TH1F("h2st", "test hstack", 100, -4, 4); + h2st->FillRandom("gaus", 15000); hs->Add(h2st); - auto h3st = new TH1F("h3st","test hstack",100,-4,4); - h3st->FillRandom("gaus",10000); + auto h3st = new TH1F("h3st", "test hstack", 100, -4, 4); + h3st->FillRandom("gaus", 10000); hs->Add(h3st); // draw the stack diff --git a/tutorials/hist/hist028_THStack_multicolor.C b/tutorials/hist/hist028_THStack_multicolor.C new file mode 100644 index 0000000000000..7c24dcfda5615 --- /dev/null +++ b/tutorials/hist/hist028_THStack_multicolor.C @@ -0,0 +1,58 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Use a THStack to show a 2-D hist with cells with different colors. +/// ~~~{.cpp} +/// root > .x multicolor.C +/// root > .x multicolor.C(1) +/// ~~~ +/// \macro_image +/// \macro_code +/// +/// \date August 2016 +/// \author Rene Brun + +#include "TCanvas.h" +#include "TH2.h" +#include "THStack.h" +#include "TRandom.h" + +void hist028_THStack_multicolor(Int_t isStack = 0) +{ + TCanvas *c1 = new TCanvas; + Int_t nbins = 20; + TH2F *h1 = new TH2F("h1", "h1", nbins, -4, 4, nbins, -4, 4); + h1->SetFillColor(kBlue); + TH2F *h2 = new TH2F("h2", "h2", nbins, -4, 4, nbins, -4, 4); + h2->SetFillColor(kRed); + TH2F *h3 = new TH2F("h3", "h3", nbins, -4, 4, nbins, -4, 4); + h3->SetFillColor(kYellow); + THStack *hs = new THStack("hs", "three plots"); + hs->Add(h1); + hs->Add(h2); + hs->Add(h3); + TRandom r; + Int_t i; + for (i = 0; i < 20000; i++) + h1->Fill(r.Gaus(), r.Gaus()); + for (i = 0; i < 200; i++) { + Int_t ix = (Int_t)r.Uniform(0, nbins); + Int_t iy = (Int_t)r.Uniform(0, nbins); + Int_t bin = h1->GetBin(ix, iy); + Double_t val = h1->GetBinContent(bin); + if (val <= 0) + continue; + if (!isStack) + h1->SetBinContent(bin, 0); + if (r.Rndm() > 0.5) { + if (!isStack) + h2->SetBinContent(bin, 0); + h3->SetBinContent(bin, val); + } else { + if (!isStack) + h3->SetBinContent(bin, 0); + h2->SetBinContent(bin, val); + } + } + hs->Draw("lego1"); +} diff --git a/tutorials/hist/ratioplot1.C b/tutorials/hist/hist029_TRatioPlot_simple.C similarity index 81% rename from tutorials/hist/ratioplot1.C rename to tutorials/hist/hist029_TRatioPlot_simple.C index 6260630377bc3..94ed65bcf39b9 100644 --- a/tutorials/hist/ratioplot1.C +++ b/tutorials/hist/hist029_TRatioPlot_simple.C @@ -10,11 +10,13 @@ /// \macro_image /// \macro_code /// +/// \date February 2023 /// \author Paul Gessinger -void ratioplot1() { +void hist029_TRatioPlot_simple() +{ gStyle->SetOptStat(0); - auto C = new TCanvas("C", "A ratio example"); + auto C = new TCanvas("C", "A ratio example"); auto h1 = new TH1D("h1", "TRatioPlot Example; x; y", 50, 0, 10); auto h2 = new TH1D("h2", "h2", 50, 0, 10); auto f1 = new TF1("f1", "exp(- x/[0] )"); @@ -33,8 +35,8 @@ void ratioplot1() { // Add a legend to the ratio plot rp->GetUpperPad()->cd(); - TLegend *legend = new TLegend(0.3,0.7,0.7,0.85); - legend->AddEntry("h1","First histogram","l"); - legend->AddEntry("h2","Second histogram","le"); + TLegend *legend = new TLegend(0.3, 0.7, 0.7, 0.85); + legend->AddEntry("h1", "First histogram", "l"); + legend->AddEntry("h2", "Second histogram", "le"); legend->Draw(); } diff --git a/tutorials/hist/ratioplot2.C b/tutorials/hist/hist030_TRatioPlot_residual.C similarity index 93% rename from tutorials/hist/ratioplot2.C rename to tutorials/hist/hist030_TRatioPlot_residual.C index 5a36c92f77e7b..60266dabf14da 100644 --- a/tutorials/hist/ratioplot2.C +++ b/tutorials/hist/hist030_TRatioPlot_residual.C @@ -12,9 +12,11 @@ /// \macro_image /// \macro_code /// +/// \date September 2023 /// \author Paul Gessinger -void ratioplot2() { +void hist030_TRatioPlot_residual() +{ gStyle->SetOptStat(0); auto c1 = new TCanvas("c1", "fit residual simple"); auto h1 = new TH1D("h1", "h1", 50, -5, 5); diff --git a/tutorials/hist/hist031_TRatioPlot_residual_fit.C b/tutorials/hist/hist031_TRatioPlot_residual_fit.C new file mode 100644 index 0000000000000..6f5f988622743 --- /dev/null +++ b/tutorials/hist/hist031_TRatioPlot_residual_fit.C @@ -0,0 +1,30 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Example which shows how you can get the graph of the lower plot and set the y axis range for it. +/// +/// Since the lower plot is not created until `TRatioPlot::Draw` is called, you can only use the method +/// afterwards. +/// +/// \macro_image +/// \macro_code +/// +/// \date January 2020 +/// \author Paul Gessinger + +void hist031_TRatioPlot_residual_fit() +{ + gStyle->SetOptStat(0); + auto c1 = new TCanvas("c1", "fit residual simple"); + c1->SetLogy(); + auto h1 = new TH1D("h1", "h1", 50, -5, 5); + h1->FillRandom("gaus", 2000); + h1->Fit("gaus", "0"); + h1->SetMinimum(0.001); + h1->GetXaxis()->SetTitle("x"); + h1->GetYaxis()->SetTitle("y"); + auto rp1 = new TRatioPlot(h1); + rp1->Draw(); + rp1->GetLowerRefGraph()->SetMinimum(-2); + rp1->GetLowerRefGraph()->SetMaximum(2); +} diff --git a/tutorials/hist/ratioplot4.C b/tutorials/hist/hist032_TRatioPlot_fit_lines.C similarity index 93% rename from tutorials/hist/ratioplot4.C rename to tutorials/hist/hist032_TRatioPlot_fit_lines.C index 106e97375fe11..d511ae92a32d9 100644 --- a/tutorials/hist/ratioplot4.C +++ b/tutorials/hist/hist032_TRatioPlot_fit_lines.C @@ -9,9 +9,11 @@ /// \macro_image /// \macro_code /// +/// \date January 2020 /// \author Paul Gessinger -void ratioplot4() { +void hist032_TRatioPlot_fit_lines() +{ gStyle->SetOptStat(0); auto c1 = new TCanvas("c1", "fit residual simple"); auto h1 = new TH1D("h1", "h1", 50, -5, 5); diff --git a/tutorials/hist/ratioplot5.C b/tutorials/hist/hist033_TRatioPlot_fit_confidence.C similarity index 86% rename from tutorials/hist/ratioplot5.C rename to tutorials/hist/hist033_TRatioPlot_fit_confidence.C index 43a5c1a9b7e9e..e17e35c4953a2 100644 --- a/tutorials/hist/ratioplot5.C +++ b/tutorials/hist/hist033_TRatioPlot_fit_confidence.C @@ -7,14 +7,16 @@ /// \macro_image /// \macro_code /// +/// \date January 2020 /// \author Paul Gessinger -void ratioplot5() { +void hist033_TRatioPlot_fit_confidence() +{ gStyle->SetOptStat(0); auto c1 = new TCanvas("c1", "fit residual simple"); auto h1 = new TH1D("h1", "h1", 50, -5, 5); h1->FillRandom("gaus", 2000); - h1->Fit("gaus","0"); + h1->Fit("gaus", "0"); h1->GetXaxis()->SetTitle("x"); h1->GetYaxis()->SetTitle("y"); auto rp1 = new TRatioPlot(h1); diff --git a/tutorials/hist/ratioplot6.C b/tutorials/hist/hist034_TRatioPlot_fit_margin.C similarity index 92% rename from tutorials/hist/ratioplot6.C rename to tutorials/hist/hist034_TRatioPlot_fit_margin.C index 3f2ee17e34fb9..81943de1ad8ff 100644 --- a/tutorials/hist/ratioplot6.C +++ b/tutorials/hist/hist034_TRatioPlot_fit_margin.C @@ -7,9 +7,11 @@ /// \macro_image /// \macro_code /// +/// \date January 2020 /// \author Paul Gessinger -void ratioplot6() { +void hist034_TRatioPlot_fit_margin() +{ gStyle->SetOptStat(0); auto c1 = new TCanvas("c1", "fit residual simple"); gPad->SetFrameFillStyle(0); diff --git a/tutorials/hist/ratioplotOld.C b/tutorials/hist/hist035_TRatioPlot_manual_ratio.C similarity index 87% rename from tutorials/hist/ratioplotOld.C rename to tutorials/hist/hist035_TRatioPlot_manual_ratio.C index 3823ccbae99fd..7be844ef507f5 100644 --- a/tutorials/hist/ratioplotOld.C +++ b/tutorials/hist/hist035_TRatioPlot_manual_ratio.C @@ -7,9 +7,11 @@ /// \macro_image /// \macro_code /// +/// \date May 2021 /// \author Olivier Couet -void ratioplotOld( ) { +void hist035_TRatioPlot_manual_ratio() +{ // Define two gaussian histograms. Note the X and Y title are defined // at booking time using the convention "Hist_title ; X_title ; Y_title" TH1F *h1 = new TH1F("h1", "Two gaussian plots and their ratio;x title; h1 and h2 gaussian histograms", 100, -5, 5); @@ -30,7 +32,7 @@ void ratioplotOld( ) { h1->Draw(); // Draw h1 h2->Draw("same"); // Draw h2 on top of h1 -#if ROOT_VERSION_CODE >= ROOT_VERSION(6,8,0) +#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 8, 0) // Avoid the first label (0) to be clipped. TAxis *axis = h1->GetYaxis(); axis->ChangeLabel(1, -1, -1, -1, -1, -1, " "); @@ -40,34 +42,34 @@ void ratioplotOld( ) { // Do not draw the Y axis label on the upper plot and redraw a small // axis instead, in order to avoid the first label (0) to be clipped. h1->GetYaxis()->SetLabelSize(0.); - TGaxis *axis = new TGaxis( -5, 20, -5, 220, 20,220,510,""); + TGaxis *axis = new TGaxis(-5, 20, -5, 220, 20, 220, 510, ""); axis->SetLabelFont(43); // Absolute font size in pixel (precision 3) axis->SetLabelSize(15); axis->Draw(); #endif // lower plot will be in pad - c->cd(); // Go back to the main canvas before defining pad2 + c->cd(); // Go back to the main canvas before defining pad2 TPad *pad2 = new TPad("pad2", "pad2", 0, 0.05, 1, 0.3); pad2->SetTopMargin(0); pad2->SetBottomMargin(0.2); pad2->SetGridx(); // vertical grid pad2->Draw(); - pad2->cd(); // pad2 becomes the current pad + pad2->cd(); // pad2 becomes the current pad // Define the ratio plot - TH1F *h3 = (TH1F*)h1->Clone("h3"); + TH1F *h3 = (TH1F *)h1->Clone("h3"); h3->SetLineColor(kBlack); h3->SetMinimum(0.8); // Define Y .. h3->SetMaximum(1.35); // .. range h3->Sumw2(); - h3->SetStats(0); // No statistics on lower plot + h3->SetStats(0); // No statistics on lower plot h3->Divide(h2); h3->SetMarkerStyle(21); - h3->Draw("ep"); // Draw the ratio plot + h3->Draw("ep"); // Draw the ratio plot // h1 settings - h1->SetLineColor(kBlue+1); + h1->SetLineColor(kBlue + 1); h1->SetLineWidth(2); // Y axis h1 plot settings diff --git a/tutorials/hist/hist036_TH2_labels.C b/tutorials/hist/hist036_TH2_labels.C new file mode 100644 index 0000000000000..ea1eebe5951c0 --- /dev/null +++ b/tutorials/hist/hist036_TH2_labels.C @@ -0,0 +1,48 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// 2-D histograms with alphanumeric labels. +/// +/// \macro_image +/// \macro_code +/// +/// \date July 2016 +/// \author Rene Brun + +TCanvas *hist036_TH2_labels() +{ + const Int_t nx = 12; + const Int_t ny = 20; + const char *month[nx] = {"January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; + const char *people[ny] = {"Jean", "Pierre", "Marie", "Odile", "Sebastien", "Fons", "Rene", + "Nicolas", "Xavier", "Greg", "Bjarne", "Anton", "Otto", "Eddy", + "Peter", "Pasha", "Philippe", "Suzanne", "Jeff", "Valery"}; + TCanvas *c1 = new TCanvas("c1", "demo bin labels", 10, 10, 600, 600); + c1->SetGrid(); + c1->SetLeftMargin(0.15); + c1->SetBottomMargin(0.15); + TH2F *h = new TH2F("h", "test", 3, 0, 3, 2, 0, 2); + h->SetCanExtend(TH1::kAllAxes); + h->SetStats(0); + gRandom->SetSeed(); + for (Int_t i = 0; i < 15000; i++) { + Int_t rx = gRandom->Rndm() * nx; + Int_t ry = gRandom->Rndm() * ny; + h->Fill(people[ry], month[rx], 1); + } + h->LabelsDeflate("X"); + h->LabelsDeflate("Y"); + h->LabelsOption("v"); + h->Draw("text"); + + TPaveText *pt = new TPaveText(0.6, 0.85, 0.98, 0.98, "brNDC"); + pt->SetFillColor(18); + pt->SetTextAlign(12); + pt->AddText("Use the axis Context Menu LabelsOption"); + pt->AddText(" \"a\" to sort by alphabetic order"); + pt->AddText(" \">\" to sort by decreasing values"); + pt->AddText(" \"<\" to sort by increasing values"); + pt->Draw(); + return c1; +} diff --git a/tutorials/hist/th2polyBoxes.C b/tutorials/hist/hist037_TH2Poly_boxes.C similarity index 59% rename from tutorials/hist/th2polyBoxes.C rename to tutorials/hist/hist037_TH2Poly_boxes.C index ccfc752f825ee..2a896d2a422c0 100644 --- a/tutorials/hist/th2polyBoxes.C +++ b/tutorials/hist/hist037_TH2Poly_boxes.C @@ -7,38 +7,40 @@ /// \macro_image /// \macro_code /// +/// \date August 2016 /// \author Olivier Couet -TCanvas *th2polyBoxes() { - TCanvas *ch2p2 = new TCanvas("ch2p2","ch2p2",600,400); +TCanvas *hist037_TH2Poly_boxes() +{ + TCanvas *ch2p2 = new TCanvas("ch2p2", "ch2p2", 600, 400); gStyle->SetPalette(57); TH2Poly *h2p = new TH2Poly(); h2p->SetName("Boxes"); h2p->SetTitle("Boxes"); - Int_t i,j; + Int_t i, j; Int_t nx = 40; Int_t ny = 40; - Double_t xval1,yval1,xval2,yval2; - Double_t dx=0.2, dy=0.1; + Double_t xval1, yval1, xval2, yval2; + Double_t dx = 0.2, dy = 0.1; xval1 = 0.; xval2 = dx; - for (i = 0; iAddBin(xval1, yval1, xval2, yval2); yval1 = yval2; - yval2 = yval2+yval2*dy; + yval2 = yval2 + yval2 * dy; } xval1 = xval2; - xval2 = xval2+xval2*dx; + xval2 = xval2 + xval2 * dx; } TRandom ran; - for (i = 0; i<300000; i++) { - h2p->Fill(50*ran.Gaus(2.,1), ran.Gaus(2.,1)); + for (i = 0; i < 300000; i++) { + h2p->Fill(50 * ran.Gaus(2., 1), ran.Gaus(2., 1)); } h2p->Draw("COLZ"); diff --git a/tutorials/hist/th2polyHoneycomb.C b/tutorials/hist/hist038_TH2Poly_honeycomb.C similarity index 91% rename from tutorials/hist/th2polyHoneycomb.C rename to tutorials/hist/hist038_TH2Poly_honeycomb.C index 30ba17a195d8e..63e87863071cd 100644 --- a/tutorials/hist/th2polyHoneycomb.C +++ b/tutorials/hist/hist038_TH2Poly_honeycomb.C @@ -8,11 +8,13 @@ /// \macro_code /// \macro_image /// +/// \date August 2023 /// \author Olivier Couet -void th2polyHoneycomb(){ +void hist038_TH2Poly_honeycomb() +{ TCanvas *C = new TCanvas("C", "C", 1200, 600); - C->Divide(2,1); + C->Divide(2, 1); TH2Poly *hc1 = new TH2Poly(); hc1->Honeycomb(0, 0, .1, 5, 5); diff --git a/tutorials/hist/hist039_TH2Poly_usa.C b/tutorials/hist/hist039_TH2Poly_usa.C new file mode 100644 index 0000000000000..383da5a6b0949 --- /dev/null +++ b/tutorials/hist/hist039_TH2Poly_usa.C @@ -0,0 +1,75 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook -js +/// This tutorial illustrates how to create an histogram with polygonal +/// bins (TH2Poly), fill it and draw it using the `col` option. The initial data +/// are stored in TMultiGraphs. They represent the USA map. Such histograms can +/// be rendered in 3D using the option `legogl`. +/// +/// The initial data have been downloaded from: http://www.maproom.psu.edu/dcw/ +/// This database was developed in 1991/1992 and national boundaries reflect +/// political reality as of that time. +/// +/// \macro_code +/// \macro_image +/// +/// \date February 2024 +/// \author Olivier Couet + +void hist039_TH2Poly_usa() +{ + Int_t i, bin; + const Int_t nx = 48; + const char *states[nx] = { + "alabama", "arizona", "arkansas", "california", "colorado", "connecticut", "delaware", + "florida", "georgia", "idaho", "illinois", "indiana", "iowa", "kansas", + "kentucky", "louisiana", "maine", "maryland", "massachusetts", "michigan", "minnesota", + "mississippi", "missouri", "montana", "nebraska", "nevada", "new_hampshire", "new_jersey", + "new_mexico", "new_york", "north_carolina", "north_dakota", "ohio", "oklahoma", "oregon", + "pennsylvania", "rhode_island", "south_carolina", "south_dakota", "tennessee", "texas", "utah", + "vermont", "virginia", "washington", "west_virginia", "wisconsin", "wyoming"}; + Double_t pop[nx] = {4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969, 9829211, 1545801, + 12910409, 6423113, 3007856, 2818747, 4314113, 4492076, 1318301, 5699478, 6593587, 9969727, + 5266214, 2951996, 5987580, 974989, 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, + 9380884, 646844, 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254, + 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270}; + + TCanvas *usa = new TCanvas("USA", "USA"); + usa->ToggleEventStatus(); + Double_t lon1 = -130; + Double_t lon2 = -65; + Double_t lat1 = 24; + Double_t lat2 = 50; + TH2Poly *p = new TH2Poly("Lower48", "Lower 48 Population (2009);Latitude;Longitude", lon1, lon2, lat1, lat2); + + TFile::SetCacheFileDir("."); + TFile *f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD"); + + if (!f) { + printf("Cannot access usa.root. Is internet working ?\n"); + return; + } + + // Define the TH2Poly bins. + TMultiGraph *mg; + TKey *key; + TIter nextkey(gDirectory->GetListOfKeys()); + while ((key = (TKey *)nextkey())) { + TObject *obj = key->ReadObj(); + if (obj->InheritsFrom("TMultiGraph")) { + mg = (TMultiGraph *)obj; + bin = p->AddBin(mg); + } + } + + // Fill TH2Poly, with capital letters for the states names + for (i = 0; i < nx; i++) + p->Fill(states[i], pop[i]); + + gStyle->SetOptStat(0); + p->Draw("colz textn"); + + // Add the reference for the population + TLatex pupulationRef(-128, 27, "#scale[.55]{#splitline{Source:}{http://eadiv.state.wy.us/pop/st-09est.htm}}"); + pupulationRef.DrawClone(); +} diff --git a/tutorials/hist/th2polyEurope.C b/tutorials/hist/hist040_TH2Poly_europe.C similarity index 51% rename from tutorials/hist/th2polyEurope.C rename to tutorials/hist/hist040_TH2Poly_europe.C index 2e83027f7f45e..03493c1a46bca 100644 --- a/tutorials/hist/th2polyEurope.C +++ b/tutorials/hist/hist040_TH2Poly_europe.C @@ -20,24 +20,25 @@ /// \macro_output /// \macro_code /// +/// \date August 2020 /// \author Olivier Couet -void th2polyEurope(Int_t npoints=500000) +void hist040_TH2Poly_europe(Int_t npoints = 500000) { - Int_t i,j; + Int_t i, j; Double_t lon1 = -25; - Double_t lon2 = 35; - Double_t lat1 = 34; - Double_t lat2 = 72; - Double_t R = (lat2-lat1)/(lon2-lon1); - Int_t W = 800; - Int_t H = (Int_t)(R*800); + Double_t lon2 = 35; + Double_t lat1 = 34; + Double_t lat2 = 72; + Double_t R = (lat2 - lat1) / (lon2 - lon1); + Int_t W = 800; + Int_t H = (Int_t)(R * 800); gStyle->SetStatX(0.28); gStyle->SetStatY(0.45); gStyle->SetStatW(0.15); // Canvas used to draw TH2Poly (the map) - TCanvas *ce = new TCanvas("ce", "ce",0,0,W,H); + TCanvas *ce = new TCanvas("ce", "ce", 0, 0, W, H); ce->ToggleEventStatus(); ce->SetGridx(); ce->SetGridy(); @@ -46,39 +47,32 @@ void th2polyEurope(Int_t npoints=500000) const Int_t nx = 36; // see http://en.wikipedia.org/wiki/Area_and_population_of_European_countries const char *countries[nx] = { - "france", "spain", "sweden", "germany", "finland", - "norway", "poland", "italy", "yugoslavia", "united_kingdom", - "romania", "belarus","greece", "czechoslovakia","bulgaria", - "iceland", "hungary","portugal","austria", "ireland", - "lithuania", "latvia", "estonia", "denmark", "netherlands", - "switzerland","moldova","belgium", "albania", "cyprus", - "luxembourg", "andorra","malta", "liechtenstein", "san_marino", "monaco" }; - Float_t surfaces[nx] = { - 547030, 505580, 449964, 357021, 338145, - 324220, 312685, 301230, 255438, 244820, - 237500, 207600, 131940, 127711, 110910, - 103000, 93030, 89242, 83870, 70280, - 65200, 64589, 45226, 43094, 41526, - 41290, 33843, 30528, 28748, 9250, - 2586, 468, 316, 160, 61, 2}; - - TH1F *h = new TH1F("h","Countries surfaces (in km^{2})",3,0,3); - for (i=0; iFill(countries[i], surfaces[i]); + "france", "spain", "sweden", "germany", "finland", "norway", "poland", "italy", + "yugoslavia", "united_kingdom", "romania", "belarus", "greece", "czechoslovakia", "bulgaria", "iceland", + "hungary", "portugal", "austria", "ireland", "lithuania", "latvia", "estonia", "denmark", + "netherlands", "switzerland", "moldova", "belgium", "albania", "cyprus", "luxembourg", "andorra", + "malta", "liechtenstein", "san_marino", "monaco"}; + Float_t surfaces[nx] = {547030, 505580, 449964, 357021, 338145, 324220, 312685, 301230, 255438, + 244820, 237500, 207600, 131940, 127711, 110910, 103000, 93030, 89242, + 83870, 70280, 65200, 64589, 45226, 43094, 41526, 41290, 33843, + 30528, 28748, 9250, 2586, 468, 316, 160, 61, 2}; + + TH1F *h = new TH1F("h", "Countries surfaces (in km^{2})", 3, 0, 3); + for (i = 0; i < nx; i++) + h->Fill(countries[i], surfaces[i]); h->LabelsDeflate(); TFile::SetCacheFileDir("."); TFile *f; - f = TFile::Open("http://root.cern/files/europe.root","cacheread"); + f = TFile::Open("http://root.cern/files/europe.root", "cacheread"); if (!f) { printf("Cannot access europe.root. Is internet working ?\n"); return; } - TH2Poly *p = new TH2Poly( - "Europe", - "Europe (bin contents are normalized to the surfaces in km^{2})", - lon1,lon2,lat1,lat2); + TH2Poly *p = + new TH2Poly("Europe", "Europe (bin contents are normalized to the surfaces in km^{2})", lon1, lon2, lat1, lat2); p->GetXaxis()->SetNdivisions(520); p->GetXaxis()->SetTitle("longitude"); p->GetYaxis()->SetTitle("latitude"); @@ -88,17 +82,17 @@ void th2polyEurope(Int_t npoints=500000) TMultiGraph *mg; TKey *key; TIter nextkey(gDirectory->GetListOfKeys()); - while ((key = (TKey*)nextkey())) { + while ((key = (TKey *)nextkey())) { TObject *obj = key->ReadObj(); if (obj->InheritsFrom("TMultiGraph")) { - mg = (TMultiGraph*)obj; + mg = (TMultiGraph *)obj; p->AddBin(mg); } } TRandom r; Double_t longitude, latitude; - Double_t x, y, pi4 = TMath::Pi()/4, alpha = TMath::Pi()/360; + Double_t x, y, pi4 = TMath::Pi() / 4, alpha = TMath::Pi() / 360; gBenchmark->Start("Partitioning"); p->ChangePartition(100, 100); @@ -106,45 +100,45 @@ void th2polyEurope(Int_t npoints=500000) // Fill TH2Poly according to a Mercator projection. gBenchmark->Start("Filling"); - for (i=0; iFill(x,y); + for (i = 0; i < npoints; i++) { + longitude = r.Uniform(lon1, lon2); + latitude = r.Uniform(lat1, lat2); + x = longitude; + y = 38 * TMath::Log(TMath::Tan(pi4 + alpha * latitude)); + p->Fill(x, y); } gBenchmark->Show("Filling"); Int_t nbins = p->GetNumberOfBins(); Double_t maximum = p->GetMaximum(); - // h2 contains the surfaces computed from TH2Poly. TH1F *h2 = (TH1F *)h->Clone("h2"); h2->Reset(); - for (j=0; jGetBinName(i+1))) { - h2->Fill(countries[j],p->GetBinContent(i+1)); - h2->SetBinError(j, p->GetBinError(i+1)); + for (j = 0; j < nx; j++) { + for (i = 0; i < nbins; i++) { + if (strstr(countries[j], p->GetBinName(i + 1))) { + h2->Fill(countries[j], p->GetBinContent(i + 1)); + h2->SetBinError(j, p->GetBinError(i + 1)); } } } // Normalize the TH2Poly bin contents to the real surfaces. - Double_t scale = surfaces[0]/maximum; - for (i=0; iSetBinContent(i+1, scale*p->GetBinContent(i+1)); + Double_t scale = surfaces[0] / maximum; + for (i = 0; i < nbins; i++) + p->SetBinContent(i + 1, scale * p->GetBinContent(i + 1)); gStyle->SetOptStat(1111); p->Draw("COLZ"); - TCanvas *c1 = new TCanvas("c1", "c1",W+10,0,W-20,H); + TCanvas *c1 = new TCanvas("c1", "c1", W + 10, 0, W - 20, H); c1->SetRightMargin(0.047); - scale = h->GetMaximum()/h2->GetMaximum(); + scale = h->GetMaximum() / h2->GetMaximum(); h->SetStats(0); - h->SetLineColor(kRed-3); + h->SetLineColor(kRed - 3); h->SetLineWidth(2); h->SetMarkerStyle(20); h->SetMarkerColor(kBlue); @@ -155,22 +149,24 @@ void th2polyEurope(Int_t npoints=500000) h->GetYaxis()->SetLabelFont(42); h2->Scale(scale); - Double_t scale2=TMath::Sqrt(scale); - for (i=0; iSetBinError(i+1, scale2*h2->GetBinError(i+1)); + Double_t scale2 = TMath::Sqrt(scale); + for (i = 0; i < nx; i++) + h2->SetBinError(i + 1, scale2 * h2->GetBinError(i + 1)); h2->Draw("E SAME"); h2->SetMarkerStyle(20); h2->SetMarkerSize(0.8); - TLegend *leg = new TLegend(0.5,0.67,0.92,0.8,nullptr,"NDC"); + TLegend *leg = new TLegend(0.5, 0.67, 0.92, 0.8, nullptr, "NDC"); leg->SetTextFont(42); leg->SetTextSize(0.025); - leg->AddEntry(h,"Real countries surfaces from Wikipedia (in km^{2})","lp"); - leg->AddEntry(h2,"Countries surfaces from TH2Poly (with errors)","lp"); + leg->AddEntry(h, "Real countries surfaces from Wikipedia (in km^{2})", "lp"); + leg->AddEntry(h2, "Countries surfaces from TH2Poly (with errors)", "lp"); leg->Draw(); leg->Draw(); Double_t wikiSum = h->Integral(); Double_t polySum = h2->Integral(); - Double_t error = TMath::Abs(wikiSum-polySum)/wikiSum; - printf("THPoly Europe surface estimation error wrt wikipedia = %f per cent when using %d points\n",100*error,npoints); + Double_t error = TMath::Abs(wikiSum - polySum) / wikiSum; + printf("THPoly Europe surface estimation error wrt wikipedia = %f per cent when using %d points\n", 100 * error, + npoints); } diff --git a/tutorials/hist/tprofile2polyRealistic.C b/tutorials/hist/hist041_TProfile2Poly_realistic.C similarity index 82% rename from tutorials/hist/tprofile2polyRealistic.C rename to tutorials/hist/hist041_TProfile2Poly_realistic.C index aae6c6a648dc4..74820e61986a3 100644 --- a/tutorials/hist/tprofile2polyRealistic.C +++ b/tutorials/hist/hist041_TProfile2Poly_realistic.C @@ -6,6 +6,7 @@ /// \macro_image /// \macro_code /// +/// \date November 2022 /// \author Filip Ilic #include @@ -16,14 +17,14 @@ #include #include -void tprofile2polyRealistic(Int_t numEvents=100000) +void hist041_TProfile2Poly_realistic(Int_t numEvents = 100000) { int NUM_LS = 8; TCanvas *c1 = new TCanvas("c1", "moving charge", 900, 400); TCanvas *c2 = new TCanvas("c2", "Merge Individual moving charge plots", 800, 400); c1->Divide(NUM_LS, 3); - c2->Divide(3,1); + c2->Divide(3, 1); // -------------------- Construct Reference plot bins ------------------------ auto new_avg = new TProfile2Poly(); @@ -60,7 +61,7 @@ void tprofile2polyRealistic(Int_t numEvents=100000) if (!infile) // Verify that the file was open successfully { - std::cerr << dir.Data() << std::endl; // Report error + std::cerr << dir.Data() << std::endl; // Report error std::cerr << "Error code: " << std::strerror(errno) << std::endl; // Get some info as to why return; } @@ -68,7 +69,7 @@ void tprofile2polyRealistic(Int_t numEvents=100000) std::vector> allCoords; Double_t a, b; - while (infile >> a >> b) + while (infile >> a >> b) allCoords.emplace_back(a, b); if (allCoords.size() % 3 != 0) { @@ -89,8 +90,8 @@ void tprofile2polyRealistic(Int_t numEvents=100000) det_err_merge->AddBin(3, x, y); for (int l = 0; l < NUM_LS; ++l) { - det_avg_ls[l].AddBin(3, x, y); - det_err_ls[l].AddBin(3, x, y); + det_avg_ls[l].AddBin(3, x, y); + det_err_ls[l].AddBin(3, x, y); } } @@ -105,9 +106,9 @@ void tprofile2polyRealistic(Int_t numEvents=100000) Double_t xoffset2 = 0; Double_t yoffset2 = 0; - for (int i = 0; i <= NUM_LS-1; ++i) { // LumiSection + for (int i = 0; i <= NUM_LS - 1; ++i) { // LumiSection std::cout << "[In Progress] LumiSection " << i << std::endl; - for (int j = 0; j < numEvents; ++j) { // Events + for (int j = 0; j < numEvents; ++j) { // Events Double_t r1 = ran.Gaus(0, 10); Double_t r2 = ran.Gaus(0, 8); Double_t rok = ran.Gaus(10, 1); @@ -122,14 +123,12 @@ void tprofile2polyRealistic(Int_t numEvents=100000) xoffset2 += 0.00003; yoffset2 += 0.00004; - if (r2 > 3. - yoffset1 && r2 < 8. - yoffset1 && - r1 > 1. + xoffset1 && r1 < 5. + xoffset1 ) { - val -= rbad1; + if (r2 > 3. - yoffset1 && r2 < 8. - yoffset1 && r1 > 1. + xoffset1 && r1 < 5. + xoffset1) { + val -= rbad1; } - if (r2 > -10 + yoffset2 && r2 < -8 + yoffset2 && - r1 > -6 + xoffset2 && r1 < 8 + xoffset2 ) { - val -= rbad2; + if (r2 > -10 + yoffset2 && r2 < -8 + yoffset2 && r1 > -6 + xoffset2 && r1 < 8 + xoffset2) { + val -= rbad2; } tot_avg_ls[i].Fill(r1, r2, val); @@ -139,21 +138,21 @@ void tprofile2polyRealistic(Int_t numEvents=100000) std::string title; - c1->cd(i+1); + c1->cd(i + 1); title = "Global View: Avg in LS " + std::to_string(i); tot_avg_ls[i].SetTitle(title.c_str()); tot_avg_ls[i].SetStats(false); tot_avg_ls[i].Draw("COLZ"); c1->Update(); - c1->cd((i+1)+NUM_LS); + c1->cd((i + 1) + NUM_LS); title = "Detector View: Avg in LS " + std::to_string(i); det_avg_ls[i].SetTitle(title.c_str()); det_avg_ls[i].SetStats(false); det_avg_ls[i].Draw("COLZ"); c1->Update(); - c1->cd((i+1)+(NUM_LS*2)); + c1->cd((i + 1) + (NUM_LS * 2)); title = "Detector View: Error in LS " + std::to_string(i); det_err_ls[i].SetTitle(title.c_str()); det_err_ls[i].SetStats(false); @@ -162,11 +161,11 @@ void tprofile2polyRealistic(Int_t numEvents=100000) c1->Update(); } - std::vector tot_avg_v; - std::vector det_avg_v; - for (int t = 0; t < NUM_LS; t++){ - tot_avg_v.push_back(&tot_avg_ls[t]); - det_avg_v.push_back(&det_avg_ls[t]); + std::vector tot_avg_v; + std::vector det_avg_v; + for (int t = 0; t < NUM_LS; t++) { + tot_avg_v.push_back(&tot_avg_ls[t]); + det_avg_v.push_back(&det_avg_ls[t]); } std::cout << "[In Progress] Merging" << std::endl; diff --git a/tutorials/hist/tprofile2polyRealisticModuleError.C b/tutorials/hist/hist042_TProfile2Poly_module_error.C similarity index 83% rename from tutorials/hist/tprofile2polyRealisticModuleError.C rename to tutorials/hist/hist042_TProfile2Poly_module_error.C index 75752b2285478..c2cc1445dc9e0 100644 --- a/tutorials/hist/tprofile2polyRealisticModuleError.C +++ b/tutorials/hist/hist042_TProfile2Poly_module_error.C @@ -6,13 +6,14 @@ /// \macro_image /// \macro_code /// +/// \date November 2022 /// \author Filip Ilic #include #include #include -void tprofile2polyRealisticModuleError(Int_t numEvents = 1000000) +void hist042_TProfile2Poly_module_error(Int_t numEvents = 1000000) { TCanvas *c1 = new TCanvas("c1", "4 Malfunctioning Panels", 800, 400); c1->Divide(3, 1); @@ -29,14 +30,14 @@ void tprofile2polyRealisticModuleError(Int_t numEvents = 1000000) if (!infile) // Verify that the file was open successfully { - std::cerr << dir.Data() << std::endl; // Report error + std::cerr << dir.Data() << std::endl; // Report error std::cerr << "Error code: " << std::strerror(errno) << std::endl; // Get some info as to why return; } std::vector> allCoords; Double_t a, b; - while (infile >> a >> b) + while (infile >> a >> b) allCoords.emplace_back(a, b); if (allCoords.size() % 3 != 0) { @@ -68,10 +69,14 @@ void tprofile2polyRealisticModuleError(Int_t numEvents = 1000000) Double_t val = rok; // -------------------- Malfunctioning panels ------------------- - if (th2p->IsInsideBin(4, r1, r2)) val = rok - rbad1; - if (th2p->IsInsideBin(20, r1, r2)) val = rok - rbad2; - if (th2p->IsInsideBin(13, r1, r2)) val = rok + rbad1; - if (th2p->IsInsideBin(37, r1, r2)) val = rok + rbad2; + if (th2p->IsInsideBin(4, r1, r2)) + val = rok - rbad1; + if (th2p->IsInsideBin(20, r1, r2)) + val = rok - rbad2; + if (th2p->IsInsideBin(13, r1, r2)) + val = rok + rbad1; + if (th2p->IsInsideBin(37, r1, r2)) + val = rok + rbad2; // -------------------- Fill histograms ------------------------ th2p->Fill(r1, r2, val); diff --git a/tutorials/hist/hlHisto1.C b/tutorials/hist/hist043_Graphics_highlight.C similarity index 77% rename from tutorials/hist/hlHisto1.C rename to tutorials/hist/hist043_Graphics_highlight.C index 48103722b86bc..2f1ab73089aa3 100644 --- a/tutorials/hist/hlHisto1.C +++ b/tutorials/hist/hist043_Graphics_highlight.C @@ -16,33 +16,35 @@ TText *info = nullptr; void HighlightTitle(TVirtualPad *pad, TObject *obj, Int_t xhb, Int_t yhb) { - auto h2 = dynamic_cast(obj); - if (!h2) return; + auto h2 = dynamic_cast(obj); + if (!h2) + return; if (!h2->IsHighlight()) { // after highlight disabled h2->SetTitle("Disable highlight"); return; } - if (info) info->SetTitle(""); + if (info) + info->SetTitle(""); TString t; - t.Form("bin[%02d, %02d] (%5.2f, %5.2f) content %g", xhb, yhb, - h2->GetXaxis()->GetBinCenter(xhb), h2->GetYaxis()->GetBinCenter(yhb), - h2->GetBinContent(xhb, yhb)); + t.Form("bin[%02d, %02d] (%5.2f, %5.2f) content %g", xhb, yhb, h2->GetXaxis()->GetBinCenter(xhb), + h2->GetYaxis()->GetBinCenter(yhb), h2->GetBinContent(xhb, yhb)); h2->SetTitle(t.Data()); pad->Update(); } -void hlHisto1() +void hist043_Graphics_highlight() { auto c1 = new TCanvas(); c1->HighlightConnect("HighlightTitle(TVirtualPad*,TObject*,Int_t,Int_t)"); auto h2 = new TH2F("h2", "", 50, -5.0, 5.0, 50, -5.0, 5.0); - for (Int_t i = 0; i < 10000; i++) h2->Fill(gRandom->Gaus(), gRandom->Gaus()); + for (Int_t i = 0; i < 10000; i++) + h2->Fill(gRandom->Gaus(), gRandom->Gaus()); h2->Draw(); info = new TText(0.0, -4.0, "please move the mouse over the frame"); info->SetTextAlign(22); - info->SetTextColor(kRed+1); + info->SetTextColor(kRed + 1); info->SetBit(kCannotPick); info->Draw(); c1->Update(); diff --git a/tutorials/hist/hlHisto2.C b/tutorials/hist/hist044_Graphics_highlight2D.C similarity index 83% rename from tutorials/hist/hlHisto2.C rename to tutorials/hist/hist044_Graphics_highlight2D.C index 6abfccc6315fe..3b33f98aebfbe 100644 --- a/tutorials/hist/hlHisto2.C +++ b/tutorials/hist/hist044_Graphics_highlight2D.C @@ -18,15 +18,18 @@ TText *info = nullptr; void Highlight2(TVirtualPad *pad, TObject *obj, Int_t xhb, Int_t yhb) { auto h2 = dynamic_cast(obj); - if(!h2) return; - auto CanvasProj = (TCanvas *) gROOT->GetListOfCanvases()->FindObject("CanvasProj"); + if (!h2) + return; + auto CanvasProj = (TCanvas *)gROOT->GetListOfCanvases()->FindObject("CanvasProj"); if (!h2->IsHighlight()) { // after highlight disabled - if (CanvasProj) delete CanvasProj; + if (CanvasProj) + delete CanvasProj; h2->SetTitle("Disable highlight"); return; } - if (info) info->SetTitle(""); + if (info) + info->SetTitle(""); auto px = h2->ProjectionX("_px", yhb, yhb); auto py = h2->ProjectionY("_py", xhb, xhb); @@ -51,23 +54,23 @@ void Highlight2(TVirtualPad *pad, TObject *obj, Int_t xhb, Int_t yhb) CanvasProj->Update(); } -void hlHisto2() +void hist044_Graphics_highlight2D() { auto c1 = new TCanvas("Canvas", "Canvas", 0, 0, 500, 500); c1->HighlightConnect("Highlight2(TVirtualPad*,TObject*,Int_t,Int_t)"); auto h2 = new TH2F("h2", "", 50, -5.0, 5.0, 50, -5.0, 5.0); - for (Int_t i = 0; i < 10000; i++) h2->Fill(gRandom->Gaus(), gRandom->Gaus()); + for (Int_t i = 0; i < 10000; i++) + h2->Fill(gRandom->Gaus(), gRandom->Gaus()); h2->Draw("col"); info = new TText(0.0, -4.0, "please move the mouse over the frame"); info->SetTextAlign(22); info->SetTextSize(0.04); - info->SetTextColor(kRed+1); + info->SetTextColor(kRed + 1); info->SetBit(kCannotPick); info->Draw(); c1->Update(); h2->SetHighlight(); } - diff --git a/tutorials/hist/hlHisto3.C b/tutorials/hist/hist045_Graphics_highlight_ntuple.C similarity index 79% rename from tutorials/hist/hlHisto3.C rename to tutorials/hist/hist045_Graphics_highlight_ntuple.C index 9f1c694448eec..7e5f1f6f42143 100644 --- a/tutorials/hist/hlHisto3.C +++ b/tutorials/hist/hist045_Graphics_highlight_ntuple.C @@ -25,7 +25,7 @@ TList *InitGraphs(TNtuple *nt, TH1F *histo, Bool_t is_top) Int_t nbins = histo->GetNbinsX(); for (Int_t bin = 0; bin < nbins; bin++) { auto g = new TGraph(); - g->SetName(TString::Format("g%sbin_%d", histo->GetName(), bin+1)); + g->SetName(TString::Format("g%sbin_%d", histo->GetName(), bin + 1)); g->SetBit(kCannotPick); g->SetMarkerStyle(25); g->SetMarkerColor(histo->GetLineColor()); @@ -33,10 +33,11 @@ TList *InitGraphs(TNtuple *nt, TH1F *histo, Bool_t is_top) } for (Long64_t ie = 0; ie < nev; ie++) { - Double_t value = is_top ? pz[ie] : px[ie]*py[ie]*pz[ie]; + Double_t value = is_top ? pz[ie] : px[ie] * py[ie] * pz[ie]; Int_t bin = histo->FindBin(value) - 1; auto g = dynamic_cast(list->At(bin)); - if (g) g->SetPoint(g->GetN(), py[ie], px[ie]); + if (g) + g->SetPoint(g->GetN(), py[ie], px[ie]); } return list; @@ -45,45 +46,54 @@ TList *InitGraphs(TNtuple *nt, TH1F *histo, Bool_t is_top) void Highlight3(TVirtualPad *pad, TObject *obj, Int_t xhb, Int_t yhb) { auto histo = dynamic_cast(obj); - if(!histo) return; + if (!histo) + return; TCanvas *Canvas2 = (TCanvas *)gROOT->GetListOfCanvases()->FindObject("Canvas2"); - if (!Canvas2) return; + if (!Canvas2) + return; TGraph *gcommon = (TGraph *)Canvas2->FindObject("Graph"); - if (!gcommon) return; + if (!gcommon) + return; TList *list = nullptr; if (!strcmp(histo->GetName(), "histo1")) list = list1; else if (!strcmp(histo->GetName(), "histo2")) list = list2; - if (!list) return; + if (!list) + return; TGraph *g = (TGraph *)list->At(xhb); - if (!g) return; + if (!g) + return; TVirtualPad *savepad = gPad; Canvas2->cd(); gcommon->Draw("AP"); - //gcommon->SetTitle(TString::Format("%d / %d", g->GetN(), gcommon->GetN())); + // gcommon->SetTitle(TString::Format("%d / %d", g->GetN(), gcommon->GetN())); if (histo->IsHighlight()) // don't draw g after highlight disabled if (g->GetN() > 0) g->Draw("P"); Canvas2->Update(); - if (savepad) savepad->cd(); + if (savepad) + savepad->cd(); } -void hlHisto3() +void hist045_Graphics_highlight_ntuple() { auto dir = gROOT->GetTutorialDir(); dir.Append("/hsimple.C"); - dir.ReplaceAll("/./","/"); - if (!gInterpreter->IsLoaded(dir.Data())) gInterpreter->LoadMacro(dir.Data()); - auto file = (TFile*)gROOT->ProcessLineFast("hsimple(1)"); - if (!file) return; + dir.ReplaceAll("/./", "/"); + if (!gInterpreter->IsLoaded(dir.Data())) + gInterpreter->LoadMacro(dir.Data()); + auto file = (TFile *)gROOT->ProcessLineFast("hsimple(1)"); + if (!file) + return; TNtuple *ntuple; file->GetObject("ntuple", ntuple); - if (!ntuple) return; + if (!ntuple) + return; const char *cut = "pz > 3.0"; TCanvas *Canvas1 = new TCanvas("Canvas1", "Canvas1", 0, 0, 700, 500); @@ -96,8 +106,7 @@ void hlHisto3() Canvas1->cd(1); ntuple->Draw("pz>>histo1(100, 2.0, 12.0)", cut); auto histo1 = (TH1F *)gPad->FindObject("histo1"); - auto info1 = new TText(7.0, histo1->GetMaximum()*0.6, - "please move the mouse over the frame"); + auto info1 = new TText(7.0, histo1->GetMaximum() * 0.6, "please move the mouse over the frame"); info1->SetTextColor(histo1->GetLineColor()); info1->SetBit(kCannotPick); info1->Draw(); @@ -106,8 +115,8 @@ void hlHisto3() Canvas1->cd(2); ntuple->Draw("(px*py*pz)>>histo2(100, -50.0, 50.0)", cut); auto histo2 = (TH1F *)gPad->FindObject("histo2"); - histo2->SetLineColor(kGreen+2); - auto info2 = new TText(10.0, histo2->GetMaximum()*0.6, info1->GetTitle()); + histo2->SetLineColor(kGreen + 2); + auto info2 = new TText(10.0, histo2->GetMaximum() * 0.6, info1->GetTitle()); info2->SetTextColor(histo2->GetLineColor()); info2->SetBit(kCannotPick); info2->Draw(); diff --git a/tutorials/hist/hlHisto4.C b/tutorials/hist/hist046_Graphics_highlight1D.C similarity index 78% rename from tutorials/hist/hlHisto4.C rename to tutorials/hist/hist046_Graphics_highlight1D.C index c90b2c436d29d..976b834b07a08 100644 --- a/tutorials/hist/hlHisto4.C +++ b/tutorials/hist/hist046_Graphics_highlight1D.C @@ -18,21 +18,28 @@ TH1 *hz = nullptr; void HighlightZoom(TVirtualPad *pad, TObject *obj, Int_t xhb, Int_t yhb) { auto h = dynamic_cast(obj); - if(!h) return; + if (!h) + return; auto Canvas2 = (TCanvas *)gROOT->GetListOfCanvases()->FindObject("Canvas2"); if (!h->IsHighlight()) { // after highlight disabled - if (Canvas2) delete Canvas2; - if (hz) { delete hz; hz = nullptr; } + if (Canvas2) + delete Canvas2; + if (hz) { + delete hz; + hz = nullptr; + } return; } - if (info) info->SetTitle(""); + if (info) + info->SetTitle(""); if (!Canvas2) { Canvas2 = new TCanvas("Canvas2", "Canvas2", 605, 0, 400, 400); Canvas2->SetGrid(); - if (hz) hz->Draw(); // after reopen this canvas + if (hz) + hz->Draw(); // after reopen this canvas } if (!hz) { hz = (TH1 *)h->Clone("hz"); @@ -43,14 +50,14 @@ void HighlightZoom(TVirtualPad *pad, TObject *obj, Int_t xhb, Int_t yhb) hz->SetHighlight(kFALSE); } - Int_t zf = hz->GetNbinsX()*0.05; // zoom factor - hz->GetXaxis()->SetRange(xhb-zf, xhb+zf); + Int_t zf = hz->GetNbinsX() * 0.05; // zoom factor + hz->GetXaxis()->SetRange(xhb - zf, xhb + zf); Canvas2->Modified(); Canvas2->Update(); } -void hlHisto4() +void hist046_Graphics_highlight1D() { auto Canvas1 = new TCanvas("Canvas1", "", 0, 0, 600, 400); Canvas1->HighlightConnect("HighlightZoom(TVirtualPad*,TObject*,Int_t,Int_t)"); @@ -64,10 +71,10 @@ void hlHisto4() gStyle->SetGridColor(kGray); Canvas1->SetGrid(); - info = new TText(0.0, h1->GetMaximum()*0.7, "please move the mouse over the frame"); + info = new TText(0.0, h1->GetMaximum() * 0.7, "please move the mouse over the frame"); info->SetTextSize(0.04); info->SetTextAlign(22); - info->SetTextColor(kRed-1); + info->SetTextColor(kRed - 1); info->SetBit(kCannotPick); info->Draw(); diff --git a/tutorials/hist/hist047_Graphics_candle_decay.C b/tutorials/hist/hist047_Graphics_candle_decay.C new file mode 100644 index 0000000000000..f8241729be184 --- /dev/null +++ b/tutorials/hist/hist047_Graphics_candle_decay.C @@ -0,0 +1,48 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Candle Decay, illustrate a time development of a certain value. +/// +/// \macro_image (tcanvas_js) +/// \macro_code +/// +/// \date November 2024 +/// \author Georg Troska, Alexandr Prozorov + +void hist047_Graphics_candle_decay() +{ + // create a new 2D histogram with x-axis title probability density and y-axis title time + // it is of a type TH2I (2D histogram with integer values) + auto *hist = new TH2I("hist", "Decay; probability density; time", 1000, 0, 1000, 20, 0, 20); + TRandom rand; // create a random number generator outside the loop to avoid reseeding + + for (int iBin = 0; iBin < 19; iBin++) { + for (int j = 0; j < 1000000; j++) { + // generate a random number from a 2D Gaussian distribution + // a simulation of a time development of a certain value + float myRand = rand.Gaus(350 + iBin * 8, 20 + 2 * iBin); + hist->Fill(myRand, iBin); + } + } + hist->SetBarWidth(3); + hist->SetFillStyle(0); + hist->SetFillColor(kGray); + hist->SetLineColor(kBlue); + // create a new canvas + auto *can = new TCanvas("can", "Candle Decay", 800, 600); + can->Divide(2, 1); // divide the canvas into 2 pads (2 rows, 1 column) + + can->cd(1); + hist->Draw("violiny(112000000)"); + can->cd(2); + auto *hist2 = static_cast(hist->Clone("hist2")); + hist2->SetBarWidth(0.8); + // There are six predefined candle-plot representations: (X can be replaced by Y) + // "CANDLEX1": Standard candle (whiskers cover the whole distribution) + // "CANDLEX2": Standard candle with better whisker definition + outliers. It is a good compromise + // "CANDLEX3": Like candle2 but with a mean as a circle. It is easier to distinguish mean and median + // "CANDLEX4": Like candle3 but showing the uncertainty of the median as well (notched candle plots). For bigger + // datasets per candle "CANDLEX5": Like candle2 but showing all data points. For very small datasets "CANDLEX6": + // Like candle2 but showing all datapoints scattered. For huge datasets + hist2->DrawCopy("candley2"); +} diff --git a/tutorials/hist/candlehisto.C b/tutorials/hist/hist048_Graphics_candle_hist.C similarity index 80% rename from tutorials/hist/candlehisto.C rename to tutorials/hist/hist048_Graphics_candle_hist.C index dfe3970cac7ec..a812560815b60 100644 --- a/tutorials/hist/candlehisto.C +++ b/tutorials/hist/hist048_Graphics_candle_hist.C @@ -6,9 +6,10 @@ /// \macro_image /// \macro_code /// +/// \date December 2017 /// \author Georg Troska -void candlehisto() +void hist048_Graphics_candle_hist() { TCanvas *c1 = new TCanvas("c1", "Candle Presets", 800, 600); c1->Divide(3, 2); @@ -18,7 +19,7 @@ void candlehisto() h1->GetXaxis()->SetTitle("Deg"); float myRand; - for (int i = 0; i < 360; i+= 10) { + for (int i = 0; i < 360; i += 10) { for (int j = 0; j < 100; j++) { myRand = rng->Gaus(sin(i * 3.14 / 180), 0.2); h1->Fill(i, myRand); @@ -28,7 +29,7 @@ void candlehisto() for (int i = 1; i < 7; i++) { c1->cd(i); TString title = TString::Format("CANDLEX%d", i); - TH2I *myhist = (TH2I*)h1->DrawCopy(title); + TH2I *myhist = (TH2I *)h1->DrawCopy(title); myhist->SetTitle(title); } @@ -38,7 +39,7 @@ void candlehisto() for (int i = 1; i < 3; i++) { c2->cd(i); TString title = TString::Format("VIOLINX%d", i); - TH2I *myhist = (TH2I*)h1->DrawCopy(title); + TH2I *myhist = (TH2I *)h1->DrawCopy(title); myhist->SetFillColor(kGray + 2); } @@ -48,16 +49,16 @@ void candlehisto() for (int i = 0; i < 6; i++) { c3->cd(i + 1); TString title = TString::Format("candlex(%s)", myopt[i].Data()); - TH2I *myhist = (TH2I*)h1->DrawCopy(title); + TH2I *myhist = (TH2I *)h1->DrawCopy(title); myhist->SetFillColor(kYellow); if (i == 4) { - TH2I *myhist2 = (TH2I*)h1->DrawCopy("candlex(1000000) same"); + TH2I *myhist2 = (TH2I *)h1->DrawCopy("candlex(1000000) same"); myhist2->SetFillColor(kRed); } if (i == 5) { myhist->SetBarWidth(0.2); myhist->SetBarOffset(0.25); - TH2I *myhist2 = (TH2I*)h1->DrawCopy("candlex(2000000) same"); + TH2I *myhist2 = (TH2I *)h1->DrawCopy("candlex(2000000) same"); myhist2->SetFillColor(kRed); myhist2->SetBarWidth(0.6); myhist2->SetBarOffset(-0.5); diff --git a/tutorials/hist/candleplot.C b/tutorials/hist/hist049_Graphics_candle_plot.C similarity index 52% rename from tutorials/hist/candleplot.C rename to tutorials/hist/hist049_Graphics_candle_plot.C index a51791788ac2b..23b010094a3b3 100644 --- a/tutorials/hist/candleplot.C +++ b/tutorials/hist/hist049_Graphics_candle_plot.C @@ -6,16 +6,18 @@ /// \macro_image /// \macro_code /// +/// \date May 2024 /// \author Georg Troska -void candleplot() { +void hist049_Graphics_candle_plot() +{ gStyle->SetTimeOffset(0); - TDatime dateBegin(2010,1,1,0,0,0); - TDatime dateEnd(2011,1,1,0,0,0); + TDatime dateBegin(2010, 1, 1, 0, 0, 0); + TDatime dateEnd(2011, 1, 1, 0, 0, 0); - auto h1 = new TH2I("h1","Machine A + B",12,dateBegin.Convert(),dateEnd.Convert(),1000,0,1000); - auto h2 = new TH2I("h2","Machine B",12,dateBegin.Convert(),dateEnd.Convert(),1000,0,1000); + auto h1 = new TH2I("h1", "Machine A + B", 12, dateBegin.Convert(), dateEnd.Convert(), 1000, 0, 1000); + auto h2 = new TH2I("h2", "Machine B", 12, dateBegin.Convert(), dateEnd.Convert(), 1000, 0, 1000); h1->GetXaxis()->SetTimeDisplay(1); h1->GetXaxis()->SetTimeFormat("%d/%m/%y"); @@ -23,10 +25,12 @@ void candleplot() { h1->GetXaxis()->SetTitle("Date [day/month/year]"); float Rand; - for (int i = dateBegin.Convert(); i < dateEnd.Convert(); i+=86400*30) { + for (int i = dateBegin.Convert(); i < dateEnd.Convert(); i += 86400 * 30) { for (int j = 0; j < 1000; j++) { - Rand = gRandom->Gaus(500+sin(i/10000000.)*100,50); h1->Fill(i,Rand); - Rand = gRandom->Gaus(500+sin(i/11000000.)*100,70); h2->Fill(i,Rand); + Rand = gRandom->Gaus(500 + sin(i / 10000000.) * 100, 50); + h1->Fill(i, Rand); + Rand = gRandom->Gaus(500 + sin(i / 11000000.) * 100, 70); + h2->Fill(i, Rand); } } @@ -45,5 +49,5 @@ void candleplot() { h1->Draw("candle2"); h2->Draw("candle3 same"); - gPad->BuildLegend(0.78,0.695,0.980,0.935,"","f"); + gPad->BuildLegend(0.78, 0.695, 0.980, 0.935, "", "f"); } diff --git a/tutorials/hist/hist050_Graphics_candle_plot_options.C b/tutorials/hist/hist050_Graphics_candle_plot_options.C new file mode 100644 index 0000000000000..50e57a54408bc --- /dev/null +++ b/tutorials/hist/hist050_Graphics_candle_plot_options.C @@ -0,0 +1,46 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Example showing how to combine the various candle plot options. +/// +/// \macro_image +/// \macro_code +/// +/// \date December 2017 +/// \author Georg Troska + +void hist050_Graphics_candle_plot_options() +{ + TCanvas *c1 = new TCanvas("c1", "Candle Presets", 800, 600); + c1->Divide(3, 2); + + TRandom *rng = new TRandom(); + TH2I *h1 = new TH2I("h1", "Sin", 18, 0, 360, 300, -1.5, 1.5); + h1->GetXaxis()->SetTitle("Deg"); + float myRand; + for (int i = 0; i < 360; i += 10) { + for (int j = 0; j < 100; j++) { + myRand = rng->Gaus(sin(i * 3.14 / 180), 0.2); + h1->Fill(i, myRand); + } + } + for (int i = 1; i < 7; i++) { + c1->cd(i); + char str[16]; + sprintf(str, "candlex%d", i); + TH2I *myhist = (TH2I *)h1->DrawCopy(str); + myhist->SetTitle(str); + } + + TCanvas *c2 = new TCanvas("c2", "Candle Individual", 800, 600); + c2->Divide(4, 4); + char myopt[16][8] = {"0", "1", "11", "21", "31", "30", "111", "311", + "301", "1111", "2321", "12111", "112111", "212111", "312111"}; + for (int i = 0; i < 15; i++) { + c2->cd(i + 1); + char str[16]; + sprintf(str, "candlex(%s)", myopt[i]); + TH2I *myhist = (TH2I *)h1->DrawCopy(str); + myhist->SetTitle(str); + } +} diff --git a/tutorials/hist/hist051_Graphics_candle_plot_stack.C b/tutorials/hist/hist051_Graphics_candle_plot_stack.C new file mode 100644 index 0000000000000..24cb3bbe198e3 --- /dev/null +++ b/tutorials/hist/hist051_Graphics_candle_plot_stack.C @@ -0,0 +1,55 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Example showing how a THStack with candle plot option. +/// +/// \macro_image +/// \macro_code +/// +/// \date May 2024 +/// \authors Georg Troska, Olivier Couet + +void hist051_Graphics_candle_plot_stack() +{ + gStyle->SetTimeOffset(0); + auto rng = new TRandom(); + auto dateBegin = new TDatime(2010, 1, 1, 0, 0, 0); + auto dateEnd = new TDatime(2011, 1, 1, 0, 0, 0); + int bins = 1000; + auto h1 = new TH2I("h1", "Machine A", 6, dateBegin->Convert(), dateEnd->Convert(), bins, 0, 1000); + auto h2 = new TH2I("h2", "Machine B", 6, dateBegin->Convert(), dateEnd->Convert(), bins, 0, 1000); + auto hsum = new TH2I("h4", "Sum", 6, dateBegin->Convert(), dateEnd->Convert(), bins, 0, 1000); + + float Rand; + for (int i = dateBegin->Convert(); i < dateEnd->Convert(); i += 86400 * 30) { + for (int j = 0; j < 1000; j++) { + Rand = rng->Gaus(500 + sin(i / 10000000.) * 100, 50); + h1->Fill(i, Rand); + hsum->Fill(i, Rand); + Rand = rng->Gaus(500 + sin(i / 12000000.) * 100, 50); + h2->Fill(i, Rand); + hsum->Fill(i, Rand); + } + } + + h2->SetLineColor(kRed); + hsum->SetFillColor(kGreen); + TCanvas *c1 = new TCanvas(); + + auto hs = new THStack("hs", "Machine A+B"); + hs->Add(h1); + hs->Add(h2, "candle2"); + hs->Add(hsum, "violin1"); + hs->Draw("candle3"); + hs->GetXaxis()->SetNdivisions(410); + + gPad->SetGrid(1, 0); + + hs->GetXaxis()->SetTimeDisplay(1); + hs->GetXaxis()->SetTimeFormat("%d/%m/%y"); + hs->GetXaxis()->SetNdivisions(-6); + hs->GetXaxis()->SetTitle("Date [day/month/year]"); + c1->Modified(); + + gPad->BuildLegend(0.75, 0.75, 0.95, 0.95, ""); +} diff --git a/tutorials/hist/hist052_Graphics_candle_plot_whiskers.C b/tutorials/hist/hist052_Graphics_candle_plot_whiskers.C new file mode 100644 index 0000000000000..fe48c64d78938 --- /dev/null +++ b/tutorials/hist/hist052_Graphics_candle_plot_whiskers.C @@ -0,0 +1,92 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Example of candle plot showing the whiskers definition. +/// +/// \macro_image +/// \macro_output +/// \macro_code +/// +/// \date June 2022 +/// \author Georg Troska + +void hist052_Graphics_candle_plot_whiskers() +{ + auto c1 = new TCanvas("c1", "Candle Presets", 700, 800); + c1->Divide(1, 2); + + auto rng = new TRandom(); + auto h1 = new TH2I("h1", "Gaus", 100, -5, 5, 1, 0, 1); + auto h2 = new TH1I("h2", "Gaus", 100, -5, 5); + + h1->GetXaxis()->SetTitle("Standard deviation #sigma"); + h2->GetXaxis()->SetTitle("Standard deviation #sigma"); + h2->GetYaxis()->SetTitle("dN/d#sigma"); + + float myRand; + for (int i = 0; i < 100000; i++) { + myRand = rng->Gaus(0, 1); + h1->Fill(myRand, 0); + h2->Fill(myRand); + } + + Double_t *q = new Double_t[3]; + Double_t *p = new Double_t[3]; + q[0] = 0.; + q[1] = 0.; + q[2] = 0.; + p[0] = 0.25; + p[1] = 0.5; + p[2] = 0.75; + + h2->GetQuantiles(3, q, p); + cout << "Q1 (-25%): " << q[0] << " Median: " << q[1] << " Q3 (+25%): " << q[2] << endl; + double iqr = q[2] - q[0]; + auto mygaus_1_middle = new TF1("mygaus_1_middle", "gaus", q[0], q[2]); + auto mygaus_1_left = new TF1("mygaus_1_left", "gaus", q[0] - 1.5 * iqr, q[0]); + mygaus_1_left->SetLineColor(kGreen); + auto mygaus_1_right = new TF1("mygaus_1_right", "gaus", q[2], q[2] + 1.5 * iqr); + mygaus_1_right->SetLineColor(kGreen); + c1->cd(1); + h1->SetLineWidth(3); + h1->SetFillStyle(0); + h1->Draw("candley2 scat"); + + c1->cd(2); + h2->Draw(""); + h2->Fit("mygaus_1_left", "R"); + mygaus_1_left->Draw("same"); + auto l3 = new TLine(q[0] - 1.5 * iqr, 0, q[0] - 1.5 * iqr, mygaus_1_left->Eval(q[0] - 1.5 * iqr)); + l3->SetLineColor(kGreen); + l3->SetLineWidth(2); + l3->Draw(""); + auto l1 = new TLine(q[0], 0, q[0], mygaus_1_left->Eval(q[0])); + l1->SetLineWidth(2); + l1->SetLineColor(kGreen); + l1->Draw(""); + + h2->Fit("mygaus_1_right", "R", ""); + mygaus_1_right->Draw("same"); + auto l4 = new TLine(q[2] + 1.5 * iqr, 0, q[2] + 1.5 * iqr, mygaus_1_left->Eval(q[2] + 1.5 * iqr)); + l4->SetLineColor(kGreen); + l4->SetLineWidth(2); + l4->Draw(""); + auto l5 = new TLine(q[2], 0, q[2], mygaus_1_right->Eval(q[2])); + l5->SetLineWidth(2); + l5->SetLineColor(kGreen); + l5->Draw(""); + + h2->Fit("mygaus_1_middle", "R"); + mygaus_1_middle->Draw("same"); + + // In principal one could calculate these values by h2->Integral() as well + TText t; + t.SetTextFont(42); + t.DrawText(0, mygaus_1_middle->Eval(0) / 2, "50%"); + t.DrawText(-1.5, mygaus_1_middle->Eval(-1.5) / 2, "24.65%"); + t.DrawText(+1, mygaus_1_middle->Eval(+1.5) / 2, "24.65%"); + t.DrawText(q[0] - 1.5 * iqr, 1000, Form("%.3f", q[0] - 1.5 * iqr))->SetTextAngle(90); + t.DrawText(q[2] + 1.5 * iqr, 1000, Form("%.3f", q[2] + 1.5 * iqr))->SetTextAngle(90); + t.DrawText(q[0], 1000, Form("%.3f", q[0]))->SetTextAngle(90); + t.DrawText(q[2], 1000, Form("%.3f", q[2]))->SetTextAngle(90); +} diff --git a/tutorials/hist/candlescaled.C b/tutorials/hist/hist053_Graphics_candle_scaled.C similarity index 67% rename from tutorials/hist/candlescaled.C rename to tutorials/hist/hist053_Graphics_candle_scaled.C index ca78ff343b618..64146fddbd57d 100644 --- a/tutorials/hist/candlescaled.C +++ b/tutorials/hist/hist053_Graphics_candle_scaled.C @@ -7,18 +7,19 @@ /// \macro_image /// \macro_code /// +/// \date February 2023 /// \author Georg Troska -void candlescaled() +void hist053_Graphics_candle_scaled() { - TCanvas *c1 = new TCanvas("c1","TCandle Scaled",800,600); - c1->Divide(2,2); - TH2I *h1 = new TH2I("h1","GausXY",20,-5,5,100,-5,5); - TH2I *h3 = new TH2I("h3","GausXY",100,-5,5,20,-5,5); + TCanvas *c1 = new TCanvas("c1", "TCandle Scaled", 800, 600); + c1->Divide(2, 2); + TH2I *h1 = new TH2I("h1", "GausXY", 20, -5, 5, 100, -5, 5); + TH2I *h3 = new TH2I("h3", "GausXY", 100, -5, 5, 20, -5, 5); for (int j = 0; j < 100000; j++) { - auto myRand1 = gRandom->Gaus(0,1); - auto myRand2 = gRandom->Gaus(0,1); + auto myRand1 = gRandom->Gaus(0, 1); + auto myRand2 = gRandom->Gaus(0, 1); h1->Fill(myRand1, myRand2); h3->Fill(myRand1, myRand2); } @@ -35,13 +36,13 @@ void candlescaled() h3->DrawCopy("candleY2"); TCandle::SetScaledViolin(false); /* This is a global option for all existing violin, default is true */ - TH2I *h2 = (TH2I*)h1->Clone(); + TH2I *h2 = (TH2I *)h1->Clone(); h2->SetFillStyle(0); - h2->SetFillColor(kGray+2); + h2->SetFillColor(kGray + 2); h2->SetLineColor(kBlue); - TH2I *h4 = (TH2I*)h3->Clone(); + TH2I *h4 = (TH2I *)h3->Clone(); h4->SetFillStyle(0); - h4->SetFillColor(kGray+2); + h4->SetFillColor(kGray + 2); h4->SetLineColor(kBlue); c1->cd(3); diff --git a/tutorials/hist/logscales.C b/tutorials/hist/hist054_Graphics_logscales.C similarity index 52% rename from tutorials/hist/logscales.C rename to tutorials/hist/hist054_Graphics_logscales.C index 66986a508823a..022ec788832a3 100644 --- a/tutorials/hist/logscales.C +++ b/tutorials/hist/hist054_Graphics_logscales.C @@ -6,23 +6,27 @@ /// \macro_image /// \macro_code /// +/// \date July 2016 /// \author Olivier Couet -void logscales() { - TCanvas *c1 = new TCanvas("c1", "Various options on LOG scales plots",0,0,700,900); +void hist054_Graphics_logscales() +{ + TCanvas *c1 = new TCanvas("c1", "Various options on LOG scales plots", 0, 0, 700, 900); c1->SetFillColor(30); - TPad *pad1 = new TPad("pad1","pad1",0.03,0.62,0.50,0.92,32); - TPad *pad2 = new TPad("pad2","pad2",0.51,0.62,0.98,0.92,33); - TPad *pad3 = new TPad("pad3","pad3",0.03,0.02,0.97,0.535,38); - pad1->Draw(); pad2->Draw(); pad3->Draw(); + TPad *pad1 = new TPad("pad1", "pad1", 0.03, 0.62, 0.50, 0.92, 32); + TPad *pad2 = new TPad("pad2", "pad2", 0.51, 0.62, 0.98, 0.92, 33); + TPad *pad3 = new TPad("pad3", "pad3", 0.03, 0.02, 0.97, 0.535, 38); + pad1->Draw(); + pad2->Draw(); + pad3->Draw(); - TPaveLabel *title = new TPaveLabel(0.1,0.94,0.9,0.98, "Various options on LOG scales plots"); + TPaveLabel *title = new TPaveLabel(0.1, 0.94, 0.9, 0.98, "Various options on LOG scales plots"); title->SetFillColor(16); title->SetTextFont(42); title->Draw(); - TPaveText *pave = new TPaveText(0.1,0.55,0.9,0.61); + TPaveText *pave = new TPaveText(0.1, 0.55, 0.9, 0.61); pave->SetFillColor(42); pave->SetTextAlign(12); pave->SetTextFont(42); @@ -32,17 +36,20 @@ void logscales() { pad1->cd(); pad1->SetLogy(); pad1->SetGridy(); - TF1 *f1 = new TF1("f1","x*sin(x)*exp(-0.1*x)+15",-10.,10.); - TF1 *f2 = new TF1("f2","(sin(x)+cos(x))**5+15",-10.,10.); - TF1 *f3 = new TF1("f3","(sin(x)/(x)-x*cos(x))+15",-10.,10.); - f1->SetLineWidth(1); f1->SetLineColor(2); - f2->SetLineWidth(1); f2->SetLineColor(3); - f3->SetLineWidth(1); f3->SetLineColor(4); + TF1 *f1 = new TF1("f1", "x*sin(x)*exp(-0.1*x)+15", -10., 10.); + TF1 *f2 = new TF1("f2", "(sin(x)+cos(x))**5+15", -10., 10.); + TF1 *f3 = new TF1("f3", "(sin(x)/(x)-x*cos(x))+15", -10., 10.); + f1->SetLineWidth(1); + f1->SetLineColor(2); + f2->SetLineWidth(1); + f2->SetLineColor(3); + f3->SetLineWidth(1); + f3->SetLineColor(4); f1->Draw(); f2->Draw("same"); f3->Draw("same"); f1->GetYaxis()->SetMoreLogLabels(); - TPaveText *pave1 = new TPaveText(-6,2,6,6); + TPaveText *pave1 = new TPaveText(-6, 2, 6, 6); pave1->SetFillColor(42); pave1->SetTextAlign(12); pave1->SetTextFont(42); @@ -51,9 +58,9 @@ void logscales() { pave1->Draw(); pad2->cd(); - double x[10] = { 200, 300, 400, 500, 600, 650, 700, 710, 900,1000 }; - double y[10] = { 200, 1000, 900, 400, 500, 250, 800, 150, 201, 220 }; - TGraph *g_2 = new TGraph(10,x,y); + double x[10] = {200, 300, 400, 500, 600, 650, 700, 710, 900, 1000}; + double y[10] = {200, 1000, 900, 400, 500, 250, 800, 150, 201, 220}; + TGraph *g_2 = new TGraph(10, x, y); g_2->Draw("AL*"); g_2->SetMarkerColor(2); g_2->GetYaxis()->SetMoreLogLabels(); @@ -62,7 +69,7 @@ void logscales() { g_2->GetXaxis()->SetMoreLogLabels(); pad2->SetLogx(); pad2->SetGridx(); - TPaveText *pave2 = new TPaveText(150,80,500,180); + TPaveText *pave2 = new TPaveText(150, 80, 500, 180); pave2->SetFillColor(42); pave2->SetTextFont(42); pave2->SetTextAlign(12); @@ -76,30 +83,34 @@ void logscales() { pad3->SetGridy(); pad3->SetLogy(); pad3->SetLogx(); - TF1 *f4 = new TF1("f4a","x*sin(x+10)+25",1,21); + TF1 *f4 = new TF1("f4a", "x*sin(x+10)+25", 1, 21); f4->SetLineWidth(1); f4->Draw(); f4->SetNpx(200); f4->GetYaxis()->SetMoreLogLabels(); f4->GetXaxis()->SetMoreLogLabels(); - f4 = new TF1("f4b","x*cos(x+10)*sin(x+10)+25",1,21); - f4->SetLineWidth(1); f4->Draw("same"); + f4 = new TF1("f4b", "x*cos(x+10)*sin(x+10)+25", 1, 21); + f4->SetLineWidth(1); + f4->Draw("same"); f4->SetNpx(200); Int_t a = 20; - for (int i=a; i>=1; i--) { - f4 = new TF1(Form("f4b_%d",i),"x*sin(x+10)*[0]/[1]+25",1,21); - f4->SetParameter(0,i); - f4->SetParameter(1,a); + for (int i = a; i >= 1; i--) { + f4 = new TF1(Form("f4b_%d", i), "x*sin(x+10)*[0]/[1]+25", 1, 21); + f4->SetParameter(0, i); + f4->SetParameter(1, a); f4->SetNpx(200); - f4->SetLineWidth(1); f4->SetLineColor(i+10); + f4->SetLineWidth(1); + f4->SetLineColor(i + 10); f4->Draw("same"); - f4 = new TF1(Form("f4c_%d",i),"x*cos(x+10)*sin(x+10)*[0]/[1]+25",1,25); - f4->SetParameter(0,i); - f4->SetParameter(1,a); + f4 = new TF1(Form("f4c_%d", i), "x*cos(x+10)*sin(x+10)*[0]/[1]+25", 1, 25); + f4->SetParameter(0, i); + f4->SetParameter(1, a); f4->SetNpx(200); - f4->SetLineWidth(1); f4->SetLineColor(i+30); f4->Draw("same"); + f4->SetLineWidth(1); + f4->SetLineColor(i + 30); + f4->Draw("same"); } - TPaveText *pave3 = new TPaveText(1.2,8,9,15); + TPaveText *pave3 = new TPaveText(1.2, 8, 9, 15); pave3->SetFillColor(42); pave3->AddText("Log scale along X and Y axis."); pave3->SetTextFont(42); diff --git a/tutorials/hist/xyplot.C b/tutorials/hist/hist055_Graphics_xyplot.C similarity index 67% rename from tutorials/hist/xyplot.C rename to tutorials/hist/hist055_Graphics_xyplot.C index 6dca3335fc6a5..f5e0fbb90ab05 100644 --- a/tutorials/hist/xyplot.C +++ b/tutorials/hist/hist055_Graphics_xyplot.C @@ -7,11 +7,12 @@ /// \macro_image /// \macro_code /// +/// \date January 2017 /// \author Olivier Couet -void xyplot() +void hist055_Graphics_xyplot() { - TCanvas *c = new TCanvas("c","XY plot",200,10,700,500); + TCanvas *c = new TCanvas("c", "XY plot", 200, 10, 700, 500); // Remove the frame c->SetFillColor(kWhite); @@ -21,8 +22,8 @@ void xyplot() // Define and draw a curve the frame const Int_t n = 4; Double_t x[n] = {-1, -3, -9, 3}; - Double_t y[n] = {-1000, 900, 300, 300}; - TGraph* gr = new TGraph(n,x,y); + Double_t y[n] = {-1000, 900, 300, 300}; + TGraph *gr = new TGraph(n, x, y); gr->SetTitle("XY plot"); gr->SetMinimum(-1080); gr->SetMaximum(1080); @@ -41,27 +42,23 @@ void xyplot() // Draw orthogonal axis system centered at (0,0). // Draw the Y axis. Note the 4th label is erased with SetLabelAttributes - TGaxis *yaxis = new TGaxis(0, gPad->GetUymin(), - 0, gPad->GetUymax(), - gPad->GetUymin(),gPad->GetUymax(),6,"+LN"); - yaxis->ChangeLabel(4,-1,0.); + TGaxis *yaxis = new TGaxis(0, gPad->GetUymin(), 0, gPad->GetUymax(), gPad->GetUymin(), gPad->GetUymax(), 6, "+LN"); + yaxis->ChangeLabel(4, -1, 0.); yaxis->Draw(); // Draw the Y-axis title. - TLatex *ytitle = new TLatex(-0.5,gPad->GetUymax(),"Y axis"); + TLatex *ytitle = new TLatex(-0.5, gPad->GetUymax(), "Y axis"); ytitle->Draw(); ytitle->SetTextSize(0.03); ytitle->SetTextAngle(90.); ytitle->SetTextAlign(31); // Draw the X axis - TGaxis *xaxis = new TGaxis(gPad->GetUxmin(), 0, - gPad->GetUxmax(), 0, - gPad->GetUxmin(),gPad->GetUxmax(),510,"+L"); + TGaxis *xaxis = new TGaxis(gPad->GetUxmin(), 0, gPad->GetUxmax(), 0, gPad->GetUxmin(), gPad->GetUxmax(), 510, "+L"); xaxis->Draw(); // Draw the X axis title. - TLatex *xtitle = new TLatex(gPad->GetUxmax(),-200.,"X axis"); + TLatex *xtitle = new TLatex(gPad->GetUxmax(), -200., "X axis"); xtitle->Draw(); xtitle->SetTextAlign(31); xtitle->SetTextSize(0.03); diff --git a/tutorials/hist/hist056_TPolyMarker_contour.C b/tutorials/hist/hist056_TPolyMarker_contour.C new file mode 100644 index 0000000000000..f5be782f23835 --- /dev/null +++ b/tutorials/hist/hist056_TPolyMarker_contour.C @@ -0,0 +1,69 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Make a contour plot and get the first contour in a TPolyMarker. +/// This macro generates a color contour plot by selecting entries +/// from an ntuple file. +/// The TGraph object corresponding to the first contour line is +/// accessed and displayed into a separate canvas. +/// +/// \macro_code +/// +/// \date January 2017 +/// \author Rene Brun + +void hist056_TPolyMarker_contour() +{ + TString dir = gROOT->GetTutorialDir(); + dir.Append("/hsimple.C"); + dir.ReplaceAll("/./", "/"); + if (!gInterpreter->IsLoaded(dir.Data())) + gInterpreter->LoadMacro(dir.Data()); + TFile *file = (TFile *)gROOT->ProcessLineFast("hsimple(1)"); + if (!file) + return; + TTree *ntuple = (TTree *)file->Get("ntuple"); + + TCanvas *c1 = new TCanvas("c1", "Contours", 10, 10, 800, 600); + ntuple->Draw("py:px", "px*px+py*py < 20", "contz,list"); + + // we must call Update to force the canvas to be painted. When + // painting the contour plot, the list of contours is generated + // and a reference to it added to the Root list of special objects + c1->Update(); + + TCanvas *c2 = new TCanvas("c2", "First contour", 100, 100, 800, 600); + + TObjArray *contours = (TObjArray *)gROOT->GetListOfSpecials()->FindObject("contours"); + if (!contours) + return; + TList *lcontour1 = (TList *)contours->At(0); + if (!lcontour1) + return; + TGraph *gc1 = (TGraph *)lcontour1->First(); + if (!gc1) + return; + if (gc1->GetN() < 10) + return; + gc1->SetMarkerStyle(21); + gc1->Draw("alp"); + + // We make a TCutG object with the array obtained from this graph + TCutG *cutg = new TCutG("cutg", gc1->GetN(), gc1->GetX(), gc1->GetY()); + + // We create a polymarker object with npmax points. + const Int_t npmax = 50000; + TPolyMarker *pm = new TPolyMarker(npmax); + Int_t np = 0; + while (1) { + Double_t x = -4 + 8 * gRandom->Rndm(); + Double_t y = -4 + 8 * gRandom->Rndm(); + if (cutg->IsInside(x, y)) { + pm->SetPoint(np, x, y); + np++; + if (np == npmax) + break; + } + } + pm->Draw(); +} diff --git a/tutorials/hist/hist057_TExec_th1.C b/tutorials/hist/hist057_TExec_th1.C new file mode 100644 index 0000000000000..e89cb86ee079c --- /dev/null +++ b/tutorials/hist/hist057_TExec_th1.C @@ -0,0 +1,35 @@ +/// \file +/// \ingroup tutorial_hist +/// Echo object at mouse position. +/// Example of macro called when a pad is redrawn +/// one must create a TExec object in the following way +/// ~~~{.cpp} +/// gPad->AddExec("ex1", ".x hist057_TExec_th1.C"); +/// ~~~ +/// this macro prints the bin number and the bin content when one clicks +/// on the histogram contour of any histogram in a pad +/// +/// \macro_code +/// +/// \date November 2022 +/// \authors Rene Brun, Sergey Linev + +void hist057_TExec_th1() +{ + if (!gPad) { + Error("hist057_TExec_th1", "gPad is null, you are not supposed to run this macro"); + return; + } + + Int_t event = gPad->GetEvent(); + int px = gPad->GetEventX(); + TObject *select = gPad->GetSelected(); + + if (select && select->InheritsFrom(TH1::Class())) { + TH1 *h = (TH1 *)select; + Float_t xx = gPad->AbsPixeltoX(px); + Float_t x = gPad->PadtoX(xx); + Int_t binx = h->GetXaxis()->FindBin(x); + printf("event=%d, hist:%s, bin=%d, content=%f\n", event, h->GetName(), binx, h->GetBinContent(binx)); + } +} diff --git a/tutorials/hist/hist058_TExec_th2.C b/tutorials/hist/hist058_TExec_th2.C new file mode 100644 index 0000000000000..c6f4243870d4a --- /dev/null +++ b/tutorials/hist/hist058_TExec_th2.C @@ -0,0 +1,80 @@ +/// \file +/// \ingroup tutorial_hist +/// Echo object at mouse position and show a graphics line. +/// Example of macro called when a mouse event occurs in a pad. +/// +/// Example: +/// ~~~{.cpp} +/// TFile::Open("hsimple.root"); +/// hpxpy->Draw("colz"); +/// gPad->AddExec("ex2", ".x hist058_TExec_th2.C"); +/// ~~~ +/// When moving the mouse in the canvas, a second canvas shows the +/// projection along X of the bin corresponding to the Y position +/// of the mouse. The resulting histogram is fitted with a gaussian. +/// A "dynamic" line shows the current bin position in Y. +/// This more elaborated example can be used as a starting point +/// to develop more powerful interactive applications exploiting CLING +/// as a development engine. +/// +/// \macro_code +/// +/// \date February 2023 +/// \authors Rene Brun, Sergey Linev + +void hist058_TExec_th2() +{ + if (!gPad) { + Error("hist058_TExec_th2", "gPad is null, you are not supposed to run this macro"); + return; + } + + int px = gPad->GetEventX(); + int py = gPad->GetEventY(); + float uxmin = gPad->GetUxmin(); + float uxmax = gPad->GetUxmax(); + int pxmin = gPad->XtoAbsPixel(uxmin); + int pxmax = gPad->XtoAbsPixel(uxmax); + TObject *select = gPad->GetSelected(); + TCanvas *c2 = (TCanvas *)gROOT->GetListOfCanvases()->FindObject("c2"); + + gPad->GetCanvas()->FeedbackMode(kTRUE); + + int pyold = gPad->GetUniqueID(); // misuse of pad unique for last draw position + + if (pyold && c2) { + // erase line at old position + gVirtualX->DrawLine(pxmin, pyold, pxmax, pyold); + gPad->SetUniqueID(0); + } + + TH2 *h = dynamic_cast(select); + if (!h) + return; + + // erase old position and draw a line at current position + gVirtualX->DrawLine(pxmin, py, pxmax, py); + gPad->SetUniqueID(py); + + Float_t upy = gPad->AbsPixeltoY(py); + Float_t y = gPad->PadtoY(upy); + + // create or set the new canvas c2 + auto padsav = gPad; + if (c2) + delete c2->GetPrimitive("Projection"); + else + c2 = new TCanvas("c2", "Projection Canvas", 710, 10, 700, 500); + c2->SetGrid(); + c2->cd(); + + // draw slice corresponding to mouse position + Int_t biny = h->GetYaxis()->FindBin(y); + TH1D *hp = h->ProjectionX("", biny, biny); + hp->SetName("Projection"); + hp->SetTitle(TString::Format("Projection of biny=%d", biny)); + hp->Fit("gaus", "ql"); + c2->Update(); + + padsav->cd(); +} diff --git a/tutorials/hist/statsEditing.C b/tutorials/hist/hist060_Stats.C similarity index 72% rename from tutorials/hist/statsEditing.C rename to tutorials/hist/hist060_Stats.C index eb473376311b6..6cadf3efabfce 100644 --- a/tutorials/hist/statsEditing.C +++ b/tutorials/hist/hist060_Stats.C @@ -10,19 +10,21 @@ /// \macro_image /// \macro_code /// +/// \date August 2016 /// \author Olivier Couet -TCanvas *statsEditing() { +TCanvas *hist060_Stats() +{ // Create and plot a test histogram with stats TCanvas *se = new TCanvas; - TH1F *h = new TH1F("h","test",100,-3,3); - h->FillRandom("gaus",3000); + TH1F *h = new TH1F("h", "test", 100, -3, 3); + h->FillRandom("gaus", 3000); gStyle->SetOptStat(); h->Draw(); se->Update(); // Retrieve the stat box - TPaveStats *ps = (TPaveStats*)se->GetPrimitive("stats"); + TPaveStats *ps = (TPaveStats *)se->GetPrimitive("stats"); ps->SetName("mystats"); TList *listOfLines = ps->GetListOfLines(); @@ -32,10 +34,10 @@ TCanvas *statsEditing() { // Add a new line in the stat box. // Note that "=" is a control character - TLatex *myt = new TLatex(0,0,"Test = 10"); - myt ->SetTextFont(42); - myt ->SetTextSize(0.04); - myt ->SetTextColor(kRed); + TLatex *myt = new TLatex(0, 0, "Test = 10"); + myt->SetTextFont(42); + myt->SetTextSize(0.04); + myt->SetTextColor(kRed); listOfLines->Add(myt); // the following line is needed to avoid that the automatic redrawing of stats diff --git a/tutorials/hist/fillhistosauto2p.C b/tutorials/hist/hist101_TH1_autobinning.C similarity index 98% rename from tutorials/hist/fillhistosauto2p.C rename to tutorials/hist/hist101_TH1_autobinning.C index 6937e1a8f382f..a5cbe8f26c2e0 100644 --- a/tutorials/hist/fillhistosauto2p.C +++ b/tutorials/hist/hist101_TH1_autobinning.C @@ -24,7 +24,7 @@ TF1 *gam1 = new TF1("gam", "1/(1+0.1*x*0.1*x)", -1., .25); TF1 *iga = new TF1("inv gam", "1.-1/(1+0.1*x*0.1*x)", -100., 100.); TF1 *iga1 = new TF1("inv gam", "1.-1/(1+0.1*x*0.1*x)", -.5, 1.); -void fillhistosauto2p(unsigned opt = 1, unsigned n = 1001) +void hist101_TH1_autobinning(unsigned opt = 1, unsigned n = 1001) { UInt_t nh = 10; diff --git a/tutorials/hist/hist102_TH2_contour_list.C b/tutorials/hist/hist102_TH2_contour_list.C new file mode 100644 index 0000000000000..5e3b329536b6a --- /dev/null +++ b/tutorials/hist/hist102_TH2_contour_list.C @@ -0,0 +1,194 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook +/// Getting Contours From TH2D. +/// +/// #### Image produced by `.x ContourList.C` +/// The contours values are drawn next to each contour. +/// \macro_image +/// +/// #### Output produced by `.x ContourList.C` +/// It shows that 6 contours and 12 graphs were found. +/// \macro_output +/// +/// #### `ContourList.C` +/// \macro_code +/// +/// \date November 2022 +/// \authors Josh de Bever (CSI Medical Physics Group, The University of Western Ontario, London, Ontario, Canada), +/// Olivier Couet + +Double_t SawTooth(Double_t x, Double_t WaveLen); + +TCanvas *hist102_TH2_contour_list() +{ + + const Double_t PI = TMath::Pi(); + + TCanvas *c = new TCanvas("c", "Contour List", 0, 0, 600, 600); + c->SetRightMargin(0.15); + c->SetTopMargin(0.15); + + Int_t i, j; + + Int_t nZsamples = 80; + Int_t nPhiSamples = 80; + + Double_t HofZwavelength = 4.0; // 4 meters + Double_t dZ = HofZwavelength / (Double_t)(nZsamples - 1); + Double_t dPhi = 2 * PI / (Double_t)(nPhiSamples - 1); + + TArrayD z(nZsamples); + TArrayD HofZ(nZsamples); + TArrayD phi(nPhiSamples); + TArrayD FofPhi(nPhiSamples); + + // Discretized Z and Phi Values + for (i = 0; i < nZsamples; i++) { + z[i] = (i)*dZ - HofZwavelength / 2.0; + HofZ[i] = SawTooth(z[i], HofZwavelength); + } + + for (Int_t i = 0; i < nPhiSamples; i++) { + phi[i] = (i)*dPhi; + FofPhi[i] = sin(phi[i]); + } + + // Create Histogram + TH2D *HistStreamFn = + new TH2D("HstreamFn", + "#splitline{Histogram with negative and positive contents. Six contours are defined.}{It is plotted " + "with options CONT LIST to retrieve the contours points in TGraphs}", + nZsamples, z[0], z[nZsamples - 1], nPhiSamples, phi[0], phi[nPhiSamples - 1]); + + // Load Histogram Data + for (Int_t i = 0; i < nZsamples; i++) { + for (Int_t j = 0; j < nPhiSamples; j++) { + HistStreamFn->SetBinContent(i, j, HofZ[i] * FofPhi[j]); + } + } + + gStyle->SetOptStat(0); + gStyle->SetTitleW(0.99); + gStyle->SetTitleH(0.08); + + Double_t contours[6]; + contours[0] = -0.7; + contours[1] = -0.5; + contours[2] = -0.1; + contours[3] = 0.1; + contours[4] = 0.4; + contours[5] = 0.8; + + HistStreamFn->SetContour(6, contours); + + // Draw contours as filled regions, and Save points + HistStreamFn->Draw("CONT Z LIST"); + c->Update(); // Needed to force the plotting and retrieve the contours in TGraphs + + // Get Contours + TObjArray *conts = (TObjArray *)gROOT->GetListOfSpecials()->FindObject("contours"); + + if (!conts) { + printf("*** No Contours Were Extracted!\n"); + return nullptr; + } + + TList *contLevel = nullptr; + TGraph *curv = nullptr; + TGraph *gc = nullptr; + + Int_t nGraphs = 0; + Int_t TotalConts = conts->GetSize(); + + printf("TotalConts = %d\n", TotalConts); + + for (i = 0; i < TotalConts; i++) { + contLevel = (TList *)conts->At(i); + printf("Contour %d has %d Graphs\n", i, contLevel->GetSize()); + nGraphs += contLevel->GetSize(); + } + + nGraphs = 0; + + TCanvas *c1 = new TCanvas("c1", "Contour List", 610, 0, 600, 600); + c1->SetTopMargin(0.15); + TH2F *hr = new TH2F( + "hr", + "#splitline{Negative contours are returned first (highest to lowest). Positive contours are returned " + "from}{lowest to highest. On this plot Negative contours are drawn in red and positive contours in blue.}", + 2, -2, 2, 2, 0, 6.5); + + hr->Draw(); + Double_t xval0, yval0, zval0; + TLatex l; + l.SetTextSize(0.03); + char val[20]; + + for (i = 0; i < TotalConts; i++) { + contLevel = (TList *)conts->At(i); + if (i < 3) + zval0 = contours[2 - i]; + else + zval0 = contours[i]; + printf("Z-Level Passed in as: Z = %f\n", zval0); + + // Get first graph from list on curves on this level + curv = (TGraph *)contLevel->First(); + for (j = 0; j < contLevel->GetSize(); j++) { + curv->GetPoint(0, xval0, yval0); + if (zval0 < 0) + curv->SetLineColor(kRed); + if (zval0 > 0) + curv->SetLineColor(kBlue); + nGraphs++; + printf("\tGraph: %d -- %d Elements\n", nGraphs, curv->GetN()); + + // Draw clones of the graphs to avoid deletions in case the 1st + // pad is redrawn. + gc = (TGraph *)curv->Clone(); + gc->Draw("C"); + + sprintf(val, "%g", zval0); + l.DrawLatex(xval0, yval0, val); + curv = (TGraph *)contLevel->After(curv); // Get Next graph + } + } + c1->Update(); + printf("\n\n\tExtracted %d Contours and %d Graphs \n", TotalConts, nGraphs); + gStyle->SetTitleW(0.); + gStyle->SetTitleH(0.); + return c1; +} + +Double_t SawTooth(Double_t x, Double_t WaveLen) +{ + + // This function is specific to a sawtooth function with period + // WaveLen, symmetric about x = 0, and with amplitude = 1. Each segment + // is 1/4 of the wavelength. + // + // | + // /\ | + // / \ | + // / \ | + // / \ + // /--------\--------/------------ + // |\ / + // | \ / + // | \ / + // | \/ + // + + Double_t y; + if ((x < -WaveLen / 2) || (x > WaveLen / 2)) + y = -99999999; // Error X out of bounds + if (x <= -WaveLen / 4) { + y = x + 2.0; + } else if ((x > -WaveLen / 4) && (x <= WaveLen / 4)) { + y = -x; + } else if ((x > WaveLen / 4) && (x <= WaveLen / 2)) { + y = x - 2.0; + } + return y; +} diff --git a/tutorials/hist/hist103_THnSparse_hist.C b/tutorials/hist/hist103_THnSparse_hist.C new file mode 100644 index 0000000000000..d12f716f85ea8 --- /dev/null +++ b/tutorials/hist/hist103_THnSparse_hist.C @@ -0,0 +1,427 @@ +/// \file +/// \ingroup tutorial_hist +/// Evaluate the performance of THnSparse vs TH1/2/3/nF +/// for different numbers of dimensions and bins per dimension. +/// +/// The script calculates the bandwidth for filling and retrieving +/// bin contents (in million entries per second) for these two +/// histogramming techniques, where "seconds" is CPU and real time. +/// +/// The first line of the plots contains the bandwidth based on the +/// CPU time (THnSpase, TH1/2/3/nF*, ratio), the second line shows +/// the plots for real time, and the third line shows the fraction of +/// filled bins and memory used by THnSparse vs. TH1/2/3/nF. +/// +/// The timing depends on the distribution and the amount of entries +/// in the histograms; here, a Gaussian distribution (center is +/// contained in the histograms) is used to fill each histogram with +/// 1000 entries. The filling and reading is repeated until enough +/// statistics have been collected. +/// +/// tutorials/tree/drawsparse.C shows an example for visualizing a +/// THnSparse. It creates a TTree which is then drawn using +/// TParallelCoord. +/// +/// This macro should be run in compiled mode due to the many nested +/// loops that force CLING to disable its optimization. If run +/// interpreted one would not benchmark THnSparse but CLING. +/// +/// Run as: +/// ~~~{.cpp} +/// root[0] .L $ROOTSYS/tutorials/hist/hist103_THnSparse_hist.C+ +/// root[1] hist103_THnSparse_hist() +/// ~~~ +/// +/// \macro_code +/// +/// \date October 2023 +/// \author Axel.Naumann + +#include "TH1.h" +#include "TH2.h" +#include "TH3.h" +#include "THn.h" +#include "THnSparse.h" +#include "TStopwatch.h" +#include "TRandom.h" +#include "TCanvas.h" +#include "TFile.h" +#include "TStyle.h" +#include "TSystem.h" + +#ifndef INT_MAX +#define INT_MAX std::numeric_limits::max() +#endif + +class TTimeHists { +public: + enum EHist { + kHist, + kSparse, + kNumHist + }; + enum ETime { + kReal, + kCPU, + kNumTime + }; + TTimeHists(Int_t dim, Int_t bins, Long_t num) + : fValue(nullptr), fDim(dim), fBins(bins), fNum(num), fSparse(nullptr), fHist(nullptr), fHn(nullptr) + { + } + ~TTimeHists(); + bool Run(); + Double_t GetTime(EHist hist, ETime time) const + { + if (time == kReal) + return fTime[hist][0]; + return fTime[hist][1]; + } + static void SetDebug(Int_t lvl) { fgDebug = lvl; } + THnSparse *GetSparse() const { return fSparse; } + +protected: + void Fill(EHist hist); + Double_t Check(EHist hist); + void SetupHist(EHist hist); + void NextValues(); + void SetupValues(); + +private: + Double_t *fValue; + Int_t fDim; + Int_t fBins; + Long_t fNum; + Double_t fTime[2][2]; + THnSparse *fSparse; + TH1 *fHist; + THn *fHn; + static Int_t fgDebug; +}; + +Int_t TTimeHists::fgDebug = 0; + +TTimeHists::~TTimeHists() +{ + delete[] fValue; + delete fSparse; + delete fHist; + delete fHn; +} + +bool TTimeHists::Run() +{ + // run all tests with current settings, and check for identity of content. + + Double_t check[2]; + Long64_t rep[2]; + for (int h = 0; h < 2; ++h) { + rep[h] = 0; + SetupValues(); + try { + TStopwatch w; + w.Start(); + SetupHist((EHist)h); + w.Stop(); + do { + w.Start(kFALSE); + Fill((EHist)h); + check[h] = Check((EHist)h); + w.Stop(); + ++rep[h]; + } while ((!h && w.RealTime() < 0.1) || (h && rep[0] > 0 && rep[1] < rep[0])); + + fTime[h][0] = (1. * fNum * rep[h]) / w.RealTime() / 1E6; + fTime[h][1] = (1. * fNum * rep[h]) / w.CpuTime() / 1E6; + + if (h == 1 && (fTime[h][0] > 1E20 || fTime[h][1] > 1E20)) { + do { + // some more cycles: + w.Start(kFALSE); + Fill((EHist)h); + Check((EHist)h); + w.Stop(); + ++rep[h]; + } while (w.RealTime() < 0.1); + + fTime[h][0] = (1. * fNum * rep[h]) / w.RealTime() / 1E6; + fTime[h][1] = (1. * fNum * rep[h]) / w.CpuTime() / 1E6; + } + + if (fTime[h][0] > 1E20) + fTime[h][0] = 1E20; + if (fTime[h][1] > 1E20) + fTime[h][1] = 1E20; + } catch (std::exception &) { + fTime[h][0] = fTime[h][1] = -1.; + check[h] = -1.; // can never be < 1 without exception + rep[h] = -1; + } + } + if (check[0] != check[1]) + if (check[0] != -1.) + printf("ERROR: mismatch of histogram (%g) and sparse histogram (%g) for dim=%d, bins=%d!\n", check[0], + check[1], fDim, fBins); + // else + // printf("ERROR: cannot allocate histogram for dim=%d, bins=%d - out of memory!\n", + // fDim, fBins); + return (check[0] == check[1]); +} + +void TTimeHists::NextValues() +{ + for (Int_t d = 0; d < fDim; ++d) + fValue[d] = gRandom->Gaus() / 4.; +} + +void TTimeHists::SetupValues() +{ + // define fValue + if (!fValue) + fValue = new Double_t[fDim]; + gRandom->SetSeed(42); +} + +void TTimeHists::Fill(EHist hist) +{ + for (Long_t n = 0; n < fNum; ++n) { + NextValues(); + if (fgDebug > 1) { + printf("%ld: fill %s", n, hist == kHist ? (fDim < 4 ? "hist" : "arr") : "sparse"); + for (Int_t d = 0; d < fDim; ++d) + printf("[%g]", fValue[d]); + printf("\n"); + } + if (hist == kHist) { + switch (fDim) { + case 1: fHist->Fill(fValue[0]); break; + case 2: ((TH2F *)fHist)->Fill(fValue[0], fValue[1]); break; + case 3: ((TH3F *)fHist)->Fill(fValue[0], fValue[1], fValue[2]); break; + default: fHn->Fill(fValue); break; + } + } else { + fSparse->Fill(fValue); + } + } +} + +void TTimeHists::SetupHist(EHist hist) +{ + if (hist == kHist) { + switch (fDim) { + case 1: fHist = new TH1F("h1", "h1", fBins, -1., 1.); break; + case 2: fHist = new TH2F("h2", "h2", fBins, -1., 1., fBins, -1., 1.); break; + case 3: fHist = new TH3F("h3", "h3", fBins, -1., 1., fBins, -1., 1., fBins, -1., 1.); break; + default: { + MemInfo_t meminfo; + gSystem->GetMemInfo(&meminfo); + Int_t size = 1; + for (Int_t d = 0; d < fDim; ++d) { + if ((Int_t)(size * sizeof(Float_t)) > INT_MAX / (fBins + 2) || + (meminfo.fMemFree > 0 && meminfo.fMemFree / 2 < (Int_t)(size * sizeof(Float_t) / 1000 / 1000))) + throw std::bad_alloc(); + size *= (fBins + 2); + } + if (meminfo.fMemFree > 0 && meminfo.fMemFree / 2 < (Int_t)(size * sizeof(Float_t) / 1000 / 1000)) + throw std::bad_alloc(); + Int_t *bins = new Int_t[fDim]; + Double_t *xmin = new Double_t[fDim]; + Double_t *xmax = new Double_t[fDim]; + for (Int_t d = 0; d < fDim; ++d) { + bins[d] = fBins; + xmin[d] = -1.; + xmax[d] = 1.; + } + fHn = new THnF("hn", "hn", fDim, bins, xmin, xmax); + } + } + } else { + Int_t *bins = new Int_t[fDim]; + Double_t *xmin = new Double_t[fDim]; + Double_t *xmax = new Double_t[fDim]; + for (Int_t d = 0; d < fDim; ++d) { + bins[d] = fBins; + xmin[d] = -1.; + xmax[d] = 1.; + } + fSparse = new THnSparseF("hs", "hs", fDim, bins, xmin, xmax); + } +} + +Double_t TTimeHists::Check(EHist hist) +{ + // Check bin content of all bins + Double_t check = 0.; + Int_t *x = new Int_t[fDim]; + memset(x, 0, sizeof(Int_t) * fDim); + + if (hist == kHist) { + Long_t idx = 0; + Long_t size = 1; + for (Int_t d = 0; d < fDim; ++d) + size *= (fBins + 2); + while (x[0] <= fBins + 1) { + Double_t v = -1.; + if (fDim < 4) { + Long_t histidx = x[0]; + if (fDim == 2) + histidx = fHist->GetBin(x[0], x[1]); + else if (fDim == 3) + histidx = fHist->GetBin(x[0], x[1], x[2]); + v = fHist->GetBinContent(histidx); + } else + v = fHn->GetBinContent(x); + Double_t checkx = 0.; + if (v) + for (Int_t d = 0; d < fDim; ++d) + checkx += x[d]; + check += checkx * v; + + if (fgDebug > 2 || (fgDebug > 1 && v)) { + printf("%s%d", fDim < 4 ? "hist" : "arr", fDim); + for (Int_t d = 0; d < fDim; ++d) + printf("[%d]", x[d]); + printf(" = %g\n", v); + } + + ++x[fDim - 1]; + // Adjust the bin idx + // no wrapping for dim 0 - it's what we break on! + for (Int_t d = fDim - 1; d > 0; --d) { + if (x[d] > fBins + 1) { + x[d] = 0; + ++x[d - 1]; + } + } + ++idx; + } // while next bin + } else { + for (Long64_t i = 0; i < fSparse->GetNbins(); ++i) { + Double_t v = fSparse->GetBinContent(i, x); + Double_t checkx = 0.; + for (Int_t d = 0; d < fDim; ++d) + checkx += x[d]; + check += checkx * v; + + if (fgDebug > 1) { + printf("sparse%d", fDim); + for (Int_t d = 0; d < fDim; ++d) + printf("[%d]", x[d]); + printf(" = %g\n", v); + } + } + } + check /= fNum; + if (fgDebug > 0) + printf("check %s%d = %g\n", hist == kHist ? (fDim < 4 ? "hist" : "arr") : "sparse", fDim, check); + return check; +} + +void hist103_THnSparse_hist() +{ +// Exclude this macro also for Cling as this script requires exception support +// which is not supported in Cling as of v6.00/00. +#if defined(__CLING__) + printf("Please run this script in compiled mode by running \".x hist103_THnSparse_hist.C+\"\n"); + return; +#endif + + TH2F *htime[TTimeHists::kNumHist][TTimeHists::kNumTime]; + for (int h = 0; h < TTimeHists::kNumHist; ++h) + for (int t = 0; t < TTimeHists::kNumTime; ++t) { + TString name("htime_"); + if (h == 0) + name += "arr"; + else + name += "sp"; + if (t == 0) + name += "_r"; + + TString title; + title.Form("Throughput (fill,get) %s (%s, 1M entries/sec);dim;bins;1M entries/sec", + h == 0 ? "TH1/2/3/nF" : "THnSparseF", t == 0 ? "real" : "CPU"); + htime[h][t] = new TH2F(name, title, 6, 0.5, 6.5, 10, 5, 105); + } + + TH2F *hsparse_mem = + new TH2F("hsparse_mem", "Fractional memory usage;dim;bins;fraction of memory used", 6, 0.5, 6.5, 10, 5, 105); + TH2F *hsparse_bins = new TH2F("hsparse_bins", "Fractional number of used bins;dim;bins;fraction of filled bins", 6, + 0.5, 6.5, 10, 5, 105); + + // TTimeHists::SetDebug(2); + Double_t max = -1.; + for (Int_t dim = 1; dim < 7; ++dim) { + printf("Processing dimension %d", dim); + for (Int_t bins = 10; bins <= 100; bins += 10) { + TTimeHists timer(dim, bins, /*num*/ 1000); + timer.Run(); + for (int h = 0; h < TTimeHists::kNumHist; ++h) { + for (int t = 0; t < TTimeHists::kNumTime; ++t) { + Double_t time = timer.GetTime((TTimeHists::EHist)h, (TTimeHists::ETime)t); + if (time >= 0.) + htime[h][t]->Fill(dim, bins, time); + } + } + hsparse_mem->Fill(dim, bins, timer.GetSparse()->GetSparseFractionMem()); + hsparse_bins->Fill(dim, bins, timer.GetSparse()->GetSparseFractionBins()); + + if (max < timer.GetTime(TTimeHists::kSparse, TTimeHists::kReal)) + max = timer.GetTime(TTimeHists::kSparse, TTimeHists::kReal); + printf("."); + fflush(stdout); + } + printf(" done\n"); + } + + Double_t markersize = 2.5; + hsparse_mem->SetMarkerSize(markersize); + hsparse_bins->SetMarkerSize(markersize); + + TH2F *htime_ratio[TTimeHists::kNumTime]; + for (int t = 0; t < TTimeHists::kNumTime; ++t) { + const char *name = t ? "htime_ratio" : "htime_ratio_r"; + htime_ratio[t] = (TH2F *)htime[TTimeHists::kSparse][t]->Clone(name); + TString title; + title.Form("Relative speed improvement (%s, 1M entries/sec): sparse/hist;dim;bins;#Delta 1M entries/sec", + t == 0 ? "real" : "CPU"); + htime_ratio[t]->SetTitle(title); + htime_ratio[t]->Divide(htime[TTimeHists::kHist][t]); + htime_ratio[t]->SetMinimum(0.1); + htime_ratio[t]->SetMarkerSize(markersize); + } + + TFile *f = new TFile("sparsehist.root", "RECREATE"); + + TCanvas *canv = new TCanvas("c", "c"); + canv->Divide(3, 3); + + gStyle->SetPalette(8, nullptr); + gStyle->SetPaintTextFormat(".2g"); + gStyle->SetOptStat(0); + const char *opt = "TEXT COL"; + + for (int t = 0; t < TTimeHists::kNumTime; ++t) { + for (int h = 0; h < TTimeHists::kNumHist; ++h) { + htime[h][t]->SetMaximum(max); + htime[h][t]->SetMarkerSize(markersize); + canv->cd(1 + h + 3 * t); + htime[h][t]->Draw(opt); + htime[h][t]->Write(); + } + canv->cd(3 + t * 3); + htime_ratio[t]->Draw(opt); + gPad->SetLogz(); + htime_ratio[t]->Write(); + } + + canv->cd(7); + hsparse_mem->Draw(opt); + canv->cd(8); + hsparse_bins->Draw(opt); + hsparse_mem->Write(); + hsparse_bins->Write(); + + canv->Write(); + + delete f; +} diff --git a/tutorials/hist/hist104_TH2Poly_fibonacci.C b/tutorials/hist/hist104_TH2Poly_fibonacci.C new file mode 100644 index 0000000000000..5e5f5d95040f5 --- /dev/null +++ b/tutorials/hist/hist104_TH2Poly_fibonacci.C @@ -0,0 +1,161 @@ +/// \file +/// \ingroup tutorial_hist +/// \notebook -js +/// A TH2Poly build with Fibonacci numbers. +/// +/// In mathematics, the Fibonacci sequence is a suite of integer in which +/// every number is the sum of the two preceding one. +/// +/// The first 10 Fibonacci numbers are: +/// +/// 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ... +/// +/// This tutorial computes Fibonacci numbers and uses them to build a TH2Poly +/// producing the "Fibonacci spiral" created by drawing circular arcs connecting +/// the opposite corners of squares in the Fibonacci tiling. +/// +/// \macro_image +/// \macro_code +/// +/// \date September 2016 +/// \author Olivier Couet + +void Arc(int n, double a, double r, double *px, double *py); +void AddFibonacciBin(TH2Poly *h2pf, double N); + +void hist104_TH2Poly_fibonacci(int N = 7) +{ + // N = number of Fibonacci numbers > 1 + + TCanvas *C = new TCanvas("C", "C", 800, 600); + C->SetFrameLineWidth(0); + + TH2Poly *h2pf = new TH2Poly(); // TH2Poly containing Fibonacci bins. + h2pf->SetTitle(Form("The first %d Fibonacci numbers", N)); + h2pf->SetMarkerColor(kRed - 2); + h2pf->SetStats(0); + + double f0 = 0.; + double f1 = 1.; + double ft; + + AddFibonacciBin(h2pf, f1); + + for (int i = 0; i <= N; i++) { + ft = f1; + f1 = f0 + f1; + f0 = ft; + AddFibonacciBin(h2pf, f1); + } + + h2pf->Draw("A COL L TEXT"); +} + +void Arc(int n, double a, double r, double *px, double *py) +{ + // Add points on a arc of circle from point 2 to n-2 + + double da = TMath::Pi() / (2 * (n - 2)); // Angle delta + + for (int i = 2; i <= n - 2; i++) { + a = a + da; + px[i] = r * TMath::Cos(a) + px[0]; + py[i] = r * TMath::Sin(a) + py[0]; + } +} + +void AddFibonacciBin(TH2Poly *h2pf, double N) +{ + // Add to h2pf the bin corresponding to the Fibonacci number N + + double X1 = 0.; // + double Y1 = 0.; // Current Fibonacci + double X2 = 1.; // square position. + double Y2 = 1.; // + + static int MoveId = 0; + + static double T = 1.; // Current Top limit of the bins + static double B = 0.; // Current Bottom limit of the bins + static double L = 0.; // Current Left limit of the bins + static double R = 1.; // Current Right limit of the bins + + const int NP = 50; // Number of point to build the current bin + double px[NP]; // Bin's X positions + double py[NP]; // Bin's Y positions + + double pi2 = TMath::Pi() / 2; + + switch (MoveId) { + case 1: + R = R + N; + X2 = R; + Y2 = T; + X1 = X2 - N; + Y1 = Y2 - N; + px[0] = X1; + py[0] = Y2; + px[1] = X1; + py[1] = Y1; + px[NP - 1] = X2; + py[NP - 1] = Y2; + Arc(NP, 3 * pi2, (double)N, px, py); + break; + + case 2: + T = T + N; + X2 = R; + Y2 = T; + X1 = X2 - N; + Y1 = Y2 - N; + px[0] = X1; + py[0] = Y1; + px[1] = X2; + py[1] = Y1; + px[NP - 1] = X1; + py[NP - 1] = Y2; + Arc(NP, 0., (double)N, px, py); + break; + + case 3: + L = L - N; + X1 = L; + Y1 = B; + X2 = X1 + N; + Y2 = Y1 + N; + px[0] = X2; + py[0] = Y1; + px[1] = X2; + py[1] = Y2; + px[NP - 1] = X1; + py[NP - 1] = Y1; + Arc(NP, pi2, (double)N, px, py); + break; + + case 4: + B = B - N; + X1 = L; + Y1 = B; + X2 = X1 + N; + Y2 = Y1 + N; + px[0] = X2; + py[0] = Y2; + px[1] = X1; + py[1] = Y2; + px[NP - 1] = X2; + py[NP - 1] = Y1; + Arc(NP, 2 * pi2, (double)N, px, py); + break; + } + + if (MoveId == 0) + h2pf->AddBin(X1, Y1, X2, Y2); // First bin is a square + else + h2pf->AddBin(NP, px, py); // Other bins have an arc of circle + + h2pf->Fill((X1 + X2) / 2.5, (Y1 + Y2) / 2.5, N); + + MoveId++; + if (MoveId == 5) + MoveId = 1; +} diff --git a/tutorials/hist/DynamicSlice.C b/tutorials/hist/hist105_TExec_dynamic_slice.C similarity index 67% rename from tutorials/hist/DynamicSlice.C rename to tutorials/hist/hist105_TExec_dynamic_slice.C index 43dd60891431a..62bcd328abf0f 100644 --- a/tutorials/hist/DynamicSlice.C +++ b/tutorials/hist/hist105_TExec_dynamic_slice.C @@ -6,25 +6,25 @@ /// \macro_image /// \macro_code /// +/// \date November 2022 /// \authors Rene Brun, Sergey Linev - -void DynamicSlice() +void hist105_TExec_dynamic_slice() { // Create a new canvas. - TCanvas* c1 = new TCanvas("c1","Dynamic Slice Example", 10, 10, 700, 500); + TCanvas *c1 = new TCanvas("c1", "Dynamic Slice Example", 10, 10, 700, 500); - //create a 2-d histogram, fill and draw it - TH2F *hpxpy = new TH2F("hpxpy", "py vs px", 40,-4,4, 40,-4,4); + // create a 2-d histogram, fill and draw it + TH2F *hpxpy = new TH2F("hpxpy", "py vs px", 40, -4, 4, 40, -4, 4); hpxpy->SetStats(0); - Double_t px,py; + Double_t px, py; for (Int_t i = 0; i < 50000; i++) { - gRandom->Rannor(px,py); - hpxpy->Fill(px,py); + gRandom->Rannor(px, py); + hpxpy->Fill(px, py); } hpxpy->Draw("col"); - //Add a TExec object to the canvas + // Add a TExec object to the canvas c1->AddExec("dynamic", "DynamicExec()"); } @@ -56,10 +56,10 @@ void DynamicExec() pyold = 0; } - if(!select || !select->InheritsFrom(TH2::Class())) + if (!select || !select->InheritsFrom(TH2::Class())) return; - TH2 *h = (TH2*)select; + TH2 *h = (TH2 *)select; // draw a line at current position gVirtualX->DrawLine(pxmin, py, pxmax, py); @@ -68,21 +68,23 @@ void DynamicExec() Float_t upy = gPad->AbsPixeltoY(py); Float_t y = gPad->PadtoY(upy); - //create or set the new canvas c2 + // create or set the new canvas c2 TVirtualPad *padsav = gPad; - TCanvas *c2 = (TCanvas*)gROOT->GetListOfCanvases()->FindObject("c2"); - if(c2) delete c2->GetPrimitive("Projection"); - else c2 = new TCanvas("c2","Projection Canvas",710,10,700,500); + TCanvas *c2 = (TCanvas *)gROOT->GetListOfCanvases()->FindObject("c2"); + if (c2) + delete c2->GetPrimitive("Projection"); + else + c2 = new TCanvas("c2", "Projection Canvas", 710, 10, 700, 500); c2->SetGrid(); c2->cd(); - //draw slice corresponding to mouse position + // draw slice corresponding to mouse position Int_t biny = h->GetYaxis()->FindBin(y); - TH1D *hp = h->ProjectionX("",biny,biny); + TH1D *hp = h->ProjectionX("", biny, biny); hp->SetFillColor(38); hp->SetName("Projection"); - hp->SetTitle(TString::Format("Projection of biny=%d",biny)); - hp->Fit("gaus","ql"); + hp->SetTitle(TString::Format("Projection of biny=%d", biny)); + hp->Fit("gaus", "ql"); hp->GetFunction("gaus")->SetLineColor(kRed); hp->GetFunction("gaus")->SetLineWidth(6); c2->Update(); diff --git a/tutorials/hist/histpalettecolor.C b/tutorials/hist/histpalettecolor.C deleted file mode 100644 index b6d773c4f36dc..0000000000000 --- a/tutorials/hist/histpalettecolor.C +++ /dev/null @@ -1,57 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Palette coloring for histogram is activated thanks to the options `PFC` -/// (Palette Fill Color), `PLC` (Palette Line Color) and `AMC` (Palette Marker Color). -/// When one of these options is given to `TH1::Draw` the histogram get its color -/// from the current color palette defined by `gStyle->SetPalette(...)`. The color -/// is determined according to the number of objects having palette coloring in -/// the current pad. -/// -/// In this example five histograms are displayed with palette coloring for lines and -/// and marker. The histograms are drawn with markers and error bars and one can see -/// the color of each histogram is picked inside the default palette `kBird`. -/// -/// \macro_image -/// \macro_code -/// -/// \author Olivier Couet - -void histpalettecolor() -{ - auto C = new TCanvas(); - - gStyle->SetOptTitle(kFALSE); - gStyle->SetOptStat(0); - - auto h1 = new TH1F("h1","Histogram drawn with full circles",100,-4,4); - auto h2 = new TH1F("h2","Histogram drawn with full squares",100,-4,4); - auto h3 = new TH1F("h3","Histogram drawn with full triangles up",100,-4,4); - auto h4 = new TH1F("h4","Histogram drawn with full triangles down",100,-4,4); - auto h5 = new TH1F("h5","Histogram drawn with empty circles",100,-4,4); - - TRandom3 rng; - Double_t px,py; - for (Int_t i = 0; i < 25000; i++) { - rng.Rannor(px,py); - h1->Fill(px,10.); - h2->Fill(px, 8.); - h3->Fill(px, 6.); - h4->Fill(px, 4.); - h5->Fill(px, 2.); - } - - h1->SetMarkerStyle(kFullCircle); - h2->SetMarkerStyle(kFullSquare); - h3->SetMarkerStyle(kFullTriangleUp); - h4->SetMarkerStyle(kFullTriangleDown); - h5->SetMarkerStyle(kOpenCircle); - - h1->Draw("PLC PMC"); - h2->Draw("SAME PLC PMC"); - h3->Draw("SAME PLC PMC"); - h4->Draw("SAME PLC PMC"); - h5->Draw("SAME PLC PMC"); - - gPad->BuildLegend(); -} diff --git a/tutorials/hist/hlabels1.C b/tutorials/hist/hlabels1.C deleted file mode 100644 index 5ea972aba1fb2..0000000000000 --- a/tutorials/hist/hlabels1.C +++ /dev/null @@ -1,39 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// 1-D histograms with alphanumeric labels -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -TCanvas *hlabels1() -{ - const Int_t nx = 20; - const char *people[nx] = {"Jean","Pierre","Marie","Odile","Sebastien", - "Fons","Rene","Nicolas","Xavier","Greg","Bjarne","Anton","Otto", - "Eddy","Peter","Pasha","Philippe","Suzanne","Jeff","Valery"}; - TCanvas *c1 = new TCanvas("c1","demo bin labels",10,10,900,500); - c1->SetGrid(); - c1->SetTopMargin(0.15); - TH1F *h = new TH1F("h","test",3,0,3); - h->SetStats(0); - h->SetFillColor(38); - h->SetCanExtend(TH1::kAllAxes); - for (Int_t i=0;i<5000;i++) { - Int_t r = gRandom->Rndm()*20; - h->Fill(people[r],1); - } - h->LabelsDeflate(); - h->Draw(); - TPaveText *pt = new TPaveText(0.7,0.85,0.98,0.98,"brNDC"); - pt->SetFillColor(18); - pt->SetTextAlign(12); - pt->AddText("Use the axis Context Menu LabelsOption"); - pt->AddText(" \"a\" to sort by alphabetic order"); - pt->AddText(" \">\" to sort by decreasing values"); - pt->AddText(" \"<\" to sort by increasing values"); - pt->Draw(); - return c1; -} diff --git a/tutorials/hist/hlabels2.C b/tutorials/hist/hlabels2.C deleted file mode 100644 index 8ff688d6cbd80..0000000000000 --- a/tutorials/hist/hlabels2.C +++ /dev/null @@ -1,49 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// 2-D histograms with alphanumeric labels. -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -TCanvas *hlabels2() -{ - const Int_t nx = 12; - const Int_t ny = 20; - const char *month[nx] = {"January","February","March","April","May", - "June","July","August","September","October","November", - "December"}; - const char *people[ny] = {"Jean","Pierre","Marie","Odile","Sebastien", - "Fons","Rene","Nicolas","Xavier","Greg","Bjarne","Anton", - "Otto","Eddy","Peter","Pasha","Philippe","Suzanne","Jeff", - "Valery"}; - TCanvas *c1 = new TCanvas("c1","demo bin labels",10,10,600,600); - c1->SetGrid(); - c1->SetLeftMargin(0.15); - c1->SetBottomMargin(0.15); - TH2F *h = new TH2F("h","test",3,0,3,2,0,2); - h->SetCanExtend(TH1::kAllAxes); - h->SetStats(0); - gRandom->SetSeed(); - for (Int_t i=0;i<15000;i++) { - Int_t rx = gRandom->Rndm()*nx; - Int_t ry = gRandom->Rndm()*ny; - h->Fill(people[ry],month[rx],1); - } - h->LabelsDeflate("X"); - h->LabelsDeflate("Y"); - h->LabelsOption("v"); - h->Draw("text"); - - TPaveText *pt = new TPaveText(0.6,0.85,0.98,0.98,"brNDC"); - pt->SetFillColor(18); - pt->SetTextAlign(12); - pt->AddText("Use the axis Context Menu LabelsOption"); - pt->AddText(" \"a\" to sort by alphabetic order"); - pt->AddText(" \">\" to sort by decreasing values"); - pt->AddText(" \"<\" to sort by increasing values"); - pt->Draw(); - return c1; -} diff --git a/tutorials/hist/hstack.C b/tutorials/hist/hstack.C deleted file mode 100644 index fae2ca00db880..0000000000000 --- a/tutorials/hist/hstack.C +++ /dev/null @@ -1,72 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Example of stacked histograms: class THStack. -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -void hstack() -{ - auto hs = new THStack("hs","Stacked 1D histograms"); - //create three 1-d histograms - auto h1st = new TH1F("h1st","test hstack",100,-4,4); - h1st->FillRandom("gaus",20000); - h1st->SetFillColor(kRed); - h1st->SetMarkerStyle(21); - h1st->SetMarkerColor(kRed); - hs->Add(h1st); - auto h2st = new TH1F("h2st","test hstack",100,-4,4); - h2st->FillRandom("gaus",15000); - h2st->SetFillColor(kBlue); - h2st->SetMarkerStyle(21); - h2st->SetMarkerColor(kBlue); - hs->Add(h2st); - auto h3st = new TH1F("h3st","test hstack",100,-4,4); - h3st->FillRandom("gaus",10000); - h3st->SetFillColor(kGreen); - h3st->SetMarkerStyle(21); - h3st->SetMarkerColor(kGreen); - hs->Add(h3st); - - auto cst = new TCanvas("cst","stacked hists",10,10,700,700); - cst->Divide(2,2); - // in top left pad, draw the stack with defaults - cst->cd(1); - hs->Draw(); - // in top right pad, draw the stack in non-stack mode - // and errors option - cst->cd(2); - gPad->SetGrid(); - hs->Draw("nostack,e1p"); - //in bottom left, draw in stack mode with "lego1" option - cst->cd(3); - gPad->SetFrameFillColor(17); - gPad->SetTheta(3.77); - gPad->SetPhi(2.9); - hs->Draw("lego1"); - - cst->cd(4); - //create two 2-D histograms and draw them in stack mode - gPad->SetFrameFillColor(17); - auto a = new THStack("a","Stacked 2D histograms"); - auto f1 = new TF2("f1", - "xygaus + xygaus(5) + xylandau(10)",-4,4,-4,4); - Double_t params1[] = {130,-1.4,1.8,1.5,1, 150,2,0.5,-2,0.5, - 3600,-2,0.7,-3,0.3}; - f1->SetParameters(params1); - auto h2sta = new TH2F("h2sta","h2sta",20,-4,4,20,-4,4); - h2sta->SetFillColor(38); - h2sta->FillRandom("f1",4000); - auto f2 = new TF2("f2","xygaus + xygaus(5)",-4,4,-4,4); - Double_t params2[] = {100,-1.4,1.9,1.1,2, 80,2,0.7,-2,0.5}; - f2->SetParameters(params2); - auto h2stb = new TH2F("h2stb","h2stb",20,-4,4,20,-4,4); - h2stb->SetFillColor(46); - h2stb->FillRandom("f2",3000); - a->Add(h2sta); - a->Add(h2stb); - a->Draw(); -} diff --git a/tutorials/hist/hsum.C b/tutorials/hist/hsum.C deleted file mode 100644 index c2d0582ac7a0f..0000000000000 --- a/tutorials/hist/hsum.C +++ /dev/null @@ -1,66 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -js -/// Histograms filled and drawn in a loop. -/// Simple example illustrating how to use the C++ interpreter -/// to fill histograms in a loop and show the graphics results -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -void hsum() -{ - TCanvas *c1 = new TCanvas("c1","The HSUM example",200,10,600,400); - c1->SetGrid(); - - gBenchmark->Start("hsum"); - - // Create some histograms. - auto total = new TH1F("total","This is the total distribution",100,-4,4); - auto main = new TH1F("main","Main contributor",100,-4,4); - auto s1 = new TH1F("s1","This is the first signal",100,-4,4); - auto s2 = new TH1F("s2","This is the second signal",100,-4,4); - total->Sumw2(); // store the sum of squares of weights - total->SetMarkerStyle(21); - total->SetMarkerSize(0.7); - main->SetFillColor(16); - s1->SetFillColor(42); - s2->SetFillColor(46); - TSlider *slider = nullptr; - - // Fill histograms randomly - gRandom->SetSeed(); - const Int_t kUPDATE = 500; - Float_t xs1, xs2, xmain; - for ( Int_t i=0; i<10000; i++) { - xmain = gRandom->Gaus(-1,1.5); - xs1 = gRandom->Gaus(-0.5,0.5); - xs2 = gRandom->Landau(1,0.15); - main->Fill(xmain); - s1->Fill(xs1,0.3); - s2->Fill(xs2,0.2); - total->Fill(xmain); - total->Fill(xs1,0.3); - total->Fill(xs2,0.2); - if (i && (i%kUPDATE) == 0) { - if (i == kUPDATE) { - total->Draw("e1p"); - main->Draw("same"); - s1->Draw("same"); - s2->Draw("same"); - c1->Update(); - slider = new TSlider("slider", - "test",4.2,0,4.6,total->GetMaximum(),38); - slider->SetFillColor(46); - } - if (slider) slider->SetRange(0., 1.*i/10000.); - c1->Modified(); - c1->Update(); - } - } - slider->SetRange(0., 1.); - c1->Modified(); - gBenchmark->Show("hsum"); -} diff --git a/tutorials/hist/index.md b/tutorials/hist/index.md new file mode 100644 index 0000000000000..ef15335b400de --- /dev/null +++ b/tutorials/hist/index.md @@ -0,0 +1,174 @@ +\addtogroup tutorial_hist + +@{ +A histogram is a visual representation of the distribution of quantitative data. +[TH1 class](classTH1.html) introduces the basic data structure used in root for histograms. + +In a nutshell: + +~~~{.cpp} + // Open the file to write the histogram to + auto outFile = std::unique_ptr(TFile::Open("outfile.root", "RECREATE")); + + // Create the histogram object + // There are several constructors you can use (\see TH1). In this example we use the + // simplest one, accepting a number of bins and a range. + int nBins = 30; + double rangeMin = 0.0; + double rangeMax = 10.0; + TH1D histogram("histogram", "My first ROOT histogram", nBins, rangeMin, rangeMax); + + // Fill the histogram. In this simple example we use a fake set of data. + // The 'D' in TH1D stands for 'double', so we fill the histogram with doubles. + // In general you should prefer TH1D over TH1F unless you have a very specific reason + // to do otherwise. + const std::array values{1, 2, 3, 3, 3, 4, 3, 2, 1, 0}; + for (double val : values) { + histogram.Fill(val); + } + + // Write the histogram to `outFile`. + outFile->WriteObject(&histogram, histogram.GetName()); + + // When the TFile goes out of scope it will close itself and write its contents to disk. +~~~ + +Explore the examples below for [different histogram classes](group__Histograms.html) + +## Tutorials sorted after groups + +- [Introduction](\ref introduction) +- [TH1 Histograms](\ref th1) +- [TH2 Histograms](\ref th2) +- [THStack](\ref thstack) +- [TRatio plots](\ref ratioplots) +- [TPoly](\ref tpoly) +- [Graphics](\ref graphics) +- [TExec](\ref texec) + +[List of all tutorials](\ref alltutorials) +\anchor introduction + +## Introduction + +| **Tutorial** | **Description** | +|--------------------------|----------------------------| +| hist000_TH1_first.C | First example | + +\anchor th1 + +## TH1 Histograms + +These examples shows some of the ratioplots + +| **Tutorial** | **Description** | +|--------------------------|----------------------------| +|hist000_TH1_first.C|Hello World example for TH1| +|hist001_TH1_fillrandom.C|Fill a 1D histogram with random values using predefined functions| +|hist002_TH1_fillrandom_userfunc.C|Fill a 1D histogram from a user-defined parametric function.| +|hist003_TH1_draw.C|Draw a 1D histogram to a canvas.| +|hist004_TH1_labels.C|1D histograms with alphanumeric labels.| +|hist005_TH1_palettecolor.C|Palette coloring for TH1| +|hist006_TH1_bar_charts.C|Draw 1D histograms as bar charts| +|hist007_TH1_liveupdate.C|Histograms filled and drawn in a loop.| +|hist008_TH1_zoom.C|Changing the Range on the X-Axis of a Histogram| +|hist009_TH1_normalize.C|Normalizing a Histogram| +|hist010_TH1_two_scales.C|Example of macro illustrating how to superimpose two histograms| +|hist011_TH1_legend_autoplaced.C|The legend can be placed automatically in the current pad in an empty space| +|hist012_TH1_hksimple.C|Illustrates the advantages of a TH1K histogram| +|hist013_TH1_rebin.C|Rebin a variable bin-width histogram.| +|hist014_TH1_cumulative.C|Illustrate use of the TH1::GetCumulative method.| +|hist015_TH1_read_and_draw.C|Read a 1-D histogram from a ROOT File and draw it.| +|hist016_TH1_different_scales_canvas.C|Example of a canvas showing two histograms with different scales.| +|hist017_TH1_smooth.C|Histogram smoothing.| +|hist101_TH1_autobinning.C|Fill multiple histograms with different functions and automatic binning.| +|hist060_Stats.C|Edit statistics box.| + +\anchor th2 + +## TH2 Histograms + +| **Tutorial** | **Description** | +|--------------------------|----------------------------| +|hist018_TH2_cutg.C|This example demonstrates how to display a 2D histogram and| +|hist019_TH2_projection.C|This example demonstrates how to display a histogram and its two projections.| +|hist020_TH2_draw.C|Display the various 2-d drawing options| +|hist021_TH2_reverse_axis.C|Example showing an histogram with reverse axis.| +|hist022_TH2_palette.C|When an histogram is drawn with the option `COLZ`, a palette is automatically drawn| +|hist102_TH2_contour_list.C|Getting Contours From TH2D.| + +\anchor thstack + +## THStack + +| **Tutorial** | **Description** | +|--------------------------|----------------------------| +|hist023_THStack_simple.C|Example of stacked histograms: class THStack.| +|hist024_THStack_pads.C|Drawing stack histograms on subpads.| +|hist025_THStack_2d_palette_color.C|Palette coloring for 2D histograms' stack is activated thanks to the option `PFC`| +|hist026_THStack_color_scheme.C|This example demonstrates how to use the accessible color schemes with THStack.| +|hist027_THStack_palette_color.C|Palette coloring for histograms' stack is activated thanks to the options `PFC`| +|hist028_THStack_multicolor.C|Use a THStack to show a 2-D hist with cells with different colors.| + +\anchor ratioplots + +## Ratio plots + +| **Tutorial** | **Description** | +|--------------------------|----------------------------| +|hist029_TRatioPlot_simple.C|Example creating a simple ratio plot of two histograms using the `pois` division option.| +|hist030_TRatioPlot_residual.C|Example of a fit residual plot.| +|hist031_TRatioPlot_residual_fit.C|Example which shows how you can get the graph of the lower plot and set the y axis range for it.| +|hist032_TRatioPlot_fit_lines.C|Example that shows custom dashed lines on the lower plot, specified by a vector of floats.| +|hist033_TRatioPlot_fit_confidence.C|Example that shows how you can set the colors of the confidence interval bands by using| +|hist034_TRatioPlot_fit_margin.C|Example showing a fit residual plot, where the separation margin has been set to 0.| +|hist035_TRatioPlot_manual_ratio.C|Example displaying two histograms and their ratio. This macro does not use the| + +\anchor tpoly + +## TPoly + +| **Tutorial** | **Description** | +|--------------------------|----------------------------| +|hist037_TH2Poly_boxes.C|This tutorial illustrates how to create an histogram with polygonal| +|hist038_TH2Poly_honeycomb.C|This tutorial illustrates how to create an histogram with hexagonal| +|hist039_TH2Poly_usa.C|This tutorial illustrates how to create an histogram with polygonal| +|hist040_TH2Poly_europe.C|This tutorial illustrates how to create an histogram with polygonal| +|hist041_TProfile2Poly_realistic.C|Different charges depending on region| +|hist042_TProfile2Poly_module_error.C|Simulate faulty detector panel w.r.t. particle charge| +|hist056_TPolyMarker_contour.C|Make a contour plot and get the first contour in a TPolyMarker.| +|hist104_TH2Poly_fibonacci.C|A TH2Poly build with Fibonacci numbers.| + +\anchor graphics + +## Graphics + +| **Tutorial** | **Description** | +|--------------------------|----------------------------| +|hist043_Graphics_highlight.C|This tutorial demonstrates how the highlight mechanism can be used on an histogram.| +|hist044_Graphics_highlight2D.C|This tutorial demonstrates how the highlight mechanism can be used on an histogram.| +|hist045_Graphics_highlight_ntuple.C|This tutorial demonstrates how the highlight mechanism can be used on a ntuple.| +|hist046_Graphics_highlight1D.C|This tutorial demonstrates how the highlight mechanism can be used on an histogram.| +|hist047_Graphics_candle_decay.C|Candle Decay, illustrate a time development of a certain value.| +|hist048_Graphics_candle_hist.C|Example showing how to combine the various candle plot options.| +|hist049_Graphics_candle_plot.C|Example of candle plot with 2-D histograms.| +|hist050_Graphics_candle_plot_options.C|Example showing how to combine the various candle plot options.| +|hist051_Graphics_candle_plot_stack.C|Example showing how a THStack with candle plot option.| +|hist052_Graphics_candle_plot_whiskers.C|Example of candle plot showing the whiskers definition.| +|hist053_Graphics_candle_scaled.C|Candle Scaled, illustrates what scaling does on candle and violin charts.| +|hist054_Graphics_logscales.C|Draw parametric functions with log scales.| +|hist055_Graphics_xyplot.C|Example showing how to produce a plot with an orthogonal axis system| + +\anchor texec + +## TExec + +| **Tutorial** | **Description** | +|--------------------------|----------------------------| +|hist057_TExec_th1.C|Echo object at mouse position.| +|hist058_TExec_th2.C|Echo object at mouse position and show a graphics line.| +|hist105_TExec_dynamic_slice.C|Show the slice of a TH2 following the mouse position.| + +\anchor alltutorials + +@} diff --git a/tutorials/hist/multicolor.C b/tutorials/hist/multicolor.C deleted file mode 100644 index e082e0b34d919..0000000000000 --- a/tutorials/hist/multicolor.C +++ /dev/null @@ -1,54 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Use a THStack to show a 2-D hist with cells with different colors. -/// ~~~{.cpp} -/// root > .x multicolor.C -/// root > .x multicolor.C(1) -/// ~~~ -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -#include "TCanvas.h" -#include "TH2.h" -#include "THStack.h" -#include "TRandom.h" - -void multicolor(Int_t isStack=0) { - TCanvas *c1 = new TCanvas; - Int_t nbins = 20; - TH2F *h1 = new TH2F("h1","h1",nbins,-4,4,nbins,-4,4); - h1->SetFillColor(kBlue); - TH2F *h2 = new TH2F("h2","h2",nbins,-4,4,nbins,-4,4); - h2->SetFillColor(kRed); - TH2F *h3 = new TH2F("h3","h3",nbins,-4,4,nbins,-4,4); - h3->SetFillColor(kYellow); - THStack *hs = new THStack("hs","three plots"); - hs->Add(h1); - hs->Add(h2); - hs->Add(h3); - TRandom r; - Int_t i; - for (i=0;i<20000;i++) h1->Fill(r.Gaus(),r.Gaus()); - for (i=0;i<200;i++) { - Int_t ix = (Int_t)r.Uniform(0,nbins); - Int_t iy = (Int_t)r.Uniform(0,nbins); - Int_t bin = h1->GetBin(ix,iy); - Double_t val = h1->GetBinContent(bin); - if (val <= 0) continue; - if (!isStack) h1->SetBinContent(bin,0); - if (r.Rndm() > 0.5) { - if (!isStack) h2->SetBinContent(bin,0); - h3->SetBinContent(bin,val); - } else { - if (!isStack) h3->SetBinContent(bin,0); - h2->SetBinContent(bin,val); - } - } - hs->Draw("lego1"); -} - - - diff --git a/tutorials/hist/ratioplot3.C b/tutorials/hist/ratioplot3.C deleted file mode 100644 index a77b1ae60236a..0000000000000 --- a/tutorials/hist/ratioplot3.C +++ /dev/null @@ -1,28 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Example which shows how you can get the graph of the lower plot and set the y axis range for it. -/// -/// Since the lower plot is not created until `TRatioPlot::Draw` is called, you can only use the method -/// afterwards. -/// -/// \macro_image -/// \macro_code -/// -/// \author Paul Gessinger - -void ratioplot3() { - gStyle->SetOptStat(0); - auto c1 = new TCanvas("c1", "fit residual simple"); - c1->SetLogy(); - auto h1 = new TH1D("h1", "h1", 50, -5, 5); - h1->FillRandom("gaus", 2000); - h1->Fit("gaus", "0"); - h1->SetMinimum(0.001); - h1->GetXaxis()->SetTitle("x"); - h1->GetYaxis()->SetTitle("y"); - auto rp1 = new TRatioPlot(h1); - rp1->Draw(); - rp1->GetLowerRefGraph()->SetMinimum(-2); - rp1->GetLowerRefGraph()->SetMaximum(2); -} diff --git a/tutorials/hist/rebin.C b/tutorials/hist/rebin.C deleted file mode 100644 index d7b46194a1ba9..0000000000000 --- a/tutorials/hist/rebin.C +++ /dev/null @@ -1,61 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -js -/// Rebin a variable bin-width histogram. -/// -/// This tutorial illustrates how to: -/// - create a variable bin-width histogram with a binning such -/// that the population per bin is about the same. -/// - rebin a variable bin-width histogram into another one. -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -#include "TH1.h" -#include "TCanvas.h" -void rebin() { - //create a fix bin histogram - TH1F *h = new TH1F("h","test rebin",100,-3,3); - Int_t nentries = 1000; - h->FillRandom("gaus",nentries); - Double_t xbins[1001]; - Int_t k=0; - TAxis *axis = h->GetXaxis(); - for (Int_t i=1;i<=100;i++) { - Int_t y = (Int_t)h->GetBinContent(i); - if (y <=0) continue; - Double_t dx = axis->GetBinWidth(i)/y; - Double_t xmin = axis->GetBinLowEdge(i); - for (Int_t j=0;jGetXmax(); - //create a variable bin-width histogram out of fix bin histogram - //new rebinned histogram should have about 10 entries per bin - TH1F *hnew = new TH1F("hnew","rebinned",k,xbins); - hnew->FillRandom("gaus",10*nentries); - - //rebin hnew keeping only 50% of the bins - Double_t xbins2[501]; - Int_t kk=0; - for (Int_t j=0;jRebin(kk,"hnew2",xbins2); - - //draw the 3 histograms - TCanvas *c1 = new TCanvas("c1","c1",800,1000); - c1->Divide(1,3); - c1->cd(1); - h->Draw(); - c1->cd(2); - hnew->Draw(); - c1->cd(3); - hnew2->Draw(); -} diff --git a/tutorials/hist/reverseaxis.C b/tutorials/hist/reverseaxis.C deleted file mode 100644 index 3114be58592b0..0000000000000 --- a/tutorials/hist/reverseaxis.C +++ /dev/null @@ -1,65 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Example showing an histogram with reverse axis. -/// -/// \macro_image -/// \macro_code -/// -/// \author Olivier Couet - -void ReverseXAxis (TH1 *h); -void ReverseYAxis (TH1 *h); - -void reverseaxis() -{ - TH2F *hpxpy = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4); - Float_t px, py; - TRandom r; - for (Int_t i = 0; i < 25000; i++) { - r.Rannor(px,py); - hpxpy->Fill(px,py); - } - TCanvas *c1 = new TCanvas("c1"); - hpxpy->Draw("colz"); - ReverseXAxis(hpxpy); - ReverseYAxis(hpxpy); -} - -void ReverseXAxis(TH1 *h) -{ - // Remove the current axis - h->GetXaxis()->SetLabelOffset(999); - h->GetXaxis()->SetTickLength(0); - - // Redraw the new axis - gPad->Update(); - TGaxis *newaxis = new TGaxis(gPad->GetUxmax(), - gPad->GetUymin(), - gPad->GetUxmin(), - gPad->GetUymin(), - h->GetXaxis()->GetXmin(), - h->GetXaxis()->GetXmax(), - 510,"-"); - newaxis->SetLabelOffset(-0.03); - newaxis->Draw(); -} - -void ReverseYAxis(TH1 *h) -{ - // Remove the current axis - h->GetYaxis()->SetLabelOffset(999); - h->GetYaxis()->SetTickLength(0); - - // Redraw the new axis - gPad->Update(); - TGaxis *newaxis = new TGaxis(gPad->GetUxmin(), - gPad->GetUymax(), - gPad->GetUxmin()-0.001, - gPad->GetUymin(), - h->GetYaxis()->GetXmin(), - h->GetYaxis()->GetXmax(), - 510,"+"); - newaxis->SetLabelOffset(-0.03); - newaxis->Draw(); -} diff --git a/tutorials/hist/testSmooth.C b/tutorials/hist/testSmooth.C deleted file mode 100644 index c53a669070fe0..0000000000000 --- a/tutorials/hist/testSmooth.C +++ /dev/null @@ -1,68 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Histogram smoothing. -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -int ipad = 1; -TCanvas * c1 = 0; - -void smooth_hist(const char * fname, double xmin, double xmax, int n1, int n2) { - - std::cout << "smoothing a " << fname << " histogram" << std::endl; - - TH1D * h1 = new TH1D("h1","h1",100,xmin,xmax); - TH1D * h2 = new TH1D("h2","h2",100,xmin,xmax); - h1->FillRandom(fname,n1); - - TH1D * h1_s = new TH1D(*h1); - h1_s->SetName("h1_s"); - h1_s->Smooth(); - - h2->FillRandom(fname,n2); - - double p1 = h1->Chi2Test(h2,""); - double p2 = h1_s->Chi2Test(h2,"UU"); - if (p2 < p1) Error("testSmooth","TH1::Smooth is not working correctly - a worst chi2 is obtained"); - - std::cout << " chi2 test non-smoothed histo " << p1 << std::endl; - std::cout << " chi2 test smoothed histo " << p2 << std::endl; - - double a1 = h1->AndersonDarlingTest(h2); - double a2 = h1_s->AndersonDarlingTest(h2); - - std::cout << " AD test non-smoothed histo " << a1 << std::endl; - std::cout << " AD test smoothed histo " << a2 << std::endl; - - double k1 = h1->KolmogorovTest(h2); - double k2 = h1_s->KolmogorovTest(h2); - - std::cout << " KS test non-smoothed histo " << k1 << std::endl; - std::cout << " KS test smoothed histo " << k2 << std::endl; - - c1->cd(ipad++); - h1->Draw("E"); - h1_s->SetLineColor(kRed); - h1_s->Draw("same"); - h2->Scale(double(n1)/n2); - h2->SetLineColor(kGreen); - h2->Draw("same"); -} - -void testSmooth(int n1 = 1000, int n2 = 1000000) { - - TH1::AddDirectory(false); - - c1 = new TCanvas(); - c1->Divide(1,3); - - - smooth_hist("gaus",-5,5,n1,n2); - smooth_hist("landau",-5,15,n1,n2); - smooth_hist("expo",-5,0,n1,n2); - -} diff --git a/tutorials/hist/th2polyUSA.C b/tutorials/hist/th2polyUSA.C deleted file mode 100644 index 5c089ee1820bf..0000000000000 --- a/tutorials/hist/th2polyUSA.C +++ /dev/null @@ -1,82 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -js -/// This tutorial illustrates how to create an histogram with polygonal -/// bins (TH2Poly), fill it and draw it using the `col` option. The initial data -/// are stored in TMultiGraphs. They represent the USA map. Such histograms can -/// be rendered in 3D using the option `legogl`. -/// -/// The initial data have been downloaded from: http://www.maproom.psu.edu/dcw/ -/// This database was developed in 1991/1992 and national boundaries reflect -/// political reality as of that time. -/// -/// \macro_code -/// \macro_image -/// -/// \author Olivier Couet - -void th2polyUSA() -{ - Int_t i, bin; - const Int_t nx = 48; - const char *states [nx] = { - "alabama", "arizona", "arkansas", "california", - "colorado", "connecticut", "delaware", "florida", - "georgia", "idaho", "illinois", "indiana", - "iowa", "kansas", "kentucky", "louisiana", - "maine", "maryland", "massachusetts", "michigan", - "minnesota", "mississippi", "missouri", "montana", - "nebraska", "nevada", "new_hampshire", "new_jersey", - "new_mexico", "new_york", "north_carolina", "north_dakota", - "ohio", "oklahoma", "oregon", "pennsylvania", - "rhode_island", "south_carolina", "south_dakota", "tennessee", - "texas", "utah", "vermont", "virginia", - "washington", "west_virginia", "wisconsin", "wyoming" - }; - Double_t pop[nx] = { - 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969, - 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076, - 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989, - 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844, - 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254, - 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270 - }; - - TCanvas *usa = new TCanvas("USA", "USA"); - usa->ToggleEventStatus(); - Double_t lon1 = -130; - Double_t lon2 = -65; - Double_t lat1 = 24; - Double_t lat2 = 50; - TH2Poly *p = new TH2Poly("Lower48","Lower 48 Population (2009);Latitude;Longitude",lon1,lon2,lat1,lat2); - - TFile::SetCacheFileDir("."); - TFile *f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD"); - - if (!f) { - printf("Cannot access usa.root. Is internet working ?\n"); - return; - } - - // Define the TH2Poly bins. - TMultiGraph *mg; - TKey *key; - TIter nextkey(gDirectory->GetListOfKeys()); - while ((key = (TKey*)nextkey())) { - TObject *obj = key->ReadObj(); - if (obj->InheritsFrom("TMultiGraph")) { - mg = (TMultiGraph*)obj; - bin = p->AddBin(mg); - } - } - - // Fill TH2Poly, with capital letters for the states names - for (i=0; iFill(states[i], pop[i]); - - gStyle->SetOptStat(0); - p->Draw("colz textn"); - - // Add the reference for the population - TLatex pupulationRef(-128, 27, "#scale[.55]{#splitline{Source:}{http://eadiv.state.wy.us/pop/st-09est.htm}}"); - pupulationRef.DrawClone(); -} diff --git a/tutorials/hist/transpad.C b/tutorials/hist/transpad.C deleted file mode 100644 index 21d9a5417091b..0000000000000 --- a/tutorials/hist/transpad.C +++ /dev/null @@ -1,60 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Example of a canvas showing two histograms with different scales. -/// The second histogram is drawn in a transparent pad -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -void transpad() -{ - TCanvas *c1 = new TCanvas("c1","transparent pad",200,10,700,500); - TPad *pad1 = new TPad("pad1","",0,0,1,1); - TPad *pad2 = new TPad("pad2","",0,0,1,1); - pad2->SetFillStyle(4000); //will be transparent - pad1->Draw(); - pad1->cd(); - - TH1F *h1 = new TH1F("h1","h1",100,-3,3); - TH1F *h2 = new TH1F("h2","h2",100,-3,3); - TRandom r; - for (Int_t i=0;i<100000;i++) { - Double_t x1 = r.Gaus(-1,0.5); - Double_t x2 = r.Gaus(1,1.5); - if (i <1000) h1->Fill(x1); - h2->Fill(x2); - } - h1->Draw(); - pad1->Update(); //this will force the generation of the "stats" box - TPaveStats *ps1 = (TPaveStats*)h1->GetListOfFunctions()->FindObject("stats"); - ps1->SetX1NDC(0.4); ps1->SetX2NDC(0.6); - pad1->Modified(); - c1->cd(); - - //compute the pad range with suitable margins - Double_t ymin = 0; - Double_t ymax = 2000; - Double_t dy = (ymax-ymin)/0.8; //10 per cent margins top and bottom - Double_t xmin = -3; - Double_t xmax = 3; - Double_t dx = (xmax-xmin)/0.8; //10 per cent margins left and right - pad2->Range(xmin-0.1*dx,ymin-0.1*dy,xmax+0.1*dx,ymax+0.1*dy); - pad2->Draw(); - pad2->cd(); - h2->SetLineColor(kRed); - h2->Draw("][sames"); - pad2->Update(); - TPaveStats *ps2 = (TPaveStats*)h2->GetListOfFunctions()->FindObject("stats"); - ps2->SetX1NDC(0.65); ps2->SetX2NDC(0.85); - ps2->SetTextColor(kRed); - - // draw axis on the right side of the pad - TGaxis *axis = new TGaxis(xmax,ymin,xmax,ymax,ymin,ymax,50510,"+L"); - axis->SetLabelColor(kRed); - axis->Draw(); -} - - diff --git a/tutorials/hist/twoscales.C b/tutorials/hist/twoscales.C deleted file mode 100644 index 67217da2d77bf..0000000000000 --- a/tutorials/hist/twoscales.C +++ /dev/null @@ -1,51 +0,0 @@ -/// \file -/// \ingroup tutorial_hist -/// \notebook -/// Example of macro illustrating how to superimpose two histograms -/// with different scales in the "same" pad. -/// -/// \macro_image -/// \macro_code -/// -/// \author Rene Brun - -#include "TCanvas.h" -#include "TStyle.h" -#include "TH1.h" -#include "TGaxis.h" -#include "TRandom.h" - -void twoscales() -{ - TCanvas *c1 = new TCanvas("c1","hists with different scales",600,400); - - //create/fill draw h1 - gStyle->SetOptStat(kFALSE); - TH1F *h1 = new TH1F("h1","my histogram",100,-3,3); - Int_t i; - for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1)); - h1->Draw(); - c1->Update(); - - //create hint1 filled with the bins integral of h1 - TH1F *hint1 = new TH1F("hint1","h1 bins integral",100,-3,3); - Float_t sum = 0; - for (i=1;i<=100;i++) { - sum += h1->GetBinContent(i); - hint1->SetBinContent(i,sum); - } - - //scale hint1 to the pad coordinates - Float_t rightmax = 1.1*hint1->GetMaximum(); - Float_t scale = gPad->GetUymax()/rightmax; - hint1->SetLineColor(kRed); - hint1->Scale(scale); - hint1->Draw("same"); - - //draw an axis on the right side - TGaxis *axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(), - gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L"); - axis->SetLineColor(kRed); - axis->SetLabelColor(kRed); - axis->Draw(); -} diff --git a/tutorials/hist/hsumTimer.C b/tutorials/legacy/hist/hsumTimer.C similarity index 98% rename from tutorials/hist/hsumTimer.C rename to tutorials/legacy/hist/hsumTimer.C index 809347bd8491c..1da52fc812cd4 100644 --- a/tutorials/hist/hsumTimer.C +++ b/tutorials/legacy/hist/hsumTimer.C @@ -1,5 +1,5 @@ /// \file -/// \ingroup tutorial_hist +/// \ingroup tutorial_hist_legacy /// \notebook -js /// Demo of Timers. /// diff --git a/tutorials/legacy/hist/index.md b/tutorials/legacy/hist/index.md new file mode 100644 index 0000000000000..a83258766fbe0 --- /dev/null +++ b/tutorials/legacy/hist/index.md @@ -0,0 +1,3 @@ +\defgroup tutorial_hist_legacy Legacy histogram tutorials +\ingroup tutorial_legacy +\brief Examples for ROOT's histograms (legacy)