/search.css" rel="stylesheet" type="text/css"/> /search.js">
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

TH2DE.cc
Go to the documentation of this file.
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 }
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Fri May 16 2014 10:05:42 for G4DataHelpers by doxygen 1.7.4