9 #ifndef ICARUSCODE_PMT_TRIGGER_UTILITIES_PLOTSANDBOX_H
10 #define ICARUSCODE_PMT_TRIGGER_UTILITIES_PLOTSANDBOX_H
16 #include "art_root_io/TFileDirectory.h"
17 #include "cetlib_except/exception.h"
20 #include "TDirectory.h"
21 #include "TDirectoryFile.h"
33 #include <initializer_list>
43 namespace icarus::trigger::details {
47 template <
typename Map>
53 static constexpr decltype(
auto)
iterate(T&& coll) noexcept
55 auto extractor = [](
auto&&
value) -> decltype(
auto)
56 {
return *std::get<NElement>(
value); };
62 template <
typename Map>
70 namespace icarus::trigger {
class PlotSandbox; }
111 template <
typename RootDir = TDirectoryFile>
113 art::TFileDirectory parentDir,
114 std::string
const& subdir, std::string
const& dirTitle =
""
131 std::map<std::string, std::unique_ptr<PlotSandbox>>
subBoxes;
153 template <
typename SandboxType>
154 static auto*
findSandbox(SandboxType& sandbox, std::string
const&
name);
157 template <
typename SandboxType>
179 (art::TFileDirectory parentDir, std::string
name, std::string desc);
209 std::string
ID()
const;
215 virtual std::string
processTitle(std::string
const& title)
const;
240 template <
typename Obj = TObject>
241 Obj
const*
get(std::string
const&
name)
const;
254 template <
typename Obj = TObject>
255 Obj*
use(std::string
const&
name)
const;
269 template <
typename Obj = TObject>
279 template <
typename DirObj = TDirectory>
292 template <
typename DirObj = TDirectory>
307 template <
typename Obj,
typename... Args>
308 Obj*
make(std::string
const&
name, std::string
const& title, Args&&...
args);
334 template <
typename SandboxType =
PlotSandbox,
typename... Args>
336 std::string
const&
name, std::string
const& desc,
384 template <
typename Stream>
385 void dump(
Stream&& out, std::string indent, std::string firstIndent)
const;
388 template <
typename Stream>
390 {
dump(std::forward<Stream>(out), indent, indent); }
430 template <
typename Stream>
432 (
Stream&& out, std::string indent, std::string firstIndent)
const;
503 template <
typename Obj,
typename... Args>
505 art::TFileDirectory& destDir,
506 std::string
const&
name, std::string
const& title, Args&&...
args
525 template <
typename Obj,
typename... Args>
527 art::TFileDirectory& destDir,
528 std::string
const&
name, std::string
const& title, Args&&...
args
549 template <
typename Obj,
typename... Args>
551 art::TFileDirectory& destDir,
553 std::string
const&
name, std::string
const& title,
577 template <
typename GraphObj,
typename... Args>
579 art::TFileDirectory& destDir,
581 std::string
const&
name, std::string
const& title,
591 static std::pair<std::string, std::string>
splitPath
592 (std::string
const&
path,
char sep =
'/');
597 (std::initializer_list<std::string> pathElements,
char sep =
'/');
608 struct hash<icarus::trigger::PlotSandbox> {
610 {
return std::hash<std::string>()(key.
ID()); }
619 template <
typename RootDir >
621 art::TFileDirectory parentDir,
622 std::string
const& subdir, std::string
const& dirTitle
633 = parentDir.make<RootDir>(subdir.c_str(), dirTitle.c_str());
639 return { parentDir.mkdir(subdir, dirTitle), pROOTdir };
645 template <
typename Obj >
647 {
return use<std::add_const_t<Obj>>(
name); }
651 template <
typename Obj >
654 auto [ objDir, objName ] = splitPath(name);
656 TDirectory*
dir = getDirectory(objDir);
657 if (!dir)
return nullptr;
659 std::string
const processedName = processName(objName);
660 return dir->Get<Obj>(processedName.c_str());
666 template <
typename Obj >
669 auto* obj = use<Obj>(
name);
670 if (obj)
return *obj;
671 cet::exception
e {
"PlotSandbox" };
672 e <<
"PlotSandbox::demand(): object '" << name
673 <<
"' not available in the sandbox '" << ID() <<
"'"
674 <<
"\nBox content: ";
675 dumpContent(
e,
"",
"");
682 template <
typename DirObj >
684 {
return dynamic_cast<DirObj*
>(fData.outputDir.fROOTdir); }
688 template <
typename DirObj >
690 (std::string
const&
path)
const
692 TDirectory* pBaseDir = fData.outputDir.fROOTdir;
693 return dynamic_cast<DirObj*
>
694 (path.empty()? pBaseDir: pBaseDir->GetDirectory(path.c_str()));
699 template <
typename Obj,
typename... Args>
701 (std::string
const&
name, std::string
const& title, Args&&...
args)
703 auto [ objDir, objName ] = splitPath(name);
705 std::string
const processedName = processName(objName);
706 std::string
const processedTitle = processPlotTitle(title);
708 art::TFileDirectory destDir
709 = objDir.empty()? fData.outputDir.fDir: fData.outputDir.fDir.mkdir(objDir);
711 using ObjPtr_t = Obj*;
712 return doConstruct<Obj>(
714 processedName, processedTitle, std::forward<Args>(
args)...
721 <
typename SandboxType ,
typename... Args>
723 (std::string
const& name, std::string
const& desc, Args&&...
args)
726 auto [ it, bInserted ] = fData.subBoxes.try_emplace
727 (name,
new SandboxType(*
this, name, desc, std::forward<Args>(
args)...));
729 throw cet::exception(
"PlotSandbox")
730 <<
"PlotSandbox::addSubSandbox(): a subbox with name '" << name
731 <<
"' already exists in box '" << ID() <<
"'.\n";
733 return *(it->second);
738 template <
typename SandboxType>
740 (SandboxType& sandbox, std::string
const& name)
742 auto const it = sandbox.fData.subBoxes.find(name);
743 return (it == sandbox.fData.subBoxes.end())?
nullptr: it->second.get();
748 template <
typename SandboxType>
750 (SandboxType& sandbox, std::string
const& name)
752 auto* box = findSandbox(sandbox, name);
753 if (box)
return *box;
755 cet::exception
e {
"PlotSandbox" };
756 e <<
"PlotSandbox::demandSandbox(): box '" << name
757 <<
"' not available in the sandbox '" << sandbox.ID() <<
"'";
758 if (sandbox.nSubSandboxes()) {
759 e <<
"\n" <<
"Available nested boxes (" << sandbox.nSubSandboxes() <<
"):";
760 for (
auto const& subbox: sandbox.subSandboxes())
761 e <<
"\n * '" << subbox.ID() <<
"'";
764 e <<
" (no contained box!)";
773 template <
typename Obj,
typename... Args>
775 art::TFileDirectory& destDir,
776 std::string
const& name, std::string
const& title, Args&&...
args
778 return destDir.makeAndRegister<Obj>
779 (
name, title, name.c_str(), title.c_str(), std::forward<Args>(
args)...);
784 template <
typename Obj,
typename... Args>
786 art::TFileDirectory& destDir,
787 std::string
const& name, std::string
const& title, Args&&...
args
789 return destDir.makeAndRegister<Obj>(
name, title, std::forward<Args>(
args)...);
794 template <
typename Obj,
typename... Args>
796 art::TFileDirectory& destDir,
798 std::string
const& name, std::string
const& title,
802 makeWithNameTitle<Obj>(destDir,
name, title, std::forward<Args>(
args)...);
807 template <
typename GraphObj,
typename... Args>
809 art::TFileDirectory& destDir,
811 std::string
const& name, std::string
const& title,
814 return makeAndSetNameTitle<GraphObj>
815 (destDir,
name, title, std::forward<Args>(
args)...);
820 template <
typename Stream>
822 (
Stream&& out, std::string indent, std::string firstIndent)
const
825 if (hasName()) out <<
"Box '" <<
name() <<
"'";
826 else out <<
"Unnamed box";
827 if (hasDescription()) out <<
" (\"" << description() <<
"\")";
828 out <<
" [ID=" << ID() <<
"] with ";
829 dumpContent(std::forward<Stream>(out), indent,
"");
831 if (nSubSandboxes()) {
832 out <<
"\n" << indent <<
"Nested boxes (" << nSubSandboxes() <<
"):";
833 for (
auto const& subbox: subSandboxes()) {
835 subbox.dump(std::forward<Stream>(out), indent +
" ");
842 template <
typename Stream>
844 (
Stream&& out, std::string indent, std::string firstIndent)
const
848 TDirectory
const* pDir = fData.outputDir.fROOTdir;
850 out <<
"no content available";
854 TList
const* objects = pDir->GetList();
855 TList
const* keys = pDir->GetListOfKeys();
856 if (objects && !objects->IsEmpty()) {
857 out << objects->GetSize() <<
" direct entries:";
858 for (TObject
const* obj: *objects) {
859 out <<
"\n" << indent <<
" '" << obj->GetName() <<
"' ["
860 << obj->IsA()->GetName() <<
"]";
863 else out <<
"no direct entries;";
865 for (TObject
const* keyObj: *keys) {
866 auto key =
dynamic_cast<TKey
const*
>(keyObj);
868 if (objects->Contains(key->GetName()))
continue;
869 out <<
"\n" << indent
870 <<
"[KEY] '" << key->GetName() <<
"' ["
871 << key->GetClassName() <<
"]"
882 #endif // ICARUSCODE_PMT_TRIGGER_UTILITIES_PLOTSANDBOX_H
std::string ID() const
Returns a string ID for this sandbox.
Obj * make(std::string const &name, std::string const &title, Args &&...args)
Creates a new ROOT object with the specified name and title.
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Obj * makeWithNameTitle(art::TFileDirectory &destDir, std::string const &name, std::string const &title, Args &&...args) const
Creates, stores and returns a new object.
TFileDirectoryHelper outputDir
Output ROOT directory of the sandbox.
static std::string joinPath(std::initializer_list< std::string > pathElements, char sep= '/')
An object with a begin and end iterator.
The whole data in a convenient package!
decltype(auto) subSandboxes() const
Returns an object proper to iterate through all contained sand boxes.
static constexpr std::size_t NElement
PlotSandbox const * parent
Optional parent sandbox.
void dump(Stream &&out, std::string indent="") const
Dumps the hierarchy of sandboxes into the specified stream.
static TFileDirectoryHelper create(art::TFileDirectory parentDir, std::string const &subdir, std::string const &dirTitle="")
Creates a helper managing a subdirectory of parentDir.
struct icarus::trigger::PlotSandbox::Data_t fData
virtual void setParent(PlotSandbox const *parent)
Sets the parent of this box.
static std::pair< std::string, std::string > splitPath(std::string const &path, char sep= '/')
virtual ~PlotSandbox()=default
Virtual destructor. Default, but C++ wants it.
std::string const & name() const
Returns the sandbox name.
bool deleteSubSandbox(std::string const &name)
Deletes the subbox with the specified name and its directory.
static auto * findSandbox(SandboxType &sandbox, std::string const &name)
Helper function for findSandbox() implementations.
std::string name
The name/key representing this sandbox.
BEGIN_PROLOG triggeremu_data_config_icarus settings PMTADCthresholds sequence::icarus_stage0_multiTPC_TPC physics sequence::icarus_stage0_EastHits_TPC physics sequence::icarus_stage0_WestHits_TPC physics producers purityana0 caloskimCalorimetryCryoE physics caloskimCalorimetryCryoW physics path
std::string desc
The description characterizing the sandbox.
virtual std::string processName(std::string const &name) const
Processes the specified string as it were a name.
bool empty() const
Returns if the sandbox is empty (neither it nor subboxes hold objects).
auto make_transformed_span(BIter begin, EIter end, Op &&op)
DirObj * getDirectory() const
Fetches the base directory of the sandbox.
decltype(auto) map_dereferenced_values(Map &&map)
virtual std::string processedSandboxName() const
std::size_t nSubSandboxes() const
Returns the number of contained sand boxes.
virtual std::string processedSandboxDesc() const
void dump(Stream &&out, std::string indent, std::string firstIndent) const
Dumps the hierarchy of sandboxes into the specified stream.
Obj * doConstruct(art::TFileDirectory &destDir, TObject *, std::string const &name, std::string const &title, Args &&...args) const
General implementation: creates and registers an Obj (name and title used in Obj constructor).
PlotSandbox(art::TFileDirectory parentDir, std::string name, std::string desc)
Constructor: specifies all sandbox characteristics.
void resetSubboxParents(PlotSandbox const *newParent)
std::string const & description() const
Returns the sandbox description.
virtual std::string const & Description() const
std::map< std::string, std::unique_ptr< PlotSandbox > > subBoxes
Contained sand boxes.
Obj const * get(std::string const &name) const
Fetches the object with the specified name from the sandbox.
std::string processPlotTitle(std::string const &title) const
Applies title processing only at the title part of the string.
SandboxType & addSubSandbox(std::string const &name, std::string const &desc, Args &&...args)
Creates a new sandbox contained in this one.
static auto & demandSandbox(SandboxType &sandbox, std::string const &name)
Helper function for demandSandbox() implementations.
Obj & demand(std::string const &name) const
Fetches an object with the specified name to be modified.
TFileDirectoryHelper(art::TFileDirectory dir, TDirectory *ROOTdir)
Data_t & operator=(Data_t const &)=delete
static decltype(auto) constexpr iterate(T &&coll) noexcept
bool hasDescription() const
Returns whether we have a non-empty description.
Obj * use(std::string const &name) const
Fetches an object with the specified name to be modified.
void dumpContent(Stream &&out, std::string indent, std::string firstIndent) const
Dumps the content of this box (nosubboxes) into out stream.
Obj * makeAndSetNameTitle(art::TFileDirectory &destDir, std::string const &name, std::string const &title, Args &&...args) const
Creates, stores and returns a new object.
virtual std::string processTitle(std::string const &title) const
Processes the specified string as it were a description or title.
bool hasName() const
Returns whether we have a non-empty name.
PlotSandbox & operator=(PlotSandbox const &)=delete
A helper to manage ROOT objects with consistent naming.
Contains both a art::TFileDirectory and the TDirectory it manages.