From 08a9e862c392ffc59da0bc56b36c76fcb1af0063 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Tue, 18 Jul 2023 13:43:52 +0200
Subject: [PATCH] By default do not keep hash string for detector checksum to
 minimize resource usage.

---
 DDCore/src/plugins/DetectorChecksum.cpp | 800 ++++++++++++------------
 DDCore/src/plugins/DetectorChecksum.h   |  22 +-
 examples/CLICSiD/CMakeLists.txt         |   4 +-
 examples/ClientTests/CMakeLists.txt     |   8 +-
 4 files changed, 424 insertions(+), 410 deletions(-)

diff --git a/DDCore/src/plugins/DetectorChecksum.cpp b/DDCore/src/plugins/DetectorChecksum.cpp
index 8f3e8b363..5e1ab1184 100644
--- a/DDCore/src/plugins/DetectorChecksum.cpp
+++ b/DDCore/src/plugins/DetectorChecksum.cpp
@@ -91,7 +91,9 @@ std::stringstream DetectorChecksum::logger()   const    {
 DetectorChecksum::entry_t DetectorChecksum::make_entry(std::stringstream& log)   const {
   std::string data(log.str());
   hash_t hash_value = hash64(data.c_str(), data.length());
-  return { hash_value, std::move(data) };
+  if ( have_hash_strings )
+    return { hash_value, std::move(data) };
+  return { hash_value, std::string("") };
 }
 
 void DetectorChecksum::configure()   {
@@ -121,12 +123,12 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleElement(Atom element) c
     else   {
       std::stringstream log = logger();
       log << "<element"         << attr_name(element)
-	  << " Z=\""            << element->Z()   << "\""
-	  << " formula=\""      << element.name() << "\""
-	  << ">" << newline
-	  << " <atom unit=\""   << m_atomunit_nam 
-	  << "\" value=\""      << std::scientific << element->A()/m_atomunit << "\"/>" << newline
-	  << "</element>";
+          << " Z=\""            << element->Z()   << "\""
+          << " formula=\""      << element.name() << "\""
+          << ">" << newline
+          << " <atom unit=\""   << m_atomunit_nam 
+          << "\" value=\""      << std::scientific << element->A()/m_atomunit << "\"/>" << newline
+          << "</element>";
       iel = geo.emplace(element, make_entry(log) ).first;
     }
   }
@@ -146,17 +148,17 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleMaterial(Material mediu
       TGeoMixture* mix = (TGeoMixture*)mat;
       int count_elts = mix->GetNelements();
       for ( Int_t idx = 0; idx < count_elts; idx++ )
-	elts[refName(mix->GetElement(idx))] = mix->GetWmixt()[idx];
+        elts[refName(mix->GetElement(idx))] = mix->GetWmixt()[idx];
       log << " <elements count=\""<< count_elts << "\">" << newline;
       for( const auto& w : elts )
-	log << " <fraction ref=\"" << w.first << "\" n=\"" << w.second << "\">" << newline;
+        log << " <fraction ref=\"" << w.first << "\" n=\"" << w.second << "\">" << newline;
       log << " </elements>" << newline;
     }
     else   {
       log << " A=\""          << mat->GetA()                  << "\""
-	  << " Z=\""          << mat->GetZ()                  << "\">" << newline
-	  << " <element=\""   << refName(mat->GetElement())   << "\"/>" << newline
-	  << " <atom unit=\"" << m_atomunit_nam << "\" value=\"" << mat->GetA()/m_atomunit << "\"/>" << newline;
+          << " Z=\""          << mat->GetZ()                  << "\">" << newline
+          << " <element=\""   << refName(mat->GetElement())   << "\"/>" << newline
+          << " <atom unit=\"" << m_atomunit_nam << "\" value=\"" << mat->GetA()/m_atomunit << "\"/>" << newline;
     }
     log << " <D unit=\"" << m_densunit_nam << "\" value=\"" << mat->GetDensity()/m_densunit << "\"/>" << newline;
     log << "</material>";
@@ -187,221 +189,221 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleSolid(Solid solid) cons
     if ( cl == TGeoBBox::Class() )   {
       TGeoBBox* sh = (TGeoBBox*) shape;
       log << "<box" << nam
-	  << " lunit=\"" << m_len_unit_nam << "\""
-	  << " x=\"" << 2.0*sh->GetDX()/m_len_unit << "\""
-	  << " y=\"" << 2.0*sh->GetDY()/m_len_unit << "\""
-	  << " z=\"" << 2.0*sh->GetDZ()/m_len_unit << "\""
-	  << "/>";
+          << " lunit=\"" << m_len_unit_nam << "\""
+          << " x=\"" << 2.0*sh->GetDX()/m_len_unit << "\""
+          << " y=\"" << 2.0*sh->GetDY()/m_len_unit << "\""
+          << " z=\"" << 2.0*sh->GetDZ()/m_len_unit << "\""
+          << "/>";
     }
     else if ( cl == TGeoHalfSpace::Class() ) {
       TGeoHalfSpace* sh = (TGeoHalfSpace*)(const_cast<TGeoShape*>(shape));
       const auto& pnt = sh->GetPoint();
       const auto& nrm = sh->GetNorm();
       log << "<halfspace" << nam
-	  << " lunit=\"" << m_len_unit_nam << "\">" << newline
-	  << " <point x=\""        << pnt[0]/m_len_unit << "\""
-	  << " y=\""               << pnt[1]/m_len_unit << "\""
-	  << " z=\""               << pnt[2]/m_len_unit << "\"/>" << newline
-	  << " <normal x=\""       << nrm[0]/m_len_unit << "\""
-	  << " y=\""               << nrm[1]/m_len_unit << "\""
-	  << " z=\""               << nrm[2]/m_len_unit << "\"/>" << newline
-	  << "</halfspace>";
+          << " lunit=\"" << m_len_unit_nam << "\">" << newline
+          << " <point x=\""        << pnt[0]/m_len_unit << "\""
+          << " y=\""               << pnt[1]/m_len_unit << "\""
+          << " z=\""               << pnt[2]/m_len_unit << "\"/>" << newline
+          << " <normal x=\""       << nrm[0]/m_len_unit << "\""
+          << " y=\""               << nrm[1]/m_len_unit << "\""
+          << " z=\""               << nrm[2]/m_len_unit << "\"/>" << newline
+          << "</halfspace>";
     }
     else if ( cl == TGeoTube::Class() || cl == TGeoTubeSeg::Class() ) {
       const TGeoTube* sh = (const TGeoTube*) shape;
       log << "<tube" << nam
-	  << " lunit=\""    << m_len_unit_nam           << "\""
-	  << " aunit=\""    << m_ang_unit_nam           << "\""
-	  << " rmin=\""     << check_null(sh->GetRmin()/m_len_unit) << "\""
-	  << " rmax=\""     << check_null(sh->GetRmax()/m_len_unit) << "\""
-	  << " dz=\""       << check_null(2*sh->GetDz()/m_len_unit) << "\""
-	  << " startphi=\"" << 0.0                 << "\""
-	  << " deltaphi=\"" << 360.0/m_ang_unit         << "\""
-	  << "/>";
+          << " lunit=\""    << m_len_unit_nam           << "\""
+          << " aunit=\""    << m_ang_unit_nam           << "\""
+          << " rmin=\""     << check_null(sh->GetRmin()/m_len_unit) << "\""
+          << " rmax=\""     << check_null(sh->GetRmax()/m_len_unit) << "\""
+          << " dz=\""       << check_null(2*sh->GetDz()/m_len_unit) << "\""
+          << " startphi=\"" << 0.0                 << "\""
+          << " deltaphi=\"" << 360.0/m_ang_unit         << "\""
+          << "/>";
     }
     else if ( cl == TGeoTubeSeg::Class() ) {
       const TGeoTubeSeg* sh = (const TGeoTubeSeg*) shape;
       log << "<tube" << nam
-	  << " lunit=\""    << m_len_unit_nam             << "\""
-	  << " aunit=\""    << m_ang_unit_nam             << "\""
-	  << " rmin=\""     << check_null(sh->GetRmin()/m_len_unit) << "\""
-	  << " rmax=\""     << check_null(sh->GetRmax()/m_len_unit) << "\""
-	  << " dz=\""       << check_null(2*sh->GetDz()/m_len_unit) << "\""
-	  << " startphi=\"" << sh->GetPhi1()/m_ang_unit   << "\""
-	  << " deltaphi=\"" << (sh->GetPhi2() - sh->GetPhi1())/m_ang_unit << "\""
-	  << "/>";
+          << " lunit=\""    << m_len_unit_nam             << "\""
+          << " aunit=\""    << m_ang_unit_nam             << "\""
+          << " rmin=\""     << check_null(sh->GetRmin()/m_len_unit) << "\""
+          << " rmax=\""     << check_null(sh->GetRmax()/m_len_unit) << "\""
+          << " dz=\""       << check_null(2*sh->GetDz()/m_len_unit) << "\""
+          << " startphi=\"" << sh->GetPhi1()/m_ang_unit   << "\""
+          << " deltaphi=\"" << (sh->GetPhi2() - sh->GetPhi1())/m_ang_unit << "\""
+          << "/>";
     }
     else if ( cl == TGeoCtub::Class() ) {
       const TGeoCtub* sh = (const TGeoCtub*) shape;
       const Double_t* hi = sh->GetNhigh();
       const Double_t* lo = sh->GetNlow();
       log << "<cutTube" << nam
-	  << " lunit=\""    << m_len_unit_nam             << "\""
-	  << " aunit=\""    << m_ang_unit_nam             << "\""
-	  << " rmin=\""     << sh->GetRmin()/m_len_unit   << "\""
-	  << " rmax=\""     << sh->GetRmax()/m_len_unit   << "\""
-	  << " dz=\""       << 2*sh->GetDz()/m_len_unit   << "\""
-	  << " startphi=\"" << sh->GetPhi1()/m_ang_unit   << "\""
-	  << " deltaphi=\"" << (sh->GetPhi2() - sh->GetPhi1())/m_ang_unit << "\""
-	  << " lowX=\""     << lo[0]/m_len_unit           << "\""
-	  << " lowY=\""     << lo[1]/m_len_unit           << "\""
-	  << " lowZ=\""     << lo[2]/m_len_unit           << "\""
-	  << " highX=\""    << hi[0]/m_len_unit           << "\""
-	  << " highY=\""    << hi[1]/m_len_unit           << "\""
-	  << " highZ=\""    << hi[2]/m_len_unit           << "\""
-	  << "/>";
+          << " lunit=\""    << m_len_unit_nam             << "\""
+          << " aunit=\""    << m_ang_unit_nam             << "\""
+          << " rmin=\""     << sh->GetRmin()/m_len_unit   << "\""
+          << " rmax=\""     << sh->GetRmax()/m_len_unit   << "\""
+          << " dz=\""       << 2*sh->GetDz()/m_len_unit   << "\""
+          << " startphi=\"" << sh->GetPhi1()/m_ang_unit   << "\""
+          << " deltaphi=\"" << (sh->GetPhi2() - sh->GetPhi1())/m_ang_unit << "\""
+          << " lowX=\""     << lo[0]/m_len_unit           << "\""
+          << " lowY=\""     << lo[1]/m_len_unit           << "\""
+          << " lowZ=\""     << lo[2]/m_len_unit           << "\""
+          << " highX=\""    << hi[0]/m_len_unit           << "\""
+          << " highY=\""    << hi[1]/m_len_unit           << "\""
+          << " highZ=\""    << hi[2]/m_len_unit           << "\""
+          << "/>";
     }
     else if ( cl == TGeoEltu::Class() ) {
       const TGeoEltu* sh = (const TGeoEltu*) shape;
       log << "<eltube" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " dx=\""     << sh->GetA()/m_len_unit      << "\""
-	  << " dy=\""     << sh->GetB()/m_len_unit      << "\""
-	  << " dz=\""     << sh->GetDz()/m_len_unit     << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " dx=\""     << sh->GetA()/m_len_unit      << "\""
+          << " dy=\""     << sh->GetB()/m_len_unit      << "\""
+          << " dz=\""     << sh->GetDz()/m_len_unit     << "\""
+          << "/>";
     }
     else if ( cl == TGeoTrd1::Class() ) {
       const TGeoTrd1* sh = (const TGeoTrd1*) shape;
       log << "<trd" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " x1=\""     << 2*check_null(sh->GetDx1()/m_len_unit)  << "\""
-	  << " x2=\""     << 2*check_null(sh->GetDx2()/m_len_unit)  << "\""
-	  << " y1=\""     << 2*check_null(sh->GetDy()/m_len_unit)   << "\""
-	  << " y2=\""     << 2*check_null(sh->GetDy()/m_len_unit)   << "\""
-	  << " z=\""      << 2*check_null(sh->GetDz()/m_len_unit)   << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " x1=\""     << 2*check_null(sh->GetDx1()/m_len_unit)  << "\""
+          << " x2=\""     << 2*check_null(sh->GetDx2()/m_len_unit)  << "\""
+          << " y1=\""     << 2*check_null(sh->GetDy()/m_len_unit)   << "\""
+          << " y2=\""     << 2*check_null(sh->GetDy()/m_len_unit)   << "\""
+          << " z=\""      << 2*check_null(sh->GetDz()/m_len_unit)   << "\""
+          << "/>";
     }
     else if ( cl == TGeoTrd2::Class() ) {
       const TGeoTrd2* sh = (const TGeoTrd2*) shape;
       log << "<trd" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " x1=\""     << 2*check_null(sh->GetDx1()/m_len_unit)  << "\""
-	  << " x2=\""     << 2*check_null(sh->GetDx2()/m_len_unit)  << "\""
-	  << " y1=\""     << 2*check_null(sh->GetDy1()/m_len_unit)  << "\""
-	  << " y2=\""     << 2*check_null(sh->GetDy2()/m_len_unit)  << "\""
-	  << " z=\""      << 2*check_null(sh->GetDz()/m_len_unit)   << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " x1=\""     << 2*check_null(sh->GetDx1()/m_len_unit)  << "\""
+          << " x2=\""     << 2*check_null(sh->GetDx2()/m_len_unit)  << "\""
+          << " y1=\""     << 2*check_null(sh->GetDy1()/m_len_unit)  << "\""
+          << " y2=\""     << 2*check_null(sh->GetDy2()/m_len_unit)  << "\""
+          << " z=\""      << 2*check_null(sh->GetDz()/m_len_unit)   << "\""
+          << "/>";
     }
     else if ( cl == TGeoTrap::Class() )   {
       const TGeoTrap* sh = (const TGeoTrap*) shape;
       log << "<trap" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " aunit=\""  << m_ang_unit_nam             << "\""
-	  << " z=\""      << check_null(2*sh->GetDz()/m_len_unit)   << "\""
-	  << " theta=\""  << check_null(sh->GetTheta()/m_ang_unit)  << "\""
-	  << " phi=\""    << check_null(sh->GetPhi()/m_ang_unit)    << "\""
-	  << " x1=\""     << check_null(2*sh->GetBl1()/m_len_unit)  << "\""
-	  << " x2=\""     << check_null(2*sh->GetTl1()/m_len_unit)  << "\""
-	  << " x3=\""     << check_null(2*sh->GetBl2()/m_len_unit)  << "\""
-	  << " x4=\""     << check_null(2*sh->GetTl2()/m_len_unit)  << "\""
-	  << " y1=\""     << check_null(2*sh->GetH1()/m_len_unit)   << "\""
-	  << " y2=\""     << check_null(2*sh->GetH2()/m_len_unit)   << "\""
-	  << " alpha1=\"" << check_null(sh->GetAlpha1()/m_ang_unit) << "\""
-	  << " alpha2=\"" << check_null(sh->GetAlpha2()/m_ang_unit) << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " aunit=\""  << m_ang_unit_nam             << "\""
+          << " z=\""      << check_null(2*sh->GetDz()/m_len_unit)   << "\""
+          << " theta=\""  << check_null(sh->GetTheta()/m_ang_unit)  << "\""
+          << " phi=\""    << check_null(sh->GetPhi()/m_ang_unit)    << "\""
+          << " x1=\""     << check_null(2*sh->GetBl1()/m_len_unit)  << "\""
+          << " x2=\""     << check_null(2*sh->GetTl1()/m_len_unit)  << "\""
+          << " x3=\""     << check_null(2*sh->GetBl2()/m_len_unit)  << "\""
+          << " x4=\""     << check_null(2*sh->GetTl2()/m_len_unit)  << "\""
+          << " y1=\""     << check_null(2*sh->GetH1()/m_len_unit)   << "\""
+          << " y2=\""     << check_null(2*sh->GetH2()/m_len_unit)   << "\""
+          << " alpha1=\"" << check_null(sh->GetAlpha1()/m_ang_unit) << "\""
+          << " alpha2=\"" << check_null(sh->GetAlpha2()/m_ang_unit) << "\""
+          << "/>";
     }
     else if ( cl == TGeoHype::Class() )   {
       const TGeoHype* sh = (const TGeoHype*) shape;
       log << "<hype" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " aunit=\""  << m_ang_unit_nam             << "\""
-	  << " rmin=\""   << check_null(sh->GetRmin()/m_len_unit)   << "\""
-	  << " rmax=\""   << check_null(sh->GetRmax()/m_len_unit)   << "\""
-	  << " inst=\""   << check_null(sh->GetStIn()/m_ang_unit)   << "\""
-	  << " outst=\""  << check_null(sh->GetStOut()/m_ang_unit)  << "\""
-	  << " z=\""      << check_null(2*sh->GetDz()/m_len_unit)   << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " aunit=\""  << m_ang_unit_nam             << "\""
+          << " rmin=\""   << check_null(sh->GetRmin()/m_len_unit)   << "\""
+          << " rmax=\""   << check_null(sh->GetRmax()/m_len_unit)   << "\""
+          << " inst=\""   << check_null(sh->GetStIn()/m_ang_unit)   << "\""
+          << " outst=\""  << check_null(sh->GetStOut()/m_ang_unit)  << "\""
+          << " z=\""      << check_null(2*sh->GetDz()/m_len_unit)   << "\""
+          << "/>";
     }
     else if ( cl == TGeoPgon::Class() )   {
       const TGeoPgon* sh = (const TGeoPgon*) shape;
       log << "<polyhedra" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " aunit=\""  << m_ang_unit_nam             << "\""
-	  << " startphi=\"" << check_null(sh->GetPhi1()/m_ang_unit) << "\""
-	  << " deltaphi=\"" << check_null(sh->GetDphi()/m_ang_unit) << "\""
-	  << " numsides=\"" << sh->GetNedges()     << "\">" << newline;
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " aunit=\""  << m_ang_unit_nam             << "\""
+          << " startphi=\"" << check_null(sh->GetPhi1()/m_ang_unit) << "\""
+          << " deltaphi=\"" << check_null(sh->GetDphi()/m_ang_unit) << "\""
+          << " numsides=\"" << sh->GetNedges()     << "\">" << newline;
       for(int i=0, n=sh->GetNz(); i<n; ++i)  {
         log << " <zplane z=\"" << check_null(sh->GetZ(i)/m_len_unit) 
-	    << "\" rmin=\"" << check_null(sh->GetRmin(i)/m_len_unit) << "\""
-	    << "\" rmax=\"" << check_null(sh->GetRmax(i)/m_len_unit) << "\"/>" << newline;
+            << "\" rmin=\"" << check_null(sh->GetRmin(i)/m_len_unit) << "\""
+            << "\" rmax=\"" << check_null(sh->GetRmax(i)/m_len_unit) << "\"/>" << newline;
       }
       log << "</polyhedra>";
     }
     else if ( cl == TGeoPcon::Class() )  {
       const TGeoPcon* sh = (const TGeoPcon*) shape;
       log << "<polycone" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " aunit=\""  << m_ang_unit_nam             << "\""
-	  << " startphi=\"" << check_null(sh->GetPhi1()/m_ang_unit) << "\""
-	  << " deltaphi=\"" << check_null(sh->GetDphi()/m_ang_unit) << "\">" << newline;
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " aunit=\""  << m_ang_unit_nam             << "\""
+          << " startphi=\"" << check_null(sh->GetPhi1()/m_ang_unit) << "\""
+          << " deltaphi=\"" << check_null(sh->GetDphi()/m_ang_unit) << "\">" << newline;
       for(int i=0, n=sh->GetNz(); i<n; ++i)  {
         log << " <zplane z=\"" << check_null(sh->GetZ(i)/m_len_unit) 
-	    << "\" rmin=\"" << check_null(sh->GetRmin(i)/m_len_unit) << "\""
-	    << "\" rmax=\"" << check_null(sh->GetRmax(i)/m_len_unit) << "\"/>" << newline;
+            << "\" rmin=\"" << check_null(sh->GetRmin(i)/m_len_unit) << "\""
+            << "\" rmax=\"" << check_null(sh->GetRmax(i)/m_len_unit) << "\"/>" << newline;
       }
       log << "</polycone>";
     }
     else if ( cl == TGeoCone::Class() )  {
       const TGeoCone* sh = (const TGeoCone*) shape;
       log << "<cone" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " aunit=\""  << m_ang_unit_nam             << "\""
-	  << " rmin1=\""  << check_null(sh->GetRmin1()/m_len_unit)  << "\""
-	  << " rmin2=\""  << check_null(sh->GetRmin2()/m_len_unit)  << "\""
-	  << " rmax1=\""  << check_null(sh->GetRmax1()/m_len_unit)  << "\""
-	  << " rmax2=\""  << check_null(sh->GetRmax2()/m_len_unit)  << "\""
-	  << " z=\""      << check_null(sh->GetDz()/m_len_unit)     << "\""
-	  << " startphi=\"" << 0.0/m_ang_unit           << "\""
-	  << " deltaphi=\"" << 360.0/m_ang_unit         << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " aunit=\""  << m_ang_unit_nam             << "\""
+          << " rmin1=\""  << check_null(sh->GetRmin1()/m_len_unit)  << "\""
+          << " rmin2=\""  << check_null(sh->GetRmin2()/m_len_unit)  << "\""
+          << " rmax1=\""  << check_null(sh->GetRmax1()/m_len_unit)  << "\""
+          << " rmax2=\""  << check_null(sh->GetRmax2()/m_len_unit)  << "\""
+          << " z=\""      << check_null(sh->GetDz()/m_len_unit)     << "\""
+          << " startphi=\"" << 0.0/m_ang_unit           << "\""
+          << " deltaphi=\"" << 360.0/m_ang_unit         << "\""
+          << "/>";
     }
     else if ( cl == TGeoConeSeg::Class() )  {
       const TGeoConeSeg* sh = (const TGeoConeSeg*) shape;
       log << "<cone" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " aunit=\""  << m_ang_unit_nam             << "\""
-	  << " rmin1=\""  << check_null(sh->GetRmin1()/m_len_unit)  << "\""
-	  << " rmin2=\""  << check_null(sh->GetRmin2()/m_len_unit)  << "\""
-	  << " rmax1=\""  << check_null(sh->GetRmax1()/m_len_unit)  << "\""
-	  << " rmax2=\""  << check_null(sh->GetRmax2()/m_len_unit)  << "\""
-	  << " z=\""      << check_null(sh->GetDz()/m_len_unit)     << "\""
-	  << " startphi=\"" << check_null(sh->GetPhi1()/m_ang_unit) << "\""
-	  << " deltaphi=\"" << check_null((sh->GetPhi1()-sh->GetPhi1())/m_ang_unit) << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " aunit=\""  << m_ang_unit_nam             << "\""
+          << " rmin1=\""  << check_null(sh->GetRmin1()/m_len_unit)  << "\""
+          << " rmin2=\""  << check_null(sh->GetRmin2()/m_len_unit)  << "\""
+          << " rmax1=\""  << check_null(sh->GetRmax1()/m_len_unit)  << "\""
+          << " rmax2=\""  << check_null(sh->GetRmax2()/m_len_unit)  << "\""
+          << " z=\""      << check_null(sh->GetDz()/m_len_unit)     << "\""
+          << " startphi=\"" << check_null(sh->GetPhi1()/m_ang_unit) << "\""
+          << " deltaphi=\"" << check_null((sh->GetPhi1()-sh->GetPhi1())/m_ang_unit) << "\""
+          << "/>";
     }
     else if ( cl == TGeoParaboloid::Class() )  {
       const TGeoParaboloid* sh = (const TGeoParaboloid*) shape;
       log << "<paraboloid" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " rlo=\""    << sh->GetRlo()/m_len_unit    << "\""
-	  << " rhi=\""    << sh->GetRhi()/m_len_unit    << "\""
-	  << " z=\""      << sh->GetDz()/m_len_unit     << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " rlo=\""    << sh->GetRlo()/m_len_unit    << "\""
+          << " rhi=\""    << sh->GetRhi()/m_len_unit    << "\""
+          << " z=\""      << sh->GetDz()/m_len_unit     << "\""
+          << "/>";
     }
     else if ( cl == TGeoSphere::Class() )   {
       const TGeoSphere* sh = (const TGeoSphere*) shape;
       log << "<sphere" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " aunit=\""  << m_ang_unit_nam             << "\""
-	  << " rmin=\""   << sh->GetRmin()/m_len_unit   << "\""
-	  << " rmax=\""   << sh->GetRmax()/m_len_unit   << "\""
-	  << " startphi=\""   << sh->GetPhi1()/m_ang_unit << "\""
-	  << " deltaphi=\""   << (sh->GetPhi1()-sh->GetPhi1())/m_ang_unit << "\""
-	  << " starttheta=\"" << sh->GetTheta1()/m_ang_unit << "\""
-	  << " deltatheta=\"" << (sh->GetTheta1()-sh->GetTheta1())/m_ang_unit << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " aunit=\""  << m_ang_unit_nam             << "\""
+          << " rmin=\""   << sh->GetRmin()/m_len_unit   << "\""
+          << " rmax=\""   << sh->GetRmax()/m_len_unit   << "\""
+          << " startphi=\""   << sh->GetPhi1()/m_ang_unit << "\""
+          << " deltaphi=\""   << (sh->GetPhi1()-sh->GetPhi1())/m_ang_unit << "\""
+          << " starttheta=\"" << sh->GetTheta1()/m_ang_unit << "\""
+          << " deltatheta=\"" << (sh->GetTheta1()-sh->GetTheta1())/m_ang_unit << "\""
+          << "/>";
     }
     else if ( cl == TGeoTorus::Class() )   {
       const TGeoTorus* sh = (const TGeoTorus*) shape;
       log << "<torus" << nam
-	  << " lunit=\""  << m_len_unit_nam             << "\""
-	  << " aunit=\""  << m_ang_unit_nam             << "\""
-	  << " rtor=\""   << sh->GetR()/m_len_unit      << "\""
-	  << " rmin=\""   << sh->GetRmin()/m_len_unit   << "\""
-	  << " rmax=\""   << sh->GetRmax()/m_len_unit   << "\""
-	  << " startphi=\""   << sh->GetPhi1()/m_ang_unit << "\""
-	  << " deltaphi=\""   << sh->GetDphi()/m_ang_unit << "\""
-	  << "/>";
+          << " lunit=\""  << m_len_unit_nam             << "\""
+          << " aunit=\""  << m_ang_unit_nam             << "\""
+          << " rtor=\""   << sh->GetR()/m_len_unit      << "\""
+          << " rmin=\""   << sh->GetRmin()/m_len_unit   << "\""
+          << " rmax=\""   << sh->GetRmax()/m_len_unit   << "\""
+          << " startphi=\""   << sh->GetPhi1()/m_ang_unit << "\""
+          << " deltaphi=\""   << sh->GetDphi()/m_ang_unit << "\""
+          << "/>";
     }
     else if ( cl == TGeoArb8::Class() )   {
       TGeoArb8* sh = (TGeoArb8*) shape;
@@ -430,15 +432,15 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleSolid(Solid solid) cons
       const TGeoXtru* sh = (const TGeoXtru*) shape;
       log << "<xtru" << nam << ">" << newline;
       for (int i = 0; i < sh->GetNvert(); i++) {
-	log << " <twoDimVertex x=\"" << sh->GetX(i)/m_len_unit << "\""
-	    << "\" y=\"" << sh->GetY(i)/m_len_unit << "\"/>" << newline;
+        log << " <twoDimVertex x=\"" << sh->GetX(i)/m_len_unit << "\""
+            << "\" y=\"" << sh->GetY(i)/m_len_unit << "\"/>" << newline;
       }
       for (int i = 0; i < sh->GetNz(); i++) {
-	log << " <section zOrder=\"" << i << "\""
-	    << " scalingFactor=\"" << sh->GetScale(i) << "\""
-	    << " zPosition=\"" << sh->GetZ(i)/m_len_unit << "\""
-	    << " xOffset=\""   << sh->GetXOffset(i)/m_len_unit << "\""
-	    << " yOffset=\""   << sh->GetYOffset(i)/m_len_unit << "\"/>" << newline;
+        log << " <section zOrder=\"" << i << "\""
+            << " scalingFactor=\"" << sh->GetScale(i) << "\""
+            << " zPosition=\"" << sh->GetZ(i)/m_len_unit << "\""
+            << " xOffset=\""   << sh->GetXOffset(i)/m_len_unit << "\""
+            << " yOffset=\""   << sh->GetYOffset(i)/m_len_unit << "\"/>" << newline;
       }
       log << "</xtru>";
     }
@@ -460,57 +462,61 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleSolid(Solid solid) cons
         str_oper = "intersection";
 
       if ( left->IsA() == TGeoScaledShape::Class() && right->IsA() == TGeoBBox::Class() )   {
-	const auto* scaled = (TGeoScaledShape*)left;
-	const auto* sphere = (TGeoSphere*)scaled->GetShape();
-	const auto* box    = (TGeoBBox*)right;
-	if ( scaled->IsA() == TGeoSphere::Class() && oper == TGeoBoolNode::kGeoIntersection )   {
-	  Double_t sx    = scaled->GetScale()->GetScale()[0];
-	  Double_t sy    = scaled->GetScale()->GetScale()[1];
-	  Double_t ax    = sx * sphere->GetRmax();
-	  Double_t by    = sy * sphere->GetRmax();
-	  Double_t cz    = sphere->GetRmax();
-	  Double_t dz    = box->GetDZ();
-	  Double_t zorig = box->GetOrigin()[2];
-	  Double_t zcut2 = dz + zorig;
-	  Double_t zcut1 = 2 * zorig - zcut2;
-	  log << "<ellipsoid" << nam
-	      << " lunit=\""  << m_len_unit_nam     << "\""
-	      << " ax=\""     << ax/m_len_unit      << "\""
-	      << " by=\""     << by/m_len_unit      << "\""
-	      << " cz=\""     << cz/m_len_unit      << "\""
-	      << " zcut1=\""  << zcut1/m_len_unit   << "\""
-	      << " zcut2=\""  << zcut2/m_len_unit   << "\"/>";
-	  iso = geo.emplace(solid, make_entry(log)).first;
-	  return iso->second;
-	}
+        const auto* scaled = (TGeoScaledShape*)left;
+        const auto* sphere = (TGeoSphere*)scaled->GetShape();
+        const auto* box    = (TGeoBBox*)right;
+        if ( scaled->IsA() == TGeoSphere::Class() && oper == TGeoBoolNode::kGeoIntersection )   {
+          Double_t sx    = scaled->GetScale()->GetScale()[0];
+          Double_t sy    = scaled->GetScale()->GetScale()[1];
+          Double_t ax    = sx * sphere->GetRmax();
+          Double_t by    = sy * sphere->GetRmax();
+          Double_t cz    = sphere->GetRmax();
+          Double_t dz    = box->GetDZ();
+          Double_t zorig = box->GetOrigin()[2];
+          Double_t zcut2 = dz + zorig;
+          Double_t zcut1 = 2 * zorig - zcut2;
+          log << "<ellipsoid" << nam
+              << " lunit=\""  << m_len_unit_nam     << "\""
+              << " ax=\""     << ax/m_len_unit      << "\""
+              << " by=\""     << by/m_len_unit      << "\""
+              << " cz=\""     << cz/m_len_unit      << "\""
+              << " zcut1=\""  << zcut1/m_len_unit   << "\""
+              << " zcut2=\""  << zcut2/m_len_unit   << "\"/>";
+          iso = geo.emplace(solid, make_entry(log)).first;
+          return iso->second;
+        }
       }
       // The name cannot be used. We hence use the full hash code
       // for the left and right side shapes!
       const entry_t&  ent_left  = handleSolid(Solid(left));
       const entry_t&  ent_right = handleSolid(Solid(right));
+      const entry_t&  ent_pos_left = handlePosition(mat_left);
+      const entry_t&  ent_rot_left = handleRotation(mat_left);
+      const entry_t&  ent_pos_right = handlePosition(mat_right);
+      const entry_t&  ent_rot_right = handleRotation(mat_right);
       log << "<" << str_oper << nam
-	  << " lunit=\"" << m_len_unit_nam << "\""
-	  << " aunit=\"" << m_ang_unit_nam << "\">" << newline
-	  << " <first ref=\"" << (void*)ent_left.hash << "\""  << ">" << newline
-	  << "  " << handlePosition(mat_left).data << newline
-	  << "  " << handleRotation(mat_left).data << newline
-	  << " </first>" << newline
-	  << " <second ref=\"" << (void*)ent_right.hash << "\"" << ">" << newline
-	  << "  " << handlePosition(mat_right).data << newline
-	  << "  " << handleRotation(mat_right).data << newline
-	  << " </second>" << newline
-	  << "</" << str_oper << ">";
+          << " lunit=\"" << m_len_unit_nam << "\""
+          << " aunit=\"" << m_ang_unit_nam << "\">" << newline
+          << " <first ref=\"" << (void*)ent_left.hash << "\""  << ">" << newline
+          << "  " << ent_pos_left.hash << newline
+          << "  " << ent_rot_left.hash << newline
+          << " </first>" << newline
+          << " <second ref=\"" << (void*)ent_right.hash << "\"" << ">" << newline
+          << "  " << ent_pos_right.hash << newline
+          << "  " << ent_rot_right.hash << newline
+          << " </second>" << newline
+          << "</" << str_oper << ">";
     }
     else if ( shape->IsA() == TGeoScaledShape::Class() )   {
       const TGeoScaledShape* sh  = (TGeoScaledShape*)shape;
       const TGeoShape*       org = sh->GetShape();
       const double*          scl = sh->GetScale()->GetScale();
       log << "<scaled_shape" << nam
-	  << " sx=\"" << scl[0] << "\""
-	  << " sy=\"" << scl[1] << "\""
-	  << " sz=\"" << scl[2] << "\">" << newline
-	  << "  " << handleSolid(Solid(org)).data << newline
-	  << "</scaled_shape>";
+          << " sx=\"" << scl[0] << "\""
+          << " sy=\"" << scl[1] << "\""
+          << " sz=\"" << scl[2] << "\">" << newline
+          << "  " << handleSolid(Solid(org)).hash << newline
+          << "</scaled_shape>";
     }
     else if ( shape->IsA() == TGeoShapeAssembly::Class() )   {
       log << "<shape_assembly " << nam << "\"/>";
@@ -577,10 +583,10 @@ const DetectorChecksum::entry_t& DetectorChecksum::handlePosition(const TGeoMatr
     const double* tr = trafo->GetTranslation();
     std::stringstream log = logger();
     log << "<position"
-	<< " unit=\"" << m_len_unit_nam << "\""
-	<< " x=\"" << check_null(tr[0]/m_len_unit)  << "\""
-	<< " y=\"" << check_null(tr[1]/m_len_unit)  << "\""
-	<< " z=\"" << check_null(tr[2]/m_len_unit)  << "\"";
+        << " unit=\"" << m_len_unit_nam << "\""
+        << " x=\"" << check_null(tr[0]/m_len_unit)  << "\""
+        << " y=\"" << check_null(tr[1]/m_len_unit)  << "\""
+        << " z=\"" << check_null(tr[2]/m_len_unit)  << "\"";
     log << "/>";
     ipo = geo.emplace(trafo, make_entry(log)).first;
   }
@@ -595,11 +601,11 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleRotation(const TGeoMatr
     XYZAngles    rot = detail::matrix::_xyzAngles(trafo->GetRotationMatrix());
     std::stringstream log = logger();
     log << "<rotation"
-	<< " unit=\"" << m_ang_unit_nam  << "\""
+        << " unit=\"" << m_ang_unit_nam  << "\""
         << " x=\"" << check_null(rot.X()/m_ang_unit) << "\""
-	<< " y=\"" << check_null(rot.Y()/m_ang_unit) << "\""
-	<< " z=\"" << check_null(rot.Z()/m_ang_unit) << "\""
-	<< "/>";
+        << " y=\"" << check_null(rot.Y()/m_ang_unit) << "\""
+        << " z=\"" << check_null(rot.Z()/m_ang_unit) << "\""
+        << "/>";
     iro = geo.emplace(trafo, make_entry(log)).first;
   }
   return iro->second;
@@ -617,9 +623,9 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleVis(VisAttr attr) const
     attr.rgb(red, green, blue);
 
     log << "<vis"
-	<< " name=\""           << attr.name()          << "\""
-	<< " visible=\""        << attr.visible()       << "\""
-	<< " show_daughters=\"" << attr.showDaughters() << "\"";
+        << " name=\""           << attr.name()          << "\""
+        << " visible=\""        << attr.visible()       << "\""
+        << " show_daughters=\"" << attr.showDaughters() << "\"";
     if (style == VisAttr::SOLID)
       log << " line_style=\"unbroken\"";
     else if (style == VisAttr::DASHED)
@@ -629,10 +635,10 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleVis(VisAttr attr) const
     else if (draw == VisAttr::WIREFRAME)
       log << " line_style=\"wireframe\"";
     log << "<color"
-	<< " alpha=\"" << attr.alpha()
-	<< " R=\""     << red    << "\""
-	<< " B=\""     << blue   << "\""
-	<< " G=\""     << green  << "\"/>" << newline;
+        << " alpha=\"" << attr.alpha()
+        << " R=\""     << red    << "\""
+        << " B=\""     << blue   << "\""
+        << " G=\""     << green  << "\"/>" << newline;
     log << "</vis>";
     ivi = geo.emplace(attr, make_entry(log)).first;
   }
