1 #include "art_root_io/TFileDirectory.h" 4 #include "cetlib_except/exception.h" 10 #include "RtypesCore.h" 25 template <
typename RooT,
typename T>
28 std::vector<std::string>& missingKeys;
33 RooT
const*
value = srcDir.Get<RooT>(key.c_str());
34 if (value)
return std::make_optional<T>(*value);
35 missingKeys.push_back(key);
44 std::string const PhotonLibrary::OpChannelBranchName =
"OpChannel";
47 PhotonLibrary::PhotonLibrary(art::TFileDirectory* pDir ) : fDir(pDir) {}
55 size_t storeTiming)
const 57 mf::LogInfo(
"PhotonLibrary") <<
"Writing photon library to file";
61 <<
"StoreLibraryToFile(): no ROOT file provided, can't store anything.\n";
64 TTree*
tt =
fDir->make<TTree>(
"PhotonLibraryData",
"PhotonLibraryData");
68 Float_t Visibility = 0;
69 Float_t ReflVisibility = 0;
70 Float_t ReflTfirst = 0;
71 Float_t* timing_par =
nullptr;
73 tt->Branch(
"Voxel", &Voxel,
"Voxel/I");
75 tt->Branch(
"Visibility", &Visibility,
"Visibility/F");
77 if (storeTiming != 0) {
81 <<
"StoreLibraryToFile() requested to store the time propagation distribution " 82 "parameters, which was not simulated.";
84 tt->Branch(
"timing_par", timing_par, Form(
"timing_par[%i]/F",
size_t2int(storeTiming)));
87 <<
"Time propagation lookup table is different size than Direct table \n" 88 <<
"this should not be happening. ";
95 <<
"StoreLibraryToFile() requested to store reflected light, which was not simulated.";
97 tt->Branch(
"ReflVisibility", &ReflVisibility,
"ReflVisibility/F");
100 <<
"Reflected light lookup table is different size than Direct table \n" 101 <<
"this should not be happening. ";
106 throw cet::exception(
"PhotonLibrary") <<
"StoreLibraryToFile() requested to store " 107 "reflected light timing, which was not simulated.";
109 tt->Branch(
"ReflTfirst", &ReflTfirst,
"ReflTfirst/F");
111 for (
size_t ivox = 0; ivox !=
fNVoxels; ++ivox) {
112 for (
size_t ichan = 0; ichan !=
fNOpChannels; ++ichan) {
116 if (storeTiming != 0) {
117 for (
size_t i = 0; i < storeTiming; i++)
120 if (Visibility > 0 || ReflVisibility > 0) {
137 bool storeReflected ,
157 if (storeTiming != 0) {
179 mf::LogInfo(
"PhotonLibrary") <<
"Reading photon library from input file: " 184 TDirectory* pSrcDir =
nullptr;
187 f = TFile::Open(LibraryFile.c_str());
188 tt = (TTree*)f->Get(
"PhotonLibraryData");
189 if (tt) { pSrcDir =
f; }
191 TKey* key = f->FindKeyAny(
"PhotonLibraryData");
193 tt = (TTree*)key->ReadObj();
194 pSrcDir = key->GetMotherDir();
197 mf::LogError(
"PhotonLibrary") <<
"PhotonLibraryData not found in file" << LibraryFile;
203 <<
"Error in ttree load, reading photon library: " << LibraryFile <<
"\n";
209 Float_t ReflVisibility;
211 std::vector<Float_t> timing_par;
213 tt->SetBranchAddress(
"Voxel", &Voxel);
214 tt->SetBranchAddress(
"OpChannel", &OpChannel);
215 tt->SetBranchAddress(
"Visibility", &Visibility);
220 if (getReflected) tt->SetBranchAddress(
"ReflVisibility", &ReflVisibility);
222 if (getReflT0) tt->SetBranchAddress(
"ReflTfirst", &ReflTfirst);
236 timing_par.resize(getTiming);
237 tt->SetBranchAddress(
"timing_par", timing_par.data());
240 TNamed*
n = (TNamed*)f->Get(
"fTimingParFormula");
243 <<
"Error reading the photon propagation formula. Please check the photon library." 249 <<
"Time parametrization is activated. Using the formula: " <<
fTimingParFormula <<
" with " 261 size_t NEntries = tt->GetEntries();
263 for (
size_t i = 0; i != NEntries; ++i) {
274 TF1 timingfunction(Form(
"timing_%i_%i", Voxel, OpChannel),
278 timingfunction.SetParameter(
282 timingfunction.SetParameter(
k, timing_par[
k]);
292 log <<
"Photon lookup table size : " << NVoxels <<
" voxels, " <<
fNOpChannels 297 log <<
" (no voxel geometry included)";
304 mf::LogError(
"PhotonLibrary") <<
"Error in closing file : " << LibraryFile;
355 <<
"Error - attempting to set count in voxel " << Voxel <<
" which is out of range";
365 mf::LogError(
"PhotonLibrary") <<
"Error - attempting to set timing t0 count in voxel " 366 << Voxel <<
" which is out of range";
376 mf::LogError(
"PhotonLibrary") <<
"Error - attempting to set a propagation function in voxel " 377 << Voxel <<
" which is out of range";
388 <<
"Error - attempting to set count in voxel " << Voxel <<
" which is out of range";
399 <<
"Error - attempting to set count in voxel " << Voxel <<
" which is out of range";
417 const std::vector<float>*
431 if (Voxel >=
fNVoxels)
return nullptr;
482 constexpr std::size_t NExpectedKeys = 9U;
484 std::vector<std::string> missingKeys;
486 RooReader<RooInt, Int_t> readInt{srcDir, missingKeys};
487 RooReader<RooDouble, Double_t> readDouble{srcDir, missingKeys};
498 if (
auto metaValue = readDouble(
"MinX")) xMin = *metaValue;
499 if (
auto metaValue = readDouble(
"MaxX")) xMax = *metaValue;
500 if (
auto metaValue = readInt(
"NDivX")) xN = *metaValue;
501 if (
auto metaValue = readDouble(
"MinY")) yMin = *metaValue;
502 if (
auto metaValue = readDouble(
"MaxY")) yMax = *metaValue;
503 if (
auto metaValue = readInt(
"NDivY")) yN = *metaValue;
504 if (
auto metaValue = readDouble(
"MinZ")) zMin = *metaValue;
505 if (
auto metaValue = readDouble(
"MaxZ")) zMax = *metaValue;
506 if (
auto metaValue = readInt(
"NDivZ")) zN = *metaValue;
508 if (!missingKeys.empty()) {
509 if (missingKeys.size() != NExpectedKeys) {
511 log <<
"Photon library at '" << srcDir.GetPath() <<
"' is missing " << missingKeys.size()
512 <<
" metadata elements:";
513 for (
auto const& key : missingKeys)
514 log <<
" '" << key <<
"'";
517 mf::LogTrace(
"PhotonLibrary") <<
"No voxel metadata found in '" << srcDir.GetPath() <<
"'";
522 fVoxelDef.emplace(xMin, xMax, xN, yMin, yMax, yN, zMin, zMax, zN);
534 fDir->makeAndRegister<RooInt>(
"NVoxels",
"Total number of voxels in the library",
fNVoxels);
537 fDir->makeAndRegister<RooInt>(
538 "NChannels",
"Total number of optical detector channels in the library",
fNOpChannels);
545 fDir->makeAndRegister<RooDouble>(
546 "MinX",
"Lower x coordinate covered by the library (world coordinates, cm)", lower.X());
547 fDir->makeAndRegister<RooDouble>(
548 "MinY",
"Lower y coordinate covered by the library (world coordinates, cm)", lower.Y());
549 fDir->makeAndRegister<RooDouble>(
550 "MinZ",
"Lower z coordinate covered by the library (world coordinates, cm)", lower.Z());
554 fDir->makeAndRegister<RooDouble>(
555 "MaxX",
"Upper x coordinate covered by the library (world coordinates, cm)", upper.X());
556 fDir->makeAndRegister<RooDouble>(
557 "MaxY",
"Upper y coordinate covered by the library (world coordinates, cm)", upper.Y());
558 fDir->makeAndRegister<RooDouble>(
559 "MaxZ",
"Upper z coordinate covered by the library (world coordinates, cm)", upper.Z());
563 fDir->makeAndRegister<RooDouble>(
"StepX",
"Size on x direction of a voxel (cm)", stepSizes.X());
564 fDir->makeAndRegister<RooDouble>(
"StepY",
"Size on y direction of a voxel (cm)", stepSizes.Y());
565 fDir->makeAndRegister<RooDouble>(
"StepZ",
"Size on z direction of a voxel (cm)", stepSizes.Z());
568 auto const& steps = voxelDef.
GetSteps();
569 fDir->makeAndRegister<RooInt>(
"NDivX",
"Steps on the x direction", steps[0]);
570 fDir->makeAndRegister<RooInt>(
"NDivY",
"Steps on the y direction", steps[1]);
571 fDir->makeAndRegister<RooInt>(
"NDivZ",
"Steps on the z direction", steps[2]);
581 if (!channelBranch) {
583 <<
"Tree '" << tree->GetName() <<
"' has no branch 'OpChannel'";
587 char* oldAddress = channelBranch->GetAddress();
589 channelBranch->SetAddress(&channel);
590 Int_t maxChannel = -1;
594 while (channelBranch->GetEntry(iEntry++)) {
595 if (channel > maxChannel) maxChannel =
channel;
598 MF_LOG_DEBUG(
"PhotonLibrary") <<
"Detected highest channel to be " << maxChannel <<
" from " 599 << iEntry <<
" tree entries";
602 channelBranch->SetAddress(oldAddress);
604 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
Index OpChannel(Index detNum, Index channel)
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)
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.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
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
AdcSimulator::Count Count
util::LazyVector< TF1 > fTimingParTF1LookupTable
virtual float GetCount(size_t Voxel, size_t OpChannel) const override
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
void SetTimingPar(size_t Voxel, size_t OpChannel, float Count, size_t parnum)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
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
QTextStream & endl(QTextStream &s)
float uncheckedAccessTimingPar(size_t Voxel, size_t OpChannel, size_t parnum) const
Unchecked access to a parameter the time distribution.