From a134446ff50804612050e53572aec3fb6c2084c9 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Wed, 30 Nov 2022 12:23:03 +0100
Subject: [PATCH] Add README for DDG4 and DDDigi

---
 DDCore/src/plugins/DetectorChecksum.cpp | 128 ++++++------------------
 DDCore/src/plugins/DetectorChecksum.h   |  81 ++++++---------
 DDDigi/README.md                        |  44 ++++++++
 DDG4/README.md                          |  25 +++++
 4 files changed, 132 insertions(+), 146 deletions(-)
 create mode 100644 DDDigi/README.md
 create mode 100644 DDG4/README.md

diff --git a/DDCore/src/plugins/DetectorChecksum.cpp b/DDCore/src/plugins/DetectorChecksum.cpp
index 419ea7c80..cfaa7528b 100644
--- a/DDCore/src/plugins/DetectorChecksum.cpp
+++ b/DDCore/src/plugins/DetectorChecksum.cpp
@@ -15,10 +15,10 @@
 #include <DD4hep/Plugins.h>
 #include <DD4hep/Printout.h>
 #include <DD4hep/FieldTypes.h>
-#include <DD4hep/DD4hepUnits.h>
 #include <DD4hep/DetectorTools.h>
 #include <DD4hep/MatrixHelpers.h>
 #include <DD4hep/AlignmentData.h>
+#include <DD4hep/DetFactoryHelper.h>
 #include <DD4hep/detail/ObjectsInterna.h>
 #include <DD4hep/detail/DetectorInterna.h>
 #include "DetectorChecksum.h"
@@ -29,7 +29,7 @@
 #include <TColor.h>
 #include <TGeoBoolNode.h>
 
-#include <fstream>
+// C/C++ include files
 #include <iostream>
 #include <sstream>
 #include <iomanip>
@@ -72,12 +72,14 @@ void DetectorChecksum::configure()   {
   m_ene_unit = _toDouble(m_ene_unit_nam)/m_ene__def;
   m_densunit = _toDouble(m_densunit_nam)/m_dens_def;
   m_atomunit = _toDouble(m_atomunit_nam)/m_atom_def;
-  printout(INFO,"DetectorChecksum","+++ Float precision: %d", precision);
-  printout(INFO,"DetectorChecksum","+++ Unit of length:  %-12s -> %f", m_len_unit_nam.c_str(), m_len_unit);
-  printout(INFO,"DetectorChecksum","+++ Unit of angle:   %-12s -> %f", m_ang_unit_nam.c_str(), m_ang_unit);
-  printout(INFO,"DetectorChecksum","+++ Unit of energy:  %-12s -> %f", m_ene_unit_nam.c_str(), m_ene_unit);
-  printout(INFO,"DetectorChecksum","+++ Unit of density: %-12s -> %f", m_densunit_nam.c_str(), m_densunit);
-  printout(INFO,"DetectorChecksum","+++ Unit of density: %-12s -> %f", m_atomunit_nam.c_str(), m_atomunit);
+  if ( debug > 1 )   {
+    printout(INFO,"DetectorChecksum","+++ Float precision: %d", precision);
+    printout(INFO,"DetectorChecksum","+++ Unit of length:  %-12s -> %f", m_len_unit_nam.c_str(), m_len_unit);
+    printout(INFO,"DetectorChecksum","+++ Unit of angle:   %-12s -> %f", m_ang_unit_nam.c_str(), m_ang_unit);
+    printout(INFO,"DetectorChecksum","+++ Unit of energy:  %-12s -> %f", m_ene_unit_nam.c_str(), m_ene_unit);
+    printout(INFO,"DetectorChecksum","+++ Unit of density: %-12s -> %f", m_densunit_nam.c_str(), m_densunit);
+    printout(INFO,"DetectorChecksum","+++ Unit of density: %-12s -> %f", m_atomunit_nam.c_str(), m_atomunit);
+  }
 }
 
 std::stringstream DetectorChecksum::logger()   const    {
@@ -105,7 +107,7 @@ const std::string& DetectorChecksum::handleElement(Atom element) const {
 	  << "\" value=\""    << std::scientific << element->A()/m_atomunit << "\"/>" << newline
 	  << "</element>";
       iel = geo.emplace(element, log.str()).first;
-      if ( debug > 2 ) std::cout << log.str() << std::endl;
+      if ( debug > 3 ) std::cout << log.str() << std::endl;
     }
   }
   return iel->second;
