3.2 利用可变长数组存储数据结构- Hit结构¶

描述一个粒子与DSSD的相互作用,需要如下信息:

  • position: x or y side , strip number in x/y side
  • energy: raw, calibrated
  • time: raw, calibrated

常用的数据表达方式为数组,假设有三个DSSD(128x128):

  • energy:
Int_t xe[3][128], ye[3][128];//raw
Double_t xec[3][128], yec[3][128]; //calibrated
  • time:
Int_t xt[3][128], yt[3][128];//raw
Double_t xtc[3][128], yec[3][128]; //calibrated

而在绝大多数情况下,一个DSSD只有少数条包含有用的信息,数组中大多数元素是无用的。

  • 固定数组的记录方式导致内存和空间的浪费。

  • 另外数组结构不利于表达DSSD的整体特性,如无法一次检查一个DSSD中多个条的能量信息。

In [1]:
//%jsroot on
TFile *f = new TFile("s4.root");
TTree *tree = (TTree*)f->Get("tree");
TCanvas *c1 = new TCanvas;

整个事件中只有x面有一个有效信息¶

In [2]:
tree->Scan("pe:re", "", "", 1, 1);//第4参数-事件数,第5参数-起始事件编号
//jupyter上的Scan必须指定第4个参数(事件数)
***********************************************
*    Row   * Instance *        pe *        re *
***********************************************
*        1 *        0 *       -10 *       -10 *
*        1 *        1 *       -10 *       -10 *
*        1 *        2 *       -10 *       -10 *
*        1 *        3 *       -10 *       -10 *
*        1 *        4 *       -10 *       -10 *
*        1 *        5 *       -10 *       -10 *
*        1 *        6 *       -10 *       -10 *
*        1 *        7 *       -10 *       -10 *
*        1 *        8 *       -10 *       -10 *
*        1 *        9 *       -10 *       -10 *
*        1 *       10 *       983 *       -10 *
*        1 *       11 *       -10 *       -10 *
*        1 *       12 *       -10 *       -10 *
*        1 *       13 *       -10 *       -10 *
*        1 *       14 *       -10 *       -10 *
*        1 *       15 *       -10 *       -10 *
*        1 *       16 *       -10 *       -10 *
*        1 *       17 *       -10 *       -10 *
*        1 *       18 *       -10 *       -10 *
*        1 *       19 *       -10 *       -10 *
*        1 *       20 *       -10 *       -10 *
*        1 *       21 *       -10 *       -10 *
*        1 *       22 *       -10 *       -10 *
*        1 *       23 *       -10 *       -10 *
*        1 *       24 *       -10 *       -10 *
*        1 *       25 *       -10 *       -10 *
*        1 *       26 *       -10 *       -10 *
*        1 *       27 *       -10 *       -10 *
*        1 *       28 *       -10 *       -10 *
*        1 *       29 *       -10 *       -10 *
*        1 *       30 *       -10 *       -10 *
*        1 *       31 *       -10 *       -10 *
*        1 *       32 *       -10 *       -10 *
*        1 *       33 *       -10 *       -10 *
*        1 *       34 *       -10 *       -10 *
*        1 *       35 *       -10 *       -10 *
*        1 *       36 *       -10 *       -10 *
*        1 *       37 *       -10 *       -10 *
*        1 *       38 *       -10 *       -10 *
*        1 *       39 *       -10 *       -10 *
*        1 *       40 *       -10 *       -10 *
*        1 *       41 *       -10 *       -10 *
*        1 *       42 *       -10 *       -10 *
*        1 *       43 *       -10 *       -10 *
*        1 *       44 *       -10 *       -10 *
*        1 *       45 *       -10 *       -10 *
*        1 *       46 *       -10 *       -10 *
*        1 *       47 *       -10 *       -10 *
***********************************************
Type <CR> to continue or q to quit ==> 

整个事件中x,y面都有一个有效信息¶