@@ -646,11 +652,11 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleRegion(Region region) c
   if ( ire == geo.end() )   {
     std::stringstream log = logger();
     log << "<region name=\""       << region.name() << "\""
-	<< " store_secondaries=\"" << (region.storeSecondaries() ? 1 : 0) << "\""
-	<< " cut=\""               << region.cut() << "\""
-	<< " eunit=\""             << m_ene_unit_nam << "\""
-	<< " lunit=\""             << m_len_unit_nam << "\""
-	<< "/>";
+        << " store_secondaries=\"" << (region.storeSecondaries() ? 1 : 0) << "\""
+        << " cut=\""               << region.cut() << "\""
+        << " eunit=\""             << m_ene_unit_nam << "\""
+        << " lunit=\""             << m_len_unit_nam << "\""
+        << "/>";
     ire = geo.emplace(region, make_entry(log)).first;
   }
   return ire->second;
@@ -666,10 +672,10 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleLimitSet(LimitSet lim)
     log << "<limitset name=\""     << lim.name() << "\">" << newline;
     for (const auto& limit : obj)  {
       log << "<limit name=\""      << limit.name   << "\""
-	  << "  unit=\""           << limit.unit   << "\""
-	  << "  value=\""          << limit.value  << "\""
-	  << " particles=\""       << limit.particles << "\""
-	  << "/>" << newline;
+          << "  unit=\""           << limit.unit   << "\""
+          << "  value=\""          << limit.value  << "\""
+          << " particles=\""       << limit.particles << "\""
+          << "/>" << newline;
     }
     log << "</limitSet>";
     ili = geo.emplace(lim, make_entry(log)).first;
