text: ///////////////////////////////////////////////////////////////////////////////
  // File: DDHCalFibreBundle.cc
  // Description: Create & Position fibre bundles in mother
  ///////////////////////////////////////////////////////////////////////////////
  
  #include <cmath>
  #include <algorithm>
  #include <map>
  #include <string>
  #include <vector>
  
  #include "FWCore/MessageLogger/interface/MessageLogger.h"
  #include "FWCore/PluginManager/interface/PluginFactory.h"
  #include "DataFormats/Math/interface/angle_units.h"
  #include "DetectorDescription/Core/interface/DDutils.h"
  #include "DetectorDescription/Core/interface/DDLogicalPart.h"
  #include "DetectorDescription/Core/interface/DDSolid.h"
  #include "DetectorDescription/Core/interface/DDMaterial.h"
  #include "DetectorDescription/Core/interface/DDCurrentNamespace.h"
  #include "DetectorDescription/Core/interface/DDSplit.h"
  #include "DetectorDescription/Core/interface/DDTypes.h"
  #include "DetectorDescription/Core/interface/DDAlgorithm.h"
  #include "DetectorDescription/Core/interface/DDAlgorithmFactory.h"
  
  //#define EDM_ML_DEBUG
  using namespace angle_units::operators;
  
  class DDHCalFibreBundle : public DDAlgorithm {
  public:
    //Constructor and Destructor
    DDHCalFibreBundle();
    ~DDHCalFibreBundle() override;
  
    void initialize(const DDNumericArguments& nArgs,
                    const DDVectorArguments& vArgs,
                    const DDMapArguments& mArgs,
                    const DDStringArguments& sArgs,
                    const DDStringVectorArguments& vsArgs) override;
  
    void execute(DDCompactView& cpv) override;
  
  private:
    std::string idNameSpace;          //Namespace of this and ALL sub-parts
    std::string childPrefix;          //Prefix to child name
    std::string material;             //Name of the material for bundles
    double deltaZ;                    //Width in  Z  for mother
    double deltaPhi;                  //Width in phi for mother
    int numberPhi;                    //Number of sections in phi
    double tilt;                      //Tilt angle of the readout box
    std::vector<double> areaSection;  //Area of a bundle
    std::vector<double> rStart;       //Radius at start
    std::vector<double> rEnd;         //Radius at End
    std::vector<int> bundle;          //Bundle to be positioned
  };
  
  DDHCalFibreBundle::DDHCalFibreBundle() {
  #ifdef EDM_ML_DEBUG
    edm::LogVerbatim("HCalGeom") << "DDHCalFibreBundle: Creating an instance";
  #endif
  }
  
  DDHCalFibreBundle::~DDHCalFibreBundle() {}
  
  void DDHCalFibreBundle::initialize(const DDNumericArguments& nArgs,
                                     const DDVectorArguments& vArgs,
                                     const DDMapArguments&,
                                     const DDStringArguments& sArgs,
                                     const DDStringVectorArguments&) {
    deltaPhi = nArgs["DeltaPhi"];
    deltaZ = nArgs["DeltaZ"];
    numberPhi = int(nArgs["NumberPhi"]);
    material = sArgs["Material"];
    areaSection = vArgs["AreaSection"];
    rStart = vArgs["RadiusStart"];
    rEnd = vArgs["RadiusEnd"];
    bundle = dbl_to_int(vArgs["Bundles"]);
    tilt = nArgs["TiltAngle"];
  
    idNameSpace = DDCurrentNamespace::ns();
    childPrefix = sArgs["Child"];
  #ifdef EDM_ML_DEBUG
    edm::LogVerbatim("HCalGeom") << "DDHCalFibreBundle: Parent " << parent().name() << " with " << bundle.size()
                                 << " children with prefix " << childPrefix << ", material " << material << " with "
                                 << numberPhi << " bundles along phi; width of"
                                 << " mother " << deltaZ << " along Z, " << convertRadToDeg(deltaPhi)
                                 << " along phi and with " << rStart.size() << " different bundle types";
    for (unsigned int i = 0; i < areaSection.size(); ++i)
      edm::LogVerbatim("HCalGeom") << "DDHCalFibreBundle: Child[" << i << "] Area " << areaSection[i] << " R at Start "
                                   << rStart[i] << " R at End " << rEnd[i];
    edm::LogVerbatim("HCalGeom") << "DDHCalFibreBundle: NameSpace " << idNameSpace << " Tilt Angle "
                                 << convertRadToDeg(tilt) << " Bundle type at different positions";
    for (unsigned int i = 0; i < bundle.size(); ++i) {
      edm::LogVerbatim("HCalGeom") << "DDHCalFibreBundle: Position[" << i << "] "
                                   << " with Type " << bundle[i];
    }
  #endif
  }
  
  void DDHCalFibreBundle::execute(DDCompactView& cpv) {
    DDName mother = parent().name();
    DDName matname(DDSplit(material).first, DDSplit(material).second);
    DDMaterial matter(matname);
  
    // Create the rotation matrices
    double dPhi = deltaPhi / numberPhi;
    std::vector<DDRotation> rotation;
    for (int i = 0; i < numberPhi; ++i) {
      double phi = -0.5 * deltaPhi + (i + 0.5) * dPhi;
      double phideg = convertRadToDeg(phi);
      std::string rotstr = "R0" + std::to_string(phideg);
      DDRotation rot = DDRotation(DDName(rotstr, idNameSpace));
      if (!rot) {
  #ifdef EDM_ML_DEBUG
        edm::LogVerbatim("HCalGeom") << "DDHCalFibreBundle: Creating a new "
                                     << "rotation " << rotstr << "\t" << 90 << "," << phideg << "," << 90 << ","
                                     << (phideg + 90) << ", 0, 0";
  #endif
        rot = DDrot(DDName(rotstr, idNameSpace), 90._deg, phi, 90._deg, (90._deg + phi), 0, 0);
      }
      rotation.emplace_back(rot);
    }
  
    // Create the solids and logical parts
    std::vector<DDLogicalPart> logs;
    for (unsigned int i = 0; i < areaSection.size(); ++i) {
      double r0 = rEnd[i] / std::cos(tilt);
      double dStart = areaSection[i] / (2 * dPhi * rStart[i]);
      double dEnd = areaSection[i] / (2 * dPhi * r0);
      std::string name = childPrefix + std::to_string(i);
      DDSolid solid = DDSolidFactory::cons(DDName(name, idNameSpace),
                                           0.5 * deltaZ,
                                           rStart[i] - dStart,
                                           rStart[i] + dStart,
                                           r0 - dEnd,
                                           r0 + dEnd,
                                           -0.5 * dPhi,
                                           dPhi);
  #ifdef EDM_ML_DEBUG
      edm::LogVerbatim("HCalGeom") << "DDHCalFibreBundle: Creating a new solid " << name << " a cons with dZ " << deltaZ
                                   << " rStart " << rStart[i] - dStart << ":" << rStart[i] + dStart << " rEnd "
                                   << r0 - dEnd << ":" << r0 + dEnd << " Phi " << convertRadToDeg(-0.5 * dPhi) << ":"
                                   << convertRadToDeg(0.5 * dPhi);
  #endif
      DDLogicalPart log(DDName(name, idNameSpace), matter, solid);
      logs.emplace_back(log);
    }
  
    // Now posiiton them
    int copy = 0;
    int nY = (int)(bundle.size()) / numberPhi;
    for (unsigned int i = 0; i < bundle.size(); i++) {
      DDTranslation tran(0, 0, 0);
      int ir = (int)(i) / nY;
      if (ir >= numberPhi)
        ir = numberPhi - 1;
      int ib = bundle[i];
      copy++;
      if (ib >= 0 && ib < (int)(logs.size())) {
        cpv.position(logs[ib], mother, copy, tran, rotation[ir]);
  #ifdef EDM_ML_DEBUG
        edm::LogVerbatim("HCalGeom") << "DDHCalFibreBundle: " << logs[ib].name() << " number " << copy
                                     << " positioned in " << mother << " at " << tran << " with " << rotation[ir];
  #endif
      }
    }
  }
  
  DEFINE_EDM_PLUGIN(DDAlgorithmFactory, DDHCalFibreBundle, "hcal:DDHCalFibreBundle");
  