WCSim
sample_readfile.C
Go to the documentation of this file.
1 #include <iostream>
2 #include <stdio.h>
3 #include <stdlib.h>
4 
5 #include "TTree.h"
6 #include "TH1F.h"
7 #include "TStyle.h"
8 #include "TROOT.h"
9 #include "TSystem.h"
10 #include "TCanvas.h"
11 #include "TFile.h"
12 #include "TString.h"
13 
14 #include "WCSimRootOptions.hh"
15 #include "WCSimRootGeom.hh"
16 #include "WCSimRootEvent.hh"
17 
18 // Only access the photon history class when -DWCSim_DEBUG_COMPILE_FLAG=ON is defined in compilation
19 //#define WCSIM_SAVE_PHOTON_HISTORY
20 
21 // Simple example of reading a generated Root file
22 int sample_readfile(const char *filename="../wcsim.root", TString events_tree_name="wcsimrootevent", const int verbose=0)
23 {
24  // Clear global scope
25  //gROOT->Reset();
26 
27  if(!events_tree_name.EqualTo("wcsimrootevent") &&
28  !events_tree_name.EqualTo("wcsimrootevent2") &&
29  !events_tree_name.EqualTo("wcsimrootevent_OD")) {
30  cerr << "Second argument events_tree_name MUST equal one of: wcsimrootevent wcsimrootevent2 wcsimrootevent_OD" << endl;
31  return -1;
32  }
33  const bool true_tracks_expected = events_tree_name.EqualTo("wcsimrootevent");
34 
35  // Open the file
36  TFile * file = new TFile(filename,"read");
37  if (!file->IsOpen()){
38  cout << "Error, could not open input file: " << filename << endl;
39  return -1;
40  }
41 
42  // Get the a pointer to the tree from the file
43  TTree *tree = (TTree*)file->Get("wcsimT");
44 
45  // Get the number of events
46  const long nevent = tree->GetEntries();
47  if(verbose) printf("Number of Event Tree Entries: %ld\n",nevent);
48 
49  // Create a WCSimRootEvent to put stuff from the tree in
50  WCSimRootEvent* wcsimrootsuperevent = new WCSimRootEvent();
51 
52  // Set the branch address for reading from the tree
53  TBranch *branch = tree->GetBranch(events_tree_name);
54  branch->SetAddress(&wcsimrootsuperevent);
55 
56  // Force deletion to prevent memory leak
57  tree->GetBranch(events_tree_name)->SetAutoDelete(kTRUE);
58 
59  // Geometry tree - only need 1 "event"
60  TTree *geotree = (TTree*)file->Get("wcsimGeoT");
61  WCSimRootGeom *geo = 0;
62  geotree->SetBranchAddress("wcsimrootgeom", &geo);
63  if(verbose) std::cout << "Geotree has: " << geotree->GetEntries() << " entries (1 expected)" << std::endl;
64  if (geotree->GetEntries() == 0) {
65  exit(9);
66  }
67  geotree->GetEntry(0);
68 
69  // Options tree - only need 1 "event"
70  TTree *opttree = (TTree*)file->Get("wcsimRootOptionsT");
71  WCSimRootOptions *opt = 0;
72  opttree->SetBranchAddress("wcsimrootoptions", &opt);
73  if(verbose) std::cout << "Options tree has: " << opttree->GetEntries() << " entries (1 expected)" << std::endl;
74  if (opttree->GetEntries() == 0) {
75  exit(9);
76  }
77  opttree->GetEntry(0);
78  opt->Print();
79 
80  // start with the main "subevent", as it contains most of the info
81  // and always exists.
82  WCSimRootTrigger* wcsimrootevent;
83 
84  const float detR = geo->GetWCCylRadius();
85  const float detZ = geo->GetWCCylLength();
86  TH1F *h1 = new TH1F("h1", "NDigits;NDigits in Trigger 0;Entries in bin", 8000, 0, 8000);
87  TH1F *hvtxX = new TH1F("hvtxX", "Event VTX X;True vertex X (cm);Entries in bin", 200, -detR, +detR);
88  TH1F *hvtxY = new TH1F("hvtxY", "Event VTX Y;True vertex Y (cm);Entries in bin", 200, -detR, +detR);
89  TH1F *hvtxZ = new TH1F("hvtxZ", "Event VTX Z;True vertex Z (cm);Entries in bin", 200, -detZ/2, +detZ/2);
90 
91  int num_trig=0;
92 
93  // Now loop over events
94  for (long ievent=0; ievent<nevent; ievent++)
95  {
96  // Read the event from the tree into the WCSimRootEvent instance
97  tree->GetEntry(ievent);
98  wcsimrootevent = wcsimrootsuperevent->GetTrigger(0);
99  if(verbose){
100  printf("********************************************************\n");
101  printf("Event Number (from loop): %ld\n", ievent);
102  printf("Event Number (from WCSimRootEventHeader): %d\n", wcsimrootevent->GetHeader()->GetEvtNum());
103  printf("Trigger Time [ns]: %ld\n", wcsimrootevent->GetHeader()->GetDate());
104  cout << "Trigger Type: " << wcsimrootevent->GetTriggerType()
105  << " " << WCSimEnumerations::EnumAsString(wcsimrootevent->GetTriggerType()) << endl;
106  printf("Interaction Nuance Code: %d\n", wcsimrootevent->GetMode());
107  printf("Number of Delayed Triggers (sub events): %d\n",
108  wcsimrootsuperevent->GetNumberOfSubEvents());
109 
110  if(true_tracks_expected) {
111  printf("Neutrino Vertex Geometry Volume Code: %d\n", wcsimrootevent->GetVtxvol());
112  printf("Neutrino Vertex Location [cm]: %f %f %f\n", wcsimrootevent->GetVtx(0),
113  wcsimrootevent->GetVtx(1),wcsimrootevent->GetVtx(2));
114  printf("Index of muon in WCSimRootTracks %d\n", wcsimrootevent->GetJmu());
115  printf("Number of final state particles %d\n", wcsimrootevent->GetNpar());
116  }
117  }
118  hvtxX->Fill(wcsimrootevent->GetVtx(0));
119  hvtxY->Fill(wcsimrootevent->GetVtx(1));
120  hvtxZ->Fill(wcsimrootevent->GetVtx(2));
121 
122  // Now read the tracks in the event
123 
124  // Get the number of tracks
125  const int ntrack = wcsimrootevent->GetNtrack();
126  const int ntrack_slots = wcsimrootevent->GetNtrack_slots();
127  if(verbose) {
128  cout << "SAVED TRACKS" << endl
129  << "Number of Saved WCSimRootTracks: " << ntrack << endl;
130  if(!true_tracks_expected)
131  cout << "No saved true tracks in branch: " << events_tree_name
132  << ". You can find them in: wcsimrootevent" << endl;
133  }
134  if(ntrack && !true_tracks_expected) {
135  cerr << ntrack << " true tracks found in branch: " << events_tree_name
136  << ". There should be none here. Don't trust them. You can find them in: wcsimrootevent" << endl;
137  }
138 
139  // Loop through elements in the TClonesArray of WCSimTracks
140  for (int itrack=0; itrack<ntrack_slots; itrack++)
141  {
142  TObject *element = (wcsimrootevent->GetTracks())->At(itrack);
143  if(!element)
144  continue;
145  WCSimRootTrack *wcsimroottrack = dynamic_cast<WCSimRootTrack*>(element);
146 
147  if(verbose > 1){
148  cout<<"Track: "<<itrack<<endl << " ";
149  int trackflag = wcsimroottrack->GetFlag();
150  if(trackflag==-1) cout<<"Primary neutrino track"<<endl;
151  else if(trackflag==-2) cout<<"Neutrino target nucleus track"<<endl;
152  else cout<<"Final state particle track"<<endl;
153  printf(" Track ipnu (PDG code): %d\n",wcsimroottrack->GetIpnu());
154  printf(" PDG code of parent particle (0 for primary, 999 for parent PDG code not found in the specific logic used): %d\n",wcsimroottrack->GetParenttype());
155  printf(" Track ID of parent particle (0 for primary): %d\n",wcsimroottrack->GetParentId());
156 
157  cout<<" Track initial dir [unit 3-vector]: ("
158  <<wcsimroottrack->GetDir(0)<<", "
159  <<wcsimroottrack->GetDir(1)<<", "
160  <<wcsimroottrack->GetDir(2)<<")"<<endl;
161  printf(" Track initial relativistic energy [MeV]: %f\n", wcsimroottrack->GetE());
162  printf(" Track initial momentum magnitude [MeV/c]: %f\n", wcsimroottrack->GetP());
163  printf(" Track mass [MeV/c2]: %f\n", wcsimroottrack->GetM());
164  printf(" Track ID: %d\n", wcsimroottrack->GetId());
165  printf(" Number of ID/OD crossings: %zu\n", wcsimroottrack->GetBoundaryPoints().size());
166  if (wcsimroottrack->GetBoundaryPoints().size()>0)
167  printf(" First crossing position [mm]: (%f %f %f), KE [MeV]: %f, time [ns]: %f, type: %d\n",
168  wcsimroottrack->GetBoundaryPoints().at(0).at(0),
169  wcsimroottrack->GetBoundaryPoints().at(0).at(1),
170  wcsimroottrack->GetBoundaryPoints().at(0).at(2),
171  wcsimroottrack->GetBoundaryKEs().at(0),
172  wcsimroottrack->GetBoundaryTimes().at(0),
173  wcsimroottrack->GetBoundaryTypes().at(0)
174  );
175  }//verbose
176  } // itrack // End of loop over tracks
177 
178  // Now look at the Cherenkov hits
179 
180  // Get the number of Cherenkov hits.
181  // Note... this is *NOT* the number of photons that hit tubes.
182  // It is the number of tubes hit with Cherenkov photons.
183  // The number of digitized tubes will be smaller because of the threshold.
184  // Each hit "raw" tube has several photon hits. The times are recorded.
185  // See chapter 5 of ../doc/DetectorDocumentation.pdf
186  // for more information on the structure of the root file.
187  //
188  // The following code prints out the hit times for the first 10 tubes and also
189  // adds up the total pe.
190  //
191  // For digitized info (one time/charge tube after a trigger) use
192  // the digitized information.
193  //
194 
195  int ncherenkovhits = wcsimrootevent->GetNcherenkovhits();
196  int ncherenkovdigihits = wcsimrootevent->GetNcherenkovdigihits();
197 
198  h1->Fill(ncherenkovdigihits);
199  if(verbose){
200  cout << "RAW HITS:" << endl;
201  printf("Number of PMTs with a true hit %d\n", ncherenkovhits);
202  }
203 
204  // Grab the big arrays of times and parent IDs
205  TClonesArray *timeArray = wcsimrootevent->GetCherenkovHitTimes();
206 #ifdef WCSIM_SAVE_PHOTON_HISTORY
207  TClonesArray *historyArray = wcsimrootevent->GetCherenkovHitHistories(); // scattering and reflection history
208 #endif
209 
210  int totalPe = 0;
211  // Loop through elements in the TClonesArray of WCSimRootCherenkovHits
212  for (int itruepmt=0; itruepmt < ncherenkovhits; itruepmt++)
213  {
214  TObject *Hit = (wcsimrootevent->GetCherenkovHits())->At(itruepmt);
215  WCSimRootCherenkovHit *wcsimrootcherenkovhit =
216  dynamic_cast<WCSimRootCherenkovHit*>(Hit);
217 
218  int tubeNumber = wcsimrootcherenkovhit->GetTubeID();
219  int timeArrayIndex = wcsimrootcherenkovhit->GetTotalPe(0);
220  int peForTube = wcsimrootcherenkovhit->GetTotalPe(1);
221  WCSimRootPMT pmt = geo->GetPMT(tubeNumber-1);
222  totalPe += peForTube;
223 
224  if ( itruepmt < 10 ) { // Only print first XX=10 tubes
225  if(verbose > 1) printf("photon hits on tube %d : %d, times: ( ",tubeNumber,peForTube);
226  for (int itruehit = timeArrayIndex; itruehit < timeArrayIndex + peForTube; itruehit++) {
227  WCSimRootCherenkovHitTime* HitTime =
228  dynamic_cast<WCSimRootCherenkovHitTime*>(timeArray->At(itruehit));
229 
230  if(verbose > 1) printf("%6.2f ", HitTime->GetTruetime() );
231  }//itruehit
232  if(verbose > 1) cout << ")" << endl;
233  }//itruepmt < 10
234 
235  } // itruepmt // End of loop over Cherenkov hits
236  if(verbose) cout << "Total p.e. on all tubes: " << totalPe << endl
237  << " average of " << (double)totalPe/(double)ncherenkovhits << " p.e. per tube" << endl;
238 
239  // Look at digitized hit info
240  // Loop over sub events
241  if(verbose) cout << "DIGITIZED HITS:" << endl;
242  for (int itrigger = 0 ; itrigger < wcsimrootsuperevent->GetNumberOfEvents(); itrigger++)
243  {
244  wcsimrootevent = wcsimrootsuperevent->GetTrigger(itrigger);
245  if(verbose) cout << "Sub event number = " << itrigger << "\n";
246 
247  int ncherenkovdigihits = wcsimrootevent->GetNcherenkovdigihits();
248  if(verbose) printf("Number of digits in sub-event: %d\n", ncherenkovdigihits);
249  int ncherenkovdigihits_slots = wcsimrootevent->GetNcherenkovdigihits_slots();
250  if(ncherenkovdigihits>0)
251  num_trig++;
252 
253  int idigifound = 0;
254  for (int idigi=0;idigi<ncherenkovdigihits_slots;idigi++)
255  {
256  // Loop through elements in the TClonesArray of WCSimRootCherenkovDigHits
257  TObject *element = (wcsimrootevent->GetCherenkovDigiHits())->At(idigi);
258  if(!element) continue;
259  idigifound++;
260 
261  WCSimRootCherenkovDigiHit *wcsimrootcherenkovdigihit =
262  dynamic_cast<WCSimRootCherenkovDigiHit*>(element);
263 
264  if(verbose > 1){
265  if ( idigi < 10 ){ // Only print first XX=10 tubes
266  WCSimRootPMT pmt;
267  const int tubeId = wcsimrootcherenkovdigihit->GetTubeId();
268  if(events_tree_name.EqualTo("wcsimrootevent"))
269  pmt = geo->GetPMT(tubeId - 1, false);
270  else if(events_tree_name.EqualTo("wcsimrootevent2"))
271  pmt = geo->GetPMT(tubeId - 1, true);
272  else if(events_tree_name.EqualTo("wcsimrootevent_OD"))
273  pmt = geo->GetODPMT(tubeId - 1);
274  //ensure you have the correct PMT
275  assert(tubeId == pmt.GetTubeNo());
276 
277  const float x = pmt.GetPosition(0);
278  const float y = pmt.GetPosition(1);
279  const float z = pmt.GetPosition(2);
280  printf("idigi, q [p.e.], time+950 [ns], tubeid (x,y,z): %d %f %f %d (%f, %f, %f) \n",idigi,wcsimrootcherenkovdigihit->GetQ(),
281  wcsimrootcherenkovdigihit->GetT(), tubeId, x, y, z);
282 
283  // print the parents of each photon in the digit
284  // retrieve the indices of the photons in this digit within the HitTimes array
285  std::vector<int> photonids=wcsimrootcherenkovdigihit->GetPhotonIds();
286  // loop over photons within the digit
287  int photonid=0;
288  for(auto thephotonsid : photonids){
289  WCSimRootCherenkovHitTime *thehittimeobject =
290  dynamic_cast<WCSimRootCherenkovHitTime*>(timeArray->At(thephotonsid));
291  if(thehittimeobject){
292  cout<<" digit "<<idigi<<" photon "<<photonid<<": ";
293  cout<<" HitTime index "<<thephotonsid<<", pre-smear time "<<thehittimeobject->GetTruetime()
294  <<", parent TrackID: "<<thehittimeobject->GetParentID()<<";";
295  }
296 #ifdef WCSIM_SAVE_PHOTON_HISTORY
297  // use the same index as WCSimRootCherenkovHitTime
298  WCSimRootCherenkovHitHistory *thehithistoryobject = dynamic_cast<WCSimRootCherenkovHitHistory*>(historyArray->At(thephotonsid));
299  if(thehithistoryobject) {
300  // Number of scattering, and types of reflection surface (WCSimEnumerations)
301  cout<<" Rayleigh Scattering: "<<thehithistoryobject->GetNRayScatters()<<", Mie Scattering: "<<thehithistoryobject->GetNMieScatters()<<", Reflection: ";
302  for (auto r: thehithistoryobject->GetReflectionSurfaces()) cout<<WCSimEnumerations::EnumAsString(r)<<" ";
303  cout<<";";
304  }
305 #endif
306  cout<<endl;
307  photonid++;
308  } // end loop over photons in digit
309  } // end test for first 10 tubes
310  } // end verbosity check
311  } // idigi // End of loop over Cherenkov digihits
312  if(verbose || idigifound != ncherenkovdigihits)
313  cout << idigifound << " digits found; expected " << ncherenkovdigihits << endl;
314  } // itrigger // End of loop over triggers
315 
316  // reinitialize super event between loops.
317  wcsimrootsuperevent->ReInitialize();
318 
319  } // ievent // End of loop over events
320 
321  float win_scale = 0.75;
322  int n_wide(2);
323  int n_high(2);
324  TCanvas* c1 = new TCanvas("c1", "First canvas", 500*n_wide*win_scale, 500*n_high*win_scale);
325  c1->Draw();
326  c1->Divide(2,2);
327  c1->cd(1); hvtxX->Draw();
328  c1->cd(2); hvtxY->Draw();
329  c1->cd(3); hvtxZ->Draw();
330  c1->cd(4); h1->Draw();
331 
332  cout << "********************" << endl
333  << num_trig << " triggers found with at least one digitised hit" << endl
334  << " when run over " << nevent << " events" << endl
335  << " giving average of " << (double)num_trig / (double)nevent << " triggers per event" << endl;
336 
337  return 0;
338 }
Detector geometry information (also containing PMT information arrays)
Int_t GetFlag() const
Float_t GetWCCylLength() const
WCSimRootPMT GetPMT(Int_t i, bool hybridsecondtype=false)
std::vector< double > GetBoundaryTimes() const
void Print(Option_t *option="") const
std::vector< int > GetPhotonIds() const
Int_t GetNumberOfSubEvents() const
Class holding digitised hit (aka digit or digi) information (after PMT & electronics simulation + tri...
Float_t GetWCCylRadius() const
Int_t GetIpnu() const
int64_t GetDate() const
Int_t GetId() const
Double_t GetTruetime() const
WCSimRootEventHeader * GetHeader()
Int_t GetVtxvol() const
TClonesArray * GetTracks() const
std::vector< int > GetBoundaryTypes() const
std::vector< float > GetBoundaryKEs() const
Int_t GetNcherenkovhits() const
Float_t GetDir(Int_t i=0) const
Float_t GetVtx(Int_t i=0)
std::vector< ReflectionSurface_t > GetReflectionSurfaces() const
Int_t GetParentId() const
Int_t GetParenttype() const
PMT geometry information.
Float_t GetM() const
Int_t GetNtrack_slots() const
TClonesArray * GetCherenkovHits() const
TClonesArray * GetCherenkovHitHistories() const
Class holding true (Cherenkov photon + dark noise) hit information.
Int_t GetNcherenkovdigihits() const
Class storing trigger information.
Int_t GetTotalPe(int i) const
Float_t GetE() const
WCSimRootTrigger * GetTrigger(int number)
WCSimRootPMT GetODPMT(Int_t i)
TClonesArray * GetCherenkovHitTimes() const
Int_t GetEvtNum() const
Int_t GetMode() const
string filename
Definition: MakeKin.py:235
List of WCSim running options.
Int_t GetNumberOfEvents() const
std::vector< std::vector< float > > GetBoundaryPoints() const
Class containing event information.
Int_t GetTubeNo() const
int sample_readfile(const char *filename="../wcsim.root", TString events_tree_name="wcsimrootevent", const int verbose=0)
WCSimRootGeom * geo
Int_t GetNcherenkovdigihits_slots() const
Int_t GetNtrack() const
static std::string EnumAsString(DigitizerType_t d)
Class holding true (Cherenkov photon + dark noise) hit information.
Int_t GetJmu() const
TClonesArray * GetCherenkovDigiHits() const
Class holding true track information.
Int_t GetNpar() const
TriggerType_t GetTriggerType() const
Float_t GetP() const
Class holding scattering and reflection history for each true hit (Cherenkov photon; dark noise are a...
Float_t GetPosition(Int_t i=0) const