WCSim
pmtremove.C
Go to the documentation of this file.
1 
2 #include "TROOT.h"
3 #include "TFile.h"
4 #include "TTree.h"
5 #include "WCSimRootGeom.hh"
6 #include "WCSimRootEvent.hh"
7 #include <vector>
8 #include <iostream>
9 
10 // Input arguments: infile -- name of the WCSim rootfile from which PMT's are to be removed
11 // should have geometry and rootevent trees. infile is read-only
12 // outfile -- the same, but with a fraction of PMT's removed
13 // removefrac -- fraction of PMT's to remove. For example, 0.1 will remove 10% of the
14 // existing PMT's and adjust the geometry and hits and write the result to the output rootfile
15 
16 // Example of its use: It has to be compiled because of the use of stl vectors in
17 // one of the set routines for WCSimRootEvent
18 
19 //{
20 // gSystem->Load("libWCSimRoot.so");
21 // gSystem->CompileMacro("pmtremove.C","k");
22 // pmtremove("inputsample.root","outputsample.root",0.1);
23 //}
24 
25 
26 void pmtremove(TString infile, TString outfile, double removefrac)
27 {
28  // read old geometry from the input rootfile
29 
30  TFile *f2 = new TFile(infile);
31  TTree *oldtree = (TTree*)f2->Get("wcsimGeoT");
32  WCSimRootGeom* oldgeom = new WCSimRootGeom();
33  TBranch *gb = oldtree->GetBranch("wcsimrootgeom");
34  gb->SetAddress(&oldgeom);
35  oldtree->GetEntry(0);
36  int oldpmtnum = oldgeom->GetWCNumPMT();
37  Printf("Initial Number of PMTs: %d", oldpmtnum);
38 
39  // set up the new output file
40  TFile *f3 = new TFile(outfile,"RECREATE");
41  TTree *newtree = oldtree->CloneTree(0);
42  WCSimRootGeom* newgeom = new WCSimRootGeom();
43  newtree->SetBranchAddress("wcsimrootgeom",&newgeom);
44 
45  newgeom->SetWCCylRadius(oldgeom->GetWCCylRadius());
46  newgeom->SetWCCylLength(oldgeom->GetWCCylLength());
47  newgeom->SetMailBox_x(oldgeom->GetMailBox_x());
48  newgeom->SetMailBox_y(oldgeom->GetMailBox_y());
49  newgeom->SetMailBox_z(oldgeom->GetMailBox_z());
50  newgeom->SetGeo_Type(oldgeom->GetGeo_Type());
51  newgeom->SetWCOffset(oldgeom->GetWCOffset(0),
52  oldgeom->GetWCOffset(1),
53  oldgeom->GetWCOffset(2));
54  newgeom->SetOrientation(oldgeom->GetOrientation());
55  newgeom->SetWCPMTRadius(oldgeom->GetWCPMTRadius());
56 
57  // associates old PMTs with new PMTs Index into it is the old pmt number,
58  // gives back new PMT number. If PMT is removed, this array has -1 in it.
59 
60  const int asize = oldpmtnum + 1;
61  int pmtassoc[asize];
62 
63  int newpmtnum = 0;
64  int ict = 0; // old floor count
65  for (int i=0;i<oldpmtnum;i++)
66  {
67  WCSimRootPMT pmt = oldgeom->GetPMT(i);
68  int oldtubeno = pmt.GetTubeNo();
69  double ft = removefrac*( (double) i);
70  int icc = (int) floor(ft); // check to see when this rolls around another integer
71 
72  if ( ict != icc)
73  {
74  ict = icc;
75  pmtassoc[oldtubeno] = -1; // and remove this tube
76  }
77  else
78  {
79  pmtassoc[oldtubeno] = newpmtnum+1;
80  float rot[3];
81  float pos[3];
82  for (int j=0;j<3;j++)
83  {
84  rot[j] = pmt.GetOrientation(j);
85  pos[j] = pmt.GetPosition(j);
86  }
87  newgeom->SetPMT(newpmtnum,newpmtnum+1,pmt.GetCylLoc(),rot,pos,true);
88  newpmtnum++;
89  }
90  //if (i<100) std::cout << "input pmt: " << i << " " << oldtubeno << " assoc: " << pmtassoc[oldtubeno] << std::endl;
91 
92  }
93  newgeom->SetWCNumPMT(newpmtnum);
94  std::cout << "New PMT count: " << newpmtnum << std::endl;
95  newtree->Fill();
96  newtree->Write();
97 
98  //-------------------------------------------------------------------------------------------
99  //---------- Go through events -- drop PMT hits and renumber PMTs with the ones we have.
100  //-------------------------------------------------------------------------------------------
101 
102  TTree *oldevtree = (TTree*) f2->Get("wcsimT");
103  int nevent = oldevtree->GetEntries();
104  std::cout << "Number of events: " << nevent << std::endl;
105 
106  // Create a WCSimRootEvent to put stuff from the old tree in
107  WCSimRootEvent* oldsuperevent = new WCSimRootEvent();
108  TBranch *branch = oldevtree->GetBranch("wcsimrootevent");
109  branch->SetAddress(&oldsuperevent);
110  // Force deletion to prevent memory leak
111  oldevtree->GetBranch("wcsimrootevent")->SetAutoDelete(kTRUE);
112 
113  // Initialize the output tree
114 
115  TTree *newevtree = oldevtree->CloneTree(0);
116  WCSimRootEvent *newsuperevent = new WCSimRootEvent();
117  newsuperevent->Initialize();
118  newevtree->SetBranchAddress("wcsimrootevent",&newsuperevent);
119 
120  // Now loop over events
121  for (int ev=0; ev<nevent; ev++)
122  {
123  // Read the event from the tree into the WCSimRootEvent instance
124  oldevtree->GetEntry(ev);
125 
126  // new output event -- allocate memory here and let it go out of scope at the end of the loop.
127  // performance isn't so much an issue here.
128 
129  for (int itrigger = 0; itrigger < oldsuperevent->GetNumberOfEvents(); itrigger++)
130  {
131  //std::cout << "about to get a trigger: Event: " << ev << " Trigger: " << itrigger << std::endl;
132  WCSimRootTrigger *oldtrigger;
133  oldtrigger = oldsuperevent->GetTrigger(itrigger);
134  if (itrigger > 0) newsuperevent->AddSubEvent(); // don't have to add the first trigger, done by initialize
135  WCSimRootTrigger *newtrigger = newsuperevent->GetTrigger(itrigger);
136 
137  WCSimRootEventHeader *oldheader = oldtrigger->GetHeader();
138  newtrigger->SetHeader(oldheader->GetEvtNum(),oldheader->GetRun(),oldheader->GetDate(),oldheader->GetSubEvtNumber());
139  newtrigger->SetMode(oldtrigger->GetMode());
140  newtrigger->SetVtxvol(oldtrigger->GetVtxvol());
141  for (int i=0;i<3;i++) newtrigger->SetVtx(i,oldtrigger->GetVtx(i));
142  newtrigger->SetJmu(oldtrigger->GetJmu());
143  newtrigger->SetJp(oldtrigger->GetJp());
144  newtrigger->SetNpar(oldtrigger->GetNpar());
145 
146  WCSimRootPi0 *pi0info = oldtrigger->GetPi0Info();
147  float pi0vtx[3],gammae[2],gammavtx[2][3];
148  int gammaid[2];
149  for (int i=0;i<3;i++)
150  {
151  pi0vtx[i] = pi0info->GetPi0Vtx(i);
152  gammavtx[0][i] = pi0info->GetGammaVtx(0,i);
153  gammavtx[1][i] = pi0info->GetGammaVtx(1,i);
154  }
155  for (int i=0;i<2;i++)
156  {
157  gammaid[i] = pi0info->GetGammaID(i);
158  gammae[i] = pi0info->GetGammaE(i);
159  }
160  newtrigger->SetPi0Info(pi0vtx,gammaid,gammae,gammavtx);
161 
162  // Get the number of tracks
163  int ntrack = oldtrigger->GetNtrack();
164  int ntrack_slots = oldtrigger->GetNtrack_slots();
165  //printf("ntracks=%d\n",ntrack);
166 
167  // Loop through elements in the TClonesArray of WCSimTracks
168  for (int i=0; i<ntrack; i++)
169  {
170  TObject *element = (oldtrigger->GetTracks())->At(i);
171  if(!element)
172  continue;
173  WCSimRootTrack *track = dynamic_cast<WCSimRootTrack*>(element);
174  float dir[3],pdir[3],stop[3],start[3];
175  for (int j=0;j<3;j++)
176  {
177  dir[j] = track->GetDir(j);
178  pdir[j] = track->GetPdir(j);
179  stop[j] = track->GetStop(j);
180  start[j] = track->GetStart(j);
181  }
182  newtrigger->AddTrack(track->GetIpnu(),
183  track->GetFlag(),
184  track->GetM(),
185  track->GetP(),
186  track->GetE(),
187  track->GetStartvol(),
188  track->GetStopvol(),
189  dir,
190  pdir,
191  stop,
192  start,
193  track->GetParenttype(),
194  track->GetTime(),
195  track->GetId());
196 
197  } // End of loop over tracks
198 
199  // stopped here March 22 -- keep copying info from the old trigger to the new trigger
200 
201  // Now look at the Cherenkov hits
202 
203  // Get the number of Cherenkov hits.
204  // Note... this is *NOT* the number of photons that hit tubes.
205  // It is the number of tubes hit with Cherenkov photons.
206  // The number of digitized tubes will be smaller because of the threshold.
207  // Each hit "raw" tube has several photon hits. The times are recorded.
208  // See chapter 5 of ../doc/DetectorDocumentation.pdf
209  // for more information on the structure of the root file.
210  //
211  // For digitized info (one time/charge tube after a trigger) use
212  // the digitized information.
213  //
214 
215  int ncherenkovhits = oldtrigger->GetNcherenkovhits();
216  int ncherenkovdigihits = oldtrigger->GetNcherenkovdigihits();
217  int ncherenkovdigihits_slots = oldtrigger->GetNcherenkovdigihits_slots();
218 
219  // Grab the big arrays of times and parent IDs
220  TClonesArray *timeArray = oldtrigger->GetCherenkovHitTimes();
221 
222  // Loop through elements in the TClonesArray of WCSimRootCherenkovHits and copy info for non-removed PMT's
223 
224  for (int i=0; i< ncherenkovhits; i++)
225  {
226  TObject *Hit = (oldtrigger->GetCherenkovHits())->At(i);
227  WCSimRootCherenkovHit *wcsimrootcherenkovhit = dynamic_cast<WCSimRootCherenkovHit*>(Hit);
228 
229  int tubeNumber = wcsimrootcherenkovhit->GetTubeID();
230  int timeArrayIndex = wcsimrootcherenkovhit->GetTotalPe(0);
231  int peForTube = wcsimrootcherenkovhit->GetTotalPe(1);
232 
233  if (tubeNumber < 1 || tubeNumber > oldpmtnum)
234  {
235  std::cout << "Error in pmtremove: tube number out of range: " << tubeNumber << " max: " << oldpmtnum << std::endl;
236  exit(0); // die if we get a bad tube number
237  }
238  int newtubenumber = pmtassoc[tubeNumber];
239  if (newtubenumber > 0) // keep the tube's hits
240  {
241  vector<float> truetime;
242  vector<int> ppid;
243  for (int j=0; j<peForTube; j++)
244  {
245  WCSimRootCherenkovHitTime *HitTime = dynamic_cast<WCSimRootCherenkovHitTime*>(timeArray->At(timeArrayIndex+j));
246  truetime.push_back(HitTime->GetTruetime());
247  ppid.push_back(HitTime->GetParentID());
248  }
249  newtrigger->AddCherenkovHit(newtubenumber,truetime,ppid);
250  }
251  } // End of loop over Cherenkov hits
252 
253  // Copy digitized hits for non-removed PMT's, and recompute sumq
254 
255  float sumq = 0;
256 
257  for (int i=0;i<ncherenkovdigihits_slots;i++)
258  {
259  // Loop through elements in the TClonesArray of WCSimRootCherenkovDigiHits
260  TObject *element = (oldtrigger->GetCherenkovDigiHits())->At(i);
261  if(!element)
262  continue;
263  WCSimRootCherenkovDigiHit *wcsimrootcherenkovdigihit =
264  dynamic_cast<WCSimRootCherenkovDigiHit*>(element);
265  int tubeNumber = wcsimrootcherenkovdigihit->GetTubeId();
266  if (tubeNumber < 1 || tubeNumber > oldpmtnum)
267  {
268  std::cout << "Error in pmtremove: tube number out of range: " << tubeNumber << " max: " << oldpmtnum << std::endl;
269  exit(0); // die if we get a bad tube number
270  }
271  int newtubenumber = pmtassoc[tubeNumber];
272  if (newtubenumber > 0) // keep the tube's hits
273  {
274  newtrigger->AddCherenkovDigiHit(wcsimrootcherenkovdigihit->GetQ(),
275  wcsimrootcherenkovdigihit->GetT(),
276  newtubenumber);
277  sumq += wcsimrootcherenkovdigihit->GetQ();
278  }
279  //if ( i < 10 ) // Only print first XX=10 tubes
280  //printf("q, t, tubeid: %f %f %d \n",wcsimrootcherenkovdigihit->GetQ(),
281  // wcsimrootcherenkovdigihit->GetT(),wcsimrootcherenkovdigihit->GetTubeId());
282 
283  } // End of loop over Cherenkov digihits
284  newtrigger->SetSumQ(sumq);
285  //if (ev<100) { std::cout << "Sum charge: " << ev << " " << itrigger << " " << oldtrigger->GetSumQ() << " " << sumq << std::endl; }
286  } // End of loop over triggers in the event
287 
288  newevtree->Fill();
289  newevtree->Write();
290 
291  // reinitialize super events between loops.
292 
293  oldsuperevent->ReInitialize();
294  newsuperevent->ReInitialize();
295 
296  } // End of loop over events
297 
298 
299 
300  delete f2;
301  delete f3;
302 }
Int_t GetCylLoc() const
void SetPMT(Int_t i, Int_t tubeno, Int_t mPMTNo, Int_t mPMT_PMTno, Int_t cyl_loc, Double_t rot[3], Double_t pos[3], bool expand=true, bool hybridsecondtype=false)
Int_t GetSubEvtNumber() const
Detector geometry information (also containing PMT information arrays)
Int_t GetFlag() const
Float_t GetWCPMTRadius(bool hybridsecondtype=false) const
Float_t GetWCCylLength() const
Float_t GetStop(Int_t i=0) const
WCSimRootPMT GetPMT(Int_t i, bool hybridsecondtype=false)
Class holding digitised hit (aka digit or digi) information (after PMT & electronics simulation + tri...
void SetWCNumPMT(Int_t i, bool hybridsecondtype=false)
Float_t GetWCCylRadius() const
Int_t GetIpnu() const
Float_t GetGammaVtx(int i, int j) const
Int_t GetGeo_Type() const
void SetVtxvol(Int_t i)
int64_t GetDate() const
Int_t GetId() const
void SetWCCylRadius(Double_t f)
Double_t GetTruetime() const
void SetWCCylLength(Double_t f)
WCSimRootEventHeader * GetHeader()
void pmtremove(TString infile, TString outfile, double removefrac)
Definition: pmtremove.C:26
WCSimRootTrack * AddTrack(Int_t ipnu, Int_t flag, Double_t m, Double_t p, Double_t E, Int_t startvol, Int_t stopvol, Double_t dir[3], Double_t pdir[3], Double_t stop[3], Double_t start[3], Int_t parenttype, ProcessType_t creatorProcess, Double_t time, Int_t id, Int_t idParent, std::vector< std::vector< float >> bPs, std::vector< float > bKEs, std::vector< double > bTimes, std::vector< int > bTypes)
Class storing information about pi0 decays.
Int_t GetVtxvol() const
TClonesArray * GetTracks() const
Int_t GetNcherenkovhits() const
Float_t GetDir(Int_t i=0) const
Float_t GetVtx(Int_t i=0)
Int_t GetOrientation() const
Int_t GetParenttype() const
void SetOrientation(Int_t o)
WCSimRootPi0 * GetPi0Info()
PMT geometry information.
Float_t GetStart(Int_t i=0) const
Int_t GetWCNumPMT(bool hybridsecondtype=false) const
Float_t GetM() const
Float_t GetGammaE(int i) const
Int_t GetNtrack_slots() const
TClonesArray * GetCherenkovHits() const
Class holding true (Cherenkov photon + dark noise) hit information.
void SetGeo_Type(Int_t f)
void SetJp(Int_t i)
Int_t GetNcherenkovdigihits() const
Class containing header information for this trigger.
Class storing trigger information.
void SetWCOffset(Double_t x, Double_t y, Double_t z)
void SetPi0Info(Double_t pi0Vtx[3], Int_t gammaID[2], Double_t gammaE[2], Double_t gammaVtx[2][3])
Int_t GetTotalPe(int i) const
Float_t GetE() const
WCSimRootTrigger * GetTrigger(int number)
TClonesArray * GetCherenkovHitTimes() const
Int_t GetEvtNum() const
Int_t GetMode() const
void SetNpar(Int_t i)
void SetJmu(Int_t i)
Int_t GetStartvol() const
Int_t GetGammaID(int i) const
Int_t GetNumberOfEvents() const
Class containing event information.
Int_t GetTubeNo() const
WCSimRootCherenkovDigiHit * AddCherenkovDigiHit(Double_t q, Double_t t, Int_t tubeid, Int_t mpmtid, Int_t mpmt_pmtid, std::vector< int > photon_ids)
Float_t GetWCOffset(Int_t i) const
Float_t GetPi0Vtx(int i) const
Int_t GetNcherenkovdigihits_slots() const
Int_t GetNtrack() const
Float_t GetPdir(Int_t i=0) const
Int_t GetJp() const
Double_t GetTime() const
void SetHeader(Int_t i, Int_t run, int64_t date, Int_t subevtn=1)
Class holding true (Cherenkov photon + dark noise) hit information.
Float_t GetOrientation(Int_t i=0) const
Int_t GetJmu() const
Int_t GetStopvol() const
TClonesArray * GetCherenkovDigiHits() const
void SetMode(Int_t i)
Class holding true track information.
Int_t GetNpar() const
WCSimRootCherenkovHit * AddCherenkovHit(Int_t tubeID, Int_t mPMTID, Int_t mPMT_PMTID, std::vector< Double_t > truetime, std::vector< Int_t > primParID, std::vector< Float_t > photonStartTime, std::vector< TVector3 > photonStartPos, std::vector< TVector3 > photonEndPos, std::vector< TVector3 > photonStartDir, std::vector< TVector3 > photonEndDir, std::vector< ProcessType_t > photonCreatorProcess)
void SetWCPMTRadius(Double_t f, int hybridsecondtype=false)
void SetVtx(Int_t i, Double_t f)
Float_t GetP() const
void SetSumQ(Double_t x)
Float_t GetPosition(Int_t i=0) const