diff --git a/DDCore/include/DD4hep/GeoHandler.h b/DDCore/include/DD4hep/GeoHandler.h index 3603c30321c780c0562885c4edcf85ffe26e5a0f..7381518816a5dd825003fe8942e28396d593d40b 100644 --- a/DDCore/include/DD4hep/GeoHandler.h +++ b/DDCore/include/DD4hep/GeoHandler.h @@ -37,14 +37,13 @@ namespace DD4hep { struct DetElement; struct SensitiveDetector; - /** @class GeoHandler GeoHandler.h + /** @class GeoHandlerTypes GeoHandler.h * * @author M.Frank * @version 1.0 */ - class GeoHandler { + class GeoHandlerTypes { public: - typedef std::set<TGeoVolume*> VolumeSet; typedef std::vector<TGeoVolume*> VolumeVector; typedef std::set<const TGeoVolume*> ConstVolumeSet; @@ -59,7 +58,6 @@ namespace DD4hep { typedef std::set<TNamed*> Fields; typedef std::set<TNamed*> ObjectSet; typedef LCDD::HandleMap DefinitionSet; - struct GeometryInfo { SolidSet solids; VolumeSet volumeSet; @@ -74,10 +72,18 @@ namespace DD4hep { std::set<TGeoMedium*> media; std::set<TGeoElement*> elements; }; + }; + + /** @class GeoHandler GeoHandler.h + * + * @author M.Frank + * @version 1.0 + */ + class GeoHandler : public GeoHandlerTypes { + protected: Data* m_data; - /// Internal helper to collect geometry information from traversal GeoHandler& i_collect(const TGeoNode* node, int level); diff --git a/DDCore/include/DD4hep/Printout.h b/DDCore/include/DD4hep/Printout.h new file mode 100644 index 0000000000000000000000000000000000000000..930d48c2233d5acab40e8f1a6cbbf03547548e8d --- /dev/null +++ b/DDCore/include/DD4hep/Printout.h @@ -0,0 +1,50 @@ +// $Id: Handle.h 570 2013-05-17 07:47:11Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#ifndef DD4HEP_PRINTOUT_H +#define DD4HEP_PRINTOUT_H + +// C/C++ include files +#include <cstdio> +#include <cstdlib> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + enum PrintLevel { + NOLOG=0, + VERBOSE, + DEBUG, + INFO, + WARNING, + ERROR, + FATAL, + ALWAYS + }; + + typedef size_t (*output_function_t)(void*, PrintLevel severity, const char*, const char*); + + /** Calls the display action + * @arg severity [int,read-only] Display severity flag (see enum) + * @arg src [string,read-only] Information source (component, etc.) + * @arg fmt [string,read-only] Format string for ellipsis args + * @return Status code indicating success or failure + */ + int printout(PrintLevel severity, const char* src, const char* fmt, ...); + + /// Set new print level. Returns the old print level + PrintLevel setPrintLevel(PrintLevel new_level); + + /// Customize printer function + void setPrinter(void* print_arg, output_function_t fcn); + +} /* End namespace DD4hep */ +#endif /* DD4HEP_PRINTOUT_H */ diff --git a/DDCore/include/DD4hep/VolumeManager.h b/DDCore/include/DD4hep/VolumeManager.h index 50904a21f24b0f9a055574bd44bd8494015e878e..0a96fb6dfddb1272dec073ce012d4500ce81b890 100644 --- a/DDCore/include/DD4hep/VolumeManager.h +++ b/DDCore/include/DD4hep/VolumeManager.h @@ -144,6 +144,7 @@ namespace DD4hep { /// Some useful Container abbreviations used by the VolumeManager typedef std::map<VolumeID,VolumeManager> Managers; typedef std::map<DetElement,VolumeManager> Detectors; + typedef std::map<TGeoNode*,Context*> PhysVolumes; typedef std::map<VolIdentifier,Context*> Volumes; /** @class VolumeManager::Object VolumeManager.h DD4hep/lcdd/VolumeManager.h @@ -163,6 +164,8 @@ namespace DD4hep { Managers managers; /// The container of placements managed by this instance Volumes volumes; + /// Map of placed volumes and their corresponding context + PhysVolumes phys_volumes; /// The Detector element handle managed by this instance DetElement detector; /// The ID descriptor object @@ -182,6 +185,8 @@ namespace DD4hep { virtual ~Object(); /// Search the locally cached volumes for a matching ID Context* search(const VolIdentifier& id) const; + /// Search the locally cached volumes for a matching physical volume + Context* search(const PlacedVolume pv) const; }; protected: @@ -219,6 +224,9 @@ namespace DD4hep { /// Register physical volume with the manager and pre-computed volume id bool adoptPlacement(VolumeID volume_id, Context* context); + /** This set of functions is required when reading/analyzing + * already created hits which have a VolumeID attached. + */ /// Lookup the context, which belongs to a registered physical volume. Context* lookupContext(VolumeID volume_id) const throw(); /// Lookup a physical (placed) volume identified by its 64 bit hit ID @@ -229,6 +237,20 @@ namespace DD4hep { DetElement lookupDetElement(VolumeID volume_id) const; /// Access the transformation of a physical volume to the world coordinate system const TGeoMatrix& worldTransformation(VolumeID volume_id) const; + + /** This set of functions is required when reading/analyzing + * already created hits which have a VolumeID attached. + */ + /// Lookup the context, which belongs to a registered physical volume. + Context* lookupContext(PlacedVolume vol) const throw(); + /// Access the physical volume identifier from the placed volume + VolumeID lookupID(PlacedVolume vol) const; + /// Lookup a top level subdetector detector element according to a contained 64 bit hit ID + DetElement lookupDetector(PlacedVolume vol) const; + /// Lookup the closest subdetector detector element in the hierarchy according to a contained 64 bit hit ID + DetElement lookupDetElement(PlacedVolume vol) const; + /// Access the transformation of a physical volume to the world coordinate system + const TGeoMatrix& worldTransformation(PlacedVolume vol) const; }; /// Enable printouts for debugging diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index 5722b5586da341fc3a8fca5e2bf9c7d81bd0fb11..2ed34c77f8ee2f16293f9c79c4ad1e3445a59b69 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -231,17 +231,12 @@ void LCDDImp::endDocument() { TGeoManager* mgr = m_manager; if ( !mgr->IsClosed() ) { LCDD& lcdd = *this; - Material air = material("Air"); - - m_worldVol.setMaterial(air); - m_trackingVol.setMaterial(air); - Region trackingRegion("TrackingRegion"); trackingRegion.setThreshold(1); trackingRegion.setStoreSecondaries(true); add(trackingRegion); m_trackingVol.setRegion(trackingRegion); - + // Set the world volume to invisible. VisAttr worldVis("WorldVis"); worldVis.setVisible(false); @@ -257,7 +252,6 @@ void LCDDImp::endDocument() { /// Since we allow now for anonymous shapes, /// we will rename them to use the name of the volume they are assigned to mgr->CloseGeometry(); - m_world.setPlacement(PlacedVolume(mgr->GetTopNode())); ShapePatcher patcher(m_volManager,m_world); patcher.patchShapes(); } @@ -265,25 +259,28 @@ void LCDDImp::endDocument() { void LCDDImp::init() { if ( !m_world.isValid() ) { + TGeoManager* mgr = m_manager; Box worldSolid("world_box","world_x","world_y","world_z"); Material vacuum = material("Vacuum"); - Volume world("world_volume",worldSolid,vacuum); + Material air = material("Air"); + Volume world("world_volume",worldSolid,air); Tube trackingSolid("tracking_cylinder", 0., _toDouble("tracking_region_radius"), _toDouble("2*tracking_region_zmax"),2*M_PI); - Volume tracking("tracking_volume",trackingSolid, vacuum); + Volume tracking("tracking_volume",trackingSolid, air); m_world = TopDetElement("world",world); m_trackers = TopDetElement("tracking",tracking); m_trackingVol = tracking; m_worldVol = world; PlacedVolume pv = m_worldVol.placeVolume(tracking); m_trackers.setPlacement(pv); - m_materialAir = material("Air"); - m_materialVacuum = material("Vacuum"); + m_materialAir = air; + m_materialVacuum = vacuum; m_detectors.append(m_world); m_world.add(m_trackers); m_manager->SetTopVolume(m_worldVol); + m_world.setPlacement(PlacedVolume(mgr->GetTopNode())); } } diff --git a/DDCore/src/Printout.cpp b/DDCore/src/Printout.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8fa08cff6ac6a7d90ddab2de45ef7cfcc24d913d --- /dev/null +++ b/DDCore/src/Printout.cpp @@ -0,0 +1,57 @@ +// $Id: Geant4Converter.cpp 588 2013-06-03 11:41:35Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#include "DD4hep/Printout.h" +#include <cstdarg> + +static size_t _the_printer(void*, DD4hep::PrintLevel, const char* src, const char* text) { + size_t len = ::fputs(src,stdout); + len += fputs(": ",stdout); + len += fputs(text,stdout); + ::fflush(stdout); + return len; +} + +static DD4hep::PrintLevel print_lvl = DD4hep::INFO; +static void* print_arg = 0; +static DD4hep::output_function_t print_func = _the_printer; + +/** Calls the display action + * @arg severity [int,read-only] Display severity flag + * @arg fmt [string,read-only] Format string for ellipsis args + * @return Status code indicating success or failure + */ +int DD4hep::printout(PrintLevel severity, const char* src, const char* fmt, ...) { + if ( severity >= print_lvl ) { // receives: + va_list args; // - the log level + va_start( args, fmt); // - a standard C formatted + char str[4096]; // string (like printf) + size_t len = vsnprintf(str,sizeof(str)-2,fmt,args); + va_end (args); + str[len] = '\n'; + str[len+1] = '\0'; + print_func(print_arg,severity,src,str); + } + return 1; +} + + + /// Set new print level. Returns the old print level +DD4hep::PrintLevel DD4hep::setPrintLevel(PrintLevel new_level) { + PrintLevel old = print_lvl; + print_lvl = new_level; + return old; +} + +/// Customize printer function +void DD4hep::setPrinter(void* arg, output_function_t fcn) { + print_arg = arg; + print_func = fcn; +} + diff --git a/DDCore/src/VolumeManager.cpp b/DDCore/src/VolumeManager.cpp index a11ae0e1912e7358788e6e96b0c98232260dddee..babf5c3110515a8eb6132656b8f549982707300a 100644 --- a/DDCore/src/VolumeManager.cpp +++ b/DDCore/src/VolumeManager.cpp @@ -11,6 +11,7 @@ // C/C++ includes #include <sstream> +#include <iomanip> using namespace std; using namespace DD4hep::Geometry; @@ -237,6 +238,14 @@ VolumeManager::Context* VolumeManager::Object::search(const VolIdentifier& id) return context; } +/// Search the locally cached volumes for a matching physical volume +VolumeManager::Context* VolumeManager::Object::search(const PlacedVolume pv) const { + PhysVolumes::const_iterator i = phys_volumes.find(pv.ptr()); + if ( i != phys_volumes.end() ) + return (*i).second; + return 0; +} + /// Initializing constructor to create a new object VolumeManager::VolumeManager(const string& nam, DetElement elt, Readout ro, int flags) { @@ -361,6 +370,7 @@ bool VolumeManager::adoptPlacement(VolumeID sys_id, Context* context) { } if ( i == o.volumes.end() ) { o.volumes[vid] = context; + o.phys_volumes[pv.ptr()] = context; #if 0 cout << "Inserted new volume:" << o.volumes.size() << " ID:" << (void*)context->identifier << " Mask:" << (void*)context->mask << endl; @@ -466,7 +476,6 @@ const TGeoMatrix& VolumeManager::worldTransformation(VolumeID volume_id) const return c->toWorld; } -#include <iomanip> /// Enable printouts for debugging std::ostream& DD4hep::Geometry::operator<<(std::ostream& os, const VolumeManager& m) { const VolumeManager::Object& o = *m.data<VolumeManager::Object>(); @@ -496,3 +505,48 @@ std::ostream& DD4hep::Geometry::operator<<(std::ostream& os, const VolumeManager return os; } +/// Lookup the context, which belongs to a registered physical volume. +VolumeManager::Context* VolumeManager::lookupContext(PlacedVolume pv) const throw() { + if ( isValid() ) { + Context* c = 0; + const Object& o = _data(); + if ( o.top != ptr() && (o.flags&ONE) == ONE ) { + return VolumeManager(Ref_t(o.top)).lookupContext(pv); + } + /// First look in our own volume cache if the entry is found. + c = o.search(pv); + if ( c ) return c; + /// Second: look in the subdetector volume cache if the entry is found. + for(Detectors::const_iterator j=o.subdetectors.begin(); j != o.subdetectors.end(); ++j) { + if ( (c=(*j).second._data().search(pv)) != 0 ) + return c; + } + throw runtime_error("VolumeManager::lookupContext: Failed to search Volume context [Unknown identifier]"); + } + throw runtime_error("VolumeManager::lookupContext: Failed to search Volume context [Invalid Handle]"); +} + +/// Access the physical volume identifier from the placed volume +VolumeManager::VolumeID VolumeManager::lookupID(PlacedVolume vol) const { + Context* c = lookupContext(vol); + return c->identifier; +} + +/// Lookup a top level subdetector detector element according to a contained 64 bit hit ID +DetElement VolumeManager::lookupDetector(PlacedVolume vol) const { + Context* c = lookupContext(vol); + return c->detector; +} + +/// Lookup the closest subdetector detector element in the hierarchy according to a contained 64 bit hit ID +DetElement VolumeManager::lookupDetElement(PlacedVolume vol) const { + Context* c = lookupContext(vol); + return c->element; +} + +/// Access the transformation of a physical volume to the world coordinate system +const TGeoMatrix& VolumeManager::worldTransformation(PlacedVolume vol) const { + Context* c = lookupContext(vol); + return c->toWorld; +} + diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index 76a5ecf18385c793d75267ec133b3818dd0603a9..f994c070e4909a23fed915423680a7042fa7f720 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -11,6 +11,7 @@ #include "DD4hep/DetFactoryHelper.h" #include "DD4hep/IDDescriptor.h" #include "DD4hep/FieldTypes.h" +#include "DD4hep/Printout.h" #include "XML/DocumentHandler.h" #include "XML/Conversions.h" @@ -58,7 +59,7 @@ namespace DD4hep { namespace { static UInt_t unique_mat_id = 0xAFFEFEED; void throw_print(const std::string& msg) { - cout << msg << endl; + printout(ERROR,"Compact2Objects",msg.c_str()); throw runtime_error(msg); } @@ -140,18 +141,40 @@ DECLARE_XMLELEMENT(ConstantField,create_ConstantField); static Ref_t create_SolenoidField(lcdd_t& lcdd, xml_h e) { xml_comp_t c(e); + bool has_inner_radius = c.hasAttr(_U(inner_radius)); + bool has_outer_radius = c.hasAttr(_U(outer_radius)); + + if ( !has_inner_radius && !has_outer_radius ) { + throw_print("Compact2Objects[ERROR]: For a solenoidal field at least one of the " + " xml attributes inner_radius of outer_radius MUST be set."); + } CartesianField obj; SolenoidField* ptr = new SolenoidField(); - if ( c.hasAttr(_U(inner_radius)) ) ptr->innerRadius = c.attr<double>(_U(inner_radius)); - else ptr->innerRadius = 0.0; - if ( c.hasAttr(_U(outer_radius)) ) ptr->outerRadius = c.attr<double>(_U(outer_radius)); - else ptr->outerRadius = lcdd.constant<double>("world_side"); + // + // This logic is a bit weird, but has it's origin in the compact syntax: + // If no "inner_radius" is given, the "outer_radius" IS the "inner_radius" + // and the "outer_radius" is given by one side of the world volume's box + // + if ( has_inner_radius && has_outer_radius ) { + ptr->innerRadius = c.attr<double>(_U(inner_radius)); + ptr->outerRadius = c.attr<double>(_U(outer_radius)); + } + else if ( has_inner_radius ) { + Box box = lcdd.worldVolume().solid(); + ptr->innerRadius = c.attr<double>(_U(inner_radius)); + ptr->outerRadius = box.x(); + } + else if ( has_outer_radius ) { + Box box = lcdd.worldVolume().solid(); + ptr->innerRadius = c.attr<double>(_U(outer_radius)); + ptr->outerRadius = box.x(); + } if ( c.hasAttr(_U(inner_field)) ) ptr->innerField = c.attr<double>(_U(inner_field)); if ( c.hasAttr(_U(outer_field)) ) ptr->outerField = c.attr<double>(_U(outer_field)); if ( c.hasAttr(_U(zmax)) ) ptr->maxZ = c.attr<double>(_U(zmax)); else ptr->maxZ = lcdd.constant<double>("world_side"); if ( c.hasAttr(_U(zmin)) ) ptr->minZ = c.attr<double>(_U(zmin)); - else ptr->minZ = - ptr->maxZ; + else ptr->minZ = -ptr->maxZ; obj.assign(ptr,c.nameStr(),c.typeStr()); return obj; } @@ -254,7 +277,7 @@ template <> void Converter<Material>::operator()(xml_h e) const { has_density = false; } - cout << "Creating material " << matname << endl; + printout(DEBUG,"Compact2Objects","++ Creating material %s",matname); mat = mix = new TGeoMixture(matname,composites.size(),dens_val); mat->SetRadLen(radlen_val,intlen_val); for(composites.reset(); composites; ++composites) { @@ -290,8 +313,8 @@ template <> void Converter<Material>::operator()(xml_h e) const { comp_mat = mgr.GetMaterial(nam.c_str()); dens += composites.attr<double>(_U(n)) * comp_mat->GetDensity(); } - cout << "Compact2Objects[WARNING]: Material:" << matname << " with NO density." - << " Set density to:" << dens << " g/cm**3 " << endl; + printout(WARNING,"Compact2Objects","++ Material: %s with NO density. " + "Set density to %7.3 g/cm**3",matname,dens); mix->SetDensity(dens); } } @@ -540,7 +563,8 @@ template <> void Converter<CartesianField>::operator()(xml_h e) const { lcdd.field().properties() = prp; } } - cout << "Converted field: Successfully " << msg << " field " << name << " [" << type << "]" << endl; + printout(ALWAYS,"Compact2Objects","++ Converted field: Successfully %s field %s [%s]", + msg.c_str(),name.c_str(),type.c_str()); } /** Update sensitive detectors from group tags. @@ -605,19 +629,16 @@ template <> void Converter<SensitiveDetector>::operator()(xml_h element) const else if ( ecut ) { // If no unit is given , we assume the correct Geant4 unit is used! sd.setEnergyCutoff(element.attr<double>(ecut)); } - if ( sd.verbose() ) { - cout << "SensitiveDetector-update:" << setw(18) << left << sd.name() - << setw(24) << left << " ["+sd.type()+"] " - << "Hits:" << setw(24) << left << sd.hitsCollection() - << "Cutoff:" << sd.energyCutoff() - << endl; - } + printout(DEBUG,"Compact2Objects","SensitiveDetector-update: %-18s %-24s Hits:%-24s Cutoff:%f7.3f", + sd.name(),(" ["+sd.type()+"]").c_str(),sd.hitsCollection().c_str(),sd.energyCutoff()); } catch(const exception& e) { - cout << "FAILED to convert sensitive detector:" << name << ": " << e.what() << endl; + printout(ERROR,"Compact2Objects","++ FAILED to convert sensitive detector: %s: %s", + name.c_str(),e.what()); } catch(...) { - cout << "FAILED to convert sensitive detector:" << name << ": UNKNONW Exception" << endl; + printout(ERROR,"Compact2Objects","++ FAILED to convert sensitive detector: %s: %s", + name.c_str(),"UNKNONW Exception"); } } @@ -668,10 +689,10 @@ template <> void Converter<DetElement>::operator()(xml_h element) const { lcdd.addDetector(det); } catch(const exception& e) { - cout << "FAILED to convert subdetector:" << name << " of type " << type << ": " << e.what() << endl; + printout(ERROR,"Compact2Objects","++ FAILED to convert subdetector: %s: %s",name.c_str(),e.what()); } catch(...) { - cout << "FAILED to convert subdetector:" << name << " of type " << type << ": UNKNONW Exception" << endl; + printout(ERROR,"Compact2Objects","++ FAILED to convert subdetector: %s: %s",name.c_str(),"UNKNONW Exception"); } } diff --git a/DDExamples/CLICSiDSimu/src/SteppingAction.cpp b/DDExamples/CLICSiDSimu/src/SteppingAction.cpp index d463331797acdc4f0ed2b031231e79437804b089..b09800aac66b751643aeafe9d0fef1d8e654ca14 100644 --- a/DDExamples/CLICSiDSimu/src/SteppingAction.cpp +++ b/DDExamples/CLICSiDSimu/src/SteppingAction.cpp @@ -22,8 +22,7 @@ SteppingAction::~SteppingAction() void SteppingAction::UserSteppingAction(const G4Step* aStep) { Geant4StepHandler step(aStep); - Geant4Converter& cnv = Geant4Converter::instance(); - Geant4Converter::G4GeometryInfo& data = cnv.data(); + Geant4Mapping& mapping = Geant4Mapping::instance(); SiMaterial = G4Material::GetMaterial("Silicon"); TPCGasMaterial = G4Material::GetMaterial("Argon"); @@ -65,16 +64,15 @@ void SteppingAction::UserSteppingAction(const G4Step* aStep) { ::printf(" post-Vol:%s Status:%s SD:%s\n", step.volName(step.post,"----"), step.postStepStatus(), step.sdName(step.post,"----")); #endif - const G4VPhysicalVolume* pv = step.volume(step.post); - typedef Geant4Converter::PlacementMap Places; - const Places& places = cnv.data().g4Placements; - for(Places::const_iterator i=places.begin(); i!=places.end();++i) { - const G4PVPlacement* pl = (*i).second; - const G4VPhysicalVolume* qv = pl; - if ( qv == pv ) { - const TGeoNode* tpv = (*i).first; - //printf(" Found TGeoNode:%s!\n",tpv->GetName()); - } + const G4VPhysicalVolume* pv = step.volume(step.post); + Geometry::PlacedVolume place = mapping.placement(pv); + if ( place.isValid() ) { + if ( place.volume().isSensitive() ) { + // Example code to access the physical vlume and the cell id + Geometry::VolumeManager vm = mapping.lcdd().volumeManager(); + Geometry::VolumeManager::VolumeID cell_id = vm.lookupID(place); + //const TGeoNode* tpv = pv.ptr(); + printf(" Found Sensitive TGeoNode:%s CellID: %lld!\n",place.name(),cell_id); + } } - } diff --git a/DDExamples/ILDExDet/compact/ILDEx.xml b/DDExamples/ILDExDet/compact/ILDEx.xml index 9293816025e4b30d8a0df478b741fcbc0af669cb..a43092bb078685ed64ffd7bf9ec12e8871a7acee 100644 --- a/DDExamples/ILDExDet/compact/ILDEx.xml +++ b/DDExamples/ILDExDet/compact/ILDEx.xml @@ -56,6 +56,12 @@ <limitset name="cal_limits"> <limit name="step_length_max" particles="*" value="5.0" unit="mm" /> </limitset> + <limitset name="TPC_limits"> + <limit name="step_length_max" particles="*" value="10.0" unit="mm" /> + </limitset> + <limitset name="Tracker_limits"> + <limit name="step_length_max" particles="*" value="5.0" unit="mm" /> + </limitset> </limits> <display> @@ -78,7 +84,7 @@ <detectors> <comment>Trackers</comment> - <detector name="VXD" type="ILDExVXD" vis="VXDVis" id="1" readout="VXDCollection" insideTrackingVolume="true"> + <detector name="VXD" type="ILDExVXD" vis="VXDVis" id="1" limits="Tracker_limits" readout="VXDCollection" insideTrackingVolume="true"> <layer id="0" vis="VXDLayerVis" phi0="-1.570796327e+00"> <support thickness=".1*mm" material="Carbon" vis="VXDSupportVis"/> <ladder zhalf="65*mm" radius="1.595000000e+01*mm" width="1.100000000e+01*mm" offset="-1.874869853e+00*mm" thickness="0.05*mm" material="Silicon" number="10"/> @@ -105,7 +111,7 @@ </layer> </detector> - <detector name="SIT" type="ILDExSIT" vis="SITVis" id="2" readout="SITCollection" insideTrackingVolume="true"> + <detector name="SIT" type="ILDExSIT" vis="SITVis" id="2" limits="Tracker_limits" readout="SITCollection" insideTrackingVolume="true"> <layer id="0" vis="SITLayerVis"> <support thickness="0.01*mm" material="Carbon" vis="SITSupportVis"/> <ladder thickness="0.1*mm" zhalf="370*mm" radius="155*mm" material="Silicon" number="10" /> @@ -117,7 +123,7 @@ </detector> - <detector name="TPC" type="ILDExTPCXXX" vis="TPCVis" id="3" readout="TPCCollection" insideTrackingVolume="true"> + <detector name="TPC" type="ILDExTPC" vis="TPCVis" id="3" limits="TPC_limits" readout="TPCCollection" insideTrackingVolume="true"> <tubs rmin="TPC_inner_radius" rmax="TPC_outer_radius" zhalf="TPC_zhalf"/> <!-- GEAR Data--> <driftlength value="TPC_zhalf*0.9"/> diff --git a/DDExamples/ILDExDet/src/compact/ILDExSIT_geo.cpp b/DDExamples/ILDExDet/src/compact/ILDExSIT_geo.cpp index d619763c614a47dfa4b9d4dc98d39ad0f0ff885d..83244b8be823d5c7b89aaf33f2830bf6d7777cc7 100644 --- a/DDExamples/ILDExDet/src/compact/ILDExSIT_geo.cpp +++ b/DDExamples/ILDExDet/src/compact/ILDExSIT_geo.cpp @@ -57,9 +57,9 @@ static Ref_t create_element(LCDD& lcdd, xml_h e, SensitiveDetector sens) { Position senspos (-(sens_thick+supp_thick)/2.+sens_thick/2.,0,0); Position supppos (-(sens_thick+supp_thick)/2.+sens_thick+supp_thick/2.,0,0); - sensvol.setVisAttributes(lcdd.visAttributes(x_layer.visStr())); sens.setType("tracker"); sensvol.setSensitiveDetector(sens); + sensvol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_layer.visStr()); pv = laddervol.placeVolume(sensvol,senspos) ; laddervol.placeVolume(suppvol,supppos); diff --git a/DDExamples/ILDExDet/src/compact/ILDExTPC_geo.cpp b/DDExamples/ILDExDet/src/compact/ILDExTPC_geo.cpp index 0731a058ed13890ccd12a0e6c81ee23969c6ffd0..ac16e2806ef4a70f415fe9663d8ace2f1b9717c6 100644 --- a/DDExamples/ILDExDet/src/compact/ILDExTPC_geo.cpp +++ b/DDExamples/ILDExDet/src/compact/ILDExTPC_geo.cpp @@ -32,7 +32,7 @@ static Ref_t create_element(LCDD& lcdd, xml_h e, SensitiveDetector sens) { Tube tpc_tub(x_tube.rmin(),x_tube.rmax(),x_tube.zhalf()); Volume tpc_vol(name+"_envelope_volume", tpc_tub, mat); Readout readout(sens.readout()); - + for(xml_coll_t c(e,_U(detector)); c; ++c) { xml_comp_t px_det (c); xml_comp_t px_tube (px_det.child(_U(tubs))); @@ -128,7 +128,8 @@ static Ref_t create_element(LCDD& lcdd, xml_h e, SensitiveDetector sens) { tpc.add(rdet); } }//subdetectors - tpc_vol.setVisAttributes(lcdd, x_det.visStr()); + tpc_vol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); + PlacedVolume phv = lcdd.pickMotherVolume(tpc).placeVolume(tpc_vol); tpc.setPlacement(phv); return tpc; diff --git a/DDExamples/ILDExDet/src/compact/ILDExVXD_geo.cpp b/DDExamples/ILDExDet/src/compact/ILDExVXD_geo.cpp index 1904a970960092dac56872b166fdd0b4cb06e7b1..73c45caa07d2690f4f05330a707fa2d91a9a49f9 100644 --- a/DDExamples/ILDExDet/src/compact/ILDExVXD_geo.cpp +++ b/DDExamples/ILDExDet/src/compact/ILDExVXD_geo.cpp @@ -76,9 +76,10 @@ static Ref_t create_element(LCDD& lcdd, xml_h e, SensitiveDetector sens) { Position senspos (-(sens_thick+supp_thick)/2.+sens_thick/2.,0,0); Position supppos (-(sens_thick+supp_thick)/2.+sens_thick+supp_thick/2.,0,0); - sensvol.setVisAttributes(lcdd.visAttributes(x_layer.visStr())); sens.setType("tracker"); sensvol.setSensitiveDetector(sens); + sensvol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_layer.visStr()); + laddervol.placeVolume(sensvol,senspos); laddervol.placeVolume(suppvol,supppos); diff --git a/DDExamples/ILDExSimu/run1.mac b/DDExamples/ILDExSimu/run1.mac index 432ab77ac45a1d8e00bca48d3e6252bde632c442..1b84c5acbbd90e350885a6b9711eb7d028bdb50c 100644 --- a/DDExamples/ILDExSimu/run1.mac +++ b/DDExamples/ILDExSimu/run1.mac @@ -15,9 +15,8 @@ # muon 300 MeV to the direction (1.,0.,0.) # 3 events # -/generator/select gun - +##/generator/select gun /gun/direction 1. 1. 1. -/gun/particle mu+ -/gun/energy 1000 MeV +/gun/particle pi+ +/gun/energy 100 MeV /run/beamOn 3 diff --git a/DDG4/include/DDG4/Geant4Converter.h b/DDG4/include/DDG4/Geant4Converter.h index 052c4636541cef771127dca5e9f283363072191b..f9dadc625dd15ffef266b5fc9bab0768eebd4461 100644 --- a/DDG4/include/DDG4/Geant4Converter.h +++ b/DDG4/include/DDG4/Geant4Converter.h @@ -10,31 +10,7 @@ #define DD4HEP_GEANT4CONVERTER_H // Framework include files -#include "DD4hep/GeoHandler.h" -#include "DD4hep/LCDD.h" - -// C/C++ include files -#include <set> -#include <map> -#include <vector> - -// Forward declarations -class TGeoVolume; -class TGeoElement; -class TGeoShape; -class TGeoMedium; -class TGeoNode; - -class G4Element; -class G4Material; -class G4VSolid; -class G4LogicalVolume; -class G4PVPlacement; -class G4Region; -class G4Field; -class G4FieldManager; -class G4UserLimits; -class G4VisAttributes; +#include "DDG4/Geant4Mapping.h" /* * DD4hep namespace declaration @@ -46,9 +22,6 @@ namespace DD4hep { */ namespace Simulation { - - class Geant4SensitiveDetector; - /** @class Geant4Converter Geant4Converter.h DDG4/Geant4Converter.h * * Geometry converter from DD4hep to Geant 4. @@ -56,51 +29,17 @@ namespace DD4hep { * @author M.Frank * @version 1.0 */ - struct Geant4Converter : public Geometry::GeoHandler { - typedef Geometry::LCDD LCDD; - typedef Geometry::DetElement DetElement; - typedef std::map<const TGeoElement*,G4Element*> ElementMap; - typedef std::map<const TGeoMedium*, G4Material*> MaterialMap; - typedef std::map<const TNamed*, G4UserLimits*> LimitMap; - typedef std::map<const TGeoNode*, G4PVPlacement*> PlacementMap; - typedef std::map<const TNamed*, G4Region*> RegionMap; - typedef std::map<const TNamed*, Geant4SensitiveDetector*> SensDetMap; - typedef std::map<const TGeoVolume*, G4LogicalVolume*> VolumeMap; - typedef std::map<const TGeoShape*, G4VSolid*> SolidMap; - typedef std::map<const TNamed*, G4VisAttributes*> VisMap; - struct G4GeometryInfo : public GeometryInfo { - ElementMap g4Elements; - MaterialMap g4Materials; - SolidMap g4Solids; - VolumeMap g4Volumes; - PlacementMap g4Placements; - RegionMap g4Regions; - VisMap g4Vis; - LimitMap g4Limits; - SensDetMap g4SensDets; - - SensitiveVolumes sensitives; - RegionVolumes regions; - LimitVolumes limits; - }; - - LCDD& m_lcdd; + struct Geant4Converter : public Geometry::GeoHandler, public Geant4Mapping { bool m_checkOverlaps; - G4GeometryInfo* m_dataPtr; - G4GeometryInfo& data() const { return *m_dataPtr; } - /// Initializing Constructor Geant4Converter( LCDD& lcdd ); /// Standard destructor - virtual ~Geant4Converter() {} - - /// Singleton instance - static Geant4Converter& instance(); + virtual ~Geant4Converter(); /// Create geometry conversion - void create(DetElement top); + Geant4Converter& create(DetElement top); /// Convert the geometry type material into the corresponding Geant4 object(s). virtual void* handleMaterial(const std::string& name, const TGeoMedium* medium) const; @@ -140,8 +79,6 @@ namespace DD4hep { virtual void* printSensitive(const TNamed* sens_det, const std::set<const TGeoVolume*>& volumes) const; /// Print Geant4 placement virtual void* printPlacement(const std::string& name, const TGeoNode* node) const; - - }; } // End namespace Simulation } // End namespace DD4hep diff --git a/DDG4/include/DDG4/Geant4Mapping.h b/DDG4/include/DDG4/Geant4Mapping.h new file mode 100644 index 0000000000000000000000000000000000000000..0b996b0d091e309cce8f861b7c2b15612661f4f3 --- /dev/null +++ b/DDG4/include/DDG4/Geant4Mapping.h @@ -0,0 +1,128 @@ +// $Id: Geant4Mapping.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEANT4MAPPING_H +#define DD4HEP_GEANT4MAPPING_H + +// Framework include files +#include "DD4hep/GeoHandler.h" +#include "DD4hep/LCDD.h" + +// C/C++ include files +#include <set> +#include <map> +#include <vector> + +// Forward declarations +class TGeoVolume; +class TGeoElement; +class TGeoShape; +class TGeoMedium; +class TGeoNode; + +class G4Element; +class G4Material; +class G4VSolid; +class G4LogicalVolume; +class G4PVPlacement; +class G4Region; +class G4Field; +class G4FieldManager; +class G4UserLimits; +class G4VisAttributes; +class G4VPhysicalVolume; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Simulation namespace declaration + */ + namespace Simulation { + + class Geant4SensitiveDetector; + + /** @class Geant4Mapping Geant4Mapping.h DDG4/Geant4Mapping.h + * + * Geometry mapping from DD4hep to Geant 4. + * + * @author M.Frank + * @version 1.0 + */ + struct Geant4Mapping : public Geometry::GeoHandlerTypes { + public: + typedef Geometry::LCDD LCDD; + typedef Geometry::DetElement DetElement; + typedef Geometry::SensitiveDetector SensitiveDetector; + typedef Geometry::Solid Solid; + typedef Geometry::Volume Volume; + typedef Geometry::PlacedVolume PlacedVolume; + typedef Geometry::Material Material; + typedef Geometry::Region Region; + + typedef std::map<const TGeoElement*,G4Element*> ElementMap; + typedef std::map<const TGeoMedium*, G4Material*> MaterialMap; + typedef std::map<const TNamed*, G4UserLimits*> LimitMap; + typedef std::map<const TGeoNode*, G4PVPlacement*> PlacementMap; + typedef std::map<const TNamed*, G4Region*> RegionMap; + typedef std::map<const TNamed*, Geant4SensitiveDetector*> SensDetMap; + typedef std::map<const TGeoVolume*, G4LogicalVolume*> VolumeMap; + typedef std::map<const TGeoShape*, G4VSolid*> SolidMap; + typedef std::map<const TNamed*, G4VisAttributes*> VisMap; + struct G4GeometryInfo : public GeometryInfo { + ElementMap g4Elements; + MaterialMap g4Materials; + SolidMap g4Solids; + VolumeMap g4Volumes; + PlacementMap g4Placements; + RegionMap g4Regions; + VisMap g4Vis; + LimitMap g4Limits; + SensDetMap g4SensDets; + + SensitiveVolumes sensitives; + RegionVolumes regions; + LimitVolumes limits; + }; + protected: + LCDD& m_lcdd; + G4GeometryInfo* m_dataPtr; + + /// When resolving pointers, we must check for the validity of the data block + void checkValidity() const; + public: + /// Access to the data pointer + G4GeometryInfo& data() const { return *m_dataPtr; } + /// Release data and pass over the ownership + G4GeometryInfo* detach(); + /// Set a new data block + void attach(G4GeometryInfo* data); + /// Initializing Constructor + Geant4Mapping(LCDD& lcdd, G4GeometryInfo* data); + /// Standard destructor + virtual ~Geant4Mapping(); + /// Possibility to define a singleton instance + static Geant4Mapping& instance(); + + /// Accesor to the LCDD instance + LCDD& lcdd() const { return m_lcdd; } + + /// Accessor to resolve G4 placements + G4PVPlacement* g4Placement(const TGeoNode* node) const; + /// Accessor to resolve geometry placements + PlacedVolume placement(const G4VPhysicalVolume* node) const; + + + + }; + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_GEANT4MAPPING_H diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 78608c25e472ea83d004f070e94943f1e7daf93b..03f458b75997a5a441bd866899e18b45e82dedde 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -9,6 +9,7 @@ #include "DD4hep/LCDD.h" #include "DD4hep/Volumes.h" +#include "DD4hep/Printout.h" #include "DDG4/Geant4Field.h" #include "DDG4/Geant4Converter.h" #include "DDG4/Geant4SensitiveDetector.h" @@ -16,9 +17,9 @@ // ROOT includes #include "TROOT.h" #include "TColor.h" +#include "TGeoNode.h" #include "TGeoShape.h" #include "TGeoCone.h" -#include "TGeoParaboloid.h" #include "TGeoPcon.h" #include "TGeoPgon.h" #include "TGeoSphere.h" @@ -29,13 +30,12 @@ #include "TGeoArb8.h" #include "TGeoMatrix.h" #include "TGeoBoolNode.h" +#include "TGeoParaboloid.h" #include "TGeoCompositeShape.h" -#include "TGeoNode.h" +#include "TGeoShapeAssembly.h" #include "TClass.h" #include "TMath.h" #include "Reflex/PluginService.h" -#include <iostream> -#include <iomanip> #include "G4VisAttributes.hh" #include "G4ProductionCuts.hh" @@ -43,6 +43,8 @@ // Geant4 include files #include "G4Element.hh" #include "G4SDManager.hh" +#include "G4Assembly.hh" +#include "G4AssemblyVolume.hh" #include "G4Box.hh" #include "G4Trd.hh" #include "G4Tubs.hh" @@ -70,6 +72,10 @@ #include "G4ElectroMagneticField.hh" #include "G4FieldManager.hh" +#include <iostream> +#include <iomanip> +#include <sstream> + using namespace DD4hep::Simulation; using namespace DD4hep::Geometry; using namespace DD4hep; @@ -90,11 +96,8 @@ namespace { TGeoMedium* m = v->GetMedium(); TGeoShape* s = v->GetShape(); string nam; - cout << "Node:'" << n->GetName() - << "' Vol:'" << v->GetName() - << "' Shape:'" << s->GetName() - << "' Medium:'" << m->GetName() - << "'" << endl; + printout(DEBUG,"G4","TGeoNode:'%s' Vol:'%s' Shape:'%s' Medium:'%s'", + n->GetName(),v->GetName(),s->GetName(),m->GetName()); } class G4UserRegionInformation : public G4VUserRegionInformation { @@ -105,23 +108,22 @@ namespace { G4UserRegionInformation() : threshold(0.0), storeSecondaries(false) {} virtual ~G4UserRegionInformation() {} virtual void Print() const { - if ( region.isValid() ) cout << "Region:" << region.name() << endl; + if ( region.isValid() ) + printout(DEBUG,"Region","Name:%s",region.name()); } }; - } /// Initializing Constructor -Geant4Converter::Geant4Converter( LCDD& lcdd ) : m_lcdd(lcdd) { - m_checkOverlaps = true; +Geant4Converter::Geant4Converter( LCDD& lcdd ) + : Geant4Mapping(lcdd,new G4GeometryInfo()), m_checkOverlaps(true) +{ } -#if 0 -/// Dump element in GDML format to output stream -void* Geant4Converter::printElement(const string& name, const TGeoElement* element) const { - G4Element* g4e = G4Element::GetElement(name,false); +/// Standard destructor +Geant4Converter::~Geant4Converter() { } -#endif + /// Dump element in GDML format to output stream void* Geant4Converter::handleElement(const string& name, const TGeoElement* element) const { G4Element* g4e = data().g4Elements[element]; @@ -142,7 +144,9 @@ void* Geant4Converter::handleElement(const string& name, const TGeoElement* elem else { g4e = new G4Element(element->GetTitle(),name,element->Z(),element->A()*(g/mole)); } - cout << "Created G4 " << (*g4e) << endl; + stringstream str; + str << (*g4e); + printout(DEBUG,"Geant4Converter","++ Created G4 Element:%s",str.str().c_str()); } data().g4Elements[element] = g4e; } @@ -188,8 +192,8 @@ void* Geant4Converter::handleMaterial(const string& name, const TGeoMedium* medi TGeoElement* e = mix->GetElement(i); G4Element* g4e = (G4Element*)handleElement(e->GetName(),e); if ( !g4e ) { - cout << "ERROR: Missing component " << e->GetName() - << " for material " << mix->GetName() << endl; + printout(ERROR,"Material","Missing component %s for material %s.", + e->GetName(), mix->GetName()); } mat->AddElement(g4e,(mix->GetAmixt())[i]/A_total); } @@ -198,7 +202,9 @@ void* Geant4Converter::handleMaterial(const string& name, const TGeoMedium* medi mat = new G4Material(name,m->GetZ(),m->GetA(),density,state, m->GetTemperature(),m->GetPressure()); } - cout << "Created G4 " << *mat << endl; + stringstream str; + str << (*mat); + printout(DEBUG,"Geant4Converter","++ Created G4 Material:%s",str.str().c_str()); } data().g4Materials[medium] = mat; } @@ -207,19 +213,21 @@ void* Geant4Converter::handleMaterial(const string& name, const TGeoMedium* medi /// Dump solid in GDML format to output stream void* Geant4Converter::handleSolid(const string& name, const TGeoShape* shape) const { - G4VSolid* solid = data().g4Solids[shape]; - if ( !solid && shape ) { - if ( shape->IsA() == TGeoBBox::Class() ) { + G4VSolid* solid = 0; + if ( shape ) { + if ( 0 != (solid=data().g4Solids[shape]) ) { + return solid; + } + else if ( shape->IsA() == TGeoShapeAssembly::Class() ) { + solid = (G4VSolid*)new G4Assembly(); + } + else if ( shape->IsA() == TGeoBBox::Class() ) { const TGeoBBox* s = (const TGeoBBox*)shape; - G4Box* box = new G4Box(name,s->GetDX()*CM_2_MM,s->GetDY()*CM_2_MM,s->GetDZ()*CM_2_MM); - solid = box; - //::printf("ROOT Box: %s x=%f y=%f z=%f\n",name.c_str(),s->GetDX(),s->GetDY(),s->GetDZ()); - //::printf(" +-->G4 Box: %s x=%f y=%f z=%f\n",name.c_str(),box->GetXHalfLength(),box->GetYHalfLength(),box->GetZHalfLength()); + solid = new G4Box(name,s->GetDX()*CM_2_MM,s->GetDY()*CM_2_MM,s->GetDZ()*CM_2_MM); } else if ( shape->IsA() == TGeoTube::Class() ) { const TGeoTube* s = (const TGeoTube*)shape; solid = new G4Tubs(name,s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM,s->GetDz()*CM_2_MM,0,2.*M_PI); - //::printf("Convert Tube: %s r=%f r=%f z=%f\n",name.c_str(),s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM,s->GetDz()*CM_2_MM,0,2.*M_PI); } else if ( shape->IsA() == TGeoTubeSeg::Class() ) { const TGeoTubeSeg* s = (const TGeoTubeSeg*)shape; @@ -337,24 +345,22 @@ void* Geant4Converter::handleVolume(const string& name, const TGeoVolume* volume G4GeometryInfo& info = data(); G4LogicalVolume* vol = info.g4Volumes[volume]; if ( !vol ) { - const TGeoVolume* v = volume; - Volume _v = Ref_t(v); - VisAttr vis = _v.visAttributes(); - string n = v->GetName(); - TGeoMedium* m = v->GetMedium(); - TGeoShape* s = v->GetShape(); - G4VSolid* solid = (G4VSolid*)handleSolid(s->GetName(),s); - G4Material* medium = (G4Material*)handleMaterial(m->GetName(),m); - if ( !solid ) { - throw runtime_error("G4Converter: No Geant4 Solid present for volume:"+n); - } - if ( !medium ) { - throw runtime_error("G4Converter: No Geant4 material present for volume:"+n); - } + const TGeoVolume* v = volume; + Volume _v = Ref_t(v); + VisAttr vis = _v.visAttributes(); + string n = v->GetName(); + TGeoMedium* m = v->GetMedium(); + TGeoShape* s = v->GetShape(); + G4VSolid* solid = (G4VSolid*)handleSolid(s->GetName(),s); + G4Material* medium = 0; + SensitiveDetector det = _v.sensitiveDetector(); + bool assembly = s->IsA() == TGeoShapeAssembly::Class(); + Geant4SensitiveDetector* sd = 0; + G4VisAttributes* vis_attr = 0; + + printout(INFO,"Geant4Converter","++ Convert Volume %-32s: %p %s/%s assembly:%s", + n.c_str(),v,s->IsA()->GetName(),v->IsA()->GetName(),(assembly ? "YES" : "NO")); - //Region reg = _v.region(); - SensitiveDetector det = _v.sensitiveDetector(); - Geant4SensitiveDetector* sd = 0; if ( det.isValid() ) { sd = info.g4SensDets[det.ptr()]; if ( !sd ) { @@ -364,28 +370,58 @@ void* Geant4Converter::handleVolume(const string& name, const TGeoVolume* volume sd->Activate(true); } LimitSet lim = _v.limitSet(); - G4UserLimits* l = 0; + G4UserLimits* user_limits = 0; if ( lim.isValid() ) { - l = info.g4Limits[lim.ptr()]; - if ( !l ) { + user_limits = info.g4Limits[lim.ptr()]; + if ( !user_limits ) { throw runtime_error("G4Cnv::volume["+name+"]: + FATAL Failed to " "access Geant4 user limits."); } } - vol = new G4LogicalVolume(solid,medium,n,0,sd,l); if ( vis.isValid() ) { - G4VisAttributes* attr = (G4VisAttributes*)handleVis(vis.name(),vis.ptr()); - if ( attr ) vol->SetVisAttributes(attr); + vis_attr = (G4VisAttributes*)handleVis(vis.name(),vis.ptr()); + } + Region reg = _v.region(); + G4Region* region = 0; + if ( reg.isValid() ) { + region = info.g4Regions[reg.ptr()]; + if ( !region ) { + throw runtime_error("G4Cnv::volume["+name+"]: + FATAL Failed to " + "access Geant4 region."); + } } - info.g4Volumes[v] = vol; - if ( sd ) { - cout << "G4Cnv::volume: + " << name << " <> " << vol->GetName() - << " Solid:" << solid->GetName() << " Mat:" << medium->GetName() - << " SD:" << sd->GetName() - << endl; + if ( assembly ) { + vol = (G4LogicalVolume*)new G4AssemblyVolume(); + info.g4Volumes[v] = vol; + return vol; + } + medium = (G4Material*)handleMaterial(m->GetName(),m); + if ( !solid ) { + throw runtime_error("G4Converter: No Geant4 Solid present for volume:"+n); + } + if ( !medium ) { + throw runtime_error("G4Converter: No Geant4 material present for volume:"+n); + } + if ( user_limits ) { + printout(DEBUG,"++ Volume + Apply LIMITS settings:%-24s to volume %s.",lim.name(),_v.name()); + } + vol = new G4LogicalVolume(solid,medium,n,0,sd,user_limits); + if ( region ) { + printout(INFO,"Geant4Converter","++ Volume + Apply REGION settings: %s to volume %s.",reg.name(),_v.name()); + vol->SetRegion(region); + region->AddRootLogicalVolume(vol); } - //cout << "Converted logical volume [" << n << "]:" << v.ptr() << " ---> G4 " << vol << endl; + if ( vis_attr ) { + vol->SetVisAttributes(vis_attr); + } + if ( sd ) { + printout(INFO,"Geant4Converter","++ Volume: + %s <> %s Solid:%s Mat:%s SD:%s", + name.c_str(),vol->GetName().c_str(),solid->GetName().c_str(), + medium->GetName().c_str(),sd->GetName().c_str()); + } + info.g4Volumes[v] = vol; + printout(INFO,"Geant4Converter", "++ Volume + %s converted: %p ---> G4: %p",n.c_str(),v,vol); } return vol; } @@ -410,8 +446,10 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) G4GeometryInfo& info = data(); G4PVPlacement* g4 = info.g4Placements[node]; if ( !g4 ) { - TGeoMatrix* trafo = node->GetMatrix(); - int copy = node->GetNumber(); + TGeoVolume* mot_vol = node->GetMotherVolume(); + TGeoVolume* vol = node->GetVolume(); + TGeoMatrix* trafo = node->GetMatrix(); + int copy = node->GetNumber(); // if the CellID0 volID is defined for the volume we // use it to overwrite the copy number @@ -427,33 +465,55 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) copy = it->second ; } //-------------------------------------------------------- - G4LogicalVolume* vol = info.g4Volumes[node->GetVolume()]; - G4LogicalVolume* mot = info.g4Volumes[node->GetMotherVolume()]; + G4LogicalVolume* g4vol = info.g4Volumes[vol]; + G4LogicalVolume* g4mot = info.g4Volumes[mot_vol]; + G4AssemblyVolume* ass_mot = (G4AssemblyVolume*)g4mot; + G4AssemblyVolume* ass_dau = (G4AssemblyVolume*)g4vol; + bool daughter_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class(); + bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() : false; if ( trafo ) { const Double_t* trans = trafo->GetTranslation(); + bool is_rot = trafo->IsRotation(); if ( 0 == vol ) { - cout << "FATAL: Unknown G4 volume:" << (void*)node << " " << node->GetName() << endl; + printout(FATAL,"Geant4Converter","++ Unknown G4 volume:%p %s of type %s vol:%s ptr:%s", + node,node->GetName(),node->IsA()->GetName(),vol->IsA()->GetName(),vol); } - else if ( trafo->IsRotation() ) { + else if ( is_rot ) { const Double_t* rot = trafo->GetRotationMatrix(); MyTransform3D transform(rot[0],rot[1],rot[2],trans[0]*CM_2_MM, rot[3],rot[4],rot[5],trans[1]*CM_2_MM, rot[6],rot[7],rot[8],trans[2]*CM_2_MM); + if ( mother_is_assembly ) { // Mother is an assembly: + ass_mot->AddPlacedVolume(g4vol,transform); + return 0; + } + else if ( daughter_is_assembly ) { + ass_dau->MakeImprint(g4mot,transform,copy,m_checkOverlaps); + return 0; + } g4 = new G4PVPlacement(transform, // no rotation - vol, // its logical volume + g4vol, // its logical volume name, // its name - mot, // its mother (logical) volume + g4mot, // its mother (logical) volume false, // no boolean operations copy, // its copy number m_checkOverlaps); } else { G4ThreeVector pos(trans[0]*CM_2_MM,trans[1]*CM_2_MM,trans[2]*CM_2_MM); + if ( mother_is_assembly ) { // Mother is an assembly: + ass_mot->AddPlacedVolume(g4vol,pos,0); + return 0; + } + else if ( daughter_is_assembly ) { + ass_dau->MakeImprint(g4mot,pos,0,copy,m_checkOverlaps); + return 0; + } g4 = new G4PVPlacement(0, // no rotation pos, // translation position - vol, // its logical volume + g4vol, // its logical volume name, // its name - mot, // its mother (logical) volume + g4mot, // its mother (logical) volume false, // no boolean operations copy, // its copy number m_checkOverlaps); @@ -462,20 +522,29 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) } else if ( node == s_topPtr ) { G4ThreeVector pos(0,0,0); + if ( mother_is_assembly ) { // Mother is an assembly: + ass_mot->AddPlacedVolume(g4vol,pos,0); + return 0; + } + else if ( daughter_is_assembly ) { + ass_dau->MakeImprint(g4mot,pos,0,copy,m_checkOverlaps); + return 0; + } g4 = new G4PVPlacement(0, // no rotation pos, // translation position - vol, // its logical volume + g4vol, // its logical volume name, // its name - mot, // its mother (logical) volume + g4mot, // its mother (logical) volume false, // no boolean operations copy, // its copy number m_checkOverlaps); data().g4Placements[node] = g4; - cout << "Attempt to convert TOP Detector node failed." << endl; + printout(ERROR, "Geant4Converter", "++ Attempt to convert TOP Detector node failed."); } } else { - cout << "Attempt to DOUBLE-place physical volume:" << name << " No:" << node->GetNumber() << endl; + printout(ERROR, "Geant4Converter", "++ Attempt to DOUBLE-place physical volume: %s No:%d", + name.c_str(),node->GetNumber()); } return g4; } @@ -485,7 +554,7 @@ void* Geant4Converter::handleRegion(const TNamed* region, const set<const TGeoVo G4Region* g4 = data().g4Regions[region]; if ( !g4 ) { Region r = Ref_t(region); - g4 = new G4Region(region->GetName()); + g4 = new G4Region(r.name()); // set production cut G4ProductionCuts* cuts = new G4ProductionCuts(); cuts->SetProductionCut(r.cut()); @@ -498,6 +567,7 @@ void* Geant4Converter::handleRegion(const TNamed* region, const set<const TGeoVo info->storeSecondaries = r.storeSecondaries(); g4->SetUserInformation(info); + printout(INFO, "Geant4Converter", "++ Converted region settings of:%s.",r.name()); vector<string>& limits = r.limits(); for(vector<string>::const_iterator i=limits.begin(); i!=limits.end(); ++i) { const string& nam = *i; @@ -632,7 +702,7 @@ void Geant4Converter::handleProperties(LCDD::Properties& prp) const { if ( result != 1 ) { throw runtime_error("Failed to invoke the plugin "+tag+" of type "+type); } - cout << "+++++ Executed Successfully Geant4 setup module *" << type << "* ." << endl; + printout(INFO, "Geant4Converter", "+++++ Executed Successfully Geant4 setup module *%s*.",type.c_str()); } } @@ -643,43 +713,43 @@ void* Geant4Converter::printSensitive(const TNamed* sens_det, const set<const TG Geant4SensitiveDetector* g4 = info.g4SensDets[sens_det]; ConstVolumeSet& volset = info.sensitives[sens_det]; SensitiveDetector sd = Ref_t(sens_det); - bool verbose = sd.verbose(); - - if ( verbose ) { - cout << "Geant4Converter<SensitiveDetector> +" << setw(18) << left << sd.name() - << setw(20) << left << " ["+sd.type()+"]" - << " Hits:" << setw(16) << left << sd.hitsCollection() << endl; - cout << " | " - << "Cutoff:" << setw(6) << left << sd.energyCutoff() - << setw(5) << right << volset.size() << " volumes "; - if ( sd.region().isValid() ) cout << " Region:" << setw(12) << left << sd.region().name(); - if ( sd.limits().isValid() ) cout << " Limits:" << setw(12) << left << sd.limits().name(); - cout << "." << endl; - } + stringstream str; + + printout(INFO, "Geant4Converter", "++ SensitiveDetector: %-18s %-20s Hits:%-16s", + sd.name(), ("["+sd.type()+"]").c_str(),sd.hitsCollection().c_str()); + str << " | " + << "Cutoff:" << setw(6) << left << sd.energyCutoff() + << setw(5) << right << volset.size() << " volumes "; + if ( sd.region().isValid() ) str << " Region:" << setw(12) << left << sd.region().name(); + if ( sd.limits().isValid() ) str << " Limits:" << setw(12) << left << sd.limits().name(); + str << "."; + printout(INFO, "Geant4Converter", str.str().c_str()); + for(ConstVolumeSet::iterator i=volset.begin(); i!=volset.end();++i) { map<const TGeoVolume*, G4LogicalVolume*>::iterator v = info.g4Volumes.find(*i); G4LogicalVolume* vol = (*v).second; - if ( verbose ) { - cout << " | " - << "Volume:" << setw(24) << left << vol->GetName() - << " " << vol->GetNoDaughters() << " daughters." - << endl; - } + str.str(""); + str << " | " + << "Volume:" << setw(24) << left << vol->GetName() + << " " << vol->GetNoDaughters() << " daughters."; + printout(INFO, "Geant4Converter", str.str().c_str()); } return g4; } -void printSolid(G4VSolid* sol) { +string printSolid(G4VSolid* sol) { + stringstream str; if ( typeid(*sol) == typeid(G4Box) ) { const G4Box* b = (G4Box*)sol; - cout << " Box: x=" << b->GetXHalfLength() << " y=" << b->GetYHalfLength() << " z=" << b->GetZHalfLength(); + str << "++ Box: x=" << b->GetXHalfLength() << " y=" << b->GetYHalfLength() << " z=" << b->GetZHalfLength(); } - if ( typeid(*sol) == typeid(G4Tubs) ) { + else if ( typeid(*sol) == typeid(G4Tubs) ) { const G4Tubs* t = (const G4Tubs*)sol; - cout << " Tubs: Ri=" << t->GetInnerRadius() << " Ra=" << t->GetOuterRadius() - << " z/2=" << t->GetZHalfLength() << " Phi=" << t->GetStartPhiAngle() - << "..." << t->GetDeltaPhiAngle (); + str << " Tubs: Ri=" << t->GetInnerRadius() << " Ra=" << t->GetOuterRadius() + << " z/2=" << t->GetZHalfLength() << " Phi=" << t->GetStartPhiAngle() + << "..." << t->GetDeltaPhiAngle (); } + return str.str(); } /// Print G4 placement @@ -694,21 +764,25 @@ void* Geant4Converter::printPlacement(const string& name, const TGeoNode* node) G4VSensitiveDetector* sd = vol->GetSensitiveDetector(); if ( !sd ) return g4; - cout << "G4Cnv::placement: + " << name << " No:" << node->GetNumber() - << " Vol:" << vol->GetName() << " Solid:" << sol->GetName() - << endl; - cout << " |" - << " Loc: x=" << tr.x() << " y=" << tr.y() << " z=" << tr.z(); - printSolid(sol); - cout << endl; - cout << " |" - << " Ndau:" << vol->GetNoDaughters() << " physvols." - << " Mat:" << vol->GetMaterial()->GetName() - << " Mother:" << (char*)(mot ? mot->GetName().c_str() : "---") - << endl; - cout << " |" - << " SD:" << (char*)(sd ? sd->GetName().c_str() : "---") - << endl; + stringstream str; + str << "G4Cnv::placement: + " << name << " No:" << node->GetNumber() + << " Vol:" << vol->GetName() << " Solid:" << sol->GetName(); + printout(DEBUG,"G4Placement",str.str().c_str()); + str.str(""); + str << " |" + << " Loc: x=" << tr.x() << " y=" << tr.y() << " z=" << tr.z(); + printout(DEBUG,"G4Placement",str.str().c_str()); + printout(DEBUG,"G4Placement",printSolid(sol).c_str()); + str.str(""); + str << " |" + << " Ndau:" << vol->GetNoDaughters() << " physvols." + << " Mat:" << vol->GetMaterial()->GetName() + << " Mother:" << (char*)(mot ? mot->GetName().c_str() : "---"); + printout(DEBUG,"G4Placement",str.str().c_str()); + str.str(""); + str << " |" + << " SD:" << (char*)(sd ? sd->GetName().c_str() : "---"); + printout(DEBUG,"G4Placement",str.str().c_str()); return g4; } @@ -729,54 +803,35 @@ template <typename O, typename C, typename F> void handleRMap(const O* o, const } /// Create geometry conversion -void Geant4Converter::create(DetElement top) { +Geant4Converter& Geant4Converter::create(DetElement top) { G4GeometryInfo& geo = *(m_dataPtr=new G4GeometryInfo); m_data->clear(); - collect(top,geo); + collect(top, geo); s_topPtr = top.placement().ptr(); m_checkOverlaps = false; // We do not have to handle defines etc. // All positions and the like are not really named. // Hence, start creating the G4 objects for materials, solids and log volumes. - handle(this, geo.volumes, &Geant4Converter::collectVolume); - handle(this, geo.solids, &Geant4Converter::handleSolid); - cout << "++ Handled " << geo.solids.size() << " solids." << endl; - + printout(INFO,"Geant4Converter","++ Handled %ld solids.",geo.solids.size()); handle(this, geo.vis, &Geant4Converter::handleVis); - cout << "++ Handled " << geo.solids.size() << " visualization attributes." << endl; - + printout(INFO,"Geant4Converter","++ Handled %ld visualization attributes.",geo.vis.size()); handleMap(this, geo.sensitives, &Geant4Converter::handleSensitive); - cout << "++ Handled " << geo.sensitives.size() << " sensitive detectors." << endl; - + printout(INFO,"Geant4Converter","++ Handled %ld sensitive detectors.",geo.sensitives.size()); handleMap(this, geo.limits, &Geant4Converter::handleLimitSet); - cout << "++ Handled " << geo.limits.size() << " limit sets." << endl; - + printout(INFO,"Geant4Converter","++ Handled %ld limit sets.",geo.limits.size()); handleMap(this, geo.regions, &Geant4Converter::handleRegion); - cout << "++ Handled " << geo.regions.size() << " regions." << endl; - + printout(INFO,"Geant4Converter","++ Handled %ld regions.",geo.regions.size()); handle(this, geo.volumes, &Geant4Converter::handleVolume); - cout << "++ Handled " << geo.volumes.size() << " volumes." << endl; - + printout(INFO,"Geant4Converter","++ Handled %ld volumes.",geo.volumes.size()); // Now place all this stuff appropriately handleRMap(this, *m_data, &Geant4Converter::handlePlacement); - //==================== Fields handleProperties(m_lcdd.properties()); - //cout << *(G4Material::GetMaterialTable()) << endl; //handleMap(this, geo.sensitives, &Geant4Converter::printSensitive); //handleRMap(this, *m_data, &Geant4Converter::printPlacement); -} - -/// Singleton instance -Geant4Converter& Geant4Converter::instance() { - static Geant4Converter* inst = 0; - if ( 0 == inst ) { - Geometry::LCDD& lcdd = LCDD::getInstance(); - inst = new Geant4Converter(lcdd); - } - return *inst; + return *this; } diff --git a/DDG4/src/Geant4DetectorConstruction.cpp b/DDG4/src/Geant4DetectorConstruction.cpp index ca6180d62838c2e4986de51af99478b3f1eca4d6..9c73c9e99a5666a799952970872ab60a391f40bf 100644 --- a/DDG4/src/Geant4DetectorConstruction.cpp +++ b/DDG4/src/Geant4DetectorConstruction.cpp @@ -20,12 +20,13 @@ DD4hep::Simulation::Geant4DetectorConstruction::Geant4DetectorConstruction(Geome G4VPhysicalVolume* DD4hep::Simulation::Geant4DetectorConstruction::Construct() { typedef Simulation::Geant4Converter Geant4Converter; - TGeoNode* top = gGeoManager->GetTopNode(); - Geant4Converter& conv = Geant4Converter::instance(); - DetElement world = m_lcdd.world(); - conv.create(world); - Geant4Converter::G4GeometryInfo& info = conv.data(); - m_world = info.g4Placements[top]; + TGeoNode* top = gGeoManager->GetTopNode(); + Geant4Mapping& g4map = Geant4Mapping::instance(); + DetElement world = m_lcdd.world(); + Geant4Converter conv(m_lcdd); + Geant4Converter::G4GeometryInfo* info = conv.create(world).detach(); + g4map.attach(info); + m_world = g4map.g4Placement(top); #ifdef GEANT4_HAS_GDML if ( ::getenv("DUMP_GDML") ) { G4GDMLParser parser; diff --git a/DDG4/src/Geant4Mapping.cpp b/DDG4/src/Geant4Mapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f2376c1b3a1c3d67e87dfa74c87ec2ace814dea --- /dev/null +++ b/DDG4/src/Geant4Mapping.cpp @@ -0,0 +1,70 @@ +// $Id: Geant4Mapping.cpp 588 2013-06-03 11:41:35Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#include "DDG4/Geant4Mapping.h" +#include "G4PVPlacement.hh" +#include <stdexcept> + +using namespace DD4hep::Simulation; +using namespace DD4hep::Geometry; +using namespace std; + +/// Initializing Constructor +Geant4Mapping::Geant4Mapping( LCDD& lcdd, G4GeometryInfo* data) + : m_lcdd(lcdd), m_dataPtr(data) +{ +} + +/// Standard destructor +Geant4Mapping::~Geant4Mapping() { + if ( m_dataPtr ) delete m_dataPtr; + m_dataPtr = 0; +} + +/// Possibility to define a singleton instance +Geant4Mapping& Geant4Mapping::instance() { + static Geant4Mapping inst(LCDD::getInstance(),0); + return inst; +} + +/// When resolving pointers, we must check for the validity of the data block +void Geant4Mapping::checkValidity() const { + if ( m_dataPtr ) return; + throw runtime_error("Geant4Mapping: Attempt to access an invalid data block!"); +} + +/// Release data and pass over the ownership +Geant4Mapping::G4GeometryInfo* Geant4Mapping::detach() { + G4GeometryInfo* p = m_dataPtr; + m_dataPtr = 0; + return p; +} + +/// Set a new data block +void Geant4Mapping::attach(G4GeometryInfo* data) { + m_dataPtr = data; +} + +/// Accessor to resolve G4 placements +G4PVPlacement* Geant4Mapping::g4Placement(const TGeoNode* node) const { + checkValidity(); + const PlacementMap& m = m_dataPtr->g4Placements; + PlacementMap::const_iterator i = m.find(node); + if ( i != m.end() ) return (*i).second; + return 0; +} + +/// Accessor to resolve geometry placements +PlacedVolume Geant4Mapping::placement(const G4VPhysicalVolume* node) const { + checkValidity(); + const PlacementMap& m = m_dataPtr->g4Placements; + for(PlacementMap::const_iterator i = m.begin(); i != m.end(); ++i) + if ( (*i).second == node ) return PlacedVolume((*i).first); + return PlacedVolume(0); +} diff --git a/DDG4/src/Geant4SensitiveDetector.cpp b/DDG4/src/Geant4SensitiveDetector.cpp index ac1dfe23b168c17713b45804565243925f1ba575..ec4850e24e3c0debe8220529c74a28df52259128 100644 --- a/DDG4/src/Geant4SensitiveDetector.cpp +++ b/DDG4/src/Geant4SensitiveDetector.cpp @@ -11,6 +11,7 @@ #include "DDG4/Geant4SensitiveDetector.h" #include "DDG4/Geant4Converter.h" #include "DDG4/Geant4Hits.h" +#include "DD4hep/Printout.h" #include "DD4hep/LCDD.h" #include "G4Step.hh" @@ -131,18 +132,18 @@ void Geant4SensitiveDetector::clear() { /// Dump Step information (careful: very verbose) void Geant4SensitiveDetector::dumpStep(G4Step* st, G4TouchableHistory* /* history */) { Geant4StepHandler step(st); - Geant4Converter& cnv = Geant4Converter::instance(); + Geant4Mapping& cnv = Geant4Mapping::instance(); //Geant4Converter::G4GeometryInfo& data = cnv.data(); Position pos1 = step.prePos(); Position pos2 = step.postPos(); Momentum mom = step.postMom(); - ::printf(" Track:%08ld Pos:(%8f %8f %8f) -> (%f %f %f) Mom:%7.0f %7.0f %7.0f \n", + printout(INFO,"G4Step"," Track:%08ld Pos:(%8f %8f %8f) -> (%f %f %f) Mom:%7.0f %7.0f %7.0f \n", long(step.track), pos1.X(), pos1.Y(), pos1.Z(), pos2.X(), pos2.Y(), pos2.Z(), mom.X(), mom.Y(), mom.Z()); - ::printf(" pre-Vol: %s Status:%s\n", + printout(INFO,"G4Step"," pre-Vol: %s Status:%s\n", step.preVolume()->GetName().c_str(), step.preStepStatus()); - ::printf(" post-Vol:%s Status:%s\n", + printout(INFO,"G4Step"," post-Vol:%s Status:%s\n", step.postVolume()->GetName().c_str(), step.postStepStatus()); const G4VPhysicalVolume* pv = step.volume(step.post);