2.2.2 直方图

直方图的概念

直方图(histogram)与图表(graph)的区别在于使用 bin 分割数据。bin 的原意是垃圾箱或小箱子,在 histogram 中用竖状的 bar 反映数据,这些存放数据的 bar,称为 bin,也就是将整个数据范围划分为一系列统计区间。bin 的宽度取决于数据范围上 bin 的数量。

直方图的使用

直方图是一种对数据分布情况的图形表示方式,适合用来表现数量上的差异。直方图支持批量创建和运算。直方图的创建方法有很多:

TH1I *h1 = new TH1I("histogram name", "grapg title; x title; unit title", nbins, xmin, xmax)
TH1D* h1 = new TH1D("histogram name", "grapg title; x title; unit title", nbins, xmin, xmax)
TH1F *h1 = new TH1F("histogram name", "grapg title; x title; unit title", , , )
TH1I *h1 = new TH1I("histogram name", "grapg title", , , )
TH1I *h1 = new TH1I("histogram name", "grapg title", nbins, xmin, xmax)
auto *h1 = new TH1F
TH1F *h[n]    // 批量创建
TH1F h3 = h1*h2;
TH1F h3 = 8*h1;

TH1D是缩写,分别表示THistogram类、1维、Double型,同理TH1F表示整数型一维直方图,TH2D表示双精度浮点型二维直方图。

"histogram name"表示直方图名称,直方图存储在本地时,文件名默认使用直方图名称,"grapg title"作 histogram 的图表题,nbins, xmin, xmax分别表示分 bin 数量和轴范围,即将xmin-xmax的范围上分mbins个 bin。

建立histogram之后,必须向其中填充数据,否则不能正常绘制:

h1->Fill(x);         // 填入一个值x
h1->Fill(x, w);      // 以权重为w填入一个值x
h1->Fill(x*0.5+10);  // 进行计算

控制分 bin

当 canvas 和轴发生变化时,bin 宽(形式上而非数值上)也会发生变化。如SetLogx,表示将 x轴设置为对数坐标的形式,此时 bin 宽(形式上)会随 logx 而变化,若要求 bin 宽(形式上)不随 logx 变化,可以参考这里

对 bin 的控制能够更加科学和美观的呈现结论。控制 bin 的方法有:

  • 标准控制:E.g.

    TH1 *h1 = new TH1I("h1", "a histogram title",100, 0.0, 4.0)
  • 自动控制:不指定 bin 及坐标范围(参数位置需要空出),ROOT 会自动匹配。E.g.

   TH1 *h1 = new TH1I("h1", "h1 title", , , );   // 一维整型直方图
  • 精细控制:数组的大小应为nbins+1,因为它包含下范围和上范围的轴值。E.g.

   double binEdges[] = { 0.0, 0.2, 0.5, 1., 2., 4. };
   TH1 *h1 = new TH1D("h1", "h1 title", 6, binEdges );
   TH2 *h2 = new TH2D("h2", "h2 title", 6, binEdges , 30, -1.5, 3.5);
  • 指定控制:通过符号>>控制。E.g.

    TTree->Draw("TBranch>>(xnbins,xmin,xmax)")

二维使用>>(xnbins,xmin,xmax,ynbins,ymin,ymax)的语法控制。

  • 重新排列:通过函数Rebin( mergebin, newname, xbins 0 or !0) 重制。E.g.

root [1] hist-Rebin(5)    // 原直方图上的5bins合1bin
root [2] hist-Rebin()     // 默认2合1
root [3] hist-Rebin(5, histogram2)     // 创建一个新的histogram2,将原直方图5合1后展示
root [4] hist-Rebin(5, histogram2, xbins)   // 参考:https://root.cern/doc/master/rebin_8C.html
  • 查看、获取和更改 bin 中的内容

GetBinEntries(i),用于获取TProfile对象中第i个bin的数据点数量;

