diff --git a/DDCore/include/DDSegmentation/CartesianGridXYStaggered.h b/DDCore/include/DDSegmentation/CartesianGridXYStaggered.h
new file mode 100644
index 0000000000000000000000000000000000000000..441026adfba77bd5028ff6317e65223d031e2a9e
--- /dev/null
+++ b/DDCore/include/DDSegmentation/CartesianGridXYStaggered.h
@@ -0,0 +1,150 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+//==========================================================================
+
+
+
+
+/*
+ * CartesianGridXYStaggered.h
+ *
+ *  Created on: September 15, 2023
+ *      Author: Sebouh J. Paul, UCR
+ */
+
+#ifndef DDSEGMENTATION_CARTESIANGRIDXYSTAGGERED_H
+#define DDSEGMENTATION_CARTESIANGRIDXYSTAGGERED_H
+
+#include "DDSegmentation/CartesianGrid.h"
+
+namespace dd4hep {
+  namespace DDSegmentation {
+
+    /// Segmentation base class describing cartesian grid segmentation in the X-Y plane
+    class CartesianGridXYStaggered: public CartesianGrid {
+    public:
+      /// Default constructor passing the encoding string
+      CartesianGridXYStaggered(const std::string& cellEncoding = "");
+      /// Default constructor used by derived classes passing an existing decoder
+      CartesianGridXYStaggered(const BitFieldCoder* decoder);
+      /// destructor
+      virtual ~CartesianGridXYStaggered();
+
+      /// determine the position based on the cell ID
+      virtual Vector3D position(const CellID& cellID) const;
+      /// determine the cell ID based on the position
+      virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const;
+      /// access the grid size in X
+      double gridSizeX() const {
+        return _gridSizeX;
+      }
+      /// access the grid size in Y
+      double gridSizeY() const {
+        return _gridSizeY;
+      }
+      /// access the coordinate offset in X
+      double offsetX() const {
+        return _offsetX;
+      }
+      /// access the coordinate offset in Y
+      double offsetY() const {
+        return _offsetY;
+      }
+      /// access the field name used for X
+      const std::string& fieldNameX() const {
+        return _xId;
+      }
+      /// access the field name used for Y
+      const std::string& fieldNameY() const {
+        return _yId;
+      }
+      /// access the staggering option in X
+      int staggerX() const {
+        return _staggerX;
+      }
+      /// access the staggering option in Y
+      int staggerY() const {
+        return _staggerY;
+      }
+      /// access the keyword used to determine which volumes to stagger
+      const std::string& staggerKeyword() const {
+        return _staggerKeyword;
+      }
+      /// set the grid size in X
+      void setGridSizeX(double cellSize) {
+        _gridSizeX = cellSize;
+      }
+      /// set the grid size in Y
+      void setGridSizeY(double cellSize) {
+        _gridSizeY = cellSize;
+      }
+      /// set the coordinate offset in X
+      void setOffsetX(double offset) {
+        _offsetX = offset;
+      }
+      /// set the coordinate offset in Y
+      void setOffsetY(double offset) {
+        _offsetY = offset;
+      }
+      /// set the field name used for X
+      void setFieldNameX(const std::string& fieldName) {
+        _xId = fieldName;
+      }
+      /// set the field name used for Y
+      void setFieldNameY(const std::string& fieldName) {
+        _yId = fieldName;
+      }
+      /// set the staggering option in X
+      void setStaggerX(int staggerX) {
+        _staggerX = staggerX;
+      }
+      /// set the staggering option in Y
+      void setStaggerY(int staggerY) {
+        _staggerY = staggerY;
+      }
+      /// set the keyword used to determine which volumes to stagger
+      void setStaggerKeyword(const std::string& staggerKeyword) {
+        _staggerKeyword = staggerKeyword;
+      }
+      /** \brief Returns a vector<double> of the cellDimensions of the given cell ID
+          in natural order of dimensions, e.g., dx/dy/dz, or dr/r*dPhi
+
+          Returns a vector of the cellDimensions of the given cell ID
+          \param cellID is ignored as all cells have the same dimension
+          \return std::vector<double> size 2:
+          -# size in x
+          -# size in y
+      */
+      virtual std::vector<double> cellDimensions(const CellID& cellID) const;
+
+    protected:
+      /// the grid size in X
+      double _gridSizeX;
+      /// the coordinate offset in X
+      double _offsetX;
+      /// staggering option in X.  0 = no staggering.  1 = stagger by _gridSizeX/2.0 in odd layers
+      int _staggerX;
+      /// the grid size in Y
+      double _gridSizeY;
+      /// the coordinate offset in Y
+      double _offsetY;
+      /// staggering option in Y.  0 = no staggering.  1 = stagger by _gridSizeY/2.0 in odd layers
+      int _staggerY;
+      /// the field name used for X
+      std::string _xId;
+      /// the field name used for Y
+      std::string _yId;
+      /// the keyword used to determine which volumes to stagger
+      std::string _staggerKeyword;
+    };
+
+  } /* namespace DDSegmentation */
+} /* namespace dd4hep */
+#endif // DDSEGMENTATION_CARTESIANGRIDXYSTAGGERED_H
diff --git a/DDCore/include/DDSegmentation/HexGrid.h b/DDCore/include/DDSegmentation/HexGrid.h
new file mode 100644
index 0000000000000000000000000000000000000000..434177790ebf93611e1508569a02419bb6fb42aa
--- /dev/null
+++ b/DDCore/include/DDSegmentation/HexGrid.h
@@ -0,0 +1,131 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+//==========================================================================
+
+/*
+ * HexGrid.h
+ *
+ *  Created on: August 9, 2023
+ *      Author: Sebouh J. Paul, UC Riverside
+ */
+
+#ifndef DDSEGMENTATION_HEXGRID_H
+#define DDSEGMENTATION_HEXGRID_H
+
+#include "DDSegmentation/Segmentation.h"
+
+namespace dd4hep {
+  namespace DDSegmentation {
+
+    /// Segmentation base class describing hexagonal grid segmentation, with or without staggering
+    class HexGrid: public Segmentation {
+    public:
+      /// Destructor
+      virtual ~HexGrid();
+      //protected:
+      /// Default constructor used by derived classes passing the encoding string
+      HexGrid(const std::string& cellEncoding = "");
+      /// Default constructor used by derived classes passing an existing decoder
+      HexGrid(const BitFieldCoder* decoder);
+
+      /// determine the position based on the cell ID
+      virtual Vector3D position(const CellID& cellID) const;
+      /// determine the cell ID based on the position
+      virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const;
+      // access the stagger mode: 0=no stagger; 1=stagger cycling through 3 offsets
+      int stagger() const {
+	return _stagger;
+      }
+      
+      /// access the grid size 
+      double sideLength() const {
+        return _sideLength;
+      }
+      /// access the coordinate offset in X
+      double offsetX() const {
+        return _offsetX;
+      }
+      /// access the coordinate offset in Y
+      double offsetY() const {
+        return _offsetY;
+      }
+      /// access the field name used for X
+      const std::string& fieldNameX() const {
+        return _xId;
+      }
+      /// access the field name used for Y
+      const std::string& fieldNameY() const {
+        return _yId;
+      }
+      /// access the keyword for staggering
+      const std::string& staggerKeyword() const {
+        return _staggerKeyword;
+      }
+
+      /// set the stagger mode: 0=no stagger; 1=stagger cycling through 3 offsets
+      void setStagger(int stagger) {
+	_stagger= stagger;
+      }
+      /// set the grid size in X
+      void setSideLength(double cellSize) {
+        _sideLength = cellSize;
+      }
+      /// set the coordinate offset in X
+      void setOffsetX(double offset) {
+        _offsetX = offset;
+      }
+      /// set the coordinate offset in Y
+      void setOffsetY(double offset) {
+        _offsetY = offset;
+      }
+      /// set the field name used for X
+      void setFieldNameX(const std::string& fieldName) {
+        _xId = fieldName;
+      }
+      /// set the field name used for Y
+      void setFieldNameY(const std::string& fieldName) {
+        _yId = fieldName;
+      }
+      /// set the keyword used to determine which volumes to stagger
+      void setStaggerKeyword(const std::string& staggerKeyword) {
+        _staggerKeyword = staggerKeyword;
+      }
+      /** \brief Returns a vector<double> of the cellDimensions of the given cell ID
+          in natural order of dimensions, e.g., dx/dy/dz, or dr/r*dPhi
+
+          Returns a vector of the cellDimensions of the given cell ID
+          \param cellID is ignored as all cells have the same dimension
+          \return std::vector<double> size 2:
+          -# size in x
+          -# size in y
+      */
+      virtual std::vector<double> cellDimensions(const CellID& cellID) const;
+
+    protected:
+      /// the stagger mode:  0=off ; 1=cycle through 3 different offsets (H3)
+      //  2=cycle through 4 differnt offsets (H4)
+      int _stagger;
+      /// the length of one side of a hexagon
+      double _sideLength;
+      /// the coordinate offset in X
+      double _offsetX;
+      /// the coordinate offset in Y
+      double _offsetY;
+      /// the field name used for X
+      std::string _xId;
+      /// the field name used for Y
+      std::string _yId;
+      /// the keyword used to determine which volumes to stagger
+      std::string _staggerKeyword;
+    };
+
+  } /* namespace DDSegmentation */
+} /* namespace dd4hep */
+#endif // DDSEGMENTATION_HEXGRID_H
diff --git a/DDCore/src/segmentations/CartesianGridXYStaggered.cpp b/DDCore/src/segmentations/CartesianGridXYStaggered.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..871958ffe3de6efee941bc27c9cf46858e02f970
--- /dev/null
+++ b/DDCore/src/segmentations/CartesianGridXYStaggered.cpp
@@ -0,0 +1,102 @@
+/*
+ * CartesianGridXYStaggered.cpp
+ *
+ *  Created on: Sept 15, 2023
+ *      Author: Sebouh J. Paul, UCR
+ */
+
+#include "DDSegmentation/CartesianGridXYStaggered.h"
+
+namespace dd4hep {
+namespace DDSegmentation {
+
+/// default constructor using an encoding string
+CartesianGridXYStaggered::CartesianGridXYStaggered(const std::string& cellEncoding) :
+		CartesianGrid(cellEncoding) {
+	// define type and description
+	_type = "CartesianGridXYStaggered";
+	_description = "Cartesian segmentation in the local XY-plane, with options for staggering";
+
+	// register all necessary parameters
+	registerParameter("grid_size_x", "Cell size in X", _gridSizeX, 1., SegmentationParameter::LengthUnit);
+	registerParameter("grid_size_y", "Cell size in Y", _gridSizeY, 1., SegmentationParameter::LengthUnit);
+	registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true);
+	registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true);
+	registerParameter("stagger_x", "Option to stagger the layers in x (ie, add grid_size_x/2 to offset_x for odd layers)", _staggerX, 0,
+		SegmentationParameter::NoUnit, true);
+	registerParameter("stagger_y", "Option to stagger the layers in y (ie, add grid_size_y/2 to offset_y for odd layers)", _staggerY, 0, 
+		SegmentationParameter::NoUnit, true);
+	registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x");
+	registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y");
+	registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", 
+		SegmentationParameter::NoUnit, true);
+}
+
+/// Default constructor used by derived classes passing an existing decoder
+CartesianGridXYStaggered::CartesianGridXYStaggered(const BitFieldCoder* decode) :
+		CartesianGrid(decode)
+{
+	// define type and description
+	_type = "CartesianGridXYStaggered";
+	_description = "Cartesian segmentation in the local XY-plane, with options for staggering";
+
+	// register all necessary parameters
+	registerParameter("grid_size_x", "Cell size in X", _gridSizeX, 1., SegmentationParameter::LengthUnit);
+	registerParameter("grid_size_y", "Cell size in Y", _gridSizeY, 1., SegmentationParameter::LengthUnit);
+	registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true);
+	registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true);
+	registerParameter("stagger_x", "Option to stagger the layers in x (ie, add grid_size_x/2 to offset_x for odd layers)", _staggerX, 0,
+		SegmentationParameter::NoUnit, true);
+	registerParameter("stagger_y", "Option to stagger the layers in y (ie, add grid_size_y/2 to offset_y for odd layers)", _staggerY, 0,
+		SegmentationParameter::NoUnit, true);
+	registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x");
+	registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y");
+	registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer",
+		SegmentationParameter::NoUnit, true);
+}
+
+/// destructor
+CartesianGridXYStaggered::~CartesianGridXYStaggered() {
+
+}
+
+/// determine the position based on the cell ID
+Vector3D CartesianGridXYStaggered::position(const CellID& cID) const {
+	Vector3D cellPosition;
+	if (_staggerX || _staggerY){
+		int layer= _decoder->get(cID,_staggerKeyword);
+		cellPosition.X = binToPosition( _decoder->get(cID,_xId ), _gridSizeX, _offsetX+_staggerX*_gridSizeX*(layer%2)/2.);
+		cellPosition.Y = binToPosition( _decoder->get(cID,_yId ), _gridSizeY, _offsetY+_staggerY*_gridSizeY*(layer%2)/2.);
+	} else {
+		cellPosition.X = binToPosition( _decoder->get(cID,_xId ), _gridSizeX, _offsetX);
+		cellPosition.Y = binToPosition( _decoder->get(cID,_yId ), _gridSizeY, _offsetY);
+	}
+	return cellPosition;
+}
+
+/// determine the cell ID based on the position
+  CellID CartesianGridXYStaggered::cellID(const Vector3D& localPosition, const Vector3D& /* globalPosition */, const VolumeID& vID) const {
+        CellID cID = vID ;
+	if (_staggerX || _staggerY){
+		int layer= _decoder->get(cID,_staggerKeyword);
+		_decoder->set( cID,_xId, positionToBin(localPosition.X, _gridSizeX, _offsetX+_staggerX*_gridSizeX*(layer%2)/2) );
+		_decoder->set( cID,_yId, positionToBin(localPosition.Y, _gridSizeY, _offsetY+_staggerY*_gridSizeY*(layer%2)/2) );
+	} else {
+		_decoder->set( cID,_xId, positionToBin(localPosition.X, _gridSizeX, _offsetX));
+		_decoder->set( cID,_yId, positionToBin(localPosition.Y, _gridSizeY, _offsetY));
+	}
+	return cID ;
+}
+
+
+std::vector<double> CartesianGridXYStaggered::cellDimensions(const CellID& cellID) const {
+  return {_gridSizeX, _gridSizeY};
+}
+
+
+} /* namespace DDSegmentation */
+} /* namespace dd4hep */
+
+// This is done DDCore/src/plugins/ReadoutSegmentations.cpp so the plugin is not part of libDDCore
+// needs also #include "DD4hep/Factories.h"
+// DECLARE_SEGMENTATION(CartesianGridXYStaggered,dd4hep::create_segmentation<dd4hep::DDSegmentation::CartesianGridXYStaggered>)
diff --git a/DDCore/src/segmentations/HexGrid.cpp b/DDCore/src/segmentations/HexGrid.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f051a8f618448e2aa141124be41a21df871b6f0a
--- /dev/null
+++ b/DDCore/src/segmentations/HexGrid.cpp
@@ -0,0 +1,149 @@
+/*
+ * AIDA Detector description implementation 
+ * 
+ * Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+ * All rights reserved.
+ *
+ * For the licensing terms see $DD4hepINSTALL/LICENSE.
+ * For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+ *
+ * HexGrid.cpp  
+ *
+ * Created on: August 9, 2023
+ *      Author: Sebouh J. Paul, UC Riverside
+ */
+#include "DD4hep/Factories.h"
+#include "DDSegmentation/HexGrid.h"
+
+namespace dd4hep {
+  namespace DDSegmentation {
+
+    /// Default constructor used by derived classes passing the encoding string
+    HexGrid::HexGrid(const std::string& cellEncoding) :
+      Segmentation(cellEncoding) {
+        _type = "HexGridXY";
+	_description = "Hexagonal segmentation in the local XY-plane";
+
+	// register all necessary parameters
+	registerParameter("stagger", "stagger mode", _stagger, 1);
+	registerParameter("side_length", "Cell size", _sideLength, 1., SegmentationParameter::LengthUnit);
+	registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true);
+	registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true);
+	registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x");
+	registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y");
+	registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", SegmentationParameter::NoUnit, true);
+    }
+
+    /// Default constructor used by derived classes passing an existing decoder
+    HexGrid::HexGrid(const BitFieldCoder* decode) : Segmentation(decode) {
+        // define type and description
+	_type = "HexGridXY";
+	_description = "Hexagonal segmentation in the local XY-plane";
+
+	// register all necessary parameters                                                                        
+        registerParameter("stagger", "stagger mode", _stagger, 1);
+	registerParameter("side_length", "Cell size", _sideLength, 1., SegmentationParameter::LengthUnit);
+	registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true);
+	registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true);
+	registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x");
+	registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y");
+	registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", SegmentationParameter::NoUnit, true);
+    
+    }
+
+    /// Destructor
+    HexGrid::~HexGrid() {
+    }
+
+    /// determine the position based on the cell ID
+    Vector3D HexGrid::position(const CellID& cID) const {
+        int layer=0;
+	if (_stagger) layer= _decoder->get(cID,_staggerKeyword);
+		
+	Vector3D cellPosition;
+	cellPosition.X = _decoder->get(cID,_xId )*1.5*_sideLength+_offsetX+_sideLength/2.;
+	cellPosition.Y = _decoder->get(cID,_yId )*std::sqrt(3)/2.*_sideLength+ _offsetY+_sideLength*std::sqrt(3)/2.;
+	if (_stagger==0)
+	  cellPosition.X+=_sideLength;
+	else if (_stagger==1)
+	  cellPosition.X+=(layer%3)*_sideLength;
+	else if (_stagger==2){
+	  switch (layer%4){
+	  case 0:
+	    cellPosition.X-=0.75*_sideLength;
+	    break;
+	  case 1:
+	    cellPosition.Y+=std::sqrt(3)/4*_sideLength;
+	    break;
+	  case 2:
+	    cellPosition.Y-=std::sqrt(3)/4*_sideLength;
+	    break;
+	  case 3:
+	    cellPosition.X+=0.75*_sideLength;
+	    break;
+	  }
+	}
+	return cellPosition;
+    }
+
+    inline double positive_modulo(double i, double n) {
+      return std::fmod(std::fmod(i,n) + n,n);
+    }
+
+    
+    /// determine the cell ID based on the position
+    CellID HexGrid::cellID(const Vector3D& localPosition, const Vector3D& /* globalPosition */, const VolumeID& vID) const {
+        CellID cID = vID ;
+	int layer=0;
+	if (_stagger) layer= _decoder->get(cID,_staggerKeyword);
+
+	double x=localPosition.X-_offsetX;
+	double y=localPosition.Y-_offsetY;
+	if (_stagger==0)
+	  x-=_sideLength;
+	else if (_stagger==1)
+          x-=(layer%3)*_sideLength;
+	else if (_stagger==2){
+          switch (layer%4){
+	  case 0:
+	    x+=0.75*_sideLength;
+	    break;
+          case 1:
+            y-=std::sqrt(3)/4*_sideLength;
+            break;
+          case 2:
+            y+=std::sqrt(3)/4*_sideLength;
+            break;
+          case 3:
+            x-=0.75*_sideLength;
+	    break;
+          }
+        }
+	
+	double a=positive_modulo(y/(std::sqrt(3)*_sideLength),1);
+	double b=positive_modulo(x/(3*_sideLength),1);
+	int ix = std::floor(x/(3*_sideLength/2.))+		
+	  (b<0.5)*(-abs(a-.5)<(b-.5)*3)+(b>0.5)*(abs(a-.5)-.5<(b-1)*3);
+	int iy=std::floor(y/(std::sqrt(3)*_sideLength/2.));
+	iy-=(ix+iy)&1;
+	
+	_decoder->set( cID,_xId, ix );
+	_decoder->set( cID,_yId, iy );
+	return cID ;
+    }
+
+    std::vector<double> HexGrid::cellDimensions(const CellID&) const {
+#if __cplusplus >= 201103L
+      return {2*_sideLength, std::sqrt(3)*_sideLength};
+#else
+      std::vector<double> cellDims(2,0.0);
+      cellDims[0] = 2*_sideLength;
+      cellDims[1] = std::sqrt(3)*_sideLength;
+      return cellDims;
+#endif
+}
+
+  } /* namespace DDSegmentation */
+} /* namespace dd4hep */
+
+DECLARE_SEGMENTATION(HexGrid, create_segmentation<dd4hep::DDSegmentation::HexGrid>)