@@ -687,20 +693,20 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleAlignment(Alignment ali
     data.delta.pivot.GetComponents(x, y, z);
     log << "<nominal>" << newline;
     log << "<translation"
-	<< " unit=\""  << m_len_unit_nam << "\""
-	<< " x=\""     << data.delta.translation.X()/m_len_unit  << "\""
-	<< " y=\""     << data.delta.translation.Y()/m_len_unit  << "\""
-	<< " z=\""     << data.delta.translation.Z()/m_len_unit  << "\"/>" << newline;
+        << " unit=\""  << m_len_unit_nam << "\""
+        << " x=\""     << data.delta.translation.X()/m_len_unit  << "\""
+        << " y=\""     << data.delta.translation.Y()/m_len_unit  << "\""
+        << " z=\""     << data.delta.translation.Z()/m_len_unit  << "\"/>" << newline;
     log << "<pivot"
-	<< " unit=\""  << m_len_unit_nam << "\""
-   	<< " x=\""     << x / m_len_unit << "\""
-	<< " y=\""     << y / m_len_unit << "\""
-	<< " z=\""     << z / m_len_unit << "\"/>" << newline;
+        << " unit=\""  << m_len_unit_nam << "\""
+        << " x=\""     << x / m_len_unit << "\""
+        << " y=\""     << y / m_len_unit << "\""
+        << " z=\""     << z / m_len_unit << "\"/>" << newline;
     log << "<rotation"
-	<< " unit=\""  << m_len_unit_nam << "\""
-	<< " theta=\"" << data.delta.rotation.Theta()/m_ang_unit  << "\""
-	<< " phi=\""   << data.delta.rotation.Phi()/m_len_unit  << "\""
-	<< " psi=\""   << data.delta.rotation.Psi()/m_len_unit  << "\"/>" << newline;
+        << " unit=\""  << m_len_unit_nam << "\""
+        << " theta=\"" << data.delta.rotation.Theta()/m_ang_unit  << "\""
+        << " phi=\""   << data.delta.rotation.Phi()/m_len_unit  << "\""
+        << " psi=\""   << data.delta.rotation.Psi()/m_len_unit  << "\"/>" << newline;
     log << "</nominal>";
     ial = geo.emplace(alignment, make_entry(log)).first;
   }
