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>& ,
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;
00072 NameHistory_t name_history;
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) {
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) {
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 }
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
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
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
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
00241 const IDetectorElement* child_de = this->FindChildDE(de,name_history);
00242
00243
00244 if (child_de) return this->FindDE(child_de,name_history);
00245
00246
00247
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) {
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) {
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 }