显示动态切片的二维直方图是数据处理中常用的方法。本文根据ROOT官方教程DynamicSlice.C介绍如何制作显示动态切片并且高斯拟合。
首先通过Rannor函数对二维直方图进行填充,然后通过AddExec函数对图像进行切片展示。
下面给出具体代码步骤:
创建一个画板:
TCanvas* c1 = new TCanvas("c1","Dynamic Slice Example",10,10,700,500);
创建一个二维直方图:
TH2F *hpxpy = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4);
设置直方图不显示统计信息:
hpxpy->SetStats(0);
用随即函数rannor生成的标准正态伪随机数填充直方图:
Double_t px,py;
for (Int_t i = 0; i < 50000; i++) {
gRandom->Rannor(px,py);
hpxpy->Fill(px,py);
}
绘制彩色直方图:
hpxpy->Draw("col");
将TExec对象添加到画布:
c1->AddExec("dynamic","DynamicExec()");
其中`DynamicExec()`为:当在画板中出现鼠标事件时调用的函数。在画布中移动鼠标时,第二个画布显示与对象的Y位置相对应的bin沿X的投影。 生成的直方图拟合高斯。 “动态”线显示了Y中当前bin的位置。这个更详细的示例可以用作使用Cling作为开发引擎来开发功能更强大的交互式应用程序。下面为DynamicExec()函数内容:
定义对象存储为指针选择参数:
TObject *select = gPad->GetSelected();
判断指针是否在直方图上:
if(!select) return;
if (!select->InheritsFrom(TH2::Class())) {gPad->SetUniqueID(0); return;}
创建二维直方图类h继承select对象:
TH2 *h = (TH2*)select;
打开画板rubberband反馈模式:
gPad->GetCanvas()->FeedbackMode(kTRUE);
删除旧位置并在当前位置画一条线:
int pyold = gPad->GetUniqueID(); //返回唯一的对象ID
int px = gPad->GetEventX(); //获取X事件数量
int py = gPad->GetEventY(); //获取Y事件数量
float uxmin = gPad->GetUxmin(); //返回画板可见的最小x坐标值;如果是对数轴,则返回的值以数十为单位
float uxmax = gPad->GetUxmax(); //返回垫上可见的最大x坐标值;如果是对数轴,则返回的值以数十为单位
int pxmin = gPad->XtoAbsPixel(uxmin); //获取uxmin值的像素
int pxmax = gPad->XtoAbsPixel(uxmax); //获取uxmax值的像素
if(pyold) gVirtualX->DrawLine(pxmin,pyold,pxmax,pyold); //用新坐标画这条线
gVirtualX->DrawLine(pxmin,py,pxmax,py); //如果光标移出图像,保留直线
gPad->SetUniqueID(py); //设置唯一的对象ID
Float_t upy = gPad->AbsPixeltoY(py); //return fAbsPixeltoYk + py*fPixeltoY;
Float_t y = gPad->PadtoY(upy); //将upy从pad转换为y
创建或设置新画布c2:
TVirtualPad *padsav = gPad;
TCanvas *c2 = (TCanvas*)gROOT->GetListOfCanvases()->FindObject("c2"); //使用对象名称c2查找对象
if(c2) delete c2->GetPrimitive("Projection");
else c2 = new TCanvas("c2","Projection Canvas",710,10,700,500);
c2->SetGrid(); //设置网格
c2->cd();
绘制与鼠标位置相对应的切片:
Int_t biny = h->GetYaxis()->FindBin(y);
TH1D *hp = h->ProjectionX("",biny,biny);
hp->SetFillColor(38); //设置填充颜色
char title[80];
sprintf(title,"Projection of biny=%d",biny); //定义标题名称
hp->SetName("Projection");
hp->SetTitle(title); //设置标题
hp->Fit("gaus","ql"); //进行高斯拟合
hp->GetFunction("gaus")->SetLineColor(kRed); //设置拟合线颜色
hp->GetFunction("gaus")->SetLineWidth(6); //设置拟合线粗细
c2->Update();
padsav->cd();
代码地址:https://github.com/root-project/root/blob/master/tutorials/hist/DynamicSlice.C