Skip to content

Commit

Permalink
add optional output schemes to user init
Browse files Browse the repository at this point in the history
  • Loading branch information
ManuelHu committed Aug 17, 2024
1 parent eab669f commit d955d26
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 2 deletions.
10 changes: 8 additions & 2 deletions docs/output.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ Selection of output schemes

Adding a sensitive detector of any type will add the corresponding main output scheme to the list of active output schemes.

Additional output schemes might be used for **filtering output**. Adding additional output schemes by macro commands is not yet implemented. Adding output schemes with C++ code is possible using ``RMGManager::Instance()->GetUserInit()->AddOutputScheme<T>(...);``.
Additional output schemes might be used for **filtering output**. Optional output schemes can be enabled with the macro command ``/RMG/Manager/ActivateOutputScheme [name]``.

Adding output schemes with C++ code is possible using the ``RMGUserInit`` system of remage (access it with ``auto user_init = RMGManager::Instance()->GetUserInit()``:

* ``user_init->AddOutputScheme<T>(...);`` adds and enables the output scheme ``new T(...)`` on each worker thread,
* ``user_init->AddOptionalOutputScheme<T>("name", ...);`` adds a name-tag to an output scheme, that will not be enabled right away, and
* ``user_init->ActivateOptionalOutputScheme("name")`` enables such a registered output scheme.


LH5 output
----------

It is possible to directly write a LH5 file from remage, to facilitate reading output ntuples as a `LH5 Table <https://legend-exp.github.io/legend-data-format-specs/dev/hdf5/#Table>`_. To use this feature, simply specify an output file with a `.lh5` extension.
It is possible to directly write a LH5 file from remage, to facilitate reading output ntuples as a `LH5 Table <https://legend-exp.github.io/legend-data-format-specs/dev/hdf5/#Table>`_. To use this feature, simply specify an output file with a `.lh5` extension, and remage will perform the file conversion automatically.

Additionally, the standalone tool ``remage-to-lh5`` is provided to convert a default Geant4 HDF5 file to a LH5 file. With this, executing `remage -o output.lh5 [...]` is roughly equivalent to the combination of commands:

Expand Down
10 changes: 10 additions & 0 deletions docs/rmg-commands.rst

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions include/RMGManager.hh
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ class RMGManager {
return fExceptionHandler->HadError() || RMGLog::HadError();
}

// NOLINTNEXTLINE(readability-make-member-function-const)
inline void ActivateOptionalOutputScheme(std::string name) {
GetUserInit()->ActivateOptionalOutputScheme(name);
}

private:

void SetUpDefaultG4RunManager(G4RunManagerType type = G4RunManagerType::Default);
Expand Down
26 changes: 26 additions & 0 deletions include/RMGUserInit.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define _RMG_USER_INIT_HH_

#include <functional>
#include <map>
#include <memory>
#include <type_traits>
#include <utility>
Expand All @@ -25,6 +26,7 @@
#include "G4UserSteppingAction.hh"
#include "G4UserTrackingAction.hh"

#include "RMGLog.hh"
#include "RMGVOutputScheme.hh"

class RMGUserInit {
Expand All @@ -43,6 +45,7 @@ class RMGUserInit {
[[nodiscard]] inline auto GetSteppingActions() const { return fSteppingActions; }
[[nodiscard]] inline auto GetTrackingActions() const { return fTrackingActions; }
[[nodiscard]] inline auto GetOutputSchemes() const { return fOutputSchemes; }
[[nodiscard]] inline auto GetOptionalOutputSchemes() const { return fOptionalOutputSchemes; }

// setters
template<typename T, typename... Args> inline void AddSteppingAction(Args&&... args) {
Expand All @@ -57,10 +60,24 @@ class RMGUserInit {
Add<T>(&fOutputSchemes, std::forward<Args>(args)...);
}

template<typename T, typename... Args>
inline void AddOptionalOutputScheme(std::string name, Args&&... args) {
Add<T>(&fOptionalOutputSchemes, name, std::forward<Args>(args)...);
}

inline void ActivateOptionalOutputScheme(std::string name) {
auto it = fOptionalOutputSchemes.find(name);
if (it == fOptionalOutputSchemes.end()) {
RMGLog::Out(RMGLog::fatal, "Optional output scheme '", name, "' not found!");
}
fOutputSchemes.emplace_back((*it).second);
}

private:

template<typename T> using late_init_fn = std::function<std::unique_ptr<T>()>;
template<typename T> using late_init_vec = std::vector<late_init_fn<T>>;
template<typename K, typename T> using late_init_map = std::map<K, late_init_fn<T>>;

template<typename B, typename T, typename... Args>
inline late_init_fn<B> CreateInit(Args&&... args) {
Expand All @@ -78,11 +95,20 @@ class RMGUserInit {
auto create = CreateInit<B, T>(std::forward<Args>(args)...);
vec->emplace_back(std::move(create));
}
template<typename T, typename B, typename K, typename... Args>
inline void Add(late_init_map<K, B>* map, K k, Args&&... args) {
static_assert(std::is_base_of<B, T>::value);

// capture the passed arguments for the constructor to be called later.
auto create = CreateInit<B, T>(std::forward<Args>(args)...);
map->emplace(k, std::move(create));
}

// store partial custom actions to be used later in RMGUserAction
late_init_vec<G4UserSteppingAction> fSteppingActions;
late_init_vec<G4UserTrackingAction> fTrackingActions;
late_init_vec<RMGVOutputScheme> fOutputSchemes;
late_init_map<std::string, RMGVOutputScheme> fOptionalOutputSchemes;
};

#endif
Expand Down
5 changes: 5 additions & 0 deletions src/RMGManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@ void RMGManager::DefineCommands() {
"all hits of one detector type in one ntuple.")
.SetParameterName("tree_per_det", false)
.SetStates(G4State_PreInit, G4State_Idle);

fOutputMessenger->DeclareMethod("ActivateOutputScheme", &RMGManager::ActivateOptionalOutputScheme)
.SetGuidance("Activates the output scheme that had been registered under the given name.")
.SetParameterName("tree_per_det", false)
.SetStates(G4State_PreInit, G4State_Idle);
}

// vim: tabstop=2 shiftwidth=2 expandtab

0 comments on commit d955d26

Please sign in to comment.