【ROOT from CERN】——TFunction绘制函数图像

2023-10-17 02:20

本文主要是介绍【ROOT from CERN】——TFunction绘制函数图像,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ROOT使用TFunction类来绘制函数图像,并且用作含参数函数对于TGraph与THistogram的拟合。本文只总结了官网上部分代码和最最常用的构造函数等。如果能读透做很大一部分图像完全没问题。有些部分我会使用英语。

一、继承关系-Inheritance

如图所示,TF1为一维函数图像,TF2为二维函数图像,TF12为二维函数图像沿x或y的一维图像,TF3为三维函数图像。

二、构造函数-Constructor

1、TF1

TF1::TF1 	( 	const char *  	name,const char *  	formula,Double_t  	xmin,Double_t  	xmax,Option_t *  	option )

在我们调用该构造函数时,通常不对最后一个Option_t*的变量进行赋值。C++的构造函数允许这样做,其本身具有默认初始化的值。关于最后一个变量的作用,不在这里展开,但是我把source文件里的注释放在下边(可以忽略)。暂时用不到,我也没完全弄懂。更多的构造函数形式,我会把参考文档附在文尾。

Same constructor as above (for TFormula based function) but passing an option strings
/// available options
/// VEC - vectorize the formula expressions (not possible for lambda based expressions)
/// NL  - function is not stores in the global list of functions
/// GL  - function will be always stored in the global list of functions ,
///        independently of the global setting of TF1::DefaultAddToGlobalList

(1)Expression using variable x and no parameters

Case 1: inline expression using standard C++ functions/operators

插入一个解释,此处的inline关键字被称为内联。用该关键字修饰的函数将被C++编译器解释为内联函数。您可以在《C++ Prime Plus》的8.1章节“C++内联函数”找到该语法的详细解释。

在本示例内,我们将创建一个C++标准库所拥有的函数,并且表达式内没有参数。

Example:

TF1 *fa1 = new TF1("fa1","sin(x)/x",0,10);
fa1->Draw();

Case 2: inline expression using a ROOT function (e.g. from TMath) without parameters

在本示例内,我们将创建一个TMath库所拥有的函数,并且表达式内没有参数。

Example:

TF1 *fa2 = new TF1("fa2","TMath::DiLog(x)",0,10);
fa2->Draw();

Case 3: inline expression using a user defined CLING function by name

此处的CLING为ROOT开发的C++解释器的名字。就是在Terminal中输入root打开的“ROOT的环境”,在该解释器环境中,C++将具有类似Python进行步进解释的性质。

在本示例内,我们将自定义一个C++函数,其返回表达式的函数值,并且表达式内没有参数。

Example:

Double_t myFunc(double x) { return x+sin(x); }
....
TF1 *fa3 = new TF1("fa3","myFunc(x)",-3,5);
fa3->Draw();

(2)Expression using variable x with parameters

Case 1: inline expression using standard C++ functions/operators

在本示例内,我们将创建一个C++标准库所拥有的函数,并且表达式内含有参数。该参数运用方括号和数字表示,并需要对参数进行初始化。

Example:

TF1 *fa = new TF1("fa","[0]*x*sin([1]*x)",-3,3);//This creates a function of variable x with 2 parameters. The parameters must be initialized via:
//fa->SetParameter(0,value_first_parameter);
//fa->SetParameter(1,value_second_parameter);
fa->SetParameter(0,1);
fa->SetParameter(1,1);//Parameters may be given a name:
fa->SetParName(0,"Constant");

特别地,对于TMath内置的一些含参函数,我们进行函数的四则运算形成的新的函数,其参数列表的排列我们拥有下列的形式:

Example:

TF1 *fb = new TF1("fb","gaus(0)*expo(3)",0,10);

gaus(0) is a substitute for[0]*exp(-0.5*((x-[1])/[2])**2) and (0) means start numbering parameters at 0.expo(3) is a substitute for exp([3]+[4]*x).

该示例内所引用的高斯函数和指数函数分别具有三个参数和两个参数。分别占据参数列表的0,1,2和3,4的位置,小括号内的数字表示本函数参数的起始位置。但是这两个函数可以归为C++的标准库吗,先放一个问号在这。

Case 2: inline expression using TMath functions with parameters