GetBinContent(i),用于获取TProfile对象中第i个bin的内容,即该bin中的数据值;

GetXaxis()->GetBinCenter(i),获取TProfile对象中X轴上第i个bin的中心值;

带有误差条的写入bin

histo->SetBinContent(i+1, data[i]); histo->SetBinError(i+1, TMath::Sqrt(data[i])), bin从1开始

GetBinError(i),用于获取TProfile对象中第i个bin的(上)误差;

GetBinErrorLow(i),用于获取TProfile对象中第i个bin的下误差;

GetBinWidth(i),用于获取直方图中第i个bin的宽度;

GetBinXYZ(i, j, k),这个函数用于获取多维直方图中(例如TH3)的第(i, j, k)个bin的内容。

gPad->GetUymax(), 获取坐标轴的最大值,在此之前需要运行c1->Update()

GetQuantiles(nq, yq, xq),分为函数,假设我们有一个包含 1000 个随机数的直方图,我们希望计算出它的四分位数(即分位数数量为 4)。以下是一个示例代码:

#include <TH1F.h>
#include <TMath.h>
#include <TRandom3.h>

void calculateQuantiles() {
    // 创建一个一维直方图
    TH1F *histogram = new TH1F("histogram", "Random Numbers", 100, 0, 100);
    // 生成一些随机数并填充到直方图中
    TRandom3 random;
    for (int i = 0; i < 1000; ++i) {
        histogram->Fill(random.Uniform(0, 100));
    }
    // 计算四分位数
    int nq = 4;
    double xq[nq];
    double yq[nq];
    for (int i = 0; i < nq; ++i) {
        xq[i] = double(i + 1) / nq;
    }
    histogram->GetQuantiles(nq, yq, xq);
    // 打印输出计算得到的四分位数
    for (int i = 0; i < nq; ++i) {
        std::cout << "Quantile " << i+1 << " at position " << xq[i] << " is " << yq[i] << std::endl;
    }
}

在这个例子中,我们首先创建了一个包含 100 个 bin 的一维直方图,然后生成了 1000 个 0 到 100 之间的随机数,并将它们填充到直方图中。接着,我们计算了四分位数,并将结果存储在数组 yq 中。最后,我们打印输出了计算得到的四分位数值。

通过这个例子可以更好地理解GetQuantiles函数的作用,以及如何使用它来计算直方图中指定分位数位置的数值。

数据填充

histogram 也可以通过数据值/坐标来绘制 E.g.

E.g. GRB221009A的光变曲线
#include <iostream>
#include <fstream>
#include <vector>
#include <TCanvas.h>
#include <TH1F.h>

void plot() {
	TCanvas *canvas = new TCanvas("canvas", "Histogram", 800, 800);
	canvas->Divide(1,4,0);
	
	TH1F *h1 = new TH1F("h1", "", 120, 0, 1200);
	std::ifstream file1("lightCurve221009AHxmt.txt");
	double x1, y1;
	while (file1 >> x1 >> y1) {h1->Fill(x1, y1);}
	h1->SetTitle(";;Rate [counts/bin]");
	h1->GetYaxis()->SetTitleSize(0.06);h1->GetYaxis()->CenterTitle();

   	canvas->cd(1);
	gStyle->SetOptStat(0);
	h1->SetFillColor(kYellow-6);
	h1->Draw("HIST");
	TLegend *l1 = new TLegend(0.6,0.6,0.893,0.89,"HXMT HE/Csl");
	l1->AddEntry(h1,"0.6-3MeV");
    	l1->SetBorderSize(0);l1->Draw();
}

这种方式绘制的直方图只是形式上的,不能反映真实的 bin 值,所以这种方法不适用于拟合等操作,所以建议使用TTree::SetBranchAddress("",&)函数绘制:

E.g. 拟合的坐标点填充
#include <iostream>
#include <fstream>
#include <vector>
#include <TCanvas.h>
#include <TH1F.h>
#include <TF1.h>

