diff --git a/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp b/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp
index ec080ed01ad9243835803e020cf91cf2cfbb7bf7..5da7d0519605a3698cf443d2ffe9859d94d50dd8 100644
--- a/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp
+++ b/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp
@@ -118,6 +118,7 @@ void GMDBManager::printAllElements() const { printAllRecords("Elements"); }
 
 void GMDBManager::printAllShapes() const { 
     printAllRecords("Shapes_Box"); 
+    printAllRecords("Shapes_EllipticalTube"); 
     printAllRecords("Shapes_Tube"); 
     printAllRecords("Shapes_Cons"); 
     printAllRecords("Shapes_Para");
@@ -1759,6 +1760,26 @@ bool GMDBManager::createTables() {
     }
     tab.clear();
     
+    // Shapes-EllipticalTube table
+    // ID, XHalfLength, YHalfLength, ZHalfLength
+    geoNode = "GeoEllipticalTube";
+    tableName = "Shapes_EllipticalTube";
+    m_childType_tableName[geoNode] = tableName;
+    tab.push_back(tableName);
+    tab.push_back("id");
+    tab.push_back("computedVolume");
+    tab.push_back("XHalfLength");
+    tab.push_back("YHalfLength");
+    tab.push_back("ZHalfLength");
+    storeTableColumnNames(tab);
+    queryStr = fmt::format(
+        "create table {0}({1} integer primary key, {2} real, {3} real, {4} real, {5} real )",
+        tab[0], tab[1], tab[2], tab[3], tab[4], tab[5]);
+    if (0 == (rc = execQuery(queryStr))) {
+        storeNodeType(geoNode, tableName);
+    }
+    tab.clear();
+    
     // Shapes-Tube table
     geoNode = "GeoTube";
     tableName = "Shapes_Tube";
@@ -2102,7 +2123,7 @@ bool GMDBManager::createTables() {
     }
     tab.clear();
 
-    // Shapes-Box table
+    // Shapes-GeoUnidentifiedShape table
     // ID, XHalfLength, YHalfLength, ZHalfLength
     geoNode = "GeoUnidentifiedShape";
     tableName = "Shapes_UnidentifiedShape";
diff --git a/GeoModelIO/GeoModelIOHelpers/CMakeLists.txt b/GeoModelIO/GeoModelIOHelpers/CMakeLists.txt
index 48dbc3ba4679c4148d7267e24c72f0f5ba160975..ac5927ef2ff1db33fd8aca007d810d4e1ee1b053 100644
--- a/GeoModelIO/GeoModelIOHelpers/CMakeLists.txt
+++ b/GeoModelIO/GeoModelIOHelpers/CMakeLists.txt
@@ -59,3 +59,8 @@ add_executable(test_io_shapes_unidentifiedshape tests/test_io_UnidentifiedShape.
 target_link_libraries( test_io_shapes_unidentifiedshape GeoModelIO::GeoModelDBManager GeoModelCore::GeoModelHelpers GeoModelCore::GeoModelKernel GeoModelIO::GeoModelIOHelpers)
 add_test(NAME test_IO_Shapes_UnidentifiedShape
          COMMAND test_io_shapes_unidentifiedshape)
+
+add_executable(test_io_shapes_ellipticaltube tests/test_io_shape_EllipticalTube.cpp)
+target_link_libraries( test_io_shapes_ellipticaltube GeoModelIO::GeoModelDBManager GeoModelCore::GeoModelHelpers GeoModelCore::GeoModelKernel GeoModelIO::GeoModelIOHelpers)
+add_test(NAME test_IO_Shapes_EllipticalTube
+         COMMAND test_io_shapes_ellipticaltube)
diff --git a/GeoModelIO/GeoModelIOHelpers/tests/test_io_shape_EllipticalTube.cpp b/GeoModelIO/GeoModelIOHelpers/tests/test_io_shape_EllipticalTube.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d22ff13b0c2723cea67754cbc168fcf8023f462
--- /dev/null
+++ b/GeoModelIO/GeoModelIOHelpers/tests/test_io_shape_EllipticalTube.cpp
@@ -0,0 +1,120 @@
+// Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+
+/*
+ * This example tests the I/O of GeoEllipticalTube.
+ *
+ *  Author:     Riccardo Maria BIANCHI @ CERN
+ *  Created on: Oct, 2024
+ */
+
+// GeoModel includes
+#include "GeoModelIOHelpers/GMTests_IO.h"
+#include "GeoModelKernel/GeoEllipticalTube.h"
+#include "GeoModelHelpers/defineWorld.h"
+
+// C++ includes
+#include <iostream>
+
+// Units
+#include "GeoModelKernel/Units.h"
+#define SYSTEM_OF_UNITS \
+    GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm'
+
+int main(int argc, char *argv[])
+{
+// Define the units
+#define gr SYSTEM_OF_UNITS::gram
+#define mole SYSTEM_OF_UNITS::mole
+
+    // get the World volume,
+    // we build it outside the class for convenience only
+    GeoIntrusivePtr<GeoPhysVol> world{createGeoWorld()};
+
+    // Define elements used in this example:
+    GeoElement *elAluminum = new GeoElement("Aluminum", "Al", 13, 26 * gr / mole);
+
+    // Define materials used in this example:
+    double densityOfAluminum = 2.7; // g/cm^3
+    GeoMaterial *matAluminum = new GeoMaterial("Aluminum", densityOfAluminum);
+    matAluminum->add(elAluminum, 1.0);
+    matAluminum->lock();
+
+
+      // Add a test GeoEllipticalTube shape
+      const double halfX = 5.0 * SYSTEM_OF_UNITS::cm;
+      const double halfY = 30.0 * SYSTEM_OF_UNITS::cm;
+      const double halfZ = 30.0 * SYSTEM_OF_UNITS::cm;
+  GeoEllipticalTube *sh = new GeoEllipticalTube(halfX, halfY, halfZ);                                                                          
+  GeoLogVol *lV = new GeoLogVol("ellipticaltube", sh, matAluminum);                    
+  GeoPhysVol *pV = new GeoPhysVol(lV);                                           
+  GeoNameTag *nT = new GeoNameTag("Shape-EllipticalTube");                                    
+  world->add(nT);                                                                           
+  world->add(pV);
+
+    // write to the test DB
+    std::string testDB = "test_io_shape_EllipticalTube.db";
+    unsigned loglevel = 2;
+    const bool forceDelete = true;
+    GeoModelIO::IO::saveToDB(world, testDB, loglevel, forceDelete);
+
+    // load from the test DB
+    const GeoVPhysVol *world2 = GeoModelIO::IO::loadDB(testDB);
+
+    // get the child volume, then the shape from its logVol
+    GeoIntrusivePtr<const GeoVPhysVol> childVol = world2->getChildVol(0);
+    const GeoEllipticalTube *shape = dynamic_cast<const GeoEllipticalTube *>(childVol->getLogVol()->getShape());
+
+
+    // data to test
+    std::vector<double> test_data_stored;
+    std::vector<double> test_data_restored;
+    std::vector<std::string> test_label;
+
+    test_data_stored.push_back(halfX);
+    test_data_restored.push_back(shape->getXHalfLength());
+    test_label.push_back("shape->getXHalfLength()");
+
+    bool test = true;
+    unsigned int ii{0};
+    for (const auto& num : test_data_stored) {
+        if (test_data_stored != test_data_restored)
+        {
+            std::cout << "\nERROR!!! The restored '" << test_label[ii] << "' is different from the stored version!!!" << std::endl;
+            std::cout << "Stored data: " << num << std::endl;
+            std::cout << "Restored data: " << test_data_restored[ii] << std::endl;
+            test = false;
+        }
+    }
+
+
+
+    if (shape->getXHalfLength() != halfX)
+    {
+        std::cout << "\nERROR!!! The restored 'getXHalfLength' is different from the stored version!!!" << std::endl;
+        std::cout << "Stored data: " << halfX << std::endl;
+        std::cout << "Restored data: " << shape->getXHalfLength() << std::endl;
+        test = false;
+    }
+    if (shape->getYHalfLength() != halfY)
+    {
+        std::cout << "\nERROR!!! The restored 'getYHalfLength' is different from the stored version!!!" << std::endl;
+        std::cout << "Stored data: " << halfY << std::endl;
+        std::cout << "Restored data: " << shape->getYHalfLength() << std::endl;
+        test = false;
+    }
+    if (shape->getZHalfLength() != halfZ)
+    {
+        std::cout << "\nERROR!!! The restored 'getZHalfLength' is different from the stored version!!!" << std::endl;
+        std::cout << "Stored data: " << halfZ << std::endl;
+        std::cout << "Restored data: " << shape->getZHalfLength() << std::endl;
+        test = false;
+    }
+    
+
+    // Return 0 if all OK! :-)
+    // Return 1 otherwise... :-(
+    if (test)
+        return 0;
+    return 1;
+    // ----------------
+}
diff --git a/GeoModelIO/GeoModelRead/CMakeLists.txt b/GeoModelIO/GeoModelRead/CMakeLists.txt
index 5ae4e4fb1878a249ab7cf847f74cb456065ccf4a..1c4b09d771568993c4d8b4bb322dcca28eb2678a 100644
--- a/GeoModelIO/GeoModelRead/CMakeLists.txt
+++ b/GeoModelIO/GeoModelRead/CMakeLists.txt
@@ -21,7 +21,7 @@ source_group( "src" FILES ${SOURCES} )
 set_target_properties( GeoModelRead PROPERTIES
    VERSION ${PROJECT_VERSION}
    SOVERSION ${PROJECT_VERSION_MAJOR} )
-
+ 
 # Set up an alias with the same name that you would get by "finding" a pre-built
 # version of the library.
 add_library( GeoModelIO::GeoModelRead ALIAS GeoModelRead )
diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
index 1651106ab03fbfe62650fa85d6585e066f772c64..3f7dfd127545266c9b7ec43aa0755b31064a80de 100644
--- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
+++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
@@ -77,8 +77,10 @@ class GeoSerialTransformer;
 class GeoGraphNode;
 class GeoShapeSubtraction;
 class GeoBox;
+class GeoEllipticalTube;
 
 class BuildGeoShapes_Box;
+class BuildGeoShapes_EllipticalTube;
 class BuildGeoShapes_Tube;
 class BuildGeoShapes_Cons;
 class BuildGeoShapes_Para;
@@ -169,6 +171,7 @@ class ReadGeoModel {
     };
     unsigned long getNShapes() { return m_shapes.size(); }; // TODO: to be removed later
     unsigned long getNShapes_Box() { return m_shapes_Box.size(); };
+    unsigned long getNShapes_EllipticalTube() { return m_shapes_EllipticalTube.size(); };
     unsigned long getNShapes_Cons() { return m_shapes_Cons.size(); };
     unsigned long getNShapes_Para() { return m_shapes_Para.size(); };
     unsigned long getNShapes_Pcon() { return m_shapes_Pcon.size(); };
@@ -190,6 +193,7 @@ class ReadGeoModel {
    private:
     void buildAllShapes(); // TODO: OLD METHOD, TO BE REMOVED WHEN READY
     void buildAllShapes_Box();
+    void buildAllShapes_EllipticalTube();
     void buildAllShapes_Tube();
     void buildAllShapes_Cons();
     void buildAllShapes_Para();
@@ -405,6 +409,7 @@ class ReadGeoModel {
     // std::unique_ptr<BuildGeoShapes_Box> m_builderShape_Box;
     BuildGeoVSurface*   buildsurfTool{};
     BuildGeoShapes_Box* m_builderShape_Box{};
+    BuildGeoShapes_EllipticalTube* m_builderShape_EllipticalTube{};
     BuildGeoShapes_Tube* m_builderShape_Tube{};
     BuildGeoShapes_Cons* m_builderShape_Cons{};
     BuildGeoShapes_Para* m_builderShape_Para{};
@@ -448,6 +453,7 @@ class ReadGeoModel {
 
     // containers to store shapes' parameters
     DBRowsList m_shapes_Box;
+    DBRowsList m_shapes_EllipticalTube;
     DBRowsList m_shapes_Tube;
     DBRowsList m_shapes_Cons;
     DBRowsList m_shapes_Para;
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_EllipticalTube.cpp b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_EllipticalTube.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..25f8d328e73ea422806ccf5148368c87dcd77aa0
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_EllipticalTube.cpp
@@ -0,0 +1,36 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ */
+
+#include "BuildGeoShapes_EllipticalTube.h"
+
+#include "GeoModelKernel/GeoEllipticalTube.h"
+#include "GeoModelHelpers/variantHelpers.h"
+
+#include <vector>
+#include <iostream>
+
+void BuildGeoShapes_EllipticalTube::buildShape(const DBRowEntry row)
+{
+    // === get shape numeric data from the DB row
+    // shape ID
+    const unsigned shapeId = GeoModelHelpers::variantHelper::getFromVariant_Int(row[0], "EllipticalTube:shapeID");
+    // shape volume
+    const double shapeVolume = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "EllipticalTube:shapeVolume");
+    // shape parameters
+    const double XHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "EllipticalTube:XHalfLength");
+    const double YHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[3], "EllipticalTube:YHalfLength");
+    const double ZHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "EllipticalTube:ZHalfLength");
+
+    GeoEllipticalTube *shape = new GeoEllipticalTube(XHalfLength, YHalfLength, ZHalfLength);
+
+    storeBuiltShape(shapeId, shape);
+
+    // return shape;
+    return;
+}
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_EllipticalTube.h b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_EllipticalTube.h
new file mode 100644
index 0000000000000000000000000000000000000000..39491304ba9a4018630a2dfe7edcf46f716afc8f
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_EllipticalTube.h
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * BuildGeoShapes_EllipticalTube.h
+ *
+ * Created on: Oct 3, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ *
+ */
+
+#ifndef GEOMODELREAD_BUILDGEOSHAPES_EllipticalTube_H
+#define GEOMODELREAD_BUILDGEOSHAPES_EllipticalTube_H
+
+#include "BuildGeoShapes.h"
+
+#include <vector>
+#include <variant>
+
+class BuildGeoShapes_EllipticalTube : public BuildGeoShapes
+{
+public:
+  BuildGeoShapes_EllipticalTube(const unsigned size):BuildGeoShapes("EllipticalTube", size){};
+  void buildShape(const DBRowEntry row) override;
+};
+
+#endif
diff --git a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
index 79461fb441313320ef29f5a2aa8a22f3034750d5..efad0d7287e0a95b68bf8f96590282147f2a5b31 100644
--- a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
+++ b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
@@ -25,14 +25,16 @@
  *              https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39
  *  - May 2024, R.M.Bianchi <riccardo.maria.bianchi@cern.ch>
  *              Major re-write: moved to the new DB schema based on numeric data
- *
  *  - Jun 2024, R.Xue  <r.xue@cern.ch><rux23@pitt.edu>
  *              Added methods to read in virtual surfaces from .db files
+ *  - Oct 2024, Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>,                                  
+ *              Support for the EllipticalTube shape was added. 
  *
  */
 
 // local includes
 #include "BuildGeoShapes_Box.h"
+#include "BuildGeoShapes_EllipticalTube.h"
 #include "BuildGeoShapes_Tube.h"
 #include "BuildGeoShapes_Cons.h"
 #include "BuildGeoShapes_Para.h"
@@ -79,6 +81,7 @@
 
 // GeoModel shapes
 #include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoEllipticalTube.h"
 #include "GeoModelKernel/GeoCons.h"
 #include "GeoModelKernel/GeoGenericTrap.h"
 #include "GeoModelKernel/GeoPara.h"
@@ -196,9 +199,6 @@ ReadGeoModel::ReadGeoModel(GMDBManager* db, unsigned long* progress)
     m_dbManager->loadGeoNodeTypesAndBuildCache();
     m_dbManager->createTableDataCaches();
 
-    // prepare builders
-    // m_builderShape_Box = std::make_unique<BuildGeoShapes_Box>();
-
     // Check if the user asked for running in serial or multi-threading mode
     if ("" != GeoStrUtils::getEnvVar("GEOMODEL_ENV_IO_NTHREADS")) {
         int nThreads = std::stoi(GeoStrUtils::getEnvVar("GEOMODEL_ENV_IO_NTHREADS"));
@@ -239,6 +239,7 @@ ReadGeoModel::ReadGeoModel(GMDBManager* db, unsigned long* progress)
 
 ReadGeoModel::~ReadGeoModel() {
     delete m_builderShape_Box;
+    delete m_builderShape_EllipticalTube;
     delete m_builderShape_Tube;
     delete m_builderShape_Pcon;
     delete m_builderShape_Cons;
@@ -252,6 +253,7 @@ ReadGeoModel::~ReadGeoModel() {
     delete m_builderShape_GenericTrap;
     delete m_builderShape_UnidentifiedShape;
     m_builderShape_Box = nullptr;
+    m_builderShape_EllipticalTube = nullptr;
     m_builderShape_Tube = nullptr;
     m_builderShape_Pcon = nullptr;
     m_builderShape_Cons = nullptr;
@@ -321,6 +323,7 @@ void ReadGeoModel::loadDB() {
 
     // shapes from the new DB schema
     m_shapes_Box = m_dbManager->getTableFromNodeType_VecVecData("GeoBox");
+    m_shapes_EllipticalTube = m_dbManager->getTableFromNodeType_VecVecData("GeoEllipticalTube");
     m_shapes_Tube = m_dbManager->getTableFromNodeType_VecVecData("GeoTube");
     m_shapes_Cons = m_dbManager->getTableFromNodeType_VecVecData("GeoCons");
     m_shapes_Para = m_dbManager->getTableFromNodeType_VecVecData("GeoPara");
@@ -415,6 +418,7 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
         std::thread t26(&ReadGeoModel::buildAllShapes_UnidentifiedShape, this);
         std::thread t27(&ReadGeoModel::buildAllShapes_Torus, this);
         std::thread t28(&ReadGeoModel::buildAllShapes_GenericTrap, this);
+        std::thread t29(&ReadGeoModel::buildAllShapes_EllipticalTube, this);
         
 
         t2.join();  // ok, all Elements have been built
@@ -436,6 +440,7 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
         t26.join();  // ok, all Shapes-UnidentifiedShape have been built
         t27.join();  // ok, all Shapes-Torus have been built
         t28.join();  // ok, all Shapes-GenericTrap have been built
+        t29.join();  // ok, all Shapes-EllipticalTube have been built
 
 	    // Build boolean shapes and shape operators,
         // this needs Shapes to be built
@@ -479,6 +484,7 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
         buildAllNameTags();
         // buildAllShapes();
         buildAllShapes_Box();
+        buildAllShapes_EllipticalTube();
         buildAllShapes_Tube();
         buildAllShapes_Pcon();
         buildAllShapes_Pgon();
@@ -657,6 +663,29 @@ void ReadGeoModel::buildAllShapes_Box()
         std::cout << "All " << nSize << " Shapes-Box have been built!\n";
     }
 }
+//! Iterate over the list of GeoEllipticalTube shape nodes, build them all, 
+//! and store their pointers
+void ReadGeoModel::buildAllShapes_EllipticalTube()
+{
+    if (m_loglevel >= 1) {
+        std::cout << "Building all shapes -- EllipticalTube ...\n";
+    }
+
+    // create a builder and reserve size of memory map
+    size_t nSize = m_shapes_EllipticalTube.size();
+    m_builderShape_EllipticalTube = new BuildGeoShapes_EllipticalTube(nSize);
+
+    // loop over the DB rows and build the shapes
+    for (const auto &row : m_shapes_EllipticalTube)
+    {
+        // GeoModelIO::CppHelper::printStdVectorVariants(row); // DEBUG MSG
+        m_builderShape_EllipticalTube->buildShape(row);
+    }
+    // m_builderShape_EllipticalTube->printBuiltShapes(); // DEBUG MSG
+    if (nSize > 0) {
+        std::cout << "All " << nSize << " Shapes-EllipticalTube have been built!\n";
+    }
+}
 //! Iterate over the list of GeoTube shape nodes, build them all, 
 //! and store their pointers
 void ReadGeoModel::buildAllShapes_Tube()
@@ -3279,7 +3308,7 @@ return (!(m_memMapShapes_Union.find(id) == m_memMapShapes_Union.end()));
 }
 // --- methods for caching GeoShape nodes ---
 bool ReadGeoModel::isBuiltShape(std::string_view shapeType, const unsigned shapeId) {
-const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons", "Para", "Pgon", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "SimplePolygonBrep", "GenericTrap", "Shift", "Subtraction", "Intersection", "Union"};
+const std::set<std::string> shapesNewDB{"Box", "EllipticalTube", "Tube", "Pcon", "Cons", "Para", "Pgon", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "SimplePolygonBrep", "GenericTrap", "Shift", "Subtraction", "Intersection", "Union"};
     // get shape parameters
     if (std::count(shapesNewDB.begin(), shapesNewDB.end(), shapeType))
     {
@@ -3287,6 +3316,10 @@ const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons", "Para", "
         {
             return m_builderShape_Box->isBuiltShape(shapeId);
         }
+        else if ("EllipticalTube" == shapeType)
+        {
+            return m_builderShape_EllipticalTube->isBuiltShape(shapeId);
+        }
         else if ("Tube" == shapeType)
         {
             return m_builderShape_Tube->isBuiltShape(shapeId);
@@ -3524,7 +3557,7 @@ void ReadGeoModel::storeBuiltVSurface(GeoVSurface* nodePtr) {
 GeoShape *ReadGeoModel::getBuiltShape(const unsigned shapeId, std::string_view shapeType)
 {
 
-    const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons", "Para", "Pgon", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "SimplePolygonBrep", "GenericTrap", "Shift", "Intersection", "Subtraction", "Union", "UnidentifiedShape"};
+    const std::set<std::string> shapesNewDB{"Box", "EllipticalTube", "Tube", "Pcon", "Cons", "Para", "Pgon", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "SimplePolygonBrep", "GenericTrap", "Shift", "Intersection", "Subtraction", "Union", "UnidentifiedShape"};
     // get shape parameters
     if (std::count(shapesNewDB.begin(), shapesNewDB.end(), shapeType))
     {
@@ -3532,6 +3565,10 @@ GeoShape *ReadGeoModel::getBuiltShape(const unsigned shapeId, std::string_view s
         {
             return m_builderShape_Box->getBuiltShape(shapeId);
         }
+        else if ("EllipticalTube" == shapeType)
+        {
+            return m_builderShape_EllipticalTube->getBuiltShape(shapeId);
+        }
         else if ("Tube" == shapeType)
         {
             return m_builderShape_Tube->getBuiltShape(shapeId);
diff --git a/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h b/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h
index 192082eb6cab842fab2e4080278ff970d1664f9b..9f926d4674266cb0d1e8b64a4fe557368029905b 100644
--- a/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h
+++ b/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h
@@ -20,9 +20,13 @@
  *              Also added methods to get the numbers of visited nodes.
  * - Feb 2023 - R.M.Bianchi <riccardo.maria.bianchi@cern.ch>
  *              Added 'setLoglevel' method, to steer output messages
- *
  * - Jun 2024 - R.Xue <r.xue@cern.ch><rux23@pitt.edu>
  *              Added methods to write out virtual surfaces to .db files
+ * - May 2024 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>,
+ *              Major change: we move to the new DB schema that uses numerical data
+ *              instead of strings/TEXT
+ * - Oct 2024 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>,
+ *              Support for the EllipticalTube shape was added.
  */
 
 #ifndef GeoModelWrite_WriteGeoModel_H
@@ -158,6 +162,7 @@ class WriteGeoModel : public GeoNodeAction {
     };
     unsigned long getNShapes() { return m_shapes.size(); }; // TODO: to be removed later
     unsigned long getNShapes_Box() { return m_shapes_Box.size(); };
+    unsigned long getNShapes_EllipticalTube() { return m_shapes_EllipticalTube.size(); };
     unsigned long getNShapes_Cons() { return m_shapes_Cons.size(); };
     unsigned long getNShapes_Para() { return m_shapes_Para.size(); };
     unsigned long getNShapes_Pcon() { return m_shapes_Pcon.size(); };
@@ -410,6 +415,7 @@ class WriteGeoModel : public GeoNodeAction {
     DBRowsList m_materials_Data;
 
     DBRowsList m_shapes_Box;
+    DBRowsList m_shapes_EllipticalTube;
     DBRowsList m_shapes_Tube;
     DBRowsList m_shapes_Cons;
     DBRowsList m_shapes_Para;
diff --git a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp
index b0c362b01968479b68de418862bc975414207784..6ea6a2da2c7ebe07e369522d4af03a820f18c48c 100644
--- a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp
+++ b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp
@@ -21,11 +21,18 @@
 // - Nov 2023 - R.M.Bianchi <riccardo.maria.bianchi@cern.ch>
 //              Updated to use the AlignableTransform 'default position', 
 //              which does not include alignment constants
-//
-// - May 2024 - Major change: we move to the new DB schema that uses numerical data
+// - May 2024 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>,
+//              Major change: we move to the new DB schema that uses numerical data
 //              instead of strings/TEXT
 // - Jun 2024 - R.Xue  <r.xue@cern.ch><rux23@pitt.edu>
 //              Added methods to write out virtual surfaces to .db files
+// - May 2024 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>,
+//              Major change: we move to the new DB schema that uses numerical data
+//              instead of strings/TEXT
+// - Oct 2024 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>,
+//              Support for the EllipticalTube shape was added.
+//
+
 
 // local includes
 #include "GeoModelWrite/WriteGeoModel.h"
@@ -41,6 +48,7 @@
 #include "GeoModelKernel/GeoNodePath.h"
 // GeoModelKernel shapes
 #include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoEllipticalTube.h"
 #include "GeoModelKernel/GeoCons.h"
 #include "GeoModelKernel/GeoGenericTrap.h"
 #include "GeoModelKernel/GeoPara.h"
@@ -779,7 +787,7 @@ std::pair<std::string, unsigned> WriteGeoModel::storeShape(const GeoShape* shape
     // LArCustomShape is deprecated.  Write it out as a GeoUnidentifiedShape;
     if (shapeType == "CustomShape") shapeType = "UnidentifiedShape";
 
-    const std::set<std::string> shapesNewDB{"Box", "Tube", "Cons", "Para", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "Pcon", "Pgon", "SimplePolygonBrep", "GenericTrap", "Intersection", "Shift", "Subtraction", "Union", "UnidentifiedShape"};
+    const std::set<std::string> shapesNewDB{"Box", "EllipticalTube", "Tube", "Cons", "Para", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "Pcon", "Pgon", "SimplePolygonBrep", "GenericTrap", "Intersection", "Shift", "Subtraction", "Union", "UnidentifiedShape"};
 
     // get shape parameters
     if (shapesNewDB.count(shapeType))
@@ -1129,6 +1137,13 @@ std::pair<DBRowEntry, DBRowsList> WriteGeoModel::getShapeParametersV(const GeoSh
         shapePars.push_back(box->getYHalfLength());
         shapePars.push_back(box->getZHalfLength());
     }
+    else if ("EllipticalTube" == shapeType)
+    {
+        const GeoEllipticalTube *box = dynamic_cast<const GeoEllipticalTube *>(shape);
+        shapePars.push_back(box->getXHalfLength());
+        shapePars.push_back(box->getYHalfLength());
+        shapePars.push_back(box->getZHalfLength());
+    }
     else if ("Tube" == shapeType)
     {
         const GeoTube *tube = dynamic_cast<const GeoTube *>(shape);
@@ -2142,6 +2157,10 @@ unsigned int WriteGeoModel::addShape(const std::string &type,
     {
         container = &m_shapes_Box;
     }
+    else if ("EllipticalTube" == type)
+    {
+        container = &m_shapes_EllipticalTube;
+    }
     else if ("Tube" == type)
     {
         container = &m_shapes_Tube;
@@ -2372,6 +2391,7 @@ void WriteGeoModel::saveToDB(std::vector<GeoPublisher*>& publishers) {
 
     m_dbManager->addListOfRecords("GeoShape", m_shapes); // OLD version, with shape's parameters as strings
     m_dbManager->addListOfRecords("GeoBox", m_shapes_Box); // new version, with shape's parameters as numbers
+    m_dbManager->addListOfRecords("GeoEllipticalTube", m_shapes_EllipticalTube); // new version, with shape's parameters as numbers
     m_dbManager->addListOfRecords("GeoTube", m_shapes_Tube); // new version, with shape's parameters as numbers
     m_dbManager->addListOfRecords("GeoCons", m_shapes_Cons); // new version, with shape's parameters as numbers
     m_dbManager->addListOfRecords("GeoPara", m_shapes_Para); // new version, with shape's parameters as numbers