概述

ROOT是一个面向对象的数据分析框架,主要用于高能物理领域,但也广泛应用于其他科学领域。它由CERN开发,提供了一系列强大的工具来处理、分析和可视化大规模数据。

ROOT框架提供了完整的数据分析解决方案,从基础的数据结构到高级的多变量分析工具。通过上述示例,我们可以看到:

  1. 灵活性: 支持从简单直方图到复杂多变量分析的各种需求
  2. 性能: 优化的I/O系统和多线程支持处理大规模数据
  3. 可视化: 丰富的绘图功能和交互式界面
  4. 可扩展性: 易于扩展自定义类和算法

核心功能模块

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})
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