void plot() {
	gStyle->SetOptStat(0);gStyle->SetOptFit(1);
	TCanvas *canvas = new TCanvas("canvas", "Histogram", 800, 800);
	
	TH1F *h1 = new TH1F();
	h1->SetBins(50000,0,50000);
	std::ifstream file1("CH1.csv");
	double x1, y1;
	TTree* t = new TTree();
	int x;
	double y;
	t->ReadFile("CH1.txt","x/I:y/D");
	t->SetBranchAddress("x",&x);
	t->SetBranchAddress("y",&y);
	for (int i=0; i<t->GetEntries();i++)	{
		t->GetEntry(i);
		h1->SetBinContent(x,y);
	}
	
	h1->SetTitle("T;time [ps];counts");
	h1->GetYaxis()->SetTitleSize(0.06);
	h1->GetYaxis()->CenterTitle();
	
	double max;
	int maxbin;
	TF1* func = new TF1();
	double mean,sigma;
	maxbin = h1->GetMaximumBin();
	max = h1->GetBinCenter(maxbin);
	h1->Fit("gaus","","",max-100,max+100);
	func = h1->GetFunction("gaus");
	mean  = func->GetParameter(1);
	sigma  = func->GetParameter(2);
	h1->Fit("gaus","","",mean-1.2*sigma,mean+1.2*sigma);
	func = h1->GetFunction("gaus");
	mean  = func->GetParameter(1);
	sigma  = func->GetParameter(2);
	h1->Fit("gaus","","",mean-1.2*sigma,mean+1.2*sigma);
	func = h1->GetFunction("gaus");
	mean  = func->GetParameter(1);
	sigma  = func->GetParameter(2);
	h1->Fit("gaus","","",mean-1.2*sigma,mean+1.2*sigma);
	func = h1->GetFunction("gaus");
	func = h1->GetFunction("gaus");
	mean  = func->GetParameter(1);
	sigma  = func->GetParameter(2);
	h1->Fit("gaus","","",mean-1.*sigma,mean+1.*sigma);

	canvas->cd(1);
	gStyle->SetOptStat();
	//h1->SetFillColor(kYellow-6);
//	h1->Draw("hist f1");
//	f1->Draw("same");
	h1->GetXaxis()->SetRangeUser(39000,40500);
	canvas->SaveAs("h1.root");
}

数据缩放

TH::Scale(,"")函数进行纵坐标缩放,如果选项包含“width”,则bin的内容和误差则除以bin宽。E.g.h1->Scale(1./12)缩小 12 倍。

E.g. 控制分 bin 并使用缩放归一
#include "TH2F.h"
#include "TRandom.h"
#include "TCanvas.h"

void NormalizeHistogram()
{

	std::array<double, 6> binsx{0, 5, 10, 20, 50, 100};
	TH1F *orig = new TH1F("orig", 
	"Original histogram before normalization", binsx.size() - 1, &binsx[0]);
//	TH1F *orig = new TH1F("orig", 
//	"Original histogram before normalization", 5, 0, 100);

	gStyle->SetTitleFontSize(0.06);

	TRandom2 rand;
	// Filling histogram with random entries
	for (int i = 0; i < 100000; ++i) {
		double r = rand.Rndm() * 100;
		orig->Fill(r);
	}

	TH1F *norm = (TH1F *)orig->Clone("norm");	// 强制转化orig为TH1F类的指针
	norm->SetTitle("Normalized Histogram");
	// Normalizing the Histogram by scaling by 1 / the integral and taking width into account
	norm->Scale(1. / norm->Integral(), "width");
//	norm->Scale(1., "width");
	// Drawing everything
	TCanvas *c1 = new TCanvas("c1", "Histogram Normalization", 700, 900);
	c1->Divide(1, 2);
	c1->cd(1);
	orig->Draw();
	c1->cd(2);
	norm->Draw();
}

