/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 #include "TH2DE.h" 00002 00003 #include "DetDesc/ILVolume.h" 00004 #include "DetDesc/IPVolume.h" 00005 #include "DetDesc/IDetectorElement.h" 00006 #include "DetDesc/IGeometryInfo.h" 00007 00008 #include "G4TouchableHistory.hh" 00009 #include "G4VPhysicalVolume.hh" 00010 00011 #include <sstream> 00012 00013 using namespace std; 00014 00015 TH2DE::TH2DE(const std::string& type, 00016 const std::string& name, 00017 const IInterface* parent) 00018 : GaudiTool(type,name,parent) 00019 { 00020 declareInterface<ITouchableToDetectorElement>(this); 00021 this->ClearCache(); 00022 } 00023 00024 TH2DE::~TH2DE() 00025 { 00026 this->ClearCache(); 00027 } 00028 00029 static void split(vector<string>& out, const string& src, char del) 00030 { 00031 out.clear(); 00032 string::size_type pos = 0, siz = src.size(); 00033 while (pos < siz) { 00034 string::size_type found = src.find(del,pos); 00035 if (found == string::npos) { 00036 out.push_back(src.substr(pos,siz-pos)); 00037 break; 00038 } 00039 out.push_back(src.substr(pos,found-pos)); 00040 pos = found+1; 00041 } 00042 } 00043 00044 static string dumpstr(const G4TouchableHistory* g4hist) 00045 { 00046 stringstream ss; 00047 int siz = g4hist->GetHistoryDepth(); 00048 for (int ind=0; ind < siz; ++ind) { 00049 ss << g4hist->GetVolume(ind)->GetName() << "\n"; 00050 } 00051 ss << ends; 00052 return ss.str(); 00053 } 00054 00055 StatusCode TH2DE::GetBestDetectorElement(const G4TouchableHistory* inHistory, 00056 const std::vector<std::string>& /*notused*/, 00057 const IDetectorElement* &outElement, 00058 int& outCompatibility) 00059 { 00060 if (!inHistory->GetHistoryDepth()) { 00061 warning() << "TH2DE::GetBestDetectorElement given an empty history" << endreq; 00062 return StatusCode::FAILURE; 00063 } 00064 00065 const IDetectorElement* de = this->CheckCache(inHistory); 00066 if (de) { 00067 outElement = de; 00068 return StatusCode::SUCCESS; 00069 } 00070 00071 TouchableHistory_t th; // for cache 00072 NameHistory_t name_history; // always read backwards, [0] = daughter, [n] = ancestors 00073 const int depth = inHistory->GetHistoryDepth(); 00074 for (int ind=0; ind < depth; ++ind) { 00075 G4VPhysicalVolume* g4pv = inHistory->GetVolume(ind); 00076 th.push_back(g4pv); 00077 00078 string full_name = g4pv->GetName(); 00079 00080 verbose() << ind << ": " << full_name << endreq; 00081 00082 vector<string> names; 00083 split(names,full_name,'#'); 00084 00085 #if 0 00086 for (size_t iname=0; iname<names.size(); ++iname) { 00087 debug() << iname << ": [" << names[iname] << "]"; 00088 } 00089 debug() << endreq; 00090 #endif 00091 00092 if (depth-ind == 1) { // have /dd/Structure top level DE 00093 if (names.size() != 1) { 00094 warning() << "got unknown type at top of history: " << full_name << ", " <<names.size() << endreq; 00095 return StatusCode::FAILURE; 00096 } 00097 00098 DataObject* obj = 0; 00099 StatusCode sc = detSvc()->retrieveObject(names[0],obj); 00100 if (sc.isFailure()) { 00101 warning() << "failed to get DetectorElement: " << names[0] << endreq; 00102 return StatusCode::FAILURE; 00103 } 00104 de = dynamic_cast<const IDetectorElement*>(obj); 00105 if (!de) { 00106 warning() << "failed to dynamic_cast<DetectorElement*>: " << names[0] << endreq; 00107 return StatusCode::FAILURE; 00108 } 00109 break; 00110 } 00111 00112 00113 if (names.size() > 2) { // have pv1#pv2#pv3 style path 00114 DataObject* obj = 0; 00115 StatusCode sc = detSvc()->retrieveObject(names[0],obj); 00116 if (sc.isFailure()) { 00117 warning() << "failed to get LVolume: " << names[0] << endreq; 00118 return StatusCode::FAILURE; 00119 } 00120 const ILVolume* lv = dynamic_cast<const ILVolume*>(obj); 00121 if (!lv) { 00122 warning() << "failed to dynamic_cast<LVolume*>: " << names[0] << endreq; 00123 return StatusCode::FAILURE; 00124 } 00125 const IPVolume* pv = (*lv)[names[1]]; 00126 lv = pv->lvolume(); 00127 NameHistory_t reverse; 00128 for (string::size_type iname = 2; iname < names.size(); ++iname) { 00129 pv = (*lv)[names[iname]]; 00130 reverse.push_back(LvPvPair_t(lv->name(),pv->name())); 00131 lv = pv->lvolume(); 00132 } 00133 name_history.insert(name_history.end(),reverse.rbegin(),reverse.rend()); 00134 } 00135 00136 name_history.push_back(LvPvPair_t(names[0],names[1])); 00137 00138 } // loop over history 00139 00140 if (!de) { 00141 const int depth = inHistory->GetHistoryDepth(); 00142 warning() << "failed to find top level supporting DetectorElement, history has depth of " << depth << "\n"; 00143 for (int ind=0; ind < depth; ++ind) { 00144 G4VPhysicalVolume* g4pv = inHistory->GetVolume(ind); 00145 warning() << "\n\t(" << ind << ") " << g4pv->GetName(); 00146 } 00147 warning() << endreq; 00148 return StatusCode::FAILURE; 00149 } 00150 00151 de = this->FindDE(de,name_history); 00152 if (!de) { 00153 warning() << "failed to find DetectorElement for TouchableHistory:\n" << dumpstr(inHistory) << endreq; 00154 return StatusCode::FAILURE; 00155 } 00156 00157 m_THcache[th] = de; 00158 outElement = de; 00159 outCompatibility = name_history.size(); 00160 return StatusCode::SUCCESS; 00161 } 00162 00163 int TH2DE::InHistory(const IDetectorElement* de, const NameHistory_t& name_history) 00164 { 00165 const IGeometryInfo* gi = de->geometry(); 00166 if (!gi->hasSupport()) return -1; 00167 00168 const ILVolume::ReplicaPath& rpath = gi->supportPath(); 00169 const IGeometryInfo* support_gi = gi->supportIGeometryInfo(); 00170 const ILVolume* lv = support_gi->lvolume(); 00171 00172 verbose() << "InHistory de=" << de->name() << endreq; 00173 00174 // Walk the DE's support and match against name_history; 00175 size_t index = name_history.size(); 00176 for (size_t ind = 0; index && ind < rpath.size(); ++ind) { 00177 IPVolume* pv = lv->pvolumes()[rpath[ind]]; 00178 00179 --index; 00180 const LvPvPair_t& check = name_history[index]; 00181 00182 verbose() << "("<<index<<") lvpv=" << lv->name() << "#" << pv->name() 00183 << " =?= " 00184 << check.first << "#" << check.second << endreq; 00185 00186 if (lv->name() != check.first) return -1; 00187 if (pv->name() != check.second) return -1; 00188 00189 lv = pv->lvolume(); 00190 } 00191 return index; 00192 } 00193 00194 const IDetectorElement* TH2DE::FindChildDE(const IDetectorElement* de, NameHistory_t& name_history) 00195 { 00196 IDetectorElement::IDEContainer& children = de->childIDetectorElements(); 00197 size_t nchildren = children.size(); 00198 verbose() << "Finding children from " << nchildren << endreq; 00199 for (size_t ichild = 0; ichild < nchildren; ++ichild) { 00200 IDetectorElement* child = children[ichild]; 00201 int index = this->InHistory(child,name_history); 00202 00203 if (index<0) continue; 00204 00205 verbose() << "Found child: " << child->name() << " at index " <<index<<" lv#pv=" << name_history[index].first << "#"<< name_history[index].second << endreq; 00206 00207 // strip off used history 00208 while ((int)name_history.size() > index) { 00209 LvPvPair_t lvpv = name_history.back(); 00210 verbose () << "\tpoping: index="<<index<<", size=" << name_history.size() << " [" << lvpv.first << "#" << lvpv.second << "]" << endreq; 00211 name_history.pop_back(); 00212 } 00213 return child; 00214 } 00215 return 0; 00216 } 00217 00218 const IDetectorElement* TH2DE::FindDE(const IDetectorElement* de, NameHistory_t& name_history) 00219 { 00220 // If exhausted the NH then the current DE must be the one 00221 if (!name_history.size()) return de; 00222 00223 00224 #if 0 00225 debug() << "FindDE: " << de->name() << endreq; 00226 for (size_t inh=0; inh<name_history.size(); ++inh) { 00227 debug() << inh <<": " << name_history[inh].first << "#" << name_history[inh].second << endreq; 00228 } 00229 #endif 00230 00231 LvPvPair_t lvpv(name_history.back().first,name_history.back().second); 00232 00233 string de_lvname = de->geometry()->lvolumeName(); 00234 if (de_lvname != lvpv.first) { 00235 warning() << "The given DE's LV does not match LV from top of history: " 00236 << de_lvname <<" != "<< lvpv.first << endreq; 00237 return 0; 00238 } 00239 00240 // Find immediate child that points into the history 00241 const IDetectorElement* child_de = this->FindChildDE(de,name_history); 00242 00243 // If one found, recurse. 00244 if (child_de) return this->FindDE(child_de,name_history); 00245 00246 // If we get here, we have reached the end of possible DEs. 00247 // Pop off the touchable history coresponding to current DE and return; 00248 name_history.pop_back(); 00249 return de; 00250 } 00251 00252 const IDetectorElement* TH2DE::CheckCache(const G4TouchableHistory* g4hist) 00253 { 00254 TouchableHistory_t th; 00255 const int depth = g4hist->GetHistoryDepth(); 00256 for (int ind=0; ind < depth; ++ind) { 00257 G4VPhysicalVolume* g4pv = g4hist->GetVolume(ind); 00258 th.push_back(g4pv); 00259 } 00260 return m_THcache[th]; 00261 } 00262 00263 StatusCode TH2DE::G4VolumeToDetDesc(const G4VPhysicalVolume* inVol, 00264 const IPVolume* &outVol) 00265 { 00266 00267 if (!inVol) { 00268 warning() << "TH2DE: No PhysicalVolume detected! " <<endreq; 00269 return StatusCode::FAILURE; 00270 } 00271 outVol = m_PVcache[inVol]; 00272 if (outVol) return StatusCode::FAILURE; 00273 00274 vector<string> names; 00275 split(names,inVol->GetName(),'#'); 00276 00277 DataObject* obj = 0; 00278 StatusCode sc = detSvc()->retrieveObject(names[0],obj); 00279 if (sc.isFailure()) return sc; 00280 00281 if (names.size() == 1) { // this PV is named after a detector element 00282 const IDetectorElement* de = dynamic_cast<const IDetectorElement*>(obj); 00283 const IGeometryInfo* gi = de->geometry(); 00284 const ILVolume* lv_target = gi->lvolume(); 00285 const ILVolume* lv = gi->supportIGeometryInfo()->lvolume(); 00286 const ILVolume::ReplicaPath& rpath = gi->supportPath(); 00287 const IPVolume* pv = 0; 00288 for (size_t ind=0; ind < rpath.size(); ++ind) { 00289 pv = lv->pvolumes()[rpath[ind]]; 00290 if (!pv) return StatusCode::FAILURE; 00291 lv = pv->lvolume(); 00292 if (!lv) return StatusCode::FAILURE; 00293 } 00294 if (lv != lv_target) { 00295 warning() << "Don't come full circle: " << lv_target->name() << " != " << lv->name() << endreq; 00296 return StatusCode::FAILURE; 00297 } 00298 outVol = pv; 00299 } 00300 else { 00301 const ILVolume* lv = dynamic_cast<const ILVolume*>(obj); 00302 const IPVolume* pv = (*lv)[names[1]]; 00303 if (!pv) return StatusCode::FAILURE; 00304 00305 if (names.size() > 2) { // have pv1#pv2#pv3 style path 00306 lv = pv->lvolume(); 00307 if (!lv) return StatusCode::FAILURE; 00308 00309 for (string::size_type iname = 2; iname < names.size(); ++iname) { 00310 pv = (*lv)[names[iname]]; 00311 if (!pv) return StatusCode::FAILURE; 00312 lv = pv->lvolume(); 00313 if (!lv) return StatusCode::FAILURE; 00314 } 00315 } 00316 outVol = pv; 00317 } 00318 if (outVol) { 00319 m_PVcache[inVol] = outVol; 00320 return StatusCode::SUCCESS; 00321 } 00322 return StatusCode::FAILURE; 00323 } 00324 00325 StatusCode TH2DE::ClearCache() 00326 { 00327 m_THcache.clear(); 00328 m_PVcache.clear(); 00329 return StatusCode::SUCCESS; 00330 }