@@ -743,8 +749,8 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleVolume(Volume volume) c
       const auto& solid_ent = handleSolid(sh);
       tag = "assembly";
       log << "<" << tag << nam
-	  << " solid=\""         << refName(sh)           << "\""
-	  << " solid_hash=\""    << (void*)solid_ent.hash << "\"";
+          << " solid=\""         << refName(sh)           << "\""
+          << " solid_hash=\""    << (void*)solid_ent.hash << "\"";
     }
     else {
       TGeoMedium*   med = v->GetMedium();
@@ -753,9 +759,9 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleVolume(Volume volume) c
       const auto& solid_ent = handleSolid(sh);
       tag = "volume";
       log << "<" << tag << nam
-	  << " material=\""      << refName(med)          << "\""
-	  << " solid=\""         << refName(sh)           << "\""
-	  << " solid_hash=\""    << (void*)solid_ent.hash << "\"";
+          << " material=\""      << refName(med)          << "\""
+          << " solid=\""         << refName(sh)           << "\""
+          << " solid_hash=\""    << (void*)solid_ent.hash << "\"";
     }
     collectVolume(volume);
     auto reg = volume.region();
@@ -776,7 +782,7 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleVolume(Volume volume) c
       for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
         TGeoNode* node = reinterpret_cast<TGeoNode*>(dau->At(i));
         const auto& ent = handlePlacement(node);
