WCSim
read_LIGen_OD_output.C
Go to the documentation of this file.
1 // C++ Includes
2 #include <iostream>
3 //#include <algorithm>
4 //#include <iomanip>
5 #include <cmath>
6 
7 // ROOT Includes
8 #include "TH1F.h"
9 #include "TH2F.h"
10 #include "TFile.h"
11 //#include "TApplication.h"
12 
13 
14 // WCSim Includes
15 #include "WCSimRootEvent.hh"
16 #include "WCSimRootGeom.hh"
17 
18 // Defines
19 #define PI 3.141592654
20 #define topPMT 19
21 
22 /*
23 *This macro is adapted from read_OD.C to read the output from the light injector simulation. It produces a simplified tree with OD hit information useful for the LI analysis for OD calibration, including the digitised charge and time, hit PMT position and cylinder location.
24 *
25 *How to run:
26 *
27 * enter in the terminal root -l 'read_LIGen_OD_output.C("WCSim.root","outputFile.root",false)' to run
28 * where you replace WCSim.root with your file name and outputfile with the name you wish to save it under
29 */
30 
31 // A function to easily format the histograms
32 void format_histogram(TH1D* h, std::string title ,std::string xtitle, std::string ytitle){
33  h->SetTitle( title.c_str() );
34  h->GetXaxis()->SetTitle( xtitle.c_str() );
35  h->GetYaxis()->SetTitle( ytitle.c_str() );
36  h->SetLineColor(kRed);
37  h->SetLineWidth(2);
38 }
39 // An (overloaded) function to easily format the histograms
40 void format_histogram(TH2D* h, std::string title ,std::string xtitle, std::string ytitle){
41  h->SetTitle( title.c_str() );
42  h->GetXaxis()->SetTitle( xtitle.c_str() );
43  h->GetYaxis()->SetTitle( ytitle.c_str() );
44 }
45 
46 void read_LIGen_OD_output(std::string inFileName, std::string outFileName, bool verbosity=0){
47 
48 
49  // Some nicely formatted text options
50  std::cout << std::scientific; // This causes all numbers to be displayed in scientific notation.
51  std::cout << std::setprecision(2); // Sets the decimal precision (no more than two decimal places)
52  std::cout << std::left; // Sets the text justification to left
53  const int txtW = 20; // Width of "box" holding text
54  const int numW = 10; // Width of "box" holding numbers
55 
56 
57  // Open the WCSim file
58  TFile *inFile = new TFile(inFileName.c_str(), "READ");
59  if ( !inFile->IsOpen() ){
60  std::cout << "Error: could not open input file \"" << inFileName << "\"." <<std::endl;
61 
62  } else if (verbosity) {
63  std::cout << "Input file: " << inFileName << std::endl;
64  }
65 
66 
67 
68  // Get a pointer to the tree from the input file
69  TTree *wcsimTree = (TTree*) inFile->Get("wcsimT");
70 
71  // Get the number of events in the tree
72  long int nEvent = wcsimTree->GetEntries();
73  if (verbosity) { std::cout << "Number of events: "<< nEvent << std::endl;}
74 
75  // Create a WCSimRootEvent to put stuff from the tree in
76  WCSimRootEvent *wcsimRootID = new WCSimRootEvent();
77  WCSimRootEvent *wcsimRootOD = new WCSimRootEvent();
78  WCSimRootEvent *wcsimRootMPMT = new WCSimRootEvent();
79 
80  // Set the branch address for reading from the tree
81  TBranch *branch = wcsimTree->GetBranch("wcsimrootevent");
82  TBranch *branchOD = wcsimTree->GetBranch("wcsimrootevent_OD");
83  TBranch *branchMPMT = wcsimTree->GetBranch("wcsimrootevent2");
84  branch->SetAddress(&wcsimRootID);
85  branchOD->SetAddress(&wcsimRootOD);
86  branchMPMT->SetAddress(&wcsimRootMPMT);
87 
88  // Force deletion to prevent memory leak
89  wcsimTree->GetBranch("wcsimrootevent")->SetAutoDelete(kTRUE);
90  wcsimTree->GetBranch("wcsimrootevent_OD")->SetAutoDelete(kTRUE);
91  wcsimTree->GetBranch("wcsimrootevent2")->SetAutoDelete(kTRUE);
92 
93  // Load the geometry tree (only 1 "event")
94  TTree *geoTree = (TTree*) inFile->Get("wcsimGeoT");
95  WCSimRootGeom *geo = nullptr;//new WCSimRootGeom();
96  geoTree->SetBranchAddress("wcsimrootgeom",&geo);
97  if (verbosity) {std::cout << "Geotree has " << geoTree->GetEntries() << " entries." << std::endl;}
98  geoTree->GetEntry(0);
99 
100  // Start with the main trigger as it always exists and contains most of the info
101  WCSimRootTrigger *wcsimTriggerID;
102  WCSimRootTrigger *wcsimTriggerOD;
103  WCSimRootTrigger *wcsimTriggerMPMT;
104 
105  // Create an output file
106  TFile *outFile = new TFile(outFileName.c_str(), "RECREATE");
107  TTree *outBranch = new TTree("simulation", "simulation");
108 
109  // Detector geometry details
110  int MAXPMT = geo->GetWCNumPMT(); // Get the maximum number of PMTs in the ID
111  int MAXPMTA = geo->GetODWCNumPMT(); // Get the maximum number of PMTs in the OD
112 
113  // Injector variables to read in from the root file
114  float injectorVtxX, injectorVtxY, injectorVtxZ; // injector location
115  float injectorDirX, injectorDirY, injectorDirZ; // injector direction (axis)
116  float rawHitsID; // number of raw pmt hits
117  float digiHitsID; // number of pmt digitised hits
118  int numPMTsHitID; // Number of PMTs hit
119  int numPMTsDigiHitID; // Number of PMTs with digihits
120  float rawHitsOD; // number of raw pmt hits
121  float digiHitsOD; // number of pmt digitised hits
122  int numPMTsHitOD; // Number of PMTs hit
123  int numPMTsDigiHitOD; // Number of PMTs with digihits
124  float rawHitsMPMT; // number of raw pmt hits
125  float digiHitsMPMT; // number of pmt digitised hits
126  int numPMTsHitMPMT; // Number of PMTs hit
127  int numPMTsDigiHitMPMT; // Number of PMTs with digihits
128 
129  // Variables to read in from the root file - OD only for OD LI
130  float pmtX;
131  float pmtY;
132  float pmtZ;
133  int cylLoc;
134  int tubeNumber;
135  float digiTime;
136  float digiCharge;
137 
138  // other variables
139  int event, trigger;
140 
141  // Set the branches to be saved.
142  outBranch->Branch("event", &event, "event/I");
143  outBranch->Branch("trigger", &trigger, "trigger/I");
144  outBranch->Branch("injectorVtxX", &injectorVtxX, "injectorVtxX/F");
145  outBranch->Branch("injectorVtxY", &injectorVtxY, "injectorVtxY/F");
146  outBranch->Branch("injectorVtxZ", &injectorVtxZ, "injectorVtxZ/F");
147  outBranch->Branch("injectorDirX", &injectorDirX, "injectorDirX/F");
148  outBranch->Branch("injectorDirY", &injectorDirY, "injectorDirY/F");
149  outBranch->Branch("injectorDirZ", &injectorDirZ, "injectorDirZ/F");
150  outBranch->Branch("rawHitsID", &rawHitsID, "rawHitsID/F");
151  outBranch->Branch("digiHitsID", &digiHitsID, "digiHitsID/F");
152  outBranch->Branch("numPMTsHitID", &numPMTsHitID, "numPMTsHitID/I");
153  outBranch->Branch("numPMTsDigiHitID", &numPMTsDigiHitID, "numPMTsDigiHitID/I");
154  outBranch->Branch("rawHitsMPMT", &rawHitsMPMT, "rawHitsMPMT/F");
155  outBranch->Branch("digiHitsMPMT", &digiHitsMPMT, "digiHitsMPMT/F");
156  outBranch->Branch("numPMTsHitMPMT", &numPMTsHitMPMT, "numPMTsHitMPMT/I");
157  outBranch->Branch("numPMTsDigiHitMPMT", &numPMTsDigiHitMPMT, "numPMTsDigiHitMPMT/I");
158  outBranch->Branch("rawHitsOD", &rawHitsOD, "rawHitsOD/F");
159  outBranch->Branch("digiHitsOD", &digiHitsOD, "digiHitsOD/F");
160  outBranch->Branch("numPMTsHitOD", &numPMTsHitOD, "numPMTsHitOD/I");
161  outBranch->Branch("numPMTsDigiHitOD", &numPMTsDigiHitOD, "numPMTsDigiHitOD/I");
162  outBranch->Branch("cylLoc",&cylLoc,"cylLoc/I");
163  outBranch->Branch("tubeNumber",&tubeNumber,"tubeNumber/I");
164  outBranch->Branch("pmtX",&pmtX,"pmtX/F");
165  outBranch->Branch("pmtY",&pmtY,"pmtY/F");
166  outBranch->Branch("pmtZ",&pmtZ,"pmtZ/F");
167  outBranch->Branch("digiTime",&digiTime,"digiTime/F");
168  outBranch->Branch("digiCharge",&digiCharge,"digiCharge/F");
169 
170  // Declare histograms
171  // number of hit PMTs
172  TH1D *numRawHitPMTsIDHist = new TH1D("numRawHitPMTsIDHist","numRawHitPMTsIDHist",200, 0, 1000);
173  TH1D *numDigiHitPMTsIDHist = new TH1D("numDigiHitPMTsIDHist","numDigiHitPMTsIDHist",200, 0, 1000);
174  TH1D *numRawHitPMTsMPMTHist = new TH1D("numRawHitPMTsMPMTHist","numRawHitPMTsMPMTHist",200, 0, 1000);
175  TH1D *numDigiHitPMTsMPMTHist = new TH1D("numDigiHitPMTsMPMTHist","numDigiHitPMTsMPMTHist",200, 0, 1000);
176  TH1D *numRawHitPMTsODHist = new TH1D("numRawHitPMTsODHist","numRawHitPMTsODHist",200, 0, 1000);
177  TH1D *numDigiHitPMTsODHist = new TH1D("numDigiHitPMTsODHist","numDigiHitPMTsODHist",200, 0, 1000);
178  // number of hits (pe)
179  TH1D *numRawHitsIDHist = new TH1D("numRawHitsIDHist","numRawHitsIDHist",200, 0, 1000);
180  TH1D *numDigiHitsIDHist = new TH1D("numDigiHitsIDHist","numDigiHitsIDHist",200, 0, 1000);
181  TH1D *numRawHitsMPMTHist = new TH1D("numRawHitsMPMTHist","numRawHitsMPMTHist",200, 0, 1000);
182  TH1D *numDigiHitsMPMTHist = new TH1D("numDigiHitsMPMTHist","numDigiHitsMPMTHist",200, 0, 1000);
183  TH1D *numRawHitsODHist = new TH1D("numRawHitsODHist","numRawHitsODHist",200, 0, 1000);
184  TH1D *numDigiHitsODHist = new TH1D("numDigiHitsODHist","numDigiHitsODHist",200, 0, 1000);
185 
186  // Format histograms ( hist, title, x_title, y_title)
187  format_histogram(numRawHitPMTsIDHist, "" , "Number of hit ID PMTs [raw]", "");
188  format_histogram(numDigiHitPMTsIDHist, "" , "Number of hit ID PMTs [digi]", "");
189  format_histogram(numRawHitPMTsMPMTHist, "" , "Number of hit MPMT PMTs [raw]", "");
190  format_histogram(numDigiHitPMTsMPMTHist, "" , "Number of hit MPMT PMTs [digi]", "");
191  format_histogram(numRawHitPMTsODHist, "" , "Number of hit OD PMTs [raw]", "");
192  format_histogram(numDigiHitPMTsODHist, "" , "Number of hit OD PMTs [digi]", "");
193 
194  format_histogram(numRawHitsIDHist, "" , "Number of ID hits [pe]", "");
195  format_histogram(numDigiHitsIDHist, "" , "Number of ID hits [pe]", "");
196  format_histogram(numRawHitsMPMTHist, "" , "Number of MPMT hits [pe]", "");
197  format_histogram(numDigiHitsMPMTHist, "" , "Number of MPMT hits [pe]", "");
198  format_histogram(numRawHitsODHist, "" , "Number of OD hits [pe]", "");
199  format_histogram(numDigiHitsODHist, "" , "Number of OD hits [pe]", "");
200 
201  // Event Analysis
202  for (int ev = 0; ev < nEvent; ev++){ // Loop over events
203 
204  std::string command;
205  wcsimTree->GetEntry(ev);
206  wcsimTriggerID = wcsimRootID->GetTrigger(0);
207  int numTriggersID = wcsimRootID->GetNumberOfEvents();
208  int numSubTriggersID = wcsimRootID->GetNumberOfSubEvents();
209 
210  wcsimTriggerOD = wcsimRootOD->GetTrigger(0);
211  int numTriggersOD = wcsimRootOD->GetNumberOfEvents();
212  int numSubTriggersOD = wcsimRootOD->GetNumberOfSubEvents();
213 
214  wcsimTriggerMPMT = wcsimRootMPMT->GetTrigger(0);
215  int numTriggersMPMT = wcsimRootMPMT->GetNumberOfEvents();
216  int numSubTriggersMPMT = wcsimRootMPMT->GetNumberOfSubEvents();
217  event = ev;
218 
219  for (int nTrig = 0; nTrig < numTriggersID; nTrig++){
220 
221  trigger = nTrig;
222 
223  // ID
224  wcsimTriggerID = wcsimRootID->GetTrigger(nTrig);
225  int numTracksID = wcsimTriggerID->GetNtrack();
226  WCSimRootTrack * trackID = (WCSimRootTrack*) wcsimTriggerID->GetTracks()->At(nTrig);
227 
228  // Get the injector position and injectorDirection
229  // This is the same for all ID and OD hits
230  injectorVtxX = wcsimTriggerID->GetVtx(0);
231  injectorVtxY = wcsimTriggerID->GetVtx(1);
232  injectorVtxZ = wcsimTriggerID->GetVtx(2);
233  injectorDirX = trackID->GetDir(0);
234  injectorDirY = trackID->GetDir(1);
235  injectorDirZ = trackID->GetDir(2);
236 
237  rawHitsID = 0;
238  digiHitsID = 0;
239 
240  numPMTsHitID = wcsimTriggerID->GetNcherenkovhits(); //Returns the number of PMTs with a true hit (photon or dark noise) (QE applied)
241  numPMTsDigiHitID = wcsimTriggerID->GetNcherenkovdigihits(); //Returns the number of PMTs with a true hit (photon or dark noise) (QE applied)
242 
243  // Work out the number of photons that hit the ID PMTs
244  for (int i = 0; i < numPMTsHitID; i++){
245  WCSimRootCherenkovHit *cherenkovHitID = (WCSimRootCherenkovHit*) wcsimTriggerID->GetCherenkovHits()->At(i);
246  float tmpRawHitsID = cherenkovHitID->GetTotalPe(1);
247  rawHitsID += tmpRawHitsID;
248  } // End of for loop working out number of photons in ID PMTs
249 
250  // Work out the number of digitised hits in the ID PMTs
251  for (int i = 0; i < numPMTsDigiHitID; i++){
252  WCSimRootCherenkovDigiHit *cherenkovDigiHitID = (WCSimRootCherenkovDigiHit*) wcsimTriggerID->GetCherenkovDigiHits()->At(i);
253  float tmpDigiHitsID = cherenkovDigiHitID->GetQ();
254 
255  digiHitsID += tmpDigiHitsID;
256  } // End of for loop working out number of digitized hits in PMTs
257  } // END OF loop over ID triggers
258 
259  for (int nTrig = 0; nTrig < numTriggersMPMT; nTrig++){
260 
261  trigger = nTrig;
262 
263  wcsimTriggerMPMT = wcsimRootMPMT->GetTrigger(nTrig);
264  int numTracksMPMT = wcsimTriggerMPMT->GetNtrack();
265  WCSimRootTrack * trackMPMT = (WCSimRootTrack*) wcsimTriggerMPMT->GetTracks()->At(nTrig);
266 
267  rawHitsMPMT = 0;
268  digiHitsMPMT = 0;
269 
270  numPMTsHitMPMT = wcsimTriggerMPMT->GetNcherenkovhits(); //Returns the number of PMTs with a true hit (photon or dark noise) (QE applied)
271  numPMTsDigiHitMPMT = wcsimTriggerMPMT->GetNcherenkovdigihits(); //Returns the number of PMTs with a true hit (photon or dark noise) (QE applied)
272 
273  // Work out the number of photons that hit the MPMT PMTs
274  for (int i = 0; i < numPMTsHitMPMT; i++){
275  WCSimRootCherenkovHit *cherenkovHitMPMT = (WCSimRootCherenkovHit*) wcsimTriggerMPMT->GetCherenkovHits()->At(i);
276  float tmpRawHitsMPMT = cherenkovHitMPMT->GetTotalPe(1);
277  rawHitsMPMT += tmpRawHitsMPMT;
278  } // End of for loop working out number of photons in MPMT PMTs
279 
280  // Work out the number of digitised hits in the MPMT PMTs
281  for (int i = 0; i < numPMTsDigiHitMPMT; i++){
282  WCSimRootCherenkovDigiHit *cherenkovDigiHitMPMT = (WCSimRootCherenkovDigiHit*) wcsimTriggerMPMT->GetCherenkovDigiHits()->At(i);
283  float tmpDigiHitsMPMT = cherenkovDigiHitMPMT->GetQ();
284 
285  digiHitsMPMT += tmpDigiHitsMPMT;
286  } // End of for loop working out number of digitized hits in PMTs
287  } // END OF loop over MPMT triggers
288 
289  // OD
290  for (int nTrigOD = 0; nTrigOD < numTriggersOD; nTrigOD++){
291 
292  wcsimTriggerOD = wcsimRootOD->GetTrigger(nTrigOD);
293  int numTracksOD = wcsimTriggerOD->GetNtrack();
294  WCSimRootTrack * trackOD = (WCSimRootTrack*) wcsimTriggerOD->GetTracks()->At(nTrigOD);
295 
296  rawHitsOD = 0;
297  digiHitsOD = 0;
298 
299  event = ev;
300 
301  numPMTsHitOD = wcsimTriggerOD->GetNcherenkovhits(); //number of PMTs with a true hit (photon or dark noise) (QE applied)
302  numPMTsDigiHitOD = wcsimTriggerOD->GetNcherenkovdigihits(); // number of PMTs with a true hit (photon or dark noise) (QE applied)
303  // Work out the number of photons that hit the OD PMTs
304  for (int i = 0; i < numPMTsHitOD; i++){
305  WCSimRootCherenkovHit *cherenkovHitOD = (WCSimRootCherenkovHit*) wcsimTriggerOD->GetCherenkovHits()->At(i);
306  float tmpRawHitsOD = cherenkovHitOD->GetTotalPe(1);
307  rawHitsOD += tmpRawHitsOD;
308  } // End of for loop working out number of photons in OD PMTs
309 
310  // Work out the number of digitised hits in the OD PMTs
311  for (int i = 0; i < numPMTsDigiHitOD; i++){
312  WCSimRootCherenkovDigiHit *cherenkovDigiHitOD = (WCSimRootCherenkovDigiHit*) wcsimTriggerOD->GetCherenkovDigiHits()->At(i);
313  float tmpDigiHitsOD = cherenkovDigiHitOD->GetQ();
314 
315  digiHitsOD += tmpDigiHitsOD;
316  } // End of for loop working out number of digitized hits in PMTs
317 
318  int ncherenkovdigihits_slots = wcsimTriggerOD->GetNcherenkovdigihits_slots();
319 
320  // Loop through elements in the TClonesArray of WCSimRootCherenkovHits
321  for (int i=0; i< ncherenkovdigihits_slots; i++){
322  TObject *Digi = (wcsimTriggerOD->GetCherenkovDigiHits())->At(i);
323  if(!Digi)
324  continue;
325  WCSimRootCherenkovDigiHit *wcsimrootcherenkovdigihit =
326  dynamic_cast<WCSimRootCherenkovDigiHit*>(Digi);
327  tubeNumber = wcsimrootcherenkovdigihit->GetTubeId();
328  digiCharge = wcsimrootcherenkovdigihit->GetQ();
329  digiTime = wcsimrootcherenkovdigihit->GetT();
330  WCSimRootPMT pmt = geo->GetODPMT(tubeNumber-1);
331  pmtX = pmt.GetPosition(0);
332  pmtY = pmt.GetPosition(1);
333  pmtZ = pmt.GetPosition(2);
334  cylLoc = pmt.GetCylLoc();
335  outBranch->Fill(); // fill the tree with events
336  } // end of loop over the OD digitised hits
337 
338 
339 
340  if (verbosity){
341  std::cout << "====================================================" << std::endl;
342  std::cout << "Event\t" << ev << std::endl;
343  std::cout << "Trigger\t" << nTrigOD << std::endl;
344  std::cout << "injectorVtx\t" << injectorVtxX << " " << injectorVtxY << " " << injectorVtxZ << std::endl;
345  std::cout << "injectorDir\t" << injectorDirX << " " << injectorDirY << " " << injectorDirZ << std::endl;
346  std::cout << "rawhitsOD\t" << rawHitsOD << std::endl;
347  std::cout << "digihitsOD\t" << digiHitsOD << std::endl;
348  std::cout << "rawhitsID\t" << rawHitsID << std::endl;
349  std::cout << "digihitsID\t" << digiHitsID << std::endl;
350  std::cout << "numPMTsHitOD\t" << numPMTsHitOD << std::endl;
351  std::cout << "numPMTsDigiHitOD\t" << numPMTsDigiHitOD << std::endl;
352  std::cout << "numPMTsHitID\t" << numPMTsHitID << std::endl;
353  std::cout << "numPMTsDigiHitID\t" << numPMTsDigiHitID << std::endl;
354  }
355 
356  numRawHitsIDHist->Fill(rawHitsID);
357  numDigiHitsIDHist->Fill(digiHitsID);
358  numRawHitsMPMTHist->Fill(rawHitsMPMT);
359  numDigiHitsMPMTHist->Fill(digiHitsMPMT);
360  numRawHitsODHist->Fill(rawHitsOD);
361  numDigiHitsODHist->Fill(digiHitsOD);
362 
363  numRawHitPMTsIDHist->Fill(numPMTsHitID);
364  numDigiHitPMTsIDHist->Fill(numPMTsDigiHitID);
365  numRawHitPMTsMPMTHist->Fill(numPMTsHitMPMT);
366  numDigiHitPMTsMPMTHist->Fill(numPMTsDigiHitMPMT);
367  numRawHitPMTsODHist->Fill(numPMTsHitOD);
368  numDigiHitPMTsODHist->Fill(numPMTsDigiHitOD);
369 
370 
371  } // End of loop over OD triggers
372 
373 
374  } // End of loop over events
375 
376 // outBranch->Write();
377 
378 
379  outFile->Write(); // Write all of objects to the output file.
380  outFile->Close(); // Close the output file.
381 
382 }
383 
384 
385 
386 
Int_t GetCylLoc() const
Int_t GetODWCNumPMT() const
Detector geometry information (also containing PMT information arrays)
Int_t GetNumberOfSubEvents() const
Class holding digitised hit (aka digit or digi) information (after PMT & electronics simulation + tri...
TClonesArray * GetTracks() const
Int_t GetNcherenkovhits() const
Float_t GetDir(Int_t i=0) const
Float_t GetVtx(Int_t i=0)
PMT geometry information.
Int_t GetWCNumPMT(bool hybridsecondtype=false) const
TClonesArray * GetCherenkovHits() const
Int_t GetNcherenkovdigihits() const
Class storing trigger information.
Int_t GetTotalPe(int i) const
WCSimRootTrigger * GetTrigger(int number)
void format_histogram(TH1D *h, std::string title, std::string xtitle, std::string ytitle)
WCSimRootPMT GetODPMT(Int_t i)
Int_t GetNumberOfEvents() const
void read_LIGen_OD_output(std::string inFileName, std::string outFileName, bool verbosity=0)
Class containing event information.
WCSimRootGeom * geo
Int_t GetNcherenkovdigihits_slots() const
Int_t GetNtrack() const
Class holding true (Cherenkov photon + dark noise) hit information.
TClonesArray * GetCherenkovDigiHits() const
Class holding true track information.
Float_t GetPosition(Int_t i=0) const