diff --git a/DDRec/include/DDRec/DetectorData.h b/DDRec/include/DDRec/DetectorData.h index 0bf69dca0d5f992f1f12a315c8cbb6f1781e1845..be937d0eeb404db554f5df4ec1dd3a67803aae1c 100644 --- a/DDRec/include/DDRec/DetectorData.h +++ b/DDRec/include/DDRec/DetectorData.h @@ -17,6 +17,8 @@ #include <bitset> #include <ostream> +#include <boost/variant.hpp> + #include "DD4hep/DetElement.h" namespace dd4hep { @@ -501,9 +503,42 @@ namespace dd4hep { std::map<std::string, double> doubleParameters{}; }; using DoubleParameters = StructExtension<MapStringDoubleStruct>; - std::ostream& operator<<( std::ostream& io , const DoubleParameters& d ) ; + struct MapStringVariantStruct { + std::map<std::string, boost::variant<double, int, std::string, bool>> variantParameters{}; + + template <typename T> + const T& get(const std::string& key) const { + auto it = variantParameters.find(key); + if(it == variantParameters.end()) { + throw std::runtime_error{"Key "+key+"not found"}; + } + return boost::get<T>(it->second); + } + + template <typename T> + T value_or(const std::string& key, T alternative) { + auto it = variantParameters.find(key); + if(it == variantParameters.end()) { + return alternative; + } + return boost::get<T>(it->second); + } + + template <typename T> + void set(const std::string& key, T value) { + variantParameters[key] = value; + } + + bool contains(const std::string& key) const { + return variantParameters.find(key) != variantParameters.end(); + } + }; + using VariantParameters = StructExtension<MapStringVariantStruct>; + std::ostream& operator<<( std::ostream& io , const VariantParameters& d ) ; + + } /* namespace rec */ } /* namespace dd4hep */ diff --git a/DDRec/src/DetectorData.cpp b/DDRec/src/DetectorData.cpp index bb6a2aaf83b984f88de35a99b7e2da14ae60030a..54e63a77e146adcc37f936ffc3f401f11b4bde05 100644 --- a/DDRec/src/DetectorData.cpp +++ b/DDRec/src/DetectorData.cpp @@ -225,6 +225,42 @@ namespace dd4hep { return io ; } + namespace { + struct visitor_impl { + std::ostream& m_io; + void operator()(std::string value) const { + m_io << ": str = " << value; + } + + void operator()(int value) const { + m_io << ": int = " << value; + } + + void operator()(double value) const { + m_io << ": double = " << value; + } + + void operator()(bool value) const { + m_io << ": bool = " << (value ? "true" : "false"); + } + + }; + } + + std::ostream& operator<<(std::ostream& io, const VariantParameters& v) { + boost::io::ios_base_all_saver ifs(io); + io << " --VariantParameters: " << std::scientific << std::endl ; + + visitor_impl visitor{io}; + + for (auto const& thePair: v.variantParameters) { + io << " " + << std::setw(40) << thePair.first << ""; + boost::apply_visitor(visitor, thePair.second); + io << std::endl; + } + return io ; + } } // namespace diff --git a/DDRec/src/plugins/addVariantParameters.cpp b/DDRec/src/plugins/addVariantParameters.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37355cf7c4cd342a961dbc359ff4d2ab4f865b28 --- /dev/null +++ b/DDRec/src/plugins/addVariantParameters.cpp @@ -0,0 +1,112 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : P.Gessinger +// +//========================================================================== +#include "DD4hep/Detector.h" +#include "DD4hep/Factories.h" +#include "DD4hep/Printout.h" +#include "DD4hep/DetectorTools.h" + +#include "DDRec/DetectorData.h" + +#include <regex> + + +namespace dd4hep::rec { + +static long addVariantParameters(Detector& description, int argc, char** argv) { + + if(argc < 2) { + printout(ERROR,"ParametersPlugin","+++ Invalid arguments"); + return 0; + } + + printout(INFO,"ParametersPlugin","+++ Applying %d parameters", argc); + + + static std::regex expr{"^(\\w+)(?:: ?(.*?)?)? ?= ?(.*)"}; + + std::string detector = argv[0]; + + for(int i=1;i<argc;i++) { + std::string kv = argv[i]; + std::smatch m; + if(!std::regex_match(kv, m, expr)) { + throw std::runtime_error("Unable to parse key-value pair to assign"); + } + // std::cout << m.size() << ": " << m.str(0) << std::endl; + if (m.size() != 4) { + throw std::runtime_error("Unable to parse key-value pair to assign"); + } + + std::string key = m.str(1); + std::string type = m.str(2); + if (type == "") { + type = "str"; + } + std::string value = m.str(3); + + printout(INFO,"ParametersPlugin","+++ %s -> %s: %s = %s", detector.c_str(), key.c_str(), type.c_str(), value.c_str()); + + auto recurse = [detector](auto&& self, DetElement elt) -> DetElement { + if(elt.name() == detector) { return elt; } + for(auto& child : elt.children()) { + DetElement res = self(self, child.second); + if (res.isValid()) { return res; } + } + return DetElement{}; // not found + }; + + DetElement elt = recurse(recurse, description.world()); + if(!elt.isValid()){ + printout(ERROR,"ParametersPlugin","+++ Did not find element with name '%s'", detector.c_str()); + return 0; + } + + VariantParameters* extension = elt.extension<VariantParameters>(false); + if(extension == nullptr) { + extension = new VariantParameters(); + elt.addExtension<VariantParameters>(extension); + } + + if (type == "str" || type == "string") { + extension->variantParameters[key] = value; + } + else if (type == "double") { + extension->variantParameters[key] = std::stod(value); + } + else if (type == "int") { + extension->variantParameters[key] = std::stoi(value); + } + else if (type == "bool") { + if (value == "true") { + extension->variantParameters[key] = true; + } + else if (value == "false") { + extension->variantParameters[key] = false; + } + else { + throw std::runtime_error{"Invalid boolean value: " + value}; + } + } + else { + throw std::runtime_error{"Unknown type '"+type+"'"}; + } + } + + + return 1; +} + +} + +DECLARE_APPLY(DD4hep_ParametersPlugin, dd4hep::rec::addVariantParameters) +