diff --git a/DDCore/python/dd4hep_base.py b/DDCore/python/dd4hep_base.py index c1cbdab3da0f4e13253e23b8226fc475157d0755..581a034ee2fdb7572cf48f98578063d3a61ce7e5 100644 --- a/DDCore/python/dd4hep_base.py +++ b/DDCore/python/dd4hep_base.py @@ -114,6 +114,9 @@ import_namespace_item('tools','Evaluator') import_namespace_item('core','NamedObject') import_namespace_item('core','run_interpreter') +def import_detail(): + import_namespace_item('detail','DD4hepUI') + def import_geometry(): import_namespace_item('core','setPrintLevel') import_namespace_item('core','setPrintFormat') @@ -235,6 +238,7 @@ def import_tgeo(): import_tgeo() import_geometry() +import_detail() # # Import units from TGeo. # Calling import_units makes all the units local to the dd4hep module. diff --git a/DDCore/src/DetectorData.cpp b/DDCore/src/DetectorData.cpp index bea31ce3f207fa2656fca6193ae5d0ab365242ac..15de7d2cd47a18c101e2e1e2bcc1324e4b5cc9d0 100644 --- a/DDCore/src/DetectorData.cpp +++ b/DDCore/src/DetectorData.cpp @@ -281,5 +281,12 @@ void DetectorData::adoptData(DetectorData& source, bool clr) { m_properties = source.m_properties; //m_extensions = source.m_extensions; m_volManager = source.m_volManager; + + // Update world element + m_world.setPlacement(m_manager->GetTopNode()); + // Need to update some global stuff + if ( gGeoManager != m_manager ) delete gGeoManager; + gGeoManager = m_manager; + if ( clr ) source.clearData(); } diff --git a/DDCore/src/VolumeManager.cpp b/DDCore/src/VolumeManager.cpp index 63325210b0ccd57d72293041a6dbf86084ff7447..ad5547f19804c916200beec05b838c5f6fa5a16b 100644 --- a/DDCore/src/VolumeManager.cpp +++ b/DDCore/src/VolumeManager.cpp @@ -34,10 +34,7 @@ DD4HEP_INSTANTIATE_HANDLE_NAMED(VolumeManagerObject); namespace { - - static bool s_useAllocator = false; - - class ContextExtension { + class ContextExtension : public VolumeManagerContext { public: /// The placement of the (sensitive) volume PlacedVolume placement{0}; @@ -48,110 +45,6 @@ namespace { /// Default destructor ~ContextExtension() = default; }; - - static size_t ALLOCATE_SIZE = 1000; - class VolumeContextAllocator { - - public: - struct Small { - unsigned char context[sizeof(VolumeManagerContext)]; - unsigned int chunk = 0; - unsigned short slot = 0; - unsigned char type = 0; - unsigned char used = 0; - /// Default constructor - Small() : type(1) {} - /// Default destructor - virtual ~Small() = default; - /// Inhibit copy constructor - Small(const Small& copy) = delete; - /// Inhibit assignment operator - Small& operator=(const Small& copy) = delete; - }; - struct Large : public Small { - unsigned char extension[sizeof(ContextExtension)]; - /// Default constructor - Large() : Small() { type = 2; } - /// Default destructor - virtual ~Large() = default; - /// Inhibit copy constructor - Large(const Large& copy) = delete; - /// Inhibit assignment operator - Large& operator=(const Large& copy) = delete; - }; - - std::vector<std::pair<size_t,Small*> > small; - std::vector<std::pair<size_t,Large*> > large; - std::list<Small*> free_small; - std::list<Large*> free_large; - - VolumeContextAllocator() {} - static VolumeContextAllocator* instance() { - static VolumeContextAllocator _s; - return &_s; - } - void clear() { - free_small.clear(); - for( auto& i : small ) delete i.second; - small.clear(); - - free_large.clear(); - for( auto& i : large ) delete i.second; - large.clear(); - } - void freeBlock(void* ctxt) { - Small* s = (Small*)ctxt; - switch(s->type) { - case 1: - s->used = 0; - free_small.push_back(s); - return; - case 2: - s->used = 0; - free_large.push_back((Large*)s); - return; - default: - printout(ERROR,"VolumeManager", - "++ Hit invalid context slot:%p type:%4X", - (void*)s, s->type); - return; - } - } - void* alloc_large() { - if ( s_useAllocator ) { - if ( !free_large.empty() ) { - Large* entry = free_large.back(); - free_large.pop_back(); - entry->used = 1; - return entry->context; - } - Large* blk = new Large[ALLOCATE_SIZE]; - for(size_t i=0; i<ALLOCATE_SIZE;++i) free_large.push_back(&blk[i]); - large.push_back(make_pair(ALLOCATE_SIZE,blk)); - return alloc_large(); - } - return new VolumeContextAllocator::Large(); - } - void* alloc_small() { - if ( s_useAllocator ) { - if ( !free_small.empty() ) { - Small* entry = free_small.back(); - free_small.pop_back(); - entry->used = 1; - return entry->context; - } - Small* blk = new Small[ALLOCATE_SIZE]; - for(size_t i=0; i<ALLOCATE_SIZE;++i) free_small.push_back(&blk[i]); - small.push_back(make_pair(ALLOCATE_SIZE,blk)); - return alloc_small(); - } - return new VolumeContextAllocator::Small(); - } - }; - inline ContextExtension* _getExtension(const VolumeManagerContext* ctxt) { - VolumeContextAllocator::Large* p = (VolumeContextAllocator::Large*)ctxt; - return (ContextExtension*)p->extension; - } } /// Namespace for the AIDA detector description toolkit @@ -370,16 +263,15 @@ namespace dd4hep { //m_debug = true; // This is the block, we effectively have to save for each physical volume with a VolID - void* mem = nodes.empty() - ? VolumeContextAllocator::instance()->alloc_small() - : VolumeContextAllocator::instance()->alloc_large(); - VolumeManagerContext* context = new(mem) VolumeManagerContext; + VolumeManagerContext* context = nodes.empty() + ? new VolumeManagerContext + : new ContextExtension; context->identifier = code.first; context->mask = code.second; context->element = e; context->flag = nodes.empty() ? 0 : 1; if ( context->flag ) { - ContextExtension* ext = new(_getExtension(context)) ContextExtension(); + ContextExtension* ext = (ContextExtension*)context; ext->placement = PlacedVolume(n); for (size_t i = nodes.size(); i > 1; --i) { // Omit the placement of the parent DetElement TGeoMatrix* m = nodes[i-1]->GetMatrix(); @@ -424,7 +316,6 @@ namespace dd4hep { /// Default destructor VolumeManagerContext::~VolumeManagerContext() { if ( 0 == flag ) return; - _getExtension(this)->~ContextExtension(); } /// Acces the sensitive volume placement @@ -436,13 +327,16 @@ PlacedVolume VolumeManagerContext::elementPlacement() const { PlacedVolume VolumeManagerContext::volumePlacement() const { if ( 0 == flag ) return element.placement(); - return _getExtension(this)->placement; + const ContextExtension* ext = (const ContextExtension*)this; + return ext->placement; } /// Access the transformation to the closest detector element const TGeoHMatrix& VolumeManagerContext::toElement() const { static TGeoHMatrix identity; - return ( 0 == flag ) ? identity : _getExtension(this)->toElement; + if ( 0 == flag ) return identity; + const ContextExtension* ext = (const ContextExtension*)this; + return ext->toElement; } /// Initializing constructor to create a new object @@ -770,12 +664,7 @@ std::ostream& dd4hep::operator<<(std::ostream& os, const VolumeManager& m) { /// Default destructor VolumeManagerObject::~VolumeManagerObject() { /// Cleanup volume tree - if ( s_useAllocator ) { - VolumeContextAllocator::instance()->clear(); - } - else { - destroyObjects(volumes); - } + destroyObjects(volumes); /// Cleanup dependent managers destroyHandles(managers); managers.clear(); diff --git a/DDG4/src/Geant4Kernel.cpp b/DDG4/src/Geant4Kernel.cpp index 15aa3db6f34b0c1d53f3ef8a5b079a0b417cb631..e497df984c7a536ebd16e442f57886d72a909b00 100644 --- a/DDG4/src/Geant4Kernel.cpp +++ b/DDG4/src/Geant4Kernel.cpp @@ -76,7 +76,7 @@ Geant4Kernel::Geant4Kernel(Detector& description_ref) m_numThreads(0), m_id(Geant4Kernel::thread_self()), m_master(this), m_shared(0), m_threadContext(0), phase(this) { - m_detDesc->addExtension < Geant4Kernel > (this); + //m_detDesc->addExtension < Geant4Kernel > (this); m_ident = -1; declareProperty("UI",m_uiName); declareProperty("OutputLevel", m_outputLevel = DEBUG); @@ -133,7 +133,7 @@ Geant4Kernel::~Geant4Kernel() { Geant4ActionContainer::terminate(); if ( m_detDesc && isMaster() ) { try { - m_detDesc->removeExtension < Geant4Kernel > (false); + //m_detDesc->removeExtension < Geant4Kernel > (false); m_detDesc->destroyInstance(); m_detDesc = 0; } @@ -321,7 +321,7 @@ int Geant4Kernel::terminate() { } Geant4ActionContainer::terminate(); if ( ptr == this && m_detDesc ) { - m_detDesc->removeExtension < Geant4Kernel > (false); + //m_detDesc->removeExtension < Geant4Kernel > (false); m_detDesc->destroyInstance(); m_detDesc = 0; } diff --git a/examples/CLICSiD/scripts/CLICSiD_LoadROOTGeo.py b/examples/CLICSiD/scripts/CLICSiD_LoadROOTGeo.py new file mode 100644 index 0000000000000000000000000000000000000000..5b3fa6649c033004b50d2c3d2f90f42e558e7e78 --- /dev/null +++ b/examples/CLICSiD/scripts/CLICSiD_LoadROOTGeo.py @@ -0,0 +1,66 @@ +""" + + Subtest using CLICSid showing the usage of the G4Particle gun using + the Geant4GeneratorWrapper object. + + @author M.Frank + @version 1.0 + +""" +def run(): + import sys, logging, CLICSid, DDG4 + from DDG4 import OutputLevel as Output + + logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG) + sid = CLICSid.CLICSid() + geant4 = sid.geant4 + kernel = sid.kernel + sid.loadGeometry('CLICSiD_geometry.root') + geant4.printDetectors() + + if len(sys.argv) >= 2 and sys.argv[1] =="batch": + kernel.UI = '' + + geant4.setupCshUI() + sid.setupField(quiet=False) + DDG4.importConstants(kernel.detectorDescription(),debug=False) + + prt = DDG4.EventAction(kernel,'Geant4ParticlePrint/ParticlePrint') + prt.OutputLevel = Output.INFO + prt.OutputType = 3 # Print both: table and tree + kernel.eventAction().adopt(prt) + + gen = DDG4.GeneratorAction(kernel,"Geant4GeneratorActionInit/GenerationInit") + kernel.generatorAction().adopt(gen) + logging.info("# First particle generator: gun") + gun = DDG4.GeneratorAction(kernel,"Geant4GeneratorWrapper/Gun"); + gun.Uses = 'G4ParticleGun' + gun.Mask = 1 + kernel.generatorAction().adopt(gun) + + # Merge all existing interaction records + merger = DDG4.GeneratorAction(kernel,"Geant4InteractionMerger/InteractionMerger") + merger.enableUI() + kernel.generatorAction().adopt(merger) + + + # And handle the simulation particles. + part = DDG4.GeneratorAction(kernel,"Geant4ParticleHandler/ParticleHandler") + kernel.generatorAction().adopt(part) + part.OutputLevel = Output.INFO + part.enableUI() + user = DDG4.Action(kernel,"Geant4TCUserParticleHandler/UserParticleHandler") + user.TrackingVolume_Zmax = DDG4.EcalEndcap_zmin + user.TrackingVolume_Rmax = DDG4.EcalBarrel_rmin + user.enableUI() + part.adopt(user) + + sid.setupDetectors() + sid.setupPhysics('QGSP_BERT') + sid.test_config() + gun.generator() # Instantiate gun to be able to set properties from G4 prompt + kernel.run() + kernel.terminate() + +if __name__ == "__main__": + run() diff --git a/examples/CLICSiD/scripts/CLICSid.py b/examples/CLICSiD/scripts/CLICSid.py index a2c3573cdabacccbb19c4064d122f801712b0efb..a7d8ee7a6fd58f26b07bd710d88d635065e4d31d 100644 --- a/examples/CLICSiD/scripts/CLICSid.py +++ b/examples/CLICSiD/scripts/CLICSid.py @@ -4,15 +4,19 @@ from SystemOfUnits import * class CLICSid: def __init__(self,tracker='Geant4TrackerCombineAction'): self.kernel = DDG4.Kernel() - self.description = self.kernel.detectorDescription() + self.description = self.kernel.detectorDescription() self.geant4 = DDG4.Geant4(self.kernel,tracker=tracker) self.kernel.UI = "" self.noPhysics() - def loadGeometry(self): + def loadGeometry(self, file=None): import os - install_dir = os.environ['DD4hepINSTALL'] - self.kernel.loadGeometry("file:"+install_dir+"/DDDetectors/compact/SiD.xml") + if file is None: + install_dir = os.environ['DD4hepINSTALL'] + self.kernel.loadGeometry("file:"+install_dir+"/DDDetectors/compact/SiD.xml") + else: + ui = DDG4.DD4hepUI(self.description) + ui.importROOT(file) return self # Example to show how to configure G4 magnetic field tracking diff --git a/examples/DDDB/data/VPOnly.xml b/examples/DDDB/data/VPOnly.xml new file mode 100644 index 0000000000000000000000000000000000000000..f052929d32fda7ddf418f050cf5ead5a4ee09004 --- /dev/null +++ b/examples/DDDB/data/VPOnly.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<DDDB> + <config> + <param name="print_file_load" value="true"/> + </config> + <block name="/Prs/"/> + <block name="/Spd/"/> + <block name="/Ecal/"/> + <block name="/Hcal/"/> + <block name="/Muon/"/> + <block name="/Infrastructure/"/> + + <block name="/materials/Ecal"/> + <block name="/materials/Hcal"/> + <block name="/materials/Spd"/> + <block name="/materials/Prs"/> + <block name="/materials/Muon"/> + <block name="/materials/Blockwall"/> + <block name="/materials/Bcm"/> + <block name="/materials/Bls"/> + <block name="/materials/GValve"/> + <block name="/materials/MBXW"/> + <block name="/materials/Magnet"/> + + <block name="/Conditions/Rich1/"/> + <block name="/Conditions/Rich2/"/> + <block name="/Conditions/Spd/"/> + <block name="/Conditions/Prs/"/> + <block name="/Conditions/Ecal/"/> + <block name="/Conditions/Hcal/"/> + <block name="/Conditions/Calo/"/> + <block name="/Conditions/Muon/"/> + <block name="/Conditions/LHCb/"/> +</DDDB> diff --git a/examples/Persistency/CMakeLists.txt b/examples/Persistency/CMakeLists.txt index 59e5f780b089218143156e395f18d330b850fb88..3946e35badba25e4e500f6ce8df3f29fa4197326 100644 --- a/examples/Persistency/CMakeLists.txt +++ b/examples/Persistency/CMakeLists.txt @@ -202,3 +202,16 @@ dd4hep_add_test_reg( Persist_CLICSiD_Restore_Readouts_LONGTEST REGEX_PASS "\\+\\+\\+ PASSED Checked 14 readout objects. Num.Errors: 0" REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" ) +# +if (DD4HEP_USE_GEANT4) + # + # + # Test restoring geometry from ROOT file and start Geant4 + dd4hep_add_test_reg( Persist_CLICSiD_Geant4_LONGTEST + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_Persistency.sh" + EXEC_ARGS python ${CMAKE_CURRENT_SOURCE_DIR}/../CLICSiD/scripts/CLICSiD_LoadROOTGeo.py batch + REQUIRES DDG4 Geant4 + REGEX_PASS "\\+\\+\\+ Finished run 0 after 10 events \\(10 events in total\\)" + REGEX_FAIL "Exception;EXCEPTION;ERROR" + ) +endif()