LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
PhotonLibrary.cxx
Go to the documentation of this file.
1 
5 
7 
11 
12 #include "TFile.h"
13 #include "TTree.h"
14 #include "TKey.h"
15 #include "TF1.h"
16 
17 namespace phot{
18 
19  std::string const PhotonLibrary::OpChannelBranchName = "OpChannel";
20 
21  //------------------------------------------------------------
22 
23  void PhotonLibrary::StoreLibraryToFile(std::string LibraryFile, bool storeReflected, bool storeReflT0, size_t storeTiming) const
24  {
25  mf::LogInfo("PhotonLibrary") << "Writing photon library to input file: " << LibraryFile.c_str()<<std::endl;
26 
28 
29  TTree *tt = tfs->make<TTree>("PhotonLibraryData","PhotonLibraryData");
30 
31 
32  Int_t Voxel = 0;
33  Int_t OpChannel = 0;
34  Float_t Visibility = 0;
35  Float_t ReflVisibility = 0;
36  Float_t ReflTfirst = 0;
37  Float_t *timing_par = nullptr;
38 
39  tt->Branch("Voxel", &Voxel, "Voxel/I");
40  tt->Branch(OpChannelBranchName.c_str(), &OpChannel, (OpChannelBranchName + "/I").c_str());
41  tt->Branch("Visibility", &Visibility, "Visibility/F");
42 
43  if(storeTiming!=0)
44  {
45  if (!hasTiming()) {
46  // if this happens, you need to call CreateEmptyLibrary() with storeReflected set true
47  throw cet::exception("PhotonLibrary")
48  << "StoreLibraryToFile() requested to store the time propagation distribution parameters, which was not simulated.";
49  }
50  tt->Branch("timing_par", timing_par, Form("timing_par[%i]/F",size_t2int(storeTiming)));
52  throw cet::exception(" Photon Library ") << "Time propagation lookup table is different size than Direct table \n"
53  << "this should not be happening. ";
54  }
55 
56  if(storeReflected)
57  {
58  if (!hasReflected()) {
59  // if this happens, you need to call CreateEmptyLibrary() with storeReflected set true
60  throw cet::exception("PhotonLibrary")
61  << "StoreLibraryToFile() requested to store reflected light, which was not simulated.";
62  }
63  tt->Branch("ReflVisibility", &ReflVisibility, "ReflVisibility/F");
65  throw cet::exception(" Photon Library ") << "Reflected light lookup table is different size than Direct table \n"
66  << "this should not be happening. ";
67  }
68  if(storeReflT0) {
69  if (!hasReflectedT0()) {
70  // if this happens, you need to call CreateEmptyLibrary() with storeReflectedT0 set true
71  throw cet::exception("PhotonLibrary")
72  << "StoreLibraryToFile() requested to store reflected light timing, which was not simulated.";
73  }
74  tt->Branch("ReflTfirst", &ReflTfirst, "ReflTfirst/F");
75  }
76  for(size_t ivox=0; ivox!= fNVoxels; ++ivox)
77  {
78  for(size_t ichan=0; ichan!= fNOpChannels; ++ichan)
79  {
80  Visibility = uncheckedAccess(ivox, ichan);
81  if(storeReflected)
82  ReflVisibility = uncheckedAccessRefl(ivox, ichan);
83  if(storeReflT0)
84  ReflTfirst = uncheckedAccessReflT(ivox, ichan);
85  if(storeTiming!=0)
86  {
87  for (size_t i =0; i<storeTiming; i++) timing_par[i] = uncheckedAccessTimingPar(ivox, ichan, i);
88 
89  }
90  if (Visibility > 0 || ReflVisibility > 0)
91  {
92  Voxel = ivox;
93  OpChannel = ichan;
94  // visibility(ies) is(are) already set
95  tt->Fill();
96  }
97  }
98  }
99  }
100 
101 
102  //------------------------------------------------------------
103 
105  size_t NVoxels, size_t NOpChannels,
106  bool storeReflected /* = false */,
107  bool storeReflT0 /* = false */,
108  size_t storeTiming /* = false */
109  ) {
115 
116  fNVoxels = NVoxels;
118 
120  fHasReflected = storeReflected;
121  if (storeReflected) fReflLookupTable.resize(LibrarySize());
122  fHasReflectedT0 = storeReflT0;
123  if (storeReflT0) fReflTLookupTable.resize(LibrarySize());
124  fHasTiming = storeTiming;
125  if (storeTiming!=0)
126  {
129  }
130  }
131 
132 
133  //------------------------------------------------------------
134 
135  void PhotonLibrary::LoadLibraryFromFile(std::string LibraryFile, size_t NVoxels, bool getReflected, bool getReflT0, size_t getTiming)
136  {
142 
143  mf::LogInfo("PhotonLibrary") << "Reading photon library from input file: " << LibraryFile.c_str()<<std::endl;
144 
145  TFile *f = nullptr;
146  TTree *tt = nullptr;
147 
148  try
149  {
150  f = TFile::Open(LibraryFile.c_str());
151  tt = (TTree*)f->Get("PhotonLibraryData");
152  if (!tt) { // Library not in the top directory
153  TKey *key = f->FindKeyAny("PhotonLibraryData");
154  if (key)
155  tt = (TTree*)key->ReadObj();
156  else {
157  mf::LogError("PhotonLibrary") << "PhotonLibraryData not found in file" <<LibraryFile;
158  }
159  }
160  }
161  catch(...)
162  {
163  throw cet::exception("PhotonLibrary") << "Error in ttree load, reading photon library: " << LibraryFile << "\n";
164  }
165 
166 
167  Int_t Voxel;
168  Int_t OpChannel;
169  Float_t Visibility;
170  Float_t ReflVisibility;
171  Float_t ReflTfirst;
172  std::vector<Float_t> timing_par;
173 
174  tt->SetBranchAddress("Voxel", &Voxel);
175  tt->SetBranchAddress("OpChannel", &OpChannel);
176  tt->SetBranchAddress("Visibility", &Visibility);
177 
178  fHasTiming = getTiming;
179 
180  fHasReflected = getReflected;
181  if(getReflected)
182  tt->SetBranchAddress("ReflVisibility", &ReflVisibility);
183  fHasReflectedT0 = getReflT0;
184  if(getReflT0)
185  tt->SetBranchAddress("ReflTfirst", &ReflTfirst);
186 
187  fNVoxels = NVoxels;
188  fNOpChannels = PhotonLibrary::ExtractNOpChannels(tt); // EXPENSIVE!!!
189 
190  // with STL vectors, where `resize()` directly controls the allocation of
191  // memory, reserving the space is redundant; not so with `util::LazyVector`,
192  // where `resize()` never increases the memory
195 
196  if(fHasTiming!=0)
197  {
198  timing_par.reserve(getTiming);
199  timing_par.resize(getTiming);
200  tt->SetBranchAddress("timing_par", timing_par.data());
202  TNamed *n = (TNamed*)f->Get("fTimingParFormula");
203  if(!n) mf::LogError("PhotonLibrary") <<"Error reading the photon propagation formula. Please check the photon library." << std::endl;
204  fTimingParFormula = n->GetTitle();
206  mf::LogInfo("PhotonLibrary") <<"Time parametrization is activated. Using the formula: "<< fTimingParFormula << " with " << fTimingParNParameters << " parameters."<< std::endl;
207  }
208  if(fHasReflected) {
211  }
212  if(fHasReflectedT0) {
215  }
216 
217  size_t NEntries = tt->GetEntries();
218 
219  for(size_t i=0; i!=NEntries; ++i) {
220 
221 
222  tt->GetEntry(i);
223 
224  // Set the visibility at this optical channel
225  uncheckedAccess(Voxel, OpChannel) = Visibility;
226 
227  if(fHasReflected)
228  uncheckedAccessRefl(Voxel, OpChannel) = ReflVisibility;
229  if(fHasReflectedT0)
230  uncheckedAccessReflT(Voxel, OpChannel) = ReflTfirst;
231  if(fHasTiming!=0)
232  {
233  // TODO: use TF1::Copy
234  TF1 timingfunction(Form("timing_%i_%i",Voxel,OpChannel),fTimingParFormula.c_str(),0,200);
235 
236  for (size_t k=0;k<fTimingParNParameters;k++)
237  {
238  timingfunction.SetParameter(k,timing_par[k]);
239  }
240 
241  uncheckedAccessTimingTF1(Voxel,OpChannel) = timingfunction;
242  }
243  } // for entries
244 
245  mf::LogInfo("PhotonLibrary") <<"Photon lookup table size : "<< NVoxels << " voxels, " << fNOpChannels<<" channels";
246 
247  try
248  {
249  f->Close();
250  }
251  catch(...)
252  {
253  mf::LogError("PhotonLibrary") << "Error in closing file : " << LibraryFile;
254  }
255 
256  }
257 
258  //----------------------------------------------------
259 
260  float PhotonLibrary::GetCount(size_t Voxel, size_t OpChannel) const
261  {
262  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
263  return 0;
264  else
265  return uncheckedAccess(Voxel, OpChannel);
266  }
267  //----------------------------------------------------
268 
269  float PhotonLibrary::GetTimingPar(size_t Voxel, size_t OpChannel, size_t parnum) const
270  {
271  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
272  return 0;
273  else
274  return uncheckedAccessTimingPar(Voxel, OpChannel, parnum);
275  } //----------------------------------------------------
276 
277  float PhotonLibrary::GetReflCount(size_t Voxel, size_t OpChannel) const
278  {
279  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
280  return 0;
281  else
282  return uncheckedAccessRefl(Voxel, OpChannel);
283  }
284  //----------------------------------------------------
285 
286  float PhotonLibrary::GetReflT0(size_t Voxel, size_t OpChannel) const
287  {
288  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
289  return 0;
290  else
291  return uncheckedAccessReflT(Voxel, OpChannel);
292  }
293 
294  //----------------------------------------------------
295 
296  void PhotonLibrary::SetCount(size_t Voxel, size_t OpChannel, float Count)
297  {
298  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
299  mf::LogError("PhotonLibrary")<<"Error - attempting to set count in voxel " << Voxel<<" which is out of range";
300  else
301  uncheckedAccess(Voxel, OpChannel) = Count;
302  }
303  //----------------------------------------------------
304 
305  void PhotonLibrary::SetTimingPar(size_t Voxel, size_t OpChannel, float Count, size_t parnum)
306  {
307  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
308  mf::LogError("PhotonLibrary")<<"Error - attempting to set timing t0 count in voxel " << Voxel<<" which is out of range";
309  else
310  uncheckedAccessTimingPar(Voxel, OpChannel, parnum) = Count;
311  }
312  //----------------------------------------------------
313 
314  void PhotonLibrary::SetTimingTF1(size_t Voxel, size_t OpChannel, TF1 func)
315  {
316  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
317  mf::LogError("PhotonLibrary")<<"Error - attempting to set a propagation function in voxel " << Voxel<<" which is out of range";
318  else
319  uncheckedAccessTimingTF1(Voxel, OpChannel) = func;
320  }
321  //----------------------------------------------------
322 
323 
324  void PhotonLibrary::SetReflCount(size_t Voxel, size_t OpChannel, float Count)
325  {
326  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
327  mf::LogError("PhotonLibrary")<<"Error - attempting to set count in voxel " << Voxel<<" which is out of range";
328  else
329  uncheckedAccessRefl(Voxel, OpChannel) = Count;
330  }
331  //----------------------------------------------------
332 
333  void PhotonLibrary::SetReflT0(size_t Voxel, size_t OpChannel, float Count)
334  {
335  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
336  mf::LogError("PhotonLibrary")<<"Error - attempting to set count in voxel " << Voxel<<" which is out of range";
337  else
338  uncheckedAccessReflT(Voxel, OpChannel) = Count;
339  }
340 
341  //----------------------------------------------------
342 
343  float const* PhotonLibrary::GetCounts(size_t Voxel) const
344  {
345  if (Voxel >= fNVoxels) return nullptr;
346  else return fLookupTable.data_address(uncheckedIndex(Voxel, 0));
347  }
348 
349  //----------------------------------------------------
350 
351  const std::vector<float>* PhotonLibrary::GetTimingPars(size_t Voxel) const
352  {
353  if (Voxel >= fNVoxels) return nullptr;
354  else return fTimingParLookupTable.data_address(uncheckedIndex(Voxel, 0));
355  }
356 
357  //----------------------------------------------------
358 
359  TF1* PhotonLibrary::GetTimingTF1s(size_t Voxel) const
360  {
361  if (Voxel >= fNVoxels) return nullptr;
362  /*
363  * Sorry, Universe, but we can't undergo ROOT's bad design hell.
364  * TF1::GetRandom() is non-const member, because it uses some internal
365  * integral information which can be produced on the spot instead than
366  * always be present. That's called caching, it's Good, but it must not
367  * interfere with constantness of the interface (in fact, this is one of
368  * the few acceptable uses of `mutable` members).
369  * Because of this, this method can't return a constant `TF1`, therefore
370  * it can't be constant, therefore the underlying access returning a
371  * constant object is not acceptable.
372  * So I do the Bad thing.
373  * Plus I opened JIRA ROOT-9549
374  * (https://sft.its.cern.ch/jira/browse/ROOT-9549).
375  * After that is solved, this method should become:
376  *
377  * TF1 const* PhotonLibrary::GetTimingTF1s(size_t Voxel) const
378  *
379  * and the users should update their code accordingly.
380  */
381  else return const_cast<TF1*>(fTimingParTF1LookupTable.data_address(uncheckedIndex(Voxel, 0)));
382  }
383 
384  //----------------------------------------------------
385 
386  float const* PhotonLibrary::GetReflCounts(size_t Voxel) const
387  {
388  if (Voxel >= fNVoxels) return nullptr;
389  else return fReflLookupTable.data_address(uncheckedIndex(Voxel, 0));
390  }
391 
392  //----------------------------------------------------
393 
394  float const* PhotonLibrary::GetReflT0s(size_t Voxel) const
395  {
396  if (Voxel >= fNVoxels) return nullptr;
397  else return fReflTLookupTable.data_address(uncheckedIndex(Voxel, 0));
398  }
399 
400  //----------------------------------------------------
401 
402  size_t PhotonLibrary::ExtractNOpChannels(TTree* tree) {
403  TBranch* channelBranch = tree->GetBranch(OpChannelBranchName.c_str());
404  if (!channelBranch) {
406  << "Tree '" << tree->GetName() << "' has no branch 'OpChannel'";
407  }
408 
409  // fix a new local address for the branch
410  char* oldAddress = channelBranch->GetAddress();
411  Int_t channel;
412  channelBranch->SetAddress(&channel);
413  Int_t maxChannel = -1;
414 
415  // read all the channel values and pick the largest one
416  Long64_t iEntry = 0;
417  while (channelBranch->GetEntry(iEntry++)) {
418  if (channel > maxChannel) maxChannel = channel;
419  } // while
420 
421  LOG_DEBUG("PhotonLibrary")
422  << "Detected highest channel to be " << maxChannel << " from " << iEntry
423  << " tree entries";
424 
425  // restore the old branch address
426  channelBranch->SetAddress(oldAddress);
427 
428  return size_t(maxChannel + 1);
429 
430  } // PhotonLibrary::ExtractNOpChannels()
431 
432 
433  //----------------------------------------------------
434 
435 }
virtual float GetReflT0(size_t Voxel, size_t OpChannel) const override
const_pointer data_address(size_type pos) const
Returns a constant pointer to the specified element.
Definition: LazyVector.h:510
size_t fTimingParNParameters
Definition: PhotonLibrary.h:84
static int size_t2int(size_t val)
Converts size_t into integer.
size_t fHasTiming
Whether the current library deals with time propagation distribution.
Definition: PhotonLibrary.h:73
util::LazyVector< float > fReflLookupTable
Definition: PhotonLibrary.h:79
virtual float const * GetCounts(size_t Voxel) const override
Returns a pointer to NOpChannels() visibility values, one per channel.
bool fHasReflectedT0
Whether the current library deals with reflected light timing.
Definition: PhotonLibrary.h:71
void CreateEmptyLibrary(size_t NVoxels, size_t NChannels, bool storeReflected=false, bool storeReflT0=false, size_t storeTiming=0)
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
virtual float const * GetReflT0s(size_t Voxel) const override
virtual int NOpChannels() const override
Definition: PhotonLibrary.h:65
virtual float GetReflCount(size_t Voxel, size_t OpChannel) const override
void clear()
Removes all stored data and sets the nominal size to 0.
Definition: LazyVector.h:548
static std::string const OpChannelBranchName
Name of the optical channel number in the input tree.
float uncheckedAccess(size_t Voxel, size_t OpChannel) const
Unchecked access to a visibility datum.
Definition: PhotonLibrary.h:94
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
void StoreLibraryToFile(std::string LibraryFile, bool storeReflected=false, bool storeReflT0=false, size_t storeTiming=0) const
void reserve(size_type n)
Allocates enough memory in storage to store n elements.
Definition: LazyVector.h:344
float uncheckedAccessReflT(size_t Voxel, size_t OpChannel) const
Unchecked access to a reflected T0 visibility datum.
void SetCount(size_t Voxel, size_t OpChannel, float Count)
void SetTimingTF1(size_t Voxel, size_t OpChannel, TF1 func)
std::string fTimingParFormula
Definition: PhotonLibrary.h:83
size_t uncheckedIndex(size_t Voxel, size_t OpChannel) const
Returns the index of visibility of specified voxel and cell.
Definition: PhotonLibrary.h:90
TFile f
Definition: plotHisto.C:6
util::LazyVector< float > fLookupTable
Definition: PhotonLibrary.h:78
virtual bool hasReflectedT0() const override
Returns whether the current library deals with reflected light timing.
Definition: PhotonLibrary.h:57
static size_t ExtractNOpChannels(TTree *tree)
Returns the number of optical channels in the specified tree.
Definition: type_traits.h:56
size_type size() const noexcept
Returns the size of the vector.
Definition: LazyVector.h:156
void SetReflT0(size_t Voxel, size_t OpChannel, float reflT0)
bool fHasReflected
Whether the current library deals with reflected light counts.
Definition: PhotonLibrary.h:70
TF1 & uncheckedAccessTimingTF1(size_t Voxel, size_t OpChannel)
Unchecked access to a parameter of the time distribution.
TF1 * GetTimingTF1s(size_t Voxel) const
const std::vector< float > * GetTimingPars(size_t Voxel) const
util::LazyVector< TF1 > fTimingParTF1LookupTable
Definition: PhotonLibrary.h:82
void LoadLibraryFromFile(std::string LibraryFile, size_t NVoxels, bool storeReflected=false, bool storeReflT0=false, size_t storeTiming=0)
virtual float GetCount(size_t Voxel, size_t OpChannel) const override
void SetTimingPar(size_t Voxel, size_t OpChannel, float Count, size_t parnum)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
General LArSoft Utilities.
T * make(ARGS...args) const
float uncheckedAccessRefl(size_t Voxel, size_t OpChannel) const
Unchecked access to a reflected visibility datum.
size_t LibrarySize() const
Returns the number of elements in the library.
virtual bool hasReflected() const override
Returns whether the current library deals with reflected light count.
Definition: PhotonLibrary.h:54
float GetTimingPar(size_t Voxel, size_t OpChannel, size_t parnum) const
#define LOG_DEBUG(id)
Char_t n[5]
void resize(size_type newSize)
Changes the nominal size of the container.
Definition: LazyVector.h:528
util::LazyVector< std::vector< float > > fTimingParLookupTable
Definition: PhotonLibrary.h:81
util::LazyVector< float > fReflTLookupTable
Definition: PhotonLibrary.h:80
virtual float const * GetReflCounts(size_t Voxel) const override
virtual int NVoxels() const override
Definition: PhotonLibrary.h:66
void SetReflCount(size_t Voxel, size_t OpChannel, float Count)
bool hasTiming() const
Returns whether the current library deals with time propagation distributions.
Definition: PhotonLibrary.h:51
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
float uncheckedAccessTimingPar(size_t Voxel, size_t OpChannel, size_t parnum) const
Unchecked access to a parameter the time distribution.