Exercise2.4-练习李老师课间内容

  • 本节主要目的:利用MakcClass生成的文件,编写可编译执行的分析程序进阶

前述分析程序的做法有两个主要的缺点:

  • 需要改写MakeClass生成的.h和.C程序
  • MakeClass生成的代码与用户代码混在一起
  • 当原ROOT文件TTree的结构有变化,重新用MakeClass方法生成.h和.C后,需要将用户代码部分拷贝进去。

避免上述问题的更好的方法是采用分析代码类(class ana)继承MakeClass生成的类(class tracking)的方式。通过这样的方式可不改动原来的类,将用户分析代码与原来的代码分开,互不干扰。

文件和目录的组织

主目录: ./tracking

  ./tracking 
      - main.cpp  - 主程序
      - Makefile -编译方法

  ./tracking/include/  
      - tracking.h   - MakeClass 生成的头文件
      - ana.h         - 用户分析头文件

  ./tracking/src/ 
      - tracking.C  -MakeClass生成的源文件
      - ana.cpp       用户分析源文件

$\color{red}{利用TTree的MakeClass()生成.h 和.C文件}$

  • $\color{red}{将tracking.h 移至 tracking/include目录, 将tracking.C 移至 tracking/src目录}$

改写新的main.cpp文件,放入./tracking/

#include <iostream> 
#include <TFile.h>
#include <TTree.h>
#include <TString.h>
#include "ana.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");

    //
    ana *tk = new ana(run_number,ipt); 
    tk->Analysis(opt); //等价于原Loop函数

    //
    ipf->Close();
    opf->Close();
    return 1;       
}

./tracking/include/ana.h ,用户分析类头文件

#ifndef ana_h
#define ana_h

#include <TH2.h>
#include <iostream>
#include "tracking.h"  //包含基类头文件

using namespace std;

class ana : public tracking //从tracking类中继承其成员变量和成员函数
{
 public:
  int run; //run_number
  Double_t xx[3],xz[3],yy[3],yz[3];//1A,2A,3
  Double_t p2bx,p2by;//2B x-y
  Double_t dx[3],dy[3];
  Double_t tx,ty;//target pos
  Double_t c2nx,c2ny;//chi2/ndf for xfit,yfit
  TH2D *htf8x,*htf8y,*htar;

  //构造函数:将传入的tree传递给tracking基类,完成初始化
 ana(int run_number, TTree* tree): tracking(tree), run(run_number) {} //run=run_number
  virtual ~ana() {};
  virtual void     Analysis(TTree *tree);//分析函数,作用等价于原Loop函数
  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

./tracking/include/ana.cpp ,用户分析类-具体实现

#include <TH2.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TF1.h>
#include <TFitResult.h>
#include <TGraph.h>
#include "ana.h"
using namespace std;

void ana::SetOutBranch(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");

  //difference between measured and calculated -for pos resolution.
  tree->Branch("dx",&dx,"dx[3]/D");
  tree->Branch("dy",&dy,"dy[3]/D");

  //for efficiency calculation -2B
  tree->Branch("p2bx",&p2bx,"p2bx/D");
  tree->Branch("p2by",&p2by,"p2by/D");

  //target x-y
  tree->Branch("tx",&tx,"tx/D");
  tree->Branch("ty",&ty,"ty/D");

  //ch2/ndf for linear fitting.
  tree->Branch("c2nx",&c2nx,"c2nx/D");
  tree->Branch("c2ny",&c2ny,"c2ny/D");
}

void ana::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];

  //2A
  xx[1]=PPACF8[2][0];
  yy[1]=PPACF8[2][1];
  xz[1]=PPACF8[2][2];
  yz[1]=PPACF8[2][3];

  //3
  xx[2]=PPACF8[4][0];
  yy[2]=PPACF8[4][1];
  xz[2]=PPACF8[4][2];
  yz[2]=PPACF8[4][3];

  //2B
  p2bx=PPACF8[3][0];
  p2by=PPACF8[3][1];

}

void ana::SetTrace(TH2D *h,Double_t k,Double_t b,Int_t min,Int_t max){
    if(h==0) return;
    if(min>=max) return;

    for(int i=min;i<max;i++){
        h->Fill(i,(Int_t)(i*k+b));
    }
}


void ana::Analysis(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);

   SetOutBranch(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();
      bool b1a=xx[0]>-999 && yy[0]>-999;
      bool b2a=xx[1]>-999 && yy[1]>-999;
      bool b3=xx[2]>-999 && yy[2]>-999;
      if(!b1a || !b2a || !b3) continue;

      //fit x-z trajectory
      TFitResultPtr r;
      TGraph *grx=new TGraph(3,xz,xx);
      TF1 *fx=new TF1("fx","pol1",-2000,0);
      r=grx->Fit(fx,"SQ");
      tx=fx->Eval(0);
      SetTrace(htf8x,fx->GetParameter(1),fx->GetParameter(0),-1800,0);
      for(int i=0;i<3;i++) dx[i]=xx[i]-fx->Eval(xz[i]);
      c2nx=r->Chi2()/r->Ndf();
      delete grx;
      delete fx;

      //fit y-z trajectory      
      TGraph *gry=new TGraph(3,yz,yy);
      TF1 *fy=new TF1("fy","pol1",-2000,0);
      r=gry->Fit(fy,"SQ");      
      ty=fy->Eval(0);
      SetTrace(htf8y,fy->GetParameter(1),fy->GetParameter(0),-1800,0);
      for(int i=0;i<3;i++) dy[i]=yy[i]-fy->Eval(yz[i]);
      c2ny=r->Chi2()/r->Ndf();
      delete gry;
      delete fy;

      htar->Fill(tx,ty);

      tree->Fill();
      if(jentry%10000==0) cout<<"processing "<<jentry<<endl;

   }
   htf8x->Write();
   htf8y->Write();
   htar->Write();
   tree->Write();
}

使用方法

make clean

make

./tracking 1

In [1]:
!jupyter nbconvert exercise2.4 --to html
[NbConvertApp] Converting notebook exercise2.4.ipynb to html

[NbConvertApp] Writing 322371 bytes to exercise2.4.html