在本示例内,我们将创建一个TMath库所拥有的函数,并且表达式内含有参数。

TF1 *fb2 = new TF1("fa3","TMath::Landau(x,[0],[1],0)",-5,10);
//fb2->SetParameters(value_first_parameter,value_second_parameter);
fb2->SetParameters(0.2,1.3);
fb2->Draw();

关于TMath库的函数,之后再出一篇吧。

(3)A lambda expression with variables and parameters

这是ROOT提供的一种并不常用的构造方式,各位大可忽略,接着我会介绍一种更加普遍的形式。

TF1 f1("f1","sin(x)",0,10);
TF1 f2("f2","cos(x)",0,10);
TF1 fsum("f1","[&](double *x, double *p){ return p[0]*f1(x) + p[1]*f2(x); }",0,10,2);

(4)A general C function with parameters

本形式是含参函数TF1类构造的一种相当常见而且重要的形式,该形式常被用于函数的拟合。该示例给出的就是一个拟合脚本。注意引用自定义函数名时不需要加引号。

// Macro myfunc.C
Double_t myfunction(Double_t *x, Double_t *par)
{Float_t xx =x[0];Double_t f = TMath::Abs(par[0]*sin(par[1]*xx)/xx);return f;
}
void myfunc()
{TF1 *f1 = new TF1("myfunc",myfunction,0,10,2);f1->SetParameters(2,1);f1->SetParNames("constant","coefficient");f1->Draw();
}
void myfit()
{TH1F *h1=new TH1F("h1","test",100,0,10);h1->FillRandom("myfunc",20000);TF1 *f1 = (TF1 *)gROOT->GetFunction("myfunc");f1->SetParameters(800,1);h1->Fit("myfunc");
}

该示例就是将本节(3)中的表达式单独拆分为一个函数Double_t myfunction(Double_t *x, Double_t *par),该函数拥有两个参数,分别是自变量列表和参数列表。关于函数的拟合我会在之后单独写一篇文章。

2、TF2

TF2::TF2 	( 	const char *  	name,const char *  	formula,Double_t  	xmin = 0,Double_t  	xmax = 1,Double_t  	ymin = 0,Double_t  	ymax = 1,Option_t *  	opt = nullptr ) 	

此处的opt我们平时也忽略,这里不再展开。

(1)Expression using variables x and y

与上述TF1的情况(1)类似。

Example:

TF2 *f2 = new TF2("f2","sin(x)*sin(y)/(x*y)",0,5,0,5);
f2->Draw();

但需要注意的是,一维函数即具有两个轴。而TF2仍然具有两个轴,也就意味着这本质上是一张平面投影图,只不过官方给出的事例不够明显。这里我更改绘图风格,使用f2->Draw(“COLZ”);得到下图,其特点更加直观:

(2)Expression using a user defined function

与上述TF1的情况(4)类似。

Example:

Double_t func(Double_t *val, Double_t *par)
{Float_t x = val[0];Float_t y = val[1];Double_t f = x*x-y*y;return f;
}void fplot()
{TF2 *f = new TF2("f",func,-1,1,-1,1);f->Draw("surf1");
}

需要注意的是,虽然具有三根轴,但其实际上是一个TF2类,只不过我们更改了作图风格为SURF1,仅此而已。

(3) Lambda Expression with x and y variables and parameters

与上述TF1的情况(3)类似。

Example:

TF2 f2("f2", [](double* x, double*p) { return x[0] + x[1] * p[0]; }, 0., 1., 0., 1., 1)
f2.SetParameter(0, 1.)
f2.Eval(1., 2.)

在这里插入一个解释,可以看到的是,在此类集成度高的语句的函数中,有一个[]或[&],这是C++11的新特性,被称为匿名函数

[] 不截取任何变量

[&] 截取外部作用域中所有变量,并作为引用在函数体中使用

[=] 截取外部作用域中所有变量,并拷贝一份在函数体中使用

3、TF12

TF12::TF12 	( 	const char *  	name,TF2 *  	f2,Double_t  	xy,Option_t *  	option = "x" ) 	

显然,该构造函数依托于TF2类,其需要先存在一个二维图像,其中的option的“x”或“y”选择投影到X或Y轴。下例就是在x=0.1处沿Y轴进行投影。

