diff --git a/include/HEJ/EmptyAnalysis.hh b/include/HEJ/EmptyAnalysis.hh index e40d1e3..abfbab9 100644 --- a/include/HEJ/EmptyAnalysis.hh +++ b/include/HEJ/EmptyAnalysis.hh @@ -1,53 +1,34 @@ /** \file * \brief Declaration of the trivial (empty) analysis * * \authors The HEJ collaboration (see AUTHORS for details) - * \date 2019-2020 + * \date 2019-2022 * \copyright GPLv2 or later */ #pragma once -#include - -#include "HEJ/Analysis.hh" - -namespace YAML { - class Node; -} -namespace LHEF { - class HEPRUP; -} +#include "HEJ/detail/EmptyAnalysis.hh" namespace HEJ { - class Event; - /** An analysis that does nothing * * This analysis is used by default if no user analysis is specified. * The member functions don't do anything and events passed to the * analysis are simply ignored. + * + * \internal The actual logic is in detail::EmptyAnalysis. + * The reason for this split is that until HEJ 2.3 + * `get_analysis` should return an `EmptyAnalysis` as a fallback, + * to not destroy backward compatibility without warning. + * Returning a detail::EmptyAnalysis instead avoids an internal + * deprecation warning during compilation. */ - struct EmptyAnalysis: Analysis{ - //! Create EmptyAnalysis + struct [[deprecated("to be removed in HEJ 2.3")]] + EmptyAnalysis: detail::EmptyAnalysis { static std::unique_ptr create( - YAML::Node const & parameters, LHEF::HEPRUP const & /*unused*/); - - //! Fill event into analysis (e.g. to histograms) - /** - * This function does nothing - */ - void fill(Event const & /*res_event*/, Event const & /*FO_event*/) override; - //! Whether a resummation event passes all cuts - /** - * There are no cuts, so all events pass - */ - bool pass_cuts(Event const & /*res_event*/, Event const & /*FO_event*/) override; - //! Finalise analysis - /** - * This function does nothing - */ - void finalise() override; - + YAML::Node const & parameters, + LHEF::HEPRUP const & /*unused*/ + ); ~EmptyAnalysis() override = default; }; } // namespace HEJ diff --git a/include/HEJ/detail/EmptyAnalysis.hh b/include/HEJ/detail/EmptyAnalysis.hh new file mode 100644 index 0000000..1e8355a --- /dev/null +++ b/include/HEJ/detail/EmptyAnalysis.hh @@ -0,0 +1,50 @@ +/** \file + * \brief Internal header for empty analysis, to be removed in HEJ 2.3 + * + * \authors The HEJ collaboration (see AUTHORS for details) + * \date 2022 + * \copyright GPLv2 or later + */ + +#pragma once + +#include + +#include "HEJ/Analysis.hh" + +namespace YAML { + class Node; +} +namespace LHEF { + class HEPRUP; +} + +namespace HEJ { + class Event; + + namespace detail { + struct EmptyAnalysis: Analysis{ + //! Create EmptyAnalysis + static std::unique_ptr create( + YAML::Node const & parameters, LHEF::HEPRUP const & /*unused*/); + + //! Fill event into analysis (e.g. to histograms) + /** + * This function does nothing + */ + void fill(Event const & /*res_event*/, Event const & /*FO_event*/) override; + //! Whether a resummation event passes all cuts + /** + * There are no cuts, so all events pass + */ + bool pass_cuts(Event const & /*res_event*/, Event const & /*FO_event*/) override; + //! Finalise analysis + /** + * This function does nothing + */ + void finalise() override; + + ~EmptyAnalysis() override = default; + }; + } +} // namespace HEJ diff --git a/include/HEJ/get_analysis.hh b/include/HEJ/get_analysis.hh index 2756cfc..959a232 100644 --- a/include/HEJ/get_analysis.hh +++ b/include/HEJ/get_analysis.hh @@ -1,43 +1,50 @@ /** \file * \brief Contains the get_analysis function * * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019-2020 * \copyright GPLv2 or later */ #pragma once #include #include #include "HEJ/Analysis.hh" namespace YAML { class Node; } namespace HEJ { //! Load an analysis /** * @param parameters Analysis parameters * @param heprup General run informations * @returns A pointer to an Analysis instance * * If parameters["plugin"] exists, an analysis (deriving from the * \ref Analysis class) will be loaded from the library parameters["plugin"]. * Otherwise, if parameters["rivet"] exists, the corresponding RivetAnalysis * will be loaded. If none of these parameters are specified, a pointer to * the default EmptyAnalysis is returned. */ +#ifndef HEJ_ALLOW_GET_ANALYSIS + [[deprecated( + "Instead of a pointer to an EmptyAnalysis," + "this function will return a null pointer from HEJ 2.3 on. " + "Compile with -DHEJ_ALLOW_GET_ANALYSIS to disable this warning." + )]] +#endif std::unique_ptr get_analysis( YAML::Node const & parameters, LHEF::HEPRUP const & heprup); //! Loads multiple analysis, vector version of get_analysis() /** * @param parameters Vector of Analysis parameters * @param heprup General run informations * @returns Vector of pointers to an Analysis instance */ std::vector> get_analyses( std::vector const & parameters, LHEF::HEPRUP const & heprup); } // namespace HEJ diff --git a/src/EmptyAnalysis.cc b/src/EmptyAnalysis.cc index e23b4c1..e030d06 100644 --- a/src/EmptyAnalysis.cc +++ b/src/EmptyAnalysis.cc @@ -1,72 +1,81 @@ /** * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019-2020 * \copyright GPLv2 or later */ #include "HEJ/EmptyAnalysis.hh" #include #include #include "yaml-cpp/yaml.h" #include "HEJ/exceptions.hh" -namespace HEJ { +namespace HEJ::detail { namespace { std::vector param_as_strings(YAML::Node const & parameters){ using YAML::NodeType; switch(parameters.Type()){ case NodeType::Null: case NodeType::Undefined: return {}; case NodeType::Scalar: return {parameters.as()}; case NodeType::Sequence: { std::vector param_strings; for(auto && param: parameters){ param_strings.emplace_back(param.as()); } return param_strings; } case NodeType::Map: { std::vector param_strings; for(auto && param: parameters){ param_strings.emplace_back(param.first.as()); } return param_strings; } default:; } throw std::logic_error{"unreachable"}; } } // namespace std::unique_ptr EmptyAnalysis::create( YAML::Node const & parameters, LHEF::HEPRUP const & /*unused*/ ){ const auto param_strings = param_as_strings(parameters); if(! param_strings.empty()){ std::string error{"Unknown analysis parameter(s):"}; for(auto && p: param_strings) error += " " + p; throw unknown_option{error}; } return std::make_unique(); } void EmptyAnalysis::fill( Event const & /*res_event*/, Event const & /*FO_event*/ ){ // do nothing } bool EmptyAnalysis::pass_cuts( Event const & /*res_event*/, Event const & /*FO_event*/ ){ return true; } void EmptyAnalysis::finalise(){ // do nothing } -} // namespace HEJ + +} // namespace HEJ::detail + +namespace HEJ { + std::unique_ptr EmptyAnalysis::create( + YAML::Node const & parameters, LHEF::HEPRUP const & heprup + ){ + return detail::EmptyAnalysis::create(parameters, heprup); + } +} diff --git a/src/get_analysis.cc b/src/get_analysis.cc index 1436e44..82d97f5 100644 --- a/src/get_analysis.cc +++ b/src/get_analysis.cc @@ -1,52 +1,63 @@ /** * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019-2020 * \copyright GPLv2 or later */ #include "HEJ/get_analysis.hh" #include #include #include "yaml-cpp/yaml.h" #include "HEJ/EmptyAnalysis.hh" #include "HEJ/RivetAnalysis.hh" namespace HEJ { - std::unique_ptr get_analysis( + namespace { + // Internal helper function to avoid get_analysis warning + // + // TODO: merge with `get_analysis` in HEJ 2.3 + std::unique_ptr get_analysis_impl( YAML::Node const & parameters, LHEF::HEPRUP const & heprup - ){ - if(!parameters["plugin"]){ - if(parameters["rivet"].IsDefined()) - return RivetAnalysis::create(parameters, heprup); - return EmptyAnalysis::create(parameters, heprup); + ){ + if(!parameters["plugin"]){ + if(parameters["rivet"].IsDefined()) + return RivetAnalysis::create(parameters, heprup); + return detail::EmptyAnalysis::create(parameters, heprup); + } + + using AnalysisMaker = std::unique_ptr (*)( + YAML::Node const &, LHEF::HEPRUP const &); + const auto plugin_name = parameters["plugin"].as(); + void * handle = dlopen(plugin_name.c_str(), RTLD_NOW); + char * error = dlerror(); + if(error != nullptr) throw std::runtime_error(error); + + void * sym = dlsym(handle, "make_analysis"); + error = dlerror(); + if(error != nullptr) throw std::runtime_error(error); + auto make_analysis = reinterpret_cast(sym); // NOLINT + + return make_analysis(parameters, heprup); } + } - using AnalysisMaker = std::unique_ptr (*)( - YAML::Node const &, LHEF::HEPRUP const &); - const auto plugin_name = parameters["plugin"].as(); - void * handle = dlopen(plugin_name.c_str(), RTLD_NOW); - char * error = dlerror(); - if(error != nullptr) throw std::runtime_error(error); - - void * sym = dlsym(handle, "make_analysis"); - error = dlerror(); - if(error != nullptr) throw std::runtime_error(error); - auto make_analysis = reinterpret_cast(sym); // NOLINT - - return make_analysis(parameters, heprup); + std::unique_ptr get_analysis( + YAML::Node const & parameters, LHEF::HEPRUP const & heprup + ){ + return get_analysis_impl(parameters, heprup); } std::vector> get_analyses( std::vector const & parameters, LHEF::HEPRUP const & heprup ){ std::vector> anas; anas.reserve(parameters.size()); for(auto const & param: parameters){ - anas.emplace_back(get_analysis(param, heprup)); + anas.emplace_back(get_analysis_impl(param, heprup)); } return anas; } } // namespace HEJ