1 #include "art_root_io/TFileDirectory.h" 4 #include "cetlib_except/exception.h" 10 #include "RtypesCore.h" 24 template <
typename RooT,
typename T>
27 std::vector<std::string>& missingKeys;
29 std::optional<T> operator()(std::string
const& key)
31 RooT
const*
value = srcDir.Get<RooT>(key.c_str());
32 if (value)
return std::make_optional<T>(*value);
33 missingKeys.push_back(key);
42 std::string
const PhotonLibrary::OpChannelBranchName =
"OpChannel";
45 PhotonLibrary::PhotonLibrary(art::TFileDirectory* pDir ) : fDir(pDir) {}
52 size_t storeTiming)
const 54 mf::LogInfo(
"PhotonLibrary") <<
"Writing photon library to file";
58 <<
"StoreLibraryToFile(): no ROOT file provided, can't store anything.\n";
61 TTree*
tt =
fDir->make<TTree>(
"PhotonLibraryData",
"PhotonLibraryData");
65 Float_t Visibility = 0;
66 Float_t ReflVisibility = 0;
67 Float_t ReflTfirst = 0;
68 Float_t* timing_par =
nullptr;
70 tt->Branch(
"Voxel", &Voxel,
"Voxel/I");
72 tt->Branch(
"Visibility", &Visibility,
"Visibility/F");
74 if (storeTiming != 0) {
78 <<
"StoreLibraryToFile() requested to store the time propagation distribution " 79 "parameters, which was not simulated.";
81 tt->Branch(
"timing_par", timing_par, Form(
"timing_par[%i]/F",
size_t2int(storeTiming)));
84 <<
"Time propagation lookup table is different size than Direct table \n" 85 <<
"this should not be happening. ";
92 <<
"StoreLibraryToFile() requested to store reflected light, which was not simulated.";
94 tt->Branch(
"ReflVisibility", &ReflVisibility,
"ReflVisibility/F");
97 <<
"Reflected light lookup table is different size than Direct table \n" 98 <<
"this should not be happening. ";
103 throw cet::exception(
"PhotonLibrary") <<
"StoreLibraryToFile() requested to store " 104 "reflected light timing, which was not simulated.";
106 tt->Branch(
"ReflTfirst", &ReflTfirst,
"ReflTfirst/F");
108 for (
size_t ivox = 0; ivox !=
fNVoxels; ++ivox) {
109 for (
size_t ichan = 0; ichan !=
fNOpChannels; ++ichan) {
113 if (storeTiming != 0) {
114 for (
size_t i = 0; i < storeTiming; i++)
117 if (Visibility > 0 || ReflVisibility > 0) {
133 bool storeReflected ,
153 if (storeTiming != 0) {
174 mf::LogInfo(
"PhotonLibrary") <<
"Reading photon library from input file: " 175 << LibraryFile.c_str() << std::endl;
179 TDirectory* pSrcDir =
nullptr;
182 f = TFile::Open(LibraryFile.c_str());
183 tt = (TTree*)f->Get(
"PhotonLibraryData");
184 if (tt) { pSrcDir =
f; }
186 TKey* key = f->FindKeyAny(
"PhotonLibraryData");
188 tt = (TTree*)key->ReadObj();
189 pSrcDir = key->GetMotherDir();
192 mf::LogError(
"PhotonLibrary") <<
"PhotonLibraryData not found in file" << LibraryFile;
198 <<
"Error in ttree load, reading photon library: " << LibraryFile <<
"\n";
204 Float_t ReflVisibility;
206 std::vector<Float_t> timing_par;
208 tt->SetBranchAddress(
"Voxel", &Voxel);
209 tt->SetBranchAddress(
"OpChannel", &OpChannel);
210 tt->SetBranchAddress(
"Visibility", &Visibility);
215 if (getReflected) tt->SetBranchAddress(
"ReflVisibility", &ReflVisibility);
217 if (getReflT0) tt->SetBranchAddress(
"ReflTfirst", &ReflTfirst);
231 timing_par.resize(getTiming);
232 tt->SetBranchAddress(
"timing_par", timing_par.data());
235 TNamed*
n = (TNamed*)f->Get(
"fTimingParFormula");
238 <<
"Error reading the photon propagation formula. Please check the photon library." 244 <<
"Time parametrization is activated. Using the formula: " <<
fTimingParFormula <<
" with " 256 size_t NEntries = tt->GetEntries();
258 for (
size_t i = 0; i != NEntries; ++i) {
269 TF1 timingfunction(Form(
"timing_%i_%i", Voxel, OpChannel),
273 timingfunction.SetParameter(
277 timingfunction.SetParameter(k, timing_par[k]);
287 log <<
"Photon lookup table size : " << NVoxels <<
" voxels, " <<
fNOpChannels 292 log <<
" (no voxel geometry included)";
299 mf::LogError(
"PhotonLibrary") <<
"Error in closing file : " << LibraryFile;
345 <<
"Error - attempting to set count in voxel " << Voxel <<
" which is out of range";
354 mf::LogError(
"PhotonLibrary") <<
"Error - attempting to set timing t0 count in voxel " 355 << Voxel <<
" which is out of range";
364 mf::LogError(
"PhotonLibrary") <<
"Error - attempting to set a propagation function in voxel " 365 << Voxel <<
" which is out of range";
375 <<
"Error - attempting to set count in voxel " << Voxel <<
" which is out of range";
385 <<
"Error - attempting to set count in voxel " << Voxel <<
" which is out of range";
414 if (Voxel >=
fNVoxels)
return nullptr;
462 constexpr std::size_t NExpectedKeys = 9U;
464 std::vector<std::string> missingKeys;
466 RooReader<RooInt, Int_t> readInt{srcDir, missingKeys};
467 RooReader<RooDouble, Double_t> readDouble{srcDir, missingKeys};
479 if (
auto metaValue = readDouble(
"MinX")) xMin = *metaValue;
480 if (
auto metaValue = readDouble(
"MaxX")) xMax = *metaValue;
481 if (
auto metaValue = readInt(
"NDivX")) xN = *metaValue;
482 if (
auto metaValue = readDouble(
"MinY")) yMin = *metaValue;
483 if (
auto metaValue = readDouble(
"MaxY")) yMax = *metaValue;
484 if (
auto metaValue = readInt(
"NDivY")) yN = *metaValue;
485 if (
auto metaValue = readDouble(
"MinZ")) zMin = *metaValue;
486 if (
auto metaValue = readDouble(
"MaxZ")) zMax = *metaValue;
487 if (
auto metaValue = readInt(
"NDivZ")) zN = *metaValue;
489 if (!missingKeys.empty()) {
490 if (missingKeys.size() != NExpectedKeys) {
492 log <<
"Photon library at '" << srcDir.GetPath() <<
"' is missing " << missingKeys.size()
493 <<
" metadata elements:";
494 for (
auto const& key : missingKeys)
495 log <<
" '" << key <<
"'";
498 mf::LogTrace(
"PhotonLibrary") <<
"No voxel metadata found in '" << srcDir.GetPath() <<
"'";
503 fVoxelDef.emplace(xMin, xMax, xN, yMin, yMax, yN, zMin, zMax, zN);
514 fDir->makeAndRegister<RooInt>(
"NVoxels",
"Total number of voxels in the library",
fNVoxels);
517 fDir->makeAndRegister<RooInt>(
518 "NChannels",
"Total number of optical detector channels in the library",
fNOpChannels);
525 fDir->makeAndRegister<RooDouble>(
526 "MinX",
"Lower x coordinate covered by the library (world coordinates, cm)", lower.X());
527 fDir->makeAndRegister<RooDouble>(
528 "MinY",
"Lower y coordinate covered by the library (world coordinates, cm)", lower.Y());
529 fDir->makeAndRegister<RooDouble>(
530 "MinZ",
"Lower z coordinate covered by the library (world coordinates, cm)", lower.Z());
534 fDir->makeAndRegister<RooDouble>(
535 "MaxX",
"Upper x coordinate covered by the library (world coordinates, cm)", upper.X());
536 fDir->makeAndRegister<RooDouble>(
537 "MaxY",
"Upper y coordinate covered by the library (world coordinates, cm)", upper.Y());
538 fDir->makeAndRegister<RooDouble>(
539 "MaxZ",
"Upper z coordinate covered by the library (world coordinates, cm)", upper.Z());
543 fDir->makeAndRegister<RooDouble>(
"StepX",
"Size on x direction of a voxel (cm)", stepSizes.X());
544 fDir->makeAndRegister<RooDouble>(
"StepY",
"Size on y direction of a voxel (cm)", stepSizes.Y());
545 fDir->makeAndRegister<RooDouble>(
"StepZ",
"Size on z direction of a voxel (cm)", stepSizes.Z());
548 auto const& steps = voxelDef.
GetSteps();
549 fDir->makeAndRegister<RooInt>(
"NDivX",
"Steps on the x direction", steps[0]);
550 fDir->makeAndRegister<RooInt>(
"NDivY",
"Steps on the y direction", steps[1]);
551 fDir->makeAndRegister<RooInt>(
"NDivZ",
"Steps on the z direction", steps[2]);
560 if (!channelBranch) {
562 <<
"Tree '" << tree->GetName() <<
"' has no branch 'OpChannel'";
566 char* oldAddress = channelBranch->GetAddress();
568 channelBranch->SetAddress(&channel);
569 Int_t maxChannel = -1;
573 while (channelBranch->GetEntry(iEntry++)) {
574 if (channel > maxChannel) maxChannel = channel;
577 MF_LOG_DEBUG(
"PhotonLibrary") <<
"Detected highest channel to be " << maxChannel <<
" from " 578 << iEntry <<
" tree entries";
581 channelBranch->SetAddress(oldAddress);
583 return size_t(maxChannel + 1);
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.
size_t fTimingParNParameters
static int size_t2int(size_t val)
Converts size_t into integer.
std::optional< sim::PhotonVoxelDef > fVoxelDef
Voxel definition loaded from library metadata.
size_t fHasTiming
Whether the current library deals with time propagation distribution.
void LoadLibraryFromFile(std::string LibraryFile, size_t NVoxels, bool storeReflected=false, bool storeReflT0=false, size_t storeTiming=0, int maxrange=200)
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
util::LazyVector< float > fReflLookupTable
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.
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
sim::PhotonVoxelDef const & GetVoxelDef() const
Vector GetVoxelSize() const
Returns a vector describing the span of a single voxel in x, y an z [cm].
bool hasVoxelDef() const
Returns whether voxel metadata is available.
virtual int NOpChannels() const override
Representation of a region of space diced into voxels.
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.
void clear()
Removes all stored data and sets the nominal size to 0.
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.
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
size_t uncheckedIndex(size_t Voxel, size_t OpChannel) const
Returns the index of visibility of specified voxel and cell.
util::LazyVector< float > fLookupTable
virtual bool hasReflectedT0() const override
Returns whether the current library deals with reflected light timing.
static size_t ExtractNOpChannels(TTree *tree)
Returns the number of optical channels in the specified tree.
size_type size() const noexcept
Returns the size of the vector.
void SetReflT0(size_t Voxel, size_t OpChannel, float reflT0)
bool fHasReflected
Whether the current library deals with reflected light counts.
TF1 & uncheckedAccessTimingTF1(size_t Voxel, size_t OpChannel)
Unchecked access to a parameter of the time distribution.
decltype(auto) GetRegionUpperCorner() const
Returns the volume vertex (type Point) with the highest coordinates.
void StoreMetadata() const
Writes the current metadata (if any) into the ROOT output file.
TF1 * GetTimingTF1s(size_t Voxel) const
const std::vector< float > * GetTimingPars(size_t Voxel) const
util::LazyVector< TF1 > fTimingParTF1LookupTable
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
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
General LArSoft Utilities.
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.
float GetTimingPar(size_t Voxel, size_t OpChannel, size_t parnum) const
std::array< unsigned int, 3U > GetSteps() const
Returns the number of voxels along each of the three dimensions.
MaybeLogger_< ELseverityLevel::ELsev_success, true > LogTrace
void resize(size_type newSize)
Changes the nominal size of the container.
util::LazyVector< std::vector< float > > fTimingParLookupTable
util::LazyVector< float > fReflTLookupTable
art::TFileDirectory * fDir
ROOT directory where to write data.
virtual float const * GetReflCounts(size_t Voxel) const override
virtual int NVoxels() const override
void SetReflCount(size_t Voxel, size_t OpChannel, float Count)
bool hasTiming() const
Returns whether the current library deals with time propagation distributions.
void LoadMetadata(TDirectory &srcDir)
Reads the metadata from specified ROOT directory and sets it as current.
decltype(auto) GetRegionLowerCorner() const
Returns the volume vertex (type Point) with the lowest coordinates.
cet::coded_exception< error, detail::translate > exception
float uncheckedAccessTimingPar(size_t Voxel, size_t OpChannel, size_t parnum) const
Unchecked access to a parameter the time distribution.