From fef1775a82a37a7c120052fc974a253de9d1cc26 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Mon, 11 Jul 2022 16:42:54 +0200
Subject: [PATCH] Start to support Geant4 GFlash parametrization

---
 DDCore/include/DD4hep/OpaqueData.h            | 16 +++++
 DDCore/src/ConditionAny.cpp                   | 25 +++----
 DDG4/include/DDG4/Geant4PhysicsList.h         |  4 +-
 DDG4/include/DDG4/Geant4SensDetAction.h       |  2 -
 DDG4/plugins/Geant4.10.PhysicsConstructors.h  |  6 +-
 DDG4/plugins/Geant4GFlashShowerModel.cpp      | 58 ++++++++++-----
 DDG4/plugins/Geant4SDActions.cpp              | 23 +++---
 .../ClientTests/src/MaterialTester_geo.cpp    | 23 +++---
 examples/Conditions/CMakeLists.txt            |  6 +-
 .../src/ConditionAnyExampleObjects.cpp        | 70 +++++++++----------
 .../src/ConditionAnyExample_populate.cpp      | 26 ++++---
 .../src/ConditionExample_populate.cpp         | 20 +++---
 12 files changed, 166 insertions(+), 113 deletions(-)

diff --git a/DDCore/include/DD4hep/OpaqueData.h b/DDCore/include/DD4hep/OpaqueData.h
index 3819727f8..45ce18864 100644
--- a/DDCore/include/DD4hep/OpaqueData.h
+++ b/DDCore/include/DD4hep/OpaqueData.h
@@ -114,6 +114,8 @@ namespace dd4hep {
   public:
     /// Standard initializing constructor
     OpaqueDataBlock();
+    /// Initializing constructor binding data to buffer with move
+    template <typename OBJECT> OpaqueDataBlock(OBJECT&& data);
     /// Copy constructor (Required by ROOT dictionaries)
     OpaqueDataBlock(const OpaqueDataBlock& copy);
     /// Standard Destructor
@@ -138,6 +140,8 @@ namespace dd4hep {
     template <typename T> T& bind(const std::string& value);
     /// Bind data value
     template <typename T> T& bind(void* ptr, size_t len, const std::string& value);
+    /// Bind data value
+    template <typename T> T& bind(T&& data);
     /// Bind external data value to the pointer
     template <typename T> void bindExtern(T* ptr);
   };
@@ -172,6 +176,12 @@ namespace dd4hep {
     throw std::bad_cast();
   }
 
+  /// Initializing constructor binding data to buffer with move
+  template <typename OBJECT> OpaqueDataBlock::OpaqueDataBlock(OBJECT&& obj)    {
+    this->bind(&BasicGrammar::instance<OBJECT>());
+    new(this->pointer) OBJECT(std::move(obj));
+  }
+
   /// Construct conditions object and bind the data
   template <typename T, typename... Args> inline T& OpaqueDataBlock::construct(Args... args)   {
     this->bind(&BasicGrammar::instance<T>());
@@ -184,6 +194,12 @@ namespace dd4hep {
     return *(new(this->pointer) T());
   }
 
+  /// Bind data value
+  template <typename T> inline T& OpaqueDataBlock::bind(T&& obj)   {
+    this->bind(&BasicGrammar::instance<T>());
+    new(this->pointer) T(std::move(obj));
+  }
+
   /// Bind data value
   template <typename T> inline T& OpaqueDataBlock::bind(void* ptr, size_t len)  {
     this->bind(ptr,len,&BasicGrammar::instance<T>());
diff --git a/DDCore/src/ConditionAny.cpp b/DDCore/src/ConditionAny.cpp
index 14ae22a9c..7e974f493 100644
--- a/DDCore/src/ConditionAny.cpp
+++ b/DDCore/src/ConditionAny.cpp
@@ -17,11 +17,8 @@
 #include "DD4hep/detail/ConditionsInterna.h"
 
 // C/C++ include files
-#include <climits>
 #include <iomanip>
-#include <cstdio>
 
-using namespace std;
 using namespace dd4hep;
 
 namespace {
@@ -36,8 +33,8 @@ 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>();
+    this->assign(o, "", "");
+    o->data.bind<std::any>();
     o->hash = hash_key;
     return;
   }
@@ -45,11 +42,11 @@ ConditionAny::ConditionAny(key_type hash_key) : Handle<Object>()
 }
 
 /// Initializing constructor for a pure, undecorated conditions object
-ConditionAny::ConditionAny(const string& nam, const string& typ) : Handle<Object>()
+ConditionAny::ConditionAny(const std::string& nam, const std::string& typ) : Handle<Object>()
 {
   Object* o = new Object();
-  this->assign(o,nam,typ);
-  o->data.bind<any>();
+  this->assign(o, nam, typ);
+  o->data.bind<std::any>();
   o->hash = 0;
 }
 
@@ -116,7 +113,7 @@ bool ConditionAny::testFlag(mask_type option) const {
 
 /// Generic getter. Specify the exact type, not a polymorph type
 std::any& ConditionAny::get() {
-  auto& o = this->access()->data;
+  OpaqueData& o = this->access()->data;
   if ( o.grammar && (o.grammar == any_grammar()) )   {
     return *(std::any*)o.ptr();
   }
@@ -125,7 +122,7 @@ std::any& ConditionAny::get() {
 
 /// Generic getter (const version). Specify the exact type, not a polymorph type
 const std::any& ConditionAny::get() const {
-  const auto& o = this->access()->data;
+  const OpaqueData& o = this->access()->data;
   if ( o.grammar && (o.grammar == any_grammar()) )   {
     return *(std::any*)o.ptr();
   }
@@ -138,8 +135,8 @@ bool ConditionAny::has_value()   const   {
 }
 
 /// Access to the type information
-const type_info& ConditionAny::any_type() const   {
-  const auto* o = this->ptr();
+const std::type_info& ConditionAny::any_type() const   {
+  const Object* o = this->ptr();
   if ( o && o->data.grammar && (o->data.grammar == any_grammar()) )   {
     const std::any* a = (const std::any*)o->data.ptr();
     return a->type();
@@ -148,8 +145,8 @@ const type_info& ConditionAny::any_type() const   {
 }
 
 /// Access to the type information as string
-const std::string  ConditionAny::any_type_name() const   {
-  const auto* o = this->ptr();
+const std::string ConditionAny::any_type_name() const   {
+  const Object* o = this->ptr();
   if ( o && o->data.grammar && (o->data.grammar == any_grammar()) )   {
     const std::any* a = (const std::any*)o->data.ptr();
     return typeName(a->type());
diff --git a/DDG4/include/DDG4/Geant4PhysicsList.h b/DDG4/include/DDG4/Geant4PhysicsList.h
index 8fe5f2ef0..04c8c912e 100644
--- a/DDG4/include/DDG4/Geant4PhysicsList.h
+++ b/DDG4/include/DDG4/Geant4PhysicsList.h
@@ -116,8 +116,10 @@ namespace dd4hep {
       Geant4PhysicsList(Geant4Context* context, const std::string& nam);
       /// Default destructor
       virtual ~Geant4PhysicsList();
+
       /// Dump content to stdout
       void dump();
+
       /// Install command control messenger if wanted
       virtual void installCommandMessenger();
       /// Access all physics processes
@@ -190,7 +192,7 @@ namespace dd4hep {
        */
       void addPhysicsConstructor(const std::string& physics_name);
       /// Add PhysicsConstructor as Geant4Action object
-      /** The action object must bve a sub-class of type G4VPhysicsConstructor.
+      /** The action object must be a sub-class of type G4VPhysicsConstructor.
        *  -- The Geant4Action object to supports properties.
        *  -- Specific user actions may be implemented in the 
        *     base class calls to 'ConstructParticle' or 'ConstructProcess'.
diff --git a/DDG4/include/DDG4/Geant4SensDetAction.h b/DDG4/include/DDG4/Geant4SensDetAction.h
index 200ab98f1..d8c85fb40 100644
--- a/DDG4/include/DDG4/Geant4SensDetAction.h
+++ b/DDG4/include/DDG4/Geant4SensDetAction.h
@@ -10,7 +10,6 @@
 // Author     : M.Frank
 //
 //==========================================================================
-
 #ifndef DDG4_GEANT4SENSDETACTION_H
 #define DDG4_GEANT4SENSDETACTION_H
 
@@ -574,7 +573,6 @@ namespace dd4hep {
       virtual void clear(G4HCofThisEvent* hce);
     };
 
-
   }    // End namespace sim
 }      // End namespace dd4hep
 
diff --git a/DDG4/plugins/Geant4.10.PhysicsConstructors.h b/DDG4/plugins/Geant4.10.PhysicsConstructors.h
index 21d0b0141..cb68d68df 100644
--- a/DDG4/plugins/Geant4.10.PhysicsConstructors.h
+++ b/DDG4/plugins/Geant4.10.PhysicsConstructors.h
@@ -2,7 +2,7 @@
 #define DDG4_PLUGINS_GEANT4_10_PHYSICSCONSTRUCTORS_H
 
 //==========================================================================
-//  AIDA Detector description implementation 
+//  AIDA Detector description implementation
 //--------------------------------------------------------------------------
 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
 // All rights reserved.
@@ -107,4 +107,8 @@ DECLARE_GEANT4_PHYSICS(G4NeutronTrackingCut)
 #include "G4OpticalPhysics.hh"
 DECLARE_GEANT4_PHYSICS(G4OpticalPhysics)
 
+// Fast simulation
+#include "G4FastSimulationPhysics.hh"
+DECLARE_GEANT4_PHYSICS(G4FastSimulationPhysics)
+
 #endif
diff --git a/DDG4/plugins/Geant4GFlashShowerModel.cpp b/DDG4/plugins/Geant4GFlashShowerModel.cpp
index c3e936800..635917348 100644
--- a/DDG4/plugins/Geant4GFlashShowerModel.cpp
+++ b/DDG4/plugins/Geant4GFlashShowerModel.cpp
@@ -35,9 +35,14 @@ namespace dd4hep  {
     
     class Geant4InputAction;
 
-    /// Steering class for Geant4 GFlash parametrization
+    /// Geant4 wrapper for the GFlash shower model
     /**
-     *  Steering class for Geant4 GFlash parametrization
+     *  Geant4 wrapper for the GFlash shower model
+     *  See e.g. the G4 example examples/extended/parameterisations/gflash/gflash3
+     *  for details.
+     *
+     *  The parametrization is passed as a Geant4Action to be able to configure it,
+     *  which is polymorph the GVFlashShowerParameterisation.
      *
      *  \author  M.Frank
      *
@@ -49,15 +54,20 @@ namespace dd4hep  {
       /// Define standard assignments and constructors
       DDG4_DEFINE_ACTION_CONSTRUCTORS(Geant4GFlashShowerModel);
 
-      /// Region name to which this parametrization should be applied
-      std::string m_regionName;
-      /// Name of the shower model constructor
+      /// Property: Region name to which this parametrization should be applied
+      std::string m_regionName    { "Region-name-not-specified"};
+      /// Property: Name of the shower model constructor
       std::string m_modelName;
+      /// Property: Name of the Geant4Action implementing the parametrization
       std::string m_paramName;
 
+      /// Reference to the shower model
       GFlashShowerModel*             m_showerModel     { nullptr };
+      /// Reference to the parametrization
       GVFlashShowerParameterisation* m_parametrization { nullptr };
+      /// Reference to the particle bounds object
       GFlashParticleBounds*          m_particleBounds  { nullptr };
+      /// Reference to the hit maker
       GFlashHitMaker*                m_hitMaker        { nullptr };
 
     public:
@@ -96,8 +106,10 @@ namespace dd4hep  {
 
 // #include <DDG4/Geant4GFlashShowerModel.h>
 // Framework include files
+#include <DD4hep/Detector.h>
 #include <DDG4/Geant4Action.h>
 #include <DDG4/Geant4Kernel.h>
+#include <DDG4/Geant4Mapping.h>
 
 // Geant4 include files
 #include "GVFlashShowerParameterisation.hh"
@@ -121,8 +133,8 @@ Geant4GFlashShowerModel::Geant4GFlashShowerModel(Geant4Context* ctxt, const std:
 /// Default destructor
 Geant4GFlashShowerModel::~Geant4GFlashShowerModel()    {
   auto* a = dynamic_cast<Geant4Action*>(this->m_parametrization);
-  detail::releasePtr(a);
   this->m_parametrization = nullptr;
+  detail::releasePtr(a);
   detail::deletePtr(m_particleBounds);
   detail::deletePtr(m_showerModel);
   detail::deletePtr(m_hitMaker);
@@ -132,16 +144,17 @@ Geant4GFlashShowerModel::~Geant4GFlashShowerModel()    {
 void Geant4GFlashShowerModel::adoptShowerParametrization(Geant4Action* action)   {
   if ( this->m_parametrization )    {
     auto* a = dynamic_cast<Geant4Action*>(this->m_parametrization);
-    detail::releasePtr(a);
     this->m_parametrization = nullptr;
+    detail::releasePtr(a);
   }
   if ( action )   {
     this->m_parametrization = dynamic_cast<GVFlashShowerParameterisation*>(action);
-    if ( !this->m_parametrization )   {
-      except("The supplied parametrization %s was found as Geant4Action, but is no "
-	     "GVFlashShowerParameterisation!", this->m_paramName.c_str());
+    if ( this->m_parametrization )   {
+      action->addRef();
+      return;
     }
-    action->addRef();
+    except("The supplied parametrization %s was found as Geant4Action, but is no "
+	   "GVFlashShowerParameterisation!", this->m_paramName.c_str());
   }
 }
 
@@ -156,16 +169,25 @@ void Geant4GFlashShowerModel::constructField(Geant4DetectorConstructionContext*
 /// Sensitive detector construction callback. Called at "ConstructSDandField()"
 void Geant4GFlashShowerModel::constructSensitives(Geant4DetectorConstructionContext* /* ctxt */)    {
   auto& kernel = this->context()->kernel();
-  G4Region* region = 0;
-  Geant4Action* action = nullptr;
-  if ( !this->m_parametrization && this->m_paramName.empty() )    {
-    except("No proper parametrization name supplied in the properties: %s",this->m_paramName.c_str());
+  Geant4GeometryInfo& mapping = Geant4Mapping::instance().data();
+  Region rg = kernel.detectorDescription().region(this->m_regionName);
+  if ( !rg.isValid() )   {
+    except("Failed to access the region %s from the detector description.", this->m_regionName.c_str());
   }
-
+  auto region_iter = mapping.g4Regions.find(rg);
+  if ( region_iter == mapping.g4Regions.end() )    {
+    except("Failed to locate G4Region: %s from the Geant4 mapping.");
+  }
+  G4Region* region = (*region_iter).second;
   this->m_showerModel = new GFlashShowerModel(this->name(), region);
   if ( !this->m_parametrization )   {
-    action = kernel.globalAction(this->m_paramName, false);
-    this->adoptShowerParametrization(action);
+    if ( this->m_paramName.empty() )    {
+      except("No proper parametrization name supplied in the properties: %s",this->m_paramName.c_str());
+    }
+    this->adoptShowerParametrization(kernel.globalAction(this->m_paramName, false));
+  }
+  if ( !this->m_parametrization )    {
+    except("No proper parametrization supplied. Failed to construct shower model.");
   }
   this->m_hitMaker = new GFlashHitMaker();
   this->m_particleBounds = new GFlashParticleBounds();
diff --git a/DDG4/plugins/Geant4SDActions.cpp b/DDG4/plugins/Geant4SDActions.cpp
index 8aff2daca..be59e9f4d 100644
--- a/DDG4/plugins/Geant4SDActions.cpp
+++ b/DDG4/plugins/Geant4SDActions.cpp
@@ -1,5 +1,5 @@
 //==========================================================================
-//  AIDA Detector description implementation 
+//  AIDA Detector description implementation
 //--------------------------------------------------------------------------
 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
 // All rights reserved.
@@ -210,8 +210,9 @@ namespace dd4hep {
       return true;
     }
     /// Method for generating hit(s) using the information of the G4GFlashSpot object.
-    template <> bool Geant4SensitiveAction<Geant4Calorimeter>::processGFlash(G4GFlashSpot* spot,
-									     G4TouchableHistory* /*hist*/ )
+    template <> bool
+    Geant4SensitiveAction<Geant4Calorimeter>::processGFlash(G4GFlashSpot* spot,
+							    G4TouchableHistory* /*hist*/ )
     {
       typedef Geant4Calorimeter::Hit Hit;
       Geant4GFlashSpotHandler h(spot);
@@ -277,7 +278,8 @@ namespace dd4hep {
       m_collectionID = declareReadoutFilteredCollection<Geant4Calorimeter::Hit>();
     }
     /// Method for generating hit(s) using the information of G4Step object.
-    template <> bool Geant4SensitiveAction<Geant4OpticalCalorimeter>::process(G4Step* step,G4TouchableHistory*) {
+    template <> bool
+    Geant4SensitiveAction<Geant4OpticalCalorimeter>::process(G4Step* step,G4TouchableHistory*) {
       G4Track * track =  step->GetTrack();
       // check that particle is optical photon:
       if( track->GetDefinition() != G4OpticalPhoton::OpticalPhotonDefinition() )  {
@@ -311,8 +313,9 @@ namespace dd4hep {
       }
     }
     /// Method for generating hit(s) using the information of the G4GFlashSpot object.
-    template <> bool Geant4SensitiveAction<Geant4OpticalCalorimeter>::processGFlash(G4GFlashSpot* spot,
-										    G4TouchableHistory* /*hist*/ )
+    template <> bool
+    Geant4SensitiveAction<Geant4OpticalCalorimeter>::processGFlash(G4GFlashSpot* spot,
+								   G4TouchableHistory* /*hist*/ )
     {
       typedef Geant4Calorimeter::Hit Hit;
       Geant4GFlashSpotHandler h(spot);
@@ -370,7 +373,8 @@ namespace dd4hep {
       m_collectionID = declareReadoutFilteredCollection<Geant4Calorimeter::Hit>();
     }
     /// Method for generating hit(s) using the information of G4Step object.
-    template <> bool Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::process(G4Step* step,G4TouchableHistory*) {
+    template <> bool
+    Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::process(G4Step* step,G4TouchableHistory*) {
       typedef Geant4Calorimeter::Hit Hit;
       Geant4StepHandler    h(step);
       HitContribution      contrib = Hit::extractContribution(step,true);
@@ -414,8 +418,9 @@ namespace dd4hep {
       return true;
     }
     /// Method for generating hit(s) using the information of the G4GFlashSpot object.
-    template <> bool Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::processGFlash(G4GFlashSpot* spot,
-											 G4TouchableHistory* /*hist*/ )
+    template <> bool
+    Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::processGFlash(G4GFlashSpot* spot,
+									G4TouchableHistory* /*hist*/ )
     {
       typedef Geant4Calorimeter::Hit Hit;
       Geant4GFlashSpotHandler h(spot);
diff --git a/examples/ClientTests/src/MaterialTester_geo.cpp b/examples/ClientTests/src/MaterialTester_geo.cpp
index b84c70023..5fe7a2ae3 100644
--- a/examples/ClientTests/src/MaterialTester_geo.cpp
+++ b/examples/ClientTests/src/MaterialTester_geo.cpp
@@ -78,32 +78,33 @@ static Ref_t create_element(Detector& description, xml_h xml_det, SensitiveDetec
     if ( material->GetNproperties() > 0 )    {
       printout(INFO,det_name,"+++          Properties: %d", material->GetNproperties());
       for(Int_t i=0, n=material->GetNproperties(); i<n; ++i)  {
-        TGDMLMatrix* m = material->GetProperty(i);
+        TGDMLMatrix* matrix = material->GetProperty(i);
         printout(INFO,det_name,"+++                   \"%s\" [%s] rows:%d cols:%d",
-                 m->GetName(), m->GetTitle(), m->GetRows(), m->GetCols());
-        m->Print();
+                 matrix->GetName(), matrix->GetTitle(), matrix->GetRows(), matrix->GetCols());
+        matrix->Print();
       }
       printout(INFO,det_name,"+++          Properties by NAME:");
       for(Int_t i=0, n=material->GetNproperties(); i<n; ++i)  {
         const auto* name = material->GetProperties().At(i)->GetName();
-        const auto* m = material->GetProperty(name);
+        const auto* matrix = material->GetProperty(name);
         printout(INFO,det_name,"+++                   \"%s\" [%s,%s] cols: %d rows: %d", name,
-                 m->GetName(), m->GetTitle(), m->GetCols(), m->GetRows());
+                 matrix->GetName(), matrix->GetTitle(), matrix->GetCols(), matrix->GetRows());
       }
     }
     if ( material->GetNconstProperties() > 0 )    {
       printout(INFO,det_name,"+++          CONST Properties: %d", material->GetNconstProperties());
       const TList& all = material->GetConstProperties();
       for(Int_t i=0, n=material->GetNconstProperties(); i<n; ++i)  {
-        const TNamed* m = (const TNamed*)all.At(i);
-        double        v = material->GetConstProperty(i);
-        printout(INFO,det_name,"+++                   \"%s\" [%s] value: %f", m->GetName(), m->GetTitle(), v);
+        const TNamed* prop  = (const TNamed*)all.At(i);
+        double        value = material->GetConstProperty(i);
+        printout(INFO,det_name,"+++                   \"%s\" [%s] value: %f",
+		 prop->GetName(), prop->GetTitle(), value);
       }
       printout(INFO,det_name,"+++          CONST Properties by NAME:");
       for(Int_t i=0, n=material->GetNconstProperties(); i<n; ++i)  {
-        const auto* name = material->GetConstProperties().At(i)->GetName();
-        double v = material->GetConstProperty(name);
-        printout(INFO,det_name,"+++                   \"%s\"  value: %f", name, v);
+        const auto* name  = material->GetConstProperties().At(i)->GetName();
+        double      value = material->GetConstProperty(name);
+        printout(INFO,det_name,"+++                   \"%s\"  value: %f", name, value);
       }
     }
   }
diff --git a/examples/Conditions/CMakeLists.txt b/examples/Conditions/CMakeLists.txt
index 85396422a..3f499f81c 100644
--- a/examples/Conditions/CMakeLists.txt
+++ b/examples/Conditions/CMakeLists.txt
@@ -234,8 +234,8 @@ dd4hep_add_test_reg( Conditions_any_basic
 #---Testing: Simple stress: Load Telescope geometry and have multiple runs on IOVs
 dd4hep_add_test_reg( Conditions_any_Telescope_populate
   COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_Conditions.sh"
-  EXEC_ARGS  geoPluginRun  -destroy -plugin DD4hep_ConditionAnyExample_populate
-      -input file:${CMAKE_INSTALL_PREFIX}/examples/AlignDet/compact/Telescope.xml -iovs 2
-  REGEX_PASS "\\+ Analyzed 1020 any object/elements"
+  EXEC_ARGS  geoPluginRun  -destroy -print WARNING -plugin DD4hep_ConditionAnyExample_populate
+      -input file:${CMAKE_INSTALL_PREFIX}/examples/AlignDet/compact/Telescope.xml -iovs 2 -extend 1
+  REGEX_PASS "\\+ Analyzed 1360 any object/elements"
   REGEX_FAIL " ERROR ;EXCEPTION;Exception"
   )
diff --git a/examples/Conditions/src/ConditionAnyExampleObjects.cpp b/examples/Conditions/src/ConditionAnyExampleObjects.cpp
index 3d5525eb9..0e537a3a1 100644
--- a/examples/Conditions/src/ConditionAnyExampleObjects.cpp
+++ b/examples/Conditions/src/ConditionAnyExampleObjects.cpp
@@ -36,10 +36,10 @@ namespace {
 /// 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());
+  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);
+  printout(printLevel,"ConditionUpdate1", "++ Building dependent condition: %016llX",key.hash);
   ConditionAny    target(key.hash, vector<int>());
 #endif
   return target;
@@ -57,10 +57,10 @@ void ConditionAnyUpdate1::resolve(Condition target, ConditionUpdateContext& cont
 /// 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());
+  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);
+  printout(printLevel,"ConditionUpdate2", "++ Building dependent condition: %016llX",key.hash);
   ConditionAny target(key.hash);
 #endif
   target.get() = vector<int>();
@@ -84,10 +84,10 @@ void ConditionAnyUpdate2::resolve(Condition target, ConditionUpdateContext& cont
 /// Interface to client Callback in order to update the condition
 Condition ConditionAnyUpdate3::operator()(const ConditionKey& key, ConditionUpdateContext&)  {
 #ifdef DD4HEP_CONDITIONS_DEBUG
-  printout(printLevel,"ConditionUpdate3","++ Building dependent condition: %016llX  [%s]",key.hash, key.name.c_str());
+  printout(printLevel,"ConditionUpdate3", "++ Building dependent condition: %016llX  [%s]",key.hash, key.name.c_str());
   return ConditionAny(key.name,"derived");
 #else
-  printout(printLevel,"ConditionUpdate3","++ Building dependent condition: %016llX",key.hash);
+  printout(printLevel,"ConditionUpdate3", "++ Building dependent condition: %016llX",key.hash);
   return ConditionAny(key.hash);
 #endif
 }
@@ -112,10 +112,10 @@ void ConditionAnyUpdate3::resolve(Condition target, ConditionUpdateContext& cont
 /// Interface to client Callback in order to update the condition
 Condition ConditionAnyUpdate4::operator()(const ConditionKey& key, ConditionUpdateContext& context)  {
 #ifdef DD4HEP_CONDITIONS_DEBUG
-  printout(printLevel,"ConditionUpdate4","++ Building dependent condition: %016llX  [%s]",key.hash, key.name.c_str());
+  printout(printLevel,"ConditionUpdate4", "++ Building dependent condition: %016llX  [%s]",key.hash, key.name.c_str());
   ConditionAny target(key.name,"derived", vector<int>());
 #else
-  printout(printLevel,"ConditionUpdate4","++ Building dependent condition: %016llX",key.hash);
+  printout(printLevel,"ConditionUpdate4", "++ Building dependent condition: %016llX",key.hash);
   ConditionAny target(key.hash, vector<int>());
 #endif
   vector<int>& data  = target.as<std::vector<int> >();
@@ -180,15 +180,15 @@ int ConditionsAnyDependencyCreator::operator()(DetElement de, int)  const  {
   content.addDependency(build_1.release());
   content.addDependency(build_2.release());
   content.addDependency(build_3.release());
-  printout(printLevel,"Example","++ Added derived conditions dependencies for %s",de.path().c_str());
+  printout(printLevel,"Example", "++ Added derived conditions dependencies for %s",de.path().c_str());
   return 1;
 }
 
 /// Standard destructor
 ConditionsAnyDataAccess::~ConditionsAnyDataAccess()   {
-  printout(printLevel,"Example","+=========================================================================");
-  printout(printLevel,"Example","+ Analyzed %d any object/elements", num_any_ingredients);
-  printout(printLevel,"Example","+=========================================================================");
+  printout(ALWAYS,"Example", "+=========================================================================");
+  printout(ALWAYS,"Example", "+ Analyzed %d any object/elements", num_any_ingredients);
+  printout(ALWAYS,"Example", "+=========================================================================");
 }
 
 /// Callback to process a single detector element
@@ -218,107 +218,107 @@ int ConditionsAnyDataAccess::accessConditions(DetElement de, const std::vector<C
     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!");
+      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]",
+      printout(printLevel, "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());
+      printout(printLevel, "accessConditions", "           value: %s", cond.value<string>().c_str());
       ++num_any_ingredients;
     }
     else if ( cond.item_key() == key_temperature.item_key() )  {
       result += int(cond.as<double>());
-      printout(INFO,"accessConditions","Condition: %s type: %s [%s]",
+      printout(printLevel, "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>());
+      printout(printLevel, "accessConditions", "           value: %f", cond.as<double>());
       ++num_any_ingredients;
     }
     else if ( cond.item_key() == key_pressure.item_key() )  {
       result += int(cond.as<double>());
-      printout(INFO,"accessConditions","Condition: %s type: %s [%s]",
+      printout(printLevel, "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>());
+      printout(printLevel, "accessConditions", "           value: %f", cond.as<double>());
       ++num_any_ingredients;
     }
     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]",
+      printout(printLevel, "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());
+      printout(printLevel, "accessConditions", "           value: %s", str.str().c_str());
       ++num_any_ingredients;
     }
     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]",
+      printout(printLevel, "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());
+      printout(printLevel, "accessConditions", "           value: %s", str.str().c_str());
       ++num_any_ingredients;
     }
     else if ( cond.item_key() == key_derived_data.item_key() )  {
       result += int(cond.as<int>());
-      printout(INFO,"accessConditions","Condition: %s type: %s [%s]",
+      printout(printLevel, "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>());
+      printout(printLevel, "accessConditions", "           value: %d", cond.as<int>());
       ++num_any_ingredients;
     }
     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]",
+      printout(printLevel, "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());
+      printout(printLevel, "accessConditions", "           value: %s", str.str().c_str());
       ++num_any_ingredients;
     }
     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]",
+      printout(printLevel, "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());
+      printout(printLevel, "accessConditions", "           value: %s", str.str().c_str());
       ++num_any_ingredients;
     }
     else if ( cond.item_key() == key_derived3.item_key() )  {
       result += int(cond.as<vector<int> >().size());
       __prt(str,cond.as<vector<int> >());
-      printout(INFO,"accessConditions","Condition: %s type: %s [%s]",
+      printout(printLevel, "accessConditions", "Condition: %s type: %s [%s]",
 	       key_derived3.toString().c_str(),
 	       typeName(typeid(cond.get())).c_str(),
 	       typeName(cond.any_type()).c_str());
-      printout(INFO,"accessConditions","           value: %s", str.str().c_str());
+      printout(printLevel, "accessConditions", "           value: %s", str.str().c_str());
       ++num_any_ingredients;
     }
     else if ( cond.item_key() == key_derived4.item_key() )  {
       result += int(cond.as<vector<int> >().size());
       __prt(str,cond.as<vector<int> >());
-      printout(INFO,"accessConditions","Condition: %s type: %s [%s]",
+      printout(printLevel, "accessConditions", "Condition: %s type: %s [%s]",
 	       key_derived4.toString().c_str(),
 	       typeName(typeid(cond.get())).c_str(),
 	       typeName(cond.any_type()).c_str());
-      printout(INFO,"accessConditions","           value: %s", str.str().c_str());
+      printout(printLevel, "accessConditions", "           value: %s", str.str().c_str());
       ++num_any_ingredients;
     }
     if ( !IOV::key_is_contained(iov.key(),cond.iov().key()) )  {
-      printout(INFO,"CondAccess","++ IOV mismatch:%s <> %s",
+      printout(ERROR,"CondAccess", "++ IOV mismatch:%s <> %s",
                iov.str().c_str(), cond.iov().str().c_str());
       continue;
     }
@@ -369,6 +369,6 @@ int ConditionsAnyCreator::operator()(DetElement de, int)  const  {
   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());
+  printout(printLevel, "Creator", "++ Adding manually conditions for %s",de.path().c_str());
   return 5;
 }
diff --git a/examples/Conditions/src/ConditionAnyExample_populate.cpp b/examples/Conditions/src/ConditionAnyExample_populate.cpp
index d2245a9f7..3c6046981 100644
--- a/examples/Conditions/src/ConditionAnyExample_populate.cpp
+++ b/examples/Conditions/src/ConditionAnyExample_populate.cpp
@@ -28,9 +28,10 @@ using namespace dd4hep::ConditionExamples;
  */
 static int condition_example (Detector& description, int argc, char** argv)  {
 
-  string input;
-  int    num_iov = 10, extend = 0;
-  bool   arg_error = false;
+  string     input;
+  PrintLevel print_level = INFO;
+  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];
@@ -38,6 +39,8 @@ static int condition_example (Detector& description, int argc, char** argv)  {
       num_iov = ::atol(argv[++i]);
     else if ( 0 == ::strncmp("-extend",argv[i],4) )
       extend = ::atol(argv[++i]);
+    else if ( 0 == ::strncmp("-print",argv[i],4) )
+      print_level = dd4hep::decodePrintLevel(argv[++i]);
     else
       arg_error = true;
   }
@@ -48,6 +51,7 @@ static int condition_example (Detector& description, int argc, char** argv)  {
       "     name:   factory name     DD4hep_ConditionExample_populate                \n"
       "     -input   <string>        Geometry file                                   \n"
       "     -iovs    <number>        Number of parallel IOV slots for processing.    \n"
+      "     -print   <leve>          Set print level (number or string)              \n"
       "\tArguments given: " << arguments(argc,argv) << endl << flush;
     ::exit(EINVAL);
   }
@@ -60,9 +64,9 @@ static int condition_example (Detector& description, int argc, char** argv)  {
   /******************** Initialize the conditions manager *****************/
   ConditionsManager manager = installManager(description);
   const IOVType*    iov_typ = manager.registerIOVType(0,"run").second;
-  if ( 0 == iov_typ )
+  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));
@@ -75,7 +79,7 @@ static int condition_example (Detector& description, int argc, char** argv)  {
     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);
+    Scanner(ConditionsAnyCreator(*slice, *iov_pool, print_level),description.world(),0,true);
   }
   
   // ++++++++++++++++++++++++ Now compute the conditions for each of these IOVs
@@ -86,16 +90,16 @@ static int condition_example (Detector& description, int argc, char** argv)  {
     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());
+      Scanner(ConditionsAnyDataAccess(req_iov, *slice, print_level), description.world());
     }
     // Now compute the tranformation matrices
-    printout(INFO,"Prepare","Total %ld conditions (S:%ld,L:%ld,C:%ld,M:%ld) of IOV %s",
+    printout(ALWAYS,"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)",
+  printout(ALWAYS,"Statistics","+=========================================================================");
+  printout(ALWAYS,"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","+=========================================================================");
+  printout(ALWAYS,"Statistics","+=========================================================================");
   // All done.
   return 1;
 }
diff --git a/examples/Conditions/src/ConditionExample_populate.cpp b/examples/Conditions/src/ConditionExample_populate.cpp
index 0caeeaa17..b1aac8e33 100644
--- a/examples/Conditions/src/ConditionExample_populate.cpp
+++ b/examples/Conditions/src/ConditionExample_populate.cpp
@@ -41,9 +41,10 @@ using namespace dd4hep::ConditionExamples;
  */
 static int condition_example (Detector& description, int argc, char** argv)  {
 
-  string input;
-  int    num_iov = 10, extend = 0;
-  bool   arg_error = false;
+  string     input;
+  PrintLevel print_level = INFO;
+  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];
@@ -51,6 +52,8 @@ static int condition_example (Detector& description, int argc, char** argv)  {
       num_iov = ::atol(argv[++i]);
     else if ( 0 == ::strncmp("-extend",argv[i],4) )
       extend = ::atol(argv[++i]);
+    else if ( 0 == ::strncmp("-print",argv[i],4) )
+      print_level = dd4hep::decodePrintLevel(argv[++i]);
     else
       arg_error = true;
   }
@@ -61,6 +64,7 @@ static int condition_example (Detector& description, int argc, char** argv)  {
       "     name:   factory name     DD4hep_ConditionExample_populate                \n"
       "     -input   <string>        Geometry file                                   \n"
       "     -iovs    <number>        Number of parallel IOV slots for processing.    \n"
+      "     -print   <leve>          Set print level (number or string)              \n"
       "\tArguments given: " << arguments(argc,argv) << endl << flush;
     ::exit(EINVAL);
   }
@@ -88,7 +92,7 @@ static int condition_example (Detector& description, int argc, char** argv)  {
     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(ConditionsCreator(*slice, *iov_pool, INFO),description.world(),0,true);
+    Scanner(ConditionsCreator(*slice, *iov_pool, print_level),description.world(),0,true);
   }
   
   // ++++++++++++++++++++++++ Now compute the conditions for each of these IOVs
@@ -102,13 +106,13 @@ static int condition_example (Detector& description, int argc, char** argv)  {
       Scanner(ConditionsPrinter(slice.get(),"Example"),description.world());
     }
     // Now compute the tranformation matrices
-    printout(INFO,"Prepare","Total %ld conditions (S:%ld,L:%ld,C:%ld,M:%ld) of IOV %s",
+    printout(ALWAYS,"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)",
+  printout(ALWAYS,"Statistics","+=========================================================================");
+  printout(ALWAYS,"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","+=========================================================================");
+  printout(ALWAYS,"Statistics","+=========================================================================");
   // All done.
   return 1;
 }
-- 
GitLab