diff --git a/DDCore/include/DD4hep/ConditionAny.h b/DDCore/include/DD4hep/ConditionAny.h new file mode 100644 index 0000000000000000000000000000000000000000..124430b3841257f1b7e56bb9660fc70fb8502cdc --- /dev/null +++ b/DDCore/include/DD4hep/ConditionAny.h @@ -0,0 +1,198 @@ +//========================================================================== +// 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 : M.Frank +// +//========================================================================== +#ifndef DD4HEP_CONDITIONSANY_H +#define DD4HEP_CONDITIONSANY_H + +// Framework include files +#include "DD4hep/Conditions.h" + +// C/C++ include files +#include <any> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Conditions internal namespace + namespace detail { + class ConditionObject; + } + + /// Main condition object handle. + /** + * Convenience handle for specialized Condition objects + * with a concrete payload of std::any. + * + * Note: + * Conditions may be shared between several DetElement objects. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CONDITIONS + */ + class ConditionAny : public Handle<detail::ConditionObject> { + public: + /// Forward definition of the key type + using key_type = Condition::key_type; + /// High part of the key identifies the detector element + using detkey_type = Condition::detkey_type; + /// Low part of the key identifies the item identifier + using itemkey_type = Condition::itemkey_type; + + private: + /// Verify that underlying data are either invalid of contain an instance of std::any. + void use_data(detail::ConditionObject* obj); + + public: + + /// Default constructor + ConditionAny() = default; + /// Move constructor + ConditionAny(ConditionAny&& c) = default; + /// Move constructor from Condition + ConditionAny(Condition&& c); + /// Copy constructor + ConditionAny(const ConditionAny& c) = default; + /// Copy constructor from Condition + ConditionAny(const Condition& c); + /// Initializing constructor + ConditionAny(Object* p); + /// Constructor from another handle + template <typename Q> ConditionAny(const Handle<Q>& e); + /// Initializing constructor for a initialized std::any payload + ConditionAny(key_type hash_key); + /// Initializing constructor for a initialized std::any payload + ConditionAny(const std::string& name, const std::string& type); + /// Initializing constructor for a initialized and filled std::any payload + template <typename PAYLOAD> ConditionAny(const std::string& name, const std::string& type, PAYLOAD&& data); + + /// Assignment move operator + template <typename Q> ConditionAny& operator=(Handle<Q>&& c); + /// Assignment copy operator + template <typename Q> ConditionAny& operator=(const Handle<Q>& c); + /// Assignment move operator + ConditionAny& operator=(Condition&& c); + /// Assignment copy operator + ConditionAny& operator=(const Condition& c); + /// Assignment move operator + ConditionAny& operator=(ConditionAny&& c) = default; + /// Assignment copy operator + ConditionAny& operator=(const ConditionAny& c) = default; + + /** Interval of validity */ + /// Access the IOV type + const IOVType& iovType() const; + /// Access the IOV block + const IOV& iov() const; + + /** Conditions identification using integer keys. */ + /// Hash identifier + key_type key() const; + /// DetElement part of the identifier + detkey_type detector_key() const; + /// Item part of the identifier + itemkey_type item_key() const; + + /// Generic getter. Specify the exact type, not a polymorph type + std::any& get(); + /// Generic getter (const version). Specify the exact type, not a polymorph type + const std::any& get() const; + + /// Access to the type information + const std::type_info& any_type() const; + /// Checks whether the object contains a value + bool has_value() const; + /// Access the contained object inside std::any + template <typename T> T& as(); + /// Access the contained object inside std::any + template <typename T> const T& as() const; + /// Access a copy of the contained object inside std::any + template <typename T> T value(); + /// Access the contained object inside std::any + template <typename T> T* pointer(); + /// Access the contained object inside std::any + template <typename T> const T* pointer() const; + }; + + /// Move constructor from Condition + inline ConditionAny::ConditionAny(Condition&& c) : Handle<detail::ConditionObject>() { + this->use_data(c.ptr()); + } + + /// Copy constructor from Condition + inline ConditionAny::ConditionAny(const Condition& c) : Handle<detail::ConditionObject>() { + this->use_data(c.ptr()); + } + + /// Construct conditions object and bind the data + template <typename PAYLOAD> inline + ConditionAny::ConditionAny(const std::string& name, const std::string& type, PAYLOAD&& data) { + ConditionAny c(name, type); + c.get() = data; + this->m_element = c.ptr(); + } + + /// Assignment move operator + template <typename Q> inline ConditionAny& ConditionAny::operator=(Handle<Q>&& c) { + this->use_data(c.ptr()); + return *this; + } + + /// Assignment copy operator + template <typename Q> inline ConditionAny& ConditionAny::operator=(const Handle<Q>& c) { + this->use_data(c.ptr()); + return *this; + } + + /// Assignment move operator + inline ConditionAny& ConditionAny::operator=(Condition&& c) { + this->use_data(c.ptr()); + return *this; + } + + /// Assignment copy operator + inline ConditionAny& ConditionAny::operator=(const Condition& c) { + this->use_data(c.ptr()); + return *this; + } + + /// Access the contained object inside std::any + template <typename T> inline T ConditionAny::value() { + return std::any_cast<T>(this->get()); + } + + /// Access the contained object inside std::any + template <typename T> inline T& ConditionAny::as() { + T* ptr_payload = std::any_cast<T>(&this->get()); + if ( ptr_payload ) return *ptr_payload; + throw std::runtime_error("ConditionAny: Cannot access value of std::any as a reference to "+typeName(typeid(T))); + } + + /// Access the contained object inside std::any + template <typename T> inline const T& ConditionAny::as() const { + const T* ptr_payload = std::any_cast<T>(&this->get()); + if ( ptr_payload ) return *ptr_payload; + throw std::runtime_error("ConditionAny: Cannot access value of std::any as a reference to "+typeName(typeid(T))); + } + + /// Access the contained object inside std::any + template <typename T> inline T* ConditionAny::pointer() { + return isValid() ? std::any_cast<T>(&this->get()) : nullptr; + } + + /// Access the contained object inside std::any + template <typename T> inline const T* ConditionAny::pointer() const { + return isValid() ? std::any_cast<const T>(&this->get()) : nullptr; + } + +} /* End namespace dd4hep */ +#endif // DD4HEP_CONDITIONANY_H diff --git a/DDCore/src/ConditionAny.cpp b/DDCore/src/ConditionAny.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30487f0968141f7a105a5d3430990214eb02dfa2 --- /dev/null +++ b/DDCore/src/ConditionAny.cpp @@ -0,0 +1,128 @@ +//========================================================================== +// 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 : M.Frank +// +//========================================================================== + +// Framework includes +#include "DD4hep/Printout.h" +#include "DD4hep/ConditionAny.h" +#include "DD4hep/detail/ConditionsInterna.h" + +// C/C++ include files +#include <climits> +#include <iomanip> +#include <cstdio> + +using namespace std; +using namespace dd4hep; + +namespace { + inline const BasicGrammar* any_grammar() { + static const BasicGrammar* s_any_grammar = &BasicGrammar::instance<std::any>(); + return s_any_grammar; + } +} + +/// Initializing constructor for a pure, undecorated conditions object +ConditionAny::ConditionAny(key_type hash_key) : Handle<Object>() +{ + if ( hash_key != 0 && hash_key != ~0x0ULL ) { + Object* o = new Object(); + this->assign(o,"",""); + o->data.bind<any>(); + o->hash = hash_key; + return; + } + except("ConditionAny","+++ Cannot create a any-condition with an invalid key: %016llX",hash_key); +} + +/// Initializing constructor for a pure, undecorated conditions object +ConditionAny::ConditionAny(const string& nam, const string& typ) : Handle<Object>() +{ + Object* o = new Object(); + this->assign(o,nam,typ); + o->data.bind<any>(); + o->hash = 0; +} + +void ConditionAny::use_data(detail::ConditionObject* obj) { + if ( obj ) { + if ( !obj->data.grammar ) { + except("ConditionAny","+++ Cannot assign unbound conditions data to handle. [Invalid operation]"); + } + if ( obj->data.grammar != any_grammar() ) { + except("ConditionAny", + "+++ Cannot assign data of type " + + obj->data.grammar->type_name() + + " to std::any. [Invalid operation]"); + } + } + this->m_element = obj; +} + +/// Access the IOV type +const dd4hep::IOVType& ConditionAny::iovType() const { + return *(this->access()->iovType()); +} + +/// Access the IOV block +const dd4hep::IOV& ConditionAny::iov() const { + return *(this->access()->iovData()); +} + +/// Hash identifier +ConditionAny::key_type ConditionAny::key() const { + return this->access()->hash; +} + +/// DetElement part of the identifier +ConditionAny::detkey_type ConditionAny::detector_key() const { + return ConditionKey::KeyMaker(this->access()->hash).values.det_key; +} + +/// Item part of the identifier +ConditionAny::itemkey_type ConditionAny::item_key() const { + return ConditionKey::KeyMaker(access()->hash).values.item_key; +} + +/// Generic getter. Specify the exact type, not a polymorph type +std::any& ConditionAny::get() { + return this->access()->data.get<std::any>(); +} + +/// Generic getter (const version). Specify the exact type, not a polymorph type +const std::any& ConditionAny::get() const { + return this->access()->data.get<std::any>(); +} + +/// Checks whether the object contains a value +bool ConditionAny::has_value() const { + return this->get().has_value(); +} + +/// Access to the type information +const type_info& ConditionAny::any_type() const { + return this->get().type(); +} + +#if 0 +/// Access to the grammar type +const dd4hep::BasicGrammar& ConditionAny::descriptor() const { + const BasicGrammar* grammar = access()->data.grammar; + if ( !grammar ) { + invalidHandleError<ConditionAny>(); + // This code is never reached, since function above throws exception! + // Needed to satisfay CppCheck + throw runtime_error("Null pointer in Grammar object"); + } + return *grammar; +} +#endif diff --git a/DDCore/src/GrammarTypesUnparsed.cpp b/DDCore/src/GrammarTypesUnparsed.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ee9b9684f0f046200a453fc27334e4fb3f47503 --- /dev/null +++ b/DDCore/src/GrammarTypesUnparsed.cpp @@ -0,0 +1,19 @@ +//========================================================================== +// 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 : M.Frank +// +//========================================================================== + +// Framework include files +#include "DD4hep/GrammarUnparsed.h" +// C/C++ include files +#include <any> + +template dd4hep::BasicGrammar const& dd4hep::BasicGrammar::instance<std::any>(); diff --git a/examples/Conditions/src/ConditionAnyExampleObjects.cpp b/examples/Conditions/src/ConditionAnyExampleObjects.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09dcbeaa976f6969c455e36ec97754a5f676fa21 --- /dev/null +++ b/examples/Conditions/src/ConditionAnyExampleObjects.cpp @@ -0,0 +1,256 @@ +//========================================================================== +// 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 : M.Frank +// +//========================================================================== + +// Framework include files +#include "ConditionAnyExampleObjects.h" +#include "DD4hep/DD4hepUnits.h" +#include "DD4hep/ConditionAny.h" +#include "DD4hep/ConditionsProcessor.h" + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::ConditionExamples; +using cond::DependencyBuilder; +using cond::ConditionsLoadInfo; + +namespace { + template <typename T> inline void __prt(ostream& os, const vector<T>& obj) { + for(const auto& o : obj) os << o << " "; + } +} + +/// Interface to client Callback in order to update the condition +Condition ConditionAnyUpdate1::operator()(const ConditionKey& key, ConditionUpdateContext&) { +#ifdef DD4HEP_CONDITIONS_DEBUG + printout(printLevel,"ConditionUpdate1","++ Building dependent condition: %016llX [%s]",key.hash, key.name.c_str()); + ConditionAny target(key.name, "derived", vector<int>()); +#else + printout(printLevel,"ConditionUpdate1","++ Building dependent condition: %016llX",key.hash); + ConditionAny target(key.hash, vector<int>()); +#endif + return target; +} + +/// Interface to client Callback in order to update the condition +void ConditionAnyUpdate1::resolve(Condition target, ConditionUpdateContext& context) { + ConditionAny tar(target); + vector<int>& data = tar.as<vector<int> >(); + ConditionAny cond0 = context.condition(context.key(0)); + data.emplace_back(cond0.value<int>()); + data.emplace_back(cond0.value<int>()*2); +} + +/// Interface to client Callback in order to update the condition +Condition ConditionAnyUpdate2::operator()(const ConditionKey& key, ConditionUpdateContext&) { +#ifdef DD4HEP_CONDITIONS_DEBUG + printout(printLevel,"ConditionUpdate2","++ Building dependent condition: %016llX [%s]",key.hash, key.name.c_str()); + ConditionAny target(key.name,"derived"); +#else + printout(printLevel,"ConditionUpdate2","++ Building dependent condition: %016llX",key.hash); + ConditionAny target(key.hash); +#endif + target.get() = vector<int>(); + return target; +} + +/// Interface to client Callback in order to update the condition +void ConditionAnyUpdate2::resolve(Condition target, ConditionUpdateContext& context) { + ConditionAny tar(target); + vector<int>& data = tar.as<vector<int> >(); + ConditionAny cond0 = context.condition(context.key(0)); + ConditionAny cond1 = context.condition(context.key(1)); + + data.push_back(cond0.value<int>()); + data.push_back(cond0.value<int>()*2); + vector<int>& c1 = cond1.as<vector<int> >(); + data.insert(data.end(), c1.begin(), c1.end()); +} +/// Initializing constructor +ConditionsAnyDependencyCreator::ConditionsAnyDependencyCreator(ConditionsContent& c, PrintLevel p, bool persist, int ex) + : OutputLevel(p), content(c), persist_conditions(persist), extended(ex) +{ + call1 = std::shared_ptr<ConditionUpdateCall>(new ConditionAnyUpdate1(printLevel)); + call2 = std::shared_ptr<ConditionUpdateCall>(new ConditionAnyUpdate2(printLevel)); +} + +/// Callback to process a single detector element +int ConditionsAnyDependencyCreator::operator()(DetElement de, int) const { + ConditionKey key (de,"derived_data"); + ConditionKey target1(de,"derived_data/derived_1"); + ConditionKey target2(de,"derived_data/derived_2"); + DependencyBuilder build_1(de, target1.item_key(), call1); + DependencyBuilder build_2(de, target2.item_key(), call2); + + // Compute the derived stuff + build_1.add(key); + + build_2.add(key); + build_2.add(target1); + + content.addDependency(build_1.release()); + content.addDependency(build_2.release()); + printout(printLevel,"Example","++ Added derived conditions dependencies for %s",de.path().c_str()); + return 1; +} + +/// Callback to process a single detector element +int ConditionsAnyDataAccess::operator()(DetElement de, int level) const { + vector<Condition> conditions; + conditionsCollector(map,conditions)(de, level); + return accessConditions(de, conditions); +} + +/// Common call to access selected conditions +int ConditionsAnyDataAccess::accessConditions(DetElement de, const std::vector<Condition>& conditions) const { + ConditionKey key_temperature (de,"temperature"); + ConditionKey key_pressure (de,"pressure"); + ConditionKey key_double_table(de,"double_table"); + ConditionKey key_int_table (de,"int_table"); + ConditionKey key_derived_data(de,"derived_data"); + ConditionKey key_derived1 (de,"derived_data/derived_1"); + ConditionKey key_derived2 (de,"derived_data/derived_2"); + ConditionKey key_path (de,"de_path"); + int result = 0, count = 0; + + // Let's go for the deltas.... + for( auto condition : conditions ) { + stringstream str; + ConditionAny cond = condition; + // const auto& info = cond.descriptor().type(); + if ( 0 == dynamic_cast<detail::ConditionObject*>(cond.ptr()) ) { + printout(ERROR,"accessConditions","Condition with bad base class!"); + } + + if ( cond.item_key() == key_path.item_key() ) { + result += int(cond.as<string>().length()); + printout(INFO,"accessConditions","Condition: %s type: %s [%s]", + key_temperature.toString().c_str(), + typeName(typeid(cond.get())).c_str(), + typeName(cond.any_type()).c_str()); + printout(INFO,"accessConditions"," value: %s", cond.value<string>().c_str()); + } + else if ( cond.item_key() == key_temperature.item_key() ) { + result += int(cond.as<double>()); + printout(INFO,"accessConditions","Condition: %s type: %s [%s]", + key_temperature.toString().c_str(), + typeName(typeid(cond.get())).c_str(), + typeName(cond.any_type()).c_str()); + printout(INFO,"accessConditions"," value: %f", cond.as<double>()); + } + else if ( cond.item_key() == key_pressure.item_key() ) { + result += int(cond.as<double>()); + printout(INFO,"accessConditions","Condition: %s type: %s [%s]", + key_pressure.toString().c_str(), + typeName(typeid(cond.get())).c_str(), + typeName(cond.any_type()).c_str()); + printout(INFO,"accessConditions"," value: %f", cond.as<double>()); + } + else if ( cond.item_key() == key_double_table.item_key() ) { + result += int(cond.as<vector<double> >().size()); + __prt(str,cond.as<vector<double> >()); + printout(INFO,"accessConditions","Condition: %s type: %s [%s]", + key_double_table.toString().c_str(), + typeName(typeid(cond.get())).c_str(), + typeName(cond.any_type()).c_str()); + printout(INFO,"accessConditions"," value: %s", str.str().c_str()); + } + else if ( cond.item_key() == key_int_table.item_key() ) { + result += int(cond.as<vector<int> >().size()); + __prt(str,cond.as<vector<int> >()); + printout(INFO,"accessConditions","Condition: %s type: %s [%s]", + key_int_table.toString().c_str(), + typeName(typeid(cond.get())).c_str(), + typeName(cond.any_type()).c_str()); + printout(INFO,"accessConditions"," value: %s", str.str().c_str()); + } + else if ( cond.item_key() == key_derived_data.item_key() ) { + result += int(cond.as<int>()); + printout(INFO,"accessConditions","Condition: %s type: %s [%s]", + key_derived_data.toString().c_str(), + typeName(typeid(cond.get())).c_str(), + typeName(cond.any_type()).c_str()); + printout(INFO,"accessConditions"," value: %d", cond.as<int>()); + } + else if ( cond.item_key() == key_derived1.item_key() ) { + result += int(cond.as<vector<int> >().size()); + __prt(str,cond.as<vector<int> >()); + printout(INFO,"accessConditions","Condition: %s type: %s [%s]", + key_derived1.toString().c_str(), + typeName(typeid(cond.get())).c_str(), + typeName(cond.any_type()).c_str()); + printout(INFO,"accessConditions"," value: %s", str.str().c_str()); + } + else if ( cond.item_key() == key_derived2.item_key() ) { + result += int(cond.as<vector<int> >().size()); + __prt(str,cond.as<vector<int> >()); + printout(INFO,"accessConditions","Condition: %s type: %s [%s]", + key_derived2.toString().c_str(), + typeName(typeid(cond.get())).c_str(), + typeName(cond.any_type()).c_str()); + printout(INFO,"accessConditions"," value: %s", str.str().c_str()); + } + if ( !IOV::key_is_contained(iov.key(),cond.iov().key()) ) { + printout(INFO,"CondAccess","++ IOV mismatch:%s <> %s", + iov.str().c_str(), cond.iov().str().c_str()); + continue; + } + ++count; + } + return count; +} + +/// Callback to process a single detector element +int ConditionsAnyKeys::operator()(DetElement de, int) const { + content.insertKey(ConditionKey(de,"temperature").hash); + content.insertKey(ConditionKey(de,"pressure").hash); + content.insertKey(ConditionKey(de,"double_table").hash); + content.insertKey(ConditionKey(de,"int_table").hash); + content.insertKey(ConditionKey(de,"derived_data").hash); + content.insertKey(ConditionKey(de,"de_path").hash); + return 1; +} + +template<typename T> +Condition ConditionsAnyCreator::make_condition(DetElement de, const string& name, const T& val) const { + ConditionAny cond(de.path()+"#"+name, name); + cond.get() = std::make_any<T>(val); + cond->hash = ConditionKey::hashCode(de,name); + return cond; +} + +template<typename T, typename... Args> +Condition ConditionsAnyCreator::make_condition_args(DetElement de, const string& name, Args... args) const { + ConditionAny cond(de.path()+"#"+name, name); + cond.get() = std::make_any<T>(std::forward<Args>(args)...); + cond->hash = ConditionKey::hashCode(de,name); + return cond; +} + +/// Callback to process a single detector element +int ConditionsAnyCreator::operator()(DetElement de, int) const { + Condition temperature = make_condition<double>(de,"temperature",1.222); + Condition pressure = make_condition<double>(de,"pressure",888.88); + Condition derived = make_condition<int> (de,"derived_data",102030); + Condition dbl_table = make_condition<vector<double> >(de,"double_table",{1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.}); + Condition int_table = make_condition<vector<int> > (de,"int_table",{-30,-20,-10,0,10,20,30,40,50,60,70,80,90,100,110,120}); + Condition path = make_condition<std::string> (de,"de_path",de.path()); + + slice.manager.registerUnlocked(pool, temperature); + slice.manager.registerUnlocked(pool, pressure); + slice.manager.registerUnlocked(pool, derived); + slice.manager.registerUnlocked(pool, dbl_table); + slice.manager.registerUnlocked(pool, int_table); + slice.manager.registerUnlocked(pool, path); + printout(printLevel,"Creator","++ Adding manually conditions for %s",de.path().c_str()); + return 5; +} diff --git a/examples/Conditions/src/ConditionAnyExampleObjects.h b/examples/Conditions/src/ConditionAnyExampleObjects.h new file mode 100644 index 0000000000000000000000000000000000000000..654bf77a1d4b6ef4fd44dd58e2477d1d59b838eb --- /dev/null +++ b/examples/Conditions/src/ConditionAnyExampleObjects.h @@ -0,0 +1,167 @@ +//========================================================================== +// 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 : M.Frank +// +//========================================================================== +#ifndef EXAMPLES_CONDITIONS_SRC_CONDITIONANYEXAMPLEOBJECTS_H +#define EXAMPLES_CONDITIONS_SRC_CONDITIONANYEXAMPLEOBJECTS_H + +// Framework include files +#include "ConditionExampleObjects.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for conditions examples + namespace ConditionExamples { + + /// Specialized conditions update callback + /** + * Used by clients to update a condition. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CONDITIONS + */ + class ConditionAnyUpdate1 : public ConditionUpdateCall, public OutputLevel { + public: + /// Initializing constructor + ConditionAnyUpdate1(PrintLevel p) : OutputLevel(p) { } + /// Default destructor + virtual ~ConditionAnyUpdate1() = default; + /// Interface to client Callback in order to update the condition + virtual Condition operator()(const ConditionKey& key, ConditionUpdateContext& context) override final; + /// Interface to client Callback in order to update the condition + virtual void resolve(Condition condition, ConditionUpdateContext& context) override final; + }; + + /// Specialized conditions update callback + /** + * Used by clients to update a condition. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CONDITIONS + */ + class ConditionAnyUpdate2 : public ConditionUpdateCall, public OutputLevel { + public: + /// Initializing constructor + ConditionAnyUpdate2(PrintLevel p) : OutputLevel(p) { } + /// Default destructor + virtual ~ConditionAnyUpdate2() = default; + /// Interface to client Callback in order to update the condition + virtual Condition operator()(const ConditionKey& key, ConditionUpdateContext& context) override final; + /// Interface to client Callback in order to update the condition + virtual void resolve(Condition condition, ConditionUpdateContext& context) override final; + }; + + /// This is important, otherwise the register and forward calls won't find them! + /** + * \author M.Frank + * \version 1.02 + * \date 01/04/2016 + */ + class ConditionsAnyKeys : public OutputLevel { + public: + /// Content object to be filled + ConditionsContent& content; + /// Constructor + ConditionsAnyKeys(ConditionsContent& c, PrintLevel p) : OutputLevel(p), content(c) {} + /// Callback to process a single detector element + virtual int operator()(DetElement de, int level) const final; + }; + + /// Example how to populate the detector description with derived conditions + /** + * This is simply a DetElement crawler... + * + * \author M.Frank + * \version 1.0 + * \date 01/04/2016 + */ + class ConditionsAnyDependencyCreator : public OutputLevel { + public: + /// Content object to be filled + ConditionsContent& content; + /// Three different update call types + std::shared_ptr<ConditionUpdateCall> scall1, call1, call2, call3, call4, call5, call6, callUnresolved; + /// Flag for special setup for ROOT persistency + bool persist_conditions; + /// Flag to indicate increased complexity + int extended; + public: + /// Constructor + ConditionsAnyDependencyCreator(ConditionsContent& c, PrintLevel p, bool persist=false, int extended=0); + /// Destructor + virtual ~ConditionsAnyDependencyCreator() = default; + /// Callback to process a single detector element + virtual int operator()(DetElement de, int level) const final; + }; + + /// Example how to populate the detector description with conditions constants + /** + * This is simply a DetElement crawler... + * + * \author M.Frank + * \version 1.0 + * \date 01/04/2016 + */ + class ConditionsAnyCreator : public OutputLevel { + public: + /// Content object for which conditions are supposedly created + ConditionsSlice& slice; + /// Conditions pool the created conditions are inserted to (not equals user pool!) + ConditionsPool& pool; + public: + /// Constructor + ConditionsAnyCreator(ConditionsSlice& s, ConditionsPool& p, PrintLevel l=DEBUG) + : OutputLevel(l), slice(s), pool(p) {} + /// Destructor + virtual ~ConditionsAnyCreator() = default; + /// Callback to process a single detector element + virtual int operator()(DetElement de, int level) const final; + template<typename T> + Condition make_condition(DetElement de, + const std::string& name, + const T& val) const; + template<typename T, typename... Args> + Condition make_condition_args(DetElement de, + const std::string& name, + Args... args) const; + }; + + /// Example how to access the conditions constants from a detector element + /** + * \author M.Frank + * \version 1.0 + * \date 01/04/2016 + */ + class ConditionsAnyDataAccess : public OutputLevel { + public: + /// Reference to the IOV to be checked + const IOV& iov; + /// Reference to the conditions map to access conditions + ConditionsMap& map; + + public: + /// Constructor + ConditionsAnyDataAccess(const IOV& i, ConditionsMap& m, PrintLevel l=DEBUG) + : OutputLevel(l), iov(i), map(m) {} + /// Destructor + virtual ~ConditionsAnyDataAccess() = default; + /// Callback to process a single detector element + virtual int operator()(DetElement de, int level) const; + /// Common call to access selected conditions + virtual int accessConditions(DetElement de, + const std::vector<Condition>& conditions) const; + }; + } /* End namespace condExamples */ +} /* End namespace dd4hep */ +#endif // EXAMPLES_CONDITIONS_SRC_CONDITIONEXAMPLEOBJECTS_H diff --git a/examples/Conditions/src/ConditionAnyExample_populate.cpp b/examples/Conditions/src/ConditionAnyExample_populate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2245a9f746a9b17996ddce2b11510c7979ae724 --- /dev/null +++ b/examples/Conditions/src/ConditionAnyExample_populate.cpp @@ -0,0 +1,104 @@ +//========================================================================== +// 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 : M.Frank +// +//========================================================================== +// Framework include files +#include "ConditionAnyExampleObjects.h" +#include "DD4hep/Factories.h" + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::ConditionExamples; + +/// Plugin function: Condition program example +/** + * Factory: DD4hep_ConditionExample_populate + * + * \author M.Frank + * \version 1.0 + * \date 01/12/2016 + */ +static int condition_example (Detector& description, int argc, char** argv) { + + string input; + int num_iov = 10, extend = 0; + bool arg_error = false; + for(int i=0; i<argc && argv[i]; ++i) { + if ( 0 == ::strncmp("-input",argv[i],4) ) + input = argv[++i]; + else if ( 0 == ::strncmp("-iovs",argv[i],4) ) + num_iov = ::atol(argv[++i]); + else if ( 0 == ::strncmp("-extend",argv[i],4) ) + extend = ::atol(argv[++i]); + else + arg_error = true; + } + if ( arg_error || input.empty() ) { + /// Help printout describing the basic command line interface + cout << + "Usage: -plugin <name> -arg [-arg] \n" + " name: factory name DD4hep_ConditionExample_populate \n" + " -input <string> Geometry file \n" + " -iovs <number> Number of parallel IOV slots for processing. \n" + "\tArguments given: " << arguments(argc,argv) << endl << flush; + ::exit(EINVAL); + } + + // First we load the geometry + description.fromXML(input); + + detail::have_condition_item_inventory(1); + + /******************** Initialize the conditions manager *****************/ + ConditionsManager manager = installManager(description); + const IOVType* iov_typ = manager.registerIOVType(0,"run").second; + if ( 0 == iov_typ ) + except("ConditionsPrepare","++ Unknown IOV type supplied."); + + /******************** Now as usual: create the slice ********************/ + shared_ptr<ConditionsContent> content(new ConditionsContent()); + shared_ptr<ConditionsSlice> slice(new ConditionsSlice(manager,content)); + Scanner(ConditionsAnyKeys(*content,INFO),description.world()); + Scanner(ConditionsAnyDependencyCreator(*content,DEBUG,false,extend),description.world()); + + /******************** Populate the conditions store *********************/ + // Have 10 run-slices [11,20] .... [91,100] + for(int i=0; i<num_iov; ++i) { + IOV iov(iov_typ, IOV::Key(1+i*10,(i+1)*10)); + ConditionsPool* iov_pool = manager.registerIOV(*iov.iovType, iov.key()); + // Create conditions with all deltas. Use a generic creator + Scanner(ConditionsAnyCreator(*slice, *iov_pool, INFO),description.world(),0,true); + } + + // ++++++++++++++++++++++++ Now compute the conditions for each of these IOVs + ConditionsManager::Result total; + for(int i=0; i<num_iov; ++i) { + IOV req_iov(iov_typ,i*10+5); + // Select the proper set of conditions and attach them to the user pool + ConditionsManager::Result r = manager.prepare(req_iov,*slice); + total += r; + if ( 0 == i ) { // First one we print... + Scanner(ConditionsAnyDataAccess(req_iov,*slice,INFO),description.world()); + } + // Now compute the tranformation matrices + printout(INFO,"Prepare","Total %ld conditions (S:%ld,L:%ld,C:%ld,M:%ld) of IOV %s", + r.total(), r.selected, r.loaded, r.computed, r.missing, req_iov.str().c_str()); + } + printout(INFO,"Statistics","+========================================================================="); + printout(INFO,"Statistics","+ Accessed a total of %ld conditions (S:%6ld,L:%6ld,C:%6ld,M:%ld)", + total.total(), total.selected, total.loaded, total.computed, total.missing); + printout(INFO,"Statistics","+========================================================================="); + // All done. + return 1; +} + +// first argument is the type from the xml file +DECLARE_APPLY(DD4hep_ConditionAnyExample_populate,condition_example) diff --git a/examples/Conditions/src/Conditions_any_basic.cpp b/examples/Conditions/src/Conditions_any_basic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dfa09a4d0f986b25cbd72127efdc4a6b04f59138 --- /dev/null +++ b/examples/Conditions/src/Conditions_any_basic.cpp @@ -0,0 +1,135 @@ +//========================================================================== +// 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 : M.Frank +// +//========================================================================== + +// Framework include files +#include <DD4hep/ConditionAny.h> +#include <DD4hep/Factories.h> +#include <iostream> + +using namespace std; +using namespace dd4hep; + +namespace { + class base_0 { + public: + int data_0 {0}; + base_0() = default; + base_0(base_0&& copy) = default; + base_0(const base_0& copy) = default; + virtual ~base_0() = default; + base_0& operator=(base_0&& copy) = default; + base_0& operator=(const base_0& copy) = default; + }; + + template <typename T> class base_1 { + public: + T data_1; + base_1() = default; + base_1(base_1&& copy) = default; + base_1(const base_1& copy) = default; + virtual ~base_1() = default; + base_1& operator=(base_1&& copy) = default; + base_1& operator=(const base_1& copy) = default; + }; + template <typename T> class base_2: virtual public base_0 { + public: + T data_2; + base_2() = default; + base_2(base_2&& copy) = default; + base_2(const base_2& copy) = default; + virtual ~base_2() = default; + base_2& operator=(base_2&& copy) = default; + base_2& operator=(const base_2& copy) = default; + }; + + class payload : public base_1<int>, public base_2<double> { + public: + payload() = default; + payload(payload&& copy) = default; + payload(const payload& copy) = default; + virtual ~payload() { cout << "payload destroyed..." << endl; } + payload& operator=(payload&& copy) = default; + payload& operator=(const payload& copy) = default; + }; +} + +/// Plugin function: Condition program example +/** + * Factory: DD4hep_Conditions_dynamic + * + * \author M.Frank + * \version 1.0 + * \date 01/12/2016 + */ +static int condition_any_basic (Detector& /* description */, int /* argc */, char** /* argv */) { + ConditionAny c1("any_cond","payload"); + Condition c2("vector_cond","std::vector<int>"); + + cout << endl << endl; + cout << "Size std::any: " << sizeof(std::any) << endl; + cout << "Size std::vector: " << sizeof(std::vector<int>) << endl; + if ( sizeof(std::any) > sizeof(std::vector<int>) ) { + cout << endl << "Test FAILED" << endl << endl; + return EINVAL; + } + cout << "Payload test PASSED" << endl << endl; + + c1.get() = std::make_any<payload>(); + auto& v2 = c2.bind<std::vector<int> >(); + v2.push_back(1); + v2.push_back(2); + + cout << "c1 : " << c1.any_type().name() << endl; + + // Assign incompatible exception to any condition: + try { + c1 = c2; + cout << "Assigned: ConditionAny = Condition(vector) . " << endl; + } + catch(const std::exception& e) { + cout << "Expected exception: ConditionAny = Condition(vector) : " << e.what() << endl; + } + + // Assign any to condition: + Condition cc(c2); + c2 = c1; + cout << "Assigned: Condition(vector) = ConditionAny ." << endl; + c2 = cc; // Restore value! + + Condition c3(c1); + cout << "Construct c3: Condition( Condition(any) ) Pointer: " + << (void*)c3.ptr() << endl; + + ConditionAny c4(c3); + cout << "Construct c4: Condition(any)( ConditionAny ) Pointer: " + << (void*)c4.ptr() << " type:" << c4.any_type().name() << endl; + + try { + ConditionAny c5(c2); + cout << "Construct c5: ConditionAny( Condition(vector) ) Pointer: " + << (void*)c5.ptr() << " type:" << c5.any_type().name() << endl; + } + catch(const std::exception& e) { + cout << "Expected exception: Construct c5: ConditionAny( Condition(vector) ) : " << e.what() << endl; + } + + c1.destroy(); + c2.destroy(); + + cout << endl << "Test PASSED" << endl << endl; + // All done. + return 1; +} + +// first argument is the type from the xml file +DECLARE_APPLY(DD4hep_Conditions_any_basic,condition_any_basic)