In [3]:
tree->Scan("pe:re", "", "", 1, 2);
***********************************************
*    Row   * Instance *        pe *        re *
***********************************************
*        2 *        0 *       -10 *       -10 *
*        2 *        1 *       -10 *       -10 *
*        2 *        2 *       -10 *       -10 *
*        2 *        3 *       -10 *       -10 *
*        2 *        4 *       -10 *       -10 *
*        2 *        5 *       -10 *       -10 *
*        2 *        6 *       -10 *       -10 *
*        2 *        7 *       -10 *       -10 *
*        2 *        8 *       978 *       -10 *
*        2 *        9 *       -10 *       -10 *
*        2 *       10 *       -10 *       -10 *
*        2 *       11 *       -10 *       -10 *
*        2 *       12 *       -10 *       -10 *
*        2 *       13 *       -10 *       -10 *
*        2 *       14 *       -10 *       -10 *
*        2 *       15 *       -10 *       -10 *
*        2 *       16 *       -10 *       -10 *
*        2 *       17 *       -10 *       -10 *
*        2 *       18 *       -10 *       -10 *
*        2 *       19 *       -10 *       -10 *
*        2 *       20 *       -10 *       -10 *
*        2 *       21 *       -10 *       -10 *
*        2 *       22 *       -10 *       -10 *
*        2 *       23 *       -10 *       -10 *
*        2 *       24 *       -10 *       -10 *
*        2 *       25 *       -10 *       -10 *
*        2 *       26 *       -10 *       -10 *
*        2 *       27 *       -10 *       -10 *
*        2 *       28 *       -10 *       -10 *
*        2 *       29 *       -10 *       -10 *
*        2 *       30 *       -10 *       -10 *
*        2 *       31 *       -10 *       -10 *
*        2 *       32 *       -10 *       -10 *
*        2 *       33 *       -10 *       -10 *
*        2 *       34 *       -10 *       -10 *
*        2 *       35 *       -10 *       -10 *
*        2 *       36 *       -10 *       -10 *
*        2 *       37 *       -10 *       -10 *
*        2 *       38 *       -10 *       -10 *
*        2 *       39 *       -10 *       -10 *
*        2 *       40 *       -10 *       -10 *
*        2 *       41 *       -10 *       -10 *
*        2 *       42 *       -10 *       623 *
*        2 *       43 *       -10 *       287 *
*        2 *       44 *       -10 *       -10 *
*        2 *       45 *       -10 *       -10 *
*        2 *       46 *       -10 *       -10 *
*        2 *       47 *       -10 *       -10 *
***********************************************
Type <CR> to continue or q to quit ==> 
  • 将某一方向的信息记为 (id,energy),则上一个事件中只有pie: (8,978),ring: (42,623), (43,287)有信号。
    • 如果要观察pe和re之间能量的关联,必须用“pe[8]:re[42]”, “pe[8]:re[43]”
  • 对于不同pie和ring的组合,上述条件都要做相应的变化。

尝试用 ”pe>0 && re>0“条件,筛选事件。¶

  • 第54个事件 pe:1139, re:876
In [4]:
tree->Scan("pe:re", "pe>0&& re>0", "", 1000, 1);
***********************************************
*    Row   * Instance *        pe *        re *
***********************************************
*       54 *        1 *      1139 *       876 *
*      124 *       15 *       914 *       156 *
*      198 *       22 *      1057 *       794 *
*      305 *       35 *      1031 *       106 *
*      313 *       12 *       946 *       710 *
*      395 *       35 *       377 *       157 *
*      805 *       41 *       886 *       822 *
*      812 *       20 *      1066 *        79 *
*      838 *       40 *      1392 *      1307 *
*      958 *       22 *      1415 *      1350 *
***********************************************
==> 10 selected entries
In [5]:
tree->Scan("pe:re", "" ,"" ,1 , 54);
***********************************************
*    Row   * Instance *        pe *        re *
***********************************************
*       54 *        0 *       -10 *       212 *
*       54 *        1 *      1139 *       876 *
*       54 *        2 *       -10 *       -10 *
*       54 *        3 *       -10 *       -10 *
*       54 *        4 *       -10 *       -10 *
*       54 *        5 *       -10 *       -10 *
*       54 *        6 *       -10 *       -10 *
*       54 *        7 *       -10 *       -10 *
*       54 *        8 *       -10 *       -10 *
*       54 *        9 *       -10 *       -10 *
*       54 *       10 *       -10 *       -10 *
*       54 *       11 *       -10 *       -10 *
*       54 *       12 *       -10 *       -10 *
*       54 *       13 *       -10 *       -10 *
*       54 *       14 *       -10 *       -10 *
*       54 *       15 *       -10 *       -10 *
*       54 *       16 *       -10 *       -10 *
*       54 *       17 *       -10 *       -10 *
*       54 *       18 *       -10 *       -10 *
*       54 *       19 *       -10 *       -10 *
*       54 *       20 *       -10 *       -10 *
*       54 *       21 *       -10 *       -10 *
*       54 *       22 *       -10 *       -10 *
*       54 *       23 *       -10 *       -10 *
*       54 *       24 *       -10 *       -10 *
*       54 *       25 *       -10 *       -10 *
*       54 *       26 *       -10 *       -10 *
*       54 *       27 *       -10 *       -10 *
*       54 *       28 *       -10 *       -10 *
*       54 *       29 *       -10 *       -10 *
*       54 *       30 *       -10 *       -10 *
*       54 *       31 *       -10 *       -10 *
*       54 *       32 *       -10 *       -10 *
*       54 *       33 *       -10 *       -10 *
*       54 *       34 *       -10 *       -10 *
*       54 *       35 *       -10 *       -10 *
*       54 *       36 *       -10 *       -10 *
*       54 *       37 *       -10 *       -10 *
*       54 *       38 *       -10 *       -10 *
*       54 *       39 *       -10 *       -10 *
*       54 *       40 *       -10 *       -10 *
*       54 *       41 *       -10 *       -10 *
*       54 *       42 *       -10 *       -10 *
*       54 *       43 *       -10 *       -10 *
*       54 *       44 *       -10 *       -10 *
*       54 *       45 *       -10 *       -10 *
*       54 *       46 *       -10 *       -10 *
*       54 *       47 *       -10 *       -10 *
***********************************************
Type <CR> to continue or q to quit ==> 
  • "pe>0 && re>0" 条件只能用于数组下标相同的pe和re元素
