Back to home page

EIC code displayed by LXR

 
 

    


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

0001 #include "GDXMLRead.hh"
0002 
0003 #include <iostream>
0004 #include <iomanip>
0005 #include <sstream>
0006 #include <string>
0007 #include <csignal>
0008 #include <vector>
0009 
0010 #include "SLOG.hh"
0011 #include "GDXMLErrorHandler.hh"
0012 
0013 std::string Matrix::desc() const 
0014 {
0015     std::stringstream ss ; 
0016     ss 
0017         << " repeat_index " << std::setw(5) << repeat_index
0018         << " matrixElement " << std::setw(10) << matrixElement
0019         << " name " << std::setw(25) << name 
0020         << " values " << values
0021         ; 
0022     std::string s = ss.str(); 
0023     return s ;  
0024 }
0025 
0026 double atod_( const char* a ) 
0027 {
0028     std::string s(a);
0029     std::istringstream iss(s);
0030     double d ; 
0031     iss >> d ; 
0032     return d ; 
0033 }
0034 
0035 std::string Transcode(const XMLCh* const toTranscode)
0036 {
0037    char* char_str = xercesc::XMLString::transcode(toTranscode);
0038    std::string my_str(char_str);
0039    xercesc::XMLString::release(&char_str);
0040    return my_str;
0041 }
0042 
0043 
0044 const plog::Severity GDXMLRead::LEVEL = SLOG::EnvLevel("GDXMLRead", "DEBUG") ; 
0045 
0046 
0047 GDXMLRead::GDXMLRead( const char* path, bool kludge_truncated_matrix_)
0048     :
0049     validate(false),
0050     kludge_truncated_matrix(kludge_truncated_matrix_),
0051     handler(new GDXMLErrorHandler(!validate)),
0052     parser(new xercesc::XercesDOMParser),
0053     doc(nullptr),
0054     element(nullptr)
0055 {
0056     LOG(LEVEL) << "reading " << path  ; 
0057 
0058     if (validate)
0059     {   
0060         parser->setValidationScheme(xercesc::XercesDOMParser::Val_Always);
0061     }   
0062     parser->setValidationSchemaFullChecking(validate);
0063     parser->setCreateEntityReferenceNodes(false); 
0064      // Entities will be automatically resolved by Xerces
0065 
0066     parser->setDoNamespaces(true);
0067     parser->setDoSchema(validate);
0068     parser->setErrorHandler(handler);
0069 
0070     try 
0071     { 
0072         parser->parse(path); 
0073     }
0074     catch (const xercesc::XMLException &e) 
0075     { 
0076         LOG(error) << "XMLException " << Transcode(e.getMessage()) ; 
0077     }
0078     catch (const xercesc::DOMException &e) 
0079     { 
0080         LOG(error) << "DOMException " << Transcode(e.getMessage()); 
0081     }
0082 
0083     doc = parser->getDocument();
0084 
0085     if (!doc)
0086     {   
0087        LOG(fatal) << "Unable to open document " << path   ; 
0088        return ;
0089     }   
0090 
0091     element = doc->getDocumentElement();
0092     LOG(LEVEL) << "documenElement " << element  ; 
0093     assert( element); 
0094 
0095     for(xercesc::DOMNode* iter = element->getFirstChild(); iter != 0; iter = iter->getNextSibling())
0096     {
0097         if (iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)  { continue; }
0098 
0099         const xercesc::DOMElement* const child = dynamic_cast<xercesc::DOMElement*>(iter); 
0100 
0101         assert( child ); 
0102 
0103         const std::string tag = Transcode(child->getTagName());
0104 
0105         if (tag=="define")
0106         { 
0107             DefineRead(child);    
0108         }  
0109         else
0110         {
0111             LOG(LEVEL) << " tag " << tag ; 
0112         }
0113 
0114         /*
0115 
0116           if (tag=="define")    { DefineRead(child);    } else
0117           if (tag=="materials") { MaterialsRead(child); } else
0118           if (tag=="solids")    { SolidsRead(child);    } else
0119           if (tag=="setup")     { SetupRead(child);     } else
0120           if (tag=="structure") { StructureRead(child); } else
0121           if (tag=="userinfo")  { UserinfoRead(child);  } else
0122           if (tag=="extension") { ExtensionRead(child); }
0123           else
0124           {
0125             G4String error_msg = "Unknown tag in gdml: " + tag;
0126             G4Exception("G4GDMLRead::Read()", "InvalidRead",
0127                         FatalException, error_msg);
0128           }
0129        */
0130 
0131     }
0132 }
0133 
0134 
0135 void GDXMLRead::MatrixRead( const xercesc::DOMElement* const matrixElement, bool& truncated_values )
0136 {
0137     std::string name = ""; 
0138     //int coldim  = 0;
0139     std::string values = ""; 
0140 
0141     const xercesc::DOMNamedNodeMap* const attributes = matrixElement->getAttributes();
0142     XMLSize_t attributeCount = attributes->getLength();
0143 
0144     for (XMLSize_t attribute_index=0; attribute_index<attributeCount; attribute_index++)
0145     {   
0146         xercesc::DOMNode* node = attributes->item(attribute_index);
0147 
0148         if (node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE) { continue; }
0149 
0150         const xercesc::DOMAttr* const attribute = dynamic_cast<xercesc::DOMAttr*>(node); 
0151  
0152         assert( attribute );  
0153 
0154         const std::string attName = Transcode(attribute->getName());
0155         const std::string attValue = Transcode(attribute->getValue());
0156 
0157         if (attName=="name")   { name  = attValue ; } else
0158         //if (attName=="name")   { name  = GenerateName(attValue); } else
0159         //if (attName=="coldim") { coldim = eval.EvaluateInteger(attValue); } else
0160         if (attName=="values") { values = attValue; }
0161     }   
0162 
0163 
0164 
0165     // collecting matrix to check for issue of repeated matrix names 
0166     // that causes GDML read error
0167     Matrix m = {} ; 
0168     m.name = name ; 
0169     m.values = values ; 
0170     m.matrixElement = const_cast<xercesc::DOMElement*>(matrixElement) ;   
0171     m.repeat_index = -1 ; 
0172 
0173     matrix.push_back(m) ; 
0174 
0175 
0176     std::vector<double> valueList;
0177     std::stringstream ss; 
0178     ss.str(values.c_str())  ;
0179     char delim = ' ' ; 
0180     std::string s;
0181     while (std::getline(ss, s, delim)) valueList.push_back(atod_(s.c_str())) ; 
0182 
0183 
0184     truncated_values = false ; 
0185     if(values.length() >= 9999 || valueList.size() % 2 != 0) truncated_values = true ; 
0186     if(truncated_values) 
0187     {
0188         xercesc::DOMElement* me = const_cast<xercesc::DOMElement*>(matrixElement);  
0189         truncated_matrixElement.push_back(me); 
0190         if(kludge_truncated_matrix) KludgeTruncatedMatrix(me); 
0191     }
0192 
0193     LOG(LEVEL)
0194         << " " << ( truncated_values ? "**" : "  " )
0195         << " values.lenth " << std::setw(7) << values.size() 
0196         << " last50 " << std::setw(50) << values.substr(std::max(0,int(values.length())-50)) 
0197         << " valueList.size " << std::setw(10) << valueList.size()
0198         << " " << ( truncated_values ? "**" : "  " )
0199         << " name " << name 
0200         ; 
0201 }
0202 
0203 /**
0204 GDXMLRead::checkDuplicatedMatrix
0205 ----------------------------------------
0206 
0207 **/
0208 
0209 int GDXMLRead::checkDuplicatedMatrix()
0210 {
0211     unsigned num_matrix =  matrix.size() ; 
0212     LOG(LEVEL) << " num_matrix " << num_matrix ; 
0213     int total_duplicated_matrix = 0 ;  
0214 
0215     for(unsigned i=0 ; i < num_matrix ; i++)
0216     {
0217         Matrix& im = matrix[i]  ;  
0218 
0219         std::vector<unsigned> dupes ; 
0220         for(unsigned j=0 ; j < num_matrix ; j++)
0221         {
0222             Matrix& jm = matrix[j]  ;  
0223             if( j > i && jm.repeat_index == -1 )   // avoid comparing twice 
0224             {  
0225                 if( im == jm ) 
0226                 {
0227                     dupes.push_back(j) ; 
0228                     jm.repeat_index = dupes.size() ; 
0229 
0230                     bool expect = im.values.compare(jm.values) == 0 ; 
0231                     assert(expect) ;  
0232                     if(!expect) std::raise(SIGINT); 
0233                 } 
0234             }
0235         }
0236 
0237         std::stringstream ss ; 
0238 
0239         if(dupes.size() > 0 )
0240         {
0241             ss << std::endl << " i " << std::setw(5) << i << " : " << matrix[i].desc() << std::endl ; 
0242             for(unsigned k=0 ; k < dupes.size() ; k++)
0243             {
0244                 unsigned j = dupes[k] ; 
0245                 ss << " j " << std::setw(5) << j << " : " << matrix[j].desc() << std::endl ; 
0246             }
0247         }
0248         std::string s = ss.str(); 
0249         LOG(LEVEL) <<  s ; 
0250 
0251         total_duplicated_matrix += dupes.size() ; 
0252     } 
0253 
0254     LOG(LEVEL)
0255         << " num_matrix " << num_matrix 
0256         << " total_duplicated__matrix " << total_duplicated_matrix 
0257         ; 
0258 
0259     return total_duplicated_matrix ; 
0260 }
0261 
0262 
0263 int GDXMLRead::pruneDuplicatedMatrix()
0264 {
0265     assert(the_defineElement);
0266     unsigned num_matrix =  matrix.size() ; 
0267     LOG(LEVEL) << " num_matrix " << num_matrix ; 
0268 
0269     unsigned prune_count = 0 ;
0270     for(unsigned i=0 ; i < num_matrix ; i++)
0271     {
0272         Matrix& im = matrix[i]  ;  
0273         if( im.repeat_index > -1 )
0274         {
0275             LOG(LEVEL) << "pruning i " << std::setw(5) << i << " im.desc " << im.desc() ; 
0276             the_defineElement->removeChild(im.matrixElement) ; 
0277             prune_count += 1 ; 
0278         }
0279     }
0280     LOG(LEVEL)
0281         << " prune_count " << prune_count 
0282         ;
0283 
0284     return prune_count ; 
0285 }
0286 
0287 
0288 
0289 /**
0290 GDXMLRead::KludgeFix
0291 ---------------------------
0292 
0293 Splits the input string into elements delimited by a single space 
0294 and returns a string with one or two of the last elements trimmed
0295 to make the number of elements even.
0296 
0297 Note this should only be used for values that need trimming
0298 due to truncation.
0299 **/
0300 
0301 std::string GDXMLRead::KludgeFix( const char* values )
0302 {
0303     std::stringstream ss; 
0304     ss.str(values)  ;
0305 
0306     std::vector<std::string> elem ; 
0307     char delim = ' ' ; 
0308     std::string s ; 
0309     while (std::getline(ss, s, delim)) elem.push_back(s) ; 
0310 
0311     unsigned num_trim = elem.size() % 2 == 1 ? 1 : 2 ; 
0312     unsigned i0 = 0 ; 
0313     unsigned i1 = elem.size() - num_trim ; 
0314 
0315     std::stringstream kk ; 
0316     for(unsigned i=i0 ; i < i1 ; i++)
0317     { 
0318         std::string k = elem[i]; 
0319         kk << k ;
0320         if(i < i1 - 1 ) kk << delim  ; 
0321     }
0322 
0323     std::string kludged = kk.str();         
0324     return kludged ;   
0325 }
0326 
0327 /**
0328 GDXMLRead::KludgeTruncatedMatrix
0329 ----------------------------------------
0330 
0331 **/
0332 
0333 void GDXMLRead::KludgeTruncatedMatrix(xercesc::DOMElement* matrixElement )
0334 {
0335     xercesc::DOMNamedNodeMap* attributes = matrixElement->getAttributes();
0336     XMLSize_t attributeCount = attributes->getLength();
0337 
0338     for (XMLSize_t attribute_index=0; attribute_index<attributeCount; attribute_index++)
0339     {   
0340         xercesc::DOMNode* node = attributes->item(attribute_index);
0341         if (node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE) { continue; }
0342         xercesc::DOMAttr* attribute = dynamic_cast<xercesc::DOMAttr*>(node); 
0343         const std::string attName = Transcode(attribute->getName());
0344 
0345         if( attName == "values" )
0346         {
0347             const std::string attValueOri = Transcode(attribute->getValue());
0348             std::string attValueKlu = KludgeFix(attValueOri.c_str());             
0349 
0350 
0351             LOG(LEVEL) 
0352                 << " attName " << attName 
0353                 << " attValueOri.length " << attValueOri.length() 
0354                 << " attValueKlu.length " << attValueKlu.length() 
0355                  ; 
0356 
0357             LOG(LEVEL) 
0358                 << std::endl
0359                 << " attValueOri.length " << attValueOri.length() << std::endl
0360                 << " attValueKlu.length " << attValueKlu.length() << std::endl 
0361                 << " attValueOri.last50 " << std::setw(50) << attValueOri.substr(std::max(0,int(attValueOri.length())-50)) << std::endl 
0362                 << " attValueKlu.last50 " << std::setw(50) << attValueKlu.substr(std::max(0,int(attValueKlu.length())-50)) 
0363                 ; 
0364 
0365             xercesc::XMLString::transcode(attValueKlu.c_str() , tempStr, 9999);
0366             attribute->setValue(tempStr); 
0367         }
0368     }
0369 }
0370 
0371 Constant GDXMLRead::ConstantRead( const xercesc::DOMElement* const constantElement )
0372 {
0373     Constant c = {} ;
0374     c.name = "" ; 
0375     c.value = 0.0 ; 
0376     c.constantElement = const_cast<xercesc::DOMElement*>(constantElement) ; 
0377 
0378     const xercesc::DOMNamedNodeMap* const attributes = constantElement->getAttributes(); 
0379     XMLSize_t attributeCount = attributes->getLength();
0380 
0381     for (XMLSize_t attribute_index=0; attribute_index<attributeCount; attribute_index++) 
0382     {   
0383         xercesc::DOMNode* node = attributes->item(attribute_index);
0384         if (node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE) { continue; }
0385         const xercesc::DOMAttr* const attribute = dynamic_cast<xercesc::DOMAttr*>(node);   
0386         assert(attribute);
0387         const std::string attName = Transcode(attribute->getName());
0388         const std::string attValue = Transcode(attribute->getValue());
0389         if (attName=="name")  { c.name = attValue; }  else
0390         if (attName=="value") { c.value = atod_(attValue.c_str()); }
0391    }   
0392     return c ; 
0393 }
0394 
0395 void GDXMLRead::DefineRead( const xercesc::DOMElement* const defineElement )
0396 {
0397     assert( the_defineElement == nullptr ); 
0398     the_defineElement = const_cast<xercesc::DOMElement*>(defineElement) ; 
0399 
0400     LOG(LEVEL) ; 
0401 
0402     xercesc::DOMElement* modifiableDefineElement = const_cast<xercesc::DOMElement*>(defineElement); 
0403 
0404 
0405    for (xercesc::DOMNode* iter = defineElement->getFirstChild(); iter != 0; iter = iter->getNextSibling())
0406    {   
0407       if (iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE) { continue; }
0408 
0409       const xercesc::DOMElement* const child = dynamic_cast<xercesc::DOMElement*>(iter);
0410       assert( child ); 
0411       const std::string tag = Transcode(child->getTagName());
0412 
0413       bool truncated_matrix_values = false ; 
0414 
0415       if (tag=="constant")
0416       { 
0417           Constant c = ConstantRead(child); 
0418           constants.push_back(c); 
0419       } 
0420       else if (tag=="matrix")     
0421       { 
0422           MatrixRead(child, truncated_matrix_values); 
0423       }  
0424       else 
0425 /*
0426       if (tag=="position")   { PositionRead(child); } else 
0427       if (tag=="rotation")   { RotationRead(child); } else 
0428       if (tag=="scale")      { ScaleRead(child); } else 
0429       if (tag=="variable")   { VariableRead(child); } else 
0430       if (tag=="quantity")   { QuantityRead(child); } else 
0431       if (tag=="expression") { ExpressionRead(child); } else
0432 */
0433       {   
0434           std::cout << "Unknown tag in define " << tag << std::endl ; 
0435       }   
0436    }   
0437 
0438 
0439     LOG(LEVEL) << "constants.size " << constants.size() ; 
0440 
0441     for(unsigned i=0 ; i < constants.size() ; i++)
0442     {
0443         const Constant& c = constants[i] ;
0444         LOG(LEVEL)
0445             << " c.name " << std::setw(20) << c.name 
0446             << " c.value " << std::setw(10) << c.value 
0447             << " c.constantElement " << c.constantElement 
0448             ;  
0449         modifiableDefineElement->removeChild(c.constantElement); 
0450     }
0451 
0452 
0453 }
0454 
0455 
0456 
0457 
0458 
0459 GDXMLRead::~GDXMLRead()
0460 {
0461     delete handler ; 
0462     delete parser ; 
0463 }
0464 
0465 
0466