-	log << " <physvol name=\"" << refName(node) << " hash=\"" << (void*)ent.hash << "\"/>" << newline;
+        log << " <physvol name=\"" << refName(node) << " hash=\"" << (void*)ent.hash << "\"/>" << newline;
       }
       log << "</" << tag << ">";
     }
@@ -802,22 +808,22 @@ const DetectorChecksum::entry_t& DetectorChecksum::handlePlacement(PlacedVolume
     const auto& vol_ent = handleVolume(volume);
     std::stringstream  log = logger();
     log << "<physvol" << attr_name(node)
-	<< " volume=\"" << refName(volume) << "\"";
+        << " volume=\"" << refName(volume) << "\"";
     log << " volume_hash=\"" << (void*)vol_ent.hash << "\"";
     log << ">" << newline;
     if ( matrix )   {
-      log << " " << handlePosition(matrix).data << newline;
+      log << " " << handlePosition(matrix).hash << newline;
       if ( matrix->IsRotation() )  {
-	log << " " << handleRotation(matrix).data << newline;
+        log << " " << handleRotation(matrix).hash << newline;
       }
     }
     if ( node.data() )   {
       const auto& ids = node.volIDs();
       for (const auto& vid : ids )
-	log << " <physvolid"
-	    << " name=\""  << vid.first  << "\""
-	    << " value=\"" << vid.second << "\""
-	    << "/>" << newline;
+        log << " <physvolid"
+            << " name=\""  << vid.first  << "\""
+            << " value=\"" << vid.second << "\""
+            << "/>" << newline;
     }
     log << "</physvol>";
     ipl = geo.emplace(node, make_entry(log)).first;
@@ -833,15 +839,15 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleDetElement(DetElement d
     const auto& place = handlePlacement(det.placement());
     const auto& par = det.parent().isValid() ? handleDetElement(det.parent()) : empty_entry;
     log << "<detelement"
-	<< " name=\""          << det.name()        << "\""
-	<< " id=\""            << det.id()          << "\""
-	<< " type=\""          << det.type()        << "\""
-	<< " key=\""           << det.key()         << "\""
-	<< " parent=\""        << (void*)par.hash   << "\""
-	<< " flag=\""          << det.typeFlag()    << "\""
-	<< " combineHits=\""   << det.combineHits() << "\""
-	<< " placement=\""     << (void*)place.hash << "\""
-	<< "/>";
+        << " name=\""          << det.name()        << "\""
+        << " id=\""            << det.id()          << "\""
+        << " type=\""          << det.type()        << "\""
+        << " key=\""           << det.key()         << "\""
+        << " parent=\""        << (void*)par.hash   << "\""
+        << " flag=\""          << det.typeFlag()    << "\""
+        << " combineHits=\""   << det.combineHits() << "\""
+        << " placement=\""     << (void*)place.hash << "\""
+        << "/>";
     dit = geo.emplace(det, make_entry(log)).first;
   }
   return dit->second;
@@ -855,18 +861,18 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleSensitive(SensitiveDete
     if ( isi == geo.end() ) {
       std::stringstream log = logger();
       log << "<sensitive_detector"
-	  << " name=\""            << refName(sd)                  << "\""
-	  << " type=\""            << sd.type()                    << "\""
-	  << " ecut=\""            << sd.energyCutoff()/m_ene_unit << "\""
-	  << " eunit=\""           << m_ene_unit_nam               << "\""
-	  << " hits_collection=\"" << sd.hitsCollection()          << "\""
-	  << " combine_hits=\""    << sd.combineHits()             << "\"";
+          << " name=\""            << refName(sd)                  << "\""
+          << " type=\""            << sd.type()                    << "\""
+          << " ecut=\""            << sd.energyCutoff()/m_ene_unit << "\""
+          << " eunit=\""           << m_ene_unit_nam               << "\""
+          << " hits_collection=\"" << sd.hitsCollection()          << "\""
+          << " combine_hits=\""    << sd.combineHits()             << "\"";
       Readout ro = sd.readout();
       if ( ro.isValid() ) {
-	const auto& ro_ent = handleIdSpec(ro.idSpec());
-	log << " iddescriptor=\"" << (void*)ro_ent.hash            << "\"";
-	const auto& seg_ent = handleSegmentation(ro.segmentation());
-	log << " segmentation=\"" << (void*)seg_ent.hash           << "\"";
+        const auto& ro_ent = handleIdSpec(ro.idSpec());
+        log << " iddescriptor=\"" << (void*)ro_ent.hash            << "\"";
+        const auto& seg_ent = handleSegmentation(ro.segmentation());
+        log << " segmentation=\"" << (void*)seg_ent.hash           << "\"";
       }
       log << "/>";
       isi = geo.emplace(sd, make_entry(log)).first;
@@ -886,21 +892,21 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleSegmentation(Segmentati
       std::stringstream log = logger();
       const auto& p = seg.parameters();
       log << "<segmentation" << attr_name(seg)
-	  << " type=\"" << seg.type() << "\">" << newline;
+          << " type=\"" << seg.type() << "\">" << newline;
       log << " <parameters>" << newline;
       for ( const auto& v : p )  {
-	log << "  <parameter";
-	log << " name=\"" << v->name() << "\""
-	    << " type=\"" << v->type() << "\"";
-	if ( v->unitType() == param_t::LengthUnit )
-	  log << " value=\"" << _toDouble(v->value())/m_len_unit << "\""
-	      << " unit=\""  << m_len_unit_nam << "\"";
-	else if ( v->unitType() == param_t::AngleUnit )
-	  log << " value=\"" << _toDouble(v->value())/m_ang_unit << "\""
-	      << " unit=\""  << m_ang_unit_nam << "\"";
-	else
-	  log << " value=\"" << v->value() << "\"";
-	log << "/>" << newline;
+        log << "  <parameter";
+        log << " name=\"" << v->name() << "\""
+            << " type=\"" << v->type() << "\"";
+        if ( v->unitType() == param_t::LengthUnit )
+          log << " value=\"" << _toDouble(v->value())/m_len_unit << "\""
+              << " unit=\""  << m_len_unit_nam << "\"";
+        else if ( v->unitType() == param_t::AngleUnit )
+          log << " value=\"" << _toDouble(v->value())/m_ang_unit << "\""
+              << " unit=\""  << m_ang_unit_nam << "\"";
+        else
+          log << " value=\"" << v->value() << "\"";
+        log << "/>" << newline;
       }
       log << " </parameters>" << newline;
       log << "</segmentatoin>";
@@ -921,11 +927,11 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleIdSpec(IDDescriptor id_
       std::stringstream log = logger();
       log << "<id name=\"" << refName(id_spec) << "\">" << newline;
       for (const auto& i : fm )  {
-	const BitFieldElement* f = i.second;
-	log << " <idfield label=\"" << f->name()       << "\""
-	    << " signed=\""         << true_false(f->isSigned()) << "\""
-	    << " length=\""         << f->width()      << "\""
-	    << " start=\""          << f->offset()     << "\"/>" << newline;
+        const BitFieldElement* f = i.second;
+        log << " <idfield label=\"" << f->name()       << "\""
+            << " signed=\""         << true_false(f->isSigned()) << "\""
+            << " length=\""         << f->width()      << "\""
+            << " start=\""          << f->offset()     << "\"/>" << newline;
       }
       log << "</id>";
       iid = geo.emplace(id_spec, make_entry(log)).first;
@@ -953,8 +959,8 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleField(OverlayedField f)
       PluginDebug dbg;
       PluginService::Create<NamedObject*>(type + "_Convert2Detector", &m_detDesc, &field, &fld);
       throw std::runtime_error("Failed to locate plugin to convert electromagnetic field:"
-			       + std::string(f->GetName()) + " of type " + type + ". "
-			       + dbg.missingFactory(type));
+                               + std::string(f->GetName()) + " of type " + type + ". "
+                               + dbg.missingFactory(type));
     }
 #endif
     log << "</field>";
@@ -967,13 +973,13 @@ const DetectorChecksum::entry_t& DetectorChecksum::handleField(OverlayedField f)
 const DetectorChecksum::entry_t& DetectorChecksum::handleHeader() const {
   GeometryInfo& geo = data();
   Header hdr = m_detDesc.header();
-  if ( hdr.isValid() && geo.header.data.empty() )  {
+  if ( hdr.isValid() && 0 == geo.header.hash )  {
     std::stringstream log = logger();
     log << "<header name=\"" << hdr.name() << "\">"
-	<< "<autor name=\""  << hdr.author() << "\"/>"
-	<< "<generator version=\"" << hdr.version() << "\"" << " url=\"" << hdr.url() << "\"/>"
-	<< "<comment>" << hdr.comment() << "</comment>"
-	<< "</header>";
+        << "<autor name=\""  << hdr.author() << "\"/>"
+        << "<generator version=\"" << hdr.version() << "\"" << " url=\"" << hdr.url() << "\"/>"
+        << "<comment>" << hdr.comment() << "</comment>"
+        << "</header>";
     geo.header = make_entry(log);
     return geo.header;
   }
@@ -1022,8 +1028,8 @@ std::vector<PlacedVolume> _get_path(PlacedVolume node, const std::set<PlacedVolu
       TGeoNode* n = reinterpret_cast<TGeoNode*>(dau->At(i));
       auto cont = _get_path(n, match);
       if ( !cont.empty() )   {
-	cont.emplace_back(node);
-	return cont;
+        cont.emplace_back(node);
+        return cont;
       }
     }
     return { };
@@ -1063,22 +1069,22 @@ void DetectorChecksum::checksumDetElement(int lvl, DetElement det, hashes_t& has
     if ( hash_readout )   {
       SensitiveDetector sd = m_detDesc.sensitiveDetector(det.name());
       if ( sd.isValid() )   {
-	Readout ro = sd.readout();
-	const auto& sens_ent = handleSensitive(sd);
-	hashes.push_back(sens_ent.hash);
-	hash_debug(" .sensitive", sens_ent);
-	if ( ro.isValid() ) {
-	  const auto& id_ent = handleIdSpec(ro.idSpec());
-	  const auto& seg_ent = handleSegmentation(ro.segmentation());
-
-	  hash_idx_id = hashes.size();
-	  hashes.push_back(id_ent.hash);
-	  hash_idx_seg = hashes.size();
-	  hashes.push_back(seg_ent.hash);
-
-	  hash_debug(" .iddesc",  id_ent);
-	  hash_debug(" .readout", seg_ent);
-	}
+        Readout ro = sd.readout();
+        const auto& sens_ent = handleSensitive(sd);
+        hashes.push_back(sens_ent.hash);
+        hash_debug(" .sensitive", sens_ent);
+        if ( ro.isValid() ) {
+          const auto& id_ent = handleIdSpec(ro.idSpec());
+          const auto& seg_ent = handleSegmentation(ro.segmentation());
+
+          hash_idx_id = hashes.size();
+          hashes.push_back(id_ent.hash);
+          hash_idx_seg = hashes.size();
+          hashes.push_back(seg_ent.hash);
+
+          hash_debug(" .iddesc",  id_ent);
+          hash_debug(" .readout", seg_ent);
+        }
       }
     }
 
@@ -1094,8 +1100,8 @@ void DetectorChecksum::checksumDetElement(int lvl, DetElement det, hashes_t& has
     for( const auto& pv : child_places )   {
       auto chain = _get_path(pv, child_places);
       for( std::size_t i=0; i < chain.size()-1; ++i )   {
-	checksumPlacement(chain[i], hashes, false);
-	hashed_places.insert(chain[i]);
+        checksumPlacement(chain[i], hashes, false);
+        hashed_places.insert(chain[i]);
       }
       if ( !chain.empty() ) hashed_places.insert(chain[chain.size()-1]);
     }
@@ -1104,10 +1110,10 @@ void DetectorChecksum::checksumDetElement(int lvl, DetElement det, hashes_t& has
     const TObjArray* dau = det_pv.volume()->GetNodes();
     if (dau && dau->GetEntries() > 0) {
       for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
-	PlacedVolume pv = reinterpret_cast<TGeoNode*>(dau->At(i));
-	if ( hashed_places.find(pv) == hashed_places.end() )  {
-	  checksumPlacement(det_pv, hashes, true);
-	}
+        PlacedVolume pv = reinterpret_cast<TGeoNode*>(dau->At(i));
+        if ( hashed_places.find(pv) == hashed_places.end() )  {
+          checksumPlacement(det_pv, hashes, true);
+        }
       }
     }
 
@@ -1115,7 +1121,7 @@ void DetectorChecksum::checksumDetElement(int lvl, DetElement det, hashes_t& has
     std::size_t hash_idx_children = hashes.size();
     if ( recursive )   {
       for ( const auto& c : det.children() )
-	checksumDetElement(lvl+1, c.second, hashes, recursive);
+        checksumDetElement(lvl+1, c.second, hashes, recursive);
     }
 
     /// All done: Some debugging printout
@@ -1123,47 +1129,47 @@ void DetectorChecksum::checksumDetElement(int lvl, DetElement det, hashes_t& has
       std::stringstream str;
       hash_t code = detail::hash64(&hashes[hash_idx_de], (hash_idx_ro-hash_idx_de)*sizeof(hash_t));
       str << "+++ " << std::setw(4) << std::left << lvl
-	  << " " << std::setw(36) << std::left << det.name() << " de"
-	  << " " << std::setfill('0') << std::setw(16) << std::hex << code;
+          << " " << std::setw(36) << std::left << det.name() << " de"
+          << " " << std::setfill('0') << std::setw(16) << std::hex << code;
       code = detail::hash64(&hashes[hash_idx_pv], sizeof(hash_t));
       str << " " << std::setfill(' ') << std::setw(9) << std::left << "+place"
-	  << " " << std::setfill('0') << std::setw(16) << std::hex << code;
+          << " " << std::setfill('0') << std::setw(16) << std::hex << code;
       code = detail::hash64(&hashes[hash_idx_daughters], (hash_idx_children-hash_idx_daughters)*sizeof(hash_t));
       if ( !(child_places.empty() && hashed_places.empty()) )
-	str << " " << std::setfill(' ') << std::setw(10) << std::left << "+daughters"
-	    << " " << std::setfill('0') << std::setw(16) << std::hex << code;
+        str << " " << std::setfill(' ') << std::setw(10) << std::left << "+daughters"
+            << " " << std::setfill('0') << std::setw(16) << std::hex << code;
       code = detail::hash64(&hashes[hash_idx_children], (hashes.size()-hash_idx_children)*sizeof(hash_t));
       if ( !det.children().empty() )
-	str << " " << std::setfill(' ') << std::setw(9) << std::left << "+children"
-	    << " " << std::setfill('0') << std::setw(16) << std::hex << code;
+        str << " " << std::setfill(' ') << std::setw(9) << std::left << "+children"
+            << " " << std::setfill('0') << std::setw(16) << std::hex << code;
       std::cout << str.str() << std::endl;
       if ( hash_idx_pv-hash_idx_ro > 0 )  {
-	str.str("");
-	str << std::setfill(' ') << "+++ " << std::setw(4) << std::left << lvl
-	    << " " << std::setw(56) << std::left << " ";
-	code = detail::hash64(&hashes[hash_idx_ro], (hash_idx_pv-hash_idx_ro)*sizeof(hash_t));
-	str << " " << std::setfill(' ') << std::setw(9) << std::left << "+readout"
-	    << " " << std::setfill('0') << std::setw(16) << std::hex << code;
-	if ( hash_idx_id > 0 )  {
-	  code = detail::hash64(&hashes[hash_idx_id], sizeof(hash_t));
-	  str << " " << std::setfill(' ') << std::setw(10) << std::left << "+iddesc"
-	      << " " << std::setfill('0') << std::setw(16) << std::hex << code;
-	}
-	if ( hash_idx_seg > 0 )  {
-	  code = detail::hash64(&hashes[hash_idx_seg], sizeof(hash_t));
-	  str << " " << std::setfill(' ') << std::setw(9) << std::left << "+segment"
-	      << " " << std::setfill('0') << std::setw(16) << std::hex << code;
-	}
-	std::cout << str.str() << std::endl;
+        str.str("");
+        str << std::setfill(' ') << "+++ " << std::setw(4) << std::left << lvl
+            << " " << std::setw(56) << std::left << " ";
+        code = detail::hash64(&hashes[hash_idx_ro], (hash_idx_pv-hash_idx_ro)*sizeof(hash_t));
+        str << " " << std::setfill(' ') << std::setw(9) << std::left << "+readout"
+            << " " << std::setfill('0') << std::setw(16) << std::hex << code;
+        if ( hash_idx_id > 0 )  {
+          code = detail::hash64(&hashes[hash_idx_id], sizeof(hash_t));
+          str << " " << std::setfill(' ') << std::setw(10) << std::left << "+iddesc"
+              << " " << std::setfill('0') << std::setw(16) << std::hex << code;
+        }
+        if ( hash_idx_seg > 0 )  {
+          code = detail::hash64(&hashes[hash_idx_seg], sizeof(hash_t));
+          str << " " << std::setfill(' ') << std::setw(9) << std::left << "+segment"
+              << " " << std::setfill('0') << std::setw(16) << std::hex << code;
+        }
+        std::cout << str.str() << std::endl;
       }
       if ( lvl == 0 )   {
-	str.str("");
-	code = detail::hash64(&hashes[0], hashes.size()*sizeof(hash_t));
-	str << std::setfill(' ') << "+++ " << std::setw(4) << std::left << lvl
-	    << " " << std::setw(39) << std::left << "Combined hash code"
-	    << " " << std::setfill('0') << std::setw(16) << std::hex << code
-	    << "  (" << std::dec << hashes.size() << " sub-codes)";
-	std::cout << str.str() << std::endl;
+        str.str("");
+        code = detail::hash64(&hashes[0], hashes.size()*sizeof(hash_t));
+        str << std::setfill(' ') << "+++ " << std::setw(4) << std::left << lvl
+            << " " << std::setw(39) << std::left << "Combined hash code"
+            << " " << std::setfill('0') << std::setw(16) << std::hex << code
+            << "  (" << std::dec << hashes.size() << " sub-codes)";
+        std::cout << str.str() << std::endl;
       }
     }
     return;
@@ -1193,10 +1199,10 @@ void DetectorChecksum::checksumPlacement(PlacedVolume pv, hashes_t& hashes, bool
     if ( recursive )   {
       const TObjArray* dau = v->GetNodes();
       if (dau && dau->GetEntries() > 0)   {
-	for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
-	  PlacedVolume node = reinterpret_cast<TGeoNode*>(dau->At(i));
-	  checksumPlacement(node, hashes, recursive);
-	}
+        for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
+          PlacedVolume node = reinterpret_cast<TGeoNode*>(dau->At(i));
+          checksumPlacement(node, hashes, recursive);
+        }
       }
     }
     return;
@@ -1210,7 +1216,7 @@ void DetectorChecksum::dump_elements()   const   {
   for(const auto& e : geo)   {
     Atom a = e.first;
     printout(ALWAYS, "DetectorChecksum", "+++ Element   %-32s    0x%016lx%s",
-	     a.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
+             a.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
   }
 }
 
@@ -1220,7 +1226,7 @@ void DetectorChecksum::dump_materials()   const   {
   for(const auto& e : geo)   {
     Material material = e.first;
     printout(ALWAYS, "DetectorChecksum", "+++ Material  %-32s    0x%016lx%s",
-	     material.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
+             material.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
   }
 }
 
@@ -1230,7 +1236,7 @@ void DetectorChecksum::dump_solids()   const   {
   for(const auto& e : geo)   {
     Solid solid = e.first;
     printout(ALWAYS, "DetectorChecksum", "+++ Solid     %-32s    0x%016lx%s",
-	     solid.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
+             solid.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
   }
 }
 
@@ -1240,7 +1246,7 @@ void DetectorChecksum::dump_volumes()   const   {
   for(const auto& e : geo)   {
     Volume volume = e.first;
     printout(ALWAYS, "DetectorChecksum", "+++ Volume    %-32s    0x%016lx%s",
-	     volume.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
+             volume.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
   }
 }
 
@@ -1250,7 +1256,7 @@ void DetectorChecksum::dump_placements()   const   {
   for(const auto& e : geo)   {
     PlacedVolume pv = e.first;
     printout(ALWAYS, "DetectorChecksum", "+++ Placement %-32s    0x%016lx%s",
-	     pv.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
+             pv.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
   }
 }
 
@@ -1260,7 +1266,7 @@ void DetectorChecksum::dump_detelements()   const   {
   for(const auto& e : geo)   {
     DetElement de = e.first;
     printout(ALWAYS, "DetectorChecksum", "+++ Detelement %-32s    0x%016lx%s",
-	     de.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
+             de.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
     if ( de.path() == "/world" )   {
       PlacedVolume pv  = de.placement();
       Volume       vol = pv.volume();
@@ -1270,11 +1276,11 @@ void DetectorChecksum::dump_detelements()   const   {
       const auto&   ep = handlePlacement(pv);
 
       printout(ALWAYS, "DetectorChecksum", "    Solid     %-32s    0x%016lx%s",
-	       sol.name(), es.hash, debug > 2 ? ("\n"+es.data).c_str() : "");
+               sol.name(), es.hash, debug > 2 ? ("\n"+es.data).c_str() : "");
       printout(ALWAYS, "DetectorChecksum", "    Volume    %-32s    0x%016lx%s",
-	       vol.name(), ev.hash, debug > 2 ? ("\n"+ev.data).c_str() : "");
+               vol.name(), ev.hash, debug > 2 ? ("\n"+ev.data).c_str() : "");
       printout(ALWAYS, "DetectorChecksum", "    Placement %-32s    0x%016lx%s",
-	       pv.name(),  ep.hash, debug > 2 ? ("\n"+ep.data).c_str() : "");
+               pv.name(),  ep.hash, debug > 2 ? ("\n"+ep.data).c_str() : "");
     }
   }
 }
@@ -1285,7 +1291,7 @@ void DetectorChecksum::dump_iddescriptors()   const   {
   for(const auto& e : geo)   {
     IDDescriptor v = e.first;
     printout(ALWAYS, "DetectorChecksum", "+++ ID desc   %-32s    0x%016lx%s",
-	     v.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
+             v.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
   }
 }
 
@@ -1295,7 +1301,7 @@ void DetectorChecksum::dump_segmentations()   const   {
   for(const auto& e : geo)   {
     Segmentation segmentation = e.first;
     printout(ALWAYS, "DetectorChecksum", "+++ Segment   %-32s    0x%016lx%s",
-	     segmentation.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
+             segmentation.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
   }
 }
 
@@ -1305,7 +1311,7 @@ void DetectorChecksum::dump_sensitives()   const   {
   for(const auto& e : geo)   {
     SensitiveDetector sd = e.first;
     printout(ALWAYS, "DetectorChecksum", "+++ Sens.Det. %-32s    0x%016lx%s",
-	     sd.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
+             sd.name(), e.second.hash, debug > 2 ? ("\n"+e.second.data).c_str() : "");
   }
 }
 
@@ -1315,6 +1321,7 @@ static long create_checksum(Detector& description, int argc, char** argv) {
   int dump_elements = 0, dump_materials = 0, dump_solids = 0, dump_volumes = 0;
   int dump_placements = 0, dump_detelements = 0, dump_sensitives = 0;
   int dump_iddesc = 0, dump_segmentations = 0;
+  int have_hash_strings = 0;
   std::string len_unit, ang_unit, ene_unit, dens_unit, atom_unit;
 
   for(int i = 0; i < argc && argv[i]; ++i)  {
@@ -1360,38 +1367,42 @@ static long create_checksum(Detector& description, int argc, char** argv) {
       dump_segmentations = 1;
     else if ( 0 == ::strncmp("-dump_iddescriptors",argv[i],10) )
       dump_iddesc = 1;
+    else if ( 0 == ::strncmp("-keep_hashes",argv[i],8) )
+      have_hash_strings = 1;
     else  {
       std::cout <<
         "Usage: -plugin DD4hepDetectorChecksum -arg [-arg]                             \n\n"
         "     -detector <string>     Top level DetElement path. Default: '/world'        \n"
-	"     -meshes                also hash the detector's meshed solids              \n"
-	"                            (may be sensitive to changes due to rounding)       \n"
-	"                            default: false                                      \n"
-	"     -readout               also hash the detector's readout properties         \n"
-	"                            (sensitive det, id desc, segmentation)              \n"
-	"                            default: false                                      \n"
-	"                                                                                \n"
-	"   Debugging: Dump individual hash codes (debug>=1)                             \n"
-	"   Debugging: and the hashed string (debug>2)                                   \n"
-	"     -dump_elements         Dump hashes of used elements                        \n"
-	"     -dump_materials        Dump hashes of used materials                       \n"
-	"     -dump_solids           Dump hashes of used solids                          \n"
-	"     -dump_volumes          Dump hashes of used volumes                         \n"
-	"     -dump_placements       Dump hashes of used placements                      \n"
-	"     -dump_detelements      Dump hashes of used detelements                     \n"
-	"     -dump_sensitive        Dump hashes of sensitive detectors                  \n"
-	"     -dump_readout          Dump hashes of readout entities                     \n"
-	"     -dump_iddescriptors    Dump hashes of ID descriptors                       \n"
-	"     -dump_segmentations    Dump hashes of readout segmentations                \n"
-	"                                                                                \n"
-	"   Modify units in the created hash strings (deprecated):                       \n"
-	"     -length_unit  <value>  Unit of length  as literal. default: mm             \n"
-	"     -angle_unit   <value>  Unit of angle   as literal. default: deg            \n"
-	"     -energy_unit  <value>  Unit of energy  as literal. default: GeV            \n"
-	"     -density_unit <value>  Unit of density as literal. default: g/cm3          \n"
-	"     -atomic_unit <value>   Unit of atomic weight as literal. default: g/mole   \n"
-	"                                                                                \n"
-	"     -debug <number>        Enable debug printouts.                             \n"
+        "     -meshes                also hash the detector's meshed solids              \n"
+        "                            (may be sensitive to changes due to rounding)       \n"
+        "                            default: false                                      \n"
+        "     -readout               also hash the detector's readout properties         \n"
+        "                            (sensitive det, id desc, segmentation)              \n"
+        "                            default: false                                      \n"
+        "     -keep_hash             keep the hash strings (not only hash codes.         \n"
+        "                            Useful for debugging and -dump_<x> options.         \n"
+        "                                                                                \n"
+        "   Debugging: Dump individual hash codes (debug>=1)                             \n"
+        "   Debugging: and the hashed string (debug>2)                                   \n"
+        "     -dump_elements         Dump hashes of used elements                        \n"
+        "     -dump_materials        Dump hashes of used materials                       \n"
+        "     -dump_solids           Dump hashes of used solids                          \n"
+        "     -dump_volumes          Dump hashes of used volumes                         \n"
+        "     -dump_placements       Dump hashes of used placements                      \n"
+        "     -dump_detelements      Dump hashes of used detelements                     \n"
+        "     -dump_sensitive        Dump hashes of sensitive detectors                  \n"
+        "     -dump_readout          Dump hashes of readout entities                     \n"
+        "     -dump_iddescriptors    Dump hashes of ID descriptors                       \n"
+        "     -dump_segmentations    Dump hashes of readout segmentations                \n"
+        "                                                                                \n"
+        "   Modify units in the created hash strings (deprecated):                       \n"
+        "     -length_unit  <value>  Unit of length  as literal. default: mm             \n"
+        "     -angle_unit   <value>  Unit of angle   as literal. default: deg            \n"
+        "     -energy_unit  <value>  Unit of energy  as literal. default: GeV            \n"
+        "     -density_unit <value>  Unit of density as literal. default: g/cm3          \n"
+        "     -atomic_unit <value>   Unit of atomic weight as literal. default: g/mole   \n"
+        "                                                                                \n"
+        "     -debug <number>        Enable debug printouts.                             \n"
         "     -help                  Print this help output                              \n"
         "     Arguments given: " << arguments(argc, argv) << std::endl << std::flush;
       ::exit(EINVAL);
@@ -1406,6 +1417,7 @@ static long create_checksum(Detector& description, int argc, char** argv) {
   if ( !dens_unit.empty() ) wr.m_densunit_nam = dens_unit;
   if ( !atom_unit.empty() ) wr.m_atomunit_nam = atom_unit;
   if ( newline ) wr.newline = "\n";
+  wr.have_hash_strings = have_hash_strings;
   wr.hash_meshes = meshes;
   wr.hash_readout = readout;
   wr.max_level = level;
@@ -1428,12 +1440,12 @@ static long create_checksum(Detector& description, int argc, char** argv) {
       hash_vec.clear();
       wr.checksumDetElement(0, de, hash_vec, true);
       if ( wr.debug > 2 )   {
-	std::cout << wr.debug_hash.str() << std::endl;
-	wr.debug_hash.str("");
+        std::cout << wr.debug_hash.str() << std::endl;
+        wr.debug_hash.str("");
       }
       checksum = detail::hash64(&hash_vec[0], hash_vec.size()*sizeof(DetectorChecksum::hash_t));
       printout(ALWAYS,"DetectorChecksum","+++ Checksum for %s 0x%016lx",
-	       de.path().c_str(), checksum);
+               de.path().c_str(), checksum);
       if ( make_dump ) goto MakeDump;
     }
     return 1;
@@ -1446,7 +1458,7 @@ static long create_checksum(Detector& description, int argc, char** argv) {
   checksum = detail::hash64(&hash_vec[0], hash_vec.size()*sizeof(DetectorChecksum::hash_t));
   if ( wr.debug > 2 ) std::cout << wr.debug_hash.str() << std::endl;
   printout(ALWAYS,"DetectorChecksum","+++ Checksum for %s 0x%016lx",
-	   de.path().c_str(), checksum);
+           de.path().c_str(), checksum);
 
  MakeDump:
   if ( make_dump )   {
diff --git a/DDCore/src/plugins/DetectorChecksum.h b/DDCore/src/plugins/DetectorChecksum.h
index 5474d3bbb..9a814b219 100644
--- a/DDCore/src/plugins/DetectorChecksum.h
+++ b/DDCore/src/plugins/DetectorChecksum.h
@@ -39,8 +39,8 @@ namespace dd4hep {
     public:
       using hash_t       = uint64_t;
       struct entry_t   {
-	hash_t   hash;
-	std::string  data;
+        hash_t      hash { 0 };
+        std::string data { "" };
       };
       using ElementMap       = std::map<Atom,              entry_t>;
       using MaterialMap      = std::map<Material,          entry_t>;
@@ -75,14 +75,14 @@ namespace dd4hep {
         VisMap           mapOfVis;
         LimitMap         mapOfLimits;
         IdSpecMap        mapOfIdSpecs;
-	SegmentationMap  mapOfSegmentations;
+        SegmentationMap  mapOfSegmentations;
         SensDetMap       mapOfSensDets;
         TrafoMap         mapOfPositions;
         TrafoMap         mapOfRotations;
         FieldMap         mapOfFields;
-	AlignmentMap     mapOfAlignments;
-	MapOfDetElements mapOfDetElements;
-	entry_t  header;
+        AlignmentMap     mapOfAlignments;
+        MapOfDetElements mapOfDetElements;
+        entry_t  header;
 
         GeometryInfo() = default;
       };
@@ -115,13 +115,15 @@ namespace dd4hep {
       /// Property: precision of hashed printouts
       mutable int precision     { 6 };
       /// Property: Include meshed solids in detector hash
-      int hash_meshes  { 0 };
+      int hash_meshes           { 0 };
       /// Property: Include readout property in detector hash
-      int hash_readout  { 0 };
+      int hash_readout          { 0 };
       /// Property: maximum depth level for printouts
-      int max_level     { 1 };
+      int max_level             { 1 };
+      /// Property: Keep hash-strings, not only hash values (debugging)
+      int have_hash_strings     { 0 };
       /// Property: debug level
-      int debug         { 4 };
+      int debug                 { 4 };
 
       GeometryInfo& data() const {
         return *m_dataPtr;
diff --git a/examples/CLICSiD/CMakeLists.txt b/examples/CLICSiD/CMakeLists.txt
index 9631b78e2..de3c1d9cf 100644
--- a/examples/CLICSiD/CMakeLists.txt
+++ b/examples/CLICSiD/CMakeLists.txt
@@ -133,7 +133,7 @@ endif()
 dd4hep_add_test_reg( CLICSiD_check_checksum_EcalBarrel
   COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_CLICSiD.sh"
   EXEC_ARGS  geoPluginRun -input ${DD4hep_ROOT}/DDDetectors/compact/SiD.xml -plugin DD4hepDetectorChecksum -readout -detector EcalBarrel
-  REGEX_PASS "Combined hash code                      91ac921728a25197  \\(10375 sub-codes\\)"
+  REGEX_PASS "Combined hash code                      4af999c3b33c5a53  \\(10375 sub-codes\\)"
   REGEX_FAIL "Exception;EXCEPTION;ERROR"
 )
 #
@@ -141,7 +141,7 @@ dd4hep_add_test_reg( CLICSiD_check_checksum_EcalBarrel
 dd4hep_add_test_reg( CLICSiD_check_checksum_full
   COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_CLICSiD.sh"
   EXEC_ARGS  geoPluginRun -input ${DD4hep_ROOT}/DDDetectors/compact/SiD.xml -plugin DD4hepDetectorChecksum -readout 
-  REGEX_PASS "Combined hash code                      15a55d11308fce12  \\(3395674 sub-codes\\)"
+  REGEX_PASS "Combined hash code                      2aa2f0fe61a8331f  \\(3395674 sub-codes\\)"
   REGEX_FAIL "Exception;EXCEPTION;ERROR"
 )
 #
diff --git a/examples/ClientTests/CMakeLists.txt b/examples/ClientTests/CMakeLists.txt
index 6d6fa5dd4..797bd9dd3 100644
--- a/examples/ClientTests/CMakeLists.txt
+++ b/examples/ClientTests/CMakeLists.txt
@@ -379,7 +379,7 @@ dd4hep_add_test_reg( MiniTel_check_checksum_Minitel3
   COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_CLICSiD.sh"
   EXEC_ARGS  geoPluginRun -input ${ClientTestsEx_INSTALL}/compact/MiniTelGenerate.xml
   	      -plugin DD4hepDetectorChecksum -readout -detector Minitel3
-  REGEX_PASS "Combined hash code                      96566298cb469f79  \\(54 sub-codes\\)"
+  REGEX_PASS "Combined hash code                      8e54af7d60ff83d0  \\(54 sub-codes\\)"
   REGEX_FAIL "Exception;EXCEPTION;ERROR"
 )
 #
@@ -388,7 +388,7 @@ dd4hep_add_test_reg( MiniTel_check_checksum_full
   COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_CLICSiD.sh"
   EXEC_ARGS  geoPluginRun -input ${ClientTestsEx_INSTALL}/compact/MiniTelGenerate.xml
   	      -plugin DD4hepDetectorChecksum -readout
-  REGEX_PASS "Combined hash code                      97ecf7772fe1d462  \\(207 sub-codes\\)"
+  REGEX_PASS "Combined hash code                      7330636481b0401d  \\(207 sub-codes\\)"
   REGEX_FAIL "Exception;EXCEPTION;ERROR"
 )
 #
@@ -397,7 +397,7 @@ dd4hep_add_test_reg( Check_Shape_Tessellated_check_checksum
   COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_CLICSiD.sh"
   EXEC_ARGS  geoPluginRun -input ${ClientTestsEx_INSTALL}/compact/Check_Shape_Tessellated.xml
   	      -plugin DD4hepDetectorChecksum
-  REGEX_PASS "Combined hash code                      c8eb13dd1d4d9ca1  \\(13 sub-codes\\)"
+  REGEX_PASS "Combined hash code                      13a268b6718de7a8  \\(13 sub-codes\\)"
   REGEX_FAIL "Exception;EXCEPTION;ERROR"
 )
 #
@@ -406,7 +406,7 @@ dd4hep_add_test_reg( Check_Shape_Tessellated_check_checksum_with_meshes
   COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_CLICSiD.sh"
   EXEC_ARGS  geoPluginRun -input ${ClientTestsEx_INSTALL}/compact/Check_Shape_Tessellated.xml
   	      -plugin DD4hepDetectorChecksum -meshes -precision 3
-  REGEX_PASS "Combined hash code                      ada64a13764bb466  \\(13 sub-codes\\)"
+  REGEX_PASS "Combined hash code                      1fc84f1c2d93fd80  \\(13 sub-codes\\)"
   REGEX_FAIL "Exception;EXCEPTION;ERROR"
 )
 #
-- 
GitLab