ROOT的运行环境( .x mycode.cpp
) 下,代码将解释执行。这种方式运行速度慢,而且代码结构不利于编写复杂的分析程序。
本节介绍编译执行分析程序的方法,在程序中ROOT库与其他C++外部库一样通过include方式进行调用。
推荐用这种方法进行编写分析程序。
主目录: ./tracking
./tracking
- main.cpp - 主程序
- Makefile -编译方法
./tracking/include/
- tracking.h (*.h, *.hh, *.hpp) - 头文件
./tracking/src/
- tracking.C (*.C, *.cc, *.cpp) -源文件
root -l f8ppac001.root
[0] tree->MakeClass("tracking")
生成 tracking.h 和 tracking.C
#include <iostream>
#include <TFile.h>
#include <TTree.h>
#include <TString.h>
#include "tracking.h"
using namespace std;
int main(int argc, char* argv[])
{
if(argc != 2) {
cout<<"Usage: ./"<<argv[0]<<" run_number "<<endl;
return -1;
}
int run_number = atoi(argv[1]);
TString InputPath, OutputPath, infile, outfile;
InputPath = "./";
OutputPath = "./";
infile.Form("%sf8ppac%03d.root", InputPath.Data(), run_number);
outfile.Form("%sout%03d.root", OutputPath.Data(), run_number);
//input
TFile *ipf = new TFile(infile);
if(!ipf->IsOpen()) {
cout<<"Cannot open input file: "<<infile<<endl;
return -1;
}
TTree *ipt = (TTree*)ipf->Get("tree");
//output
TFile *opf = new TFile(outfile,"RECREATE");
TTree *opt = new TTree("tree","ppac tracking");
cout << "Inputfile: " <<infile.Data() << endl;
cout << "Outputfile: " <<outfile.Data() << endl;
tracking *tk = new tracking(ipt); //当traking构造函数中传入的ipt已存在时,构造函数内部的tree指针就指向ipt
tk->Loop(opt);
//
ipf->Close();
opf->Close();
return 1;
}
在写头文件时需要注意,在开头和结尾处必须按照如下样式加上预编译语句(如下):
#ifndef TRCKING_H
#define TRCKING_H
//你的代码写在这里
#endif
这样做是为了防止重复编译,不这样做就有可能出错。 至于"tracking_h"这个名称,只要不与已存在的定义重合可以随意取。一般建议写成这种形式(或大写成 TRACKING_H),因为这样比较容易和头文件的名字对应。
一般的编程规范推荐在头文件中只进行变量和函数原型声明,而不写出函数的具体实现。按照上述原则应将原 tracking.h 目录下的成员函数的具体实现部分挪至 src/tracking.cpp 文件内。为了尽量少修改MakeClass自动生成的代码,以下代码只添加用户代码,不做其他改动。
//////////////////////////////////////////////////////////
// This class has been automatically generated on
// Wed Mar 11 09:58:39 2020 by ROOT version 6.18/04
// from TTree tree/tree
// found on file: f8ppac001.root
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// This class has been automatically generated on
// Wed Mar 11 09:58:39 2020 by ROOT version 6.18/04
// from TTree tree/tree
// found on file: f8ppac001.root
//////////////////////////////////////////////////////////
#ifndef tracking_h
#define tracking_h
#include <TROOT.h>
#include <TChain.h>
#include <TFile.h>
#include <TH2.h>
// Header file for the classes stored in the TTree if any.
class tracking {
public :
TTree *fChain; //!pointer to the analyzed TTree or TChain
Int_t fCurrent; //!current Tree number in a TChain
// Fixed size dimensions of array or collections stored in the TTree if any.
// Declaration of leaf types
Float_t PPACF8[5][5];
Float_t F8PPACRawData[5][5];
Int_t beamTrig;
Int_t must2Trig;
Float_t targetX,targetY;
//----- user-defined variables -------
Double_t xx[3],xz[3],yy[3],yz[3];//1A,2A,3
Double_t xx2b[2],yy2b[2],xz2b,yz2b;//2B x,y, 0-measured, 1- fitted.
Double_t dx[3],dy[3];//residual
Double_t tx,ty;//target position
Double_t c2nx,c2ny;//chi2/ndf for xfit,yfit
// List of branches
TBranch *b_PPACF8; //!
TBranch *b_F8PPACRawData; //!
TBranch *b_beamTrig; //!
TBranch *b_must2Trig; //!
TBranch *b_targetX; //!
TBranch *b_targetY; //!
tracking(TTree *tree=0);
virtual ~tracking();
virtual Int_t Cut(Long64_t entry);
virtual Int_t GetEntry(Long64_t entry);
virtual Long64_t LoadTree(Long64_t entry);
virtual void Init(TTree *tree);
virtual void Loop(TTree *tree);
virtual Bool_t Notify();
virtual void Show(Long64_t entry = -1);
//----- user-defined methods -----
virtual void SetOutBranch(TTree *tree);
virtual void TrackInit();
virtual void SetTrace(TH2D *h,Double_t k,Double_t b,Int_t min,Int_t max);
};
#endif
#ifdef tracking_cxx
tracking::tracking(TTree *tree) : fChain(0)
{
// if parameter tree is not specified (or zero), connect the file
// used to generate this class and read the Tree.
if (tree == 0) {
TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("f8ppac001.root");
if (!f || !f->IsOpen()) {
f = new TFile("f8ppac001.root");
}
f->GetObject("tree",tree);
}
Init(tree);
}
...
void tracking::Init(TTree *tree)
{
// The Init() function is called when the selector needs to initialize
// a new tree or chain. Typically here the branch addresses and branch
// pointers of the tree will be set.
// It is normally not necessary to make changes to the generated
// code, but the routine can be extended by the user if needed.
// Init() will be called many times when running on PROOF
// (once per file to be processed).
// Set branch addresses and branch pointers
if (!tree) return;
fChain = tree;
fCurrent = -1;
fChain->SetMakeClass(1);
fChain->SetBranchAddress("PPACF8", PPACF8, &b_PPACF8);
fChain->SetBranchAddress("F8PPACRawData", F8PPACRawData, &b_F8PPACRawData);
fChain->SetBranchAddress("beamTrig", &beamTrig, &b_beamTrig);
fChain->SetBranchAddress("must2Trig", &must2Trig, &b_must2Trig);
fChain->SetBranchAddress("targetX",&targetX,&b_targetX);
fChain->SetBranchAddress("targetY",&targetY,&b_targetY);
Notify();
}
...
#endif // #ifdef tracking_cxx
#define tracking_cxx
#include <TH2.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TF1.h>
#include <TFitResult.h>
#include <TGraph.h>
#include "tracking.h"
using namespace std;
void tracking::SetBranch(TTree *tree)
{
//measured pos
tree->Branch("xx", &xx, "xx[3]/D");//1A,2A,3
tree->Branch("xz", &xz, "xz[3]/D");
tree->Branch("yy", &yy, "yy[3]/D");
tree->Branch("yz", &yz, "yz[3]/D");
...
}
void tracking::TrackInit()
{
tx = -999;
ty = -999;
//1A
xx[0] = PPACF8[0][0];
yy[0] = PPACF8[0][1];
xz[0] = PPACF8[0][2];
yz[0] = PPACF8[0][3];
...
}
void tracking::SetTrace(TH2D *h, Double_t k, Double_t b, Int_t min, Int_t max){
if(h == 0) return;
if(min >= max) return;
...
}
void tracking::Loop(TTree *tree)
{
TH2D *htf8x = new TH2D("htf8x", "x trace by ppac", 2200, -2000, 200, 300, -150, 150);
TH2D *htf8y = new TH2D("htf8y", "y trace by ppac", 2200, -2000, 200, 300, -150, 150);
TH2D *htar = new TH2D("htar", "distribution on target", 100, -50, 50, 100, -50, 50);
SetBranch(tree);
if (fChain == 0) return;
Long64_t nentries = fChain->GetEntriesFast();
Long64_t nbytes = 0, nb = 0;
for (Long64_t jentry=0; jentry<nentries;jentry++) {
Long64_t ientry = LoadTree(jentry);
if (ientry < 0) break;
nb = fChain->GetEntry(jentry); nbytes += nb;
TrackInit();
...
}
}
...
}
参考链接:跟我一起写Makefile:https://blog.csdn.net/xiaoshuai537/article/details/79340153
下面的Makefile中ROOTCFLAGS,ROOTLIBS,ROOTGLIBS是编译和链接ROOT环境的必要语句。
OBJ = 程序编译后的名称
#############################################################################
OBJ = tracking
MainFile = main.cpp
###############################################################################
SourceFile := $(wildcard $(shell pwd)/src/*.c $(shell pwd)/src/*.cc $(shell pwd)/src/*.C $(shell pwd)/src/*.cpp $(shell pwd)/src/*.cxx)
IncludeFile := $(wildcard $(shell pwd)/include/*.h $(shell pwd)/include/*.hh $(shell pwd)/include/*.hpp)
###############################################################################
ROOTCFLAGS = $(shell root-config --cflags)
ROOTLIBS = $(shell root-config --libs)
ROOTGLIBS = $(shell root-config --glibs)
GXX = g++
# -Wl ,--no-as-needed
DIR_INC = -I$(shell pwd)/include
CFLAGS = -Wall -O2 $(ROOTCFLAGS) $(DIR_INC) #动态连接库不要写在这里
LIBS = $(ROOTGLIBS) -lSpectrum #动态连接库写在这里
###############################################################################
all:$(OBJ)
$(OBJ): $(MainFile) $(SourceFile)
$(GXX) $(CFLAGS) -o $@ $(MainFile) $(SourceFile) $(LIBS)
@echo "=============================================================="
@echo "$@ done !"
@echo "=============================================================="
clean:
rm -f *.o *.d $(OBJ)
make clean
make
ROOT环境内直接用.x myClass.C
运行时 ROOT 自动载入所用函数的库文件,因此不用显式包含库文件;make编译时要求用户在代码中显式包含库文件。
#include <TGraph.h>
#include <iostream>
#include <TGraph.h>
#include "mylib.h"
未包含函数的库文件是root编程中最常见的错误。
直接使用cout, 或cin等在 std 的 namespace 上定义的函数也会报错。
using namespace std;
或直接使用std::cout
,std::cin
(推荐)C++编译器编译报错给出一堆错误信息时,一般只修正出现的第一个错误信息,然后再次编译。按上述步骤依次进行修改。
编译成功时输出如下的信息:
g++ -Wall -O2 -I/Users/zhli/ROOT/root61804/include -I/Users/zhli/ana/course/data_analysis/chapt2/compile/include -I/Users/zhli/ROOT/root61804/include -L/Users/zhli/ROOT/root61804/lib -lCore -lImt -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lROOTVecOps -lTree -lTreePlayer -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lMultiProc -lROOTDataFrame -lpthread -stdlib=libc++ -lm -ldl -lSpectrum -lXMLParser -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -pthread -stdlib=libc++ -std=c++11 -m64 -I/Users/zhli/ROOT/root61804/include -L/Users/zhli/ROOT/root61804/lib -lCore -lImt -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lROOTVecOps -lTree -lTreePlayer -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lMultiProc -lROOTDataFrame -lpthread -stdlib=libc++ -lm -ldl -L/Users/zhli/ROOT/root61804/lib -lGui -lCore -lImt -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lROOTVecOps -lTree -lTreePlayer -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lMultiProc -lROOTDataFrame -lpthread -stdlib=libc++ -lm -ldl -o tracking main.cpp /Users/zhli/ana/course/data_analysis/chapt2/compile/src/tracking.C
==============================================================
tracking done !
==============================================================
./tracking 1
!ls -R
2.3_comiling_1.html f8ppac001.root out001.root 2.3_comiling_1.ipynb include src Makefile main.cpp tracking Untitled.ipynb main.cpp~ ./include: tracking.h tracking.h~ ./src: tracking.C tracking.C~
!./tracking 1
Inputfile: ./f8ppac001.root Outputfile: ./out001.root