LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PhotonVisibilityService.cc
Go to the documentation of this file.
1 // ////////////////////////////////////////////////////////////////////////
2 //
3 // \file PhotonVisibilityService_service.cc
4 //
6 //
7 // Ben Jones, MIT 2012
8 //
9 // This service reports the visibility of a particular point in
10 // the detector to each OpDet. This is used by the fast
11 // optical simulation and by track-light association algorithms.
12 //
13 // Visibility is defined as the fraction of isotropically produced
14 // photons from a detector voxel which are expected to reach the
15 // OpDet in question.
16 //
17 // This information is lookup up from a previously generated
18 // optical library file, whose path is specified to this service.
19 //
20 // Note that it is important that the voxelization schemes match
21 // between the library and the service instance for sensible results.
22 //
23 //
24 
25 // LArSoft includes
27 
33 
34 // framework libraries
37 #include "art_root_io/TFileService.h"
39 #include "cetlib/search_path.h"
40 #include "fhiclcpp/ParameterSet.h"
42 
43 // ROOT libraries
44 #include "TF1.h"
45 
46 // C/C++ standard libraries
47 #include <fstream>
48 
49 namespace phot {
50 
52  {
53  delete fparslogNorm;
54  delete fparslogNorm_far;
55  delete fparsMPV;
56  delete fparsMPV_far;
57  delete fparsWidth;
58  delete fparsCte;
59  delete fparsCte_far;
60  delete fparsSlope;
61  delete fparslogNorm_refl;
62  delete fparsMPV_refl;
63  delete fparsWidth_refl;
64  delete fparsCte_refl;
65  delete fparsSlope_refl;
66  delete fTheLibrary;
67  }
68 
69  //--------------------------------------------------------------------
71  :
72 
73  fCurrentVoxel(0)
74  , fCurrentValue(0.)
75  , fXmin(0.)
76  , fXmax(0.)
77  , fYmin(0.)
78  , fYmax(0.)
79  , fZmin(0.)
80  , fZmax(0.)
81  , fNx(0)
82  , fNy(0)
83  , fNz(0)
84  , fUseCryoBoundary(false)
85  , fUseAutomaticVoxels(false)
86  , fSaveTPCVoxels()
88  , fLibraryBuildJob(false)
89  , fDoNotLoadLibrary(false)
90  , fParameterization(false)
91  , fHybrid(false)
92  , fStoreReflected(false)
93  , fStoreReflT0(false)
94  , fIncludePropTime(false)
95  , fUseNhitsModel(false)
96  , fParPropTime(false)
100  , fInterpolate(false)
101  , fReflectOverZeroX(false)
102  , fparslogNorm(nullptr)
103  , fparslogNorm_far(nullptr)
104  , fparsMPV(nullptr)
105  , fparsMPV_far(nullptr)
106  , fparsWidth(nullptr)
107  , fparsCte(nullptr)
108  , fparsCte_far(nullptr)
109  , fparsSlope(nullptr)
110  , fD_break(0.0)
111  , fD_max(0.0)
112  , fTF1_sampling_factor(0.0)
113  , fparslogNorm_refl(nullptr)
114  , fparsMPV_refl(nullptr)
115  , fparsWidth_refl(nullptr)
116  , fparsCte_refl(nullptr)
117  , fparsSlope_refl(nullptr)
118  , fT0_max(0.0)
119  , fT0_break_point(0.0)
120  , fLibraryFile()
121  , fTheLibrary(nullptr)
122  , fVoxelDef()
123  {
124  this->reconfigure(pset);
125 
126  if (pset.has_key("ReflectOverZeroX")) { // legacy parameter warning
127  if (pset.has_key("Mapping")) {
129  << "`PhotonVisbilityService` configuration specifies both `Mapping` and "
130  "`ReflectOverZeroX`."
131  " Please remove the latter (and use `PhotonMappingXMirrorTransformations` tool).";
132  }
133  else {
134  mf::LogWarning("PhotonVisbilityService")
135  << "Please update the configuration of `PhotonVisbilityService` service"
136  " replacing `ReflectOverZeroX` with tool configuration:"
137  "\n Mapping: { tool_type: \"PhotonMappingXMirrorTransformations\" }";
138  }
139  } // if
140  fhicl::ParameterSet mapDefaultSet;
141  mapDefaultSet.put("tool_type",
142  fReflectOverZeroX ? "PhotonMappingXMirrorTransformations" :
143  "PhotonMappingIdentityTransformations");
144  fMapping = art::make_tool<phot::IPhotonMappingTransformations>(
145  pset.get<fhicl::ParameterSet>("Mapping", mapDefaultSet));
146 
147  mf::LogInfo("PhotonVisibilityService") << "PhotonVisbilityService initializing" << std::endl;
148  }
149 
150  //--------------------------------------------------------------------
152  {
153  // Don't do anything if the library has already been loaded.
154 
155  if (fTheLibrary == 0) {
156 
157  if ((!fLibraryBuildJob) && (!fDoNotLoadLibrary)) {
158  std::string LibraryFileWithPath;
159  cet::search_path sp("FW_SEARCH_PATH");
160 
161  if (!sp.find_file(fLibraryFile, LibraryFileWithPath))
162  throw cet::exception("PhotonVisibilityService")
163  << "Unable to find photon library in " << sp.to_string() << "\n";
164 
165  if (!fParameterization) {
167 
168  mf::LogInfo("PhotonVisibilityService")
169  << "PhotonVisibilityService Loading photon library from file " << LibraryFileWithPath
170  << " for " << GetVoxelDef().GetNVoxels() << " voxels and " << geom->NOpDets()
171  << " optical detectors." << std::endl;
172 
173  if (fHybrid) {
174  fTheLibrary = new PhotonLibraryHybrid(LibraryFileWithPath, GetVoxelDef());
175  }
176  else {
177  PhotonLibrary* lib = new PhotonLibrary;
178  fTheLibrary = lib;
179 
180  size_t NVoxels = GetVoxelDef().GetNVoxels();
181  lib->LoadLibraryFromFile(LibraryFileWithPath,
182  NVoxels,
184  fStoreReflT0,
187 
188  // if the library does not have metadata, we supply some;
189  // otherwise we check that it's compatible with the configured one
190  // (and shrug if it's not); overriding configured metadata
191  // from the one in the library is currently not supported
192  if (!lib->hasVoxelDef())
193  lib->SetVoxelDef(GetVoxelDef());
194  else if (GetVoxelDef() != lib->GetVoxelDef()) {
195  // this might become a fatal error in the future if some protocol
196  // is imposed... it may also be possible to check only the size
197  // rather than the coordinates, which may allow for translations
198  // of the geometry volumes in world space.
199  mf::LogWarning("PhotonVisbilityService")
200  << "Photon library reports the geometry:\n"
201  << lib->GetVoxelDef() << "while PhotonVisbilityService is configured with:\n"
202  << GetVoxelDef();
203  } // if metadata
204  }
205  }
206  }
207  else {
209 
210  size_t NOpDets = geom->NOpDets();
211  size_t NVoxels = GetVoxelDef().GetNVoxels();
212  if (fLibraryBuildJob) {
213  mf::LogInfo("PhotonVisibilityService")
214  << " Vis service running library build job. Please ensure "
215  << " job contains LightSource, LArG4, SimPhotonCounter";
216  }
217 
218  art::TFileDirectory* pDir = nullptr;
219  try {
221  }
222  catch (art::Exception const& e) {
223  if (e.categoryCode() != art::errors::ServiceNotFound) throw;
224  if (fLibraryBuildJob) {
225  throw art::Exception(e.categoryCode(), "", e)
226  << "PhotonVisibilityService: "
227  "service `TFileService` is required when building a photon library.\n";
228  }
229  }
230 
231  PhotonLibrary* lib = new PhotonLibrary(pDir);
232  fTheLibrary = lib;
233 
234  lib->CreateEmptyLibrary(NVoxels, NOpDets, fStoreReflected, fStoreReflT0, fParPropTime_npar);
235  lib->SetVoxelDef(GetVoxelDef());
236  }
237  }
238  }
239 
240  //--------------------------------------------------------------------
242  {
243  if (fTheLibrary == 0) LoadLibrary();
244 
245  if (fLibraryBuildJob) {
246 
247  if (fHybrid) {
248  std::cout << "This is would be building a Hybrid Library. Not defined. " << std::endl;
249  }
250  mf::LogInfo("PhotonVisibilityService") << " Vis service "
251  << " Storing Library entries to file..." << std::endl;
252  PhotonLibrary* lib = dynamic_cast<PhotonLibrary*>(fTheLibrary);
254  }
255  }
256 
257  //--------------------------------------------------------------------
259  {
260 
262 
263  // Library details
264  fLibraryBuildJob = p.get<bool>("LibraryBuildJob", false);
265  fParameterization = p.get<bool>("DUNE10ktParameterization", false);
266  fHybrid = p.get<bool>("HybridLibrary", false);
267  fLibraryFile = p.get<std::string>("LibraryFile", "");
268  fDoNotLoadLibrary = p.get<bool>("DoNotLoadLibrary");
269  fStoreReflected = p.get<bool>("StoreReflected", false);
270  fStoreReflT0 = p.get<bool>("StoreReflT0", false);
271  // Parametrizations (time and Nhits)
272  fIncludePropTime = p.get<bool>("IncludePropTime", false);
273  fUseNhitsModel = p.get<bool>("UseNhitsModel", false);
274  fApplyVISBorderCorrection = p.get<bool>("ApplyVISBorderCorrection", false);
275  fVISBorderCorrectionType = p.get<std::string>("VIS_BORDER_correction_type", "");
276 
277  // Voxel parameters
278  fUseCryoBoundary = p.get<bool>("UseCryoBoundary", false);
279  fInterpolate = p.get<bool>("Interpolate", false);
280  fReflectOverZeroX = p.get<bool>("ReflectOverZeroX", false);
281  fUseAutomaticVoxels = p.get<bool>("UseAutomaticVoxels", false);
282  fSaveTPCVoxels = p.get<std::string>("TPCVoxelListFile", "");
283  fSaveOtherVoxels = p.get<std::string>("OtherVoxelListFile", "");
284 
285  fParPropTime = p.get<bool>("ParametrisedTimePropagation", false);
286  fParPropTime_npar = p.get<size_t>("ParametrisedTimePropagationNParameters", 0);
287  fParPropTime_formula = p.get<std::string>("ParametrisedTimePropagationFittedFormula", "");
288  fParPropTime_MaxRange = p.get<int>("ParametrisedTimePropagationMaxRange", 200);
289 
290  if (!fParPropTime) { fParPropTime_npar = 0; }
291 
292  if (!fUseNhitsModel) {
293 
294  if (fUseCryoBoundary) {
295  auto const CryoBounds = geom->Cryostat().Boundaries();
296  fXmin = CryoBounds.MinX();
297  fXmax = CryoBounds.MaxX();
298  fYmin = CryoBounds.MinY();
299  fYmax = CryoBounds.MaxY();
300  fZmin = CryoBounds.MinZ();
301  fZmax = CryoBounds.MaxZ();
302  }
303  else {
304  fXmin = p.get<double>("XMin");
305  fXmax = p.get<double>("XMax");
306  fYmin = p.get<double>("YMin");
307  fYmax = p.get<double>("YMax");
308  fZmin = p.get<double>("ZMin");
309  fZmax = p.get<double>("ZMax");
310  }
311 
312  fNx = p.get<int>("NX");
313  fNy = p.get<int>("NY");
314  fNz = p.get<int>("NZ");
315 
316  // Find the TPC volume, following example from
317  // https://github.com/LArSoft/larsim/blob/05378155a2a07551fa5757d0449ffb30476d5cf9/larsim/LegacyLArG4/OpFastScintillation.cxx#L2149-L2165
318  geo::BoxBoundedGeo cryoVolume{geom->Cryostat().BoundingBox()};
319  geo::BoxBoundedGeo tpcVolume{geom->Cryostat().TPC(0).ActiveBoundingBox()};
320  for (geo::CryostatGeo const& cryo : geom->Iterate<geo::CryostatGeo>()) {
321 
322  cryoVolume.ExtendToInclude(cryo.BoundingBox());
323  for (geo::TPCGeo const& TPC : cryo.IterateTPCs()) {
324  tpcVolume.ExtendToInclude(TPC.ActiveBoundingBox());
325  }
326  }
327 
328  // Try to make ~10cm voxels: fit TPC exactly, then fit cryostat approximately
329  if (fUseAutomaticVoxels) {
330 
331  std::string logString = "Automatic voxelisation x-dimension\n";
332  float voxelSizeGoal = 10.0; // 10cm standard choice
333  findVoxelSuggestion(tpcVolume.MinX(),
334  tpcVolume.MaxX(),
335  cryoVolume.MinX(),
336  cryoVolume.MaxX(),
337  fNx,
338  fXmin,
339  fXmax,
340  voxelSizeGoal,
341  &logString);
342  logString += "Automatic voxelisation y-dimension\n";
343  findVoxelSuggestion(tpcVolume.MinY(),
344  tpcVolume.MaxY(),
345  cryoVolume.MinY(),
346  cryoVolume.MaxY(),
347  fNy,
348  fYmin,
349  fYmax,
350  voxelSizeGoal,
351  &logString);
352  logString += "Automatic voxelisation z-dimension\n";
353  findVoxelSuggestion(tpcVolume.MinZ(),
354  tpcVolume.MaxZ(),
355  cryoVolume.MinZ(),
356  cryoVolume.MaxZ(),
357  fNz,
358  fZmin,
359  fZmax,
360  voxelSizeGoal,
361  &logString);
362  mf::LogInfo("PhotonVisibilityService") << logString;
363  }
364 
366 
367  // Output lists of voxels within the TPC and outside it
368  if (fSaveTPCVoxels != "" || fSaveOtherVoxels != "") {
369 
370  unsigned int const totalVoxels = fVoxelDef.GetNVoxels();
371  std::vector<unsigned int> tpcVoxels, otherVoxels;
372  tpcVoxels.reserve(totalVoxels);
373  otherVoxels.reserve(totalVoxels);
374  for (unsigned int voxelID = 0; voxelID < totalVoxels; ++voxelID) {
375 
376  auto const voxelCenter = fVoxelDef.GetPhotonVoxel(voxelID).GetCenter();
377  if (tpcVolume.ContainsPosition(voxelCenter)) { tpcVoxels.push_back(voxelID); }
378  else {
379  otherVoxels.push_back(voxelID);
380  }
381  }
382  std::string logString = "Voxels within TPC: " + std::to_string(tpcVoxels.size());
383  if (fSaveTPCVoxels != "") logString += " saved to file\n\t" + fSaveTPCVoxels;
384  logString += "\nVoxels outside TPC: " + std::to_string(otherVoxels.size());
385  if (fSaveOtherVoxels != "") logString += " saved to file\n\t" + fSaveOtherVoxels;
386  mf::LogInfo("PhotonVisibilityService") << logString << std::endl;
387 
388  if (fSaveTPCVoxels != "") {
389  std::ofstream outputFile = std::ofstream(fSaveTPCVoxels);
390  for (auto voxel : tpcVoxels)
391  outputFile << voxel << "\n";
392  }
393  if (fSaveOtherVoxels != "") {
394  std::ofstream outputFile = std::ofstream(fSaveOtherVoxels);
395  for (auto voxel : otherVoxels)
396  outputFile << voxel << "\n";
397  }
398  }
399  }
400 
401  if (fIncludePropTime) {
402 
403  // load VUV arrival time distribution parametrization (no detector dependent at first order)
404  std::cout << "Loading the VUV time parametrization" << std::endl;
405  fDistances_landau = p.get<std::vector<double>>("Distances_landau");
406  fNorm_over_entries = p.get<std::vector<std::vector<double>>>("Norm_over_entries");
407  fMpv = p.get<std::vector<std::vector<double>>>("Mpv");
408  fWidth = p.get<std::vector<std::vector<double>>>("Width");
409  fDistances_exp = p.get<std::vector<double>>("Distances_exp");
410  fSlope = p.get<std::vector<std::vector<double>>>("Slope");
411  fExpo_over_Landau_norm = p.get<std::vector<std::vector<double>>>("Expo_over_Landau_norm");
412  fstep_size = p.get<double>("step_size");
413  fmax_d = p.get<double>("max_d");
414  fmin_d = p.get<double>("min_d");
415  fvuv_vgroup_mean = p.get<double>("vuv_vgroup_mean");
416  fvuv_vgroup_max = p.get<double>("vuv_vgroup_max");
417  finflexion_point_distance = p.get<double>("inflexion_point_distance");
418  fangle_bin_timing_vuv = p.get<double>("angle_bin_timing_vuv");
419 
420  if (fStoreReflected) {
421 
422  // load VIS arrival time distribution paramterisation
423  std::cout << "Loading the VIS time paramterisation" << std::endl;
424  fDistances_refl = p.get<std::vector<double>>("Distances_refl");
425  fDistances_radial_refl = p.get<std::vector<double>>("Distances_radial_refl");
426  fCut_off = p.get<std::vector<std::vector<std::vector<double>>>>("Cut_off");
427  fTau = p.get<std::vector<std::vector<std::vector<double>>>>("Tau");
428  fvis_vmean = p.get<double>("vis_vmean");
429  fangle_bin_timing_vis = p.get<double>("angle_bin_timing_vis");
430  }
431  }
432 
433  if (fUseNhitsModel) {
434  std::cout << "Loading semi-analytic mode models" << std::endl;
435  // VUV
436  fIsFlatPDCorr = p.get<bool>("FlatPDCorr", false);
437  fIsDomePDCorr = p.get<bool>("DomePDCorr", false);
438  fdelta_angulo_vuv = p.get<double>("delta_angulo_vuv");
439  if (fIsFlatPDCorr) {
440  fGHvuvpars_flat = p.get<std::vector<std::vector<double>>>("GH_PARS_flat");
441  fborder_corr_angulo_flat = p.get<std::vector<double>>("GH_border_angulo_flat");
442  fborder_corr_flat = p.get<std::vector<std::vector<double>>>("GH_border_flat");
443  }
444  if (fIsDomePDCorr) {
445  fGHvuvpars_dome = p.get<std::vector<std::vector<double>>>("GH_PARS_dome");
446  fborder_corr_angulo_dome = p.get<std::vector<double>>("GH_border_angulo_dome");
447  fborder_corr_dome = p.get<std::vector<std::vector<double>>>("GH_border_dome");
448  }
449 
450  if (fStoreReflected) {
451  fdelta_angulo_vis = p.get<double>("delta_angulo_vis");
452  if (fIsFlatPDCorr) {
453  fvis_distances_x_flat = p.get<std::vector<double>>("VIS_distances_x_flat");
454  fvis_distances_r_flat = p.get<std::vector<double>>("VIS_distances_r_flat");
455  fvispars_flat =
456  p.get<std::vector<std::vector<std::vector<double>>>>("VIS_correction_flat");
457  }
458  if (fIsDomePDCorr) {
459  fvis_distances_x_dome = p.get<std::vector<double>>("VIS_distances_x_dome");
460  fvis_distances_r_dome = p.get<std::vector<double>>("VIS_distances_r_dome");
461  fvispars_dome =
462  p.get<std::vector<std::vector<std::vector<double>>>>("VIS_correction_dome");
463  }
464  }
465  // optical detector information
466  fradius = p.get<double>("PMT_radius", 10.16);
467  }
468 
469  return;
470  }
471 
472  //------------------------------------------------------
473 
474  // Eventually we will calculate the light quenching factor here
475  double PhotonVisibilityService::GetQuenchingFactor(double /* dQdx */) const
476  {
477  // for now, no quenching
478  return 1.0;
479  }
480 
481  //------------------------------------------------------
482 
483  // Get a vector of the relative visibilities of each OpDet
484  // in the event to a point p
485 
487  bool wantReflected) const -> MappedCounts_t
488  {
490 
491  // first we fill a container of visibilities in the library index space
492  // (it is directly the values of the library unless interpolation is
493  // requested)
494  if (fInterpolate) {
495  // this is a punch into multithreading face:
496  static std::vector<float> ret;
497  ret.resize(fMapping->libraryMappingSize(p));
498  for (std::size_t libIndex = 0; libIndex < ret.size(); ++libIndex) {
499  ret[libIndex] = doGetVisibilityOfOpLib(p, LibraryIndex_t(libIndex), wantReflected);
500  }
501  data = &ret.front();
502  }
503  else {
504  auto const VoxID = VoxelAt(p);
505  data = GetLibraryEntries(VoxID, wantReflected);
506  }
507  return fMapping->applyOpDetMapping(p, data);
508  }
509 
510  //------------------------------------------------------
511 
512  // Get distance to optical detector OpDet
513  double PhotonVisibilityService::DistanceToOpDetImpl(geo::Point_t const& p, unsigned int OpDet)
514  {
516  return geom->OpDetGeoFromOpDet(OpDet).DistanceToPoint(p);
517  }
518 
519  //------------------------------------------------------
520 
521  // Get the solid angle reduction factor for planar optical detector OpDet
522  double PhotonVisibilityService::SolidAngleFactorImpl(geo::Point_t const& p, unsigned int OpDet)
523  {
525  return geom->OpDetGeoFromOpDet(OpDet).CosThetaFromNormal(p);
526  }
527 
528  //------------------------------------------------------
529 
531  LibraryIndex_t libIndex,
532  bool wantReflected /* = false */) const
533  {
534  if (!fInterpolate) { return GetLibraryEntry(VoxelAt(p), libIndex, wantReflected); }
535 
536  // In case we're outside the bounding box we'll get a empty optional list.
537  auto const neis = GetVoxelDef().GetNeighboringVoxelIDs(LibLocation(p));
538  if (!neis) return 0.0;
539 
540  // Sum up all the weighted neighbours to get interpolation behaviour
541  float vis = 0.0;
542  for (const sim::PhotonVoxelDef::NeiInfo& n : neis.value()) {
543  if (n.id < 0) continue;
544  vis += n.weight * GetLibraryEntry(n.id, libIndex, wantReflected);
545  }
546  return vis;
547  }
548 
549  //------------------------------------------------------
550 
552  bool wantReflected /* = false */) const
553  {
554  return HasLibraryEntries(VoxelAt(p), wantReflected);
555  }
556 
557  //------------------------------------------------------
558 
560  unsigned int OpChannel,
561  bool wantReflected) const
562  {
563  // here we quietly confuse op. det. channel (interface) and op. det. (library)
564  LibraryIndex_t const libIndex = fMapping->opDetToLibraryIndex(p, OpChannel);
565  return doGetVisibilityOfOpLib(p, libIndex, wantReflected);
566  }
567 
568  //------------------------------------------------------
569 
570  void PhotonVisibilityService::StoreLightProd(int VoxID, double N)
571  {
572  fCurrentVoxel = VoxID;
573  fCurrentValue = N;
574  mf::LogInfo("PhotonVisibilityService")
575  << " PVS notes production of " << N << " photons at Vox " << VoxID << std::endl;
576  }
577 
578  //------------------------------------------------------
579 
580  void PhotonVisibilityService::RetrieveLightProd(int& VoxID, double& N) const
581  {
582  N = fCurrentValue;
583  VoxID = fCurrentVoxel;
584  }
585 
586  //------------------------------------------------------
587 
589  int OpChannel,
590  float N,
591  bool wantReflected)
592  {
593  if (fTheLibrary == 0) LoadLibrary();
594 
595  PhotonLibrary* lib = dynamic_cast<PhotonLibrary*>(fTheLibrary);
596 
597  if (!wantReflected)
598  lib->SetCount(VoxID, OpChannel, N);
599 
600  else
601  lib->SetReflCount(VoxID, OpChannel, N);
602 
603  //std::cout<< " PVS logging " << VoxID << " " << OpChannel<<std::endl;
604  MF_LOG_DEBUG("PhotonVisibilityService")
605  << " PVS logging " << VoxID << " " << OpChannel << std::endl;
606  }
607 
608  //------------------------------------------------------
609 
611  int VoxID,
612  bool wantReflected) const
613  {
614  if (fTheLibrary == 0) LoadLibrary();
615 
616  if (!wantReflected)
617  return fTheLibrary->GetCounts(VoxID);
618  else
619  return fTheLibrary->GetReflCounts(VoxID);
620  }
621 
622  //------------------------------------------------------
623 
625  bool /* wantReflected */ /* = false */) const
626  {
627  if (!fTheLibrary) LoadLibrary();
628  return fTheLibrary->isVoxelValid(VoxID);
629  }
630 
631  //------------------------------------------------------
632 
634  OpDetID_t libOpChannel,
635  bool wantReflected) const
636  {
637  if (fTheLibrary == 0) LoadLibrary();
638 
639  if (!wantReflected)
640  return fTheLibrary->GetCount(VoxID, libOpChannel);
641  else
642  return fTheLibrary->GetReflCount(VoxID, libOpChannel);
643  }
644  // Methodes to handle the extra library parameter refl T0
645  //------------------------------------------------------
646 
647  // Get a vector of the refl <tfirst> of each OpDet
648  // in the event to a point p
649 
651  {
652  // both the input and the output go through mapping to apply needed symmetries.
653  int const VoxID = VoxelAt(p);
655  return fMapping->applyOpDetMapping(p, data);
656  }
657 
658  //------------------------------------------------------
659 
661  {
662  if (fTheLibrary == 0) LoadLibrary();
663 
664  return fTheLibrary->GetReflT0s(VoxID);
665  }
666 
667  //------------------------------------------------------
668 
669  void PhotonVisibilityService::SetLibraryReflT0Entry(int VoxID, int OpChannel, float T0)
670  {
671  PhotonLibrary* lib = dynamic_cast<PhotonLibrary*>(fTheLibrary);
672  if (fTheLibrary == 0) LoadLibrary();
673 
674  lib->SetReflT0(VoxID, OpChannel, T0);
675 
676  MF_LOG_DEBUG("PhotonVisibilityService")
677  << " PVS logging " << VoxID << " " << OpChannel << std::endl;
678  }
679 
680  //------------------------------------------------------
681 
682  float PhotonVisibilityService::GetLibraryReflT0Entry(int VoxID, OpDetID_t libOpChannel) const
683  {
684  if (fTheLibrary == 0) LoadLibrary();
685 
686  return fTheLibrary->GetReflT0(VoxID, libOpChannel);
687  }
688 
689  //------------------------------------------------------
690 
692 
694  {
695  int const VoxID = VoxelAt(p);
697  return fMapping->applyOpDetMapping(p, params);
698  }
699 
701  {
702  int const VoxID = VoxelAt(p);
704  return fMapping->applyOpDetMapping(p, functions);
705  }
706 
707  //------------------------------------------------------
708 
710  int VoxID) const
711  {
712  PhotonLibrary* lib = dynamic_cast<PhotonLibrary*>(fTheLibrary);
713  if (fTheLibrary == 0) LoadLibrary();
714 
715  return lib->GetTimingPars(VoxID);
716  }
717 
718  //------------------------------------------------------
719 
721  int VoxID) const
722  {
723  PhotonLibrary* lib = dynamic_cast<PhotonLibrary*>(fTheLibrary);
724  if (fTheLibrary == 0) LoadLibrary();
725 
726  return lib->GetTimingTF1s(VoxID);
727  }
728 
729  //------------------------------------------------------
730 
732  int OpChannel,
733  float par,
734  size_t parnum)
735  {
736  PhotonLibrary* lib = dynamic_cast<PhotonLibrary*>(fTheLibrary);
737  if (fTheLibrary == 0) LoadLibrary();
738 
739  lib->SetTimingPar(VoxID, OpChannel, par, parnum);
740 
741  MF_LOG_DEBUG("PhotonVisibilityService")
742  << " PVS logging " << VoxID << " " << OpChannel << std::endl;
743  }
744 
745  //------------------------------------------------------
746 
747  void PhotonVisibilityService::SetLibraryTimingTF1Entry(int VoxID, int OpChannel, TF1 const& func)
748  {
749  PhotonLibrary* lib = dynamic_cast<PhotonLibrary*>(fTheLibrary);
750  if (fTheLibrary == 0) LoadLibrary();
751 
752  lib->SetTimingTF1(VoxID, OpChannel, func);
753 
754  MF_LOG_DEBUG("PhotonVisibilityService")
755  << " PVS logging " << VoxID << " " << OpChannel << std::endl;
756  }
757 
758  //------------------------------------------------------
759 
761  OpDetID_t libOpChannel,
762  size_t npar) const
763  {
764  PhotonLibrary* lib = dynamic_cast<PhotonLibrary*>(fTheLibrary);
765  if (fTheLibrary == 0) LoadLibrary();
766 
767  return lib->GetTimingPar(VoxID, libOpChannel, npar);
768  }
769 
770  //------------------------------------------------------
771 
773  {
774  // the last word about the number of channels belongs to the mapping;
775  // this should be also the same answer as `geo::GeometryCore::NOpDets()`.
776  return fMapping->opDetMappingSize();
777  }
778 
779  //------------------------------------------------------
781  double& d_break,
782  double& d_max,
783  double& tf1_sampling_factor) const
784  {
785  functions[0] = fparslogNorm;
786  functions[1] = fparsMPV;
787  functions[2] = fparsWidth;
788  functions[3] = fparsCte;
789  functions[4] = fparsSlope;
790  functions[5] = fparslogNorm_far;
791  functions[6] = fparsMPV_far;
792  functions[7] = fparsCte_far;
793 
794  d_break = fD_break;
795  d_max = fD_max;
796  tf1_sampling_factor = fTF1_sampling_factor;
797  }
798 
799  //------------------------------------------------------
801  double& t0_max,
802  double& t0_break_point) const
803  {
804  functions[0] = fparslogNorm_refl;
805  functions[1] = fparsMPV_refl;
806  functions[2] = fparsWidth_refl;
807  functions[3] = fparsCte_refl;
808  functions[4] = fparsSlope_refl;
809 
810  t0_max = fT0_max;
811  t0_break_point = fT0_break_point;
812  }
813 
814  //------------------------------------------------------
816  double& step_size,
817  double& max_d,
818  double& min_d,
819  double& vuv_vgroup_mean,
820  double& vuv_vgroup_max,
821  double& inflexion_point_distance,
822  double& angle_bin_timing_vuv) const
823  {
824  v[0] = std::vector(1, fDistances_landau);
825  v[1] = fNorm_over_entries;
826  v[2] = fMpv;
827  v[3] = fWidth;
828  v[4] = std::vector(1, fDistances_exp);
829  v[5] = fSlope;
830  v[6] = fExpo_over_Landau_norm;
831 
832  step_size = fstep_size;
833  max_d = fmax_d;
834  min_d = fmin_d;
835  vuv_vgroup_mean = fvuv_vgroup_mean;
836  vuv_vgroup_max = fvuv_vgroup_max;
837  inflexion_point_distance = finflexion_point_distance;
838  angle_bin_timing_vuv = fangle_bin_timing_vuv;
839  }
840 
842  std::vector<double>& distances,
843  std::vector<double>& radial_distances,
844  std::vector<std::vector<std::vector<double>>>& cut_off,
845  std::vector<std::vector<std::vector<double>>>& tau,
846  double& vis_vmean,
847  double& angle_bin_timing_vis) const
848  {
849  distances = fDistances_refl;
850  radial_distances = fDistances_radial_refl;
851  cut_off = fCut_off;
852  tau = fTau;
853 
854  vis_vmean = fvis_vmean;
855  angle_bin_timing_vis = fangle_bin_timing_vis;
856  }
857 
859  bool& isDomePDCorr,
860  double& delta_angulo_vuv,
861  double& radius) const
862  {
863  isFlatPDCorr = fIsFlatPDCorr;
864  isDomePDCorr = fIsDomePDCorr;
865  delta_angulo_vuv = fdelta_angulo_vuv;
866  radius = fradius;
867  }
868  void PhotonVisibilityService::LoadGHFlat(std::vector<std::vector<double>>& GHvuvpars_flat,
869  std::vector<double>& border_corr_angulo_flat,
870  std::vector<std::vector<double>>& border_corr_flat) const
871  {
872  if (!fIsFlatPDCorr) return;
873  GHvuvpars_flat = fGHvuvpars_flat;
874  border_corr_angulo_flat = fborder_corr_angulo_flat;
875  border_corr_flat = fborder_corr_flat;
876  }
877  void PhotonVisibilityService::LoadGHDome(std::vector<std::vector<double>>& GHvuvpars_dome,
878  std::vector<double>& border_corr_angulo_dome,
879  std::vector<std::vector<double>>& border_corr_dome) const
880  {
881  if (!fIsDomePDCorr) return;
882  GHvuvpars_dome = fGHvuvpars_dome;
883  border_corr_angulo_dome = fborder_corr_angulo_dome;
884  border_corr_dome = fborder_corr_dome;
885  }
887  double& radius) const
888  {
889  delta_angulo_vis = fdelta_angulo_vis;
890  radius = fradius;
891  }
893  std::vector<double>& vis_distances_x_flat,
894  std::vector<double>& vis_distances_r_flat,
895  std::vector<std::vector<std::vector<double>>>& vispars_flat) const
896  {
897  if (!fIsFlatPDCorr) return;
898  vis_distances_x_flat = fvis_distances_x_flat;
899  vis_distances_r_flat = fvis_distances_r_flat;
900  vispars_flat = fvispars_flat;
901  }
903  std::vector<double>& vis_distances_x_dome,
904  std::vector<double>& vis_distances_r_dome,
905  std::vector<std::vector<std::vector<double>>>& vispars_dome) const
906  {
907  if (!fIsDomePDCorr) return;
908  vis_distances_x_dome = fvis_distances_x_dome;
909  vis_distances_r_dome = fvis_distances_r_dome;
910  vispars_dome = fvispars_dome;
911  }
912 
913  //------------------------------------------------------
914  /***
915  * Preform any necessary transformations on the coordinates before trying to access
916  * a voxel ID.
917  **/
919  {
920  return fMapping->detectorToLibrary(p);
921  }
922 
924  float tpcMax,
925  float cryoMin,
926  float cryoMax,
927  int& nVoxels,
928  float& voxelMin,
929  float& voxelMax,
930  float voxelSizeGoal,
931  std::string* logString) const
932  {
933  // Scan the "jog" parameter, which adds an integer amount of voxels within the TPC
934  int bestJog = 0;
935  float bestResult = 1000;
936  for (int jog = -10; jog <= 10; ++jog) {
937  float result = testVoxelSuggestion(
938  tpcMin, tpcMax, cryoMin, cryoMax, nVoxels, voxelMin, voxelMax, voxelSizeGoal, jog);
939  if (result < bestResult) {
940  bestResult = result;
941  bestJog = jog;
942  }
943  }
944 
945  // Print the best result (and update the outputs)
946  testVoxelSuggestion(tpcMin,
947  tpcMax,
948  cryoMin,
949  cryoMax,
950  nVoxels,
951  voxelMin,
952  voxelMax,
953  voxelSizeGoal,
954  bestJog,
955  logString);
956  }
957 
959  float tpcMax,
960  float cryoMin,
961  float cryoMax,
962  int& nVoxels,
963  float& voxelMin,
964  float& voxelMax,
965  float voxelSizeGoal,
966  int jog,
967  std::string* logString) const
968  {
969  // Examine TPC to establish voxel size
970  float tpcSize = tpcMax - tpcMin;
971  int tpcVoxelNumber = ceil(tpcSize / voxelSizeGoal) + jog; // units are cm
972  float voxelSize = tpcSize / tpcVoxelNumber;
973  float cryoSize = cryoMax - cryoMin;
974 
975  // Extend voxel grid to full cryostat
976  voxelMin = tpcMin;
977  while (voxelMin > cryoMin)
978  voxelMin -= voxelSize;
979  voxelMax = tpcMax;
980  while (voxelMax < cryoMax)
981  voxelMax += voxelSize;
982  float cryoVoxelNumberGuess = cryoSize / voxelSize;
983  nVoxels = round((voxelMax - voxelMin) / voxelSize);
984 
985  if (logString) {
986  *logString += "\tTPC size " + std::to_string(tpcSize) + "cm requires " +
987  std::to_string(tpcVoxelNumber) + " voxels of size " +
988  std::to_string(voxelSize) + "cm\n";
989  *logString += "\tCryostat boundaries " + std::to_string(cryoMin) + " to " +
990  std::to_string(cryoMax) + "cm would use " +
991  std::to_string(cryoVoxelNumberGuess) + " voxels\n";
992  *logString += "\tCryostat voxel range " + std::to_string(voxelMin) + " to " +
993  std::to_string(voxelMax) + "cm uses " + std::to_string(nVoxels) + " voxels\n";
994  }
995 
996  // Return figure of merit for optimisation
997  float voxelDelta = fabs(nVoxels - cryoVoxelNumberGuess);
998  return voxelDelta;
999  }
1000 
1002 } // namespace
Definitions of voxel data structures.
std::vector< std::vector< std::vector< double > > > fTau
MappedParams_t doGetTimingPar(geo::Point_t const &p) const
void LoadTimingsForVISPar(std::vector< double > &distances, std::vector< double > &radial_distances, std::vector< std::vector< std::vector< double >>> &cut_off, std::vector< std::vector< std::vector< double >>> &tau, double &vis_vmean, double &angle_bin_timing_vis) const
details::range_type< T > Iterate() const
Initializes the specified ID with the ID of the first cryostat.
Definition: GeometryCore.h:541
phot::IPhotonLibrary::Counts_t GetLibraryReflT0Entries(int VoxID) const
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
virtual float GetReflT0(size_t Voxel, size_t OpChannel) const =0
double CosThetaFromNormal(geo::Point_t const &point) const
Get cos(angle) to normal of this detector - used for solid angle calcs.
Definition: OpDetGeo.cxx:113
MappedCounts_t doGetAllVisibilities(geo::Point_t const &p, bool wantReflected=false) const
phot::IPhotonLibrary::Counts_t GetLibraryEntries(int VoxID, bool wantReflected=false) const
std::unique_ptr< phot::IPhotonMappingTransformations > fMapping
Mapping of detector space into library space.
void RetrieveLightProd(int &VoxID, double &N) const
void SetDirectLightPropFunctions(TF1 const *functions[8], double &d_break, double &d_max, double &tf1_sampling_factor) const
void LoadLibraryFromFile(std::string LibraryFile, size_t NVoxels, bool storeReflected=false, bool storeReflT0=false, size_t storeTiming=0, int maxrange=200)
std::vector< std::vector< double > > fborder_corr_flat
std::vector< double > fvis_distances_r_flat
void LoadTimingsForVUVPar(std::vector< std::vector< double >>(&v)[7], double &step_size, double &max_d, double &min_d, double &vuv_vgroup_mean, double &vuv_vgroup_max, double &inflexion_point_distance, double &angle_bin_timing_vuv) const
std::vector< double > fvis_distances_x_dome
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
void SetLibraryTimingParEntry(int VoxID, int OpChannel, float value, size_t parnum)
sim::PhotonVoxelDef const & GetVoxelDef() const
Definition: PhotonLibrary.h:89
bool hasVoxelDef() const
Returns whether voxel metadata is available.
Definition: PhotonLibrary.h:85
std::vector< std::vector< double > > fWidth
std::vector< double > fvis_distances_r_dome
virtual float GetReflCount(size_t Voxel, size_t OpChannel) const =0
phot::IPhotonMappingTransformations::LibraryIndex_t LibraryIndex_t
Type of optical library index.
Representation of a region of space diced into voxels.
Definition: PhotonVoxels.h:58
Geometry information for a single TPC.
Definition: TPCGeo.h:36
float GetLibraryTimingParEntry(int VoxID, OpDetID_t libOpChannel, size_t npar) const
geo::BoxBoundedGeo const & ActiveBoundingBox() const
Returns the box of the active volume of this TPC.
Definition: TPCGeo.h:263
bool HasLibraryEntries(int VoxID, bool wantReflected=false) const
void LoadVisParsFlat(std::vector< double > &vis_distances_x_flat, std::vector< double > &vis_distances_r_flat, std::vector< std::vector< std::vector< double >>> &vispars_flat) const
float doGetVisibilityOfOpLib(geo::Point_t const &p, LibraryIndex_t libIndex, bool wantReflected=false) const
bool doHasVisibility(geo::Point_t const &p, bool wantReflected=false) const
std::vector< double > fvis_distances_x_flat
void StoreLibraryToFile(std::string LibraryFile, bool storeReflected=false, bool storeReflT0=false, size_t storeTiming=0) const
std::vector< std::vector< std::vector< double > > > fCut_off
Geometry information for a single cryostat.
Definition: CryostatGeo.h:43
float GetLibraryEntry(int VoxID, OpDetID_t libOpChannel, bool wantReflected=false) const
void LoadGHDome(std::vector< std::vector< double >> &GHvuvpars_dome, std::vector< double > &border_corr_angulo_dome, std::vector< std::vector< double >> &border_corr_dome) const
geo::BoxBoundedGeo const & BoundingBox() const
Returns the bounding box of this cryostat.
Definition: CryostatGeo.h:124
CryostatGeo const & Cryostat(CryostatID const &cryoid=cryostat_zero) const
Returns the specified cryostat.
int VoxelAt(geo::Point_t const &p) const
void SetCount(size_t Voxel, size_t OpChannel, float Count)
void findVoxelSuggestion(float tpcMin, float tpcMax, float cryoMin, float cryoMax, int &nVoxels, float &voxelMin, float &voxelMax, float voxelSizeGoal, std::string *logString=nullptr) const
void SetTimingTF1(size_t Voxel, size_t OpChannel, TF1 func)
void LoadVUVSemiAnalyticProperties(bool &isFlatPDCorr, bool &isDomePDCorr, double &delta_angulo_vuv, double &radius) const
double GetQuenchingFactor(double dQdx) const
float GetLibraryReflT0Entry(int VoxID, OpDetID_t libOpChannel) const
void SetReflectedCOLightPropFunctions(TF1 const *functions[5], double &t0_max, double &t0_break_point) const
void StoreLightProd(int VoxID, double N)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
void SetVoxelDef(sim::PhotonVoxelDef const &voxelDef)
Definition: PhotonLibrary.h:97
PhotonVisibilityService(fhicl::ParameterSet const &pset)
void LoadGHFlat(std::vector< std::vector< double >> &GHvuvpars_flat, std::vector< double > &border_corr_angulo_flat, std::vector< std::vector< double >> &border_corr_flat) const
MappedFunctions_t doGetTimingTF1(geo::Point_t const &p) const
geo::Point_t LibLocation(geo::Point_t const &p) const
void SetReflT0(size_t Voxel, size_t OpChannel, float reflT0)
void LoadVisParsDome(std::vector< double > &vis_distances_x_dome, std::vector< double > &vis_distances_r_dome, std::vector< std::vector< std::vector< double >>> &vispars_dome) const
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::vector< double > fDistances_radial_refl
Float_t radius
Definition: plot.C:23
void SetLibraryReflT0Entry(int VoxID, int OpChannel, float value)
virtual Counts_t GetReflCounts(size_t Voxel) const =0
T get(std::string const &key) const
Definition: ParameterSet.h:314
virtual float GetCount(size_t Voxel, size_t OpChannel) const =0
virtual Counts_t GetCounts(size_t Voxel) const =0
Returns a pointer to NOpChannels() visibility values, one per channel.
void reconfigure(fhicl::ParameterSet const &p)
TF1 * GetTimingTF1s(size_t Voxel) const
const std::vector< float > * GetTimingPars(size_t Voxel) const
std::vector< std::vector< double > > fGHvuvpars_flat
phot::IPhotonMappingTransformations::OpDetID_t OpDetID_t
Type of (global) optical detector ID.
std::vector< float > const * Params_t
bool has_key(std::string const &key) const
float testVoxelSuggestion(float tpcMin, float tpcMax, float cryoMin, float cryoMax, int &nVoxels, float &voxelMin, float &voxelMax, float voxelSizeGoal, int jog, std::string *logString=nullptr) const
unsigned int NOpDets() const
Number of OpDets in the whole detector.
virtual bool isVoxelValid(size_t Voxel) const
std::vector< std::vector< double > > fGHvuvpars_dome
Encapsulate the geometry of an optical detector.
void SetTimingPar(size_t Voxel, size_t OpChannel, float Count, size_t parnum)
std::vector< std::vector< double > > fExpo_over_Landau_norm
const sim::PhotonVoxelDef & GetVoxelDef() const
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
double DistanceToPoint(geo::Point_t const &point) const
Returns the distance of the specified point from detector center [cm].
Definition: OpDetGeo.cxx:98
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
void LoadVisSemiAnalyticProperties(double &delta_angulo_vis, double &radius) const
General LArSoft Utilities.
std::vector< std::vector< double > > fMpv
std::optional< std::array< NeiInfo, 8U > > GetNeighboringVoxelIDs(Point const &v) const
Returns IDs of the eight neighboring voxels around v.
virtual T0s_t GetReflT0s(size_t Voxel) const =0
void SetLibraryEntry(int VoxID, OpDetID_t libOpChannel, float N, bool wantReflected=false)
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:33
A container for photon visibility mapping data.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
Definition: CryostatGeo.cxx:84
Point GetCenter() const
Returns the center of the voxel (type Point).
Definition: PhotonVoxels.h:186
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< std::vector< double > > fborder_corr_dome
#define MF_LOG_DEBUG(id)
float GetTimingPar(size_t Voxel, size_t OpChannel, size_t parnum) const
float doGetVisibility(geo::Point_t const &p, unsigned int OpChannel, bool wantReflected=false) const
std::vector< double > fborder_corr_angulo_flat
void ExtendToInclude(Coord_t x, Coord_t y, Coord_t z)
Extends the current box to also include the specified point.
unsigned int GetNVoxels() const
Returns the total number of voxels in the volume.
void SetLibraryTimingTF1Entry(int VoxID, int OpChannel, TF1 const &func)
std::vector< std::vector< std::vector< double > > > fvispars_dome
std::vector< std::vector< double > > fNorm_over_entries
Char_t n[5]
const float * Counts_t
Type for visibility count per optical channel.
geo::BoxBoundedGeo const & Boundaries() const
Returns boundaries of the cryostat (in centimetres).
Definition: CryostatGeo.h:114
static double DistanceToOpDetImpl(geo::Point_t const &p, unsigned int OpDet)
MappedT0s_t doGetReflT0s(geo::Point_t const &p) const
static double SolidAngleFactorImpl(geo::Point_t const &p, unsigned int OpDet)
Float_t e
Definition: plot.C:35
void SetReflCount(size_t Voxel, size_t OpChannel, float Count)
std::vector< std::vector< double > > fSlope
phot::IPhotonLibrary::Functions_t GetLibraryTimingTF1Entries(int VoxID) const
std::vector< double > fborder_corr_angulo_dome
phot::IPhotonLibrary::Params_t GetLibraryTimingParEntries(int VoxID) const
std::vector< std::vector< std::vector< double > > > fvispars_flat
void put(std::string const &key)
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
PhotonVoxel GetPhotonVoxel(int ID) const