diff --git a/macro/sts/geometry/create_stsgeo_v21f.C b/macro/sts/geometry/create_stsgeo_v21f.C
new file mode 100644
index 0000000000000000000000000000000000000000..b97c1a89af17ec1d5a0fa74321856136940e862d
--- /dev/null
+++ b/macro/sts/geometry/create_stsgeo_v21f.C
@@ -0,0 +1,2188 @@
+/* Copyright (C) 2012-2021 Goethe-Universitaet Frankfurt, Frankfurt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Mehul Shiroya [committer], Volker Friese, Evgeny Lavrik*/
+
+/******************************************************************************
+ ** Creation of STS geometry in ROOT format (TGeo).
+ **
+ ** @file create_stsgeo_v21f.C
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @since 15 June 2012
+ ** @date 09.05.2014
+ ** @author Tomas Balog <T.Balog@gsi.de>
+ ** 
+ ** v21f: Similar to the STS geometry version v21b
+ * 		  [ Airex foam in the front and  back side wall (Solid).
+ * 		  New beam pipe R = 2.0 cm  upstream-side with thickness 1 mm. 
+ * 		  Central ladders adjusted 5mm away from the beampipe.
+ * 		  Nomenclature for the Halfladders has been changed from the upside(u)	to top (t)
+ * 	      and from downside(d) to bottom (b). ]
+ * 		  The only difference is that it includes beampipe flange in the back side of the wall,
+ * 		  which is considered to be made of carbon fiber(70%) and epoxy resin(30%).	
+ * 
+ ** v19r: bugfix of v19q - align all halfladders
+ ** v19q: based on v19l - align ladders to virtual plane in station center, closing the gaps in z
+ ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm
+ ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm
+ ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m)
+ ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug)
+ ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm
+ ** v19k: ladders on upstream side of units get upper half ladders installed first, 
+ **       ladders on downstream side of units get lower half ladders installed first, 
+ **       this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits)
+ **       parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm
+ ** v19j: use overlap and distance parameters from CAD model
+ ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm
+ ** v19g: place a box with services around v19e
+ ** v19f: place a box with services around v19d
+ ** v19e: increase spacing between stations by +10 mm from 100 mm
+ ** v19d: increase spacing between stations by + 5 mm from 100 mm
+ ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c
+ ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits)
+ ** v19a: import passive materials from gdml file
+ **       extend CF ladder structures and cables towards FEE plane
+ **       change CF ladder frame shape
+ ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b)
+ ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials
+ ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu
+ ** v18a: adds 9 cooling/holding plates and a box around the setup
+ ** v16g: v16g is the new standard geometry from November 2017
+ ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R")
+ ** v16f: switch from stations to units
+ **     - split in upstream / downstream and left / right parts
+ **     - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL
+ ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D")
+ ** v16d: skip keeping volumes of sts and stations
+ ** v16c: like v16b, but senors of ladders beampipe next to beampipe
+ **       shifted closer to the pipe, like in the CAD model
+ ** v16b: like v16a, but yellow sensors removed
+ ** v16a: derived from v15c (no cones), but with sensor types renamed:
+ ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5
+ **
+ ** v15c: as v15b without cones
+ ** v15b: introduce modified carbon ladders from v13z
+ ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design
+ **
+ ** TODO:
+ **
+ ** DONE:
+ ** v15b - use carbon macaroni as ladder support
+ ** v15b - introduce a small gap between lowest sensor and carbon ladder
+ ** v15b - build small cones for the first 2 stations
+ ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm
+ ** v15b - for all ladders set an even number of ladder elements 
+ ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26
+ ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors
+ ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size
+ **
+ ** The geometry hierarachy is:
+ **
+ ** 1. Sensors  (see function CreateSensors)
+ **    The sensors are the active volumes and the lowest geometry level.
+ **    They are built as TGeoVolumes, shape box, material silicon.
+ **    x size is determined by strip pitch 58 mu and 1024 strips 
+ **    plus guard ring of 1.3 mm at each border -> 6.1992 cm.
+ **    Sensor type 1 is half of that (3.0792 cm).
+ **    y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus
+ **    guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm.
+ **    z size is a parameter, to be set by gkSensorThickness.
+ **
+ ** 2. Sectors  (see function CreateSectors)
+ **    Sectors consist of several chained sensors. These are arranged
+ **    vertically on top of each other with a gap to be set by
+ **    gkChainGapY. Sectors are constructed as TGeoVolumeAssembly.
+ **    The sectors are auxiliary volumes used for proper placement
+ **    of the sensor(s) in the module. They do not show up in the
+ **    final geometry.
+ **
+ ** 3. Modules (see function ConstructModule)
+ **    A module is a readout unit, consisting of one sensor or
+ **    a chain of sensors (see sector) and a cable.
+ **    The cable extends from the top of the sector vertically to the
+ **    top of the halfladder the module is placed in. The cable and module
+ **    volume thus depend on the vertical position of the sector in 
+ **    the halfladder. The cables consist of silicon with a thickness to be
+ **    set by gkCableThickness.
+ **    Modules are constructed as TGeoVolume, shape box, medium gStsMedium.
+ **    The module construction can be switched off (gkConstructCables)
+ **    to reproduce older geometries.
+ **
+ ** 4. Halfladders (see function ConstructHalfLadder)
+ **    A halfladder is a vertical assembly of several modules. The modules
+ **    are placed vertically such that their sectors overlap by 
+ **    gkSectorOverlapY. They are displaced in z direction to allow for the 
+ **    overlap in y by gkSectorGapZ.
+ **    The horizontal placement of modules in the halfladder can be choosen
+ **    to left aligned or right aligned, which only matters if sensors of
+ **    different x size are involved.
+ **    Halfladders are constructed as TGeoVolumeAssembly.
+ **
+ ** 5. Ladders (see function CreateLadders and ConstructLadder)
+ **    A ladder is a vertical assembly of two halfladders, and is such the
+ **    vertical building block of a station. The second (bottom) half ladder
+ **    is rotated upside down. The vertical arrangement is such that the
+ **    inner sectors of the two halfladders have the overlap gkSectorOverlapY
+ **    (function CreateLadder) or that there is a vertical gap for the beam
+ **    hole (function CreateLadderWithGap).
+ **    Ladders are constructed as TGeoVolumeAssembly.
+ **   
+ ** 6. Stations (see function ConstructStation)
+ **    A station represents one layer of the STS geometry: one measurement
+ **    at (approximately) a given z position. It consist of several ladders
+ **    arranged horizontally to cover the acceptance.
+ **    The ladders are arranged such that there is a horizontal overlap
+ **    between neighbouring ladders (gkLadderOverLapX) and a vertical gap
+ **    to allow for this overlap (gkLadderGapZ). Each second ladder is
+ **    rotated around its y axis to face away from or into the beam.
+ **    Stations are constructed as TGeoVolumes, shape box minus tube (for
+ **    the beam hole), material gStsMedium.
+ **
+ ** 7. STS
+ **    The STS is a volume hosting the entire detectors system. It consists
+ **    of several stations located at different z positions.
+ **    The STS is constructed as TGeoVolume, shape box minus cone (for the
+ **    beam pipe), material gStsMedium. The size of the box is computed to
+ **    enclose all stations.
+ *****************************************************************************/
+
+
+// Remark: With the proper steering variables, this should exactly reproduce
+// the geometry version v11b of A. Kotynia's described in the ASCII format.
+// The only exception is a minimal difference in the z position of the
+// sectors/sensors. This is because of ladder types 2 and 4 containing the half
+// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders
+// covering the beam hole cannot be transformed into each other by rotations,
+// but only by a reflection. This means they are constructionally different.
+// To avoid introducing another two ladder types, the difference in z position
+// was accepted.
+
+
+// Differences to v12:
+// gkChainGap reduced from 1 mm to 0
+// gkCableThickness increased from 100 mum to 200 mum (2 cables per module)
+// gkSectorOverlapY reduced from 3 mm to 2.4 mm
+// New sensor types 05 and 06
+// New sector types 07 and 08
+// Re-definiton of ladders (17 types instead of 8)
+// Re-definiton of station from new ladders
+
+
+#include "TGeoCompositeShape.h"
+#include "TGeoCone.h"
+#include "TGeoManager.h"
+#include "TGeoPara.h"
+#include "TGeoPhysicalNode.h"
+#include "TGeoTrd2.h"
+#include "TGeoTube.h"
+#include "TGeoXtru.h"
+
+#include <iomanip>
+#include <iostream>
+
+// forward declarations
+Int_t CreateSensors();
+Int_t CreateSectors();
+Int_t CreateLadders();
+TGeoVolume* ConstructModule(const char* name, TGeoVolume* sector, Double_t cableLength);
+TGeoVolume* ConstructHalfLadder(const TString& name, Int_t nSectors, Int_t* sectorTypes, char align,
+                                Double_t ladderLength, Double_t offsetY);
+TGeoVolume* ConstructLadder(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t gapY,
+                            Double_t shiftZ, Double_t pitchZ, Int_t nSectors);
+TGeoVolume* ConstructUnit(Int_t iSide, Int_t iUnit, Int_t nLadders, Int_t* ladderTypes, Int_t iStation);
+void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile);
+void PostProcessGdml(TGeoVolume* gdmlTop);
+void CheckVolume(TGeoVolume* volume);
+void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE);
+Double_t BeamPipeRadius(Double_t z);
+TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x);
+TGeoVolume* ConstructSmallCone(Double_t coneDz);
+TGeoVolume* ConstructBigCone(Double_t coneDz);
+
+// -------------   Version highlight        -----------------------------------
+
+const std::string gVersionHighlight = R"(
+Summary:
+  This version adds passive materials imported from GDML model to the STS geometry:
+    * Taken from and largely correspond to mechanical CAD drawings of the detector
+    * Thermal insulation box:
+      - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet)
+      - front window of complex shape with interface to MVD / target chamber
+      - back window with large aperture (2000 x 1200 mm) square cut into carbon foam
+    * Structural units:
+      - made of 2 complex shape aluminum C-Frames, 15mm thick
+      - placed at 25, 35, ... ,105 cm absolute Z
+      - contain front-end and power distribution boxes with equivalent X_0 values
+
+  Scripted geometry tweaks:
+    * Ladders and cables are extended towards the read-out planes having same lengths in respective rows
+    * Adjusted form and shape of carbon ladder structures from L-type to X-type
+    * Reduced verbosity of this file
+
+  Sensor arrangement is the same as in version v16g
+
+  !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall.
+  The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e
+)";
+
+// -------------   Steering variables       -----------------------------------
+
+// ---> Horizontal width of sensors [cm]
+const Double_t gkSensorSizeX = 6.2;  // was 6.2092;  // 6.2 - Oleg CAD 15/05/2020
+
+// ---> Thickness of sensors [cm]
+const Double_t gkSensorThickness = 0.03;
+
+// ---> Vertical gap between chained sensors [cm]
+const Double_t gkChainGapY = 0.00;
+
+// ---> Thickness of cables [cm]
+const Double_t gkCableThickness = 0.02;
+
+// ---> Horizontal overlap of neighbouring ladders [cm]
+const Double_t gkLadderOverlapX = 0.25;  // delta X - Oleg CAD 14/05/2020
+
+// ---> Vertical overlap of neighbouring sectors in a ladder [cm]
+const Double_t gkSectorOverlapY = 0.46;  // delta Y - Oleg CAD 14/05/2020
+
+// ---> Gap in z between neighbouring sectors in a ladder [cm]
+const Double_t gkSectorGapZ = 0.12;  // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020
+
+// ---> Gap in z between neighbouring ladders [cm]
+const Double_t gkLadderGapZ = 0.50 - 0.15;  // for asym // 0.5 for sym  // delta Z prime
+
+// ---> Gap in z between lowest sector to carbon support structure [cm]
+const Double_t gkSectorGapZFrame =
+  0.280
+  - 0.025;  // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder
+
+// ---> Switch to construct / not to construct readout cables
+const Bool_t gkConstructCables = kTRUE;
+
+// ---> Switch to construct / not to construct frames
+const Bool_t gkConstructCones       = kFALSE;  // kTRUE;   // switch this false by default for v15c and v16x
+const Bool_t gkConstructFrames      = kTRUE;   // kFALSE;  // switch this true  by default for v15c and v16x
+const Bool_t gkConstructSmallFrames = kTRUE;   // kFALSE;
+const Bool_t gkCylindricalFrames    = kTRUE;   // kFALSE;
+
+// ---> Size of the frame
+const Double_t gkFrameThickness     = 0.2;
+const Double_t gkThinFrameThickness = 0.05;
+const Double_t gkFrameStep          = 4.0;  // size of frame cell along y direction
+const Double_t gkCylinderDiaInner =
+  0.07;  // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015)
+const Double_t gkCylinderDiaOuter =
+  0.15;  // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015)
+
+// ---> Switch to import / not to import the Passive materials from GDML file
+const Bool_t gkImportPassive = kTRUE;
+
+// ----------------------------------------------------------------------------
+
+
+// --------------   Parameters of beam pipe in the STS region    --------------
+// ---> Needed to compute stations and STS such as to avoid overlaps
+const Double_t gkPipeZ1 = 18.0;
+const Double_t gkPipeR1 = 2.0;
+const Double_t gkPipeZ2 = 125.0;
+const Double_t gkPipeR2 = 5.0;
+//const Double_t gkPipeZ3 = 125.0;
+//const Double_t gkPipeR3 = 5.5;
+
+//const Double_t gkPipeZ2 = 50.0;
+//const Double_t gkPipeR2 = 1.8;
+
+//DE const Double_t gkPipeZ1 =  27.0;
+//DE const Double_t gkPipeR1 =   1.05;
+//DE const Double_t gkPipeZ2 = 160.0;
+//DE const Double_t gkPipeR2 =   3.25;
+// ----------------------------------------------------------------------------
+
+//TString unitName[16] =    // names of units for v16e
+// {            "Unit00D",
+//   "Unit01U", "Unit01D",
+//   "Unit02U", "Unit02D",
+//   "Unit03U", "Unit03D",
+//   "Unit04U", "Unit04D",
+//   "Unit05U", "Unit05D",
+//   "Unit06U", "Unit06D",
+//   "Unit07U", "Unit07D",
+//   "Unit08U"            };
+
+//TString unitName[32] =    // names of units for v16f
+// {                         "Unit00DR", "Unit00DL",
+//   "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL",
+//   "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL",
+//   "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL",
+//   "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL",
+//   "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL",
+//   "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL",
+//   "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL",
+//   "Unit08UR", "Unit08UL" };
+
+TString unitName[32] =  // names of units for v16g - while merging D and U parts
+  {"Unit00R", "Unit00L", "Unit01R", "Unit01L", "Unit01R", "Unit01L", "Unit02R", "Unit02L",
+   "Unit02R", "Unit02L", "Unit03R", "Unit03L", "Unit03R", "Unit03L", "Unit04R", "Unit04L",
+   "Unit04R", "Unit04L", "Unit05R", "Unit05L", "Unit05R", "Unit05L", "Unit06R", "Unit06L",
+   "Unit06R", "Unit06L", "Unit07R", "Unit07L", "Unit07R", "Unit07L", "Unit08R", "Unit08L"};
+
+TString unitName18[18] =  // names of units for v16g
+  {"Unit00R", "Unit00L", "Unit01R", "Unit01L", "Unit02R", "Unit02L", "Unit03R", "Unit03L", "Unit04R",
+   "Unit04L", "Unit05R", "Unit05L", "Unit06R", "Unit06L", "Unit07R", "Unit07L", "Unit08R", "Unit08L"};
+
+// -------------   Other global variables   -----------------------------------
+// ---> STS medium (for every volume except silicon)
+TGeoMedium* gStsMedium = NULL;  // will be set later
+// ---> TGeoManager (too lazy to write out 'Manager' all the time
+TGeoManager* gGeoMan = NULL;  // will be set later
+// ----------------------------------------------------------------------------
+
+
+// ============================================================================
+// ======                         Main function                           =====
+// ============================================================================
+
+void create_stsgeo_v21f(const char* geoTag = "v21f")
+{
+
+  // -------   Geometry file name (output)   ----------------------------------
+  TString geoFileName = "sts_";
+  geoFileName         = geoFileName + geoTag + ".geo.root";
+  // --------------------------------------------------------------------------
+
+
+  // -------   Open info file   -----------------------------------------------
+  TString infoFileName = geoFileName;
+  infoFileName.ReplaceAll("root", "info");
+  fstream infoFile;
+  infoFile.open(infoFileName.Data(), fstream::out);
+  infoFile << "STS geometry created with create_stsgeo_v21f.C" << endl;
+  infoFile << gVersionHighlight << endl;
+  infoFile << "Global variables: " << endl;
+  infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl;
+  infoFile << "Vertical gap in sensor chain = " << gkChainGapY << " cm" << endl;
+  infoFile << "Vertical overlap of sensors = " << gkSectorOverlapY << " cm" << endl;
+  infoFile << "Gap in z between neighbour sensors = " << gkSectorGapZ << " cm" << endl;
+  infoFile << "Horizontal overlap of sensors = " << gkLadderOverlapX << " cm" << endl;
+  infoFile << "Gap in z between neighbour ladders = " << gkLadderGapZ << " cm" << endl;
+  if (gkConstructCables) infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl;
+  else
+    infoFile << "No cables" << endl;
+  infoFile << endl;
+  infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " << gkPipeZ1 << " cm" << endl;
+  infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " << gkPipeZ2 << " cm" << endl;
+  //infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " << gkPipeZ3
+  //         << " cm" << endl;
+  // --------------------------------------------------------------------------
+
+
+  // -------   Load media from media file   -----------------------------------
+  FairGeoLoader* geoLoad    = new FairGeoLoader("TGeo", "FairGeoLoader");
+  FairGeoInterface* geoFace = geoLoad->getGeoInterface();
+  TString geoPath           = gSystem->Getenv("VMCWORKDIR");
+  TString medFile           = geoPath + "/geometry/media.geo";
+  geoFace->setMediaFile(medFile);
+  geoFace->readMedia();
+  gGeoMan = gGeoManager;
+  gSystem->Load("libGeom");
+  // --------------------------------------------------------------------------
+
+
+  // -----------------   Get and create the required media    -----------------
+  FairGeoMedia* geoMedia   = geoFace->getMedia();
+  FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
+
+  // ---> air
+  FairGeoMedium* mAir = geoMedia->getMedium("air");
+  if (!mAir) Fatal("Main", "FairMedium air not found");
+  geoBuild->createMedium(mAir);
+  TGeoMedium* air = gGeoMan->GetMedium("air");
+  if (!air) Fatal("Main", "Medium air not found");
+
+  // ---> air
+  FairGeoMedium* mvacuum = geoMedia->getMedium("vacuum");
+  if (!mvacuum) Fatal("Main", "FairMedium vacuum not found");
+  geoBuild->createMedium(mvacuum);
+  TGeoMedium* Vacuum = gGeoMan->GetMedium("vacuum");
+  if (!Vacuum) Fatal("Main", "Medium vacuum not found");
+
+
+  // ---> silicon
+  FairGeoMedium* mSilicon = geoMedia->getMedium("silicon");
+  if (!mSilicon) Fatal("Main", "FairMedium silicon not found");
+  geoBuild->createMedium(mSilicon);
+  TGeoMedium* silicon = gGeoMan->GetMedium("silicon");
+  if (!silicon) Fatal("Main", "Medium silicon not found");
+
+  // ---> carbon
+  FairGeoMedium* mCarbon = geoMedia->getMedium("carbon");
+  if (!mCarbon) Fatal("Main", "FairMedium carbon not found");
+  geoBuild->createMedium(mCarbon);
+  TGeoMedium* carbon = gGeoMan->GetMedium("carbon");
+  if (!carbon) Fatal("Main", "Medium carbon not found");
+
+  // ---> STSBoxCarbonFoam
+  FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam");
+  if (!mSTSBoxCarbonFoam) Fatal("Main", "FairMedium STSBoxCarbonFoam not found");
+  geoBuild->createMedium(mSTSBoxCarbonFoam);
+  TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam");
+  if (!STSBoxCarbonFoam) Fatal("Main", "Medium STSBoxCarbonFoam not found");
+
+  // ---> STSBoxCarbonFibre
+  FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre");
+  if (!mSTSBoxCarbonFibre) Fatal("Main", "FairMedium STSBoxCarbonFibre not found");
+  geoBuild->createMedium(mSTSBoxCarbonFibre);
+  TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre");
+  if (!STSBoxCarbonFibre) Fatal("Main", "Medium STSBoxCarbonFibre not found");
+
+  // ---> STScable
+  FairGeoMedium* mSTScable = geoMedia->getMedium("STScable");
+  if (!mSTScable) Fatal("Main", "FairMedium STScable not found");
+  geoBuild->createMedium(mSTScable);
+  TGeoMedium* STScable = gGeoMan->GetMedium("STScable");
+  if (!STScable) Fatal("Main", "Medium STScable not found");
+
+  // ---> Aluminium
+  FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium");
+  if (!mAluminium) Fatal("Main", "FairMedium aluminium not found");
+  geoBuild->createMedium(mAluminium);
+  TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium");
+  if (!aluminium) Fatal("Main", "Medium aluminium not found");
+
+  // ---
+  //gStsMedium = air;
+  gStsMedium = gGeoMan->GetMedium("air");
+  if (!gStsMedium) Fatal("Main", "medium sts_air not found");
+  // --------------------------------------------------------------------------
+  // --------------------------------------------------------------------------
+
+
+  // --------------   Create geometry and top volume  -------------------------
+  gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
+  //gGeoMan->SetName("STSgeom");
+  TGeoVolume* top = new TGeoVolumeAssembly("top");
+  //  TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.);
+  //  TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air"));
+  gGeoMan->SetTopVolume(top);
+
+  // --------------------------------------------------------------------------
+
+
+  // --------------   Create media   ------------------------------------------
+  /*
+  cout << endl;
+  cout << "===> Creating media....";
+  cout << CreateMedia();
+  cout << " media created" << endl;
+  TList* media = gGeoMan->GetListOfMedia();
+  for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) {
+    cout << "Medium " << iMedium << ": " 
+   << ((TGeoMedium*) media->At(iMedium))->GetName() << endl;
+  }
+   
+  gStsMedium = gGeoMan->GetMedium("air");
+  if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found");
+  */
+  // --------------------------------------------------------------------------
+
+
+  // ---------------   Create sensors   ---------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating sensors...." << endl << endl;
+  infoFile << endl << "Sensors: " << endl;
+  Int_t nSensors = CreateSensors();
+  for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) {
+    TString name       = Form("Sensor%02d", iSensor);
+    TGeoVolume* sensor = gGeoMan->GetVolume(name);
+
+    // add color to sensors
+    if (iSensor == 1) sensor->SetLineColor(kRed);
+    if (iSensor == 2) sensor->SetLineColor(kGreen + 3);
+    if (iSensor == 3) sensor->SetLineColor(kBlue + 3);
+    if (iSensor == 4) sensor->SetLineColor(kAzure - 7);
+    if (iSensor == 5) sensor->SetLineColor(kYellow);
+    if (iSensor == 6) sensor->SetLineColor(kYellow);
+    if (iSensor == 7) sensor->SetLineColor(kYellow);
+
+    CheckVolume(sensor);
+    CheckVolume(sensor, infoFile);
+  }
+  // --------------------------------------------------------------------------
+
+
+  // ----------------   Create sectors   --------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating sectors...." << endl;
+  // infoFile << endl << "Sectors: " << endl;
+  Int_t nSectors = CreateSectors();
+  for (Int_t iSector = 1; iSector <= nSectors; iSector++) {
+    // cout << endl;
+    TString name       = Form("Sector%02d", iSector);
+    TGeoVolume* sector = gGeoMan->GetVolume(name);
+    CheckVolume(sector);
+    // CheckVolume(sector, infoFile);
+  }
+  // --------------------------------------------------------------------------
+
+
+  // ----------------   Create ladders   --------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating ladders...." << endl;
+  infoFile << endl << "Ladders:" << endl;
+
+  TString name = "";
+  TGeoVolume* ladder;
+
+
+  Int_t nLadders = CreateLadders();
+
+  for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) {
+    cout << endl;
+
+    //    name = Form("LadderType%02d", iLadder);  // v19a
+    //    name = Form("LadderType0%02d", iLadder); // v19b
+    name   = Form("LadderType00%02d", iLadder);  // v19k
+    ladder = gGeoMan->GetVolume(name);
+    CheckVolume(ladder);
+    CheckVolume(ladder, infoFile, kFALSE);
+
+    cout << "DF1: ladder name: " << name << endl << endl;
+
+    //    name = Form("LadderType%02d", iLadder);  // v19a
+    //    name = Form("LadderType1%02d", iLadder); // v19b
+    name   = Form("LadderType01%02d", iLadder);  // v19k
+    ladder = gGeoMan->GetVolume(name);
+    CheckVolume(ladder);
+    CheckVolume(ladder, infoFile, kFALSE);
+
+    cout << "DF2: ladder name: " << name << endl << endl;
+
+    //    name = Form("LadderType%02d", iLadder);  // v19a
+    name   = Form("LadderType10%02d", iLadder);  // v19k
+    ladder = gGeoMan->GetVolume(name);
+    CheckVolume(ladder);
+    CheckVolume(ladder, infoFile, kFALSE);
+
+    cout << "DF3: ladder name: " << name << endl << endl;
+
+    //    name = Form("LadderType%02d", iLadder);  // v19a
+    name   = Form("LadderType11%02d", iLadder);  // v19k
+    ladder = gGeoMan->GetVolume(name);
+    CheckVolume(ladder);
+    CheckVolume(ladder, infoFile, kFALSE);
+
+    cout << "DF4: ladder name: " << name << endl << endl;
+  }
+  // --------------------------------------------------------------------------
+
+
+  // ----------------   Create cones   ----------------------------------------
+  Double_t coneDz            = 1.64;
+  TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz);
+  if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found");
+  TGeoVolume* coneBigVolum = ConstructBigCone(coneDz);
+  if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found");
+  // --------------------------------------------------------------------------
+
+  // ----------------   Create stations   -------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating stations...." << endl;
+  infoFile << endl << "Stations: " << endl;
+  Int_t angle = 0;
+  nLadders    = 0;
+  Int_t ladderTypes[16];  // there are max 16 ladders in one layer
+  TGeoTranslation* statTrans = NULL;
+
+  TGeoVolume* myunit[32];  // units
+
+  //  Int_t statPos[16]   = { 30, 30, 40, 40, 50, 50,  60,  60,
+  //                          70, 70, 80, 80, 90, 90, 100, 100 };  // z positions of units
+  //  Int_t statPos18[18] = { 30, 30,                              // expanded for placement of Unit00
+  //                          30, 30, 40, 40, 50, 50,  60,  60,
+  //                          70, 70, 80, 80, 90, 90, 100, 100 };  // z positions of units
+
+  Double_t statPos[16]   = {30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5,  61.5,
+                          72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5};  // z positions of units
+  Double_t statPos18[18] = {30.0, 30.0,                                         // expanded for placement of Unit00
+                            30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5,  61.5,
+                            72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5};  // z positions of unit
+
+  //Double_t statPos[16]   = {26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5,  57.5,
+  //                        68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5};  // z positions of units
+  //Double_t statPos18[18] = {26.0, 26.0,                                         // expanded for placement of Unit00
+  //                          26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5,  57.5,
+  //                          68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5};  // z positions of unit
+
+
+  ////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 };  // size of cutouts in stations
+  //  Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 };  // size of cutouts in stations, derived from gapXYZ[x][1]/2
+
+  Int_t cone_size[8] = {0, 0, 0, 1, 1, 1, 1, 1};  // size of cones: 0 = small, 1 = large
+
+  Double_t cone_offset[2] = {0.305, 0.285};
+
+  //==============================================================================================
+
+  // explanation: type xyzz
+  // where  x = carbon ladder orientation
+  // where  y = FEB box orientation
+  // where zz = sensor arrangement on ladder
+  // with FEB orientation - v19b
+  Int_t allUnitTypes[16][16] = {
+    {-1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1},         // unit00D Station01 00
+    {-1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1},  // unit01U Station01 01
+
+    {-1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1},             // unit01D Station02 02
+    {-1, -1, 1130, 0, 1129, 0, 1128, 0, 1002, 0, 1028, 0, 1029, 0, -1, -1},  // unit02U Station02 03
+
+    {-1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1},           // unit02D Station03 04
+    {-1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1},  // unit03U Station03 05
+
+    {-1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1},              // unit03D Station04 06
+    {-1, 0, 1133, 0, 1131, 0, 1131, 0, 1004, 0, 1031, 0, 1032, 0, 1034, -1},  // unit04U Station04 07
+
+    {-1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1},            // unit04D Station05 08
+    {-1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1},  // unit05U Station05 09
+
+    {-1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1},              // unit05D Station06 10
+    {-1, 0, 1137, 0, 1136, 0, 1135, 0, 1006, 0, 1035, 0, 1036, 0, 1038, -1},  // unit06U Station06 11
+
+    {21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0},              // unit06D Station07 12
+    {0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021},  // unit07U Station07 13
+
+    {0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126},                // unit07D Station08 14
+    {1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0}};  // unit08U Station08 15
+
+
+  //==============================================================================================
+
+  // without FEB orientation - v19a
+  // v19a   Int_t allUnitTypes[16][16]=
+  // v19a   { {  -1,  -1,  -1,  -1,  10,   0,   9,   0,     1,   0,   9,   0,  -1,  -1,  -1,  -1 },    // unit00D Station01 00
+  // v19a     {  -1,  -1,  -1,  -1,   0, 109,   0, 101,     0, 109,   0, 110,  -1,  -1,  -1,  -1 },    // unit01U Station01 01
+  // v19a     {  -1,  -1,   0,  10,   0,   9,   0,   2,     0,   9,   0,  10,   0,  11,  -1,  -1 },    // unit01D Station02 02
+  // v19a     {  -1,  -1, 111,   0, 110,   0, 109,   0,   102,   0, 109,   0, 110,   0,  -1,  -1 },    // unit02U Station02 03
+  // v19a     {  -1,  -1,  14,   0,  12,   0,  12,   0,     3,   0,  12,   0,  13,   0,  -1,  -1 },    // unit02D Station03 04
+  // v19a     {  -1,  -1,   0, 113,   0, 112,   0, 103,     0, 112,   0, 112,   0, 114,  -1,  -1 },    // unit03U Station03 05
+  // v19a     {  -1,  15,   0,  13,   0,  12,   0,   4,     0,  12,   0,  12,   0,  14,   0,  -1 },    // unit03D Station04 06
+  // v19a     {  -1,   0, 114,   0, 112,   0, 112,   0,   104,   0, 112,   0, 113,   0, 115,  -1 },    // unit04U Station04 07
+  // v19a     {  -1,   0,  18,   0,  17,   0,  16,   0,     5,   0,  16,   0,  17,   0,  19,  -1 },    // unit04D Station05 08
+  // v19a     {  -1, 119,   0, 117,   0, 116,   0, 105,     0, 116,   0, 117,   0, 118,   0,  -1 },    // unit05U Station05 09
+  // v19a     {  -1,  19,   0,  17,   0,  16,   0,   6,     0,  16,   0,  17,   0,  18,   0,  -1 },    // unit05D Station06 10
+  // v19a     {  -1,   0, 118,   0, 117,   0, 116,   0,   106,   0, 116,   0, 117,   0, 119,  -1 },    // unit06U Station06 11
+  // v19a     {  21,   0,  25,   0,  20,   0,  20,   0,     7,   0,  20,   0,  20,   0,  27,   0 },    // unit06D Station07 12
+  // v19a     {   0, 127,   0, 120,   0, 120,   0, 107,     0, 120,   0, 120,   0, 125,   0, 121 },    // unit07U Station07 13
+  // v19a     {   0,  24,   0,  22,   0,  22,   0,   8,     0,  22,   0,  22,   0,  23,   0,  26 },    // unit07D Station08 14
+  // v19a     { 126,   0, 123,   0, 122,   0, 122,   0,   108,   0, 122,   0, 122,   0, 124,   0 } };  // unit08U Station08 15
+
+  //  // generate unit
+  //  for (Int_t iUnit = 0; iUnit < 16; iUnit++)
+  //    for (Int_t iLadder = 0; iLadder < 16; iLadder++)
+  //    {
+  //      allUnitTypes[iUnit][iLadder] = 0;
+  //      if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] <  100))  // if carbon structure is oriented upstream
+  //        allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder];
+  //      if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100))  // if carbon structure is oriented downstream
+  //        allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder];
+  //    }
+
+
+  // dump unit
+  for (Int_t iUnit = 0; iUnit < 16; iUnit++) {
+    cout << "DE unitTypes[" << iUnit << "] = { ";
+    for (Int_t iLadder = 0; iLadder < 16; iLadder++) {
+      cout << allUnitTypes[iUnit][iLadder];
+      if (iLadder < 15) cout << ", ";
+      else
+        cout << " };";
+    }
+    cout << endl;
+  }
+
+
+  // --- Units 01 - 16
+  for (Int_t iUnit = 0; iUnit < 16; iUnit++) {
+    cout << endl;
+
+    nLadders = 0;
+    //int ladderTypes[nLadders];
+    for (Int_t iLadder = 0; iLadder < 16; iLadder++)
+      if (allUnitTypes[iUnit][iLadder] >= 0) {
+        ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder];
+        cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl;
+        nLadders++;
+      }
+    myunit[iUnit * 2 + 0] = ConstructUnit(0, iUnit * 2 + 0, nLadders, ladderTypes, iUnit / 2 + 1);
+    myunit[iUnit * 2 + 1] = ConstructUnit(1, iUnit * 2 + 1, nLadders, ladderTypes, iUnit / 2 + 1);
+
+    //    if (gkConstructCones) {
+    //      if (iUnit%2 == 0)
+    //        angle =  90;
+    //      else
+    //        angle = -90;
+    //
+    //      // upstream
+    //      TGeoRotation* coneRot11 = new TGeoRotation;
+    //      coneRot11->RotateZ(angle);
+    //      coneRot11->RotateY(180);
+    //      TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11);
+    //      if (cone_size[iUnit] == 0)
+    //        myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11);
+    //      else
+    //        myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11);
+    //
+    //      // downstream
+    //      TGeoRotation* coneRot12 = new TGeoRotation;
+    //      coneRot12->RotateZ(angle);
+    //      TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0.,  coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12);
+    //      if (cone_size[iUnit] == 0)
+    //        myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12);
+    //      else
+    //        myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12);
+    //
+    //      myunit[iUnit]->GetShape()->ComputeBBox();
+    //    }
+
+    //    CheckVolume(myunit[iUnit]);
+    //    CheckVolume(myunit[iUnit], infoFile);
+    if ((iUnit % 2 == 0) || (iUnit == 15)) {
+      CheckVolume(myunit[iUnit * 2 + 0]);
+      CheckVolume(myunit[iUnit * 2 + 0], infoFile);
+      CheckVolume(myunit[iUnit * 2 + 1]);
+      CheckVolume(myunit[iUnit * 2 + 1], infoFile);
+    }
+    infoFile << "Position z = " << statPos[iUnit] << endl;
+  }
+  // --------------------------------------------------------------------------
+
+
+  // ---------------   Create STS volume   ------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating STS...." << endl;
+
+  // --- Create STS volume
+  TString stsName = "sts_";
+  stsName += geoTag;
+
+  //  TGeoShape* stsShape = new TGeoCompositeShape("stsShape",
+  //                                               "stsBox-stsCone1:trans1-stsCone2:trans2");
+  //  TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium);
+
+  Double_t stsBorder = 2 * 5.;
+
+  TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data());
+
+  // --- Place stations in the STS
+  Double_t stsPosZ = 0.5 * (statPos[15] + statPos[0]);  // todo units: update statPos[7]
+  //  cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl;
+
+  //  for (Int_t iUnit = 0; iUnit < 16; iUnit++) {
+  for (Int_t iUnit = 0; iUnit < 18; iUnit++) {
+    //  for (Int_t iUnit = 0; iUnit < 32; iUnit++) {
+    TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]);
+    //    Double_t posZ = statPos[iUnit] - stsPosZ;
+    Double_t posZ = statPos18[iUnit] - stsPosZ;
+    //    Double_t posZ = statPos[iUnit/2] - stsPosZ;
+    TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ);
+    sts->AddNode(station, iUnit + 1, trans);
+    sts->GetShape()->ComputeBBox();
+  }
+
+  // --- Import passive elements from GDML file
+  if (gkImportPassive) { ImportPassive(sts, geoTag, infoFile); }
+
+  // --------------------------------------------------------------------------
+  // --------------------------------------------------------------------------
+
+
+  cout << endl;
+  CheckVolume(sts);
+
+
+  // ---------------   Finish   -----------------------------------------------
+  TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ - 4.0);
+  top->AddNode(sts, 1, stsTrans);
+  top->GetShape()->ComputeBBox();
+  cout << endl << endl;
+
+  CheckVolume(top);
+  cout << endl << endl;
+  gGeoMan->CloseGeometry();
+  gGeoMan->CheckOverlaps(0.0001);
+  gGeoMan->PrintOverlaps();
+  gGeoMan->CheckOverlaps(0.0001, "s");
+  gGeoMan->PrintOverlaps();
+  gGeoMan->Test();
+
+  //TFile* geoFile = new TFile(geoFileName, "RECREATE");
+  //top->Write();
+  sts->Export(geoFileName);  // an another way of writing the stsvolume placement
+
+  TFile* geoFile                 = new TFile(geoFileName, "UPDATE");
+  TGeoTranslation* sts_placement = new TGeoTranslation("sts_trans", 0., 0., stsPosZ - 4.0);
+  sts_placement->Write();
+  //*/
+  cout << endl;
+  cout << "Geometry " << top->GetName() << " written to " << geoFileName << endl;
+  geoFile->Close();
+
+  TString geoFileName_ = "sts_";
+  geoFileName_         = geoFileName_ + geoTag + "_geo.root";
+
+  geoFile = new TFile(geoFileName_, "RECREATE");
+  gGeoMan->Write();  // use this is you want GeoManager format in the output
+  geoFile->Close();
+
+  TString geoFileName__ = "sts_";
+  geoFileName_          = geoFileName__ + geoTag + "-geo.root";
+  sts->Export(geoFileName_);
+
+  geoFile = new TFile(geoFileName_, "UPDATE");
+  stsTrans->Write();
+  geoFile->Close();
+
+
+  // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl");
+  top->Draw("ogl");
+  //sts->Draw("ogl");
+  gGeoManager->SetVisLevel(9);
+
+  infoFile.close();
+}
+// ============================================================================
+// ======                   End of main function                          =====
+// ============================================================================
+
+
+// ****************************************************************************
+// *****      Definition of media, sensors, sectors and ladders           *****
+// *****                                                                  *****
+// *****     Decoupled from main function for better readability          *****
+// ****************************************************************************
+
+/** ===========================================================================
+ ** Create media
+ **
+ ** Currently created: air, active silicon, passive silion
+ **
+ ** Not used for the time being
+ **/
+Int_t CreateMedia()
+{
+
+  Int_t nMedia     = 0;
+  Double_t density = 0.;
+
+  // --- Material air
+  density             = 1.205e-3;  // [g/cm^3]
+  TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density);
+  matAir->AddElement(14.0067, 7, 0.755);  // Nitrogen
+  matAir->AddElement(15.999, 8, 0.231);   // Oxygen
+  matAir->AddElement(39.948, 18, 0.014);  // Argon
+
+  // --- Material silicon
+  density             = 2.33;  // [g/cm^3]
+  TGeoElement* elSi   = gGeoMan->GetElementTable()->GetElement(14);
+  TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density);
+
+
+  // --- Air (passive)
+  TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir);
+  medAir->SetParam(0, 0.);     // is passive
+  medAir->SetParam(1, 1.);     // is in magnetic field
+  medAir->SetParam(2, 20.);    // max. field [kG]
+  medAir->SetParam(6, 0.001);  // boundary crossing precision [cm]
+
+
+  // --- Active silicon for sensors
+  TGeoMedium* medSiAct = new TGeoMedium("silicon", nMedia++, matSi);
+  medSiAct->SetParam(0, 1.);     // is active
+  medSiAct->SetParam(1, 1.);     // is in magnetic field
+  medSiAct->SetParam(2, 20.);    // max. field [kG]
+  medSiAct->SetParam(6, 0.001);  // boundary crossing precisison [cm]
+
+  // --- Passive silicon for cables
+  TGeoMedium* medSiPas = new TGeoMedium("carbon", nMedia++, matSi);
+  medSiPas->SetParam(0, 0.);     // is passive
+  medSiPas->SetParam(1, 1.);     // is in magnetic field
+  medSiPas->SetParam(2, 20.);    // max. field [kG]
+  medSiPas->SetParam(6, 0.001);  // boundary crossing precisison [cm]
+
+  return nMedia;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Create sensors
+ **
+ ** Sensors are created as volumes with box shape and active silicon as medium.
+ ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2
+ **/
+Int_t CreateSensors()
+{
+
+  Int_t nSensors = 0;
+
+  Double_t xSize      = 0.;
+  Double_t ySize      = 0.;
+  Double_t zSize      = gkSensorThickness;
+  TGeoMedium* silicon = gGeoMan->GetMedium("silicon");
+
+
+  // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm)
+  xSize                    = gkSensorSizeX;
+  ySize                    = 2.2;
+  TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor01", shape_sensor01, silicon);
+  nSensors++;
+
+
+  // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm)
+  xSize                    = gkSensorSizeX;
+  ySize                    = 4.2;
+  TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor02", shape_sensor02, silicon);
+  nSensors++;
+
+
+  // ---  Sensor type 03: Big sensor (6.2 cm x 6.2 cm)
+  xSize                    = gkSensorSizeX;
+  ySize                    = 6.2;
+  TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor03", shape_sensor03, silicon);
+  nSensors++;
+
+
+  // ---  Sensor type 04: Big sensor (6.2 cm x 12.4 cm)
+  xSize                    = gkSensorSizeX;
+  ySize                    = 12.4;
+  TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor04", shape_sensor04, silicon);
+  nSensors++;
+
+
+  // below are extra small sensors, those are not available in the CAD model
+
+  // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm)
+  xSize                    = 4.0;
+  ySize                    = 2.5;
+  TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor05", shape_sensor05, silicon);
+  nSensors++;
+
+
+  // ---  Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm)
+  xSize                    = 3.1;
+  ySize                    = 4.2;
+  TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor06", shape_sensor06, silicon);
+  nSensors++;
+
+
+  // ---  Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm)
+  xSize                    = 1.5;
+  ySize                    = 4.2;
+  TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor07", shape_sensor07, silicon);
+  nSensors++;
+
+
+  return nSensors;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Create sectors
+ **
+ ** A sector is either a single sensor or several chained sensors.
+ ** It is implemented as TGeoVolumeAssembly.
+ ** Currently available:
+ ** - single sensors of type 1 - 4
+ ** - two chained sensors of type 4
+ ** - three chained sensors of type 4
+ **/
+Int_t CreateSectors()
+{
+
+  Int_t nSectors = 0;
+
+  TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01");
+  TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02");
+  TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03");
+  TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04");
+  TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05");
+  TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06");
+  TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07");
+  //  TGeoBBox*   box4     = (TGeoBBox*) sensor04->GetShape();
+
+  // --- Sector type 1: single sensor of type 1
+  TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01");
+  sector01->AddNode(sensor01, 1);
+  sector01->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 2: single sensor of type 2
+  TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02");
+  sector02->AddNode(sensor02, 1);
+  sector02->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 3: single sensor of type 3
+  TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03");
+  sector03->AddNode(sensor03, 1);
+  sector03->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 4: single sensor of type 4
+  TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04");
+  sector04->AddNode(sensor04, 1);
+  sector04->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 5: single sensor of type 5
+  TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05");
+  sector05->AddNode(sensor05, 1);
+  sector05->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 6: single sensor of type 6
+  TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06");
+  sector06->AddNode(sensor06, 1);
+  sector06->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 7: single sensor of type 7
+  TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07");
+  sector07->AddNode(sensor07, 1);
+  sector07->GetShape()->ComputeBBox();
+  nSectors++;
+
+  //  // --- Sector type 5: two sensors of type 4
+  //  TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05");
+  //  Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY();
+  //  TGeoTranslation* transD5 =
+  //    new TGeoTranslation("td", 0., -1. * shift5, 0.);
+  //  TGeoTranslation* transU5 =
+  //    new TGeoTranslation("tu", 0., shift5, 0.);
+  //  sector05->AddNode(sensor04, 1, transD5);
+  //  sector05->AddNode(sensor04, 2, transU5);
+  //  sector05->GetShape()->ComputeBBox();
+  //  nSectors++;
+
+  return nSectors;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Create ladders
+ **
+ ** Ladders are the building blocks of the stations. They contain 
+ ** several modules placed one after the other along the z axis
+ ** such that the sectors are arranged vertically (with overlap).
+ ** 
+ ** A ladder is constructed out of two half ladders, the second of which
+ ** is rotated in the x-y plane by 180 degrees and displaced
+ ** in z direction.
+ **/
+Int_t CreateLadders()
+{
+
+  Int_t nLadders = 0;
+
+  // --- Some variables
+  Int_t nSectors = 0;
+  Int_t sectorTypes[10];
+  TGeoBBox* shape = NULL;
+  TString s0name;
+  TString hlname;
+  char align;
+  TGeoVolume* s0vol       = NULL;
+  TGeoVolume* halfLadderU = NULL;
+  TGeoVolume* halfLadderD = NULL;
+
+  // --- Ladders 01-23
+  // --- Ladders 01-27
+  Int_t allSectorTypes[38][6] = {
+    {1, 2, 3, 3, 0, -1},  // ladder 01 - 5 - last column defines alignment of small sensors
+    {1, 2, 3, 3, 0, 0},   // ladder 02 - 5 - last column defines alignment of small sensors
+    {2, 2, 3, 4, 0, -1},  // ladder 03 - 6 - last column defines alignment of small sensors
+    {2, 2, 3, 4, 0, 0},   // ladder 04 - 6 - last column defines alignment of small sensors
+    {2, 3, 4, 4, 0, -1},  // ladder 05 - 7 - last column defines alignment of small sensors
+    {2, 3, 4, 4, 0, 0},   // ladder 06 - 7 - last column defines alignment of small sensors
+    {2, 2, 3, 4, 4, 0},   // ladder 07 -     last column defines alignment of small sensors
+    {3, 4, 4, 4, 0, 0},   // ladder 08 -     last column defines alignment of small sensors
+    {1, 1, 2, 3, 3, 0},   // ladder 09 -     last column defines alignment of small sensors
+    {1, 1, 2, 2, 3, 0},   // ladder 10 -     last column defines alignment of small sensors
+    {2, 2, 0, 0, 0, 0},   // ladder 11 -     last column defines alignment of small sensors
+    {2, 2, 2, 3, 4, 0},   // ladder 12 -     last column defines alignment of small sensors
+    {2, 2, 3, 4, 0, 0},   // ladder 13 -     last column defines alignment of small sensors
+    {2, 3, 4, 0, 0, 0},   // ladder 14 -     last column defines alignment of small sensors
+    {3, 3, 0, 0, 0, 0},   // ladder 15 -     last column defines alignment of small sensors
+    {2, 2, 3, 4, 4, 0},   // ladder 16 -     last column defines alignment of small sensors
+    {2, 3, 4, 4, 0, 0},   // ladder 17 -     last column defines alignment of small sensors
+    {3, 4, 4, 0, 0, 0},   // ladder 18 -     last column defines alignment of small sensors
+    {4, 4, 0, 0, 0, 0},   // ladder 19 -     last column defines alignment of small sensors
+    {1, 2, 4, 4, 4, 0},   // ladder 20 -     last column defines alignment of small sensors
+    {4, 0, 0, 0, 0, 0},   // ladder 21 -     last column defines alignment of small sensors
+    {2, 3, 4, 4, 4, 0},   // ladder 22 -     last column defines alignment of small sensors
+    {2, 3, 3, 4, 4, 0},   // ladder 23 -     last column defines alignment of small sensors
+    {2, 3, 4, 4, 0, 0},   // ladder 24 - copy of 17 with different total length
+    {3, 4, 4, 0, 0, 0},   // ladder 25 - copy of 18 with different total length
+    {4, 4, 0, 0, 0, 0},   // ladder 26 - copy of 19 with different total length
+    {4, 4, 0, 0, 0, 0},   // ladder 27 - copy of 19 with different total length
+
+    {1, 1, 2, 3, 3, 0},  // ladder 28 - copy of 09 with different total length
+    {1, 1, 2, 2, 3, 0},  // ladder 29 - copy of 10 with different total length
+    {2, 2, 0, 0, 0, 0},  // ladder 30 - copy of 11 with different total length
+
+    {2, 2, 2, 3, 4, 0},  // ladder 31 - copy of 12 with different total length
+    {2, 2, 3, 4, 0, 0},  // ladder 32 - copy of 13 with different total length
+    {2, 3, 4, 0, 0, 0},  // ladder 33 - copy of 14 with different total length
+    {3, 3, 0, 0, 0, 0},  // ladder 34 - copy of 15 with different total length
+
+    {2, 2, 3, 4, 4, 0},  // ladder 35 - copy of 16 with different total length
+    {2, 3, 4, 4, 0, 0},  // ladder 36 - copy of 17 with different total length
+    {3, 4, 4, 0, 0, 0},  // ladder 37 - copy of 18 with different total length
+    {4, 4, 0, 0, 0, 0},  // ladder 38 - copy of 19 with different total length
+
+  };  // 8 full - 19 partial ladders
+
+  //  Issue #405
+  //  Counting from the most upstream ladder, the gaps between sensors are as follows:
+  //    01 (most upstream): 41.3mm
+  //    02: 41.3mm
+  //    03: 42.0mm
+  //    04: 48.6mm
+  //    05: 60.8mm
+  //    06: 67.0mm
+  //    07: 79.2mm
+  //    08 (most downstream): 88.0mm
+
+  Double_t pitchZ        = 0;
+  Double_t gapXYZ[38][3] = {
+    {0., 5.43, 0.},               // ladder 01
+    {0., 6.00, 0.},               // ladder 02
+    {0., 6.70, 0.},               // ladder 03
+    {0., 7.35, 0.},               // ladder 04
+    {0., 8.02, 0.},               // ladder 05
+    {0., 8.70, 0.},               // ladder 06
+    {0., 9.22, 0.},               // ladder 07
+    {0., 10.00, 0.},              // ladder 08
+    {0., -gkSectorOverlapY, 0.},  // ladder 09
+    {0., -gkSectorOverlapY, 0.},  // ladder 10
+    {0., -gkSectorOverlapY, 0.},  // ladder 11
+    {0., -gkSectorOverlapY, 0.},  // ladder 12
+    {0., -gkSectorOverlapY, 0.},  // ladder 13
+    {0., -gkSectorOverlapY, 0.},  // ladder 14
+    {0., -gkSectorOverlapY, 0.},  // ladder 15
+    {0., -gkSectorOverlapY, 0.},  // ladder 16
+    {0., -gkSectorOverlapY, 0.},  // ladder 17
+    {0., -gkSectorOverlapY, 0.},  // ladder 18
+    {0., -gkSectorOverlapY, 0.},  // ladder 19
+    {0., -gkSectorOverlapY, 0.},  // ladder 20
+    {0., -gkSectorOverlapY, 0.},  // ladder 21
+    {0., -gkSectorOverlapY, 0.},  // ladder 22
+    {0., -gkSectorOverlapY, 0.},  // ladder 23
+
+    {0., -gkSectorOverlapY, 0.},  // ladder 24 - copy of 17 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 25 - copy of 18 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 26 - copy of 19 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 27 - copy of 19 with different total length
+
+    {0., -gkSectorOverlapY, 0.},  // ladder 28 - copy of 09 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 29 - copy of 10 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 30 - copy of 11 with different total length
+
+    {0., -gkSectorOverlapY, 0.},  // ladder 31 - copy of 12 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 32 - copy of 13 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 33 - copy of 14 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 34 - copy of 15 with different total length
+
+    {0., -gkSectorOverlapY, 0.},  // ladder 35 - copy of 16 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 36 - copy of 17 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 37 - copy of 18 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 38 - copy of 19 with different total length
+
+  };
+
+  Double_t ladderLength[38] = {
+    48.0,  // ladder 01
+    48.0,  // ladder 02
+    66.8,  // ladder 03
+    66.8,  // ladder 04
+    81.8,  // ladder 05
+    81.8,  // ladder 06
+    89.2,  // ladder 07
+    96.7,  // ladder 08
+    48.0,  // ladder 09
+    48.0,  // ladder 10
+    48.0,  // ladder 11
+    66.8,  // ladder 12
+    66.8,  // ladder 13
+    66.8,  // ladder 14
+    66.8,  // ladder 15
+    81.8,  // ladder 16
+    81.8,  // ladder 17
+    81.8,  // ladder 18
+    81.8,  // ladder 19
+    89.2,  // ladder 20
+    89.2,  // ladder 21
+    96.7,  // ladder 22
+    96.7,  // ladder 23
+
+    96.7,  // ladder 24 - copy of 17 with different total length
+    89.2,  // ladder 25 - copy of 18 with different total length
+    96.7,  // ladder 26 - copy of 19 with different total length
+    89.2,  // ladder 27 - copy of 19 with different total length
+
+    66.8,  // ladder 28 - copy of 09 with different total length
+    66.8,  // ladder 29 - copy of 10 with different total length
+    66.8,  // ladder 30 - copy of 11 with different total length
+
+    81.8,  // ladder 31 - copy of 12 with different total length
+    81.8,  // ladder 32 - copy of 13 with different total length
+    81.8,  // ladder 33 - copy of 14 with different total length
+    81.8,  // ladder 34 - copy of 15 with different total length
+
+    89.2,  // ladder 35 - copy of 16 with different total length
+    89.2,  // ladder 36 - copy of 17 with different total length
+    89.2,  // ladder 37 - copy of 18 with different total length
+    89.2,  // ladder 38 - copy of 19 with different total length
+
+  };
+  // ========================================================================
+
+  // calculate Z shift for ladders with and without gaps in the center
+  s0name = Form("Sector%02d", allSectorTypes[0][0]);
+  s0vol  = gGeoMan->GetVolume(s0name);
+  shape  = (TGeoBBox*) s0vol->GetShape();
+
+  // ========================================================================
+
+  for (Int_t iLadder = 0; iLadder < 38; iLadder++) {
+    cout << endl;
+    nSectors = 0;
+    for (Int_t i = 0; i < 5; i++)
+      if (allSectorTypes[iLadder][i] != 0) {
+        sectorTypes[nSectors] = allSectorTypes[iLadder][i];  // copy sectors for this ladder
+        cout << "DE iLadder " << iLadder + 1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i]
+             << ";" << endl;
+        nSectors++;  // count how many sectors are in this ladder
+      }
+
+    // always set displacement in z between upper and lower half ladder
+    gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ;
+
+    // define additional offset to carbon ladder for half ladders with less than 5 sensors
+    pitchZ = 2. * shape->GetDZ() + gkSectorGapZ;
+
+    if (allSectorTypes[iLadder][5] == 0) align = 'l';
+    else
+      align = 'r';
+    hlname = Form("HalfLadder%02dt", iLadder + 1);
+    // build upper half ladder
+    halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, ladderLength[iLadder] / 2.,
+                                      gapXYZ[iLadder][1] / 2.);  // mirrored
+
+    if (allSectorTypes[iLadder][5] == 0) align = 'r';
+    else
+      align = 'l';
+    hlname = Form("HalfLadder%02db", iLadder + 1);
+    // build lower half ladder
+    halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, ladderLength[iLadder] / 2.,
+                                      gapXYZ[iLadder][1] / 2.);  // mirrored
+
+    // at this point half ladders are constructed
+
+    // build all 4 possible ladders types for this sensor arrangement
+    ConstructLadder(iLadder + 1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ,
+                    nSectors);  // v19a
+    ConstructLadder(100 + iLadder + 1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ,
+                    nSectors);  // v19b
+
+    ConstructLadder(1000 + iLadder + 1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ,
+                    nSectors);  // v19k
+    ConstructLadder(1100 + iLadder + 1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ,
+                    nSectors);  // v19k
+
+    nLadders++;
+  }
+
+  return nLadders;
+}
+/** ======================================================================= **/
+
+
+// ****************************************************************************
+// *****                                                                  *****
+// *****    Generic functions  for the construction of STS elements       *****
+// *****                                                                  *****
+// *****  module:     volume (made of a sector and a cable)               *****
+// *****  haf ladder: assembly (made of modules)                          *****
+// *****  ladder:     assembly (made of two half ladders)                 *****
+// *****  station:    volume (made of ladders)                            *****
+// *****                                                                  *****
+// ****************************************************************************
+
+
+/** ===========================================================================
+ ** Construct a module
+ **
+ ** A module is a sector plus the readout cable extending from the
+ ** top of the sector. The cable is made from passive silicon.
+ ** The cable has the same x size as the sector.
+ ** Its thickness is given by the global variable gkCableThickness.
+ ** The cable length is a parameter.
+ ** The sensor(s) of the sector is/are placed directly in the module;
+ ** the sector is just auxiliary for the proper placement.
+ **
+ ** Arguments: 
+ **            name             volume name
+ **            sector           pointer to sector volume
+ **            cableLength      length of cable
+ **/
+TGeoVolume* ConstructModule(const char* name, TGeoVolume* sector, Double_t cableLength)
+{
+
+  // --- Check sector volume
+  if (!sector) Fatal("CreateModule", "Sector volume not found!");
+
+  // --- Get size of sector
+  TGeoBBox* box    = (TGeoBBox*) sector->GetShape();
+  Double_t sectorX = 2. * box->GetDX();
+  Double_t sectorY = 2. * box->GetDY();
+  Double_t sectorZ = 2. * box->GetDZ();
+
+  // --- Get size of cable
+  Double_t cableX = sectorX;
+  Double_t cableY = cableLength;
+  Double_t cableZ = gkCableThickness;
+
+  // --- Create module volume
+  Double_t moduleX = TMath::Max(sectorX, cableX);
+  Double_t moduleY = sectorY + cableLength;
+
+  Double_t moduleZ = TMath::Max(sectorZ, cableZ);
+
+  TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, moduleX / 2., moduleY / 2., moduleZ / 2.);
+
+  // --- Position of sector in module
+  // --- Sector is centred in x and z and aligned to the bottom
+  Double_t sectorXpos = 0.;
+  Double_t sectorYpos = 0.5 * (sectorY - moduleY);
+  Double_t sectorZpos = 0.;
+
+
+  // --- Get sensor(s) from sector
+  Int_t nSensors = sector->GetNdaughters();
+  for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) {
+    TGeoNode* sensor = sector->GetNode(iSensor);
+
+    // --- Calculate position of sensor in module
+    const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation();
+    Double_t sensorXpos        = 0.;
+    Double_t sensorYpos        = sectorYpos + xSensTrans[1];
+    Double_t sensorZpos        = 0.;
+    TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", sensorXpos, sensorYpos, sensorZpos);
+
+    // --- Add sensor volume to module
+    TGeoVolume* sensVol = sensor->GetVolume();
+    module->AddNode(sensor->GetVolume(), iSensor + 1, sensTrans);
+    module->GetShape()->ComputeBBox();
+  }
+
+
+  // --- Create cable volume, if necessary, and place it in module
+  // --- Cable is centred in x and z and aligned to the top
+  if (gkConstructCables && cableLength > 0.0001) {
+    TString cableName       = TString(name) + "_cable";
+    TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable");
+    if (!cableMedium) Fatal("CreateModule", "Medium STScable not found!");
+    TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), cableMedium, cableX / 2., cableY / 2., cableZ / 2.);
+    // add color to cables
+    cable->SetLineColor(kOrange);
+    cable->SetTransparency(60);
+    Double_t cableXpos          = 0.;
+    Double_t cableYpos          = sectorY + 0.5 * cableY - 0.5 * moduleY;
+    Double_t cableZpos          = 0.;
+    TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", cableXpos, cableYpos, cableZpos);
+    module->AddNode(cable, 1, cableTrans);
+    module->GetShape()->ComputeBBox();
+  }
+
+  return module;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Construct a half ladder
+ **
+ ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting
+ ** of several modules arranged on top of each other. The modules
+ ** have a given overlap in y and a displacement in z to allow for the
+ ** overlap.
+ **
+ ** The typ of sectors / modules to be placed must be specified:
+ **    1 = sensor01
+ **    2 = sensor02
+ **    3 = sensor03
+ **    4 = sensor04
+ **    5 = 2 x sensor04 (chained)
+ **    6 = 3 x sensor04 (chained)
+ ** The cable is added automatically from the top of each sensor to
+ ** the top of the half ladder.
+ ** The alignment can be left (l) or right (r), which matters in the
+ ** case of different x sizes of sensors (e.g. SensorType01).
+ **
+ ** Arguments: 
+ **            name             volume name
+ **            nSectors         number of sectors
+ **            sectorTypes      array with sector types
+ **            align            horizontal alignment of sectors
+ *             ladderLength     full length of the ladder towards FEE
+ *             offsetY          gap in the beam-pipe region
+ **/
+TGeoVolume* ConstructHalfLadder(const TString& name, Int_t nSectors, Int_t* sectorTypes, char align,
+                                Double_t ladderLength, Double_t offsetY)
+{
+
+  // --- Create half ladder volume assembly
+  TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name);
+
+  // --- Determine size of ladder
+  Double_t ladderX = 0.;
+  Double_t ladderY = 0.;
+  Double_t ladderZ = 0.;
+  for (Int_t iSector = 0; iSector < nSectors; iSector++) {
+    TString sectorName = Form("Sector%02d", sectorTypes[iSector]);
+    TGeoVolume* sector = gGeoMan->GetVolume(sectorName);
+    if (!sector) Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data()));
+    TGeoBBox* box = (TGeoBBox*) sector->GetShape();
+    // --- Ladder x size equals largest sector x size
+    ladderX = TMath::Max(ladderX, 2. * box->GetDX());
+    // --- Ladder y size is sum of sector ysizes
+    ladderY += 2. * box->GetDY();
+    // --- Ladder z size is sum of sector z sizes
+    ladderZ += 2. * box->GetDZ();
+  }
+  // --- Subtract overlaps in y
+  ladderY -= Double_t(nSectors - 1) * gkSectorOverlapY;
+  // --- Add gaps in z direction
+  ladderZ += Double_t(nSectors - 1) * gkSectorGapZ;
+
+  ladderY = TMath::Max(ladderLength - offsetY, ladderY);
+
+  // --- Create and place modules
+  Double_t yPosSect = -0.5 * ladderY;
+  Double_t zPosMod  = -0.5 * ladderZ;
+  for (Int_t iSector = 0; iSector < nSectors; iSector++) {
+    TString sectorName = Form("Sector%02d", sectorTypes[iSector]);
+    TGeoVolume* sector = gGeoMan->GetVolume(sectorName);
+    TGeoBBox* box      = (TGeoBBox*) sector->GetShape();
+    Double_t sectorX   = 2. * box->GetDX();
+    Double_t sectorY   = 2. * box->GetDY();
+    Double_t sectorZ   = 2. * box->GetDZ();
+    yPosSect += 0.5 * sectorY;  // Position of sector in ladder
+    Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY;
+    TString moduleName   = name + "_" + Form("Module%02d", sectorTypes[iSector]);
+    TGeoVolume* module   = ConstructModule(moduleName.Data(), sector, cableLength);
+
+    TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape();
+    Double_t moduleX   = 2. * shapeMod->GetDX();
+    Double_t moduleY   = 2. * shapeMod->GetDY();
+    Double_t moduleZ   = 2. * shapeMod->GetDZ();
+    Double_t xPosMod   = 0.;
+    if (align == 'l') xPosMod = 0.5 * (moduleX - ladderX);  // left aligned
+    else if (align == 'r')
+      xPosMod = 0.5 * (ladderX - moduleX);  // right aligned
+    else
+      xPosMod = 0.;                                // centred in x
+    Double_t yPosMod = 0.5 * (ladderY - moduleY);  // top aligned
+    zPosMod += 0.5 * moduleZ;
+    TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, yPosMod, zPosMod);
+    halfLadder->AddNode(module, iSector + 1, trans);
+    halfLadder->GetShape()->ComputeBBox();
+    yPosSect += 0.5 * sectorY - gkSectorOverlapY;
+    zPosMod += 0.5 * moduleZ + gkSectorGapZ;
+  }
+
+  CheckVolume(halfLadder);
+  cout << endl;
+
+  return halfLadder;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Add a carbon support to a ladder
+ ** 
+ ** Arguments: 
+ **            LadderIndex      ladder number
+ **            ladder           pointer to ladder
+ **            xu               size of halfladder
+ **            ladderY          height of ladder along y
+ **            ladderZ          thickness of ladder along z
+ **/
+void AddCarbonLadder(Int_t LadderIndex, TGeoVolume* ladder, Double_t xu, Double_t ladderY, Double_t ladderZ)
+{
+
+  // --- Some variables
+  TString name = Form("LadderType%04d", LadderIndex);  // v19k
+  Int_t i;
+  Double_t j;
+
+  Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep);
+
+  //  cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl;
+
+  Double_t ladderDZ = (xu / 2. + sqrt(2.) * gkFrameThickness / 2. + gkSectorGapZFrame * 2) / 2.;
+  cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl;
+
+  TGeoBBox* fullFrameShp      = new TGeoBBox(name + "_CarbonElement_shp", xu / 2., gkFrameStep / 2., ladderDZ);
+  TGeoVolume* fullFrameBoxVol = new TGeoVolume(name + "_CarbonElement", fullFrameShp, gStsMedium);
+
+  ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu / 2.);
+  TGeoRotation* fullFrameRot = new TGeoRotation;
+  fullFrameRot->RotateY(180);
+
+  Int_t inum = YnumOfFrameBoxes - 3.5;  // - 3.5 was done to short frame box to remove overlaps
+  for (i = 1; i <= inum; i++) {
+    j = -(inum - 1) / 2. + (i - 1);
+    // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2)
+    // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1   (= 3)
+    //        cout << "DE: i " << i << " j " << j << endl;
+
+    if (LadderIndex % 100 <= 3)  // central ladders in stations 1 to 3
+    {
+      if ((j >= -1) && (j <= 1))  // keep the inner 2 (even) or 3 (odd) elements free for the cone
+        continue;
+    }
+    else if (LadderIndex % 100 <= 8)  // central ladders in stations 4 to 8
+    {
+      if ((j >= -2) && (j <= 2))  // keep the inner 4 elements free for the cone
+        continue;
+    }
+
+    cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ / 2. - ladderDZ << " cm " << endl;
+    ladder->AddNode(fullFrameBoxVol, i,
+                    new TGeoCombiTrans(name + "_CarbonElement_posrot", 0., j * gkFrameStep, -(ladderZ / 2. + ladderDZ),
+                                       fullFrameRot));
+  }
+
+  ladder->GetShape()->ComputeBBox();
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Construct a ladder out of two half ladders with vertical gap
+ ** 
+ ** The second half ladder will be rotated by 180 degrees 
+ ** in the x-y plane. The two half ladders will be put on top of each
+ ** other with a vertical gap.
+ **
+ ** Arguments: 
+ **            name             volume name
+ **            halfLadderU      pointer to upper half ladder
+ **            halfLadderD      pointer to lower half ladder
+ **            gapY             vertical gap
+ **            shiftZ           relative displacement along the z axis
+ **/
+
+TGeoVolume* ConstructLadder(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t gapY,
+                            Double_t shiftZ, Double_t pitchZ, Int_t nSectors)
+{
+
+  // --- Some variables
+  TGeoBBox* shape = NULL;
+
+  // define additional offset to carbon ladder for half ladders with less than 5 sensors
+  Double_t offsetZ = (5. - nSectors) * pitchZ;
+
+  // --- Dimensions of half ladders
+  shape       = (TGeoBBox*) halfLadderU->GetShape();  // up
+  Double_t xu = 2. * shape->GetDX();
+  Double_t yu = 2. * shape->GetDY();
+  Double_t zu = 2. * shape->GetDZ();
+
+  shape       = (TGeoBBox*) halfLadderD->GetShape();  // down
+  Double_t xd = 2. * shape->GetDX();
+  Double_t yd = 2. * shape->GetDY();
+  Double_t zd = 2. * shape->GetDZ();
+
+  // --- Create ladder volume assembly
+  TString name               = Form("LadderType%04d", LadderIndex);  // v19k
+  TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name);
+  Double_t ladderX           = TMath::Max(xu, xd);
+  Double_t ladderY           = yu + yd + gapY;
+  Double_t ladderZ           = TMath::Max(zu,
+                                zd + shiftZ + offsetZ);  // there are 6 slots - 5 x 1.5 mm + 0.3 mm = 7.8 mm
+  //  Double_t ladderZ = TMath::Max(zu, zd + shiftZ);
+
+  cout << "DERR iladder " << LadderIndex << " nSec " << nSectors << " zu " << zu << " zd " << zd << " zd+shi "
+       << zd + shiftZ << " ladderZ " << ladderZ << " offsetZ " << offsetZ << endl;
+
+  // --- Place half ladders
+  Double_t xPosU = 0.0;                   // centred in x
+  Double_t yPosU = 0.5 * (ladderY - yu);  // top aligned
+  Double_t zPosU = 0;
+  zPosU          = 0.5 * (ladderZ - zu);                             // front aligned
+  if (LadderIndex >= 1000) zPosU = -0.5 * (ladderZ - zu) + offsetZ;  // back aligned with possible offset
+  //zPosU = -zPosU;
+
+  TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU);
+  ladder->AddNode(halfLadderU, 1, tu);
+
+  Double_t xPosD = 0.0;                    // centred in x
+  Double_t yPosD = 0.5 * -(ladderY - yd);  // bottom aligned
+  Double_t zPosD = 0;
+  zPosD          = 0.5 * -(ladderZ - zd) + offsetZ;         // back aligned with possible offset
+  if (LadderIndex >= 1000) zPosD = -0.5 * -(ladderZ - zd);  // front aligned
+  //zPosD = -zPosD;
+
+  TGeoRotation* rd = new TGeoRotation();
+  rd->RotateZ(180.);
+  TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd);
+  ladder->AddNode(halfLadderD, 2, cd);
+
+  ladder->GetShape()->ComputeBBox();
+
+  shape = (TGeoBBox*) ladder->GetShape();
+  cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() << " ladderY " << 2. * shape->GetDY()
+       << " ladderZ " << 2. * shape->GetDZ() << endl;
+
+  cout << "DDDD ladder" << LadderIndex << endl;
+  cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ
+       << endl;
+
+  // ----------------   Create and place frame boxes   ------------------------
+
+  if (gkConstructFrames) AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ);
+
+  // --------------------------------------------------------------------------
+
+  shape = (TGeoBBox*) ladder->GetShape();
+  cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() << " ladderY " << 2. * shape->GetDY()
+       << " ladderZ " << 2. * shape->GetDZ() << endl;
+
+  return ladder;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Construct a unit
+ **
+ ** The unit volume is the minimal box comprising all ladders
+ ** minus a tube accomodating the beam pipe.
+ **
+ ** The ladders are arranged horizontally from left to right with
+ ** a given overlap in x.
+ ** Every second ladder is slightly displaced upstream from the centre
+ ** z plane and facing downstream, the others are slightly displaced
+ ** downstream and facing upstream (rotated around the y axis).
+ **
+ ** Arguments: 
+ **            name             volume name
+ **            nLadders         number of ladders
+ **            ladderTypes      array of ladder types
+ **/
+
+TGeoVolume* ConstructUnit(Int_t iSide, Int_t iUnit, Int_t nLadders, Int_t* ladderTypes, Int_t iStation)
+{
+
+  Bool_t isFirstPartOfHalfUnit = kFALSE;
+
+  //  TString name = Form("Unit%02d", iUnit);    // 0,1,2,3,4,5,6,7 - Unit00 missing in output
+  //  TString name = Form("Unit%02d", iUnit+1);  // 1,2,3,4,5,6,7,8
+
+  TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]);
+  if (!unit)  // if it does not yet exist, create a new one
+  {
+    unit                  = new TGeoVolumeAssembly(unitName[iUnit]);
+    isFirstPartOfHalfUnit = kTRUE;
+  }
+
+  // --- Some local variables
+  TGeoBBox* ladderShape = NULL;
+  TGeoVolume* ladder    = NULL;
+  TString ladderName;
+  Double_t subtractedVal;
+
+  // --- Determine size of unit from ladders
+  Double_t statX = 0.;
+  //  Double_t statY     = 0.;
+
+  for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
+    Int_t ladderType = ladderTypes[iLadder];  // v19k
+
+    //    if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl;
+
+    if (ladderType > 0) {
+      ladderName = Form("LadderType%04d", ladderType);  // v19k
+
+      ladder = gGeoManager->GetVolume(ladderName);
+      if (!ladder) Fatal("ConstructUnit", Form("Volume %s not found", ladderName.Data()));
+      ladderShape = (TGeoBBox*) ladder->GetShape();
+      statX += 2. * ladderShape->GetDX();
+    }
+    else
+      statX += gkSensorSizeX;  // empty ladder in unit
+  }
+  statX -= Double_t(nLadders - 1) * gkLadderOverlapX;
+
+  //  if (iSide == 0) cout << "DWER -" << endl;
+
+  // --- Place ladders in unit
+  cout << "xPos0: " << statX << endl;
+  Double_t xPos = -0.5 * statX;
+  cout << "xPos1: " << xPos << endl;
+  Double_t yPos = 0.;
+  Double_t zPos = 0.;
+
+  Double_t maxdz = 0.;
+  for (Int_t iLadder = 0; iLadder < nLadders; iLadder++)  // find maximum dz in this unit
+  {
+    Int_t ladderType = ladderTypes[iLadder];  // v19k
+
+    if (ladderType > 0) {
+      ladderName = Form("LadderType%04d", ladderType);  // v19k
+
+      ladder      = gGeoManager->GetVolume(ladderName);
+      ladderShape = (TGeoBBox*) ladder->GetShape();
+      if (maxdz < ladderShape->GetDZ()) maxdz = ladderShape->GetDZ();
+    }
+  }
+
+  for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
+    Int_t ladderType = ladderTypes[iLadder];  // v19k
+
+    if (ladderType > 0) {
+      ladderName = Form("LadderType%04d", ladderType);  // v19k
+
+      ladder      = gGeoManager->GetVolume(ladderName);
+      ladderShape = (TGeoBBox*) ladder->GetShape();
+      xPos += ladderShape->GetDX();
+      cout << "xPos2: " << xPos << endl;
+      yPos              = 0.;  // vertically centred
+      TGeoRotation* rot = new TGeoRotation();
+
+      if (gkConstructFrames)
+        subtractedVal = ladderShape->GetDX() + sqrt(2.) * gkFrameThickness / 2. + gkSectorGapZFrame * 2;
+      else
+        subtractedVal = 0.;
+
+      zPos = 0.5 * gkLadderGapZ + (2 * maxdz - ladderShape->GetDZ() - subtractedVal / 2.);  // z-aligned ladders
+
+      // v19k
+      cout << "DE ladder" << ladderTypes[iLadder] << "  dx: " << ladderShape->GetDX()
+           << "  dy: " << ladderShape->GetDY() << "  dz: " << ladderShape->GetDZ() << "  max dz: " << maxdz << endl;
+
+      // v19k
+      cout << "DE ladder" << ladderTypes[iLadder] << "  fra: " << gkFrameThickness / 2. << "  sub: " << subtractedVal
+           << "  zpo: " << zPos << endl
+           << endl;
+
+      // v19k
+      if (ladderTypes[iLadder] / 1000 == 1)  // flip some of the ladders to reproduce the CAD layout
+        rot->RotateY(180.);
+      else
+        zPos = -zPos;
+
+      if (!isFirstPartOfHalfUnit) zPos += 10.5;  // v19d
+      //      zPos += 10.0;   // initial version
+
+      TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot);
+      // start
+      //      cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl;
+
+      if (iSide == 0) {
+        if (iLadder < nLadders / 2)  // right side - only half unit -x
+        {
+          unit->AddNode(ladder, iStation * 100 + iLadder + 1, trans);
+          // calculate Station number to encode the ladder copy number
+          cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl;
+        }
+      }
+      else {
+        if (iLadder >= nLadders / 2)  // left  side - only half unit +x
+        {
+          unit->AddNode(ladder, iStation * 100 + iLadder + 1, trans);
+          // calculate Station number to encode the ladder copy number
+          cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl;
+        }
+      }
+      unit->GetShape()->ComputeBBox();
+      // stop
+      xPos += ladderShape->GetDX() - gkLadderOverlapX;
+      cout << "xPos3: " << xPos << endl;
+    }
+    else
+      xPos += gkSensorSizeX - gkLadderOverlapX;
+  }
+
+  return unit;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Import and add the passive materials to the STS volume
+ **/
+void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile)
+{
+  TString passiveName     = TString("sts_passive_") + geoTag;
+  TString basePath        = gSystem->Getenv("VMCWORKDIR");
+  TString relPath         = "/geometry/sts/passive/" + passiveName + ".gdml";
+  TString passiveFileName = basePath + relPath;
+  infoFile << std::endl << std::endl;
+  infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl;
+
+  TGDMLParse parser;
+  TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName);
+  PostProcessGdml(gdmlVolume);
+  gdmlVolume->SetName(passiveName);
+
+  TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.);
+  infoFile << "Passive assembly is translated for Z=2.68 cm downstream with "
+              "respect to parent volume"
+           << std::endl
+           << std::endl;
+
+  gdmlVolume->GetShape()->ComputeBBox();
+  CheckVolume(gdmlVolume, infoFile);
+
+  infoFile << std::endl;
+  for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) {
+    CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE);
+  }
+
+  stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, "");
+}
+
+/** ===========================================================================
+ ** Assign visual properties to the imported gdml volumes
+ **/
+void PostProcessGdml(TGeoVolume* gdmlVolume)
+{
+  const UInt_t kPOBColor        = kRed - 6;
+  const UInt_t kPOBTransparency = 0;  // 5;
+
+  const UInt_t kFEBColor        = kOrange - 6;
+  const UInt_t kFEBTransparency = 0;  // 5;
+
+  const UInt_t kUnitColor        = kCyan - 10;
+  const UInt_t kUnitTransparency = 0;  // 5;
+
+  const UInt_t kCfColor        = kCyan - 1;
+  const UInt_t kCfTransparency = 0;  // 10;
+
+  // name <Color, Transparency>
+  std::map<std::string, std::tuple<UInt_t, UInt_t>> props {
+    {"passive_POB", std::tuple<UInt_t, UInt_t> {kPOBColor, kPOBTransparency}},
+    {"passive_FEB", std::tuple<UInt_t, UInt_t> {kFEBColor, kFEBTransparency}},
+    {"passive_unit", std::tuple<UInt_t, UInt_t> {kUnitColor, kUnitTransparency}},
+    {"passive_Box_Wall", std::tuple<UInt_t, UInt_t> {kCfColor, kCfTransparency}},
+    {"passive_Box_Wall_Front_CF2", std::tuple<UInt_t, UInt_t> {kCfColor + 3, kCfTransparency}},
+    {"passive_Box_Wall_Back_CF2", std::tuple<UInt_t, UInt_t> {kCfColor + 3, kCfTransparency}},
+    {"passive_Box_Wall_Back_Light_Foam", std::tuple<UInt_t, UInt_t> {kCfColor - 8, kCfTransparency}},
+    {"passive_Box_Wall_Front_Light_Foam", std::tuple<UInt_t, UInt_t> {kCfColor - 8, kCfTransparency}},
+  };
+
+  // Match volume name and apply visual properties   passive_Box_Wall_Front_Light_Foam
+  const TObjArray* volumes = gGeoManager->GetListOfVolumes();
+  for (auto& entry : props) {
+    TIter next(volumes);
+    TGeoVolume* vol = nullptr;
+    while ((vol = (TGeoVolume*) next())) {
+      if (TString(vol->GetName()).Contains(entry.first.c_str())) {
+        vol->SetLineColor(std::get<0>(entry.second));
+        vol->SetTransparency(std::get<1>(entry.second));
+      }
+    }
+  }
+}
+
+/** ===========================================================================
+ ** Volume information for debugging
+ **/
+void CheckVolume(TGeoVolume* volume)
+{
+
+  TGeoBBox* shape = (TGeoBBox*) volume->GetShape();
+  cout << volume->GetName() << ": size " << fixed << setprecision(4) << setw(7) << 2. * shape->GetDX() << " x "
+       << setw(7) << 2. * shape->GetDY() << " x " << setw(7) << 2. * shape->GetDZ();
+  if (volume->IsAssembly()) cout << ", assembly";
+  else {
+    if (volume->GetMedium()) cout << ", medium " << volume->GetMedium()->GetName();
+    else
+      cout << ", "
+           << "\033[31m"
+           << " no medium"
+           << "\033[0m";
+  }
+  cout << endl;
+  if (volume->GetNdaughters()) {
+    cout << "Daughters: " << endl;
+    for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) {
+      TGeoNode* node  = volume->GetNode(iNode);
+      TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape();
+      cout << setw(15) << node->GetName() << ", size " << fixed << setprecision(3) << setw(6) << 2. * shape->GetDX()
+           << " x " << setw(6) << 2. * shape->GetDY() << " x " << setw(6) << 2. * shape->GetDZ() << ", position ( ";
+      TGeoMatrix* matrix  = node->GetMatrix();
+      const Double_t* pos = matrix->GetTranslation();
+      cout << setfill(' ');
+      cout << fixed << setw(8) << pos[0] << ", " << setw(8) << pos[1] << ", " << setw(8) << pos[2] << " )" << endl;
+    }
+  }
+}
+/** ======================================================================= **/
+
+/** ===========================================================================
+ ** Volume information for output to file
+ **/
+void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren)
+{
+  if (!file) return;
+
+  TGeoBBox* shape = (TGeoBBox*) volume->GetShape();
+  file << volume->GetName() << ": size " << fixed << setprecision(4) << setw(7) << 2. * shape->GetDX() << " x "
+       << setw(7) << 2. * shape->GetDY() << " x " << setw(7) << 2. * shape->GetDZ();
+  if (volume->IsAssembly()) file << ", assembly";
+  else {
+    if (volume->GetMedium()) file << ", medium " << volume->GetMedium()->GetName();
+    else
+      file << ", "
+           << "\033[31m"
+           << " no medium"
+           << "\033[0m";
+  }
+  file << endl;
+  if (volume->GetNdaughters() && listChildren) {
+    file << "Contains: ";
+    for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++)
+      file << volume->GetNode(iNode)->GetVolume()->GetName() << " ";
+    file << endl;
+  }
+}
+
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Calculate beam pipe outer radius for a given z
+ **/
+Double_t BeamPipeRadius(Double_t z)
+{
+  if (z < gkPipeZ2) return gkPipeR1;
+  Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1);
+  return gkPipeR2 + slope * (z - gkPipeZ2);
+}
+/** ======================================================================= **/
+
+
+/** ======================================================================= **/
+TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x)
+{
+  // --- Material of the frames
+  TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon");
+
+  TGeoBBox* frameVertPillarShp;
+
+  Double_t t = gkFrameThickness / 2.;
+
+  // --- Main vertical pillars
+  //      TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t);  // square crossection, along y
+  //  TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial);
+  //  frameVertPillarVol->SetLineColor(kGreen);
+  //  frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.));
+  //  frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.));
+
+  if (gkCylindricalFrames)
+    //          TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.);  // circle crossection, along z
+    frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner / 2., gkCylinderDiaOuter / 2.,
+                                      gkFrameStep / 2.);  // circle crossection, along z
+  else
+    frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t,
+                                      gkFrameStep / 2.);  // square crossection, along z
+  TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial);
+  frameVertPillarVol->SetLineColor(kGreen);
+
+  TGeoRotation* xRot90 = new TGeoRotation;
+  xRot90->RotateX(90.);
+  frameBoxVol->AddNode(
+    frameVertPillarVol, 1,
+    new TGeoCombiTrans(name + "_vertpillar_pos_1", x - t, 0., -(x + sqrt(2.) * t - 2. * t) / 2., xRot90));
+  frameBoxVol->AddNode(
+    frameVertPillarVol, 2,
+    new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x - t), 0., -(x + sqrt(2.) * t - 2. * t) / 2., xRot90));
+
+  //  TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.);
+  TGeoRotation* vertRot = new TGeoRotation;
+  vertRot->RotateX(90.);
+  vertRot->RotateY(45.);
+  frameBoxVol->AddNode(frameVertPillarVol, 3,
+                       new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x - sqrt(2.) * t) / 2., vertRot));
+
+  // --- Small horizontal pillar
+  // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.);
+  // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial);
+  // frameHorPillarVol->SetLineColor(kCyan);
+  // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.));
+
+  if (gkConstructSmallFrames) {
+
+    // --- Small sloping pillars
+    TGeoPara* frameSlopePillarShp =
+      new TGeoPara(name + "_slopepillar_shape", (x - 2. * t) / TMath::Cos(31.4 / 180. * TMath::Pi()),
+                   gkThinFrameThickness / 2., gkThinFrameThickness / 2., 31.4, 0., 90.);
+    TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial);
+    frameSlopePillarVol->SetLineColor(kCyan);
+    TGeoRotation* slopeRot  = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4);
+    TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4);
+    TGeoCombiTrans* slopeTrRot =
+      new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x + sqrt(2.) * t - 2. * t) / 2., slopeRot);
+    TGeoCombiTrans* slopeTrRot2 =
+      new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x + sqrt(2.) * t - 2. * t) / 2., slopeRot2);
+
+    frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot);
+    frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2);
+
+
+    Double_t angl = 23.;
+    // --- Small sub pillar
+    TGeoPara* frameSubPillarShp =
+      new TGeoPara(name + "_subpillar_shape", (sqrt(2) * (x / 2. - t) - t / 2.) / TMath::Cos(angl / 180. * TMath::Pi()),
+                   gkThinFrameThickness / 2., gkThinFrameThickness / 2., angl, 0., 90.);
+    TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial);
+    frameSubPillarVol->SetLineColor(kMagenta);
+
+    Double_t posZ = t * (1. - 3. / (2. * sqrt(2.)));
+
+    // one side of X direction
+    TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90. + angl);
+    TGeoCombiTrans* subTrRot1 =
+      new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x / 2. + t - t / (2. * sqrt(2.))), 1., posZ, subRot1);
+
+    TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90. - 45., -90. + angl);
+    TGeoCombiTrans* subTrRot2 =
+      new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x / 2. + t - t / (2. * sqrt(2.))), -1., posZ, subRot2);
+
+    // other side of X direction
+    TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90. + 45., -90. + angl);
+    TGeoCombiTrans* subTrRot3 =
+      new TGeoCombiTrans(name + "_subpillar_posrot_3", -x / 2. + t - t / (2. * sqrt(2.)), 1., posZ, subRot3);
+
+    TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90. + angl);
+    TGeoCombiTrans* subTrRot4 =
+      new TGeoCombiTrans(name + "_subpillar_posrot_4", -x / 2. + t - t / (2. * sqrt(2.)), -1., posZ, subRot4);
+
+    frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1);
+    frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2);
+    frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3);
+    frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4);
+    //                frameBoxVol->GetShape()->ComputeBBox();
+  }
+
+  return frameBoxVol;
+}
+/** ======================================================================= **/
+
+/** ======================================================================= **/
+TGeoVolume* ConstructSmallCone(Double_t coneDz)
+{
+  // --- Material of the frames
+  TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon");
+
+  // --- Outer cone
+  //  TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.);
+  //  TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.);
+
+  Double_t radius    = 3.0;
+  Double_t thickness = 0.04;  // 0.4 mm
+  //  TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.);
+  TGeoConeSeg* A = new TGeoConeSeg("A", coneDz, radius, radius + thickness, radius, radius + thickness, 0., 180.);
+  TGeoBBox* B    = new TGeoBBox("B", 8., 6., 10.);
+
+  TGeoCombiTrans* M = new TGeoCombiTrans("M");
+  M->RotateX(45.);
+  M->SetDy(-5.575);
+  M->SetDz(6.935);
+  M->RegisterYourself();
+
+  TGeoShape* coneShp  = new TGeoCompositeShape("Cone_shp", "A-B:M");
+  TGeoVolume* coneVol = new TGeoVolume("Cone", coneShp, framesMaterial);
+  coneVol->SetLineColor(kGreen);
+  //  coneVol->RegisterYourself();
+
+  //  // --- Inner cone
+  //  Double_t thickness = 0.02;
+  //  Double_t thickness2 = 0.022;
+  //  //  TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.);
+  //  TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.);
+  //
+  //  TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2");
+  //  M2->RotateX (45.);
+  //  M2->SetDy (-5.575+thickness*sqrt(2.));
+  //  M2->SetDz (6.935);
+  //  M2->RegisterYourself();
+  //
+  //  TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2");
+  //  TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium);
+  //  coneVol2->SetLineColor(kGreen);
+  ////  coneVol2->RegisterYourself();
+  //
+  //  coneVol->AddNode(coneVol2, 1);
+
+  return coneVol;
+}
+/** ======================================================================= **/
+
+/** ======================================================================= **/
+TGeoVolume* ConstructBigCone(Double_t coneDz)
+{
+  // --- Material of the frames
+  TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon");
+
+  // --- Outer cone
+  TGeoConeSeg* bA = new TGeoConeSeg("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.);
+  TGeoBBox* bB    = new TGeoBBox("bB", 8., 6., 10.);
+
+  TGeoCombiTrans* bM = new TGeoCombiTrans("bM");
+  bM->RotateX(45.);
+  bM->SetDy(-5.575);
+  bM->SetDz(6.935);
+  bM->RegisterYourself();
+
+  TGeoShape* coneBigShp  = new TGeoCompositeShape("ConeBig_shp", "bA-bB:bM");
+  TGeoVolume* coneBigVol = new TGeoVolume("ConeBig", coneBigShp, framesMaterial);
+  coneBigVol->SetLineColor(kGreen);
+  //  coneBigVol->RegisterYourself();
+
+  // --- Inner cone
+  Double_t thickness  = 0.02;
+  Double_t thickness2 = 0.022;
+  TGeoConeSeg* bA2    = new TGeoConeSeg("bA2", coneDz - thickness, 6. + thickness, 7.6 - thickness2, 5.99 + thickness,
+                                     6.05 - thickness2, 0., 180.);
+
+  TGeoCombiTrans* bM2 = new TGeoCombiTrans("bM2");
+  bM2->RotateX(45.);
+  bM2->SetDy(-5.575 + thickness * sqrt(2.));
+  bM2->SetDz(6.935);
+  bM2->RegisterYourself();
+
+  TGeoShape* coneBigShp2  = new TGeoCompositeShape("ConeBig2_shp", "bA2-bB:bM2");
+  TGeoVolume* coneBigVol2 = new TGeoVolume("ConeBig2", coneBigShp2, gStsMedium);
+  coneBigVol2->SetLineColor(kGreen);
+  //  coneBigVol2->RegisterYourself();
+
+  coneBigVol->AddNode(coneBigVol2, 1);
+
+  return coneBigVol;
+}
+
+/** ======================================================================= **/
diff --git a/macro/sts/geometry/create_stsgeo_v21g.C b/macro/sts/geometry/create_stsgeo_v21g.C
new file mode 100644
index 0000000000000000000000000000000000000000..73e85ea83a28e0c5e0d5b9d34c9a515a0cc21c93
--- /dev/null
+++ b/macro/sts/geometry/create_stsgeo_v21g.C
@@ -0,0 +1,2197 @@
+/* Copyright (C) 2012-2021 Goethe-Universitaet Frankfurt, Frankfurt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Mehul Shiroya [committer], Volker Friese, Evgeny Lavrik*/
+
+/******************************************************************************
+ ** Creation of STS geometry in ROOT format (TGeo).
+ **
+ ** @file create_stsgeo_v21g.C
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @since 15 June 2012
+ ** @date 09.05.2014
+ ** @author Tomas Balog <T.Balog@gsi.de>
+ ** 
+ ** v21g: Similar to the geometry version v21e 
+ * 		  [ Airex foam in the front and  back side wall (Solid).
+ * 		  New beam pipe R = 2.0 cm upstream-side with thickness 1mm.
+ * 		  Central ladders adjusted 5mm away from the beampipe. Global origin is taken from center of magnet. 
+ * 		  Origin of the STS is taken from last station which is located at(0,0,0) position.	
+ * 		  Global origin is considered from the center of the magnet.
+ *		  Nomenclature for the Halfladders has been changed from the upside(u)	to top (t)
+ * 	      and from downside(d) to bottom (b). ]
+ * 		  The only difference is that it includes beampipe flange in the back side of the wall,
+ * 		  which is considered to be made of carbon fiber(70%) and epoxy resin(30%).
+ **
+ ** v19r: bugfix of v19q - align all halfladders
+ ** v19q: based on v19l - align ladders to virtual plane in station center, closing the gaps in z
+ ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm
+ ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm
+ ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m)
+ ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug)
+ ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm
+ ** v19k: ladders on upstream side of units get upper half ladders installed first, 
+ **       ladders on downstream side of units get lower half ladders installed first, 
+ **       this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits)
+ **       parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm
+ ** v19j: use overlap and distance parameters from CAD model
+ ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm
+ ** v19g: place a box with services around v19e
+ ** v19f: place a box with services around v19d
+ ** v19e: increase spacing between stations by +10 mm from 100 mm
+ ** v19d: increase spacing between stations by + 5 mm from 100 mm
+ ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c
+ ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits)
+ ** v19a: import passive materials from gdml file
+ **       extend CF ladder structures and cables towards FEE plane
+ **       change CF ladder frame shape
+ ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b)
+ ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials
+ ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu
+ ** v18a: adds 9 cooling/holding plates and a box around the setup
+ ** v16g: v16g is the new standard geometry from November 2017
+ ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R")
+ ** v16f: switch from stations to units
+ **     - split in upstream / downstream and left / right parts
+ **     - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL
+ ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D")
+ ** v16d: skip keeping volumes of sts and stations
+ ** v16c: like v16b, but senors of ladders beampipe next to beampipe
+ **       shifted closer to the pipe, like in the CAD model
+ ** v16b: like v16a, but yellow sensors removed
+ ** v16a: derived from v15c (no cones), but with sensor types renamed:
+ ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5
+ **
+ ** v15c: as v15b without cones
+ ** v15b: introduce modified carbon ladders from v13z
+ ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design
+ **
+ ** TODO:
+ **
+ ** DONE:
+ ** v15b - use carbon macaroni as ladder support
+ ** v15b - introduce a small gap between lowest sensor and carbon ladder
+ ** v15b - build small cones for the first 2 stations
+ ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm
+ ** v15b - for all ladders set an even number of ladder elements 
+ ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26
+ ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors
+ ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size
+ **
+ ** The geometry hierarachy is:
+ **
+ ** 1. Sensors  (see function CreateSensors)
+ **    The sensors are the active volumes and the lowest geometry level.
+ **    They are built as TGeoVolumes, shape box, material silicon.
+ **    x size is determined by strip pitch 58 mu and 1024 strips 
+ **    plus guard ring of 1.3 mm at each border -> 6.1992 cm.
+ **    Sensor type 1 is half of that (3.0792 cm).
+ **    y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus
+ **    guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm.
+ **    z size is a parameter, to be set by gkSensorThickness.
+ **
+ ** 2. Sectors  (see function CreateSectors)
+ **    Sectors consist of several chained sensors. These are arranged
+ **    vertically on top of each other with a gap to be set by
+ **    gkChainGapY. Sectors are constructed as TGeoVolumeAssembly.
+ **    The sectors are auxiliary volumes used for proper placement
+ **    of the sensor(s) in the module. They do not show up in the
+ **    final geometry.
+ **
+ ** 3. Modules (see function ConstructModule)
+ **    A module is a readout unit, consisting of one sensor or
+ **    a chain of sensors (see sector) and a cable.
+ **    The cable extends from the top of the sector vertically to the
+ **    top of the halfladder the module is placed in. The cable and module
+ **    volume thus depend on the vertical position of the sector in 
+ **    the halfladder. The cables consist of silicon with a thickness to be
+ **    set by gkCableThickness.
+ **    Modules are constructed as TGeoVolume, shape box, medium gStsMedium.
+ **    The module construction can be switched off (gkConstructCables)
+ **    to reproduce older geometries.
+ **
+ ** 4. Halfladders (see function ConstructHalfLadder)
+ **    A halfladder is a vertical assembly of several modules. The modules
+ **    are placed vertically such that their sectors overlap by 
+ **    gkSectorOverlapY. They are displaced in z direction to allow for the 
+ **    overlap in y by gkSectorGapZ.
+ **    The horizontal placement of modules in the halfladder can be choosen
+ **    to left aligned or right aligned, which only matters if sensors of
+ **    different x size are involved.
+ **    Halfladders are constructed as TGeoVolumeAssembly.
+ **
+ ** 5. Ladders (see function CreateLadders and ConstructLadder)
+ **    A ladder is a vertical assembly of two halfladders, and is such the
+ **    vertical building block of a station. The second (bottom) half ladder
+ **    is rotated upside down. The vertical arrangement is such that the
+ **    inner sectors of the two halfladders have the overlap gkSectorOverlapY
+ **    (function CreateLadder) or that there is a vertical gap for the beam
+ **    hole (function CreateLadderWithGap).
+ **    Ladders are constructed as TGeoVolumeAssembly.
+ **   
+ ** 6. Stations (see function ConstructStation)
+ **    A station represents one layer of the STS geometry: one measurement
+ **    at (approximately) a given z position. It consist of several ladders
+ **    arranged horizontally to cover the acceptance.
+ **    The ladders are arranged such that there is a horizontal overlap
+ **    between neighbouring ladders (gkLadderOverLapX) and a vertical gap
+ **    to allow for this overlap (gkLadderGapZ). Each second ladder is
+ **    rotated around its y axis to face away from or into the beam.
+ **    Stations are constructed as TGeoVolumes, shape box minus tube (for
+ **    the beam hole), material gStsMedium.
+ **
+ ** 7. STS
+ **    The STS is a volume hosting the entire detectors system. It consists
+ **    of several stations located at different z positions.
+ **    The STS is constructed as TGeoVolume, shape box minus cone (for the
+ **    beam pipe), material gStsMedium. The size of the box is computed to
+ **    enclose all stations.
+ *****************************************************************************/
+
+
+// Remark: With the proper steering variables, this should exactly reproduce
+// the geometry version v11b of A. Kotynia's described in the ASCII format.
+// The only exception is a minimal difference in the z position of the
+// sectors/sensors. This is because of ladder types 2 and 4 containing the half
+// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders
+// covering the beam hole cannot be transformed into each other by rotations,
+// but only by a reflection. This means they are constructionally different.
+// To avoid introducing another two ladder types, the difference in z position
+// was accepted.
+
+
+// Differences to v12:
+// gkChainGap reduced from 1 mm to 0
+// gkCableThickness increased from 100 mum to 200 mum (2 cables per module)
+// gkSectorOverlapY reduced from 3 mm to 2.4 mm
+// New sensor types 05 and 06
+// New sector types 07 and 08
+// Re-definiton of ladders (17 types instead of 8)
+// Re-definiton of station from new ladders
+
+
+#include "TGeoCompositeShape.h"
+#include "TGeoCone.h"
+#include "TGeoManager.h"
+#include "TGeoPara.h"
+#include "TGeoPhysicalNode.h"
+#include "TGeoTrd2.h"
+#include "TGeoTube.h"
+#include "TGeoXtru.h"
+
+#include <iomanip>
+#include <iostream>
+
+// forward declarations
+Int_t CreateSensors();
+Int_t CreateSectors();
+Int_t CreateLadders();
+TGeoVolume* ConstructModule(const char* name, TGeoVolume* sector, Double_t cableLength);
+TGeoVolume* ConstructHalfLadder(const TString& name, Int_t nSectors, Int_t* sectorTypes, char align,
+                                Double_t ladderLength, Double_t offsetY);
+TGeoVolume* ConstructLadder(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t gapY,
+                            Double_t shiftZ, Double_t pitchZ, Int_t nSectors);
+TGeoVolume* ConstructUnit(Int_t iSide, Int_t iUnit, Int_t nLadders, Int_t* ladderTypes, Int_t iStation);
+void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile);
+void PostProcessGdml(TGeoVolume* gdmlTop);
+void CheckVolume(TGeoVolume* volume);
+void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE);
+Double_t BeamPipeRadius(Double_t z);
+TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x);
+TGeoVolume* ConstructSmallCone(Double_t coneDz);
+TGeoVolume* ConstructBigCone(Double_t coneDz);
+
+// -------------   Version highlight        -----------------------------------
+
+const std::string gVersionHighlight = R"(
+Summary:
+  This version adds passive materials imported from GDML model to the STS geometry:
+    * Taken from and largely correspond to mechanical CAD drawings of the detector
+    * Thermal insulation box:
+      - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet)
+      - front window of complex shape with interface to MVD / target chamber
+      - back window with large aperture (2000 x 1200 mm) square cut into carbon foam
+    * Structural units:
+      - made of 2 complex shape aluminum C-Frames, 15mm thick
+      - placed at 25, 35, ... ,105 cm absolute Z
+      - contain front-end and power distribution boxes with equivalent X_0 values
+
+  Scripted geometry tweaks:
+    * Ladders and cables are extended towards the read-out planes having same lengths in respective rows
+    * Adjusted form and shape of carbon ladder structures from L-type to X-type
+    * Reduced verbosity of this file
+
+  Sensor arrangement is the same as in version v16g
+
+  !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall.
+  The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e
+)";
+
+// -------------   Steering variables       -----------------------------------
+
+// ---> Horizontal width of sensors [cm]
+const Double_t gkSensorSizeX = 6.2;  // was 6.2092;  // 6.2 - Oleg CAD 15/05/2020
+
+// ---> Thickness of sensors [cm]
+const Double_t gkSensorThickness = 0.03;
+
+// ---> Vertical gap between chained sensors [cm]
+const Double_t gkChainGapY = 0.00;
+
+// ---> Thickness of cables [cm]
+const Double_t gkCableThickness = 0.02;
+
+// ---> Horizontal overlap of neighbouring ladders [cm]
+const Double_t gkLadderOverlapX = 0.25;  // delta X - Oleg CAD 14/05/2020
+
+// ---> Vertical overlap of neighbouring sectors in a ladder [cm]
+const Double_t gkSectorOverlapY = 0.46;  // delta Y - Oleg CAD 14/05/2020
+
+// ---> Gap in z between neighbouring sectors in a ladder [cm]
+const Double_t gkSectorGapZ = 0.12;  // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020
+
+// ---> Gap in z between neighbouring ladders [cm]
+const Double_t gkLadderGapZ = 0.50 - 0.15;  // for asym // 0.5 for sym  // delta Z prime
+
+// ---> Gap in z between lowest sector to carbon support structure [cm]
+const Double_t gkSectorGapZFrame =
+  0.280
+  - 0.025;  // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder
+
+// ---> Switch to construct / not to construct readout cables
+const Bool_t gkConstructCables = kTRUE;
+
+// ---> Switch to construct / not to construct frames
+const Bool_t gkConstructCones       = kFALSE;  // kTRUE;   // switch this false by default for v15c and v16x
+const Bool_t gkConstructFrames      = kTRUE;   // kFALSE;  // switch this true  by default for v15c and v16x
+const Bool_t gkConstructSmallFrames = kTRUE;   // kFALSE;
+const Bool_t gkCylindricalFrames    = kTRUE;   // kFALSE;
+
+// ---> Size of the frame
+const Double_t gkFrameThickness     = 0.2;
+const Double_t gkThinFrameThickness = 0.05;
+const Double_t gkFrameStep          = 4.0;  // size of frame cell along y direction
+const Double_t gkCylinderDiaInner =
+  0.07;  // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015)
+const Double_t gkCylinderDiaOuter =
+  0.15;  // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015)
+
+// ---> Switch to import / not to import the Passive materials from GDML file
+const Bool_t gkImportPassive = kTRUE;
+
+// ----------------------------------------------------------------------------
+
+
+// --------------   Parameters of beam pipe in the STS region    --------------
+// ---> Needed to compute stations and STS such as to avoid overlaps
+const Double_t gkPipeZ1 = 18.0;
+const Double_t gkPipeR1 = 2.0;
+const Double_t gkPipeZ2 = 125.0;
+const Double_t gkPipeR2 = 5.0;
+//const Double_t gkPipeZ3 = 125.0;
+//const Double_t gkPipeR3 = 5.5;
+
+//const Double_t gkPipeZ2 = 50.0;
+//const Double_t gkPipeR2 = 1.8;
+
+//DE const Double_t gkPipeZ1 =  27.0;
+//DE const Double_t gkPipeR1 =   1.05;
+//DE const Double_t gkPipeZ2 = 160.0;
+//DE const Double_t gkPipeR2 =   3.25;
+// ----------------------------------------------------------------------------
+
+//TString unitName[16] =    // names of units for v16e
+// {            "Unit00D",
+//   "Unit01U", "Unit01D",
+//   "Unit02U", "Unit02D",
+//   "Unit03U", "Unit03D",
+//   "Unit04U", "Unit04D",
+//   "Unit05U", "Unit05D",
+//   "Unit06U", "Unit06D",
+//   "Unit07U", "Unit07D",
+//   "Unit08U"            };
+
+//TString unitName[32] =    // names of units for v16f
+// {                         "Unit00DR", "Unit00DL",
+//   "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL",
+//   "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL",
+//   "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL",
+//   "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL",
+//   "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL",
+//   "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL",
+//   "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL",
+//   "Unit08UR", "Unit08UL" };
+
+TString unitName[32] =  // names of units for v16g - while merging D and U parts
+  {"Unit00R", "Unit00L", "Unit01R", "Unit01L", "Unit01R", "Unit01L", "Unit02R", "Unit02L",
+   "Unit02R", "Unit02L", "Unit03R", "Unit03L", "Unit03R", "Unit03L", "Unit04R", "Unit04L",
+   "Unit04R", "Unit04L", "Unit05R", "Unit05L", "Unit05R", "Unit05L", "Unit06R", "Unit06L",
+   "Unit06R", "Unit06L", "Unit07R", "Unit07L", "Unit07R", "Unit07L", "Unit08R", "Unit08L"};
+
+TString unitName18[18] =  // names of units for v16g
+  {"Unit00R", "Unit00L", "Unit01R", "Unit01L", "Unit02R", "Unit02L", "Unit03R", "Unit03L", "Unit04R",
+   "Unit04L", "Unit05R", "Unit05L", "Unit06R", "Unit06L", "Unit07R", "Unit07L", "Unit08R", "Unit08L"};
+
+// -------------   Other global variables   -----------------------------------
+// ---> STS medium (for every volume except silicon)
+TGeoMedium* gStsMedium = NULL;  // will be set later
+// ---> TGeoManager (too lazy to write out 'Manager' all the time
+TGeoManager* gGeoMan = NULL;  // will be set later
+// ----------------------------------------------------------------------------
+
+
+// ============================================================================
+// ======                         Main function                           =====
+// ============================================================================
+
+void create_stsgeo_v21g(const char* geoTag = "v21g")
+{
+
+  // -------   Geometry file name (output)   ----------------------------------
+  TString geoFileName = "sts_";
+  geoFileName         = geoFileName + geoTag + ".geo.root";
+  // --------------------------------------------------------------------------
+
+
+  // -------   Open info file   -----------------------------------------------
+  TString infoFileName = geoFileName;
+  infoFileName.ReplaceAll("root", "info");
+  fstream infoFile;
+  infoFile.open(infoFileName.Data(), fstream::out);
+  infoFile << "STS geometry created with create_stsgeo_v21g.C" << endl;
+  infoFile << gVersionHighlight << endl;
+  infoFile << "Global variables: " << endl;
+  infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl;
+  infoFile << "Vertical gap in sensor chain = " << gkChainGapY << " cm" << endl;
+  infoFile << "Vertical overlap of sensors = " << gkSectorOverlapY << " cm" << endl;
+  infoFile << "Gap in z between neighbour sensors = " << gkSectorGapZ << " cm" << endl;
+  infoFile << "Horizontal overlap of sensors = " << gkLadderOverlapX << " cm" << endl;
+  infoFile << "Gap in z between neighbour ladders = " << gkLadderGapZ << " cm" << endl;
+  if (gkConstructCables) infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl;
+  else
+    infoFile << "No cables" << endl;
+  infoFile << endl;
+  infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " << gkPipeZ1 << " cm" << endl;
+  infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " << gkPipeZ2 << " cm" << endl;
+  //infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " << gkPipeZ3
+  //         << " cm" << endl;
+  // --------------------------------------------------------------------------
+
+
+  // -------   Load media from media file   -----------------------------------
+  FairGeoLoader* geoLoad    = new FairGeoLoader("TGeo", "FairGeoLoader");
+  FairGeoInterface* geoFace = geoLoad->getGeoInterface();
+  TString geoPath           = gSystem->Getenv("VMCWORKDIR");
+  TString medFile           = geoPath + "/geometry/media.geo";
+  geoFace->setMediaFile(medFile);
+  geoFace->readMedia();
+  gGeoMan = gGeoManager;
+  gSystem->Load("libGeom");
+  // --------------------------------------------------------------------------
+
+
+  // -----------------   Get and create the required media    -----------------
+  FairGeoMedia* geoMedia   = geoFace->getMedia();
+  FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
+
+  // ---> air
+  FairGeoMedium* mAir = geoMedia->getMedium("air");
+  if (!mAir) Fatal("Main", "FairMedium air not found");
+  geoBuild->createMedium(mAir);
+  TGeoMedium* air = gGeoMan->GetMedium("air");
+  if (!air) Fatal("Main", "Medium air not found");
+
+  // ---> air
+  FairGeoMedium* mvacuum = geoMedia->getMedium("vacuum");
+  if (!mvacuum) Fatal("Main", "FairMedium vacuum not found");
+  geoBuild->createMedium(mvacuum);
+  TGeoMedium* Vacuum = gGeoMan->GetMedium("vacuum");
+  if (!Vacuum) Fatal("Main", "Medium vacuum not found");
+
+  // ---> silicon
+  FairGeoMedium* mSilicon = geoMedia->getMedium("silicon");
+  if (!mSilicon) Fatal("Main", "FairMedium silicon not found");
+  geoBuild->createMedium(mSilicon);
+  TGeoMedium* silicon = gGeoMan->GetMedium("silicon");
+  if (!silicon) Fatal("Main", "Medium silicon not found");
+
+  // ---> carbon
+  FairGeoMedium* mCarbon = geoMedia->getMedium("carbon");
+  if (!mCarbon) Fatal("Main", "FairMedium carbon not found");
+  geoBuild->createMedium(mCarbon);
+  TGeoMedium* carbon = gGeoMan->GetMedium("carbon");
+  if (!carbon) Fatal("Main", "Medium carbon not found");
+
+  // ---> STSBoxCarbonFoam
+  FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam");
+  if (!mSTSBoxCarbonFoam) Fatal("Main", "FairMedium STSBoxCarbonFoam not found");
+  geoBuild->createMedium(mSTSBoxCarbonFoam);
+  TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam");
+  if (!STSBoxCarbonFoam) Fatal("Main", "Medium STSBoxCarbonFoam not found");
+
+  // ---> STSBoxCarbonFibre
+  FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre");
+  if (!mSTSBoxCarbonFibre) Fatal("Main", "FairMedium STSBoxCarbonFibre not found");
+  geoBuild->createMedium(mSTSBoxCarbonFibre);
+  TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre");
+  if (!STSBoxCarbonFibre) Fatal("Main", "Medium STSBoxCarbonFibre not found");
+
+  // ---> STScable
+  FairGeoMedium* mSTScable = geoMedia->getMedium("STScable");
+  if (!mSTScable) Fatal("Main", "FairMedium STScable not found");
+  geoBuild->createMedium(mSTScable);
+  TGeoMedium* STScable = gGeoMan->GetMedium("STScable");
+  if (!STScable) Fatal("Main", "Medium STScable not found");
+
+  // ---> Aluminium
+  FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium");
+  if (!mAluminium) Fatal("Main", "FairMedium aluminium not found");
+  geoBuild->createMedium(mAluminium);
+  TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium");
+  if (!aluminium) Fatal("Main", "Medium aluminium not found");
+
+  // ---
+  //gStsMedium = air;
+  gStsMedium = gGeoMan->GetMedium("air");
+  if (!gStsMedium) Fatal("Main", "medium sts_air not found");
+  // --------------------------------------------------------------------------
+  // --------------------------------------------------------------------------
+
+  // --------------   Create geometry and top volume  -------------------------
+  gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
+  //gGeoMan->SetName("STSgeom");
+  TGeoVolume* top = new TGeoVolumeAssembly("top");
+  //  TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.);
+  //  TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air"));
+  gGeoMan->SetTopVolume(top);
+
+  // --------------------------------------------------------------------------
+
+
+  // --------------   Create media   ------------------------------------------
+  /*
+  cout << endl;
+  cout << "===> Creating media....";
+  cout << CreateMedia();
+  cout << " media created" << endl;
+  TList* media = gGeoMan->GetListOfMedia();
+  for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) {
+    cout << "Medium " << iMedium << ": " 
+   << ((TGeoMedium*) media->At(iMedium))->GetName() << endl;
+  }
+  gStsMedium = gGeoMan->GetMedium("air");
+  if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found");
+  */
+  // --------------------------------------------------------------------------
+
+
+  // ---------------   Create sensors   ---------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating sensors...." << endl << endl;
+  infoFile << endl << "Sensors: " << endl;
+  Int_t nSensors = CreateSensors();
+  for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) {
+    TString name       = Form("Sensor%02d", iSensor);
+    TGeoVolume* sensor = gGeoMan->GetVolume(name);
+
+    // add color to sensors
+    if (iSensor == 1) sensor->SetLineColor(kRed);
+    if (iSensor == 2) sensor->SetLineColor(kGreen + 3);
+    if (iSensor == 3) sensor->SetLineColor(kBlue + 3);
+    if (iSensor == 4) sensor->SetLineColor(kAzure - 7);
+    if (iSensor == 5) sensor->SetLineColor(kYellow);
+    if (iSensor == 6) sensor->SetLineColor(kYellow);
+    if (iSensor == 7) sensor->SetLineColor(kYellow);
+
+    CheckVolume(sensor);
+    CheckVolume(sensor, infoFile);
+  }
+  // --------------------------------------------------------------------------
+
+
+  // ----------------   Create sectors   --------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating sectors...." << endl;
+  // infoFile << endl << "Sectors: " << endl;
+  Int_t nSectors = CreateSectors();
+  for (Int_t iSector = 1; iSector <= nSectors; iSector++) {
+    // cout << endl;
+    TString name       = Form("Sector%02d", iSector);
+    TGeoVolume* sector = gGeoMan->GetVolume(name);
+    CheckVolume(sector);
+    // CheckVolume(sector, infoFile);
+  }
+  // --------------------------------------------------------------------------
+
+
+  // ----------------   Create ladders   --------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating ladders...." << endl;
+  infoFile << endl << "Ladders:" << endl;
+
+  TString name = "";
+  TGeoVolume* ladder;
+
+
+  Int_t nLadders = CreateLadders();
+
+  for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) {
+    cout << endl;
+
+    //    name = Form("LadderType%02d", iLadder);  // v19a
+    //    name = Form("LadderType0%02d", iLadder); // v19b
+    name   = Form("LadderType00%02d", iLadder);  // v19k
+    ladder = gGeoMan->GetVolume(name);
+    CheckVolume(ladder);
+    CheckVolume(ladder, infoFile, kFALSE);
+
+    cout << "DF1: ladder name: " << name << endl << endl;
+
+    //    name = Form("LadderType%02d", iLadder);  // v19a
+    //    name = Form("LadderType1%02d", iLadder); // v19b
+    name   = Form("LadderType01%02d", iLadder);  // v19k
+    ladder = gGeoMan->GetVolume(name);
+    CheckVolume(ladder);
+    CheckVolume(ladder, infoFile, kFALSE);
+
+    cout << "DF2: ladder name: " << name << endl << endl;
+
+    //    name = Form("LadderType%02d", iLadder);  // v19a
+    name   = Form("LadderType10%02d", iLadder);  // v19k
+    ladder = gGeoMan->GetVolume(name);
+    CheckVolume(ladder);
+    CheckVolume(ladder, infoFile, kFALSE);
+
+    cout << "DF3: ladder name: " << name << endl << endl;
+
+    //    name = Form("LadderType%02d", iLadder);  // v19a
+    name   = Form("LadderType11%02d", iLadder);  // v19k
+    ladder = gGeoMan->GetVolume(name);
+    CheckVolume(ladder);
+    CheckVolume(ladder, infoFile, kFALSE);
+
+    cout << "DF4: ladder name: " << name << endl << endl;
+  }
+  // --------------------------------------------------------------------------
+
+
+  // ----------------   Create cones   ----------------------------------------
+  Double_t coneDz            = 1.64;
+  TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz);
+  if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found");
+  TGeoVolume* coneBigVolum = ConstructBigCone(coneDz);
+  if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found");
+  // --------------------------------------------------------------------------
+
+  // ----------------   Create stations   -------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating stations...." << endl;
+  infoFile << endl << "Stations: " << endl;
+  Int_t angle = 0;
+  nLadders    = 0;
+  Int_t ladderTypes[16];  // there are max 16 ladders in one layer
+  TGeoTranslation* statTrans = NULL;
+
+  TGeoVolume* myunit[32];  // units
+
+  //  Int_t statPos[16]   = { 30, 30, 40, 40, 50, 50,  60,  60,
+  //                          70, 70, 80, 80, 90, 90, 100, 100 };  // z positions of units
+  //  Int_t statPos18[18] = { 30, 30,                              // expanded for placement of Unit00
+  //                          30, 30, 40, 40, 50, 50,  60,  60,
+  //                          70, 70, 80, 80, 90, 90, 100, 100 };  // z positions of units
+  // v19h
+
+  Double_t statPos[16] = {-73.5, -73.5, -63.0, -63.0, -52.5, -52.5, -42.0, -42.0,
+                          -31.5, -31.5, -21.0, -21.0, -10.5, -10.5, 0,     0};
+
+  Double_t statPos18[18] = {-73.5, -73.5, -73.5, -73.5, -63.0, -63.0, -52.5, -52.5, -42.0,
+                            -42.0, -31.5, -31.5, -21.0, -21.0, -10.5, -10.5, 0,     0};  // z positions of unit
+
+  //  // v19d
+  //  Double_t statPos[16]   = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0,  61.5,  61.5,
+  //                             72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 };  // z positions of units
+  //  Double_t statPos18[18] = { 30.0, 30.0,                              // expanded for placement of Unit00
+  //                             30.0, 30.0, 40.5, 40.5, 51.0, 51.0,  61.5,  61.5,
+  //                             72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 };  // z positions of units
+
+  ////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 };  // size of cutouts in stations
+  //  Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 };  // size of cutouts in stations, derived from gapXYZ[x][1]/2
+
+  Int_t cone_size[8] = {0, 0, 0, 1, 1, 1, 1, 1};  // size of cones: 0 = small, 1 = large
+
+  Double_t cone_offset[2] = {0.305, 0.285};
+
+  //==============================================================================================
+
+  // explanation: type xyzz
+  // where  x = carbon ladder orientation
+  // where  y = FEB box orientation
+  // where zz = sensor arrangement on ladder
+  // with FEB orientation - v19b
+  Int_t allUnitTypes[16][16] = {
+    {-1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1},         // unit00D Station01 00
+    {-1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1},  // unit01U Station01 01
+
+    {-1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1},             // unit01D Station02 02
+    {-1, -1, 1130, 0, 1129, 0, 1128, 0, 1002, 0, 1028, 0, 1029, 0, -1, -1},  // unit02U Station02 03
+
+    {-1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1},           // unit02D Station03 04
+    {-1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1},  // unit03U Station03 05
+
+    {-1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1},              // unit03D Station04 06
+    {-1, 0, 1133, 0, 1131, 0, 1131, 0, 1004, 0, 1031, 0, 1032, 0, 1034, -1},  // unit04U Station04 07
+
+    {-1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1},            // unit04D Station05 08
+    {-1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1},  // unit05U Station05 09
+
+    {-1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1},              // unit05D Station06 10
+    {-1, 0, 1137, 0, 1136, 0, 1135, 0, 1006, 0, 1035, 0, 1036, 0, 1038, -1},  // unit06U Station06 11
+
+    {21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0},              // unit06D Station07 12
+    {0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021},  // unit07U Station07 13
+
+    {0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126},                // unit07D Station08 14
+    {1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0}};  // unit08U Station08 15
+
+
+  //==============================================================================================
+
+  // without FEB orientation - v19a
+  // v19a   Int_t allUnitTypes[16][16]=
+  // v19a   { {  -1,  -1,  -1,  -1,  10,   0,   9,   0,     1,   0,   9,   0,  -1,  -1,  -1,  -1 },    // unit00D Station01 00
+  // v19a     {  -1,  -1,  -1,  -1,   0, 109,   0, 101,     0, 109,   0, 110,  -1,  -1,  -1,  -1 },    // unit01U Station01 01
+  // v19a     {  -1,  -1,   0,  10,   0,   9,   0,   2,     0,   9,   0,  10,   0,  11,  -1,  -1 },    // unit01D Station02 02
+  // v19a     {  -1,  -1, 111,   0, 110,   0, 109,   0,   102,   0, 109,   0, 110,   0,  -1,  -1 },    // unit02U Station02 03
+  // v19a     {  -1,  -1,  14,   0,  12,   0,  12,   0,     3,   0,  12,   0,  13,   0,  -1,  -1 },    // unit02D Station03 04
+  // v19a     {  -1,  -1,   0, 113,   0, 112,   0, 103,     0, 112,   0, 112,   0, 114,  -1,  -1 },    // unit03U Station03 05
+  // v19a     {  -1,  15,   0,  13,   0,  12,   0,   4,     0,  12,   0,  12,   0,  14,   0,  -1 },    // unit03D Station04 06
+  // v19a     {  -1,   0, 114,   0, 112,   0, 112,   0,   104,   0, 112,   0, 113,   0, 115,  -1 },    // unit04U Station04 07
+  // v19a     {  -1,   0,  18,   0,  17,   0,  16,   0,     5,   0,  16,   0,  17,   0,  19,  -1 },    // unit04D Station05 08
+  // v19a     {  -1, 119,   0, 117,   0, 116,   0, 105,     0, 116,   0, 117,   0, 118,   0,  -1 },    // unit05U Station05 09
+  // v19a     {  -1,  19,   0,  17,   0,  16,   0,   6,     0,  16,   0,  17,   0,  18,   0,  -1 },    // unit05D Station06 10
+  // v19a     {  -1,   0, 118,   0, 117,   0, 116,   0,   106,   0, 116,   0, 117,   0, 119,  -1 },    // unit06U Station06 11
+  // v19a     {  21,   0,  25,   0,  20,   0,  20,   0,     7,   0,  20,   0,  20,   0,  27,   0 },    // unit06D Station07 12
+  // v19a     {   0, 127,   0, 120,   0, 120,   0, 107,     0, 120,   0, 120,   0, 125,   0, 121 },    // unit07U Station07 13
+  // v19a     {   0,  24,   0,  22,   0,  22,   0,   8,     0,  22,   0,  22,   0,  23,   0,  26 },    // unit07D Station08 14
+  // v19a     { 126,   0, 123,   0, 122,   0, 122,   0,   108,   0, 122,   0, 122,   0, 124,   0 } };  // unit08U Station08 15
+
+  //  // generate unit
+  //  for (Int_t iUnit = 0; iUnit < 16; iUnit++)
+  //    for (Int_t iLadder = 0; iLadder < 16; iLadder++)
+  //    {
+  //      allUnitTypes[iUnit][iLadder] = 0;
+  //      if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] <  100))  // if carbon structure is oriented upstream
+  //        allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder];
+  //      if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100))  // if carbon structure is oriented downstream
+  //        allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder];
+  //    }
+
+
+  // dump unit
+  for (Int_t iUnit = 0; iUnit < 16; iUnit++) {
+    cout << "DE unitTypes[" << iUnit << "] = { ";
+    for (Int_t iLadder = 0; iLadder < 16; iLadder++) {
+      cout << allUnitTypes[iUnit][iLadder];
+      if (iLadder < 15) cout << ", ";
+      else
+        cout << " };";
+    }
+    cout << endl;
+  }
+
+
+  // --- Units 01 - 16
+  for (Int_t iUnit = 0; iUnit < 16; iUnit++) {
+    cout << endl;
+
+    nLadders = 0;
+    //int ladderTypes[nLadders];
+    for (Int_t iLadder = 0; iLadder < 16; iLadder++)
+      if (allUnitTypes[iUnit][iLadder] >= 0) {
+        ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder];
+        cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl;
+        nLadders++;
+      }
+    myunit[iUnit * 2 + 0] = ConstructUnit(0, iUnit * 2 + 0, nLadders, ladderTypes, iUnit / 2 + 1);
+    myunit[iUnit * 2 + 1] = ConstructUnit(1, iUnit * 2 + 1, nLadders, ladderTypes, iUnit / 2 + 1);
+
+    //    if (gkConstructCones) {
+    //      if (iUnit%2 == 0)
+    //        angle =  90;
+    //      else
+    //        angle = -90;
+    //
+    //      // upstream
+    //      TGeoRotation* coneRot11 = new TGeoRotation;
+    //      coneRot11->RotateZ(angle);
+    //      coneRot11->RotateY(180);
+    //      TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11);
+    //      if (cone_size[iUnit] == 0)
+    //        myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11);
+    //      else
+    //        myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11);
+    //
+    //      // downstream
+    //      TGeoRotation* coneRot12 = new TGeoRotation;
+    //      coneRot12->RotateZ(angle);
+    //      TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0.,  coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12);
+    //      if (cone_size[iUnit] == 0)
+    //        myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12);
+    //      else
+    //        myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12);
+    //
+    //      myunit[iUnit]->GetShape()->ComputeBBox();
+    //    }
+
+    //    CheckVolume(myunit[iUnit]);
+    //    CheckVolume(myunit[iUnit], infoFile);
+    if ((iUnit % 2 == 0) || (iUnit == 15)) {
+      CheckVolume(myunit[iUnit * 2 + 0]);
+      CheckVolume(myunit[iUnit * 2 + 0], infoFile);
+      CheckVolume(myunit[iUnit * 2 + 1]);
+      CheckVolume(myunit[iUnit * 2 + 1], infoFile);
+    }
+    infoFile << "Position z = " << statPos[iUnit] << endl;
+  }
+  // --------------------------------------------------------------------------
+
+
+  // ---------------   Create STS volume   ------------------------------------
+  cout << endl << endl;
+  cout << "===> Creating STS...." << endl;
+
+  // --- Create STS volume
+  TString stsName = "sts_";
+  stsName += geoTag;
+
+  //  TGeoShape* stsShape = new TGeoCompositeShape("stsShape",
+  //                                               "stsBox-stsCone1:trans1-stsCone2:trans2");
+  //  TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium);
+
+  Double_t stsBorder = 2 * 5.;
+
+  TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data());
+
+  // --- Place stations in the STS
+  Double_t stsPosZ = 0.5 * (statPos[15] + statPos[0]);  // todo units: update statPos[7]
+  //cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl;
+
+  //  for (Int_t iUnit = 0; iUnit < 16; iUnit++) {
+  for (Int_t iUnit = 0; iUnit < 18; iUnit++) {
+    //  for (Int_t iUnit = 0; iUnit < 32; iUnit++) {
+    TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]);
+    //    Double_t posZ = statPos[iUnit] - stsPosZ;
+    //Double_t posZ = statPos18[iUnit] - stsPosZ;
+    Double_t posZ =
+      statPos18[iUnit];  // change has been implemented because local sts origin is taken from last station of sts.
+    cout << "Here is position_Z of stations : " << posZ << endl;
+
+    //    Double_t posZ = statPos[iUnit/2] - stsPosZ;
+    TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ);
+    sts->AddNode(station, iUnit + 1, trans);
+    sts->GetShape()->ComputeBBox();
+  }
+
+  // --- Import passive elements from GDML file
+  if (gkImportPassive) { ImportPassive(sts, geoTag, infoFile); }
+
+  // --------------------------------------------------------------------------
+  // --------------------------------------------------------------------------
+
+  cout << endl;
+  CheckVolume(sts);
+
+
+  // ---------------   Finish   -----------------------------------------------
+  cout << "Here is sts_position_Z : " << stsPosZ << endl;
+  //  cout << "Here is position_Z of units : " << posZ << endl;
+
+  //  TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ);
+
+  // to make translation to the center of magnet (Reason: Origin point{x=0, y=0, z=0} is taken from the last sts station.)
+  TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., 59.5);
+  top->AddNode(sts, 1, stsTrans);
+  top->GetShape()->ComputeBBox();
+  cout << endl << endl;
+
+  CheckVolume(top);
+  cout << endl << endl;
+  gGeoMan->CloseGeometry();
+  gGeoMan->CheckOverlaps(0.0001);
+  gGeoMan->PrintOverlaps();
+  gGeoMan->CheckOverlaps(0.0001, "s");
+  gGeoMan->PrintOverlaps();
+  gGeoMan->Test();
+
+  //TFile* geoFile = new TFile(geoFileName, "RECREATE");
+  //top->Write();
+  sts->Export(geoFileName);  // an another way of writing the stsvolume placement
+
+  TFile* geoFile                        = new TFile(geoFileName, "UPDATE");
+  TGeoTranslation* sts_volume_placement = new TGeoTranslation("sts_trans", 0., 0., 59.5);
+  sts_volume_placement->Write();
+  //*/
+  cout << endl;
+  cout << "Geometry " << top->GetName() << " written to " << geoFileName << endl;
+  geoFile->Close();
+
+  TString geoFileName_ = "sts_";
+  geoFileName_         = geoFileName_ + geoTag + "_geo.root";
+
+  geoFile = new TFile(geoFileName_, "RECREATE");
+  gGeoMan->Write();  // use this is you want GeoManager format in the output
+  geoFile->Close();
+
+  TString geoFileName__ = "sts_";
+  geoFileName_          = geoFileName__ + geoTag + "-geo.root";
+  sts->Export(geoFileName_);
+
+  geoFile = new TFile(geoFileName_, "UPDATE");
+  stsTrans->Write();
+  geoFile->Close();
+
+
+  // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl");
+  top->Draw("ogl");
+  //sts->Draw("ogl");
+  gGeoManager->SetVisLevel(9);
+
+  infoFile.close();
+}
+// ============================================================================
+// ======                   End of main function                          =====
+// ============================================================================
+
+
+// ****************************************************************************
+// *****      Definition of media, sensors, sectors and ladders           *****
+// *****                                                                  *****
+// *****     Decoupled from main function for better readability          *****
+// ****************************************************************************
+
+/** ===========================================================================
+ ** Create media
+ **
+ ** Currently created: air, active silicon, passive silion
+ **
+ ** Not used for the time being
+ **/
+Int_t CreateMedia()
+{
+
+  Int_t nMedia     = 0;
+  Double_t density = 0.;
+
+  // --- Material air
+  density             = 1.205e-3;  // [g/cm^3]
+  TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density);
+  matAir->AddElement(14.0067, 7, 0.755);  // Nitrogen
+  matAir->AddElement(15.999, 8, 0.231);   // Oxygen
+  matAir->AddElement(39.948, 18, 0.014);  // Argon
+
+  // --- Material silicon
+  density             = 2.33;  // [g/cm^3]
+  TGeoElement* elSi   = gGeoMan->GetElementTable()->GetElement(14);
+  TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density);
+
+
+  // --- Air (passive)
+  TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir);
+  medAir->SetParam(0, 0.);     // is passive
+  medAir->SetParam(1, 1.);     // is in magnetic field
+  medAir->SetParam(2, 20.);    // max. field [kG]
+  medAir->SetParam(6, 0.001);  // boundary crossing precision [cm]
+
+
+  // --- Active silicon for sensors
+  TGeoMedium* medSiAct = new TGeoMedium("silicon", nMedia++, matSi);
+  medSiAct->SetParam(0, 1.);     // is active
+  medSiAct->SetParam(1, 1.);     // is in magnetic field
+  medSiAct->SetParam(2, 20.);    // max. field [kG]
+  medSiAct->SetParam(6, 0.001);  // boundary crossing precisison [cm]
+
+  // --- Passive silicon for cables
+  TGeoMedium* medSiPas = new TGeoMedium("carbon", nMedia++, matSi);
+  medSiPas->SetParam(0, 0.);     // is passive
+  medSiPas->SetParam(1, 1.);     // is in magnetic field
+  medSiPas->SetParam(2, 20.);    // max. field [kG]
+  medSiPas->SetParam(6, 0.001);  // boundary crossing precisison [cm]
+
+  return nMedia;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Create sensors
+ **
+ ** Sensors are created as volumes with box shape and active silicon as medium.
+ ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2
+ **/
+Int_t CreateSensors()
+{
+
+  Int_t nSensors = 0;
+
+  Double_t xSize      = 0.;
+  Double_t ySize      = 0.;
+  Double_t zSize      = gkSensorThickness;
+  TGeoMedium* silicon = gGeoMan->GetMedium("silicon");
+
+
+  // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm)
+  xSize                    = gkSensorSizeX;
+  ySize                    = 2.2;
+  TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor01", shape_sensor01, silicon);
+  nSensors++;
+
+
+  // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm)
+  xSize                    = gkSensorSizeX;
+  ySize                    = 4.2;
+  TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor02", shape_sensor02, silicon);
+  nSensors++;
+
+
+  // ---  Sensor type 03: Big sensor (6.2 cm x 6.2 cm)
+  xSize                    = gkSensorSizeX;
+  ySize                    = 6.2;
+  TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor03", shape_sensor03, silicon);
+  nSensors++;
+
+
+  // ---  Sensor type 04: Big sensor (6.2 cm x 12.4 cm)
+  xSize                    = gkSensorSizeX;
+  ySize                    = 12.4;
+  TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor04", shape_sensor04, silicon);
+  nSensors++;
+
+
+  // below are extra small sensors, those are not available in the CAD model
+
+  // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm)
+  xSize                    = 4.0;
+  ySize                    = 2.5;
+  TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor05", shape_sensor05, silicon);
+  nSensors++;
+
+
+  // ---  Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm)
+  xSize                    = 3.1;
+  ySize                    = 4.2;
+  TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor06", shape_sensor06, silicon);
+  nSensors++;
+
+
+  // ---  Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm)
+  xSize                    = 1.5;
+  ySize                    = 4.2;
+  TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", xSize / 2., ySize / 2., zSize / 2.);
+  new TGeoVolume("Sensor07", shape_sensor07, silicon);
+  nSensors++;
+
+
+  return nSensors;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Create sectors
+ **
+ ** A sector is either a single sensor or several chained sensors.
+ ** It is implemented as TGeoVolumeAssembly.
+ ** Currently available:
+ ** - single sensors of type 1 - 4
+ ** - two chained sensors of type 4
+ ** - three chained sensors of type 4
+ **/
+Int_t CreateSectors()
+{
+
+  Int_t nSectors = 0;
+
+  TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01");
+  TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02");
+  TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03");
+  TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04");
+  TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05");
+  TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06");
+  TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07");
+  //  TGeoBBox*   box4     = (TGeoBBox*) sensor04->GetShape();
+
+  // --- Sector type 1: single sensor of type 1
+  TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01");
+  sector01->AddNode(sensor01, 1);
+  sector01->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 2: single sensor of type 2
+  TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02");
+  sector02->AddNode(sensor02, 1);
+  sector02->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 3: single sensor of type 3
+  TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03");
+  sector03->AddNode(sensor03, 1);
+  sector03->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 4: single sensor of type 4
+  TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04");
+  sector04->AddNode(sensor04, 1);
+  sector04->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 5: single sensor of type 5
+  TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05");
+  sector05->AddNode(sensor05, 1);
+  sector05->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 6: single sensor of type 6
+  TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06");
+  sector06->AddNode(sensor06, 1);
+  sector06->GetShape()->ComputeBBox();
+  nSectors++;
+
+  // --- Sector type 7: single sensor of type 7
+  TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07");
+  sector07->AddNode(sensor07, 1);
+  sector07->GetShape()->ComputeBBox();
+  nSectors++;
+
+  //  // --- Sector type 5: two sensors of type 4
+  //  TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05");
+  //  Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY();
+  //  TGeoTranslation* transD5 =
+  //    new TGeoTranslation("td", 0., -1. * shift5, 0.);
+  //  TGeoTranslation* transU5 =
+  //    new TGeoTranslation("tu", 0., shift5, 0.);
+  //  sector05->AddNode(sensor04, 1, transD5);
+  //  sector05->AddNode(sensor04, 2, transU5);
+  //  sector05->GetShape()->ComputeBBox();
+  //  nSectors++;
+
+  return nSectors;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Create ladders
+ **
+ ** Ladders are the building blocks of the stations. They contain 
+ ** several modules placed one after the other along the z axis
+ ** such that the sectors are arranged vertically (with overlap).
+ ** 
+ ** A ladder is constructed out of two half ladders, the second of which
+ ** is rotated in the x-y plane by 180 degrees and displaced
+ ** in z direction.
+ **/
+Int_t CreateLadders()
+{
+
+  Int_t nLadders = 0;
+
+  // --- Some variables
+  Int_t nSectors = 0;
+  Int_t sectorTypes[10];
+  TGeoBBox* shape = NULL;
+  TString s0name;
+  TString hlname;
+  char align;
+  TGeoVolume* s0vol       = NULL;
+  TGeoVolume* halfLadderU = NULL;
+  TGeoVolume* halfLadderD = NULL;
+
+  // --- Ladders 01-23
+  // --- Ladders 01-27
+  Int_t allSectorTypes[38][6] = {
+    {1, 2, 3, 3, 0, -1},  // ladder 01 - 5 - last column defines alignment of small sensors
+    {1, 2, 3, 3, 0, 0},   // ladder 02 - 5 - last column defines alignment of small sensors
+    {2, 2, 3, 4, 0, -1},  // ladder 03 - 6 - last column defines alignment of small sensors
+    {2, 2, 3, 4, 0, 0},   // ladder 04 - 6 - last column defines alignment of small sensors
+    {2, 3, 4, 4, 0, -1},  // ladder 05 - 7 - last column defines alignment of small sensors
+    {2, 3, 4, 4, 0, 0},   // ladder 06 - 7 - last column defines alignment of small sensors
+    {2, 2, 3, 4, 4, 0},   // ladder 07 -     last column defines alignment of small sensors
+    {3, 4, 4, 4, 0, 0},   // ladder 08 -     last column defines alignment of small sensors
+    {1, 1, 2, 3, 3, 0},   // ladder 09 -     last column defines alignment of small sensors
+    {1, 1, 2, 2, 3, 0},   // ladder 10 -     last column defines alignment of small sensors
+    {2, 2, 0, 0, 0, 0},   // ladder 11 -     last column defines alignment of small sensors
+    {2, 2, 2, 3, 4, 0},   // ladder 12 -     last column defines alignment of small sensors
+    {2, 2, 3, 4, 0, 0},   // ladder 13 -     last column defines alignment of small sensors
+    {2, 3, 4, 0, 0, 0},   // ladder 14 -     last column defines alignment of small sensors
+    {3, 3, 0, 0, 0, 0},   // ladder 15 -     last column defines alignment of small sensors
+    {2, 2, 3, 4, 4, 0},   // ladder 16 -     last column defines alignment of small sensors
+    {2, 3, 4, 4, 0, 0},   // ladder 17 -     last column defines alignment of small sensors
+    {3, 4, 4, 0, 0, 0},   // ladder 18 -     last column defines alignment of small sensors
+    {4, 4, 0, 0, 0, 0},   // ladder 19 -     last column defines alignment of small sensors
+    {1, 2, 4, 4, 4, 0},   // ladder 20 -     last column defines alignment of small sensors
+    {4, 0, 0, 0, 0, 0},   // ladder 21 -     last column defines alignment of small sensors
+    {2, 3, 4, 4, 4, 0},   // ladder 22 -     last column defines alignment of small sensors
+    {2, 3, 3, 4, 4, 0},   // ladder 23 -     last column defines alignment of small sensors
+    {2, 3, 4, 4, 0, 0},   // ladder 24 - copy of 17 with different total length
+    {3, 4, 4, 0, 0, 0},   // ladder 25 - copy of 18 with different total length
+    {4, 4, 0, 0, 0, 0},   // ladder 26 - copy of 19 with different total length
+    {4, 4, 0, 0, 0, 0},   // ladder 27 - copy of 19 with different total length
+
+    {1, 1, 2, 3, 3, 0},  // ladder 28 - copy of 09 with different total length
+    {1, 1, 2, 2, 3, 0},  // ladder 29 - copy of 10 with different total length
+    {2, 2, 0, 0, 0, 0},  // ladder 30 - copy of 11 with different total length
+
+    {2, 2, 2, 3, 4, 0},  // ladder 31 - copy of 12 with different total length
+    {2, 2, 3, 4, 0, 0},  // ladder 32 - copy of 13 with different total length
+    {2, 3, 4, 0, 0, 0},  // ladder 33 - copy of 14 with different total length
+    {3, 3, 0, 0, 0, 0},  // ladder 34 - copy of 15 with different total length
+
+    {2, 2, 3, 4, 4, 0},  // ladder 35 - copy of 16 with different total length
+    {2, 3, 4, 4, 0, 0},  // ladder 36 - copy of 17 with different total length
+    {3, 4, 4, 0, 0, 0},  // ladder 37 - copy of 18 with different total length
+    {4, 4, 0, 0, 0, 0},  // ladder 38 - copy of 19 with different total length
+
+  };  // 8 full - 19 partial ladders
+
+  //  Issue #405
+  //  Counting from the most upstream ladder, the gaps between sensors are as follows:
+  //    01 (most upstream): 41.3mm
+  //    02: 41.3mm
+  //    03: 42.0mm
+  //    04: 48.6mm
+  //    05: 60.8mm
+  //    06: 67.0mm
+  //    07: 79.2mm
+  //    08 (most downstream): 88.0mm
+
+  Double_t pitchZ        = 0;
+  Double_t gapXYZ[38][3] = {
+    {0., 5.43, 0.},               // ladder 01
+    {0., 6.00, 0.},               // ladder 02
+    {0., 6.70, 0.},               // ladder 03
+    {0., 7.35, 0.},               // ladder 04
+    {0., 8.02, 0.},               // ladder 05
+    {0., 8.70, 0.},               // ladder 06
+    {0., 9.22, 0.},               // ladder 07
+    {0., 10.00, 0.},              // ladder 08
+    {0., -gkSectorOverlapY, 0.},  // ladder 09
+    {0., -gkSectorOverlapY, 0.},  // ladder 10
+    {0., -gkSectorOverlapY, 0.},  // ladder 11
+    {0., -gkSectorOverlapY, 0.},  // ladder 12
+    {0., -gkSectorOverlapY, 0.},  // ladder 13
+    {0., -gkSectorOverlapY, 0.},  // ladder 14
+    {0., -gkSectorOverlapY, 0.},  // ladder 15
+    {0., -gkSectorOverlapY, 0.},  // ladder 16
+    {0., -gkSectorOverlapY, 0.},  // ladder 17
+    {0., -gkSectorOverlapY, 0.},  // ladder 18
+    {0., -gkSectorOverlapY, 0.},  // ladder 19
+    {0., -gkSectorOverlapY, 0.},  // ladder 20
+    {0., -gkSectorOverlapY, 0.},  // ladder 21
+    {0., -gkSectorOverlapY, 0.},  // ladder 22
+    {0., -gkSectorOverlapY, 0.},  // ladder 23
+
+    {0., -gkSectorOverlapY, 0.},  // ladder 24 - copy of 17 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 25 - copy of 18 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 26 - copy of 19 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 27 - copy of 19 with different total length
+
+    {0., -gkSectorOverlapY, 0.},  // ladder 28 - copy of 09 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 29 - copy of 10 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 30 - copy of 11 with different total length
+
+    {0., -gkSectorOverlapY, 0.},  // ladder 31 - copy of 12 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 32 - copy of 13 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 33 - copy of 14 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 34 - copy of 15 with different total length
+
+    {0., -gkSectorOverlapY, 0.},  // ladder 35 - copy of 16 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 36 - copy of 17 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 37 - copy of 18 with different total length
+    {0., -gkSectorOverlapY, 0.},  // ladder 38 - copy of 19 with different total length
+
+  };
+
+  Double_t ladderLength[38] = {
+    48.0,  // ladder 01
+    48.0,  // ladder 02
+    66.8,  // ladder 03
+    66.8,  // ladder 04
+    81.8,  // ladder 05
+    81.8,  // ladder 06
+    89.2,  // ladder 07
+    96.7,  // ladder 08
+    48.0,  // ladder 09
+    48.0,  // ladder 10
+    48.0,  // ladder 11
+    66.8,  // ladder 12
+    66.8,  // ladder 13
+    66.8,  // ladder 14
+    66.8,  // ladder 15
+    81.8,  // ladder 16
+    81.8,  // ladder 17
+    81.8,  // ladder 18
+    81.8,  // ladder 19
+    89.2,  // ladder 20
+    89.2,  // ladder 21
+    96.7,  // ladder 22
+    96.7,  // ladder 23
+
+    96.7,  // ladder 24 - copy of 17 with different total length
+    89.2,  // ladder 25 - copy of 18 with different total length
+    96.7,  // ladder 26 - copy of 19 with different total length
+    89.2,  // ladder 27 - copy of 19 with different total length
+
+    66.8,  // ladder 28 - copy of 09 with different total length
+    66.8,  // ladder 29 - copy of 10 with different total length
+    66.8,  // ladder 30 - copy of 11 with different total length
+
+    81.8,  // ladder 31 - copy of 12 with different total length
+    81.8,  // ladder 32 - copy of 13 with different total length
+    81.8,  // ladder 33 - copy of 14 with different total length
+    81.8,  // ladder 34 - copy of 15 with different total length
+
+    89.2,  // ladder 35 - copy of 16 with different total length
+    89.2,  // ladder 36 - copy of 17 with different total length
+    89.2,  // ladder 37 - copy of 18 with different total length
+    89.2,  // ladder 38 - copy of 19 with different total length
+
+  };
+  // ========================================================================
+
+  // calculate Z shift for ladders with and without gaps in the center
+  s0name = Form("Sector%02d", allSectorTypes[0][0]);
+  s0vol  = gGeoMan->GetVolume(s0name);
+  shape  = (TGeoBBox*) s0vol->GetShape();
+
+  // ========================================================================
+
+  for (Int_t iLadder = 0; iLadder < 38; iLadder++) {
+    cout << endl;
+    nSectors = 0;
+    for (Int_t i = 0; i < 5; i++)
+      if (allSectorTypes[iLadder][i] != 0) {
+        sectorTypes[nSectors] = allSectorTypes[iLadder][i];  // copy sectors for this ladder
+        cout << "DE iLadder " << iLadder + 1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i]
+             << ";" << endl;
+        nSectors++;  // count how many sectors are in this ladder
+      }
+
+    // always set displacement in z between upper and lower half ladder
+    gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ;
+
+    // define additional offset to carbon ladder for half ladders with less than 5 sensors
+    pitchZ = 2. * shape->GetDZ() + gkSectorGapZ;
+
+    if (allSectorTypes[iLadder][5] == 0) align = 'l';
+    else
+      align = 'r';
+    hlname = Form("HalfLadder%02dt", iLadder + 1);
+    // build upper half ladder
+    halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, ladderLength[iLadder] / 2.,
+                                      gapXYZ[iLadder][1] / 2.);  // mirrored
+
+    if (allSectorTypes[iLadder][5] == 0) align = 'r';
+    else
+      align = 'l';
+    hlname = Form("HalfLadder%02db", iLadder + 1);
+    // build lower half ladder
+    halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, ladderLength[iLadder] / 2.,
+                                      gapXYZ[iLadder][1] / 2.);  // mirrored
+
+    // at this point half ladders are constructed
+
+    // build all 4 possible ladders types for this sensor arrangement
+    ConstructLadder(iLadder + 1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ,
+                    nSectors);  // v19a
+    ConstructLadder(100 + iLadder + 1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ,
+                    nSectors);  // v19b
+
+    ConstructLadder(1000 + iLadder + 1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ,
+                    nSectors);  // v19k
+    ConstructLadder(1100 + iLadder + 1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ,
+                    nSectors);  // v19k
+
+    nLadders++;
+  }
+
+  return nLadders;
+}
+/** ======================================================================= **/
+
+
+// ****************************************************************************
+// *****                                                                  *****
+// *****    Generic functions  for the construction of STS elements       *****
+// *****                                                                  *****
+// *****  module:     volume (made of a sector and a cable)               *****
+// *****  haf ladder: assembly (made of modules)                          *****
+// *****  ladder:     assembly (made of two half ladders)                 *****
+// *****  station:    volume (made of ladders)                            *****
+// *****                                                                  *****
+// ****************************************************************************
+
+
+/** ===========================================================================
+ ** Construct a module
+ **
+ ** A module is a sector plus the readout cable extending from the
+ ** top of the sector. The cable is made from passive silicon.
+ ** The cable has the same x size as the sector.
+ ** Its thickness is given by the global variable gkCableThickness.
+ ** The cable length is a parameter.
+ ** The sensor(s) of the sector is/are placed directly in the module;
+ ** the sector is just auxiliary for the proper placement.
+ **
+ ** Arguments: 
+ **            name             volume name
+ **            sector           pointer to sector volume
+ **            cableLength      length of cable
+ **/
+TGeoVolume* ConstructModule(const char* name, TGeoVolume* sector, Double_t cableLength)
+{
+
+  // --- Check sector volume
+  if (!sector) Fatal("CreateModule", "Sector volume not found!");
+
+  // --- Get size of sector
+  TGeoBBox* box    = (TGeoBBox*) sector->GetShape();
+  Double_t sectorX = 2. * box->GetDX();
+  Double_t sectorY = 2. * box->GetDY();
+  Double_t sectorZ = 2. * box->GetDZ();
+
+  // --- Get size of cable
+  Double_t cableX = sectorX;
+  Double_t cableY = cableLength;
+  Double_t cableZ = gkCableThickness;
+
+  // --- Create module volume
+  Double_t moduleX = TMath::Max(sectorX, cableX);
+  Double_t moduleY = sectorY + cableLength;
+
+  Double_t moduleZ = TMath::Max(sectorZ, cableZ);
+
+  TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, moduleX / 2., moduleY / 2., moduleZ / 2.);
+
+  // --- Position of sector in module
+  // --- Sector is centred in x and z and aligned to the bottom
+  Double_t sectorXpos = 0.;
+  Double_t sectorYpos = 0.5 * (sectorY - moduleY);
+  Double_t sectorZpos = 0.;
+
+
+  // --- Get sensor(s) from sector
+  Int_t nSensors = sector->GetNdaughters();
+  for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) {
+    TGeoNode* sensor = sector->GetNode(iSensor);
+
+    // --- Calculate position of sensor in module
+    const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation();
+    Double_t sensorXpos        = 0.;
+    Double_t sensorYpos        = sectorYpos + xSensTrans[1];
+    Double_t sensorZpos        = 0.;
+    TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", sensorXpos, sensorYpos, sensorZpos);
+
+    // --- Add sensor volume to module
+    TGeoVolume* sensVol = sensor->GetVolume();
+    module->AddNode(sensor->GetVolume(), iSensor + 1, sensTrans);
+    module->GetShape()->ComputeBBox();
+  }
+
+
+  // --- Create cable volume, if necessary, and place it in module
+  // --- Cable is centred in x and z and aligned to the top
+  if (gkConstructCables && cableLength > 0.0001) {
+    TString cableName       = TString(name) + "_cable";
+    TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable");
+    if (!cableMedium) Fatal("CreateModule", "Medium STScable not found!");
+    TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), cableMedium, cableX / 2., cableY / 2., cableZ / 2.);
+    // add color to cables
+    cable->SetLineColor(kOrange);
+    cable->SetTransparency(60);
+    Double_t cableXpos          = 0.;
+    Double_t cableYpos          = sectorY + 0.5 * cableY - 0.5 * moduleY;
+    Double_t cableZpos          = 0.;
+    TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", cableXpos, cableYpos, cableZpos);
+    module->AddNode(cable, 1, cableTrans);
+    module->GetShape()->ComputeBBox();
+  }
+
+  return module;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Construct a half ladder
+ **
+ ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting
+ ** of several modules arranged on top of each other. The modules
+ ** have a given overlap in y and a displacement in z to allow for the
+ ** overlap.
+ **
+ ** The typ of sectors / modules to be placed must be specified:
+ **    1 = sensor01
+ **    2 = sensor02
+ **    3 = sensor03
+ **    4 = sensor04
+ **    5 = 2 x sensor04 (chained)
+ **    6 = 3 x sensor04 (chained)
+ ** The cable is added automatically from the top of each sensor to
+ ** the top of the half ladder.
+ ** The alignment can be left (l) or right (r), which matters in the
+ ** case of different x sizes of sensors (e.g. SensorType01).
+ **
+ ** Arguments: 
+ **            name             volume name
+ **            nSectors         number of sectors
+ **            sectorTypes      array with sector types
+ **            align            horizontal alignment of sectors
+ *             ladderLength     full length of the ladder towards FEE
+ *             offsetY          gap in the beam-pipe region
+ **/
+TGeoVolume* ConstructHalfLadder(const TString& name, Int_t nSectors, Int_t* sectorTypes, char align,
+                                Double_t ladderLength, Double_t offsetY)
+{
+
+  // --- Create half ladder volume assembly
+  TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name);
+
+  // --- Determine size of ladder
+  Double_t ladderX = 0.;
+  Double_t ladderY = 0.;
+  Double_t ladderZ = 0.;
+  for (Int_t iSector = 0; iSector < nSectors; iSector++) {
+    TString sectorName = Form("Sector%02d", sectorTypes[iSector]);
+    TGeoVolume* sector = gGeoMan->GetVolume(sectorName);
+    if (!sector) Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data()));
+    TGeoBBox* box = (TGeoBBox*) sector->GetShape();
+    // --- Ladder x size equals largest sector x size
+    ladderX = TMath::Max(ladderX, 2. * box->GetDX());
+    // --- Ladder y size is sum of sector ysizes
+    ladderY += 2. * box->GetDY();
+    // --- Ladder z size is sum of sector z sizes
+    ladderZ += 2. * box->GetDZ();
+  }
+  // --- Subtract overlaps in y
+  ladderY -= Double_t(nSectors - 1) * gkSectorOverlapY;
+  // --- Add gaps in z direction
+  ladderZ += Double_t(nSectors - 1) * gkSectorGapZ;
+
+  ladderY = TMath::Max(ladderLength - offsetY, ladderY);
+
+  // --- Create and place modules
+  Double_t yPosSect = -0.5 * ladderY;
+  Double_t zPosMod  = -0.5 * ladderZ;
+  for (Int_t iSector = 0; iSector < nSectors; iSector++) {
+    TString sectorName = Form("Sector%02d", sectorTypes[iSector]);
+    TGeoVolume* sector = gGeoMan->GetVolume(sectorName);
+    TGeoBBox* box      = (TGeoBBox*) sector->GetShape();
+    Double_t sectorX   = 2. * box->GetDX();
+    Double_t sectorY   = 2. * box->GetDY();
+    Double_t sectorZ   = 2. * box->GetDZ();
+    yPosSect += 0.5 * sectorY;  // Position of sector in ladder
+    Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY;
+    TString moduleName   = name + "_" + Form("Module%02d", sectorTypes[iSector]);
+    TGeoVolume* module   = ConstructModule(moduleName.Data(), sector, cableLength);
+
+    TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape();
+    Double_t moduleX   = 2. * shapeMod->GetDX();
+    Double_t moduleY   = 2. * shapeMod->GetDY();
+    Double_t moduleZ   = 2. * shapeMod->GetDZ();
+    Double_t xPosMod   = 0.;
+    if (align == 'l') xPosMod = 0.5 * (moduleX - ladderX);  // left aligned
+    else if (align == 'r')
+      xPosMod = 0.5 * (ladderX - moduleX);  // right aligned
+    else
+      xPosMod = 0.;                                // centred in x
+    Double_t yPosMod = 0.5 * (ladderY - moduleY);  // top aligned
+    zPosMod += 0.5 * moduleZ;
+    TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, yPosMod, zPosMod);
+    halfLadder->AddNode(module, iSector + 1, trans);
+    halfLadder->GetShape()->ComputeBBox();
+    yPosSect += 0.5 * sectorY - gkSectorOverlapY;
+    zPosMod += 0.5 * moduleZ + gkSectorGapZ;
+  }
+
+  CheckVolume(halfLadder);
+  cout << endl;
+
+  return halfLadder;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Add a carbon support to a ladder
+ ** 
+ ** Arguments: 
+ **            LadderIndex      ladder number
+ **            ladder           pointer to ladder
+ **            xu               size of halfladder
+ **            ladderY          height of ladder along y
+ **            ladderZ          thickness of ladder along z
+ **/
+void AddCarbonLadder(Int_t LadderIndex, TGeoVolume* ladder, Double_t xu, Double_t ladderY, Double_t ladderZ)
+{
+
+  // --- Some variables
+  TString name = Form("LadderType%04d", LadderIndex);  // v19k
+  Int_t i;
+  Double_t j;
+
+  Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep);
+
+  //  cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl;
+
+  Double_t ladderDZ = (xu / 2. + sqrt(2.) * gkFrameThickness / 2. + gkSectorGapZFrame * 2) / 2.;
+  cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl;
+
+  TGeoBBox* fullFrameShp      = new TGeoBBox(name + "_CarbonElement_shp", xu / 2., gkFrameStep / 2., ladderDZ);
+  TGeoVolume* fullFrameBoxVol = new TGeoVolume(name + "_CarbonElement", fullFrameShp, gStsMedium);
+
+  ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu / 2.);
+  TGeoRotation* fullFrameRot = new TGeoRotation;
+  fullFrameRot->RotateY(180);
+
+  Int_t inum = YnumOfFrameBoxes - 3.5;  // - 3.5 was done to short frame box to remove overlaps
+  for (i = 1; i <= inum; i++) {
+    j = -(inum - 1) / 2. + (i - 1);
+    // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2)
+    // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1   (= 3)
+    //        cout << "DE: i " << i << " j " << j << endl;
+
+    if (LadderIndex % 100 <= 3)  // central ladders in stations 1 to 3
+    {
+      if ((j >= -1) && (j <= 1))  // keep the inner 2 (even) or 3 (odd) elements free for the cone
+        continue;
+    }
+    else if (LadderIndex % 100 <= 8)  // central ladders in stations 4 to 8
+    {
+      if ((j >= -2) && (j <= 2))  // keep the inner 4 elements free for the cone
+        continue;
+    }
+
+    cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ / 2. - ladderDZ << " cm " << endl;
+    ladder->AddNode(fullFrameBoxVol, i,
+                    new TGeoCombiTrans(name + "_CarbonElement_posrot", 0., j * gkFrameStep, -(ladderZ / 2. + ladderDZ),
+                                       fullFrameRot));
+  }
+
+  ladder->GetShape()->ComputeBBox();
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Construct a ladder out of two half ladders with vertical gap
+ ** 
+ ** The second half ladder will be rotated by 180 degrees 
+ ** in the x-y plane. The two half ladders will be put on top of each
+ ** other with a vertical gap.
+ **
+ ** Arguments: 
+ **            name             volume name
+ **            halfLadderU      pointer to upper half ladder
+ **            halfLadderD      pointer to lower half ladder
+ **            gapY             vertical gap
+ **            shiftZ           relative displacement along the z axis
+ **/
+
+TGeoVolume* ConstructLadder(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t gapY,
+                            Double_t shiftZ, Double_t pitchZ, Int_t nSectors)
+{
+
+  // --- Some variables
+  TGeoBBox* shape = NULL;
+
+  // define additional offset to carbon ladder for half ladders with less than 5 sensors
+  Double_t offsetZ = (5. - nSectors) * pitchZ;
+
+  // --- Dimensions of half ladders
+  shape       = (TGeoBBox*) halfLadderU->GetShape();  // up
+  Double_t xu = 2. * shape->GetDX();
+  Double_t yu = 2. * shape->GetDY();
+  Double_t zu = 2. * shape->GetDZ();
+
+  shape       = (TGeoBBox*) halfLadderD->GetShape();  // down
+  Double_t xd = 2. * shape->GetDX();
+  Double_t yd = 2. * shape->GetDY();
+  Double_t zd = 2. * shape->GetDZ();
+
+  // --- Create ladder volume assembly
+  TString name               = Form("LadderType%04d", LadderIndex);  // v19k
+  TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name);
+  Double_t ladderX           = TMath::Max(xu, xd);
+  Double_t ladderY           = yu + yd + gapY;
+  Double_t ladderZ           = TMath::Max(zu,
+                                zd + shiftZ + offsetZ);  // there are 6 slots - 5 x 1.5 mm + 0.3 mm = 7.8 mm
+  //  Double_t ladderZ = TMath::Max(zu, zd + shiftZ);
+
+  cout << "DERR iladder " << LadderIndex << " nSec " << nSectors << " zu " << zu << " zd " << zd << " zd+shi "
+       << zd + shiftZ << " ladderZ " << ladderZ << " offsetZ " << offsetZ << endl;
+
+  // --- Place half ladders
+  Double_t xPosU = 0.0;                   // centred in x
+  Double_t yPosU = 0.5 * (ladderY - yu);  // top aligned
+  Double_t zPosU = 0;
+  zPosU          = 0.5 * (ladderZ - zu);                             // front aligned
+  if (LadderIndex >= 1000) zPosU = -0.5 * (ladderZ - zu) + offsetZ;  // back aligned with possible offset
+  //zPosU = -zPosU;
+
+  TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU);
+  ladder->AddNode(halfLadderU, 1, tu);
+
+  Double_t xPosD = 0.0;                    // centred in x
+  Double_t yPosD = 0.5 * -(ladderY - yd);  // bottom aligned
+  Double_t zPosD = 0;
+  zPosD          = 0.5 * -(ladderZ - zd) + offsetZ;         // back aligned with possible offset
+  if (LadderIndex >= 1000) zPosD = -0.5 * -(ladderZ - zd);  // front aligned
+  //zPosD = -zPosD;
+
+  TGeoRotation* rd = new TGeoRotation();
+  rd->RotateZ(180.);
+  TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd);
+  ladder->AddNode(halfLadderD, 2, cd);
+
+  ladder->GetShape()->ComputeBBox();
+
+  shape = (TGeoBBox*) ladder->GetShape();
+  cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() << " ladderY " << 2. * shape->GetDY()
+       << " ladderZ " << 2. * shape->GetDZ() << endl;
+
+  cout << "DDDD ladder" << LadderIndex << endl;
+  cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ
+       << endl;
+
+  // ----------------   Create and place frame boxes   ------------------------
+
+  if (gkConstructFrames) AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ);
+
+  // --------------------------------------------------------------------------
+
+  shape = (TGeoBBox*) ladder->GetShape();
+  cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() << " ladderY " << 2. * shape->GetDY()
+       << " ladderZ " << 2. * shape->GetDZ() << endl;
+
+  return ladder;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Construct a unit
+ **
+ ** The unit volume is the minimal box comprising all ladders
+ ** minus a tube accomodating the beam pipe.
+ **
+ ** The ladders are arranged horizontally from left to right with
+ ** a given overlap in x.
+ ** Every second ladder is slightly displaced upstream from the centre
+ ** z plane and facing downstream, the others are slightly displaced
+ ** downstream and facing upstream (rotated around the y axis).
+ **
+ ** Arguments: 
+ **            name             volume name
+ **            nLadders         number of ladders
+ **            ladderTypes      array of ladder types
+ **/
+
+TGeoVolume* ConstructUnit(Int_t iSide, Int_t iUnit, Int_t nLadders, Int_t* ladderTypes, Int_t iStation)
+{
+
+  Bool_t isFirstPartOfHalfUnit = kFALSE;
+
+  //  TString name = Form("Unit%02d", iUnit);    // 0,1,2,3,4,5,6,7 - Unit00 missing in output
+  //  TString name = Form("Unit%02d", iUnit+1);  // 1,2,3,4,5,6,7,8
+
+  TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]);
+  if (!unit)  // if it does not yet exist, create a new one
+  {
+    unit                  = new TGeoVolumeAssembly(unitName[iUnit]);
+    isFirstPartOfHalfUnit = kTRUE;
+  }
+
+  // --- Some local variables
+  TGeoBBox* ladderShape = NULL;
+  TGeoVolume* ladder    = NULL;
+  TString ladderName;
+  Double_t subtractedVal;
+
+  // --- Determine size of unit from ladders
+  Double_t statX = 0.;
+  //  Double_t statY     = 0.;
+
+  for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
+    Int_t ladderType = ladderTypes[iLadder];  // v19k
+
+    //    if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl;
+
+    if (ladderType > 0) {
+      ladderName = Form("LadderType%04d", ladderType);  // v19k
+
+      ladder = gGeoManager->GetVolume(ladderName);
+      if (!ladder) Fatal("ConstructUnit", Form("Volume %s not found", ladderName.Data()));
+      ladderShape = (TGeoBBox*) ladder->GetShape();
+      statX += 2. * ladderShape->GetDX();
+    }
+    else
+      statX += gkSensorSizeX;  // empty ladder in unit
+  }
+  statX -= Double_t(nLadders - 1) * gkLadderOverlapX;
+
+  //  if (iSide == 0) cout << "DWER -" << endl;
+
+  // --- Place ladders in unit
+  cout << "xPos0: " << statX << endl;
+  Double_t xPos = -0.5 * statX;
+  cout << "xPos1: " << xPos << endl;
+  Double_t yPos = 0.;
+  Double_t zPos = 0.;
+
+  Double_t maxdz = 0.;
+  for (Int_t iLadder = 0; iLadder < nLadders; iLadder++)  // find maximum dz in this unit
+  {
+    Int_t ladderType = ladderTypes[iLadder];  // v19k
+
+    if (ladderType > 0) {
+      ladderName = Form("LadderType%04d", ladderType);  // v19k
+
+      ladder      = gGeoManager->GetVolume(ladderName);
+      ladderShape = (TGeoBBox*) ladder->GetShape();
+      if (maxdz < ladderShape->GetDZ()) maxdz = ladderShape->GetDZ();
+    }
+  }
+
+  for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
+    Int_t ladderType = ladderTypes[iLadder];  // v19k
+
+    if (ladderType > 0) {
+      ladderName = Form("LadderType%04d", ladderType);  // v19k
+
+      ladder      = gGeoManager->GetVolume(ladderName);
+      ladderShape = (TGeoBBox*) ladder->GetShape();
+      xPos += ladderShape->GetDX();
+      cout << "xPos2: " << xPos << endl;
+      yPos              = 0.;  // vertically centred
+      TGeoRotation* rot = new TGeoRotation();
+
+      if (gkConstructFrames)
+        subtractedVal = ladderShape->GetDX() + sqrt(2.) * gkFrameThickness / 2. + gkSectorGapZFrame * 2;
+      else
+        subtractedVal = 0.;
+
+      zPos = 0.5 * gkLadderGapZ + (2 * maxdz - ladderShape->GetDZ() - subtractedVal / 2.);  // z-aligned ladders
+
+      // v19k
+      cout << "DE ladder" << ladderTypes[iLadder] << "  dx: " << ladderShape->GetDX()
+           << "  dy: " << ladderShape->GetDY() << "  dz: " << ladderShape->GetDZ() << "  max dz: " << maxdz << endl;
+
+      // v19k
+      cout << "DE ladder" << ladderTypes[iLadder] << "  fra: " << gkFrameThickness / 2. << "  sub: " << subtractedVal
+           << "  zpo: " << zPos << endl
+           << endl;
+
+      // v19k
+      if (ladderTypes[iLadder] / 1000 == 1)  // flip some of the ladders to reproduce the CAD layout
+        rot->RotateY(180.);
+      else
+        zPos = -zPos;
+
+      if (!isFirstPartOfHalfUnit) zPos += 10.5;  // v19d
+      //      zPos += 10.0;   // initial version
+
+      TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot);
+      // start
+      //      cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl;
+
+      if (iSide == 0) {
+        if (iLadder < nLadders / 2)  // right side - only half unit -x
+        {
+          unit->AddNode(ladder, iStation * 100 + iLadder + 1, trans);
+          // calculate Station number to encode the ladder copy number
+          cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl;
+        }
+      }
+      else {
+        if (iLadder >= nLadders / 2)  // left  side - only half unit +x
+        {
+          unit->AddNode(ladder, iStation * 100 + iLadder + 1, trans);
+          // calculate Station number to encode the ladder copy number
+          cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl;
+        }
+      }
+      unit->GetShape()->ComputeBBox();
+      // stop
+      xPos += ladderShape->GetDX() - gkLadderOverlapX;
+      cout << "xPos3: " << xPos << endl;
+    }
+    else
+      xPos += gkSensorSizeX - gkLadderOverlapX;
+  }
+
+  return unit;
+}
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Import and add the passive materials to the STS volume
+ **/
+void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile)
+{
+  TString passiveName     = TString("sts_passive_") + geoTag;
+  TString basePath        = gSystem->Getenv("VMCWORKDIR");
+  TString relPath         = "/geometry/sts/passive/" + passiveName + ".gdml";
+  TString passiveFileName = basePath + relPath;
+  infoFile << std::endl << std::endl;
+  infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl;
+
+  TGDMLParse parser;
+  TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName);
+  PostProcessGdml(gdmlVolume);
+  gdmlVolume->SetName(passiveName);
+
+  TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.);
+  infoFile << "Passive assembly is translated for Z=2.68 cm downstream with "
+              "respect to parent volume"
+           << std::endl
+           << std::endl;
+
+  gdmlVolume->GetShape()->ComputeBBox();
+  CheckVolume(gdmlVolume, infoFile);
+
+  infoFile << std::endl;
+  for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) {
+    CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE);
+  }
+
+  stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, "");
+}
+
+/** ===========================================================================
+ ** Assign visual properties to the imported gdml volumes
+ **/
+void PostProcessGdml(TGeoVolume* gdmlVolume)
+{
+  const UInt_t kPOBColor        = kRed - 6;
+  const UInt_t kPOBTransparency = 0;  // 5;
+
+  const UInt_t kFEBColor        = kOrange - 6;
+  const UInt_t kFEBTransparency = 0;  // 5;
+
+  const UInt_t kUnitColor        = kCyan - 10;
+  const UInt_t kUnitTransparency = 0;  // 5;
+
+  const UInt_t kCfColor        = kCyan - 1;
+  const UInt_t kCfTransparency = 0;  // 10;
+
+  // name <Color, Transparency>
+  std::map<std::string, std::tuple<UInt_t, UInt_t>> props {
+    {"passive_POB", std::tuple<UInt_t, UInt_t> {kPOBColor, kPOBTransparency}},
+    {"passive_FEB", std::tuple<UInt_t, UInt_t> {kFEBColor, kFEBTransparency}},
+    {"passive_unit", std::tuple<UInt_t, UInt_t> {kUnitColor, kUnitTransparency}},
+    {"passive_Box_Wall", std::tuple<UInt_t, UInt_t> {kCfColor, kCfTransparency}},
+    {"passive_Box_Wall_Front_CF2", std::tuple<UInt_t, UInt_t> {kCfColor + 3, kCfTransparency}},
+    {"passive_Box_Wall_Back_CF2", std::tuple<UInt_t, UInt_t> {kCfColor + 3, kCfTransparency}},
+    {"passive_Box_Wall_Back_Light_Foam", std::tuple<UInt_t, UInt_t> {kCfColor - 8, kCfTransparency}},
+    {"passive_Box_Wall_Front_Light_Foam", std::tuple<UInt_t, UInt_t> {kCfColor - 8, kCfTransparency}},
+  };
+
+  // Match volume name and apply visual properties   passive_Box_Wall_Front_Light_Foam
+  const TObjArray* volumes = gGeoManager->GetListOfVolumes();
+  for (auto& entry : props) {
+    TIter next(volumes);
+    TGeoVolume* vol = nullptr;
+    while ((vol = (TGeoVolume*) next())) {
+      if (TString(vol->GetName()).Contains(entry.first.c_str())) {
+        vol->SetLineColor(std::get<0>(entry.second));
+        vol->SetTransparency(std::get<1>(entry.second));
+      }
+    }
+  }
+}
+
+/** ===========================================================================
+ ** Volume information for debugging
+ **/
+void CheckVolume(TGeoVolume* volume)
+{
+
+  TGeoBBox* shape = (TGeoBBox*) volume->GetShape();
+  cout << volume->GetName() << ": size " << fixed << setprecision(4) << setw(7) << 2. * shape->GetDX() << " x "
+       << setw(7) << 2. * shape->GetDY() << " x " << setw(7) << 2. * shape->GetDZ();
+  if (volume->IsAssembly()) cout << ", assembly";
+  else {
+    if (volume->GetMedium()) cout << ", medium " << volume->GetMedium()->GetName();
+    else
+      cout << ", "
+           << "\033[31m"
+           << " no medium"
+           << "\033[0m";
+  }
+  cout << endl;
+  if (volume->GetNdaughters()) {
+    cout << "Daughters: " << endl;
+    for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) {
+      TGeoNode* node  = volume->GetNode(iNode);
+      TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape();
+      cout << setw(15) << node->GetName() << ", size " << fixed << setprecision(3) << setw(6) << 2. * shape->GetDX()
+           << " x " << setw(6) << 2. * shape->GetDY() << " x " << setw(6) << 2. * shape->GetDZ() << ", position ( ";
+      TGeoMatrix* matrix  = node->GetMatrix();
+      const Double_t* pos = matrix->GetTranslation();
+      cout << setfill(' ');
+      cout << fixed << setw(8) << pos[0] << ", " << setw(8) << pos[1] << ", " << setw(8) << pos[2] << " )" << endl;
+    }
+  }
+}
+/** ======================================================================= **/
+
+/** ===========================================================================
+ ** Volume information for output to file
+ **/
+void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren)
+{
+  if (!file) return;
+
+  TGeoBBox* shape = (TGeoBBox*) volume->GetShape();
+  file << volume->GetName() << ": size " << fixed << setprecision(4) << setw(7) << 2. * shape->GetDX() << " x "
+       << setw(7) << 2. * shape->GetDY() << " x " << setw(7) << 2. * shape->GetDZ();
+  if (volume->IsAssembly()) file << ", assembly";
+  else {
+    if (volume->GetMedium()) file << ", medium " << volume->GetMedium()->GetName();
+    else
+      file << ", "
+           << "\033[31m"
+           << " no medium"
+           << "\033[0m";
+  }
+  file << endl;
+  if (volume->GetNdaughters() && listChildren) {
+    file << "Contains: ";
+    for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++)
+      file << volume->GetNode(iNode)->GetVolume()->GetName() << " ";
+    file << endl;
+  }
+}
+
+/** ======================================================================= **/
+
+
+/** ===========================================================================
+ ** Calculate beam pipe outer radius for a given z
+ **/
+Double_t BeamPipeRadius(Double_t z)
+{
+  if (z < gkPipeZ2) return gkPipeR1;
+  Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1);
+  return gkPipeR2 + slope * (z - gkPipeZ2);
+}
+/** ======================================================================= **/
+
+
+/** ======================================================================= **/
+TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x)
+{
+  // --- Material of the frames
+  TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon");
+
+  TGeoBBox* frameVertPillarShp;
+
+  Double_t t = gkFrameThickness / 2.;
+
+  // --- Main vertical pillars
+  //      TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t);  // square crossection, along y
+  //  TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial);
+  //  frameVertPillarVol->SetLineColor(kGreen);
+  //  frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.));
+  //  frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.));
+
+  if (gkCylindricalFrames)
+    //          TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.);  // circle crossection, along z
+    frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner / 2., gkCylinderDiaOuter / 2.,
+                                      gkFrameStep / 2.);  // circle crossection, along z
+  else
+    frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t,
+                                      gkFrameStep / 2.);  // square crossection, along z
+  TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial);
+  frameVertPillarVol->SetLineColor(kGreen);
+
+  TGeoRotation* xRot90 = new TGeoRotation;
+  xRot90->RotateX(90.);
+  frameBoxVol->AddNode(
+    frameVertPillarVol, 1,
+    new TGeoCombiTrans(name + "_vertpillar_pos_1", x - t, 0., -(x + sqrt(2.) * t - 2. * t) / 2., xRot90));
+  frameBoxVol->AddNode(
+    frameVertPillarVol, 2,
+    new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x - t), 0., -(x + sqrt(2.) * t - 2. * t) / 2., xRot90));
+
+  //  TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.);
+  TGeoRotation* vertRot = new TGeoRotation;
+  vertRot->RotateX(90.);
+  vertRot->RotateY(45.);
+  frameBoxVol->AddNode(frameVertPillarVol, 3,
+                       new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x - sqrt(2.) * t) / 2., vertRot));
+
+  // --- Small horizontal pillar
+  // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.);
+  // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial);
+  // frameHorPillarVol->SetLineColor(kCyan);
+  // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.));
+
+  if (gkConstructSmallFrames) {
+
+    // --- Small sloping pillars
+    TGeoPara* frameSlopePillarShp =
+      new TGeoPara(name + "_slopepillar_shape", (x - 2. * t) / TMath::Cos(31.4 / 180. * TMath::Pi()),
+                   gkThinFrameThickness / 2., gkThinFrameThickness / 2., 31.4, 0., 90.);
+    TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial);
+    frameSlopePillarVol->SetLineColor(kCyan);
+    TGeoRotation* slopeRot  = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4);
+    TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4);
+    TGeoCombiTrans* slopeTrRot =
+      new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x + sqrt(2.) * t - 2. * t) / 2., slopeRot);
+    TGeoCombiTrans* slopeTrRot2 =
+      new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x + sqrt(2.) * t - 2. * t) / 2., slopeRot2);
+
+    frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot);
+    frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2);
+
+
+    Double_t angl = 23.;
+    // --- Small sub pillar
+    TGeoPara* frameSubPillarShp =
+      new TGeoPara(name + "_subpillar_shape", (sqrt(2) * (x / 2. - t) - t / 2.) / TMath::Cos(angl / 180. * TMath::Pi()),
+                   gkThinFrameThickness / 2., gkThinFrameThickness / 2., angl, 0., 90.);
+    TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial);
+    frameSubPillarVol->SetLineColor(kMagenta);
+
+    Double_t posZ = t * (1. - 3. / (2. * sqrt(2.)));
+
+    // one side of X direction
+    TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90. + angl);
+    TGeoCombiTrans* subTrRot1 =
+      new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x / 2. + t - t / (2. * sqrt(2.))), 1., posZ, subRot1);
+
+    TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90. - 45., -90. + angl);
+    TGeoCombiTrans* subTrRot2 =
+      new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x / 2. + t - t / (2. * sqrt(2.))), -1., posZ, subRot2);
+
+    // other side of X direction
+    TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90. + 45., -90. + angl);
+    TGeoCombiTrans* subTrRot3 =
+      new TGeoCombiTrans(name + "_subpillar_posrot_3", -x / 2. + t - t / (2. * sqrt(2.)), 1., posZ, subRot3);
+
+    TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90. + angl);
+    TGeoCombiTrans* subTrRot4 =
+      new TGeoCombiTrans(name + "_subpillar_posrot_4", -x / 2. + t - t / (2. * sqrt(2.)), -1., posZ, subRot4);
+
+    frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1);
+    frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2);
+    frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3);
+    frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4);
+    //                frameBoxVol->GetShape()->ComputeBBox();
+  }
+
+  return frameBoxVol;
+}
+/** ======================================================================= **/
+
+/** ======================================================================= **/
+TGeoVolume* ConstructSmallCone(Double_t coneDz)
+{
+  // --- Material of the frames
+  TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon");
+
+  // --- Outer cone
+  //  TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.);
+  //  TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.);
+
+  Double_t radius    = 3.0;
+  Double_t thickness = 0.04;  // 0.4 mm
+  //  TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.);
+  TGeoConeSeg* A = new TGeoConeSeg("A", coneDz, radius, radius + thickness, radius, radius + thickness, 0., 180.);
+  TGeoBBox* B    = new TGeoBBox("B", 8., 6., 10.);
+
+  TGeoCombiTrans* M = new TGeoCombiTrans("M");
+  M->RotateX(45.);
+  M->SetDy(-5.575);
+  M->SetDz(6.935);
+  M->RegisterYourself();
+
+  TGeoShape* coneShp  = new TGeoCompositeShape("Cone_shp", "A-B:M");
+  TGeoVolume* coneVol = new TGeoVolume("Cone", coneShp, framesMaterial);
+  coneVol->SetLineColor(kGreen);
+  //  coneVol->RegisterYourself();
+
+  //  // --- Inner cone
+  //  Double_t thickness = 0.02;
+  //  Double_t thickness2 = 0.022;
+  //  //  TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.);
+  //  TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.);
+  //
+  //  TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2");
+  //  M2->RotateX (45.);
+  //  M2->SetDy (-5.575+thickness*sqrt(2.));
+  //  M2->SetDz (6.935);
+  //  M2->RegisterYourself();
+  //
+  //  TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2");
+  //  TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium);
+  //  coneVol2->SetLineColor(kGreen);
+  ////  coneVol2->RegisterYourself();
+  //
+  //  coneVol->AddNode(coneVol2, 1);
+
+  return coneVol;
+}
+/** ======================================================================= **/
+
+/** ======================================================================= **/
+TGeoVolume* ConstructBigCone(Double_t coneDz)
+{
+  // --- Material of the frames
+  TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon");
+
+  // --- Outer cone
+  TGeoConeSeg* bA = new TGeoConeSeg("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.);
+  TGeoBBox* bB    = new TGeoBBox("bB", 8., 6., 10.);
+
+  TGeoCombiTrans* bM = new TGeoCombiTrans("bM");
+  bM->RotateX(45.);
+  bM->SetDy(-5.575);
+  bM->SetDz(6.935);
+  bM->RegisterYourself();
+
+  TGeoShape* coneBigShp  = new TGeoCompositeShape("ConeBig_shp", "bA-bB:bM");
+  TGeoVolume* coneBigVol = new TGeoVolume("ConeBig", coneBigShp, framesMaterial);
+  coneBigVol->SetLineColor(kGreen);
+  //  coneBigVol->RegisterYourself();
+
+  // --- Inner cone
+  Double_t thickness  = 0.02;
+  Double_t thickness2 = 0.022;
+  TGeoConeSeg* bA2    = new TGeoConeSeg("bA2", coneDz - thickness, 6. + thickness, 7.6 - thickness2, 5.99 + thickness,
+                                     6.05 - thickness2, 0., 180.);
+
+  TGeoCombiTrans* bM2 = new TGeoCombiTrans("bM2");
+  bM2->RotateX(45.);
+  bM2->SetDy(-5.575 + thickness * sqrt(2.));
+  bM2->SetDz(6.935);
+  bM2->RegisterYourself();
+
+  TGeoShape* coneBigShp2  = new TGeoCompositeShape("ConeBig2_shp", "bA2-bB:bM2");
+  TGeoVolume* coneBigVol2 = new TGeoVolume("ConeBig2", coneBigShp2, gStsMedium);
+  coneBigVol2->SetLineColor(kGreen);
+  //  coneBigVol2->RegisterYourself();
+
+  coneBigVol->AddNode(coneBigVol2, 1);
+
+  return coneBigVol;
+}
+
+/** ======================================================================= **/