ATLAS Offline Software
Loading...
Searching...
No Matches
GeoModelXmlTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <GeoModelKernel/GeoPhysVol.h>
9#include <GeoModelXml/Gmx2Geo.h>
10#include <GeoModelXml/GmxInterface.h>
11#include <GeoModelRead/ReadGeoModel.h>
15
16#include <fstream>
17#include <utility>
18
20 const std::string &name,
21 const IInterface *parent)
22 : GeoModelTool(type, name, parent)
23{
24}
25
27{
28 ATH_CHECK(m_geoDbTagSvc.retrieve());
29 ATH_CHECK(m_rdbAccessSvc.retrieve());
30 ATH_CHECK(m_sqliteReadSvc.retrieve());
31
32 return StatusCode::SUCCESS;
33}
34
35const GeoVPhysVol* GeoModelXmlTool::createTopVolume(GeoPhysVol* world, GmxInterface& gmxInterface, const std::string& vNode, const std::string& tableName, const std::string& containingDetector, const std::string& envelopeName, const GeoModelIO::ReadGeoModel* sqlreader) const
36{
37 //If we have a valid sqlreader pointer, it means the volume should already exist,
38 // so we don't need to create it
39 if(!sqlreader) createVolume(world, gmxInterface, vNode, tableName);
40 else ATH_MSG_INFO("Using geometry from .sqlite file for"<<m_detectorName);
41
42 unsigned int nChildren = world->getNChildVols();
43
44 const GeoVPhysVol * envVol = nullptr;
45 const GeoVPhysVol * topVol = nullptr;
46
47 bool foundEnvelope = false;
48 bool foundContainingDetector = false;
49 // find the appropriate volume in the hierarchy, to allow it to be set as the topVolume in
50 // our detectorManager
51 std::string detectorName = m_detectorName;
52 //if a containingDetector is set, which the detector we are dealing with will sit inside, look for that first.
53 // Otherwise its just the name of the detector we are dealing with we look for
54 if(containingDetector!="") detectorName = containingDetector;
55
56 for (int iChild = nChildren - 1; iChild>=0; --iChild) {
57 if (world->getNameOfChildVol(iChild) == detectorName) {
58 // The * converts from a ConstPVLink to a reference to a GeoVPhysVol;
59 // the & takes its address.
60 envVol = &*world->getChildVol(iChild);
61 foundContainingDetector = true;
62 if(envelopeName=="") {topVol = envVol;break;}
63 unsigned int nGrandchildren = envVol->getNChildVols();
64 for (int iGchild = nGrandchildren - 1; iGchild>=0; --iGchild) {
65 if (envVol->getNameOfChildVol(iGchild) == envelopeName) {
66 topVol = &*(envVol->getChildVol(iGchild));
67 foundEnvelope = true;
68 break;
69 }
70 }
71 }
72 }
73 if(containingDetector!="" && !foundContainingDetector) ATH_MSG_ERROR("Couldn't find the containing detector "<<containingDetector<<" in the world hierarchy!");
74 else if(envelopeName!="" && !foundEnvelope) ATH_MSG_ERROR("Couldn't find the envelope volume "<<envelopeName<<" in the world hierarchy!");
75 return topVol;
76}
77
78bool GeoModelXmlTool::isAvailable(const std::string& vNode, const std::string& tableName) const
79{
80 if (m_gmxFilename.empty()) {
81 DecodeVersionKey versionKey(&*m_geoDbTagSvc, vNode);
82 const std::string& versionTag = versionKey.tag();
83 const std::string& versionNode = versionKey.node();
84 const std::string version = m_rdbAccessSvc->getChildTag(tableName, versionTag, versionNode);
85 if (version.empty()) {
86 return false;
87 }
88 ATH_MSG_INFO("Using " << version << " from " << versionNode << " tag " << versionTag);
89 }
90
91 return true;
92}
93
94std::string GeoModelXmlTool::getBlob(const std::string& vNode, const std::string& tableName) const
95{
96 DecodeVersionKey versionKey(&*m_geoDbTagSvc, vNode);
97 const IRDBRecordset_ptr recordSet = m_rdbAccessSvc->getRecordsetPtr(tableName, versionKey.tag(), versionKey.node());
98 if (!recordSet || recordSet->size() == 0) {
99 ATH_MSG_FATAL("Unable to obtain " << vNode << " recordSet");
100 throw std::runtime_error("Unable to obtain recordSet");
101 }
102 const IRDBRecord *record = (*recordSet)[0];
103 std::string clobString = record->getString("XMLCLOB");
104 return clobString;
105}
106
107void GeoModelXmlTool::createVolume(GeoPhysVol* world, GmxInterface& gmxInterface, const std::string& vNode, const std::string& tableName) const {
108 int flags{};
109 std::string gmxInput;
110
111 if (m_gmxFilename.empty()) {
112 ATH_MSG_INFO("Getting " << m_detectorName.value() << " GeoModelXml description from the geometry database");
113 flags = 0x1; // Lowest bit ==> string; next bit implies gzip'd but we decided not to gzip
114 // how to propagate these to here best...?
115 gmxInput = getBlob(vNode,tableName);
116 if (gmxInput.empty()) { // Invalid blob?
117 std::string errMessage("GeoModelXmlTool::createTopVolume: Empty response received from the database.");
118 throw std::runtime_error(errMessage);
119 }
120 } else {
121 flags = 0;
122 gmxInput = PathResolver::find_file(m_gmxFilename, "DATAPATH");
123 ATH_MSG_INFO("Getting " << m_detectorName.value() << " GeoModelXml description from file "<<gmxInput);
124 if (gmxInput.empty()) { // File not found
125 std::string errMessage("GeoModelXmlTool::createTopVolume: Unable to find file " + m_gmxFilename +
126 " with PathResolver; check filename and DATAPATH environment variable");
127 throw std::runtime_error(errMessage);
128 }
129 }
130
131 // Use the DTD from GeoModel
132 if (m_gmxFilename.empty()) {
133 std::string replacementName = "GeoModelXml/";
134 //now, work out the specific dtd version in the input .gmx
135 std::string startdelim = "SYSTEM \"";
136 std::string enddelim = "\" [";
137 unsigned startpos = gmxInput.find(startdelim) + startdelim.length();
138 unsigned endpos = gmxInput.find(enddelim);
139 std::string searchName = gmxInput.substr(startpos,(endpos - startpos));
140 if(searchName=="geomodel.dtd") replacementName+="geomodel_v0.dtd"; //used in xml for initial geometry tags - special case
141 else replacementName+=searchName;
142 ATH_MSG_DEBUG("Searching for "<<searchName<<" and replacing it with "<<replacementName);
143 size_t chars = searchName.length();
144 size_t index = gmxInput.find(searchName);
145 if(m_dtdName!="") replacementName=m_dtdName; //allow overriding of dtd version
146 if (index != std::string::npos) {
147 std::string dtdFile = PathResolver::find_file(replacementName, "DATAPATH");
148 ATH_MSG_DEBUG("dtdFile = " << dtdFile);
149 gmxInput.replace(index,chars, dtdFile);
150 } else {
151 throw std::runtime_error("GeoModelXmlTool::createTopVolume: Did not find valid .dtd in the gmx input string.");
152 }
153 }
154
155 // optionally dump to local file for examination
156 if (m_clobOutputFileName != "") {
157 std::ofstream out(m_clobOutputFileName);
158 if (m_gmxFilename.empty()) {
159 out << gmxInput;
160 } else {
161 std::ifstream in(gmxInput);
162 out << in.rdbuf();
163 }
164 out.close();
165 }
166 gmxInterface.enableLogVolDeDuplication(m_deduplicateLogVol);
167 gmxInterface.enablePhysVolDeDuplication(m_deduplicatePhysVol);
168 gmxInterface.enableShapeDeDuplication(m_deduplicateShape);
169 gmxInterface.enableTransformDeDuplication(m_deduplicateTransf);
170
171 Gmx2Geo gmx2Geo(gmxInput, world, gmxInterface, flags);
172}
173
174GeoModelIO::ReadGeoModel* GeoModelXmlTool::getSqliteReader() const{
175 return m_geoDbTagSvc->getSqliteReader();
176}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
This is a helper class to query the version tags from GeoModelSvc and determine the appropriate tag a...
const std::string & tag() const
Return version tag.
const std::string & node() const
Return the version node.
std::string getBlob(const std::string &versionNode, const std::string &tableNode) const
ServiceHandle< IRDBAccessSvc > m_sqliteReadSvc
void createVolume(GeoPhysVol *worldVol, GmxInterface &interface, const std::string &versionNode, const std::string &tableNode) const
StatusCode createBaseTool()
Gaudi::Property< bool > m_deduplicateShape
Gaudi::Property< bool > m_deduplicatePhysVol
ServiceHandle< IRDBAccessSvc > m_rdbAccessSvc
Gaudi::Property< std::string > m_dtdName
Gaudi::Property< std::string > m_gmxFilename
bool isAvailable(const std::string &versionNode, const std::string &tableNode) const
GeoModelXmlTool(const std::string &type, const std::string &name, const IInterface *parent)
const GeoVPhysVol * createTopVolume(GeoPhysVol *worldVol, GmxInterface &interface, const std::string &versionNode, const std::string &tableNode, const std::string &containingDetector="", const std::string &envelopeName="", const GeoModelIO::ReadGeoModel *sqlreader=nullptr) const
Gaudi::Property< std::string > m_detectorName
ServiceHandle< IGeoDbTagSvc > m_geoDbTagSvc
GeoModelIO::ReadGeoModel * getSqliteReader() const
Gaudi::Property< bool > m_deduplicateTransf
Gaudi::Property< bool > m_deduplicateLogVol
Gaudi::Property< std::string > m_clobOutputFileName
IRDBRecord is one record in the IRDBRecordset object.
Definition IRDBRecord.h:27
virtual const std::string & getString(const std::string &fieldName) const =0
Get string field value.
virtual unsigned int size() const =0
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
Definition index.py:1