ROOT 가이드

데이터 저장을 위한 클래스 TTree

데이터 저장

TTree 클래스는 정해진 데이터 세트의 배열이라고 할 수 있다. TTree에는 실제 나무처럼 branch(TBranch)와 leaf(TLeaf)가 있는데 실제 성질을 다르지만 이해하는데 도움은 된다. TTree에는 한개 혹은 그 이상의 branch 가 있을 수 있고 각 branch는 그 branch에 저장되는 변수의 데이터 타입을 결정한다. Branch에 저장되는 변수는 leaf라고 한다. 서로 다른 branch에 존재하는 leaf의 개수는 같다. 말이 어려우므로 실제로 어떻게 사용하는지 보면서 알아보자.

TTree를 생성할 때는 반드시 사전에 TFile을 생성해야 한다. 

TFile *file = new TFile("file.root","recreate");

TTree는 TTree([이름], [타이틀]) constructor로 생성한다.

TTree *tree = new TTree("data","tree title")

먼저 TTree는 branch라는 것을 등록해서 내가 어떤 타입의 데이터를 저장할 지 알려주어야 한다. branch는 여러개 등록할 수 있다. branch를 등록하려면 Branch의 1)이름2)데이터 전달 역할을 하는 변수가 필요하다. 가령 실험에서 관측한 입자의 종류와 운동량의 크기를 저장한다고 하자. 입자의 종류를 integer 형태로 저장한다고 할 때 다음과 다음과 같이 TTree의 Branch([이름], &[전달변수]) 함수를 이용해서 Branch를 생성할 수 있다.

Int_t pid;
tree -> Branch("particleID",&pid);

위  Branch() 함수에서 첫번째 변수는 Branch의 이름이며 두번째는 전달변수다. 이때 전달변수 앞에 '&'가 붙어있는데 이는 TTree에 전달변수의 주소를 알려주기 위함이다. 주소를 전달해 주어야 하는 것을 잊고 프로그래밍을 하다가 프로그램이 멈추거나 제대로 동작하지 않는 실수를 아주 많이 하는데 잘 기억해 두어야 할 점이다.

두번째 Branch는 운동량의 크기이므로 double형의 데이터를 사용한다.

Double_t mom;
tree -> Branch("momentum",&mom);

이렇게 tree에 branch 두개가 등록이 되면 앞으로 데이터를 저장할 때 "particleID" branch와 "momentum" branch가 하나의 세트 {pid, mom}의 형태로 저장이 된다. 저장은 TTree의 Fill() 함수로 하게 되는데 Fill() 함수를 실행하면 "particleID" branch는 전달변수 pid에 들어있던 값을 저장하고 "momentum" branch는 전달변수 mom에 들어있던 값을 저장한다. 다음을 보자.

pid = 1;
mom = 5.192;
tree -> Fill();

위 코드를 실행하게 되면 tree에 들어있는 두 branch는 전달변수 pid와 mom에 들어있던 값을 참고하여 {1, 5.192}를 저장하게 된다. 표로 그려보면 다음과 같다.

particleID (Int_t) momentum (Double_t)
1 5.192

이렇게 Fill()을 통하여 데이터를 채우는 것을 엔트리(entry)를 채운다고 한다. 우리는 위 코드를 통해서 엔트리를 한번 채워 보았다.

마지막으로 프로그램을 종료하기 전에 tree를 파일에 쓰는 것을 잊지 말자. 다른 TObject와 마찬가지로 Write() 함수를 사용한다.

void writeTree() {
    TFile *file = new TFile("file.root","recreate");
    TTree *tree = new TTree("data","particles");
    
    Int_t pid;
    tree -> Branch("particleID",&pid);
    Double_t mom;
    tree -> Branch("momentum",&mom);
 
    pid = 1;
    mom = 5.192;
    tree -> Fill();

    pid = 1;
    mom = 3.004;
    tree -> Fill();

    pid = 2;
    mom = 12.559;
    tree -> Fill();
    
    tree -> Write();
}
particleID (Int_t) momentum (Double_t)
1 5.192
1 3.004
2 12.559

데이터 읽기

 

TTree를 파일에서 꺼내온 후 데이터를 읽으려면 branch를 다시 연결해야 한다. 이미 존재하는 branch를 연결하는 것은 SetBranchAddress([이름], &[전달변수]) 함수를 이용하는데 Branch() 함수에서의 전달변수와는 다르게 이번에는 값을 받아오는 역할을 한다. Branch의 이름은 저장할 때 설정했던 이름을 적는다.

Int_t pid;
tree -> SetBranchAddress("particleID",&pid);
Double_t mom;
tree -> SetBranchAddress("momemtum",&mom);

데이터는 엔트리 별로 꺼내올 수 있는데 엔트리 번호는 0번부터 시작하며 GetEntry([번호]) 함수를 이용한다.

void readTree() {
    TFile *file = new TFile("file.root","read");
    TTree *tree = (TTree *) file -> Get("data");
    
    Int_t pid;
    tree -> SetBranchAddress("particleID",&pid);
    Double_t mom;
    tree -> SetBranchAddress("momentum",&mom);
    
    tree -> GetEntry(0);
    cout << pid << " " << mom << endl;
    tree -> GetEntry(1);
    cout << pid << " " << mom << endl;
    tree -> GetEntry(2);
    cout << pid << " " << mom << endl;
}
> root readTree.C 
root [0] 
Processing readTree.C...
1 5.192
1 3.004
2 12.559
root [1]

댓글

댓글 본문
작성자
비밀번호
버전 관리
ejungwoo
현재 버전
선택 버전
graphittie 자세히 보기