绘图选项

支持1D和2D直方图的选项

Option Description

"E"

绘制误差棒。

"HIST"

绘制直方图。

"FUNC"

当直方图具有拟合函数时,此选项允许仅绘制拟合结果。

"SAME"

叠加在同一垫中的前一张图片上。

"SAMES"

与“SAME”相同,强制绘制统计框。

"PFC"

调色板填充颜色:直方图的填充颜色取当前调色板。

"PLC"

调色板线条颜色:直方图的线条颜色取当前调色板。

"PMC"

调色板标记颜色:直方图的标记颜色取当前调色板。

"LEGO"

绘制去除隐藏线的乐高图。

"LEGO1"

绘制隐藏表面移除的乐高图.

"LEGO2"

使用颜色绘制乐高图以显示单元格内容 当选项“0”与任何乐高选项一起使用时,不会绘制空箱。

"LEGO3"

绘制一个带有隐藏表面去除的乐高图,与乐高1类似,但不绘制每个乐高条的边界线。

"LEGO4"

绘制一个带有隐藏表面去除的乐高图,就像乐高1一样,但每个乐高条上没有阴影效果。

"TEXT"

将 bin 内容绘制为文本(通过 gStyle->SetPaintTextFormat 设置格式)。

"TEXTnn"

将 bin 内容绘制为角度 nn (0 < nn <= 90) 的文本.

"X+"

TX 轴绘制在图的顶部。

"Y+"

Y 轴绘制在图的右侧。

"MIN0"

将 Y 轴的最小值设置为 0,相当于 gStyle->SetHistMinimumZero()。

支持1D直方图的选项

Option Description

"AH"

绘制无轴直方图。 “A”可以与任何绘图选项组合。 例如,“AC”将直方图绘制为无轴的平滑曲线。

"]["

选择此选项时,不会绘制直方图的第一条和最后一条垂直线。

"B"

条形图选项。

"BAR"

与选项“B”类似,但可以用 3D 效果绘制条形。

"HBAR"

“HBAR” 与选项“BAR”类似,但条形是水平绘制的。

"C"

通过直方图箱绘制平滑曲线。

"E0"

绘制误差线。 为内容为 0 的箱绘制标记。 与 E1 或 E2 结合使用可避免误差条剪切。

"E1"

在边缘处用垂直线绘制误差条。

"E2"

用矩形绘制误差线。

"E3"

通过垂直误差线的端点绘制填充区域。

"E4"

通过误差线的端点绘制平滑的填充区域。

"E5"

与 E3 类似,但忽略内容为 0 的bin。

"E6"

与 E4 类似,但忽略内容为 0 的bin。

"X0"

当与“E”选项之一一起使用时,它会像 gStyle->SetErrorX(0) 那样抑制沿 X 的误差条。

"L"

画一条线穿过bin。

"P"

在除空箱之外的每个箱处绘制当前标记。

"P*"

在除空垃圾箱之外的每个垃圾箱上画一个星形标记。

"P0"

在每个仓(包括空仓)处绘制当前标记。y bins.

"PIE"

将直方图绘制为饼图。

"*H"

在每个 bin 处绘制带有 * 的直方图。

"LF2"

像选项“L”一样绘制直方图,但有填充区域。 请注意,如果设置了直方填充颜色,但填充区域对应于直方图轮廓,则“L”也会绘制填充区域。

二维直方图

创建 2D histogram 的标准写法是(参数可以省略):

TH2* h2 = new TH2F("h2", "h2 title; x title; y title", x bins, x min, x max, y bins, y min, y max);

二维直方图方向投影

二维直方图的 x 轴、y 轴统计信息支持投影。将 Hist2 的 x 轴统计信息投影给 Hist1:

aotu Hist1 = new TH1D;
Hist1 = Hist2->ProjectionX();

二维直方图区域剪切

修改二维直方图显示区域使用类TCutG