In [6]:
f->Close();

表达参数之间关联关系时,固定长度数组结构是不方便的。¶

新的事件表达方式:Hit 结构 - 可变长数组¶

Flattening data structure-把数据结构拉平

  • 以事件pie: (8,978),ring: (42,623),(43,287) 为例

  • pie和ring的有效信号总数分别为1和2 ,记为 phit=1,rhit=2。

  • 事件信息用多个可变长数组表达:

Int_t phit;
Int_t pid[phit];//pie_id
Int_t per[phit];//pie_energy

Int_t rhit;
Int_t rid[rhit];//ring_id
Int_t rer[rhit];//ring_energy

pid[0] = 8;
per[0] = 978;

rid[0] = 42;
rer[0] = 623;
rid[1] = 43;
rer[1] = 287;

如果有多个同类型探测器:

  • energy:
Int_t xe[3][128], ye[3][128];//raw
Double_t xec[3][128], yec[3][128]; //calibrated
  • hit structure:
Int_t xhit;
Int_t xdet[xhit]; //dssd:1-3
Int_t xid[xhit];//1-128
Double_t xe[xhit],xec[xhit];

Int_t yhit;
Int_t ydet[yhit]; //dssd:1-3
Int_t yid[yhit];//1-128
Double_t ye[yhit],yec[yhit];

ROOT- Adding a Branch with a Variable Length Array¶

  • 设定足够大的数组,存到TTree上的每个事件的实际数组大小取决于phit/rhit
// declaration
Int_t  phit;
Int_t  pid[1000];
Int_t  per[1000];

Int_t  rhit;
Int_t  rid[1000];
Int_t  rer[1000];

TFile *fout=new TFile("s4hit.root", "recreate");
TTree *tree=new TTree("tree", "dssd-hit");
// fixed-length array
tree->Branch("pe", &pe, "pe[48]/I");
tree->Branch("re", &re, "re[48]/I");
// variable length array
//size of array : phit
tree->Branch("phit",&phit,"phit/I");
//array: pid, per
tree->Branch("pid",&pid,"pid[phit]/I");
tree->Branch("per",&pee,"per[phit]/I");
//size of array : rhit
tree->Branch("rhit",&rhit,"rhit/I");
//array: pid, per
tree->Branch("rid",&rid,"rid[rhit]/I");
tree->Branch("rer",&rer,"rer[rhit]/I");

应避免使用超过一维的可变长数组¶

  • 如 xe[2][xhit] 等,在实际使用的时候很容易出错
// tree event loop
//... ... ...

 for(Long64_t jentry=0; jentry<nentries; jentry++) {
    tree->GetEntry(jentry);
       //x-side
    phit = 0;
    for(int i=0; i<48; i++) {
        if(pe[i]>0) {//有效信号的能量阈值
            pid[phit] = i;
            per[phit] = pe[i];
            phit++;
        }
    }

    rhit = 0;
    for(int i=0; i<48; i++) {
        if(re[i] > 0) {//有效信号的能量阈值
            pid[rhit] = i;
            per[rhit] = pe[i];
            rhit++;
        }
    }

    if(rhit>0 || phit>0) tree->Fill();
    if(jentry % 20000 == 0) 
        cout << jentry << endl;
   }

   tree->Write();
   fout->Close();
}