@@ -140,7 +142,7 @@ const std::string& DetectorChecksum::handleMaterial(Material medium) const {
     log << " <D unit=\"" << m_densunit_nam << "\" value=\"" << mat->GetDensity()/m_densunit << "\"/>" << newline;
     log << "</material>";
     ima = geo.emplace(medium, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return ima->second;
 }
@@ -510,7 +512,7 @@ const std::string& DetectorChecksum::handleSolid(Solid solid) const {
       log << "</" << str_oper << ">" << newline;
     }
     iso = geo.emplace(solid, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return iso->second;
 }
@@ -528,7 +530,7 @@ const std::string& DetectorChecksum::handlePosition(const TGeoMatrix* trafo) con
 	<< " y=\"" << tr[1]/m_len_unit  << "\""
 	<< " z=\"" << tr[2]/m_len_unit  << "\"/>";
     ipo = geo.emplace(trafo, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return ipo->second;
 }
@@ -546,7 +548,7 @@ const std::string& DetectorChecksum::handleRotation(const TGeoMatrix* trafo) con
 	<< " y=\"" << rot.Y()/m_ang_unit << "\""
 	<< " z=\"" << rot.Z()/m_ang_unit << "\"/>";
     iro = geo.emplace(trafo, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return iro->second;
 }
@@ -581,7 +583,7 @@ const std::string& DetectorChecksum::handleVis(VisAttr attr) const {
 	<< " G=\""     << green  << "\"/>" << newline;
     log << "</vis>";
     ivi = geo.emplace(attr, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return ivi->second;
 }
@@ -599,7 +601,7 @@ const std::string& DetectorChecksum::handleRegion(Region region) const {
 	<< " lunit=\""             << m_len_unit_nam << "\""
 	<< "/>";
     ire = geo.emplace(region, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return ire->second;
 }
@@ -621,7 +623,7 @@ const std::string& DetectorChecksum::handleLimitSet(LimitSet lim) const {
     }
     log << "</limitSet>";
     ili = geo.emplace(lim, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return ili->second;
 }
@@ -652,7 +654,7 @@ const std::string& DetectorChecksum::handleAlignment(Alignment alignment)  const
 	<< " psi=\""   << data.delta.rotation.Psi()/m_len_unit  << "\"/>" << newline;
     log << "</nominal>";
     ial = geo.emplace(alignment, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return ial->second;
 }
@@ -727,7 +729,7 @@ const std::string& DetectorChecksum::handleVolume(Volume volume) const {
     }
     log << "</" << tag << ">";
     ivo = geo.emplace(volume, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return ivo->second;
 }
@@ -758,7 +760,7 @@ const std::string& DetectorChecksum::handlePlacement(PlacedVolume node) const {
     }
     log << "</physvol>";
     ipl = geo.emplace(node, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return ipl->second;
 }
@@ -781,7 +783,7 @@ const std::string& DetectorChecksum::handleDetElement(DetElement det)  const  {
 	<< " placement=\""     << det.placementPath()    << "\""
 	<< "/>";
     dit = geo.emplace(det, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return dit->second;
 }
@@ -806,7 +808,7 @@ const std::string& DetectorChecksum::handleSensitive(SensitiveDetector sd) const
 	handleSegmentation(ro.segmentation());
       }
       isi = geo.emplace(sd, log.str()).first;
-      if ( debug > 2 ) std::cout << log.str() << std::endl;
+      if ( debug > 3 ) std::cout << log.str() << std::endl;
     }
     return isi->second;
   }
@@ -847,7 +849,7 @@ const std::string& DetectorChecksum::handleSegmentation(Segmentation seg) const
       log << "</parameters>" << newline;
       log << "</segmentatoin>";
       ise = geo.emplace(seg, log.str()).first;
-      if ( debug > 2 ) std::cout << log.str() << std::endl;
+      if ( debug > 3 ) std::cout << log.str() << std::endl;
     }
     return ise->second;
   }
