LArSoft  v07_13_02
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, int fTimingMaxRange)
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; `data_init()` allocates
193  // all the storage we need at once, effectively suppressing the laziness
194  // of the vector (by design, that was only relevant in `CreateEmptyLibrary()`)
197 
198  if(fHasTiming!=0)
199  {
200  timing_par.resize(getTiming);
201  tt->SetBranchAddress("timing_par", timing_par.data());
203  TNamed *n = (TNamed*)f->Get("fTimingParFormula");
204  if(!n) mf::LogError("PhotonLibrary") <<"Error reading the photon propagation formula. Please check the photon library." << std::endl;
205  fTimingParFormula = n->GetTitle();
208  mf::LogInfo("PhotonLibrary") <<"Time parametrization is activated. Using the formula: "<< fTimingParFormula << " with " << fTimingParNParameters << " parameters."<< std::endl;
209  }
210  if(fHasReflected) {
213  }
214  if(fHasReflectedT0) {
217  }
218 
219  size_t NEntries = tt->GetEntries();
220 
221  for(size_t i=0; i!=NEntries; ++i) {
222 
223 
224  tt->GetEntry(i);
225 
226  // Set the visibility at this optical channel
227  uncheckedAccess(Voxel, OpChannel) = Visibility;
228 
229  if(fHasReflected)
230  uncheckedAccessRefl(Voxel, OpChannel) = ReflVisibility;
231  if(fHasReflectedT0)
232  uncheckedAccessReflT(Voxel, OpChannel) = ReflTfirst;
233  if(fHasTiming!=0)
234  {
235  // TODO: use TF1::Copy
236  TF1 timingfunction(Form("timing_%i_%i",Voxel,OpChannel),fTimingParFormula.c_str(),timing_par[0],fTimingMaxRange);
237  timingfunction.SetParameter(0,0.0);//first parameter is now in the range. Let's do this to keep compatible with old libraries.
238  for (size_t k=1;k<fTimingParNParameters;k++)
239  {
240  timingfunction.SetParameter(k,timing_par[k]);
241  }
242 
243  uncheckedAccessTimingTF1(Voxel,OpChannel) = timingfunction;
244  }
245  } // for entries
246 
247  mf::LogInfo("PhotonLibrary") <<"Photon lookup table size : "<< NVoxels << " voxels, " << fNOpChannels<<" channels";
248 
249  try
250  {
251  f->Close();
252  }
253  catch(...)
254  {
255  mf::LogError("PhotonLibrary") << "Error in closing file : " << LibraryFile;
256  }
257 
258  }
259 
260  //----------------------------------------------------
261 
262  float PhotonLibrary::GetCount(size_t Voxel, size_t OpChannel) const
263  {
264  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
265  return 0;
266  else
267  return uncheckedAccess(Voxel, OpChannel);
268  }
269  //----------------------------------------------------
270 
271  float PhotonLibrary::GetTimingPar(size_t Voxel, size_t OpChannel, size_t parnum) const
272  {
273  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
274  return 0;
275  else
276  return uncheckedAccessTimingPar(Voxel, OpChannel, parnum);
277  } //----------------------------------------------------
278 
279  float PhotonLibrary::GetReflCount(size_t Voxel, size_t OpChannel) const
280  {
281  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
282  return 0;
283  else
284  return uncheckedAccessRefl(Voxel, OpChannel);
285  }
286  //----------------------------------------------------
287 
288  float PhotonLibrary::GetReflT0(size_t Voxel, size_t OpChannel) const
289  {
290  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
291  return 0;
292  else
293  return uncheckedAccessReflT(Voxel, OpChannel);
294  }
295 
296  //----------------------------------------------------
297 
298  void PhotonLibrary::SetCount(size_t Voxel, size_t OpChannel, float Count)
299  {
300  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
301  mf::LogError("PhotonLibrary")<<"Error - attempting to set count in voxel " << Voxel<<" which is out of range";
302  else
303  uncheckedAccess(Voxel, OpChannel) = Count;
304  }
305  //----------------------------------------------------
306 
307  void PhotonLibrary::SetTimingPar(size_t Voxel, size_t OpChannel, float Count, size_t parnum)
308  {
309  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
310  mf::LogError("PhotonLibrary")<<"Error - attempting to set timing t0 count in voxel " << Voxel<<" which is out of range";
311  else
312  uncheckedAccessTimingPar(Voxel, OpChannel, parnum) = Count;
313  }
314  //----------------------------------------------------
315 
316  void PhotonLibrary::SetTimingTF1(size_t Voxel, size_t OpChannel, TF1 func)
317  {
318  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
319  mf::LogError("PhotonLibrary")<<"Error - attempting to set a propagation function in voxel " << Voxel<<" which is out of range";
320  else
321  uncheckedAccessTimingTF1(Voxel, OpChannel) = func;
322  }
323  //----------------------------------------------------
324 
325 
326  void PhotonLibrary::SetReflCount(size_t Voxel, size_t OpChannel, float Count)
327  {
328  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
329  mf::LogError("PhotonLibrary")<<"Error - attempting to set count in voxel " << Voxel<<" which is out of range";
330  else
331  uncheckedAccessRefl(Voxel, OpChannel) = Count;
332  }
333  //----------------------------------------------------
334 
335  void PhotonLibrary::SetReflT0(size_t Voxel, size_t OpChannel, float Count)
336  {
337  if ((Voxel >= fNVoxels) || (OpChannel >= fNOpChannels))
338  mf::LogError("PhotonLibrary")<<"Error - attempting to set count in voxel " << Voxel<<" which is out of range";
339  else
340  uncheckedAccessReflT(Voxel, OpChannel) = Count;
341  }
342 
343  //----------------------------------------------------
344 
345  float const* PhotonLibrary::GetCounts(size_t Voxel) const
346  {
347  if (Voxel >= fNVoxels) return nullptr;
348  else return fLookupTable.data_address(uncheckedIndex(Voxel, 0));
349  }
350 
351  //----------------------------------------------------
352 
353  const std::vector<float>* PhotonLibrary::GetTimingPars(size_t Voxel) const
354  {
355  if (Voxel >= fNVoxels) return nullptr;
356  else return fTimingParLookupTable.data_address(uncheckedIndex(Voxel, 0));
357  }
358 
359  //----------------------------------------------------
360 
361  TF1* PhotonLibrary::GetTimingTF1s(size_t Voxel) const
362  {
363  if (Voxel >= fNVoxels) return nullptr;
364  /*
365  * Sorry, Universe, but we can't undergo ROOT's bad design hell.
366  * TF1::GetRandom() is non-const member, because it uses some internal
367  * integral information which can be produced on the spot instead than
368  * always be present. That's called caching, it's Good, but it must not
369  * interfere with constantness of the interface (in fact, this is one of
370  * the few acceptable uses of `mutable` members).
371  * Because of this, this method can't return a constant `TF1`, therefore
372  * it can't be constant, therefore the underlying access returning a
373  * constant object is not acceptable.
374  * So I do the Bad thing.
375  * Plus I opened JIRA ROOT-9549
376  * (https://sft.its.cern.ch/jira/browse/ROOT-9549).
377  * After that is solved, this method should become:
378  *
379  * TF1 const* PhotonLibrary::GetTimingTF1s(size_t Voxel) const
380  *
381  * and the users should update their code accordingly.
382  */
383  else return const_cast<TF1*>(fTimingParTF1LookupTable.data_address(uncheckedIndex(Voxel, 0)));
384  }
385 
386  //----------------------------------------------------
387 
388  float const* PhotonLibrary::GetReflCounts(size_t Voxel) const
389  {
390  if (Voxel >= fNVoxels) return nullptr;
391  else return fReflLookupTable.data_address(uncheckedIndex(Voxel, 0));
392  }
393 
394  //----------------------------------------------------
395 
396  float const* PhotonLibrary::GetReflT0s(size_t Voxel) const
397  {
398  if (Voxel >= fNVoxels) return nullptr;
399  else return fReflTLookupTable.data_address(uncheckedIndex(Voxel, 0));
400  }
401 
402  //----------------------------------------------------
403 
404  size_t PhotonLibrary::ExtractNOpChannels(TTree* tree) {
405  TBranch* channelBranch = tree->GetBranch(OpChannelBranchName.c_str());
406  if (!channelBranch) {
408  << "Tree '" << tree->GetName() << "' has no branch 'OpChannel'";
409  }
410 
411  // fix a new local address for the branch
412  char* oldAddress = channelBranch->GetAddress();
413  Int_t channel;
414  channelBranch->SetAddress(&channel);
415  Int_t maxChannel = -1;
416 
417  // read all the channel values and pick the largest one
418  Long64_t iEntry = 0;
419  while (channelBranch->GetEntry(iEntry++)) {
420  if (channel > maxChannel) maxChannel = channel;
421  } // while
422 
423  LOG_DEBUG("PhotonLibrary")
424  << "Detected highest channel to be " << maxChannel << " from " << iEntry
425  << " tree entries";
426 
427  // restore the old branch address
428  channelBranch->SetAddress(oldAddress);
429 
430  return size_t(maxChannel + 1);
431 
432  } // PhotonLibrary::ExtractNOpChannels()
433 
434 
435  //----------------------------------------------------
436 
437 }
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:584
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
void LoadLibraryFromFile(std::string LibraryFile, size_t NVoxels, bool storeReflected=false, bool storeReflT0=false, size_t storeTiming=0, int maxrange=200)
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 data_init(size_type startIndex, size_type endIndex)
Allocates the specified range and stores default values for it.
Definition: LazyVector.h:647
void clear()
Removes all stored data and sets the nominal size to 0.
Definition: LazyVector.h:622
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
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
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:602
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.