Hit 结构数据¶

In [7]:
//%jsroot on
TFile *fhit=new TFile("s4hit.root");
TTree *tr=(TTree*) fhit->Get("tree");
In [8]:
tr->Print();//ree,pee为刻度后数据。
******************************************************************************
*Tree    :tree      : alpha                                                  *
*Entries :  5790825 : Total =      2541888463 bytes  File  Size =  188942263 *
*        :          : Tree compression factor =  13.46                       *
******************************************************************************
*Br    0 :pe        : pe[48]/I                                               *
*Entries :  5790825 : Total  Size= 1112292512 bytes  File Size  =   29248218 *
*Baskets :     5099 : Basket Size=   25600000 bytes  Compression=  38.03     *
*............................................................................*
*Br    1 :re        : re[48]/I                                               *
*Entries :  5790825 : Total  Size= 1112292512 bytes  File Size  =   41772927 *
*Baskets :     5099 : Basket Size=   25600000 bytes  Compression=  26.62     *
*............................................................................*
*Br    2 :rhit      : rhit/I                                                 *
*Entries :  5790825 : Total  Size=   23179708 bytes  File Size  =    2833849 *
*Baskets :      177 : Basket Size=     291840 bytes  Compression=   8.18     *
*............................................................................*
*Br    3 :rid       : rid[rhit]/I                                            *
*Entries :  5790825 : Total  Size=   52791843 bytes  File Size  =   14089701 *
*Baskets :      357 : Basket Size=    7382528 bytes  Compression=   3.75     *
*............................................................................*
*Br    4 :ree       : ree[rhit]/F                                            *
*Entries :  5790825 : Total  Size=   52791850 bytes  File Size  =   34140607 *
*Baskets :      357 : Basket Size=    7382528 bytes  Compression=   1.55     *
*............................................................................*
*Br    5 :rer       : rer[rhit]/I                                            *
*Entries :  5790825 : Total  Size=   52791843 bytes  File Size  =   22519855 *
*Baskets :      357 : Basket Size=    7382528 bytes  Compression=   2.34     *
*............................................................................*
*Br    6 :phit      : phit/I                                                 *
*Entries :  5790825 : Total  Size=   23179708 bytes  File Size  =    2488050 *
*Baskets :      177 : Basket Size=     291840 bytes  Compression=   9.31     *
*............................................................................*
*Br    7 :pid       : pid[phit]/I                                            *
*Entries :  5790825 : Total  Size=   37522837 bytes  File Size  =   10440561 *
*Baskets :      288 : Basket Size=    7190016 bytes  Compression=   3.59     *
*............................................................................*
*Br    8 :pee       : pee[phit]/F                                            *
*Entries :  5790825 : Total  Size=   37522844 bytes  File Size  =   18283102 *
*Baskets :      288 : Basket Size=    7190016 bytes  Compression=   2.05     *
*............................................................................*
*Br    9 :per       : per[phit]/I                                            *
*Entries :  5790825 : Total  Size=   37522837 bytes  File Size  =   13024115 *
*Baskets :      288 : Basket Size=    7190016 bytes  Compression=   2.88     *
*............................................................................*
In [9]:
tr->Scan("phit:pid:per:rhit:rid:rer","","",10,1);
***********************************************************************************************
*    Row   * Instance *      phit *       pid *       per *      rhit *       rid *       rer *
***********************************************************************************************
*        1 *        0 *         1 *        10 *       983 *         0 *           *           *
*        2 *        0 *         1 *         8 *       978 *         2 *        42 *       623 *
*        2 *        1 *         1 *           *           *         2 *        43 *       287 *
*        3 *        0 *         1 *        27 *       928 *         2 *         4 *       740 *
*        3 *        1 *         1 *           *           *         2 *         5 *       169 *
*        4 *        0 *         0 *           *           *         2 *         1 *       670 *
*        4 *        1 *         0 *           *           *         2 *         2 *       379 *
*        5 *        0 *         1 *        44 *      1402 *         0 *           *           *
*        6 *        0 *         0 *           *           *         2 *        27 *        58 *
*        6 *        1 *         0 *           *           *         2 *        28 *       854 *
*        7 *        0 *         0 *           *           *         2 *        20 *       240 *
*        7 *        1 *         0 *           *           *         2 *        21 *       807 *
*        8 *        0 *         0 *           *           *         2 *        45 *      1236 *
*        8 *        1 *         0 *           *           *         2 *        46 *       183 *
*        9 *        0 *         0 *           *           *         1 *        11 *        52 *
*       10 *        0 *         0 *           *           *         2 *        35 *       811 *
*       10 *        1 *         0 *           *           *         2 *        36 *       624 *
***********************************************************************************************
  • 运行tr->Draw(”per:rer“)时,将相同数组下标的 per 和 rer 画成一个点
  • 如上图中事件3: per[1]={928}; rer[2]={740,169}, tr->Draw(”per:rer“)将画出(928,740); 而rer[1]=169 由于没有对应的per[1],不能画出。