void h2_cut() {
   const int n = 6;
   Float_t x[6] = { 1, 2,  1, -1, -2, -1 };
   Float_t y[6] = { 2, 0, -2, -2,  0,  2 };
   TCutG *cut = new TCutG("cut", 6, x, y);
   TH2F *hist = new TH2F("hist", "Histogram with cut", 40, -10., 10., 40, -10., 10.);
   for (int i = 0; i < 100000; i++)
      hist->Fill(gRandom->Gaus(0., 3.), gRandom->Gaus(0., 3.));
   TCanvas *c1 = new TCanvas("c1", "Histogram draw with TCutG", 600, 900);
   hist->Draw("col [cut]");
   cut->Draw("l");
}

绘图选项

支持2D直方图的选项

Option Description

"ARR"

箭头模式。 显示相邻单元格之间的梯度。

"BOX"

为每个单元格绘制一个盒子,其表面积与内容的绝对值成比例。 负内容用 X 标记。

"BOX1"

为每个单元格绘制一个按钮,其表面与内容的绝对值成比例。 凹陷的按钮表示负值,凸起的按钮表示正值。

"COLZ"

为bin绘制颜色与调色板,为0值填充颜色。

"COL2"

“COL”的替代渲染算法。 可以显着提高大型非稀疏二维直方图的渲染性能。

"COLZ2"

与“COL2”相同。 此外,还绘制了调色板。

"Z CJUST"

I与颜色选项“COL”、“CONT0”等结合使用:在颜色边界处对齐调色板中的标签。 有关更多详细信息,请参阅 TPaletteAxis

"CANDLE"

沿 X 轴绘蜡烛图。

"CANDLEX"

与“CANDLE”相同。

"CANDLEY"

沿 Y 轴绘制蜡烛图。

"CANDLEXn"

沿 X 轴绘制蜡烛图。 n 为 1 到 6 的不同蜡烛样式。

"CANDLEYn"

沿 Y 轴绘制蜡烛图。 n 为 1 到 6 的不同蜡烛样式。

"VIOLIN"

沿 X 轴绘制小提琴图。is.

"VIOLINX"

与“VIOLIN”相同。

"VIOLINY"

沿 Y 轴绘制小提琴图。

"VIOLINXn"

沿 X 轴绘制小提琴图。 n 为 1 或 2 的不同小提琴风格。

"VIOLINYn"

沿 Y 轴绘制小提琴图。 n 为 1 或 2 的不同小提琴风格。

"CONT"

D绘制等值线图/等高线图(与 CONT0 相同)。

"CONT0"

使用表面颜色绘制等高线图以区分等高线。

"CONT1"

使用线条样式绘制等高线图以区分等高线。

"CONT2"

对所有等高线使用相同的线条样式绘制等高线图。

"CONT3"

使用填充区域颜色绘制等高线图。cont3 colz 合用有奇效

"CONT4"

使用表面颜色绘制等高线图。

"LIST"

为每个轮廓生成 TGraph 对象的列表。

"SAME0"

与“SAME”相同,但不使用第一个图的 z 轴范围。

"SAMES0"

与“SAMES”相同,但不使用第一个图的 z 轴范围。

"CYL"

使用圆柱坐标。 X 坐标映射在角度上,Y 坐标映射在圆柱长度上。

"POL"

使用极坐标。 X 坐标映射在角度上,Y 坐标映射在半径上。

"SPH"

使用球坐标。 X 坐标映射在纬度上,Y 坐标映射在经度上。

"PSR"

使用 PseudoRapidity/Phi 坐标。 X 坐标映射在 Phi 上。

"SURF"

绘制去除隐藏线的曲面图。

"SURF1"

绘制去除隐藏曲面的曲面图。

"SURF2"

使用颜色绘制曲面图以显示单元内容。

"SURF3"

与 SURF 相同,但在顶部绘制了轮廓视图。

"SURFn"

