1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
|
// Example of analysis class for the H1 data.
// =========================================
//
// This file uses 4 large data sets from the H1 collaboration at DESY Hamburg.
// One can access these data sets (277 MBytes) from the standard Root web site
// at: ftp://root.cern.ch/root/h1analysis/
// The Physics plots below generated by this example cannot be produced when
// using smaller data sets.
//
// There are several ways to analyze data stored in a Root Tree
// -Using TTree::Draw: This is very convenient and efficient for small tasks.
// A TTree::Draw call produces one histogram at the time. The histogram
// is automatically generated. The selection expression may be specified
// in the command line.
//
// -Using the TTreeViewer: This is a graphical interface to TTree::Draw
// with the same functionality.
//
// -Using the code generated by TTree::MakeClass: In this case, the user
// creates an instance of the analysis class. He has the control over
// the event loop and he can generate an unlimited number of histograms.
//
// -Using the code generated by TTree::MakeSelector. Like for the code
// generated by TTree::MakeClass, the user can do complex analysis.
// However, he cannot control the event loop. The event loop is controlled
// by TTree::Process called by the user. This solution is illustrated
// by the current code. The advantage of this method is that it can be run
// in a parallel environment using PROOF (the Parallel Root Facility).
//
// A chain of 4 files (originally converted from PAW ntuples) is used
// to illustrate the various ways to loop on Root data sets.
// Each data set contains a Root Tree named "h42"
// The class definition in h1analysis.h has been generated automatically
// by the Root utility TTree::MakeSelector using one of the files with the
// following statement:
// h42->MakeSelector("h1analysis");
// This produces two files: h1analysis.h and h1analysis.C (skeleton of this file)
// The h1analysis class is derived from the Root class TSelector.
//
// The following members functions are called by the TTree::Process functions.
// Begin(): called everytime a loop on the tree starts.
// a convenient place to create your histograms.
// SlaveBegin():
//
// Notify(): This function is called at the first entry of a new Tree
// in a chain.
// Process(): called to analyze each entry.
//
// SlaveTerminate():
//
// Terminate(): called at the end of a loop on a TTree.
// a convenient place to draw/fit your histograms.
//
// To use this file, try the following session
//
// Root > gROOT->Time(); //will show RT & CPU time per command
//
//==> A- create a TChain with the 4 H1 data files
// The chain can be created by executed the short macro h1chain.C below:
// {
// TChain chain("h42");
// chain.Add("$H1/dstarmb.root"); // 21330730 bytes 21920 events
// chain.Add("$H1/dstarp1a.root"); // 71464503 bytes 73243 events
// chain.Add("$H1/dstarp1b.root"); // 83827959 bytes 85597 events
// chain.Add("$H1/dstarp2.root"); // 100675234 bytes 103053 events
// //where $H1 is a system symbol pointing to the H1 data directory.
// }
//
// Root > .x h1chain.C
//
//==> B- loop on all events
// Root > chain.Process("h1analysis.C")
//
//==> C- same as B, but in addition fill the entry list with selected entries.
// The entry list is saved to a file "elist.root" by the Terminate function.
// To see the list of selected events, you can do elist->Print("all").
// The selection function has selected 7525 events out of the 283813 events
// in the chain of files. (2.65 per cent)
// Root > chain.Process("h1analysis.C","fillList")
//
//==> D- Process only entries in the entry list
// The entry list is read from the file in elist.root generated by step C
// Root > chain.Process("h1analysis.C","useList")
//
//==> E- the above steps have been executed via the interpreter.
// You can repeat the steps B, C and D using the script compiler
// by replacing "h1analysis.C" by "h1analysis.C+" or "h1analysis.C++"
//
// in a new session with ,eg:
//
//==> F- Create the chain as in A, then execute
// Root > chain.Process("h1analysis.C+","useList")
//
// The commands executed with the 4 different methods B,C,D and E
// produce two canvases shown below:
// begin_html <a href="gif/h1analysis_dstar.gif" >the Dstar plot</a> end_html
// begin_html <a href="gif/h1analysis_tau.gif" >the Tau D0 plot</a> end_html
//
// The same analysis can be run on PROOF. For a quick try start a PROOF-Lite
// session
//
// Root > TProof *p = TProof::Open("")
//
// create (if mot already done) the chain by executing the 'h1chain.C' macro
// mentioned above, and then tell ROOT to use PROOF to process the chain:
//
// Root > chain.SetProof()
//
// You can then repeat step B above. Step C can also be executed in PROOF. However,
// step D cannot be executed in PROOF as in the local session (i.e. just passing
// option 'useList'): to use the entry list you have to
//
//==> G- Load first in the session the list form the file
//
// Root > TFile f("elist.root")
// Root > TEntryList *elist = (TEntryList *) f.Get("elist")
//
// set it on the chain:
//
// Root > chain.SetEntryList(elist)
//
// call Process as in step B. Of course this works also for local processing.
//
//Author: Rene Brun
#include "h1analysis.h"
#include "TH2.h"
#include "TF1.h"
#include "TStyle.h"
#include "TCanvas.h"
#include "TPaveStats.h"
#include "TLine.h"
#include "TMath.h"
const Double_t dxbin = (0.17-0.13)/40; // Bin-width
const Double_t sigma = 0.0012;
//_____________________________________________________________________
Double_t fdm5(Double_t *xx, Double_t *par)
{
Double_t x = xx[0];
if (x <= 0.13957) return 0;
Double_t xp3 = (x-par[3])*(x-par[3]);
Double_t res = dxbin*(par[0]*TMath::Power(x-0.13957, par[1])
+ par[2] / 2.5066/par[4]*TMath::Exp(-xp3/2/par[4]/par[4]));
return res;
}
//_____________________________________________________________________
Double_t fdm2(Double_t *xx, Double_t *par)
{
Double_t x = xx[0];
if (x <= 0.13957) return 0;
Double_t xp3 = (x-0.1454)*(x-0.1454);
Double_t res = dxbin*(par[0]*TMath::Power(x-0.13957, 0.25)
+ par[1] / 2.5066/sigma*TMath::Exp(-xp3/2/sigma/sigma));
return res;
}
//_____________________________________________________________________
void h1analysis::Begin(TTree * /*tree*/)
{
// function called before starting the event loop
// -it performs some cleanup
// -it creates histograms
// -it sets some initialisation for the entry list
// This is needed when re-processing the object
Reset();
//print the option specified in the Process function.
TString option = GetOption();
Info("Begin", "starting h1analysis with process option: %s", option.Data());
//process cases with entry list
if (fChain) fChain->SetEntryList(0);
delete gDirectory->GetList()->FindObject("elist");
// case when one creates/fills the entry list
if (option.Contains("fillList")) {
fillList = kTRUE;
elist = new TEntryList("elist", "H1 selection from Cut");
// Add to the input list for processing in PROOF, if needed
if (fInput) {
fInput->Add(new TNamed("fillList",""));
// We send a clone to avoid double deletes when importing the result
fInput->Add(elist);
}
}
// case when one uses the entry list generated in a previous call
if (option.Contains("useList")) {
useList = kTRUE;
if (fInput) {
// Option "useList" not supported in PROOF directly
Warning("Begin", "option 'useList' not supported in PROOF - ignoring");
Warning("Begin", "the entry list must be set on the chain *before* calling Process");
} else {
TFile f("elist.root");
elist = (TEntryList*)f.Get("elist");
if (elist) elist->SetDirectory(0); //otherwise the file destructor will delete elist
}
}
}
//_____________________________________________________________________
void h1analysis::SlaveBegin(TTree *tree)
{
// function called before starting the event loop
// -it performs some cleanup
// -it creates histograms
// -it sets some initialisation for the entry list
//initialize the Tree branch addresses
Init(tree);
//print the option specified in the Process function.
TString option = GetOption();
Info("SlaveBegin",
"starting h1analysis with process option: %s (tree: %p)", option.Data(), tree);
//create histograms
hdmd = new TH1F("hdmd","dm_d",40,0.13,0.17);
h2 = new TH2F("h2","ptD0 vs dm_d",30,0.135,0.165,30,-3,6);
fOutput->Add(hdmd);
fOutput->Add(h2);
// Entry list stuff (re-parse option because on PROOF only SlaveBegin is called)
if (option.Contains("fillList")) {
fillList = kTRUE;
// Get the list
if (fInput) {
if ((elist = (TEntryList *) fInput->FindObject("elist")))
// Need to clone to avoid problems when destroying the selector
elist = (TEntryList *) elist->Clone();
if (elist)
fOutput->Add(elist);
else
fillList = kFALSE;
}
}
}
//_____________________________________________________________________
Bool_t h1analysis::Process(Long64_t entry)
{
// entry is the entry number in the current Tree
// Selection function to select D* and D0.
fProcessed++;
//in case one entry list is given in input, the selection has already been done.
if (!useList) {
// Read only the necessary branches to select entries.
// return as soon as a bad entry is detected
// to read complete event, call fChain->GetTree()->GetEntry(entry)
b_md0_d->GetEntry(entry); if (TMath::Abs(md0_d-1.8646) >= 0.04) return kFALSE;
b_ptds_d->GetEntry(entry); if (ptds_d <= 2.5) return kFALSE;
b_etads_d->GetEntry(entry); if (TMath::Abs(etads_d) >= 1.5) return kFALSE;
b_ik->GetEntry(entry); ik--; //original ik used f77 convention starting at 1
b_ipi->GetEntry(entry); ipi--;
b_ntracks->GetEntry(entry);
b_nhitrp->GetEntry(entry);
if (nhitrp[ik]*nhitrp[ipi] <= 1) return kFALSE;
b_rend->GetEntry(entry);
b_rstart->GetEntry(entry);
if (rend[ik] -rstart[ik] <= 22) return kFALSE;
if (rend[ipi]-rstart[ipi] <= 22) return kFALSE;
b_nlhk->GetEntry(entry); if (nlhk[ik] <= 0.1) return kFALSE;
b_nlhpi->GetEntry(entry); if (nlhpi[ipi] <= 0.1) return kFALSE;
b_ipis->GetEntry(entry); ipis--; if (nlhpi[ipis] <= 0.1) return kFALSE;
b_njets->GetEntry(entry); if (njets < 1) return kFALSE;
}
// if option fillList, fill the entry list
if (fillList) elist->Enter(entry);
// to read complete event, call fChain->GetTree()->GetEntry(entry)
// read branches not processed in ProcessCut
b_dm_d->GetEntry(entry); //read branch holding dm_d
b_rpd0_t->GetEntry(entry); //read branch holding rpd0_t
b_ptd0_d->GetEntry(entry); //read branch holding ptd0_d
//fill some histograms
hdmd->Fill(dm_d);
h2->Fill(dm_d,rpd0_t/0.029979*1.8646/ptd0_d);
return kTRUE;
}
//_____________________________________________________________________
void h1analysis::SlaveTerminate()
{
// nothing to be done
}
//_____________________________________________________________________
void h1analysis::Terminate()
{
// function called at the end of the event loop
hdmd = dynamic_cast<TH1F*>(fOutput->FindObject("hdmd"));
h2 = dynamic_cast<TH2F*>(fOutput->FindObject("h2"));
if (hdmd == 0 || h2 == 0) {
Error("Terminate", "hdmd = %p , h2 = %p", hdmd, h2);
return;
}
//create the canvas for the h1analysis fit
gStyle->SetOptFit();
TCanvas *c1 = new TCanvas("c1","h1analysis analysis",10,10,800,600);
c1->SetBottomMargin(0.15);
hdmd->GetXaxis()->SetTitle("m_{K#pi#pi} - m_{K#pi}[GeV/c^{2}]");
hdmd->GetXaxis()->SetTitleOffset(1.4);
//fit histogram hdmd with function f5 using the loglikelihood option
if (gROOT->GetListOfFunctions()->FindObject("f5"))
delete gROOT->GetFunction("f5");
TF1 *f5 = new TF1("f5",fdm5,0.139,0.17,5);
f5->SetParameters(1000000, .25, 2000, .1454, .001);
hdmd->Fit("f5","lr");
//create the canvas for tau d0
gStyle->SetOptFit(0);
gStyle->SetOptStat(1100);
TCanvas *c2 = new TCanvas("c2","tauD0",100,100,800,600);
c2->SetGrid();
c2->SetBottomMargin(0.15);
// Project slices of 2-d histogram h2 along X , then fit each slice
// with function f2 and make a histogram for each fit parameter
// Note that the generated histograms are added to the list of objects
// in the current directory.
if (gROOT->GetListOfFunctions()->FindObject("f2"))
delete gROOT->GetFunction("f2");
TF1 *f2 = new TF1("f2",fdm2,0.139,0.17,2);
f2->SetParameters(10000, 10);
h2->FitSlicesX(f2,0,-1,1,"qln");
TH1D *h2_1 = (TH1D*)gDirectory->Get("h2_1");
h2_1->GetXaxis()->SetTitle("#tau[ps]");
h2_1->SetMarkerStyle(21);
h2_1->Draw();
c2->Update();
TLine *line = new TLine(0,0,0,c2->GetUymax());
line->Draw();
// Have the number of entries on the first histogram (to cross check when running
// with entry lists)
TPaveStats *psdmd = (TPaveStats *)hdmd->GetListOfFunctions()->FindObject("stats");
psdmd->SetOptStat(1110);
c1->Modified();
//save the entry list to a Root file if one was produced
if (fillList) {
if (!elist)
elist = dynamic_cast<TEntryList*>(fOutput->FindObject("elist"));
if (elist) {
Printf("Entry list 'elist' created:");
elist->Print();
TFile efile("elist.root","recreate");
elist->Write();
} else {
Error("Terminate", "entry list requested but not found in output");
}
}
// Notify the amount of processed events
if (!fInput) Info("Terminate", "processed %lld events", fProcessed);
}
|