Example:

TF2 *f2 = new TF2("f2","sin(x)*sin(y)/(x*y)",0,5,0,5);
TF12 *f12 = new TF12("f12",f2,0.1,"y");
f12->Draw();

4、TF3

TF3::TF3 	( 	const char *  	name,const char *  	formula,Double_t  	xmin = 0,Double_t  	xmax = 1,Double_t  	ymin = 0,Double_t  	ymax = 1,Double_t  	zmin = 0,Double_t  	zmax = 1,Option_t *  	opt = nullptr ) 	

自前文一路看下来的读者已经发现了。“真正的”三维函数作图需要四根轴,很明显人类的视觉已经不够用了(赶紧考虑升一个维度)。官方也没有给出示例。拟合的效用可能远大于绘图。

当然用色块填充样式它可以表示三维物体的体积密度或者三维空间内某种粒子的通量。但对于Draw()方法而言,目前作出的图像形式比较奇怪,不论笔者如何更改作图风格,它似乎是通过点(0,0,0)的一个恒为零的面。有懂行的朋友可以给我讲一下。

Example:

Double_t func(Double_t *val, Double_t *par)
{Float_t x = val[0];Float_t y = val[1];Float_t z = val[2];Double_t f = sin(x)+sin(y)+sin(z);return f;
}void fplot()
{TF3 *f = new TF3("f",func,-1,1,-1,1,-1,1);f->Draw();
}

三、常用方法

1、含参函数的参数初始化

(1)初始化参数值

virtual void TF1::SetParameter 	( 	Int_t  	param,Double_t  	value ) 	

 单值设置。

virtual void TF1::SetParameters 	( 	Double_t  	p0,Double_t  	p1,Double_t  	p2 = 0,Double_t  	p3 = 0,Double_t  	p4 = 0,Double_t  	p5 = 0,Double_t  	p6 = 0,Double_t  	p7 = 0,Double_t  	p8 = 0,Double_t  	p9 = 0,Double_t  	p10 = 0 )

批量设置,从0开始。 

(2)赋参数名

void TF1::SetParName 	( 	Int_t  	ipar,const char *  	name ) 	

 单值设置。

void TF1::SetParNames 	( 	const char *  	name0 = "p0",const char *  	name1 = "p1",const char *  	name2 = "p2",const char *  	name3 = "p3",const char *  	name4 = "p4",const char *  	name5 = "p5",const char *  	name6 = "p6",const char *  	name7 = "p7",const char *  	name8 = "p8",const char *  	name9 = "p9",const char *  	name10 = "p10" ) 	

 批量设置,从0开始,参量名字符串用引号括起。

2、函数积分-Integral

(1)TF1

Double_t TF1::Integral 	( 	Double_t  	a,Double_t  	b,Double_t  	epsrel = 1.e-12 ) 	

epsrel的值是积分结果的相对容差,具有默认值,下同。

(2)TF2

Double_t TF2::Integral 	( 	Double_t  	ax,Double_t  	bx,Double_t  	ay,Double_t  	by,Double_t  	epsrel = 1.e-6 ) 	

(3)TF3 

Double_t TF3::Integral 	( 	Double_t  	ax,Double_t  	bx,Double_t  	ay,Double_t  	by,Double_t  	az,Double_t  	bz,Double_t  	epsrel = 1.e-6 )

【资料】

1、ROOT官网——ROOT: analyzing petabytes of data, scientifically. - ROOT 

2、ROOT文档——ROOT: Function classes.

3、ROOT的TF1实现——ROOT: hist/hist/src/TF1.cxx Source File

后续还会不断更新,如有错误请指正。

这篇关于【ROOT from CERN】——TFunction绘制函数图像的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/222281

相关文章

基于WinForm+Halcon实现图像缩放与交互功能

《基于WinForm+Halcon实现图像缩放与交互功能》本文主要讲述在WinForm中结合Halcon实现图像缩放、平移及实时显示灰度值等交互功能,包括初始化窗口的不同方式,以及通过特定事件添加相应... 目录前言初始化窗口添加图像缩放功能添加图像平移功能添加实时显示灰度值功能示例代码总结最后前言本文将

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素