使用 Gouraud 着色绘制表面,4,5,6,7。

"TRI1"

连线绘制各点

E.g. COLZ与COLZ1的区别在于是否为空bin上色
{
   auto c1 = new TCanvas("c1","c1",600,600);
   c1->Divide(1,2);
   auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
   auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
   float px, py;
   for (Int_t i = 0; i < 25000; i++) {
      gRandom->Rannor(px,py);
      hcol23->Fill(px,5*py);
      hcol24->Fill(px,5*py);
   }
   hcol23->Fill(0.,0.,-200.);
   hcol24->Fill(0.,0.,-200.);
   c1->cd(1); hcol23->Draw("COLZ");
   c1->cd(2); hcol24->Draw("COLZ1");
}
E.g. POL
{
   auto c1 = new TCanvas("c1","c1",600,400);
   auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
   float px, py;
   for (Int_t i = 0; i < 25000; i++) {
      gRandom->Rannor(px,py);
      hcol1->Fill(px,py);
   }
   hcol1->Draw("COLZPOL");
}
E.g. COUNTZ
{
   auto c1 = new TCanvas("c1","c1",600,400);
   auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
   float px, py;
   for (Int_t i = 0; i < 25000; i++) {
      gRandom->Rannor(px,py);
      hcontz->Fill(px-1,5*py);
      hcontz->Fill(2+0.5*px,2*py-10.,0.1);
   }
   hcontz->Draw("CONTZ");
}
E.g. LEGO2Z
{
   auto c2 = new TCanvas("c2","c2",600,400);
   auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
   float px, py;
   for (Int_t i = 0; i < 25000; i++) {
      gRandom->Rannor(px,py);
      hlego2->Fill(px-1,5*py);
      hlego2->Fill(2+0.5*px,2*py-10.,0.1);
   }
   hlego2->Draw("LEGO2Z");
}
E.g. SURF1
{
   auto c2 = new TCanvas("c2","c2",600,400);
   auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
   float px, py;
   for (Int_t i = 0; i < 25000; i++) {
      gRandom->Rannor(px,py);
      hsurf1->Fill(px-1,5*py);
      hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
   }
   hsurf1->Draw("SURF1");
}
E.g. Cont3 and COLZ
 {
   TCanvas *c1 = new TCanvas();
   gStyle->SetOptStat(0);
   TH2F *h1 = new TH2F("h1","h1",50,-4,4,50,-4,4);
   Double_t a,b;
   for (Int_t i=0;i<306500;i++) {gRandom->Rannor(a,b);h1->Fill(a-1.5,b-1.5);}

   for (Int_t i=0;i<550;i++) {h1->Fill(3.5,3);}
   for (Int_t i=0;i<450;i++) {h1->Fill(3.5,2);}
   for (Int_t i=0;i<350;i++) {h1->Fill(3.5,1);}
   for (Int_t i=0;i<250;i++) {h1->Fill(3.5,0);}
   for (Int_t i=0;i<150;i++) {h1->Fill(3.5,-1);}
   for (Int_t i=0;i< 50;i++) {h1->Fill(3.5,-2);}
   for (Int_t i=0;i<  5;i++) {h1->Fill(3.5,-3);}

   double contours[4];
   contours[0] = 3;
   contours[1] = 100;
   contours[2] = 900;
   contours[3] = 1500;


   h1->DrawCopy("colz");
   h1->SetContour(4,contours);
   h1->Draw("cont3 same");
   h1->SetLineColor(kRed);
}

直方图是通过THistPainter类绘制的。 每个直方图都有一个指向自己画家的指针(可用于多线程程序)。 支持许多绘图选项。 有关更多详细信息,请参阅THistPainter::Paint()。

可以在不同的垫子上用不同的选项绘制相同的直方图。 当在垫子上绘制的直方图被删除时,直方图会自动从绘制的垫子上删除。 如果在垫子上绘制直方图,然后再次填充,那么下次更新垫子时,直方图的新状态将自动显示在垫子中。 人们不需要重新绘制直方图。 要在垫子上绘制当前版本的直方图,可以使用

