Skip to content
Snippets Groups Projects
DD4hep_GdmlDetector.cpp 3.94 KiB
//==========================================================================
//  AIDA Detector description implementation 
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
// All rights reserved.
//
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
//
// Author     : M.Frank
//
//==========================================================================

// Framework include files
#include "DD4hep/Detector.h"
#include "DD4hep/Memory.h"
#include "DD4hep/DD4hepUI.h"
#include "DD4hep/Factories.h"
#include "DD4hep/Printout.h"
#include "DD4hep/DetectorTools.h"
#include "DD4hep/DetFactoryHelper.h"
#include "XML/DocumentHandler.h"
#include "XML/Utilities.h"

// ROOT includes
#include "TInterpreter.h"
#include "TGeoElement.h"
#include "TGeoManager.h"
#include "TGDMLParse.h"
#include "TGDMLWrite.h"
#include "TUri.h"

using namespace std;
using namespace dd4hep;

#if ROOT_VERSION_CODE >= ROOT_VERSION(6,13,0)

/// Factory to import subdetectors from GDML fragment
static Ref_t create_detector(Detector& description, xml_h e, Ref_t /* sens_det */)  {
  using namespace dd4hep::detail;
  xml_det_t   x_det = e;
  int         id    = x_det.hasAttr(_U(id)) ? x_det.id() : 0;
  xml_dim_t   x_pos  (x_det.child(_U(position),false));
  xml_dim_t   x_rot  (x_det.child(_U(rotation),false));
  xml_dim_t   x_gdml (x_det.child(_U(gdmlFile)));
  xml_dim_t   x_par  (x_det.child(_U(parent)));
  string      name    = x_det.nameStr();
  string      par_nam = x_par.nameStr();
  string      gdml    = x_gdml.attr<string>(_U(ref));
  string      gdml_physvol = dd4hep::getAttrOrDefault<string>(x_gdml, _Unicode(physvol), "");
  DetElement  det_parent = description.detector(par_nam);
  TGDMLParse parser;
  if ( !gdml.empty() && gdml[0] == '/' )  {
    TUri uri(gdml.c_str());
    gdml = uri.GetRelativePart();
  }
  else {
    string path = xml::DocumentHandler::system_path(e, gdml);
    TUri uri(path.c_str());
    gdml = uri.GetRelativePart();
  }
  if ( !det_parent.isValid() )  {
    except(name,"+++ Cannot access detector parent: %s",par_nam.c_str());
  }
  DetElement  sdet(name, id);
  Volume volume = parser.GDMLReadFile(gdml.c_str());
  if ( !volume.isValid() )   {
    except("ROOTGDMLParse","+++ Failed to parse GDML file:%s",gdml.c_str());
  }
  volume.import(); // We require the extensions in dd4hep.
  printout(INFO,"ROOTGDMLParse","+++ Attach GDML volume %s", volume.name());
  Volume mother = det_parent.volume();
  PlacedVolume pv;

  if ( !gdml_physvol.empty() ) {
    PlacedVolume node = volume->FindNode(gdml_physvol.c_str());
    if ( !node.isValid() ) {
      printout(ERROR,"ROOTGDMLParse","+++ Invalid gdml placed volume %s", gdml_physvol.c_str());
      printout(ERROR,"ROOTGDMLParse","+++ Valid top-level nodes are:");
      volume->PrintNodes();
      except("ROOTGDMLParse","+++ Failed to parse GDML file:%s for node:%s",
        gdml.c_str(), gdml_physvol.c_str());
    }
    volume = node.volume();
  }

  if ( x_pos && x_rot )   {
    Rotation3D rot(RotationZYX(x_rot.z(),x_rot.y(),x_rot.x()));
    Transform3D transform(rot,Position(x_pos.x(),x_pos.y(),x_pos.z()));
    pv = mother.placeVolume(volume,transform);
  }
  else if ( x_rot )  {
    Rotation3D rot(RotationZYX(x_rot.z(),x_rot.y(),x_rot.x()));
    Transform3D transform(rot,Position(0,0,0));
    pv = mother.placeVolume(volume,transform);
  }
  else if ( x_pos )   {
    pv = mother.placeVolume(volume,Position(x_pos.x(),x_pos.y(),x_pos.z()));
  }
  else  {
    pv = mother.placeVolume(volume);
  }
  volume.setVisAttributes(description, x_det.visStr());
  volume.setLimitSet(description, x_det.limitsStr());
  volume.setRegion(description, x_det.regionStr());
  if ( id != 0 )  {
    pv.addPhysVolID("system", id);
  }
  sdet.setPlacement(pv);
  return sdet;
}

// first argument is the type from the xml file
DECLARE_DETELEMENT(DD4hep_GdmlDetector,create_detector)

#endif