Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:59

0001 #pragma once
0002 
0003 #include <cstdlib>
0004 #include "plog/Severity.h"
0005 #include "G4Version.hh"
0006 
0007 class G4VPhysicalVolume ; 
0008 class G4GDMLParser ; 
0009 
0010 struct U4GDML
0011 {
0012     static const bool VERBOSE ; 
0013     static constexpr const char* SensDet = "SensDet" ; // string used by G4GDMLParse SD aux 
0014     static constexpr const plog::Severity LEVEL = info ; 
0015     //static constexpr const char* DefaultGDMLPath = "$UserGEOMDir/origin.gdml" ;  
0016     static constexpr const char* DefaultGDMLPath = "$CFBaseFromGEOM/origin.gdml" ;  
0017 
0018     static const G4VPhysicalVolume* Read();
0019     static const G4VPhysicalVolume* Read(const char* path);
0020     static const G4VPhysicalVolume* Read(const char* base, const char* name);
0021     static void Write(const G4VPhysicalVolume* world, const char* path);
0022     static void Write(const G4VPhysicalVolume* world, const char* base, const char* name) ;
0023 
0024     bool read_trim ; 
0025     bool read_validate ; 
0026     bool write_refs ; 
0027     const char* write_schema_location ; 
0028 
0029     U4GDML(const G4VPhysicalVolume* world_=nullptr ); 
0030 
0031     G4GDMLParser*      parser ;
0032     const G4VPhysicalVolume* world ;  
0033 
0034     void read( const char* base, const char* name);
0035     void read( const char* path);
0036 private:
0037     void read_( const char* path);
0038     void connectAuxSensDet(); 
0039 public:
0040 
0041     void write(const char* base, const char* name);
0042     void write(const char* path);
0043     void write_(const char* path);
0044 };
0045 
0046 
0047 const bool U4GDML::VERBOSE = getenv("U4GDML__VERBOSE") != nullptr ; 
0048 
0049 
0050 #include "sdirect.h"
0051 #include "sdirectory.h"
0052 #include "spath.h"
0053 #include "sstr.h"
0054 #include "ssys.h"
0055 
0056 #include "G4GDMLParser.hh"
0057 #include "GDXML.hh"
0058 #include "U4SensitiveDetector.hh"
0059 
0060 
0061 /**
0062 U4GDML::Read 
0063 -------------
0064 
0065 When geometry persisting is enabled the origin.gdml should be 
0066 included in the output folder. Note that this might need
0067 to have been GDML kludged to allow Geant4 for load it. 
0068 For GDML kludging see the gdxml package which loads GDML using XercesC and does 
0069 GDML fixups that allow Geant4 to parse the JUNO GDML. 
0070 
0071 **/
0072 
0073 inline const G4VPhysicalVolume* U4GDML::Read()
0074 {
0075     return Read(DefaultGDMLPath); 
0076 }
0077 
0078 inline const G4VPhysicalVolume* U4GDML::Read(const char* path_)
0079 {
0080     const char* path = spath::Resolve(path_ ? path_ : DefaultGDMLPath) ; 
0081     bool exists = path ? spath::Exists(path) : false ; 
0082     LOG_IF(fatal, !exists) << " path invalid or does not exist [" << path << "]" ; 
0083     if(!exists) return nullptr ; 
0084 
0085     U4GDML g ; 
0086     g.read(path); 
0087     return g.world ; 
0088 }
0089 inline const G4VPhysicalVolume* U4GDML::Read(const char* base, const char* name)
0090 {
0091     U4GDML g ; 
0092     g.read(base, name); 
0093     return g.world ; 
0094 }
0095 inline void U4GDML::Write(const G4VPhysicalVolume* world, const char* path)
0096 {
0097     LOG_IF(error, world == nullptr) << " world NULL " ; 
0098     if(world == nullptr) return ; 
0099 
0100     U4GDML g(world) ; 
0101     g.write(path); 
0102 }
0103 inline void U4GDML::Write(const G4VPhysicalVolume* world, const char* base, const char* name )
0104 {
0105     LOG_IF(error, world == nullptr) << " world NULL " ; 
0106     if(world == nullptr) return ; 
0107 
0108     U4GDML g(world) ; 
0109     g.write(base, name); 
0110 }
0111 
0112 
0113 
0114 inline U4GDML::U4GDML(const G4VPhysicalVolume* world_)
0115     :
0116     read_trim(false),
0117     read_validate(false),
0118     write_refs(true),
0119     write_schema_location(""),
0120     parser(new G4GDMLParser),
0121     world(world_)
0122 {
0123     parser->SetSDExport(true); 
0124 }
0125 
0126 inline void U4GDML::read(const char* base, const char* name)
0127 {
0128     const char* path = spath::Resolve(base, name); 
0129     read(path);  
0130 }
0131 
0132 /**
0133 U4GDML::read
0134 -------------
0135 
0136 Attempt to swallow the G4cout "G4GDML:" logging using sdirect.h 
0137 not working, something funny about G4cout ?::
0138 
0139    g4-cls G4ios
0140 
0141 **/
0142 
0143 inline void U4GDML::read(const char* path_)
0144 {
0145     read_(path_); 
0146     connectAuxSensDet(); 
0147 }
0148 
0149 inline void U4GDML::read_(const char* path_)
0150 {
0151     const char* path = spath::Resolve(path_); 
0152 
0153     parser->SetStripFlag(read_trim); 
0154 
0155     std::stringstream coutbuf;
0156     std::stringstream cerrbuf;
0157     {
0158         sdirect::cout_(coutbuf.rdbuf());
0159         sdirect::cerr_(cerrbuf.rdbuf());
0160 
0161         parser->Read(path, read_validate);  // noisy code 
0162 
0163     }
0164     std::string out = coutbuf.str();
0165     std::string err = cerrbuf.str();
0166     std::cout << sdirect::OutputMessage("U4GDML::read", out, err, VERBOSE );
0167 
0168     const G4String setupName = "Default" ;
0169     world = parser->GetWorldVolume(setupName) ; 
0170 }
0171 
0172 /**
0173 U4GDML::connectAuxSensDet
0174 ---------------------------
0175 
0176 Must create U4SensitiveDetector of the same names
0177 as in the GDML for the connection to work, eg::
0178 
0179     <auxiliary auxtype="SensDet" auxvalue="PMTSDMgr"/>
0180 
0181 **/
0182 
0183 inline void U4GDML::connectAuxSensDet()
0184 {
0185     const G4GDMLAuxMapType* auxmap = parser->GetAuxMap();
0186 
0187     if(VERBOSE) std::cout 
0188         << "[U4GDML::connectAuxSensDet"
0189         << " auxmap.size " << auxmap->size()
0190         << " (volumes with aux info) " 
0191         << std::endl  
0192         << U4SensitiveDetector::Desc()
0193         ;
0194 
0195 
0196     typedef G4GDMLAuxMapType::const_iterator MIT ;  
0197     typedef G4GDMLAuxListType::const_iterator VIT ; 
0198 
0199     for (MIT mit = auxmap->begin(); mit != auxmap->end(); mit++) 
0200     {
0201         G4LogicalVolume* lv = mit->first ; 
0202         G4GDMLAuxListType ls = mit->second ;      
0203         const char* lvn = lv->GetName().c_str();  
0204           
0205         if(VERBOSE) std::cout 
0206              << "lvn " << lvn
0207              << " has the following list of auxiliary information: "
0208              << std::endl 
0209              ;
0210 
0211         for (VIT vit = ls.begin(); vit != ls.end(); vit++) 
0212         {
0213             const G4GDMLAuxStructType& aux = *vit ;  
0214             const G4String& type = aux.type ;
0215             const G4String& value = aux.value ;
0216             const G4String& unit = aux.unit ;
0217             bool is_SensDet = strcmp(type.c_str(), SensDet) == 0 ; 
0218             const char* sdn = is_SensDet ? value.c_str() : nullptr ; 
0219             U4SensitiveDetector* sd = sdn ? U4SensitiveDetector::Get(sdn) : nullptr ; 
0220 
0221             if(VERBOSE) std::cout 
0222                    << " aux.type [" << type << "]"
0223                    << " aux.value ["   << value << "]"
0224                    << " aux.unit [" << unit << "]"
0225                    << " is_SensDet " << ( is_SensDet ? "YES" : "NO " ) 
0226                    << " sdn " << ( sdn ? sdn : "-" )
0227                    << " sd " << ( sd ? "YES" : "NO " )
0228                    << std::endl 
0229                    ;
0230 
0231             if(sd) 
0232             {
0233                 //if(VERBOSE)
0234                 std::cout 
0235                     << "U4GDML::connectAuxSensDet"
0236                     << " sdn " << ( sdn ? sdn : "-" )
0237                     << " lvn " << ( lvn ? lvn : "-" )
0238                     << std::endl 
0239                     ;
0240 
0241                 lv->SetSensitiveDetector(sd); 
0242             }
0243 
0244         }   
0245     } 
0246     if(VERBOSE) std::cout 
0247         << "]U4GDML::connectAuxSensDet"
0248         << std::endl  
0249         ;
0250 
0251 }
0252 
0253 
0254 inline void U4GDML::write(const char* base, const char* name)
0255 {
0256     const char* path = spath::Resolve(base, name); 
0257     write(path);  
0258 }
0259 
0260 
0261 
0262 
0263 /**
0264 U4GDML::write
0265 ---------------
0266 
0267 Example of steps taken when *path* is "/some/dir/to/example.gdml" 
0268 
0269 1. rawpath "/some/dir/to/example_raw.gdml" is written using Geant4 GDML parser
0270 2. rawpath GDML is read as XML and some issues may be fixed (using GDXML::Fix) 
0271 3. fixed XML is written to original *path* "/some/dir/to/example.gdml"  
0272 
0273 To disable use of GDXML::Fix define envvar::
0274 
0275     export U4GDML_GDXML_FIX_DISABLE=1
0276 
0277 **/
0278 
0279 inline void U4GDML::write(const char* path)
0280 {
0281     assert( sstr::EndsWith(path, ".gdml") ); 
0282     const char* dstpath = path ; 
0283 
0284 #if G4VERSION_NUMBER < 1100
0285     const char* ekey = "U4GDML_GDXML_FIX_DISABLE" ; 
0286     bool U4GDML_GDXML_FIX_DISABLE = ssys::getenvbool(ekey) ;
0287 #else
0288     bool U4GDML_GDXML_FIX_DISABLE = true;
0289 #endif
0290     bool U4GDML_GDXML_FIX = !U4GDML_GDXML_FIX_DISABLE  ; 
0291 
0292     LOG(LEVEL) 
0293 #if G4VERSION_NUMBER < 1100
0294         << " ekey " << ekey 
0295 #else
0296         << "Disabling GDXML kludge fix, as Geant4 version " << G4VERSION_NUMBER << ">= 1100 "
0297 #endif
0298         << " U4GDML_GDXML_FIX_DISABLE " << U4GDML_GDXML_FIX_DISABLE
0299         << " U4GDML_GDXML_FIX " << U4GDML_GDXML_FIX 
0300         ; 
0301 
0302     if(U4GDML_GDXML_FIX)
0303     {
0304         const char* rawpath = sstr::ReplaceEnd(path, ".gdml", "_raw.gdml" );  
0305         write_(rawpath); 
0306         LOG(LEVEL) << "[ Apply GDXML::Fix " << " rawpath " << rawpath << " dstpath " << dstpath ; 
0307         GDXML::Fix( dstpath, rawpath );     
0308         LOG(LEVEL) << "] Apply GDXML::Fix " << " rawpath " << rawpath << " dstpath " << dstpath ; 
0309     }
0310     else
0311     {
0312         LOG(LEVEL) << " NOT Applying GDXML::Fix " << " dstpath " << dstpath ; 
0313         write_(dstpath); 
0314     }
0315 }
0316 
0317 inline void U4GDML::write_(const char* path)
0318 {
0319     LOG(LEVEL) << "[" ;    
0320     bool exists = spath::Exists(path) ; 
0321     int rc = exists ? spath::Remove(path) : 0 ; 
0322 
0323     LOG_IF(fatal, rc != 0 ) 
0324         << " FAILED TO REMOVE PATH [" << path << "]" 
0325         << " CHECK PERMISSIONS " 
0326         ; 
0327 
0328     LOG(LEVEL) 
0329         << " path " << ( path ? path : "-" ) 
0330         << " exists " << ( exists ? "YES" : "NO " )
0331         << " rc " << rc
0332         ;
0333 
0334     sdirectory::MakeDirsForFile(path,0);
0335     parser->Write(path, world, write_refs, write_schema_location); 
0336     LOG(LEVEL) << "]" ;    
0337 }
0338 
0339