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" ;
0014 static constexpr const plog::Severity LEVEL = info ;
0015
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
0063
0064
0065
0066
0067
0068
0069
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
0134
0135
0136
0137
0138
0139
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);
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
0174
0175
0176
0177
0178
0179
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
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
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
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