00001 #include "TouchableToDetectorElement.h"
00002
00003 #include "G4TouchableHistory.hh"
00004
00005 #include "DetDesc/ILVolume.h"
00006 #include "DetDesc/IPVolume.h"
00007 #include "DetDesc/IDetectorElement.h"
00008 #include "DetDesc/IGeometryInfo.h"
00009
00010 #include "GaudiKernel/DataObject.h"
00011 #include "GaudiKernel/IRegistry.h"
00012 #include "GaudiKernel/RegistryEntry.h"
00013 #include "GaudiKernel/DataObject.h"
00014
00015 #include <vector>
00016
00017 TouchableToDetectorElement::TouchableToDetectorElement(
00018 const std::string& type,
00019 const std::string& name,
00020 const IInterface* parent)
00021 : GaudiTool(type,name,parent)
00022 {
00023 declareInterface<ITouchableToDetectorElement>(this);
00024
00025 }
00026
00027
00028 StatusCode TouchableToDetectorElement::G4VolumeToDetDesc(
00029 const G4VPhysicalVolume* inVol,
00030 const IPVolume* &outVol )
00031 {
00035 ILVolume::ReplicaPath rp;
00036 return G4VolumeToDetDesc(inVol,outVol,rp);
00037 }
00038
00039 StatusCode TouchableToDetectorElement::G4VolumeToDetDesc(
00040 const G4VPhysicalVolume* inVol,
00041 const IPVolume* &outVol,
00042 ILVolume::ReplicaPath& outPath )
00043 {
00053
00054 if(!inVol) {
00055 return StatusCode::FAILURE;
00056 }
00057
00058 std::string pvpath = inVol->GetName();
00059
00060 const ILVolume* lv = 0;
00061 const IPVolume* pv = 0;
00062
00063
00064 std::string lname = pvpath;
00065 std::string::size_type p = pvpath.find_first_of('#');
00066 if(p!= std::string::npos) {
00067 lname = pvpath.substr(0,p);
00068 pvpath.erase(0,p+1);
00069 }
00070
00071
00072 if(!exist<ILVolume>(detSvc(),lname,false)) {
00073 err() << "Can't find lvolume at path " << lname << " when parsing physvol " << inVol->GetName() << endreq;
00074 return StatusCode::FAILURE;
00075 }
00076 lv= getDet<ILVolume>(lname);
00077
00078
00079 while(pvpath.size() > 0) {
00080
00081 if(!lv) {
00082 err() << "Can't find lvolume." << endreq;
00083 return StatusCode::FAILURE;
00084 }
00085
00086
00087 std::string pname = pvpath;
00088 std::string::size_type p = pvpath.find_first_of('#');
00089 if(p != std::string::npos ) {
00090 pname.erase(p,std::string::npos);
00091 pvpath.erase(0,p+1);
00092 } else {
00093 pvpath.erase();
00094 }
00095
00096 ILVolume::ReplicaType replica = 0;
00097 pv = 0;
00098 for ( ILVolume::ReplicaType i = 0; i< lv->noPVolumes(); ++i ){
00099 const IPVolume* apv = lv->pvolume(i);
00100 if(!apv) {
00101 err() << "Bad link to IPVolume from " << lv->name() << endreq;
00102 return StatusCode::FAILURE;
00103 }
00104
00105 if(apv->name() == pname){ pv = apv; replica = i; break;}
00106 }
00107
00108 if(!pv) {
00109 err() << "Couldn't find a match for physical volume with name " << pname << " in lvolume name " << lv->name() << endreq;
00110 return StatusCode::FAILURE;
00111 }
00112
00113 outPath.push_back(replica);
00114
00115
00116 lv = pv->lvolume();
00117 }
00118
00119 outVol = pv;
00120
00121 return StatusCode::SUCCESS;
00122 }
00123
00124
00125
00126 template <class T>
00127 StatusCode TouchableToDetectorElement::FindObjectsInDirectory(
00128 const std::string& dirname,
00129 std::vector<const T*>& list
00130 )
00131 {
00135 info() << "Looking for structures in " << dirname << endreq;
00136 if (!existDet<DataObject>(dirname)) {
00137 err() << "No " << dirname << " in TDS" << endreq;
00138 return StatusCode::FAILURE;
00139 }
00140 const DataObject *d = getDet<DataObject>(dirname);
00141
00142 const T* t = dynamic_cast<const T*>(d);
00143 if(t) list.push_back(t);
00144
00145 IRegistry* dr = d->registry();
00146 using namespace DataSvcHelpers;
00147 RegistryEntry* dre = dynamic_cast<RegistryEntry*>(dr);
00148 if (!dre) {
00149 err() << "Failed to get RegistryEntry on DataObject" << d << endreq;
00150 return StatusCode::FAILURE;
00151 }
00152
00153 RegistryEntry::Iterator it = dre->begin(), done = dre->end();
00154 for (; it != done; ++it) {
00155 std::string id = (*it)->identifier();
00156 StatusCode sc = FindObjectsInDirectory<T>(id,list);
00157 if(sc.isFailure()) return sc;
00158 }
00159
00160 return StatusCode::SUCCESS;
00161 }
00162
00163
00164 StatusCode TouchableToDetectorElement::GetBestDetectorElement(
00165 const G4TouchableHistory* inHistory,
00166 const std::vector<std::string>& inPaths,
00167 const IDetectorElement* &outElement,
00168 int& outCompatibility )
00169 {
00170 TouchableToDetectorElement::SpecifiedVolume g4place;
00171 StatusCode sc = GetSpecifiedVolume(inHistory, g4place);
00172 if(sc.isFailure()) return sc;
00173
00174
00175 outCompatibility = 0x7fffffff;
00176 outElement = g4place.mTop;
00177
00178
00179
00180 std::vector<const IDetectorElement*> elements;
00181
00182
00183 for(unsigned int i = 0; i< inPaths.size(); ++i) {
00184 sc = FindObjectsInDirectory<IDetectorElement>(inPaths[i],elements);
00185 if(sc.isFailure()) return sc;
00186 }
00187
00188
00189 for(unsigned int i=0; i<elements.size(); ++i) {
00190 TouchableToDetectorElement::SpecifiedVolume trialVolume;
00191 sc = GetSpecifiedVolume(elements[i], g4place.mTop, trialVolume);
00192 if(sc.isFailure()) continue;
00193
00194 int compat = Compatability(g4place,trialVolume);
00195 if((compat >= 0) && (compat<outCompatibility)) {
00196 outElement = elements[i];
00197 outCompatibility = compat;
00198 }
00199 }
00200
00201 return StatusCode::SUCCESS;
00202 }
00203
00204 StatusCode TouchableToDetectorElement::GetSpecifiedVolume(
00205 const G4TouchableHistory* inHistory,
00206 TouchableToDetectorElement::SpecifiedVolume& outVol)
00207 {
00208
00209 if(!inHistory) {
00210 err() << "No good TouchableHistory provided." << endreq;
00211 return StatusCode::FAILURE;
00212 }
00213
00214
00215 G4VPhysicalVolume* top = inHistory->GetVolume(inHistory->GetHistoryDepth()-1);
00216 if(!top) {
00217 err() << "Got null G4VPhysicalVolume pointer in the bottom of G4TouchableHistory. Huh???" << endreq;
00218 return StatusCode::FAILURE;
00219 }
00220 if(!exist<IDetectorElement>(detSvc(),top->GetName()),false) {
00221 err() << "Can't find detector element at the bottom of the G4TouchableHistory, name = " << top->GetName() << endreq;
00222 return StatusCode::FAILURE;
00223 }
00224
00225 outVol.mTop = getDet<IDetectorElement>(top->GetName());
00226 outVol.mRpath.clear();
00227
00228
00229
00230
00231
00232
00233 for(int ind=inHistory->GetHistoryDepth()-2; ind>=0; --ind){
00234 G4VPhysicalVolume* g4pv = inHistory->GetVolume(ind);
00235
00236 ILVolume::ReplicaPath subpath;
00237 const IPVolume* pv;
00238 StatusCode sc = G4VolumeToDetDesc(g4pv,pv,subpath);
00239 if(sc.isFailure()) return sc;
00240
00241
00242 outVol.mRpath.insert(outVol.mRpath.end(),subpath.begin(),subpath.end());
00243
00244 }
00245
00246 return StatusCode::SUCCESS;
00247 }
00248
00249 StatusCode TouchableToDetectorElement::GetSpecifiedVolume(const IDetectorElement* inElem, const IDetectorElement* inTopElem, TouchableToDetectorElement::SpecifiedVolume& outVol)
00250 {
00254 const IGeometryInfo* topGeo = inTopElem->geometry();
00255 const IGeometryInfo* trialGeo = inElem->geometry();
00256
00257
00258 outVol.mRpath.clear();
00259 outVol.mTop = 0;
00260
00261 const IGeometryInfo* curGeo = trialGeo;
00262 while(curGeo!=topGeo) {
00263
00264
00265
00266 ILVolume::ReplicaPath rpath;
00267 IGeometryInfo* nextGeo;
00268 curGeo->location(nextGeo, rpath);
00269 curGeo = nextGeo;
00270 outVol.mRpath.insert(outVol.mRpath.begin(),rpath.begin(),rpath.end());
00271 if(0==curGeo) break;
00272 }
00273 if(curGeo==topGeo) outVol.mTop = inTopElem;
00274 else outVol.mTop = 0;
00275
00276
00277
00278
00279
00280
00281
00282
00283 return StatusCode::SUCCESS;
00284 }
00285
00287 int TouchableToDetectorElement::Compatability(const TouchableToDetectorElement::SpecifiedVolume& inPlace, const TouchableToDetectorElement::SpecifiedVolume& inContainer)
00288 {
00289
00290
00291 if(inPlace.mTop != inContainer.mTop) return -1;
00292
00293
00294
00295
00296 if(inContainer.mRpath.size() > inPlace.mRpath.size()) return -1;
00297
00298
00299 for(unsigned int i=0; i< inContainer.mRpath.size(); ++i ){
00300 if(inContainer.mRpath[i] != inPlace.mRpath[i]) return -1;
00301 }
00302
00303
00304
00305
00306 return inPlace.mRpath.size() - inContainer.mRpath.size();
00307 }
00308
00309