观察事件多重性分布¶

In [10]:
tr->Draw("rhit");
c1->Draw();

hit=0的事件 : TTree内部不填充数据¶

In [11]:
tr->Draw("rer>>(1600,0,1600)","rhit==0");
c1->Draw();
In [12]:
tr->Draw("phit");
c1->Draw();

观察pie和ring的能量关联¶

In [13]:
tr->Scan("pid:per:rid:rer:phit:rhit","","",10,1);
***********************************************************************************************
*    Row   * Instance *       pid *       per *       rid *       rer *      phit *      rhit *
***********************************************************************************************
*        1 *        0 *        10 *       983 *           *           *         1 *         0 *
*        2 *        0 *         8 *       978 *        42 *       623 *         1 *         2 *
*        2 *        1 *           *           *        43 *       287 *         1 *         2 *
*        3 *        0 *        27 *       928 *         4 *       740 *         1 *         2 *
*        3 *        1 *           *           *         5 *       169 *         1 *         2 *
*        4 *        0 *           *           *         1 *       670 *         0 *         2 *
*        4 *        1 *           *           *         2 *       379 *         0 *         2 *
*        5 *        0 *        44 *      1402 *           *           *         1 *         0 *
*        6 *        0 *           *           *        27 *        58 *         0 *         2 *
*        6 *        1 *           *           *        28 *       854 *         0 *         2 *
*        7 *        0 *           *           *        20 *       240 *         0 *         2 *
*        7 *        1 *           *           *        21 *       807 *         0 *         2 *
*        8 *        0 *           *           *        45 *      1236 *         0 *         2 *
*        8 *        1 *           *           *        46 *       183 *         0 *         2 *
*        9 *        0 *           *           *        11 *        52 *         0 *         1 *
*       10 *        0 *           *           *        35 *       811 *         0 *         2 *
*       10 *        1 *           *           *        36 *       624 *         0 *         2 *
***********************************************************************************************
In [14]:
tr->Draw("rid[0]:rid[1]>>(48,0,48,48,0,48)","rhit==2","colz");
gPad->SetLogz();
c1->Draw();
In [24]:
tr->Draw("rer[0]:rer[1]>>(400,0,1600,400,0,1600)","abs(rid[0]-rid[1])==1","colz");
c1->Draw();
In [16]:
tr->Draw("rer[0]:rer[1]>>(400,0,1600,400,0,1600)","abs(rid[0]-rid[1])!=1","colz");
c1->Draw();
In [17]:
tr->Draw("per[0]:rer[0]>>(400,0,1600,400,0,1600)","","colz");//per[0]:rer[1]
c1->Draw();
In [18]:
tr->Draw("per:rer>>(400,0,1600,400,0,1600)","pid[0]==10 && rid[0]==30","colz");
gPad->SetLogz();
c1->Draw();

观察ring的相邻条能量关联¶

In [19]:
tr->Draw("rer[0]:rer[1]>>(400,0,1600,400,0,1600)","rid[0]==13&&rid[1]==14","colz");
gPad->SetLogz();
c1->Draw();

观察pie和ring的所有条的能量分布¶

  • 未刻度能量
In [20]:
tr->Draw("per:pid>>(48,0,48,800,0,1600)","","colz");
c1->Draw();
In [21]:
tr->Draw("rer:rid>>(48,0,48,800,0,1600)","","colz");
c1->Draw();
  • 能量刻度后
In [22]:
tr->Draw("pee:pid>>(48,0,48,800,0,10000)","","colz");
c1->Draw();
In [23]:
tr->Draw("ree:rid>>(48,0,48,800,0,10000)","","colz");
c1->Draw();