h->DrawCopy();

这使直方图成为克隆(见下面的克隆)。 一旦绘制了克隆,原始直方图可能会被修改或删除,而不会影响克隆的方面。

可以使用TH1::SetMaximum()和TH1::SetMinimum()强制绘制上最大或最小尺度的特定值。 (对于一维直方图,这意味着y轴,而对于二维直方图,这些函数会影响z轴)。

TH1::UseCurrentStyle()可用于更改所有直方图图形属性,以对应当前选择的样式。 必须为每个直方图调用此函数。 如果从文件中读取和绘制许多直方图,可以通过在gROOT->ForceStyle()之前调用来强制直方图自动继承当前的图形样式。

TProfile

TProfile可以看作是THistogram的一种特殊情况,用于处理两个变量之间的关系。在实际使用中,THistogram通常用于表示数据的分布情况,而TProfile用于表示两个变量之间的关系。

属性设置与成果保存

TGraph

直方图运算

E.g. XY双高斯2维histogram
{
   TH2D h2("h2","Histogram filled with random numbers",40,-4,4,40,-20,20);
   float px, py;
   for (int i = 0; i < 25000; i++) {
      gRandom->Rannor(px,py);
      h2.Fill(px,5*py);
   }
   h2.DrawCopy("LEGO1");
}
E.g. 1维高斯和2维高斯投影,及多种2维展示风格
void histogram2D(){
    TCanvas *c = new TCanvas("c","c",800,1200);
    c->Divide(2,3); 
    //新建画布800*1200,布局为2*3,横*高,主函数名需与文件名一致,即该文件名为"histogram3D.c"
    float x,y;
    TH1F *h1 = new TH1F("h1","1D histogram",50,-10,10);
    TH2F *h2 = new TH2F("h2","2D histogram",50,-10,10,50,-10,10);
    TH2F *h3 = new TH2F("h3","2D histogram",50,-10,10,50,-10,10);
    TH1D *ph;   //一维投影
 
    for (int i=0;i<30000;i++){
        x=gRandom->Gaus(0,0.5);
        y=gRandom->Gaus(0,1);
        h1->Fill(3*x);
        h2->Fill(x,y);
        h3->Fill(x,y);
    }

    c->cd(1);
    h1->Draw();
    c->cd(2);
    h2->Draw("lego");
    c->cd(3);
    h3->Draw("lego2");
    c->cd(4);
    ph = h2->ProjectionX();
    ph->SetTitle("The projection of n2 on X");
    ph->Draw();
}

命令行中也可以对画布进行操作,例如为现有画布新建图像

root [1] c->cd(5)
(TVirtualPad *) 0x376dbd0
root [2] TF1 *f1 = new TF1("f1","sin(x)/x",-10,10)
(TF1 *) 0x3b2d290
root [3] f1->Draw()
root [4] 

堆积和堆叠

THStackTH1TH2直方图的集合。 通过使用THStack::Draw(),根据指定的绘图选项一次性绘制整个直方图集合。

THStack::Add()允许向列表中添加新的直方图。

默认情况下,直方图显示为堆积。

Stack的绘图选项:

NOSTACK,直方图都画在同一个垫子上,以“堆叠”的形式展示。

NOSTACKB,以条形图形式绘制在一起。

PADS,将当前的垫子/画布细分为等于直方图数量的垫子数量,并将每个直方图绘制成一个单独的垫子。

NOCLEAR,默认情况下,在绘制直方图之前,会擦除直方图的背景。 “不明确”选项避免了这种行为。 这在另一个绘图上绘制THStack非常有用。 如果用于绘制堆栈中直方图的图案是透明的,那么后面的绘图将可见。