@@ -872,7 +874,7 @@ const std::string& DetectorChecksum::handleIdSpec(IDDescriptor id_spec) const {
       }
       log << "</id>";
       iid = geo.emplace(id_spec, log.str()).first;
-      if ( debug > 2 ) std::cout << log.str() << std::endl;
+      if ( debug > 3 ) std::cout << log.str() << std::endl;
     }
     return iid->second;
   }
@@ -903,7 +905,7 @@ const std::string& DetectorChecksum::handleField(OverlayedField f) const {
 #endif
     log << "</field>";
     ifd = geo.emplace(f, log.str()).first;
-    if ( debug > 2 ) std::cout << log.str() << std::endl;
+    if ( debug > 3 ) std::cout << log.str() << std::endl;
   }
   return ifd->second;
 }
@@ -946,19 +948,18 @@ void DetectorChecksum::collect_det_elements(DetElement top)  const  {
 }
 
 /// Create geometry conversion
-DetectorChecksum::checksum_t DetectorChecksum::analyzeDetector(DetElement top)      {
+void DetectorChecksum::analyzeDetector(DetElement top)      {
   Detector& description = m_detDesc;
   if (!top.isValid()) {
     throw std::runtime_error("Attempt to call analyzeDetector with an invalid geometry!");
   }
-
   GeometryInfo& geo = *(m_dataPtr = new GeometryInfo);
   m_data->clear();
   handleHeader();
   collect_det_elements(top);
   for (const auto& fld : description.fields() )
     handleField(fld.second);
-  if ( debug > 0 )  {
+  if ( debug > 1 )  {
     printout(ALWAYS,"DetectorChecksum","++ ==> Computing checksum for tree: %s", top.path().c_str());
     printout(ALWAYS,"DetectorChecksum","++ Handled %ld materials.", geo.mapOfMaterials.size());
     printout(ALWAYS,"DetectorChecksum","++ Handled %ld solids.", geo.mapOfSolids.size());
@@ -966,8 +967,6 @@ DetectorChecksum::checksum_t DetectorChecksum::analyzeDetector(DetElement top)
     printout(ALWAYS,"DetectorChecksum","++ Handled %ld visualization attributes.", geo.mapOfVis.size());
     printout(ALWAYS,"DetectorChecksum","++ Handled %ld fields.", geo.mapOfFields.size());
   }
-  checksumDetElement(0, top, 0, true);
-  return 0;
 }
 
 std::vector<PlacedVolume> _get_path(PlacedVolume node, const std::set<PlacedVolume>& match)   {
@@ -1046,18 +1045,18 @@ DetectorChecksum::checksumDetElement(int lvl, DetElement top, unsigned long long
     }
 
     /// All done: Some debugging printout
-    if ( debug > 0 && lvl <= max_level )  {
+    if ( debug > 0 || lvl <= max_level )  {
       std::stringstream str;
       str << "+++ " << std::setw(4) << std::left << lvl
 	  << " " << std::setw(24) << std::left << top.name()
 	  << " " << std::setfill('0') << std::setw(16) << std::hex << de_hash;
-      str << " " << std::setfill(' ') << std::setw(10) << std::left << "+place"
+      str << " " << std::setfill(' ') << std::setw(7) << std::left << "+place"
 	  << " " << std::setfill('0') << std::setw(16) << std::hex << pv_hash;
       if ( !(child_places.empty() && hashed_places.empty()) )
 	str << " " << std::setfill(' ') << std::setw(10) << std::left << "+daughters"
 	    << " " << std::setfill('0') << std::setw(16) << std::hex << dau_hash;
       if ( !top.children().empty() )
-	str << " " << std::setfill(' ') << std::setw(10) << std::left << "+children"
+	str << " " << std::setfill(' ') << std::setw(9) << std::left << "+children"
 	    << " " << std::setfill('0') << std::setw(16) << std::hex << child_hash;
       std::cout << str.str() << std::endl;
     }
@@ -1154,72 +1153,7 @@ static long create_checksum(Detector& description, int argc, char** argv) {
   auto hash = detail::hash64("DD4hepGeometryChecksum");
   wr.analyzeDetector(description.world());
   wr.checksumDetElement(0, description.world(), hash, true);
-  //wr.gdml(description.world());
   return 1;
 }
 
 DECLARE_APPLY(DD4hepGeometryChecksum, create_checksum)
-
-#if 0
-
-      template <typename T> std::string attr_ref(T  handle)  const;
-      void gdmlDetElement(DetElement top, bool recursive)  const;
-      void gdmlReadout(SensitiveDetector sd)  const;
-      void gdml(DetElement top)   const;
-
-template <typename T> std::string DetectorChecksum::attr_ref(T handle)  const  {
-  char text[64];
-  ::snprintf(text, sizeof(text), "_%016lX\" ", (long)handle.ptr());
-  std::string n = " ref=\"" + refName(handle)+std::string(text);
-  return n;
-}
-
-void DetectorChecksum::gdmlDetElement(DetElement top, bool recursive)  const  {
-  auto& dat = data();
-  auto& geo = dat.mapOfDetElements;
-  auto it = geo.find(top);
-  if ( it != geo.end() )    {
-    std::cout << "<detelement" << attr_ref(top) << it->second << ">" << std::endl;
-    std::cout << "<children>" << std::endl;
-    for ( const auto& c : top.children() )
-      std::cout << "<child ref=\"" << attr_ref(c.second) << "\">" << std::endl;
-    std::cout << "</children>" << std::endl;
-    std::cout << "</detelement>" << std::endl;
-    if ( recursive )   {
-      /// Hash the structural children
-      for ( const auto& c : top.children() )
-	gdmlDetElement(c.second, recursive);
-    }
-    return;
-  }
-  except("DetectorChecksum","ERROR: Cannot checksum invalid DetElement");
-}
-
-void DetectorChecksum::gdmlReadout(SensitiveDetector sd)  const  {
-  auto& dat = data();
-  auto& geo = dat.mapOfSensDets;
-  auto it = geo.find(sd);
-  if ( it != geo.end() )    {
-    std::cout << "<sensitive_detector" << attr_ref(sd) << it->second << ">" << std::endl;
-    Readout ro = sd.readout();
-    if ( ro.isValid() ) {
-      Segmentation seg = ro.segmentation();
-      std::cout << "<readout>" << std::endl;
-      std::cout << handleIdSpec(ro.idSpec()) << std::endl;
-      if ( seg.isValid() )   {
-	std::cout << handleSegmentation(seg) << std::endl;
-      }
-      std::cout << "</readout>" << std::endl;
-    }
-    std::cout << "</sensitive_detector>" << std::endl;
-    return;
-  }
-  except("DetectorChecksum","ERROR: Cannot checksum invalid DetElement");
-}
-
-void DetectorChecksum::gdml(DetElement top)   const  {
-  std::cout << "<detector_elements>" << std::endl;
-  gdmlDetElement(top, true);
-  std::cout << "</detector_elements>" << std::endl;
-}
-#endif
diff --git a/DDCore/src/plugins/DetectorChecksum.h b/DDCore/src/plugins/DetectorChecksum.h
index f725970c8..7f1d21839 100644
--- a/DDCore/src/plugins/DetectorChecksum.h
+++ b/DDCore/src/plugins/DetectorChecksum.h
@@ -10,29 +10,17 @@
 // Author     : M.Frank
 //
 //==========================================================================
-
 #ifndef DDCORE_SRC_PLUGINS_DETECTORCHECKSUM_H
 #define DDCORE_SRC_PLUGINS_DETECTORCHECKSUM_H
 
-// Framework include files
+/// Framework include files
 #include <DD4hep/Detector.h>
 #include <DD4hep/GeoHandler.h>
 #include <DD4hep/DD4hepUnits.h>
-#include <DD4hep/DetFactoryHelper.h>
-
-// C/C++ include files
-#include <set>
-#include <map>
-#include <sstream>
-#include <vector>
-
-// Forward declarations
-class TGeoVolume;
-class TGeoElement;
-class TGeoShape;
-class TGeoMedium;
-class TGeoNode;
-class TGeoMatrix;
+
+/// C/C++ include files
+
+/// Forward declarations
 
 /// Namespace for the AIDA detector description toolkit
 namespace dd4hep {
@@ -40,9 +28,6 @@ namespace dd4hep {
   /// Namespace for implementation details of the AIDA detector description toolkit
   namespace detail {
 
-    // Forward declarations
-    class SensitiveDetectorObject;
-
     /// Geometry converter from dd4hep to Geant 4 in Detector format.
     /**
      *  \author  M.Frank
@@ -51,22 +36,23 @@ namespace dd4hep {
      */
     class DetectorChecksum: public GeoHandler {
     public:
-      typedef uint64_t checksum_t;
-
-      typedef std::map<Atom,              std::string> ElementMap;
-      typedef std::map<Material,          std::string> MaterialMap;
-      typedef std::map<LimitSet,          std::string> LimitMap;
-      typedef std::map<PlacedVolume,      std::string> PlacementMap;
-      typedef std::map<Region,            std::string> RegionMap;
-      typedef std::map<SensitiveDetector, std::string> SensDetMap;
-      typedef std::map<Volume,            std::string> VolumeMap;
-      typedef std::map<IDDescriptor,      std::string> IdSpecMap;
-      typedef std::map<Segmentation,      std::string> SegmentationMap;
-      typedef std::map<VisAttr,           std::string> VisMap;
-      typedef std::map<Alignment,         std::string> AlignmentMap;
-      typedef std::map<const TGeoShape*,  std::string> SolidMap;
-      typedef std::map<OverlayedField,    std::string> FieldMap;
-      typedef std::map<const TGeoMatrix*, std::string> TrafoMap;
+      using checksum_t       = uint64_t;
+      using ElementMap       = std::map<Atom,              std::string>;
+      using MaterialMap      = std::map<Material,          std::string>;
+      using LimitMap         = std::map<LimitSet,          std::string>;
+      using PlacementMap     = std::map<PlacedVolume,      std::string>;
+      using RegionMap        = std::map<Region,            std::string>;
+      using SensDetMap       = std::map<SensitiveDetector, std::string>;
+      using VolumeMap        = std::map<Volume,            std::string>;
+      using IdSpecMap        = std::map<IDDescriptor,      std::string>;
+      using SegmentationMap  = std::map<Segmentation,      std::string>;
+      using VisMap           = std::map<VisAttr,           std::string>;
+      using AlignmentMap     = std::map<Alignment,         std::string>;
+      using SolidMap         = std::map<const TGeoShape*,  std::string>;
+      using FieldMap         = std::map<OverlayedField,    std::string>;
+      using TrafoMap         = std::map<const TGeoMatrix*, std::string>;
+      using MapOfDetElements = std::map<DetElement,        std::string>;
+
       /// Data structure of the geometry converter from dd4hep to Geant 4 in Detector format.
       /**
        *  \author  M.Frank
@@ -90,30 +76,21 @@ namespace dd4hep {
         TrafoMap        mapOfRotations;
         FieldMap        mapOfFields;
 	AlignmentMap    mapOfAlignments;
-	using MapOfDetElements = std::map<DetElement, std::string>;
 	MapOfDetElements mapOfDetElements;
-#if 0
-        std::set<SensitiveDetector> sensitives;
-        std::set<Region>            regions;
-        std::set<LimitSet>          limits;
-#endif
 	std::string  header;
 
         GeometryInfo() = default;
       };
-      typedef std::set<std::string> NameSet;
 
       /// Reference to detector description
       Detector& m_detDesc;
       GeometryInfo* m_dataPtr;
-      std::string  empty_string;
 
       std::string  m_len_unit_nam = "mm";
       std::string  m_ang_unit_nam = "deg";
       std::string  m_ene_unit_nam = "GeV";
       std::string  m_densunit_nam = "g/cm3";
       std::string  m_atomunit_nam = "g/mole";
-      std::string  newline   = "";
       double       m_len_unit = dd4hep::mm;
       double       m_ang_unit = dd4hep::deg;
       double       m_ene_unit = dd4hep::GeV;
@@ -126,11 +103,17 @@ namespace dd4hep {
       double       m_dens_def = dd4hep::g/dd4hep::cm3;
       double       m_atom_def = dd4hep::g/dd4hep::mole;
 
-      int precision     { 4 };
-      int debug         { 4 };
-      int make_gdml     { 0 };
+      std::string  empty_string;
+      std::string  newline = "";
+
+      /// Property: precision of hashed printouts
+      int precision     { 6 };
+      /// Property: Include readout property in detector hash
       int hash_readout  { 0 };
+      /// Property: maximum depth level for printouts
       int max_level     { 1 };
+      /// Property: debug level
+      int debug         { 4 };
 
       GeometryInfo& data() const {
         return *m_dataPtr;
@@ -149,7 +132,7 @@ namespace dd4hep {
       void collect_det_elements(DetElement top)  const;
 
       /// Create geometry conversion in Detector format
-      checksum_t analyzeDetector(DetElement top);
+      void analyzeDetector(DetElement top);
       checksum_t checksumPlacement(PlacedVolume pv, unsigned long long int hash, bool recursive)  const;
       checksum_t checksumDetElement(int level, DetElement det, unsigned long long int hash, bool recursive)  const;
 
diff --git a/DDDigi/README.md b/DDDigi/README.md
new file mode 100644
index 000000000..0ac864160
--- /dev/null
+++ b/DDDigi/README.md
@@ -0,0 +1,44 @@
+![DDDigi](../doc/logo_small.png)
+
+DDDigi: The digitization tools of DD4hep
+========================================
+
+`DDDigi` is supposed to interprete the results of the detector simulation phase
+e.g. using the simulation toolket [DDG4](../DDG4) with its command line interface
+[ddsim](../DDG4/python/DDSim).
+This is the final phase of data processing to obtain data from the simulation 
+branch which are as close as possible to the response of the front-end electronics
+of a real experimental setup.
+
+The simulation phase ejects for all subdetectors and the individual 
+sensitive elements contained the energy deposits created by particles from a 
+primary interaction passing the sensitive volume.
+These data have to processed for taking into accound imperfections of the 
+apparatus such as 
+
+- uncertainties in cable lengths resulting in shifts of time of signal arriving.
+- uncertainties in the position of sensitive volumes.
+- dead or hot readout channels.
+- conversion of the final signal data into the equivalent of ADC counts.
+- ...
+
+
+
+
+This detector design has been pulled from , and was originally developed in
+[ATHENA](https://eicweb.phy.anl.gov/EIC/detectors/athena), for the Electron-Ion Collider.
+
+![PFRICH](doc/geometry.png)
+
+To use `ctest`, run:
+```bash
+cd ..  # `pwd` should now be `DD4hep/examples`
+mkdir build
+cd build
+cmake -DDD4HEP_EXAMPLES="OpticalTracker" .. && make && make install
+ctest --output-on-failure   # or use `--verbose` to see all output
+```
+
+
+
+![HORIZON2020](../doc/usermanuals/DDG4/setup/Horizon2020-grant-logo.png)
diff --git a/DDG4/README.md b/DDG4/README.md
new file mode 100644
index 000000000..56545651c
--- /dev/null
+++ b/DDG4/README.md
@@ -0,0 +1,25 @@
+![DDG4](../doc/logo_small.png)
+
+DDG4: The digitization tools of DD4hep
+========================================
+
+Simulating the detector response is an essential tool in high energy physics
+to analyze the sensitivity of an experiment to the underlying physics.
+Such simulation tools require a detailed though convenient detector description as 
+it is provided by the `DD4hep` toolkit `DDG4` which uses [Geant4](https://geant4.web.cern.ch/)
+to simulate the energy response of a given apparatus.
+The toolkit implements a modular and flexible approach to simulation activities using `Geant4`.
+User defined simulation applications using `DDG4` can easily be configured, 
+extended using specialized action routines.
+
+The design is strongly driven by easy of use;
+developers of detector descriptions and applications using
+them should provide minimal information and minimal specific
+code to achieve the desired result.
+
+For further details please see the user manual 
+[HTML](https://dd4hep.web.cern.ch/dd4hep/usermanuals/DDG4Manual/DDG4Manual.html)
+[PDF](https://dd4hep.web.cern.ch/dd4hep/usermanuals/DDG4Manual/DDG4Manual.pdf)
+
+
+![HORIZON2020](../doc/usermanuals/DDG4/setup/Horizon2020-grant-logo.png)
-- 
GitLab