ROOT C++库功能详解与源代码示例
·
概述
ROOT是一个面向对象的数据分析框架,主要用于高能物理领域,但也广泛应用于其他科学领域。它由CERN开发,提供了一系列强大的工具来处理、分析和可视化大规模数据。
ROOT框架提供了完整的数据分析解决方案,从基础的数据结构到高级的多变量分析工具。通过上述示例,我们可以看到:
- 灵活性: 支持从简单直方图到复杂多变量分析的各种需求
- 性能: 优化的I/O系统和多线程支持处理大规模数据
- 可视化: 丰富的绘图功能和交互式界面
- 可扩展性: 易于扩展自定义类和算法
核心功能模块
1. 基础数据类型和容器
TObject基类
// 所有ROOT对象的基类
class MyClass : public TObject {
private:
Int_t fValue;
public:
MyClass() : fValue(0) {}
MyClass(Int_t val) : fValue(val) {}
void SetValue(Int_t val) { fValue = val; }
Int_t GetValue() const { return fValue; }
void Print(Option_t* option = "") const override {
std::cout << "Value: " << fValue << std::endl;
}
ClassDef(MyClass, 1) // 支持ROOT的I/O系统
};
容器类
// TList示例
void list_example() {
TList* list = new TList();
// 添加对象
for (int i = 0; i < 5; i++) {
list->Add(new TNamed(Form("obj%d", i), Form("Object %d", i)));
}
// 遍历列表
TIter next(list);
TObject* obj;
while ((obj = next())) {
std::cout << obj->GetName() << std::endl;
}
list->Delete();
delete list;
}
// THashList示例
void hashlist_example() {
THashList* hashList = new THashList();
hashList->Add(new TNamed("key1", "value1"));
hashList->Add(new TNamed("key2", "value2"));
// 快速查找
TNamed* found = dynamic_cast<TNamed*>(hashList->FindObject("key1"));
if (found) {
std::cout << "Found: " << found->GetTitle() << std::endl;
}
hashList->Delete();
delete hashList;
}
2. 直方图处理
一维直方图
void histogram_1d() {
// 创建直方图
TH1F* hist = new TH1F("h1", "Example Histogram", 100, -5, 5);
// 填充数据
TRandom3 rnd;
for (int i = 0; i < 10000; i++) {
hist->Fill(rnd.Gaus(0, 1));
}
// 设置样式
hist->SetFillColor(kBlue);
hist->SetLineColor(kBlack);
// 绘制
TCanvas* c1 = new TCanvas("c1", "Histogram", 800, 600);
hist->Draw();
// 统计信息
std::cout << "Entries: " << hist->GetEntries() << std::endl;
std::cout << "Mean: " << hist->GetMean() << std::endl;
std::cout << "RMS: " << hist->GetRMS() << std::endl;
}
二维直方图
void histogram_2d() {
TH2F* hist2d = new TH2F("h2d", "2D Histogram",
50, -5, 5, 50, -5, 5);
TRandom3 rnd;
for (int i = 0; i < 50000; i++) {
double x = rnd.Gaus(0, 1);
double y = rnd.Gaus(0, 1) + 0.5 * x;
hist2d->Fill(x, y);
}
TCanvas* c1 = new TCanvas("c1", "2D Hist", 800, 600);
hist2d->Draw("colz"); // 使用颜色表示密度
// 添加轮廓
hist2d->SetContour(20);
hist2d->Draw("cont same");
}
3. 图形绘制
基础图形
void basic_graphics() {
// 创建画布
TCanvas* canvas = new TCanvas("canvas", "Graphics Example", 1000, 800);
canvas->Divide(2, 2); // 2x2网格
// 第一个子图:函数绘制
canvas->cd(1);
TF1* func = new TF1("func", "sin(x)/x", -10, 10);
func->SetLineColor(kRed);
func->SetLineWidth(2);
func->Draw();
// 第二个子图:数据点
canvas->cd(2);
TGraph* graph = new TGraph();
for (int i = 0; i < 10; i++) {
graph->SetPoint(i, i, i*i);
}
graph->SetMarkerStyle(20);
graph->SetMarkerColor(kBlue);
graph->Draw("AP"); // A=轴, P=点
// 第三个子图:误差图
canvas->cd(3);
TGraphErrors* grErr = new TGraphErrors();
for (int i = 0; i < 5; i++) {
grErr->SetPoint(i, i*2, i*i);
grErr->SetPointError(i, 0.2, 0.5);
}
grErr->Draw("AP");
// 第四个子图:柱状图
canvas->cd(4);
TH1F* barHist = new TH1F("bar", "Bar Chart", 5, 0, 5);
barHist->SetBinContent(1, 10);
barHist->SetBinContent(2, 25);
barHist->SetBinContent(3, 15);
barHist->SetBinContent(4, 30);
barHist->SetBinContent(5, 20);
barHist->SetFillColor(kGreen);
barHist->Draw("bar");
}
4. 文件I/O操作
TFile使用
void file_io_example() {
// 写入文件
TFile* file = new TFile("example.root", "RECREATE");
TH1F* hist = new TH1F("myhist", "My Histogram", 100, 0, 10);
hist->FillRandom("gaus", 1000);
TTree* tree = new TTree("mytree", "Example Tree");
double x, y;
tree->Branch("x", &x, "x/D");
tree->Branch("y", &y, "y/D");
TRandom3 rnd;
for (int i = 0; i < 1000; i++) {
x = rnd.Gaus(5, 2);
y = rnd.Exp(1);
tree->Fill();
}
// 写入对象
hist->Write();
tree->Write();
file->Close();
delete file;
// 读取文件
TFile* inputFile = new TFile("example.root", "READ");
TH1F* readHist = nullptr;
inputFile->GetObject("myhist", readHist);
if (readHist) {
TCanvas* c1 = new TCanvas();
readHist->Draw();
}
inputFile->Close();
delete inputFile;
}
5. TTree数据处理
创建和填充TTree
void tree_creation() {
TFile* file = new TFile("data.root", "RECREATE");
TTree* tree = new TTree("data", "Example Data Tree");
// 定义分支变量
Int_t eventId;
Float_t energy;
Float_t position[3];
std::vector<Float_t> trackEnergies;
// 创建分支
tree->Branch("eventId", &eventId, "eventId/I");
tree->Branch("energy", &energy, "energy/F");
tree->Branch("position", position, "position[3]/F");
tree->Branch("trackEnergies", &trackEnergies);
// 填充数据
TRandom3 rnd;
for (eventId = 0; eventId < 1000; eventId++) {
energy = rnd.Exp(100);
position[0] = rnd.Gaus(0, 10);
position[1] = rnd.Gaus(0, 10);
position[2] = rnd.Gaus(0, 10);
trackEnergies.clear();
int nTracks = rnd.Poisson(5);
for (int i = 0; i < nTracks; i++) {
trackEnergies.push_back(rnd.Exp(50));
}
tree->Fill();
}
tree->Write();
file->Close();
delete file;
}
TTree读取和分析
void tree_analysis() {
TFile* file = new TFile("data.root", "READ");
TTree* tree = nullptr;
file->GetObject("data", tree);
if (!tree) {
std::cout << "Tree not found!" << std::endl;
return;
}
// 方法1: 使用SetBranchAddress
Float_t energy;
tree->SetBranchAddress("energy", &energy);
TH1F* energyHist = new TH1F("energy", "Energy Distribution", 100, 0, 500);
Long64_t nEntries = tree->GetEntries();
for (Long64_t i = 0; i < nEntries; i++) {
tree->GetEntry(i);
energyHist->Fill(energy);
}
// 方法2: 使用TTree::Draw
TCanvas* c1 = new TCanvas("c1", "Tree Analysis", 1200, 800);
c1->Divide(2, 2);
c1->cd(1);
tree->Draw("energy"); // 简单绘制
c1->cd(2);
tree->Draw("position[0]:position[1]", "", "colz"); // 2D分布
c1->cd(3);
tree->Draw("energy", "energy > 50"); // 带条件绘制
c1->cd(4);
// 使用TSelector进行复杂分析
tree->Draw("trackEnergies.size()"); // 向量大小
file->Close();
delete file;
}
6. 数学工具和拟合
函数拟合
void fitting_example() {
// 创建带噪声的数据
TH1F* dataHist = new TH1F("data", "Data with Noise", 100, 0, 10);
TF1* trueFunc = new TF1("true", "[0]*sin([1]*x)/x", 0, 10);
trueFunc->SetParameters(5, 2);
TRandom3 rnd;
for (int i = 0; i < 1000; i++) {
double x = rnd.Uniform(0.1, 10);
double y = trueFunc->Eval(x) + rnd.Gaus(0, 0.1);
dataHist->Fill(x, y);
}
// 定义拟合函数
TF1* fitFunc = new TF1("fit", "[0]*sin([1]*x)/x", 0, 10);
fitFunc->SetParameters(1, 1); // 初始猜测
fitFunc->SetParNames("Amplitude", "Frequency");
// 执行拟合
TFitResultPtr fitResult = dataHist->Fit(fitFunc, "S"); // S保存结果
// 输出拟合结果
if (fitResult->IsValid()) {
std::cout << "Fit successful!" << std::endl;
std::cout << "Chi2/NDF: " << fitResult->Chi2() << "/"
<< fitResult->Ndf() << std::endl;
std::cout << "Parameters:" << std::endl;
for (int i = 0; i < fitFunc->GetNpar(); i++) {
std::cout << " " << fitFunc->GetParName(i) << " = "
<< fitFunc->GetParameter(i) << " ± "
<< fitFunc->GetParError(i) << std::endl;
}
}
// 绘制结果
TCanvas* c1 = new TCanvas("c1", "Fitting", 800, 600);
dataHist->Draw();
fitFunc->Draw("same");
// 添加图例
TLegend* leg = new TLegend(0.7, 0.7, 0.9, 0.9);
leg->AddEntry(dataHist, "Data", "lep");
leg->AddEntry(fitFunc, "Fit", "l");
leg->Draw();
}
7. 多变量分析
RDataFrame (现代ROOT数据分析)
void rdataframe_example() {
// 创建RDataFrame
ROOT::RDataFrame df(10000);
// 定义计算列和操作
auto df_with_columns = df.Define("x", "gRandom->Gaus(0,1)")
.Define("y", "gRandom->Gaus(1,2)")
.Define("z", "x + y + gRandom->Gaus(0,0.5)");
// 创建直方图
auto hx = df_with_columns.Histo1D("x");
auto hxy = df_with_columns.Histo2D({"hxy", "X vs Y", 50, -5, 5, 50, -5, 5}, "x", "y");
// 过滤数据
auto filtered = df_with_columns.Filter("x > 0 && y < 2");
auto h_filtered = filtered.Histo1D("z");
// 执行所有操作
TCanvas* c1 = new TCanvas("c1", "RDataFrame", 1200, 800);
c1->Divide(2, 2);
c1->cd(1);
hx->Draw();
c1->cd(2);
hxy->Draw("colz");
c1->cd(3);
h_filtered->Draw();
// 显示统计信息
auto count = filtered.Count();
std::cout << "Filtered entries: " << *count << std::endl;
}
8. 高级特性
多线程处理
// 使用IMT (Implicit Multi-Threading)
void enable_imt() {
// 启用多线程
ROOT::EnableImplicitMT();
// 创建大量数据
ROOT::RDataFrame df(1000000);
auto result = df.Define("x", "gRandom->Gaus(0,1)")
.Filter("x > 0")
.Mean("x");
std::cout << "Mean of positive x: " << *result << std::endl;
ROOT::DisableImplicitMT();
}
自定义类与字典生成
// LinkDef.h 文件内容
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class MyDataClass+;
#endif
// MyDataClass.h
class MyDataClass {
private:
std::vector<double> fData;
std::string fName;
public:
MyDataClass() : fName("default") {}
MyDataClass(const std::string& name) : fName(name) {}
void AddData(double value) { fData.push_back(value); }
const std::vector<double>& GetData() const { return fData; }
std::string GetName() const { return fName; }
ClassDef(MyDataClass, 1)
};
编译和运行
编译脚本
#!/bin/bash
# compile_root.sh
# 设置ROOT环境
source /path/to/root/bin/thisroot.sh
# 编译单个文件
g++ -o my_analysis my_analysis.cxx `root-config --cflags --libs`
# 或者使用CMake
CMakeLists.txt示例
cmake_minimum_required(VERSION 3.10)
project(ROOTAnalysis)
find_package(ROOT REQUIRED)
include(${ROOT_USE_FILE})
add_executable(my_analysis my_analysis.cxx)
target_link_libraries(my_analysis ${ROOT_LIBRARIES})
更多推荐

所有评论(0)