イベント数を取得したい(TTree::GetEntries

 1#include <TTree.h>
 2#include <iostream>
 3
 4// TTreeを開く
 5TTree *tree = (TTree *)file->Get("tree");
 6
 7// エントリー数を取得
 8Long64_t nentries = tree->GetEntries();
 9
10std::cout << "エントリー数: " << nentries << std::endl;

TTree::GetEntriesメソッドで、TTreeに格納されているエントリー(イベント)の総数を取得できます。 エントリー数はデータ解析に必要な基本情報で、ループ処理やプログレス表示に重要です。

 1from ROOT import TFile, TTree
 2
 3# ROOTファイルを開く
 4file = TFile("data.root")
 5
 6# TTreeを取得
 7tree = file.Get("tree")
 8
 9# エントリー数を取得
10nentries = tree.GetEntries()
11
12print(f"エントリー数: {nentries}")

メソッドシグネチャ

1Long64_t GetEntries() const;
2Long64_t GetEntries(const char *selection);

TTree::GetEntriesは、TTreeに含まれるデータのエントリー数を返すメソッドです。 エントリーはTTreeの最小データ単位で、通常は1つのイベントに対応します。

引数の説明

selection - フィルター条件(オプション)

  • セレクション文字列を指定することで、条件に合致するエントリー数のみを取得できます

  • ROOTのTCutTEntryListで指定できる条件構文が使用可能です

  • 指定しない場合は全エントリー数が返されます

戻り値

  • Long64_t: エントリー数(64ビット長整数)

  • セレクション引数なしの場合:全エントリー数

  • セレクション引数あり:条件に合致するエントリー数

エントリーとは

エントリー - TTreeの最小データ単位

  • 1行のデータに対応

  • 通常は1つの物理イベントを表現

  • ブランチの葉(リーフ)に格納される値の集合

TTreeの階層構造

TTree(木)
├── Branch1(枝)
│   ├── Leaf1(葉)
│   └── Leaf2(葉)
├── Branch2(枝)
│   └── Leaf3(葉)
└── エントリー1, 2, 3, ... N

各エントリーは、すべてのブランチに1つずつデータを保持します。

エントリー数を取得したい

 1#include <TFile.h>
 2#include <TTree.h>
 3#include <iostream>
 4
 5void get_entries_basic() {
 6    // ROOTファイルを開く
 7    TFile *file = TFile::Open("data.root");
 8
 9    // TTreeを取得
10    TTree *tree = (TTree *)file->Get("mytree");
11
12    // エントリー数を取得
13    Long64_t nentries = tree->GetEntries();
14
15    std::cout << "全エントリー数: " << nentries << std::endl;
16
17    file->Close();
18}

シンプルな用法で、TTreeの全エントリー数を取得できます。

 1from ROOT import TFile
 2
 3# ROOTファイルを開く
 4file = TFile("data.root")
 5
 6# TTreeを取得
 7tree = file.Get("mytree")
 8
 9# エントリー数を取得
10nentries = tree.GetEntries()
11
12print(f"全エントリー数: {nentries}")
13
14file.Close()

単純な条件での取得

 1#include <TFile.h>
 2#include <TTree.h>
 3#include <iostream>
 4
 5void count_entries_with_selection() {
 6    TFile *file = TFile::Open("data.root");
 7    TTree *tree = (TTree *)file->Get("tree");
 8
 9    // 条件に合致するエントリー数を取得
10    // x > 100 の条件を満たすエントリーの数
11    Long64_t n_selected = tree->GetEntries("x > 100");
12
13    std::cout << "x > 100 を満たすエントリー数: " << n_selected << std::endl;
14    std::cout << "全エントリー数: " << tree->GetEntries() << std::endl;
15
16    file->Close();
17}

複合条件での取得

 1#include <TFile.h>
 2#include <TTree.h>
 3#include <iostream>
 4
 5void count_with_complex_selection() {
 6    TFile *file = TFile::Open("data.root");
 7    TTree *tree = (TTree *)file->Get("tree");
 8
 9    // 複数条件を AND / OR で組み合わせ
10    Long64_t n_selected = tree->GetEntries("x > 100 && y < 50");
11
12    std::cout << "(x > 100) AND (y < 50): " << n_selected << " entries" << std::endl;
13
14    // OR 条件
15    Long64_t n_or = tree->GetEntries("x < 0 || y > 200");
16
17    std::cout << "(x < 0) OR (y > 200): " << n_or << " entries" << std::endl;
18
19    file->Close();
20}

Python でセレクション条件を使用

 1from ROOT import TFile
 2
 3file = TFile("data.root")
 4tree = file.Get("tree")
 5
 6# 単純条件
 7n_selected = tree.GetEntries("x > 100")
 8print(f"x > 100 のエントリー数: {n_selected}")
 9
10# 複合条件
11n_and = tree.GetEntries("x > 100 && y < 50")
12print(f"(x > 100) AND (y < 50): {n_and}")
13
14n_or = tree.GetEntries("x < 0 || y > 200")
15print(f"(x < 0) OR (y > 200): {n_or}")
16
17file.Close()

ループ処理したい

 1#include <TFile.h>
 2#include <TTree.h>
 3#include <iostream>
 4
 5void loop_over_entries() {
 6    TFile *file = TFile::Open("data.root");
 7    TTree *tree = (TTree *)file->Get("tree");
 8
 9    // エントリー数を取得
10    Long64_t nentries = tree->GetEntries();
11
12    // ブランチを設定
13    Float_t x, y;
14    tree->SetBranchAddress("x", &x);
15    tree->SetBranchAddress("y", &y);
16
17    // すべてのエントリーをループ
18    for (Long64_t i = 0; i < nentries; i++) {
19        tree->GetEntry(i);
20
21        // ここでデータ処理
22        if (x > 100) {
23            std::cout << "Entry " << i << ": x=" << x << ", y=" << y << std::endl;
24        }
25    }
26
27    file->Close();
28}

データ解析の基本となるエントリーループで、GetEntriesを活用します。

プログレス表示付きループ

 1#include <TFile.h>
 2#include <TTree.h>
 3#include <iostream>
 4#include <cmath>
 5
 6void loop_with_progress() {
 7    TFile *file = TFile::Open("data.root");
 8    TTree *tree = (TTree *)file->Get("tree");
 9
10    Long64_t nentries = tree->GetEntries();
11
12    Float_t x;
13    tree->SetBranchAddress("x", &x);
14
15    // プログレス表示用の間隔
16    Long64_t progress_step = std::max(1LL, nentries / 100);
17
18    std::cout << "処理開始: " << nentries << " エントリー" << std::endl;
19
20    for (Long64_t i = 0; i < nentries; i++) {
21        tree->GetEntry(i);
22
23        // データ処理
24        // ...
25
26        // プログレス表示(100回に1回、または最後)
27        if (i % progress_step == 0 || i == nentries - 1) {
28            int percent = (100 * (i + 1)) / nentries;
29            std::cout << "\r進捗: " << percent << "% (" << (i + 1)
30                      << "/" << nentries << ")" << std::flush;
31        }
32    }
33
34    std::cout << "\n処理完了" << std::endl;
35    file->Close();
36}

Python でのエントリーループ

 1from ROOT import TFile
 2
 3file = TFile("data.root")
 4tree = file.Get("tree")
 5
 6nentries = tree.GetEntries()
 7
 8# ブランチを設定
 9x_val = 0
10y_val = 0
11tree.SetBranchAddress("x", x_val)
12tree.SetBranchAddress("y", y_val)
13
14print(f"処理開始: {nentries} エントリー")
15
16for i in range(nentries):
17    tree.GetEntry(i)
18
19    # ここでデータ処理
20    if x_val > 100:
21        print(f"Entry {i}: x={x_val}, y={y_val}")
22
23    # プログレス表示
24    if (i + 1) % 1000 == 0:
25        print(f"進捗: {i + 1}/{nentries}")
26
27print("処理完了")
28file.Close()

エントリー数の統計情報を取得したい

 1#include <TFile.h>
 2#include <TTree.h>
 3#include <iostream>
 4
 5void tree_statistics() {
 6    TFile *file = TFile::Open("data.root");
 7    TTree *tree = (TTree *)file->Get("tree");
 8
 9    // 基本統計
10    Long64_t total_entries = tree->GetEntries();
11    Long64_t loaded_entries = tree->GetLoadedEntries();
12
13    std::cout << "全エントリー数: " << total_entries << std::endl;
14    std::cout << "ロード済みエントリー数: " << loaded_entries << std::endl;
15
16    // セレクション条件によるカウント
17    Long64_t selected_entries = tree->GetEntries("quality > 0.8");
18
19    std::cout << "品質良好なエントリー: " << selected_entries << std::endl;
20    std::cout << "品質不良なエントリー: " << (total_entries - selected_entries) << std::endl;
21
22    // 割合を計算
23    double percent = (100.0 * selected_entries) / total_entries;
24    std::cout << "品質良好な割合: " << percent << "%" << std::endl;
25
26    // ブランチごとの情報
27    TIter next(tree->GetListOfBranches());
28    TBranch *branch;
29    while ((branch = (TBranch *)next())) {
30        std::cout << "ブランチ: " << branch->GetName()
31                  << ", 最大エントリー: " << branch->GetEntries() << std::endl;
32    }
33
34    file->Close();
35}

メモリ効率的にエントリー数を確認したい

大規模ファイルでは、メモリを効率的に使用することが重要です。

 1#include <TFile.h>
 2#include <TTree.h>
 3#include <iostream>
 4
 5void efficient_entry_count() {
 6    // ファイルをREADモードで開く
 7    TFile *file = TFile::Open("large_data.root", "READ");
 8
 9    // TTreeを取得(データはまだロードされていない)
10    TTree *tree = (TTree *)file->Get("tree");
11
12    // エントリー数を取得(メモリをほとんど使わない)
13    Long64_t nentries = tree->GetEntries();
14
15    std::cout << "エントリー数: " << nentries << std::endl;
16    std::cout << "メモリ使用量: " << tree->GetTotBytes() / (1024.0 * 1024.0)
17              << " MB" << std::endl;
18    std::cout << "圧縮率: " << (100.0 * tree->GetZipBytes()) / tree->GetTotBytes()
19              << "%" << std::endl;
20
21    file->Close();
22}

実用例

複数ファイルのエントリー数を集計

 1#include <TFile.h>
 2#include <TTree.h>
 3#include <TString.h>
 4#include <iostream>
 5
 6void count_multiple_files() {
 7    const int nfiles = 10;
 8    Long64_t total_entries = 0;
 9
10    for (int i = 0; i < nfiles; i++) {
11        TString filename;
12        filename.Form("data_%03d.root", i);
13
14        TFile *file = TFile::Open(filename.Data());
15        if (!file || file->IsZombie()) {
16            std::cerr << "ファイルを開けません: " << filename << std::endl;
17            continue;
18        }
19
20        TTree *tree = (TTree *)file->Get("tree");
21        if (!tree) {
22            std::cerr << "TTreeが見つかりません: " << filename << std::endl;
23            file->Close();
24            continue;
25        }
26
27        Long64_t entries = tree->GetEntries();
28        std::cout << filename << ": " << entries << " エントリー" << std::endl;
29
30        total_entries += entries;
31        file->Close();
32    }
33
34    std::cout << "\n合計: " << total_entries << " エントリー" << std::endl;
35}

エントリー数に基づくデータ分割

 1#include <TFile.h>
 2#include <TTree.h>
 3#include <iostream>
 4
 5void split_data_by_entries() {
 6    TFile *file = TFile::Open("data.root");
 7    TTree *tree = (TTree *)file->Get("tree");
 8
 9    Long64_t nentries = tree->GetEntries();
10    Long64_t chunk_size = 10000;
11
12    // データを複数のチャンクに分割
13    Long64_t nchunks = (nentries + chunk_size - 1) / chunk_size;
14
15    std::cout << "全エントリー数: " << nentries << std::endl;
16    std::cout << "チャンクサイズ: " << chunk_size << std::endl;
17    std::cout << "チャンク数: " << nchunks << std::endl;
18
19    for (Long64_t chunk = 0; chunk < nchunks; chunk++) {
20        Long64_t start = chunk * chunk_size;
21        Long64_t end = (chunk + 1) * chunk_size;
22        if (end > nentries) end = nentries;
23
24        std::cout << "チャンク " << chunk << ": " << start << " - " << (end - 1)
25                  << " (" << (end - start) << " エントリー)" << std::endl;
26    }
27
28    file->Close();
29}

注意事項

  • 長整数型: GetEntriesはLong64_t(64ビット長整数)を返します。大規模なTTreeに対応しているため、通常のint型では値が溢れる可能性があります

  • セレクション処理時間: セレクション条件付きGetEntriesは全エントリーをスキャンするため、大規模TTreeでは時間がかかる可能性があります

  • キャッシング: GetLoadedEntries()はメモリにロードされたエントリー数を返すため、ファイルから読み込まれたエントリー数と異なる場合があります

  • ブランチの非同期化: マルティプル・バリエーション・キーによって一部のブランチが同期していない場合があります

  • エントリーサイズの確認: 各エントリーのメモリサイズはGetTotBytes()で確認できます

リファレンス