E.g. 多个绘图选项
{
   auto hs = new THStack("hs","");
   auto h1 = new TH1F("h1","test hstack",10,-4,4);
   h1->FillRandom("gaus",20000);
   h1->SetFillColor(kRed);
   hs->Add(h1);
   auto h2 = new TH1F("h2","test hstack",10,-4,4);
   h2->FillRandom("gaus",15000);
   h2->SetFillColor(kBlue);
   hs->Add(h2);
   auto h3 = new TH1F("h3","test hstack",10,-4,4);
   h3->FillRandom("gaus",10000);
   h3->SetFillColor(kGreen);
   hs->Add(h3);
   auto cs = new TCanvas("cs","cs",10,10,700,900);
   TText T; T.SetTextFont(42); T.SetTextAlign(21);
   cs->Divide(2,2);
   cs->cd(1); hs->Draw(); T.DrawTextNDC(.5,.95,"Default drawing option");
   cs->cd(2); hs->Draw("nostack"); T.DrawTextNDC(.5,.95,"Option \"nostack\"");
   cs->cd(3); hs->Draw("pads"); //T.DrawTextNDC(.5,.95,"Option \"nostackb\"");
   cs->cd(4); hs->Draw("nostackb"); T.DrawTextNDC(.5,.95,"Option \"nostackb\"");
}
E.g. 绘图选项“lego1”
#include "TCanvas.h"
#include "TH2.h"
#include "THStack.h"
#include "TRandom.h"
 
//void multicolor(Int_t isStack=0) {
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");
}

统计面板

统计面板会统计一些图形信息并展示在画布上,默认绘制,当不需要展示时,使用TH::SetStats(0)或TStyle::SetOptStat(0)函数关闭。

TH1F *hist = new TH1F("hist", "Histogram", 100, 0, 100); // 创建一个直方图
hist->SetStats(0); // 关闭统计面板

统计面板选项

直方图统计框中打印的信息类型可以通过参数模式选择。

参数模式可以是= ksiourmen和数字。

K = 1:峰度打印;K = 2:打印kurtosis和kurtosis错误,峰度是描述概率分布形状尖峭程度的统计量。

S = 1:偏度打印;S = 2:打印偏度和偏度错误,参考

I = 1:打印垃圾箱的积分;I = 2:打印选项“宽度”的垃圾箱积分。

O = 1:打印溢出数。

U = 1:打印下溢出数。

R = 1:rms打印;R = 2:rms和rms错误打印。

M = 1:打印的平均值;M = 2:打印平均值和平均误差值。

E = 1:打印事例数。

N = 1:打印直方图的名称。

示例:gStyle->SetOptStat(11),仅打印直方图名称和条目数量。gStyle->SetOptStat(1101),显示直方图名称、平均值和RMS。

备注:

切勿调用SetOptStat(000111),而应该使用SetOptStat(111)

SetOptStat(1)是允许设置最常见的情况的快捷方式,并被视为SetOptStat(1111)(用于与旧版本的向后兼容)。 如果只想打印直方图的名称,请调用SetOptStat(1000000001)

对于二维直方图,当仅选择下溢出(10000)或溢出(100000)时,统计框将显示下溢出/溢出的所有组合,而不仅仅是一个数字!

统计面板位置

当使用选项“SAME”绘制直方图时,root 不会绘制新的统计框。强制绘制必须使用参数“SAMES”。如果新的统计框隐藏了前一个统计框,则可以使用以下行更改其位置(“h”是指向直方图的指针):

    TPaveStats *st = (TPaveStats*)h->FindObject("stats")
    st->SetX1NDC(newx1); //new x start position
    st->SetX2NDC(newx2); //new x end position

TStyle::SetStatTextColor(颜色_t 颜色=1


参考

https://root.cern/doc/master/classTHistPainter.html

2维直方图保存为PDF出现渲染错误:https://root-forum.cern.ch/t/colored-2d-histograms-in-pdf-output/13822/109

最后更新于