Newer
Older
Pere Mato
committed
//====================================================================
// AIDA Detector description implementation for LCD
//--------------------------------------------------------------------
//
// Author : M.Frank
//
//====================================================================
Markus Frank
committed
#include "DD4hep/Plugins.h"
#include "DD4hep/GeoHandler.h"
Markus Frank
committed
#include "DD4hep/InstanceCount.h"
Pere Mato
committed
#include "LCDDImp.h"
Pere Mato
committed
// C/C++ include files
#include <iostream>
#include <stdexcept>
#include "TGeoCompositeShape.h"
#include "TGeoBoolNode.h"
#include "TGeoManager.h"
#include "TGeoMatrix.h"
#include "TGeoVolume.h"
#include "TGeoShape.h"
#include "TClass.h"
Pere Mato
committed
#if DD4HEP_USE_PYROOT
#endif
#ifndef __TIXML__
#include "xercesc/dom/DOMException.hpp"
namespace DD4hep {
namespace XML {
typedef xercesc::DOMException XmlException;
}
}
Pere Mato
committed
#endif
using namespace DD4hep::Geometry;
using namespace DD4hep;
namespace {
struct TopDetElement: public DetElement {
TopDetElement(const string& nam, Volume vol)
: DetElement(nam,/* "structure", */0) {
};
Markus Frank
committed
struct TypePreserve {
LCDDBuildType& m_t;
TypePreserve(LCDDBuildType& t)
: m_t(t) {
}
~TypePreserve() {
m_t = BUILD_NONE;
}
Markus Frank
committed
};
};
typedef map<const type_info*, ExtensionEntry> ExtensionMap;
static int s_extensionID = 0;
ExtensionMap& lcdd_extensions() {
static ExtensionMap s_map;
return s_map;
}
static LCDD* s_lcdd = 0;
}
void lcdd_unexpected(){
try{
throw ;
}catch( std::exception& e){
std::cout << "\n"
<< "**************************************************** \n"
<< "* A runtime error has occured : \n"
<< "* " << e.what() << std::endl
<< "* the program will have to be terminated - sorry. \n"
<< "**************************************************** \n"
<< std::endl ;
// this provokes ROOT seg fault and stack trace (comment out to avoid it)
exit(1) ;
}
}
LCDD& LCDD::getInstance() {
if (!s_lcdd)
s_lcdd = new LCDDImp();
return *s_lcdd;
void LCDD::destroyInstance() {
if (s_lcdd)
delete s_lcdd;
LCDDImp::LCDDImp()
: m_world(), m_trackers(), m_worldVol(), m_trackingVol(), m_field("global"), m_buildType(BUILD_NONE) {
std::set_unexpected( lcdd_unexpected ) ;
std::set_terminate( lcdd_unexpected ) ;
InstanceCount::increment(this);
gGeoManager = new TGeoManager();
}
{
m_manager = gGeoManager;
Markus Frank
committed
m_manager->AddNavigator();
m_manager->SetCurrentNavigator(0);
//cout << "Navigator:" << (void*)m_manager->GetCurrentNavigator() << endl;
Markus Frank
committed
{
gGeoIdentity = new TGeoIdentity();
}
attr.setAlpha(1);
attr.setLineStyle(VisAttr::SOLID);
attr.setDrawingStyle(VisAttr::SOLID);
attr.setVisible(false);
attr.setShowDaughters(true);
addVisAttribute(attr);
m_invisibleVis = attr;
}
/// Standard destructor
LCDDImp::~LCDDImp() {
Markus Frank
committed
destroyHandle(m_world);
destroyHandle(m_field);
destroyHandle(m_header);
destroyHandle(m_volManager);
destroyObject(m_properties);
for_each(m_readouts.begin(), m_readouts.end(), destroyHandles(m_readouts));
for_each(m_idDict.begin(), m_idDict.end(), destroyHandles(m_idDict));
for_each(m_limits.begin(), m_limits.end(), destroyHandles(m_limits));
for_each(m_regions.begin(), m_regions.end(), destroyHandles(m_regions));
for_each(m_alignments.begin(), m_alignments.end(), destroyHandles(m_alignments));
for_each(m_sensitive.begin(), m_sensitive.end(), destroyHandles(m_sensitive));
for_each(m_display.begin(), m_display.end(), destroyHandles(m_display));
for_each(m_fields.begin(), m_fields.end(), destroyHandles(m_fields));
for_each(m_define.begin(), m_define.end(), destroyHandles(m_define));
Markus Frank
committed
m_trackers.clear();
m_worldVol.clear();
m_trackingVol.clear();
m_invisibleVis.clear();
m_materialVacuum.clear();
m_materialAir.clear();
delete m_manager;
InstanceCount::decrement(this);
/// Add an extension object to the detector element
void* LCDDImp::addUserExtension(void* ptr, const std::type_info& info) {
Extensions::iterator j = m_extensions.find(&info);
if (j == m_extensions.end()) {
ExtensionMap& m = lcdd_extensions();
ExtensionMap::iterator i = m.find(&info);
ExtensionEntry entry;
entry.id = ++s_extensionID;
m.insert(make_pair(&info, entry));
i = m.find(&info);
}
ExtensionEntry& e = (*i).second;
//cout << "Extension[" << name() << "]:" << ptr << " " << info.name() << endl;
return m_extensions[&info] = ptr;
}
throw runtime_error("DD4hep: LCDD::addUserExtension: The object "
" already has an extension of type:" + string(info.name()) + ".");
}
/// Access an existing extension object from the detector element
void* LCDDImp::userExtension(const std::type_info& info) const {
Extensions::const_iterator j = m_extensions.find(&info);
if (j != m_extensions.end()) {
return (*j).second;
}
throw runtime_error("DD4hep: LCDD::userExtension: The object "
" has no extension of type:" + string(info.name()) + ".");
Volume LCDDImp::pickMotherVolume(const DetElement&) const { // throw if not existing
return m_worldVol;
}
LCDD& LCDDImp::addDetector(const Ref_t& x) {
m_world.add(DetElement(x));
Pere Mato
committed
/// Typed access to constants: access string values
string LCDDImp::constantAsString(const string& name) const {
Ref_t c = constant(name);
if (c.isValid())
return c->GetTitle();
throw runtime_error("LCDD: The constant " + name + " is not known to the system.");
}
/// Typed access to constants: long values
long LCDDImp::constantAsLong(const string& name) const {
return _toLong(constantAsString(name));
}
/// Typed access to constants: double values
double LCDDImp::constantAsDouble(const string& name) const {
return _toDouble(constantAsString(name));
}
/// Add a field component by named reference to the detector description
LCDD& LCDDImp::addField(const Ref_t& x) {
m_field.add(x);
m_fields.append(x);
return *this;
Markus Frank
committed
/// Retrieve a matrial by it's name from the detector description
Material LCDDImp::material(const string& name) const {
Markus Frank
committed
TGeoMedium* mat = m_manager->GetMedium(name.c_str());
Markus Frank
committed
return Material(Ref_t(mat));
}
throw runtime_error("Cannot find a material the reference name:" + name);
Markus Frank
committed
}
Handle<TObject> LCDDImp::getRefChild(const HandleMap& e, const string& name, bool do_throw) const {
Pere Mato
committed
HandleMap::const_iterator i = e.find(name);
Pere Mato
committed
return (*i).second;
int cnt = 0;
cout << "GetRefChild: Failed to find child with name: " << name
<< " Map contains " << e.size() << " elements." << endl;
for(i=e.begin(); i!=e.end(); ++i)
cout << " " << cnt << " " << (*i).first << endl;
throw runtime_error("Cannot find a child with the reference name:" + name);
Pere Mato
committed
return 0;
namespace {
struct ShapePatcher: public GeoScan {
VolumeManager m_volManager;
DetElement m_world;
ShapePatcher(VolumeManager m, DetElement e)
: GeoScan(e), m_volManager(m), m_world(e) {
}
void patchShapes() {
GeoHandler::Data& data = *m_data;
string nam;
cout << "++ Patching names of anonymous shapes...." << endl;
for (GeoHandler::Data::const_reverse_iterator i = data.rbegin(); i != data.rend(); ++i) {
int level = (*i).first;
const GeoHandler::Data::mapped_type& v = (*i).second;
for (GeoHandler::Data::mapped_type::const_iterator j = v.begin(); j != v.end(); ++j) {
TGeoVolume* v = n->GetVolume();
TGeoShape* s = v->GetShape();
const char* sn = s->GetName();
if (0 == sn || 0 == ::strlen(sn)) {
nam = v->GetName();
nam += "_shape";
s->SetName(nam.c_str());
}
else if (0 == ::strcmp(sn, s->IsA()->GetName())) {
nam = v->GetName();
nam += "_shape";
s->SetName(nam.c_str());
else {
nam = sn;
if (nam.find("_shape") == string::npos)
nam += "_shape";
}
if (s->IsA() == TGeoCompositeShape::Class()) {
TGeoCompositeShape* c = (TGeoCompositeShape*) s;
const TGeoBoolNode* boolean = c->GetBoolNode();
s = boolean->GetLeftShape();
sn = s->GetName();
if (0 == sn || 0 == ::strlen(sn)) {
s->SetName((nam + "_left").c_str());
}
else if (0 == ::strcmp(sn, s->IsA()->GetName())) {
s->SetName((nam + "_left").c_str());
}
s = boolean->GetRightShape();
sn = s->GetName();
if (0 == sn || 0 == ::strlen(sn)) {
s->SetName((nam + "_right").c_str());
}
else if (0 == ::strcmp(s->GetName(), s->IsA()->GetName())) {
s->SetName((nam + "_right").c_str());
};
}
Markus Frank
committed
TGeoManager* mgr = m_manager;
Region trackingRegion("TrackingRegion");
trackingRegion.setThreshold(1);
trackingRegion.setStoreSecondaries(true);
add(trackingRegion);
m_trackingVol.setRegion(trackingRegion);
// Set the tracking volume to invisible.
trackingVis.setVisible(false);
m_trackingVol.setVisAttributes(trackingVis);
#endif
// Set the world volume to invisible.
VisAttr worldVis("WorldVis");
worldVis.setVisible(false);
worldVis.setShowDaughters(true);
worldVis.setColor(1.0, 1.0, 1.0);
worldVis.setLineStyle(VisAttr::SOLID);
worldVis.setDrawingStyle(VisAttr::WIREFRAME);
m_worldVol.setVisAttributes(worldVis);
/// Since we allow now for anonymous shapes,
/// we will rename them to use the name of the volume they are assigned to
mgr->CloseGeometry();
ShapePatcher patcher(m_volManager, m_world);
void LCDDImp::init() {
if (!m_world.isValid()) {
Markus Frank
committed
TGeoManager* mgr = m_manager;
Box worldSolid("world_x", "world_y", "world_z");
std::cout << " *********** created World volume with size : " << worldSolid->GetDX() << ", " << worldSolid->GetDY() << ", "
<< worldSolid->GetDZ() << std::endl;
Material vacuum = material("Vacuum");
Material air = material("Air");
Volume world("world_volume", worldSolid, air);
m_world = TopDetElement("world", world);
m_worldVol = world;
Tube trackingSolid(0.,
_toDouble("tracking_region_radius"),
_toDouble("2*tracking_region_zmax"),2*M_PI);
Markus Frank
committed
Volume tracking("tracking_volume",trackingSolid, air);
m_trackers = TopDetElement("tracking",tracking);
m_trackingVol = tracking;
PlacedVolume pv = m_worldVol.placeVolume(tracking);
m_world.add(m_trackers);
#endif
Markus Frank
committed
m_materialVacuum = vacuum;
m_detectors.append(m_world);
m_manager->SetTopVolume(m_worldVol.ptr());
m_world.setPlacement(PlacedVolume(mgr->GetTopNode()));
Markus Frank
committed
void LCDDImp::fromXML(const string& xmlfile, LCDDBuildType build_type) {
TypePreserve build_type_preserve(m_buildType = build_type);
Pere Mato
committed
#if DD4HEP_USE_PYROOT
Markus Frank
committed
XML::Handle_t xml_root = XML::DocumentHandler().load(xmlfile).root();
Pere Mato
committed
try {
LCDD* lcdd = this;
string type = tag + "_XML_reader";
long result = PluginService::Create<long>(type, lcdd, &xml_root);
if (0 == result) {
Markus Frank
committed
PluginDebug dbg;
result = PluginService::Create<long>(type, lcdd, &xml_root);
if ( 0 == result ) {
throw runtime_error("DD4hep: Failed to locate plugin to interprete files of type"
" \"" + tag + "\" - no factory:" + type + ". " + dbg.missingFactory(type));
}
result = *(long*) result;
if (result != 1) {
throw runtime_error("DD4hep: Failed to parse the XML file " + xmlfile + " with the plugin " + type);
Pere Mato
committed
}
catch (const XML::XmlException& e) {
throw runtime_error(XML::_toString(e.msg) + "\nDD4hep: XML-DOM Exception while parsing " + xmlfile);
}
catch (const exception& e) {
throw runtime_error(string(e.what()) + "\nDD4hep: while parsing " + xmlfile);
catch (...) {
throw runtime_error("DD4hep: UNKNOWN exception while parsing " + xmlfile);
Pere Mato
committed
}
#endif
Markus Frank
committed
TGeoManager* mgr = m_manager;
Pere Mato
committed
mgr->SetVisLevel(4);
mgr->SetVisOption(1);
m_worldVol->Draw("ogl");
}
void LCDDImp::apply(const char* factory_type, int argc, char** argv) {
long result = PluginService::Create<long>(fac, (LCDD*) this, argc, argv);
if (0 == result) {
Markus Frank
committed
PluginDebug dbg;
result = PluginService::Create<long>(fac, (LCDD*) this, argc, argv);
if ( 0 == result ) {
throw runtime_error("DD4hep: apply-plugin: Failed to locate plugin " +
fac + ". " + dbg.missingFactory(fac));
}
result = *(long*) result;
if (result != 1) {
throw runtime_error("DD4hep: apply-plugin: Failed to execute plugin " + fac);
catch (const XML::XmlException& e) {
throw runtime_error(XML::_toString(e.msg) + "\nDD4hep: XML-DOM Exception with plugin:" + fac);
}
catch (const exception& e) {
throw runtime_error(string(e.what()) + "\nDD4hep: with plugin:" + fac);
catch (...) {
throw runtime_error("UNKNOWN exception from plugin:" + fac);