diff --git a/DDDetectors/include/DDDetectors/OtherDetectorHelpers.h b/DDDetectors/include/DDDetectors/OtherDetectorHelpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..16457c04591501aa2b195ee92019bf0cd4dceed9
--- /dev/null
+++ b/DDDetectors/include/DDDetectors/OtherDetectorHelpers.h
@@ -0,0 +1,114 @@
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+//==========================================================================
+#ifndef Other_Helpers_hh
+#define Other_Helpers_hh 1
+
+#include "DD4hep/Printout.h"
+
+#include <iostream>
+#include <map>
+#include <stdexcept>
+
+namespace ODH {//OtherDetectorHelpers
+
+  typedef enum { // These constants are also used in the MySQL database:
+    kCenter                     = 0, // centered on the z-axis
+    kUpstream                   = 1, // on the upstream branch, rotated by half the crossing angle
+    kDnstream                   = 2, // on the downstream branch, rotated by half the crossing angle
+    kPunchedCenter              = 3, // centered, with one or two inner holes
+    kPunchedUpstream            = 4, // on the upstream branch, with two inner holes
+    kPunchedDnstream            = 5, // on the downstrem branch, with two inner holes
+    kUpstreamClippedFront       = 6, // upstream, with the front face parallel to the xy-plane
+    kDnstreamClippedFront       = 7, // downstream, with the front face parallel to the xy-plane
+    kUpstreamClippedRear        = 8, // upstream, with the rear face parallel to the xy-plane
+    kDnstreamClippedRear        = 9, // downstream, with the rear face parallel to the xy-plane
+    kUpstreamClippedBoth        = 10, // upstream, with both faces parallel to the xy-plane
+    kDnstreamClippedBoth        = 11, // downstream, with both faces parallel to the xy-plane
+    kUpstreamSlicedFront        = 12, // upstream, with the front face parallel to a tilted piece
+    kDnstreamSlicedFront        = 13, // downstream, with the front face parallel to a tilted piece
+    kUpstreamSlicedRear         = 14, // upstream, with the rear face parallel to a tilted piece
+    kDnstreamSlicedRear         = 15, // downstream, with the rear face parallel to a tilted piece
+    kUpstreamSlicedBoth         = 16, // upstream, with both faces parallel to a tilted piece
+    kDnstreamSlicedBoth         = 17 // downstream, with both faces parallel to a tilted piece
+  } ECrossType;
+
+
+
+  static ECrossType getCrossType( std::string const & type) {
+
+    std::map< std::string, ODH::ECrossType > CrossTypes;
+    CrossTypes["Center"]                = ODH::kCenter               ;
+    CrossTypes["Upstream"]              = ODH::kUpstream             ;
+    CrossTypes["Dnstream"]              = ODH::kDnstream             ;
+    CrossTypes["PunchedCenter"]         = ODH::kPunchedCenter        ;
+    CrossTypes["PunchedUpstream"]       = ODH::kPunchedUpstream      ;
+    CrossTypes["PunchedDnstream"]       = ODH::kPunchedDnstream      ;
+    CrossTypes["UpstreamClippedFront"]  = ODH::kUpstreamClippedFront ;
+    CrossTypes["DnstreamClippedFront"]  = ODH::kDnstreamClippedFront ;
+    CrossTypes["UpstreamClippedRear"]   = ODH::kUpstreamClippedRear  ;
+    CrossTypes["DnstreamClippedRear"]   = ODH::kDnstreamClippedRear  ;
+    CrossTypes["UpstreamClippedBoth"]   = ODH::kUpstreamClippedBoth  ;
+    CrossTypes["DnstreamClippedBoth"]   = ODH::kDnstreamClippedBoth  ;
+    CrossTypes["UpstreamSlicedFront"]   = ODH::kUpstreamSlicedFront  ;
+    CrossTypes["DnstreamSlicedFront"]   = ODH::kDnstreamSlicedFront  ;
+    CrossTypes["UpstreamSlicedRear"]    = ODH::kUpstreamSlicedRear   ;
+    CrossTypes["DnstreamSlicedRear"]    = ODH::kDnstreamSlicedRear   ;
+    CrossTypes["UpstreamSlicedBoth"]    = ODH::kUpstreamSlicedBoth   ;
+    CrossTypes["DnstreamSlicedBoth"]    = ODH::kDnstreamSlicedBoth   ;
+
+    std::map < std::string, ODH::ECrossType>::const_iterator ct = CrossTypes.find(type);
+    if ( ct == CrossTypes.end() ) {
+      throw std::runtime_error("Unknown Crossing Type for this geometry");
+    }
+    return ct->second;
+  }
+
+  static bool checkForSensibleGeometry(double crossingAngle, ECrossType crossType) {
+    if (crossingAngle == 0 && crossType != kCenter) {
+      printout(DD4hep::ERROR, "Mask/Beampip", "You are trying to build a crossing geometry without a crossing angle.\n" );
+      printout(DD4hep::ERROR, "Mask/Beampip", "This is probably not what you want - better check your geometry data!");
+      return false; // premature exit, dd4hep will abort now
+    }
+    return true;
+  }
+
+
+  static double getCurrentAngle( double crossingAngle, ECrossType crossType ) {
+    double tmpAngle;
+    switch (crossType) {
+    case kUpstream:
+    case kPunchedUpstream:
+    case kUpstreamClippedFront:
+    case kUpstreamClippedRear:
+    case kUpstreamClippedBoth:
+    case kUpstreamSlicedFront:
+    case kUpstreamSlicedRear:
+    case kUpstreamSlicedBoth:
+      tmpAngle = -crossingAngle; break;
+    case kDnstream:
+    case kPunchedDnstream:
+    case kDnstreamClippedFront:
+    case kDnstreamClippedRear:
+    case kDnstreamClippedBoth:
+    case kDnstreamSlicedFront:
+    case kDnstreamSlicedRear:
+    case kDnstreamSlicedBoth:
+      tmpAngle = +crossingAngle; break;
+    default:
+      tmpAngle = 0; break;
+    }
+
+    return tmpAngle;
+  }
+
+}//namespace
+
+#endif // Other_Helpers_hh
diff --git a/DDDetectors/src/Beampipe_o1_v01_geo.cpp b/DDDetectors/src/Beampipe_o1_v01_geo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..508c11a9a87047abe76822db2b316881e7d89ce3
--- /dev/null
+++ b/DDDetectors/src/Beampipe_o1_v01_geo.cpp
@@ -0,0 +1,622 @@
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+//==========================================================================
+
+#include "DDDetectors/OtherDetectorHelpers.h"
+
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/DD4hepUnits.h"
+#include "DD4hep/DetType.h"
+#include "DD4hep/Printout.h"
+
+#include "DDRec/DetectorData.h"
+#include "DDRec/Surface.h"
+
+#include "XML/Utilities.h"
+
+#include <cmath>
+#include <map>
+#include <string>
+
+using DD4hep::Geometry::Transform3D;
+using DD4hep::Geometry::Position;
+using DD4hep::Geometry::RotationY;
+using DD4hep::Geometry::RotateY;
+using DD4hep::Geometry::ConeSegment;
+using DD4hep::Geometry::SubtractionSolid;
+using DD4hep::Geometry::Material;
+using DD4hep::Geometry::Volume;
+using DD4hep::Geometry::Solid;
+using DD4hep::Geometry::Tube;
+
+using DD4hep::DDRec::Vector3D;
+using DD4hep::DDRec::VolCylinder;
+using DD4hep::DDRec::VolCone;
+using DD4hep::DDRec::SurfaceType;
+
+/// helper class for a simple cylinder surface parallel to z with a given length - used as IP layer
+class SimpleCylinderImpl : public  DD4hep::DDRec::VolCylinderImpl{
+  double _half_length ;
+public:
+  /// standard c'tor with all necessary arguments - origin is (0,0,0) if not given.
+  SimpleCylinderImpl( DD4hep::Geometry::Volume vol, DDSurfaces::SurfaceType type,
+		      double thickness_inner ,double thickness_outer,  DDSurfaces::Vector3D origin ) :
+    DD4hep::DDRec::VolCylinderImpl( vol,  type, thickness_inner, thickness_outer,   origin ),
+    _half_length(0){
+  }
+  void setHalfLength( double half_length){
+    _half_length = half_length ;
+  }
+  void setID( DD4hep::long64 id ) { _id = id ;
+  }
+  // overwrite to include points inside the inner radius of the barrel
+  bool insideBounds(const DDSurfaces::Vector3D& point, double epsilon) const {
+    return ( std::abs( point.rho() - origin().rho() ) < epsilon && std::abs( point.z() ) < _half_length ) ;
+  }
+
+  virtual std::vector< std::pair<DDSurfaces::Vector3D, DDSurfaces::Vector3D> > getLines(unsigned nMax=100){
+
+    std::vector< std::pair<DDSurfaces::Vector3D, DDSurfaces::Vector3D> >  lines ;
+
+    lines.reserve( nMax ) ;
+
+    Vector3D zv( 0. , 0. , _half_length ) ;
+    double r = _o.rho() ;
+
+    unsigned n = nMax / 4 ;
+    double dPhi = 2.* ROOT::Math::Pi() / double( n ) ;
+
+    for( unsigned i = 0 ; i < n ; ++i ) {
+
+      Vector3D rv0(  r*sin(  i   *dPhi ) , r*cos(  i   *dPhi )  , 0. ) ;
+      Vector3D rv1(  r*sin( (i+1)*dPhi ) , r*cos( (i+1)*dPhi )  , 0. ) ;
+
+      Vector3D pl0 =  zv + rv0 ;
+      Vector3D pl1 =  zv + rv1 ;
+      Vector3D pl2 = -zv + rv1  ;
+      Vector3D pl3 = -zv + rv0 ;
+
+      lines.push_back( std::make_pair( pl0, pl1 ) ) ;
+      lines.push_back( std::make_pair( pl1, pl2 ) ) ;
+      lines.push_back( std::make_pair( pl2, pl3 ) ) ;
+      lines.push_back( std::make_pair( pl3, pl0 ) ) ;
+    }
+    return lines;
+  }
+};
+
+class SimpleCylinder : public DD4hep::DDRec::VolSurface{
+public:
+  SimpleCylinder( DD4hep::Geometry::Volume vol, DD4hep::DDRec::SurfaceType type, double thickness_inner ,
+		  double thickness_outer,  Vector3D origin ) :
+    DD4hep::DDRec::VolSurface( new SimpleCylinderImpl( vol,  type,  thickness_inner , thickness_outer, origin ) ) {
+  }
+  SimpleCylinderImpl* operator->() { return static_cast<SimpleCylinderImpl*>( _surf ) ; }
+} ;
+
+
+static DD4hep::Geometry::Ref_t create_element(DD4hep::Geometry::LCDD& lcdd,
+					      xml_h element,
+					      DD4hep::Geometry::SensitiveDetector /*sens*/) {
+
+  printout(DD4hep::DEBUG,"DD4hep_Beampipe", "Creating Beampipe" ) ;
+
+  //Access to the XML File
+  xml_det_t xmlBeampipe = element;
+  const std::string name = xmlBeampipe.nameStr();
+
+
+  DD4hep::Geometry::DetElement tube(  name, xmlBeampipe.id()  ) ;
+
+  // --- create an envelope volume and position it into the world ---------------------
+
+  Volume envelope = DD4hep::XML::createPlacedEnvelope( lcdd,  element , tube ) ;
+
+  DD4hep::XML::setDetectorTypeFlag( element, tube ) ;
+
+  if( lcdd.buildType() == DD4hep::BUILD_ENVELOPE ) return tube ;
+
+  //-----------------------------------------------------------------------------------
+
+
+  DD4hep::DDRec::ConicalSupportData* beampipeData = new DD4hep::DDRec::ConicalSupportData ;
+
+  //DD4hep/TGeo seems to need rad (as opposed to the manual)
+  const double phi1 = 0 ;
+  const double phi2 = 360.0*dd4hep::degree;
+
+  //Parameters we have to know about
+  DD4hep::XML::Component xmlParameter = xmlBeampipe.child(_Unicode(parameter));
+  const double crossingAngle  = xmlParameter.attr< double >(_Unicode(crossingangle))*0.5; //  only half the angle
+
+
+  double min_radius = 1.e99 ;
+
+  for(xml_coll_t c( xmlBeampipe ,Unicode("section")); c; ++c) {
+
+    xml_comp_t xmlSection( c );
+
+    ODH::ECrossType crossType = ODH::getCrossType(xmlSection.attr< std::string >(_Unicode(type)));
+    const double zStart       = xmlSection.attr< double > (_Unicode(start));
+    const double zEnd         = xmlSection.attr< double > (_Unicode(end));
+    const double rInnerStart  = xmlSection.attr< double > (_Unicode(rMin1));
+    const double rInnerEnd    = xmlSection.attr< double > (_Unicode(rMin2));
+    const double rOuterStart  = xmlSection.attr< double > (_Unicode(rMax1));
+    const double rOuterEnd    = xmlSection.attr< double > (_Unicode(rMax2));
+    const double thickness    = rOuterStart - rInnerStart;
+    Material sectionMat  = lcdd.material(xmlSection.materialStr());
+    const std::string volName      = "tube_" + xmlSection.nameStr();
+
+    std::stringstream pipeInfo;
+    pipeInfo << std::setw(8) << zStart      /dd4hep::mm
+	     << std::setw(8) << zEnd        /dd4hep::mm
+	     << std::setw(8) << rInnerStart /dd4hep::mm
+	     << std::setw(8) << rInnerEnd   /dd4hep::mm
+	     << std::setw(8) << rOuterStart /dd4hep::mm
+	     << std::setw(8) << rOuterEnd   /dd4hep::mm
+	     << std::setw(8) << thickness   /dd4hep::mm
+	     << std::setw(8) << crossType
+	     << std::setw(35) << volName
+	     << std::setw(15) << sectionMat.name();
+
+    printout(DD4hep::INFO, "DD4hep_Beampipe", pipeInfo.str() );
+
+    if( crossType == ODH::kCenter ) { // store only the central sections !
+      DD4hep::DDRec::ConicalSupportData::Section section ;
+      section.rInner = rInnerStart ;
+      section.rOuter = rOuterStart ;
+      section.zPos   = zStart ;
+      beampipeData->sections.push_back( section ) ;
+    }
+
+    // things which can be calculated immediately
+    const double zHalf       = fabs(zEnd - zStart) * 0.5; // half z length of the cone
+    const double zPosition   = fabs(zEnd + zStart) * 0.5; // middle z position
+    Material coreMaterial    = lcdd.material("beam"); // always the same
+    Material wallMaterial    = sectionMat;
+
+    // this could mess up your geometry, so better check it
+    if (not checkForSensibleGeometry(crossingAngle, crossType)){
+
+      throw std::runtime_error( " Beampipe_o1_v01_geo.cpp : checkForSensibleGeometry() failed " ) ;
+      //      return false;
+    }
+    const double rotateAngle = getCurrentAngle(crossingAngle, crossType); // for the placement at +z (better make it const now)
+    const double mirrorAngle = M_PI - rotateAngle; // for the "mirrored" placement at -z
+    // the "mirroring" in fact is done by a rotation of (almost) 180 degrees around the y-axis
+
+    switch (crossType) {
+    case ODH::kCenter:
+    case ODH::kUpstream:
+    case ODH::kDnstream: {
+      // a volume on the z-axis, on the upstream branch, or on the downstream branch
+
+      // absolute transformations for the placement in the world
+      Transform3D transformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition), rotateAngle) );
+      Transform3D transmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition), mirrorAngle) );
+
+      // solid for the tube (including vacuum and wall): a solid cone
+      ConeSegment tubeSolid( zHalf, 0, rOuterStart, 0, rOuterEnd , phi1, phi2);
+
+      // tube consists of vacuum
+      // place tube twice explicitely so we can attach surfaces to each one
+      Volume tubeLog( volName, tubeSolid, coreMaterial ) ;
+      Volume tubeLog2( volName, tubeSolid, coreMaterial ) ;
+
+      // placement of the tube in the world, both at +z and -z
+      envelope.placeVolume( tubeLog,  transformer );
+      envelope.placeVolume( tubeLog2,  transmirror );
+
+      // if inner and outer radii are equal, then omit the tube wall
+      if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
+
+	// the wall solid: a tubular cone
+	ConeSegment wallSolid( zHalf, rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, phi1, phi2);
+
+	// the wall consists of the material given in the XML
+	Volume wallLog ( volName + "_wall", wallSolid, wallMaterial);
+	Volume wallLog2( volName + "_wall2", wallSolid, wallMaterial);
+
+	if( crossType == ODH::kCenter ) {
+
+	  // add surface for tracking ....
+	  const bool isCylinder = ( rInnerStart == rInnerEnd );
+
+
+	  if (isCylinder) {  // cylinder
+
+	    Vector3D ocyl(  rInnerStart + thickness/2.  , 0. , 0. ) ;
+
+	    VolCylinder cylSurf1( wallLog , SurfaceType( SurfaceType::Helper ) , 0.5*thickness  , 0.5*thickness , ocyl );
+	    VolCylinder cylSurf2( wallLog2, SurfaceType( SurfaceType::Helper ) , 0.5*thickness  , 0.5*thickness , ocyl );
+
+	    DD4hep::DDRec::volSurfaceList( tube )->push_back( cylSurf1 );
+	    DD4hep::DDRec::volSurfaceList( tube )->push_back( cylSurf2 );
+
+	  }else{   // cone
+
+	    const double dr    = rInnerEnd - rInnerStart ;
+	    const double theta = atan2( dr , 2.* zHalf ) ;
+
+	    Vector3D ocon( rInnerStart + 0.5 * ( dr + thickness ), 0. , 0. );
+
+	    Vector3D v( 1. , 0. , theta, Vector3D::spherical ) ;
+
+	    VolCone conSurf1( wallLog , SurfaceType( SurfaceType::Helper ) , 0.5*thickness  , 0.5*thickness , v, ocon );
+	    VolCone conSurf2( wallLog2, SurfaceType( SurfaceType::Helper ) , 0.5*thickness  , 0.5*thickness , v, ocon );
+
+	    DD4hep::DDRec::volSurfaceList( tube )->push_back( conSurf1 );
+	    DD4hep::DDRec::volSurfaceList( tube )->push_back( conSurf2 );
+
+	  }
+
+	  if( rInnerStart < min_radius ) min_radius = rInnerStart ;
+	  if( rOuterStart < min_radius ) min_radius = rOuterStart ;
+	}
+
+	wallLog.setVisAttributes(lcdd, "TubeVis");
+	wallLog2.setVisAttributes(lcdd, "TubeVis");
+	tubeLog.setVisAttributes(lcdd, "VacVis");
+	tubeLog2.setVisAttributes(lcdd, "VacVis");
+
+	// placement as a daughter volume of the tube, will appear in both placements of the tube
+	tubeLog.placeVolume( wallLog,  Transform3D() );
+	tubeLog2.placeVolume( wallLog2,  Transform3D() );
+      }
+    }
+      break;
+
+    case ODH::kPunchedCenter: {
+      // a volume on the z-axis with one or two inner holes
+      // (implemented as a cone from which tubes are punched out)
+
+      const double rUpstreamPunch = rInnerStart; // just alias names denoting what is meant here
+      const double rDnstreamPunch = rInnerEnd; // (the database entries are "abused" in this case)
+
+      // relative transformations for the composition of the SubtractionVolumes
+      Transform3D upstreamTransformer(RotationY(-crossingAngle), Position(zPosition * tan(-crossingAngle), 0, 0));
+      Transform3D dnstreamTransformer(RotationY(+crossingAngle), Position(zPosition * tan(+crossingAngle), 0, 0));
+
+      // absolute transformations for the final placement in the world (angles always equal zero and 180 deg)
+      Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
+      Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
+
+      // solid for the tube (including vacuum and wall): a solid cone
+      ConeSegment tubeSolid( zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2);
+
+      // tube consists of vacuum (will later have two different daughters)
+      Volume tubeLog0( volName + "_0", tubeSolid, coreMaterial );
+      Volume tubeLog1( volName + "_1", tubeSolid, coreMaterial );
+
+      // placement of the tube in the world, both at +z and -z
+      envelope.placeVolume( tubeLog0, placementTransformer );
+      envelope.placeVolume( tubeLog1, placementTransmirror );
+
+      // the wall solid and placeholders for possible SubtractionSolids
+      ConeSegment wholeSolid(  zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2);
+
+      Solid tmpSolid0, tmpSolid1, wallSolid0, wallSolid1;
+
+      // the punched subtraction solids can be asymmetric and therefore have to be created twice:
+      // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
+      // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
+
+      if ( rUpstreamPunch > 1e-6 ) { // do we need a hole on the upstream branch?
+	Tube upstreamPunch( 0, rUpstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
+	tmpSolid0 = SubtractionSolid( wholeSolid, upstreamPunch, upstreamTransformer);
+	tmpSolid1 = SubtractionSolid( wholeSolid, upstreamPunch, dnstreamTransformer); // [sic]
+      } else { // dont't do anything, just pass on the unmodified shape
+	tmpSolid0 = wholeSolid;
+	tmpSolid1 = wholeSolid;
+      }
+
+      if (rDnstreamPunch > 1e-6 ) { // do we need a hole on the downstream branch?
+	Tube dnstreamPunch( 0, rDnstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
+	wallSolid0 = SubtractionSolid( tmpSolid0, dnstreamPunch, dnstreamTransformer);
+	wallSolid1 = SubtractionSolid( tmpSolid1, dnstreamPunch, upstreamTransformer); // [sic]
+      } else { // dont't do anything, just pass on the unmodified shape
+	wallSolid0 = tmpSolid0;
+	wallSolid1 = tmpSolid1;
+      }
+
+      // the wall consists of the material given in the XML
+      Volume wallLog0( volName + "_wall_0", wallSolid0, wallMaterial );
+      Volume wallLog1( volName + "_wall_1", wallSolid1, wallMaterial );
+
+      wallLog0.setVisAttributes(lcdd, "TubeVis");
+      wallLog1.setVisAttributes(lcdd, "TubeVis");
+      tubeLog0.setVisAttributes(lcdd, "VacVis");
+      tubeLog1.setVisAttributes(lcdd, "VacVis");
+
+      // placement as a daughter volumes of the tube
+      tubeLog0.placeVolume( wallLog0, Position() );
+      tubeLog1.placeVolume( wallLog1, Position() );
+
+      break;
+    }
+
+    case ODH::kPunchedUpstream:
+    case ODH::kPunchedDnstream: {
+      // a volume on the upstream or downstream branch with two inner holes
+      // (implemented as a cone from which another tube is punched out)
+
+      const double rCenterPunch = (crossType == ODH::kPunchedUpstream) ? (rInnerStart) : (rInnerEnd); // just alias names denoting what is meant here
+      const double rOffsetPunch = (crossType == ODH::kPunchedDnstream) ? (rInnerStart) : (rInnerEnd); // (the database entries are "abused" in this case)
+
+      // relative transformations for the composition of the SubtractionVolumes
+      Transform3D punchTransformer(RotationY(-2 * rotateAngle), Position(zPosition * tan(-2 * rotateAngle), 0, 0));
+      Transform3D punchTransmirror(RotationY(+2 * rotateAngle), Position(zPosition * tan(+2 * rotateAngle), 0, 0));
+
+      // absolute transformations for the final placement in the world
+      Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
+      Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
+
+      // solid for the tube (including vacuum and wall): a solid cone
+      ConeSegment tubeSolid( zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2);
+
+      // tube consists of vacuum (will later have two different daughters)
+      Volume tubeLog0( volName + "_0", tubeSolid, coreMaterial );
+      Volume tubeLog1( volName + "_1", tubeSolid, coreMaterial );
+
+      // placement of the tube in the world, both at +z and -z
+      envelope.placeVolume( tubeLog0, placementTransformer );
+      envelope.placeVolume( tubeLog1, placementTransmirror );
+
+      // the wall solid and the piece (only a tube, for the moment) which will be punched out
+      ConeSegment wholeSolid( zHalf, rCenterPunch , rOuterStart, rCenterPunch, rOuterEnd, phi1, phi2);
+
+      Tube punchSolid( 0, rOffsetPunch, 5 * zHalf, phi1, phi2); // a bit longer
+
+      // the punched subtraction solids can be asymmetric and therefore have to be created twice:
+      // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
+      // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
+      SubtractionSolid wallSolid0( wholeSolid, punchSolid, punchTransformer);
+      SubtractionSolid wallSolid1( wholeSolid, punchSolid, punchTransmirror);
+
+      // the wall consists of the material given in the database
+      Volume wallLog0( volName + "_wall_0", wallSolid0, wallMaterial );
+      Volume wallLog1( volName + "_wall_1", wallSolid1, wallMaterial );
+
+      wallLog0.setVisAttributes(lcdd, "TubeVis");
+      wallLog1.setVisAttributes(lcdd, "TubeVis");
+
+      tubeLog0.setVisAttributes(lcdd, "VacVis");
+      tubeLog1.setVisAttributes(lcdd, "VacVis");
+
+      // placement as a daughter volumes of the tube
+      tubeLog0.placeVolume( wallLog0 , Position() );
+      tubeLog1.placeVolume( wallLog1 , Position() );
+
+      break;
+    }
+
+    case ODH::kUpstreamClippedFront:
+    case ODH::kDnstreamClippedFront:
+    case ODH::kUpstreamSlicedFront:
+    case ODH::kDnstreamSlicedFront: {
+      // a volume on the upstream or donwstream branch, but with the front face parallel to the xy-plane
+      // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
+      // (implemented as a slightly longer cone from which the end is clipped off)
+
+      // the volume which will be used for clipping: a solid tube
+      const double clipSize = rOuterStart; // the right order of magnitude for the clipping volume (alias name)
+      Tube clipSolid( 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
+
+      // relative transformations for the composition of the SubtractionVolumes
+      const double clipAngle = (crossType == ODH::kUpstreamClippedFront || crossType == ODH::kDnstreamClippedFront) ? (rotateAngle) : (2 * rotateAngle);
+      const double clipShift = (zStart - clipSize) / cos(clipAngle) - (zPosition - clipSize / 2); // question: why is this correct?
+      Transform3D clipTransformer(RotationY(-clipAngle), Position(0, 0, clipShift));
+      Transform3D clipTransmirror(RotationY(+clipAngle), Position(0, 0, clipShift));
+
+      // absolute transformations for the final placement in the world
+      Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition - clipSize / 2) , rotateAngle) );
+      Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition - clipSize / 2) , mirrorAngle) );
+
+      // solid for the tube (including vacuum and wall): a solid cone
+
+      ConeSegment wholeSolid(  zHalf + clipSize / 2, 0, rOuterStart, 0, rOuterEnd,  phi1, phi2); // a bit longer
+
+      // clip away the protruding end
+      SubtractionSolid tubeSolid0( wholeSolid, clipSolid, clipTransformer);
+      SubtractionSolid tubeSolid1( wholeSolid, clipSolid, clipTransmirror);
+
+      // tube consists of vacuum (will later have two different daughters)
+      Volume tubeLog0( volName + "_0", tubeSolid0, coreMaterial );
+      Volume tubeLog1( volName + "_1", tubeSolid1, coreMaterial );
+
+      // placement of the tube in the world, both at +z and -z
+      envelope.placeVolume( tubeLog0, placementTransformer );
+      envelope.placeVolume( tubeLog1, placementTransmirror );
+
+      if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
+	// the wall solid: a tubular cone
+	ConeSegment wallWholeSolid(  zHalf + clipSize / 2, rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, phi1, phi2); // a bit longer
+
+	// clip away the protruding end
+	SubtractionSolid wallSolid0( wallWholeSolid, clipSolid, clipTransformer);
+	SubtractionSolid wallSolid1( wallWholeSolid, clipSolid, clipTransmirror);
+
+	// the wall consists of the material given in the database
+	Volume wallLog0( volName + "_wall_0", wallSolid0, wallMaterial );
+	Volume wallLog1( volName + "_wall_1", wallSolid1, wallMaterial );
+
+	wallLog0.setVisAttributes(lcdd, "TubeVis");
+	wallLog1.setVisAttributes(lcdd, "TubeVis");
+
+	tubeLog0.setVisAttributes(lcdd, "VacVis");
+	tubeLog1.setVisAttributes(lcdd, "VacVis");
+
+	// placement as a daughter volumes of the tube
+	tubeLog0.placeVolume( wallLog0, Position() );
+	tubeLog1.placeVolume( wallLog1, Position() );
+      }
+    }
+      break;
+
+    case ODH::kUpstreamClippedRear:
+    case ODH::kDnstreamClippedRear:
+    case ODH::kUpstreamSlicedRear:
+    case ODH::kDnstreamSlicedRear: {
+      // a volume on the upstream or donwstream branch, but with the rear face parallel to the xy-plane
+      // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
+      // (implemented as a slightly longer cone from which the end is clipped off)
+
+      // the volume which will be used for clipping: a solid tube
+      const double clipSize = rOuterEnd; // the right order of magnitude for the clipping volume (alias name)
+      Tube clipSolid( 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
+
+      // relative transformations for the composition of the SubtractionVolumes
+      const double clipAngle = (crossType == ODH::kUpstreamClippedRear || crossType == ODH::kDnstreamClippedRear) ? (rotateAngle) : (2 * rotateAngle);
+      const double clipShift = (zEnd + clipSize) / cos(clipAngle) - (zPosition + clipSize / 2); // question: why is this correct?
+      Transform3D clipTransformer(RotationY(-clipAngle), Position(0, 0, clipShift));
+      Transform3D clipTransmirror(RotationY(+clipAngle), Position(0, 0, clipShift));
+
+      // absolute transformations for the final placement in the world
+      Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition + clipSize / 2) , rotateAngle) );
+      Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition + clipSize / 2) , mirrorAngle) );
+
+      // solid for the tube (including vacuum and wall): a solid cone
+      ConeSegment wholeSolid( 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
+
+      // clip away the protruding end
+      SubtractionSolid tubeSolid0( wholeSolid, clipSolid, clipTransformer);
+      SubtractionSolid tubeSolid1( wholeSolid, clipSolid, clipTransmirror);
+
+      // tube consists of vacuum (will later have two different daughters)
+      Volume tubeLog0( volName + "_0", tubeSolid0, coreMaterial );
+      Volume tubeLog1( volName + "_1", tubeSolid1, coreMaterial );
+
+      // placement of the tube in the world, both at +z and -z
+      envelope.placeVolume( tubeLog0, placementTransformer );
+      envelope.placeVolume( tubeLog1, placementTransmirror );
+
+      if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
+	// the wall solid: a tubular cone
+	ConeSegment wallWholeSolid( rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
+
+	// clip away the protruding end
+	SubtractionSolid wallSolid0( wallWholeSolid, clipSolid, clipTransformer);
+	SubtractionSolid wallSolid1( wallWholeSolid, clipSolid, clipTransmirror);
+
+	// the wall consists of the material given in the database
+	Volume wallLog0( volName + "_wall_0", wallSolid0, wallMaterial );
+	Volume wallLog1( volName + "_wall_1", wallSolid1, wallMaterial );
+
+	wallLog0.setVisAttributes(lcdd, "TubeVis");
+	wallLog1.setVisAttributes(lcdd, "TubeVis");
+
+	tubeLog0.setVisAttributes(lcdd, "VacVis");
+	tubeLog1.setVisAttributes(lcdd, "VacVis");
+
+	// placement as a daughter volumes of the tube
+	tubeLog0.placeVolume( wallLog0, Transform3D() );
+	tubeLog1.placeVolume( wallLog1, Transform3D() );
+      }
+      break;
+    }
+
+    case ODH::kUpstreamClippedBoth:
+    case ODH::kDnstreamClippedBoth:
+    case ODH::kUpstreamSlicedBoth:
+    case ODH::kDnstreamSlicedBoth: {
+      // a volume on the upstream or donwstream branch, but with both faces parallel to the xy-plane
+      // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
+      // (implemented as a slightly longer cone from which the end is clipped off)
+
+      // the volume which will be used for clipping: a solid tube
+      const double clipSize = rOuterEnd; // the right order of magnitude for the clipping volume (alias name)
+      Tube clipSolid( 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
+
+      // relative transformations for the composition of the SubtractionVolumes
+      const double clipAngle = (crossType == ODH::kUpstreamClippedBoth || crossType == ODH::kDnstreamClippedBoth) ? (rotateAngle) : (2 * rotateAngle);
+      const double clipShiftFrnt = (zStart - clipSize) / cos(clipAngle) - zPosition;
+      const double clipShiftRear = (zEnd   + clipSize) / cos(clipAngle) - zPosition;
+      Transform3D clipTransformerFrnt(RotationY(-clipAngle), Position(0, 0, clipShiftFrnt));
+      Transform3D clipTransformerRear(RotationY(-clipAngle), Position(0, 0, clipShiftRear));
+      Transform3D clipTransmirrorFrnt(RotationY(+clipAngle), Position(0, 0, clipShiftFrnt));
+      Transform3D clipTransmirrorRear(RotationY(+clipAngle), Position(0, 0, clipShiftRear));
+
+      // absolute transformations for the final placement in the world
+      Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
+      Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
+
+      // solid for the tube (including vacuum and wall): a solid cone
+      ConeSegment wholeSolid( 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize, phi1, phi2); // a bit longer
+
+      // clip away the protruding ends
+      SubtractionSolid tmpSolid0 ( wholeSolid, clipSolid, clipTransformerFrnt);
+      SubtractionSolid tmpSolid1 ( wholeSolid, clipSolid, clipTransmirrorFrnt);
+      SubtractionSolid tubeSolid0( tmpSolid0,  clipSolid, clipTransformerRear);
+      SubtractionSolid tubeSolid1( tmpSolid1,  clipSolid, clipTransmirrorRear);
+
+      // tube consists of vacuum (will later have two different daughters)
+      Volume tubeLog0( volName + "_0", tubeSolid0, coreMaterial );
+      Volume tubeLog1( volName + "_1", tubeSolid1, coreMaterial );
+
+      // placement of the tube in the world, both at +z and -z
+      envelope.placeVolume( tubeLog0, placementTransformer );
+      envelope.placeVolume( tubeLog1, placementTransmirror );
+
+      if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
+	// the wall solid: a tubular cone
+	ConeSegment wallWholeSolid( rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize, phi1, phi2); // a bit longer
+
+	// clip away the protruding ends
+	SubtractionSolid wallTmpSolid0( wallWholeSolid, clipSolid, clipTransformerFrnt);
+	SubtractionSolid wallTmpSolid1( wallWholeSolid, clipSolid, clipTransmirrorFrnt);
+	SubtractionSolid wallSolid0   ( wallTmpSolid0,  clipSolid, clipTransformerRear);
+	SubtractionSolid wallSolid1   ( wallTmpSolid1,  clipSolid, clipTransmirrorRear);
+
+	// the wall consists of the material given in the database
+	Volume wallLog0(volName + "_wall_0", wallSolid0, wallMaterial );
+	Volume wallLog1(volName + "_wall_1", wallSolid1, wallMaterial );
+
+	wallLog0.setVisAttributes(lcdd, "TubeVis");
+	wallLog1.setVisAttributes(lcdd, "TubeVis");
+
+	tubeLog0.setVisAttributes(lcdd, "VacVis");
+	tubeLog1.setVisAttributes(lcdd, "VacVis");
+
+	// placement as a daughter volumes of the tube
+	tubeLog0.placeVolume( wallLog0, Transform3D() );
+	tubeLog1.placeVolume( wallLog1, Transform3D() );
+      }
+      break;
+    }
+    default: {
+      throw std::runtime_error( " Beampipe_o1_v01_geo.cpp : fatal failure !! ??  " ) ;
+
+      //      return false; // fatal failure
+    }
+
+    }//end switch
+  }//for all xmlSections
+
+  //######################################################################################################################################################################
+
+
+  // add a surface just inside the beampipe for tracking:
+  Vector3D oIPCyl( (min_radius-1.e-3)  , 0. , 0.  ) ;
+  SimpleCylinder ipCylSurf( envelope , SurfaceType( SurfaceType::Helper ) , 1.e-5  , 1e-5 , oIPCyl ) ;
+  // the length does not really matter here as long as it is long enough for all tracks ...
+  ipCylSurf->setHalfLength(  100*dd4hep::cm ) ;
+  DD4hep::DDRec::volSurfaceList( tube )->push_back( ipCylSurf ) ;
+
+  tube.addExtension< DD4hep::DDRec::ConicalSupportData >( beampipeData ) ;
+
+  //--------------------------------------
+
+  tube.setVisAttributes( lcdd, xmlBeampipe.visStr(), envelope );
+
+  // // tube.setPlacement(pv);
+
+  return tube;
+}
+DECLARE_DETELEMENT(DD4hep_Beampipe_o1_v01,create_element)
diff --git a/DDDetectors/src/Mask_o1_v01_geo.cpp b/DDDetectors/src/Mask_o1_v01_geo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bc6b56114ef0a93db67e649f4b6284bd7b51ea96
--- /dev/null
+++ b/DDDetectors/src/Mask_o1_v01_geo.cpp
@@ -0,0 +1,232 @@
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+//==========================================================================
+#include "DDDetectors/OtherDetectorHelpers.h"
+
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/Printout.h"
+#include "DD4hep/DD4hepUnits.h"
+
+#include <cmath>
+#include <string>
+
+using DD4hep::Geometry::Transform3D;
+using DD4hep::Geometry::Position;
+using DD4hep::Geometry::RotationY;
+using DD4hep::Geometry::RotateY;
+using DD4hep::Geometry::ConeSegment;
+using DD4hep::Geometry::SubtractionSolid;
+using DD4hep::Geometry::Material;
+using DD4hep::Geometry::Volume;
+using DD4hep::Geometry::Solid;
+using DD4hep::Geometry::Tube;
+using DD4hep::Geometry::PlacedVolume;
+using DD4hep::Geometry::Assembly;
+
+static DD4hep::Geometry::Ref_t create_element(DD4hep::Geometry::LCDD& lcdd,
+					      xml_h xmlHandle,
+					      DD4hep::Geometry::SensitiveDetector /*sens*/) {
+
+  printout(DD4hep::DEBUG,"DD4hep_Mask", "Creating Mask" ) ;
+
+  //Access to the XML File
+  xml_det_t xmlMask = xmlHandle;
+  const std::string name = xmlMask.nameStr();
+
+  //--------------------------------
+  Assembly envelope( name + "_assembly"  ) ;
+  //--------------------------------
+
+  DD4hep::Geometry::DetElement tube(  name, xmlMask.id()  ) ;
+
+  const double phi1 = 0 ;
+  const double phi2 = 360.0*dd4hep::degree;
+
+  //Parameters we have to know about
+  DD4hep::XML::Component xmlParameter = xmlMask.child(_Unicode(parameter));
+  const double crossingAngle  = xmlParameter.attr< double >(_Unicode(crossingangle))*0.5; //  only half the angle
+
+  for(xml_coll_t c( xmlMask ,Unicode("section")); c; ++c) {
+
+    xml_comp_t xmlSection( c );
+
+    ODH::ECrossType crossType = ODH::getCrossType(xmlSection.attr< std::string >(_Unicode(type)));
+    const double zStart       = xmlSection.attr< double > (_Unicode(start));
+    const double zEnd         = xmlSection.attr< double > (_Unicode(end));
+    const double rInnerStart  = xmlSection.attr< double > (_Unicode(rMin1));
+    const double rInnerEnd    = xmlSection.attr< double > (_Unicode(rMin2));
+    const double rOuterStart  = xmlSection.attr< double > (_Unicode(rMax1));
+    const double rOuterEnd    = xmlSection.attr< double > (_Unicode(rMax2));
+    const double thickness    = rOuterStart - rInnerStart;
+    Material sectionMat  = lcdd.material(xmlSection.materialStr());
+    const std::string volName      = "tube_" + xmlSection.nameStr();
+
+    std::stringstream pipeInfo;
+    pipeInfo << std::setw(8) << zStart      /dd4hep::mm
+	     << std::setw(8) << zEnd        /dd4hep::mm
+	     << std::setw(8) << rInnerStart /dd4hep::mm
+	     << std::setw(8) << rInnerEnd   /dd4hep::mm
+	     << std::setw(8) << rOuterStart /dd4hep::mm
+	     << std::setw(8) << rOuterEnd   /dd4hep::mm
+	     << std::setw(8) << thickness   /dd4hep::mm
+	     << std::setw(8) << crossType
+	     << std::setw(35) << volName
+	     << std::setw(15) << sectionMat.name();
+
+    printout(DD4hep::INFO, "DD4hep_Mask", pipeInfo.str() );
+
+    // things which can be calculated immediately
+    const double zHalf       = fabs(zEnd - zStart) * 0.5; // half z length of the cone
+    const double zPosition   = fabs(zEnd + zStart) * 0.5; // middle z position
+    Material material    = sectionMat;
+
+    // this could mess up your geometry, so better check it
+    if (not ODH::checkForSensibleGeometry(crossingAngle, crossType)){
+      throw std::runtime_error( " Mask_o1_v01_geo.cpp : checkForSensibleGeometry() failed " ) ;
+    }
+
+    const double rotateAngle = getCurrentAngle(crossingAngle, crossType); // for the placement at +z (better make it const now)
+    const double mirrorAngle = M_PI - rotateAngle; // for the "mirrored" placement at -z
+    // the "mirroring" in fact is done by a rotation of (almost) 180 degrees around the y-axis
+
+    switch (crossType) {
+    case ODH::kCenter:
+    case ODH::kUpstream:
+    case ODH::kDnstream: {
+      // a volume on the z-axis, on the upstream branch, or on the downstream branch
+
+      // absolute transformations for the placement in the world
+      Transform3D transformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition), rotateAngle) );
+      Transform3D transmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition), mirrorAngle) );
+
+      // solid for the tube (including vacuum and wall): a solid cone
+      ConeSegment tubeSolid( zHalf, rInnerStart, rOuterStart, rInnerEnd, rOuterEnd , phi1, phi2);
+
+      // tube consists of vacuum
+      Volume tubeLog( volName, tubeSolid, material ) ;
+      tubeLog.setVisAttributes(lcdd, xmlMask.visStr() );
+
+      // placement of the tube in the world, both at +z and -z
+      envelope.placeVolume( tubeLog,  transformer );
+      envelope.placeVolume( tubeLog,  transmirror );
+
+    }
+      break;
+
+    case ODH::kPunchedCenter: {
+      // a cone with one or two inner holes (two tubes are punched out)
+
+      const double rUpstreamPunch = rInnerStart; // just alias names denoting what is meant here
+      const double rDnstreamPunch = rInnerEnd; // (the database entries are "abused" in this case)
+
+      // relative transformations for the composition of the SubtractionVolumes
+      Transform3D upstreamTransformer(RotationY(-crossingAngle), Position(zPosition * tan(-crossingAngle), 0, 0));
+      Transform3D dnstreamTransformer(RotationY(+crossingAngle), Position(zPosition * tan(+crossingAngle), 0, 0));
+
+      // absolute transformations for the final placement in the world (angles always equal zero and 180 deg)
+      Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
+      Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
+
+      // the main solid and the two pieces (only tubes, for the moment) which will be punched out
+      ConeSegment wholeSolid(  zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2 );
+      Solid tmpSolid0, tmpSolid1, finalSolid0, finalSolid1;
+
+      // the punched subtraction solids can be asymmetric and therefore have to be created twice:
+      // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
+      // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
+
+      if ( rUpstreamPunch > 1e-6 ) { // do we need a hole on the upstream branch?
+	Tube upstreamPunch( 0, rUpstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
+	tmpSolid0 = SubtractionSolid( wholeSolid, upstreamPunch, upstreamTransformer);
+	tmpSolid1 = SubtractionSolid( wholeSolid, upstreamPunch, dnstreamTransformer); // [sic]
+      } else { // dont't do anything, just pass on the unmodified shape
+	tmpSolid0 = wholeSolid;
+	tmpSolid1 = wholeSolid;
+      }
+
+      if (rDnstreamPunch > 1e-6 ) { // do we need a hole on the downstream branch?
+	Tube dnstreamPunch( 0, rDnstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
+	finalSolid0 = SubtractionSolid( tmpSolid0, dnstreamPunch, dnstreamTransformer);
+	finalSolid1 = SubtractionSolid( tmpSolid1, dnstreamPunch, upstreamTransformer); // [sic]
+      } else { // dont't do anything, just pass on the unmodified shape
+	finalSolid0 = tmpSolid0;
+	finalSolid1 = tmpSolid1;
+      }
+
+      // tube consists of vacuum (will later have two different daughters)
+      Volume tubeLog0( volName + "_0", finalSolid0, material );
+      Volume tubeLog1( volName + "_1", finalSolid1, material );
+      tubeLog0.setVisAttributes(lcdd, xmlMask.visStr() );
+      tubeLog1.setVisAttributes(lcdd, xmlMask.visStr() );
+
+      // placement of the tube in the world, both at +z and -z
+      envelope.placeVolume( tubeLog0, placementTransformer );
+      envelope.placeVolume( tubeLog1, placementTransmirror );
+
+      break;
+    }
+
+    case ODH::kPunchedUpstream:
+    case ODH::kPunchedDnstream: {
+      // a volume on the upstream or downstream branch with two inner holes
+      // (implemented as a cone from which another tube is punched out)
+
+      const double rCenterPunch = (crossType == ODH::kPunchedUpstream) ? (rInnerStart) : (rInnerEnd); // just alias names denoting what is meant here
+      const double rOffsetPunch = (crossType == ODH::kPunchedDnstream) ? (rInnerStart) : (rInnerEnd); // (the database entries are "abused" in this case)
+
+      // relative transformations for the composition of the SubtractionVolumes
+      Transform3D punchTransformer(RotationY(-2 * rotateAngle), Position(zPosition * tan(-2 * rotateAngle), 0, 0));
+      Transform3D punchTransmirror(RotationY(+2 * rotateAngle), Position(zPosition * tan(+2 * rotateAngle), 0, 0));
+
+      // absolute transformations for the final placement in the world
+      Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
+      Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
+
+      // the main solid and the piece (only a tube, for the moment) which will be punched out
+      ConeSegment wholeSolid( zHalf, rCenterPunch , rOuterStart, rCenterPunch, rOuterEnd, phi1, phi2);
+      Tube punchSolid( 0, rOffsetPunch, 5 * zHalf, phi1, phi2); // a bit longer
+
+      // the punched subtraction solids can be asymmetric and therefore have to be created twice:
+      // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
+      // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
+      SubtractionSolid finalSolid0( wholeSolid, punchSolid, punchTransformer);
+      SubtractionSolid finalSolid1( wholeSolid, punchSolid, punchTransmirror);
+
+      // tube consists of vacuum (will later have two different daughters)
+      Volume tubeLog0( volName + "_0", finalSolid0, material );
+      Volume tubeLog1( volName + "_1", finalSolid1, material );
+      tubeLog0.setVisAttributes(lcdd, xmlMask.visStr() );
+      tubeLog1.setVisAttributes(lcdd, xmlMask.visStr() );
+
+      // placement of the tube in the world, both at +z and -z
+      envelope.placeVolume( tubeLog0, placementTransformer );
+      envelope.placeVolume( tubeLog1, placementTransmirror );
+
+      break;
+    }
+    default: {
+      throw std::runtime_error( " Mask_o1_v01_geo.cpp : fatal failure !! ??  " ) ;
+    }
+
+    }//end switch
+  }//for all xmlSections
+
+  //--------------------------------------
+  Volume mother =  lcdd.pickMotherVolume( tube ) ;
+  PlacedVolume pv(mother.placeVolume(envelope));
+  pv.addPhysVolID( "system", xmlMask.id() ) ; //.addPhysVolID("side", 0 ) ;
+
+  tube.setVisAttributes( lcdd, xmlMask.visStr(), envelope );
+
+  tube.setPlacement(pv);
+
+  return tube;
+}
+DECLARE_DETELEMENT(DD4hep_Mask_o1_v01,create_element)
diff --git a/DDDetectors/src/Solenoid_o1_v01_gep.cpp b/DDDetectors/src/Solenoid_o1_v01_gep.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..af085baebf95829a45903344b44012627874b52e
--- /dev/null
+++ b/DDDetectors/src/Solenoid_o1_v01_gep.cpp
@@ -0,0 +1,137 @@
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+//==========================================================================
+
+#include "DDRec/DetectorData.h"
+
+#include "DD4hep/DetFactoryHelper.h"
+
+#include "XML/Layering.h"
+#include "XML/Utilities.h"
+
+
+#include "TGeoTrd2.h"
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+
+static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
+  xml_det_t     x_det     = e;
+  int           det_id    = x_det.id();
+  string        det_name  = x_det.nameStr();
+  DetElement    sdet      (det_name,det_id);
+
+
+  // --- create an envelope volume and position it into the world ---------------------
+
+  Volume envelope = XML::createPlacedEnvelope( lcdd,  e , sdet ) ;
+  XML::setDetectorTypeFlag( e, sdet ) ;
+
+  if( lcdd.buildType() == BUILD_ENVELOPE ) return sdet ;
+
+  //-----------------------------------------------------------------------------------
+
+
+  Material air = lcdd.air();
+  PlacedVolume pv;
+  int n = 0;
+
+  //added code by Thorben Quast for event display
+  DDRec::LayeredCalorimeterData* solenoidData = new DDRec::LayeredCalorimeterData;
+  solenoidData->inner_symmetry = 0;
+  solenoidData->outer_symmetry = 0;
+  solenoidData->layoutType = DDRec::LayeredCalorimeterData::BarrelLayout ;
+
+  double inner_radius= std::numeric_limits<double>::max();
+  double outer_radius= 0;
+
+  double detZ= 0.;
+
+  for(xml_coll_t i(x_det,_U(layer)); i; ++i, ++n)  {
+    xml_comp_t x_layer = i;
+    string  l_name = det_name+_toString(n,"_layer%d");
+    double  z    = x_layer.outer_z();
+    double  rmin = x_layer.inner_r();
+    double  r    = rmin;
+    DetElement layer(sdet,_toString(n,"layer%d"),x_layer.id());
+    Tube    l_tub (rmin,2*rmin,z);
+    Volume  l_vol(l_name,l_tub,air);
+    int m = 0;
+
+
+    for(xml_coll_t j(x_layer,_U(slice)); j; ++j, ++m)  {
+      xml_comp_t x_slice = j;
+      Material mat = lcdd.material(x_slice.materialStr());
+      string s_name= l_name+_toString(m,"_slice%d");
+      double thickness = x_slice.thickness();
+
+      //NN: These probably need to be fixed and ced modified to read the extent, rather than the layer
+      //added code by Thorben Quast for event display
+      DDRec::LayeredCalorimeterData::Layer solenoidLayer;
+      solenoidLayer.distance = r;
+
+      solenoidLayer.inner_thickness = thickness/2.;
+      solenoidLayer.outer_thickness = solenoidLayer.inner_thickness ;
+
+      solenoidLayer.cellSize0 = 0;    //equivalent to
+      solenoidLayer.cellSize1 = z;    //half extension along z-axis
+      solenoidData->layers.push_back(solenoidLayer);
+
+      Tube   s_tub(r,r+thickness,z,2*M_PI);
+      Volume s_vol(s_name, s_tub, mat);
+
+      r += thickness;
+      if ( x_slice.isSensitive() ) {
+	sens.setType("tracker");
+	s_vol.setSensitiveDetector(sens);
+      }
+      // Set Attributes
+      s_vol.setAttributes(lcdd,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
+      pv = l_vol.placeVolume(s_vol);
+      // Slices have no extra id. Take the ID of the layer!
+      pv.addPhysVolID("slice",m);
+    }
+    l_tub.setDimensions(rmin,r,z);
+
+    if (rmin < inner_radius)
+      inner_radius = rmin;
+
+    if (z>detZ)
+      detZ = z;
+
+    if (r>outer_radius)
+      outer_radius = r;
+
+    l_vol.setVisAttributes(lcdd,x_layer.visStr());
+
+    pv = envelope.placeVolume(l_vol);
+    pv.addPhysVolID("layer",n);
+    layer.setPlacement(pv);
+  }
+  if ( x_det.hasAttr(_U(combineHits)) ) {
+    sdet.setCombineHits(x_det.combineHits(),sens);
+  }
+
+  /// extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ] in mm.
+  solenoidData->extent[0] = inner_radius ;
+  solenoidData->extent[1] = outer_radius ;
+  solenoidData->extent[2] = 0. ;
+  solenoidData->extent[3] = detZ;
+
+  //added code by Thorben Quast for event display
+  sdet.addExtension< DDRec::LayeredCalorimeterData >( solenoidData ) ;
+
+
+  return sdet;
+
+}
+
+DECLARE_DETELEMENT(DD4hep_Solenoid_o1_v01,create_detector)