From 4a6bcc19c40b67adb80554456793d928deec3d94 Mon Sep 17 00:00:00 2001 From: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com> Date: Wed, 25 Sep 2024 18:45:11 +0200 Subject: [PATCH] Fix histograms for Gaudi v39 and add a configurable histogram (#239) --- k4FWCore/scripts/k4run | 16 +++++++--- .../ExampleFunctionalTransformerHist.py | 8 +++++ .../ExampleFunctionalTransformerHist.cpp | 32 +++++++++++++++++-- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/k4FWCore/scripts/k4run b/k4FWCore/scripts/k4run index 12d24df2..6ea509ad 100755 --- a/k4FWCore/scripts/k4run +++ b/k4FWCore/scripts/k4run @@ -60,11 +60,9 @@ def add_arguments(parser, app_mgr): # skip public tools and the applicationmgr itself if "ToolSvc" in conf.name() or "ApplicationMgr" in conf.name(): continue - props = ( - conf.getPropertiesWithDescription() - ) # dict propertyname: (propertyvalue, propertydescription) + # dict propertyname: (propertyvalue, propertydescription) + props = conf.getPropertiesWithDescription() for prop in props: - # only add arguments for relevant properties if ( prop in FILTER_GAUDI_PROPS or "Audit" in prop @@ -208,7 +206,15 @@ def main(): opts_dict = vars(opts) for optionName, propTuple in option_db.items(): logger.info("Option name: %s %s %s", propTuple[1], optionName, opts_dict[optionName]) - propTuple[0].setProp(propTuple[1].rsplit(".", 1)[1], opts_dict[optionName]) + # After Gaudi v39 the new configurable histograms have properties that are tuples + # and by default one of the member is an empty tuple that Gaudi seems not to like + # when used in setProp - it will try to parse it as a string and fail + if "_Axis" in optionName: + propTuple[0].setProp( + propTuple[1].rsplit(".", 1)[1], tuple(x for x in opts_dict[optionName] if x != ()) + ) + else: + propTuple[0].setProp(propTuple[1].rsplit(".", 1)[1], opts_dict[optionName]) if opts.verbose: from Gaudi.Configuration import VERBOSE diff --git a/test/k4FWCoreTest/options/ExampleFunctionalTransformerHist.py b/test/k4FWCoreTest/options/ExampleFunctionalTransformerHist.py index c81e249d..5e92c9cd 100644 --- a/test/k4FWCoreTest/options/ExampleFunctionalTransformerHist.py +++ b/test/k4FWCoreTest/options/ExampleFunctionalTransformerHist.py @@ -73,6 +73,14 @@ root_hist_svc = RootHistoSink("RootHistoSink") root_hist_svc.FileName = "functional_transformer_hist.root" +try: + transformer1.CustomHistogram_Title = "Custom Title" + # Bins can be defined here + transformer1.CustomHistogram_Axis0 = (10, -5.0, 10.0, "X") +# Before Gaudi v39 there isn't a way to set the bins from python +except Exception: + pass + app = ApplicationMgr( TopAlg=[producer1, producer2, transformer1, transformer2], diff --git a/test/k4FWCoreTest/src/components/ExampleFunctionalTransformerHist.cpp b/test/k4FWCoreTest/src/components/ExampleFunctionalTransformerHist.cpp index 881640f5..37bd0c8a 100644 --- a/test/k4FWCoreTest/src/components/ExampleFunctionalTransformerHist.cpp +++ b/test/k4FWCoreTest/src/components/ExampleFunctionalTransformerHist.cpp @@ -25,8 +25,24 @@ #include +#include "GAUDI_VERSION.h" + +#if GAUDI_MAJOR_VERSION < 39 +namespace Gaudi::Accumulators { + template + using StaticRootHistogram = + Gaudi::Accumulators::RootHistogramingCounterBase; +} +#endif + struct ExampleFunctionalTransformerHist final : k4FWCore::Transformer { + StatusCode initialize() override { +#if GAUDI_MAJOR_VERSION >= 39 + m_customHistogram.createHistogram(*this); +#endif + return StatusCode::SUCCESS; + } // The pairs in KeyValues can be changed from python and they correspond // to the name of the input and output collections respectively ExampleFunctionalTransformerHist(const std::string& name, ISvcLocator* svcLoc) @@ -36,14 +52,26 @@ struct ExampleFunctionalTransformerHist final // This is the function that will be called to produce the data edm4hep::MCParticleCollection operator()(const edm4hep::MCParticleCollection& input) const override { // Fill the histogram with the energy of one particle - ++m_histograms[input[0 + !m_firstParticle.value()].getEnergy()]; + ++m_histogram[input[0 + !m_firstParticle.value()].getEnergy()]; +#if GAUDI_MAJOR_VERSION >= 39 + ++m_customHistogram[input[0 + !m_firstParticle.value()].getEnergy()]; +#endif // Return an empty collection since we don't care about the collection return {}; } private: // This is the histogram that will be filled, 1 is the number of dimensions of the histogram (1D) - mutable Gaudi::Accumulators::RootHistogram<1> m_histograms{this, "Histogram Name", "Histogram Title", {100, 0, 10.}}; + mutable Gaudi::Accumulators::StaticRootHistogram<1> m_histogram{ + this, "Histogram Name", "Histogram Title", {100, 0, 10.}}; + +public: +#if GAUDI_MAJOR_VERSION >= 39 + // This is a histogram with title, name and bins that can be set from python + // The callback function is only needed for these histograms with configurable properties + void registerCallBack(Gaudi::StateMachine::Transition, std::function) {} + mutable Gaudi::Accumulators::RootHistogram<1> m_customHistogram{this, "CustomHistogram"}; +#endif Gaudi::Property m_firstParticle{this, "FirstParticle", true}; };