00001
00002
00003
00004
00005
00006
00007 #include "Geometry/Geometry.h"
00008 extern "C" {
00009 #include <sys/types.h>
00010 #include <sys/stat.h>
00011 }
00012 #include <cassert>
00013 #include <map>
00014 #include <iostream>
00015 #include "TObjArray.h"
00016 #include "TGeoManager.h"
00017 #include "TGeoNode.h"
00018 #include "TGeoBBox.h"
00019 #include "Geometry/Exception.h"
00020 #include "Geometry/PlaneGeo.h"
00021 #include "Geometry/CellGeo.h"
00022 #include "Geometry/CellUniqueId.h"
00023 #include "JobControl/Exception.h"
00024 #include "RawData/DAQHeader.h"
00025 using namespace geo;
00026
00027 Geometry* Geometry::fInstance = 0;
00028
00029 static bool plane_sort(const PlaneGeo* p1, const PlaneGeo* p2)
00030 {
00031 double xyz1[3], xyz2[3];
00032 p1->Cell(0).GetCenter(xyz1);
00033 p2->Cell(0).GetCenter(xyz2);
00034 return xyz1[2]<xyz2[2];
00035 }
00036
00037
00038
00048 Geometry& Geometry::Instance(int runnum, short detId)
00049 {
00050
00051 if (fInstance!=0) {
00052 if (fInstance->fRunNumber != runnum || fInstance->fDetId != detId) {
00053 delete fInstance;
00054 fInstance = 0;
00055 gGeoManager->Clear();
00056 }
00057 }
00058
00059
00060 if (fInstance==0) {
00061 static char* fname[3] = {"neardet.gdml","fardet.gdml","ipnd.gdml"};
00062 if (detId!=rawdata::kNear &&
00063 detId!=rawdata::kFar &&
00064 detId!=rawdata::kIPND) {
00065 char msg[256];
00066 sprintf(msg,"Unknown detector id number: %d",(int)detId);
00067 throw Exception(__FILE__,__LINE__,Exception::BAD_GEO_CONFIG,msg);
00068 }
00069 if (runnum<0) {
00070 char msg[256];
00071 std::sprintf(msg,"Bad run number: %d",runnum);
00072 throw Exception(__FILE__,__LINE__,Exception::BAD_GEO_CONFIG,msg);
00073 }
00074 fInstance = new Geometry(fname[detId]);
00075 fInstance->fDetId = detId;
00076 fInstance->fRunNumber = runnum;
00077 }
00078 return *fInstance;
00079 }
00080
00081
00082
00083 Geometry::Geometry(const char* gdmlfile)
00084 {
00085 std::string fname;
00086
00087
00088
00089 while (1) {
00090 struct stat sb;
00091 fname = gdmlfile;
00092 if (stat(fname.c_str(), &sb)==0) break;
00093
00094 const char* srt_private = getenv("SRT_PRIVATE_CONTEXT");
00095 if (srt_private!=0) {
00096 fname = srt_private;
00097 fname += "/Geometry/gdml/";
00098 fname += gdmlfile;
00099 if (stat(fname.c_str(), &sb)==0) break;
00100 }
00101
00102 const char* srt_public = getenv("SRT_PUBLIC_CONTEXT");
00103 if (srt_public!=0) {
00104 fname = srt_public;
00105 fname += "/Geometry/gdml/";
00106 fname += gdmlfile;
00107 if (stat(fname.c_str(), &sb)==0) break;
00108 }
00109
00110
00111 throw Exception(__FILE__, __LINE__, Exception::FILE_NOT_FOUND,
00112 "GDML file not found.");
00113 }
00114
00115
00116 TGeoManager::Import(fname.c_str());
00117 this->SetDrawOptions();
00118
00119 std::vector<const TGeoNode*> n(16);
00120 n[0] = gGeoManager->GetTopNode();
00121 this->FindPlanes(n, 0);
00122 sort(fPlanes.begin(), fPlanes.end(), plane_sort);
00123
00124 this->SetDetectorSize();
00125 this->BuildMaps();
00126 }
00127
00128
00129
00130 Geometry::~Geometry()
00131 {
00132 for (unsigned int i=0; i<fPlanes.size(); ++i) {
00133 if (fPlanes[i]) { delete fPlanes[i]; fPlanes[i] = 0; }
00134 }
00135 }
00136
00137
00146 int Geometry::CurrentCell(int* planeid, int* cellid) const
00147 {
00148 try {
00149 this->IdToCell(this->CurrentCellId(), planeid, cellid);
00150 }
00151 catch (Exception e) {
00152 *planeid = -1;
00153 *cellid = -1;
00154 return -1;
00155 }
00156 return 1;
00157 }
00158
00159
00163 const CellUniqueId Geometry::CurrentCellId() const
00164 {
00165 return PathToUniqueId(gGeoManager->GetPath());
00166 }
00167
00168
00169
00170 const TGeoMaterial* Geometry::Material(double x, double y, double z) const
00171 {
00172 const TGeoNode* node = gGeoManager->FindNode(x,y,z);
00173 return node->GetMedium()->GetMaterial();
00174 }
00175
00176
00177
00178 double Geometry::DetHalfWidth() const
00179 {
00180 return fDetHalfWidth;
00181 }
00182
00183
00184
00185 double Geometry::DetHalfHeight() const
00186 {
00187 return fDetHalfHeight;
00188 }
00189
00190
00191
00192 double Geometry::DetLength() const
00193 {
00194 return fDetLength;
00195 }
00196
00197
00198
00210 double Geometry::SurfaceY() const
00211 {
00212 switch (fDetId) {
00213 case 0: return 130.0E2;
00214 case 1: return 9.94E2;
00215 case 2: return -1.966E2;
00216 default: throw Exception(__FILE__,__LINE__,Exception::BAD_GEO_CONFIG);
00217 }
00218 return 0.0;
00219 }
00220
00233 void Geometry::WorldBox(double* xlo, double* xhi,
00234 double* ylo, double* yhi,
00235 double* zlo, double* zhi) const
00236 {
00237 const TGeoShape* s = gGeoManager->GetVolume("vWorld")->GetShape();
00238 assert(s);
00239
00240 if (xlo || xhi) {
00241 double x1, x2;
00242 s->GetAxisRange(1,x1,x2); if (xlo) *xlo = x1; if (xhi) *xhi = x2;
00243 }
00244 if (ylo || yhi) {
00245 double y1, y2;
00246 s->GetAxisRange(2,y1,y2); if (ylo) *ylo = y1; if (yhi) *yhi = y2;
00247 }
00248 if (zlo || zhi) {
00249 double z1, z2;
00250 s->GetAxisRange(3,z1,z2); if (zlo) *zlo = z1; if (zhi) *zhi = z2;
00251 }
00252 }
00253
00254
00255
00256 void Geometry::SetDrawOptions() { }
00257
00258
00259
00267 void Geometry::FindPlanes(std::vector<const TGeoNode*>& n,
00268 unsigned int depth)
00269 {
00270 const char* nm = n[depth]->GetName();
00271 if (strncmp(nm,"vPlane", 6)==0) {
00272 this->MakePlane(n, depth);
00273 return;
00274 }
00275
00276
00277 unsigned int deeper = depth+1;
00278 if (deeper>=n.size()) {
00279 throw Exception(__FILE__,__LINE__,Exception::BAD_NODE,
00280 "Exceeded maximum depth.");
00281 }
00282 const TGeoVolume* v = n[depth]->GetVolume();
00283 int nd = v->GetNdaughters();
00284 for (int i=0; i<nd; ++i) {
00285 n[deeper] = v->GetNode(i);
00286 this->FindPlanes(n, deeper);
00287 }
00288 }
00289
00290
00291
00292 void Geometry::MakePlane(std::vector<const TGeoNode*>& n,
00293 unsigned int depth)
00294 {
00295 fPlanes.push_back(new PlaneGeo(n, depth));
00296 }
00297
00298
00307 const PlaneGeo& Geometry::Plane(unsigned int i) const
00308 {
00309 if (i>=fPlanes.size()) throw Exception(__FILE__,__LINE__,
00310 Exception::BAD_PLANE_NUMBER,
00311 "Plane index out of range");
00312 return *fPlanes[i];
00313 }
00314
00315
00327 const CellGeo& Geometry::IdToCell(const CellUniqueId& id,
00328 int* iplane,
00329 int* icell) const
00330 {
00331 UIDMap::const_iterator itr = fIdMap.find(id);
00332 if (itr == fIdMap.end()) {
00333 throw Exception(__FILE__,__LINE__,Exception::BAD_CELL_UNIQUE_ID);
00334 }
00335 *iplane = itr->second.first;
00336 *icell = itr->second.second;
00337 return this->Plane(*iplane).Cell(*icell);
00338 }
00339
00340
00347 const std::set<unsigned int>& Geometry::GetPlanesByView(View_t v) const
00348 {
00349
00350 if (v==kX) return fXplanes;
00351 else if (v==kY) return fYplanes;
00352 return fAllPlanes;
00353 }
00354
00355
00366 const unsigned int Geometry::NextPlaneInView(unsigned int p1, int d) const
00367 {
00368 assert(p1<fPlanes.size());
00369
00370
00371 int s = (d>0 ? 1 : -1);
00372 if (s<0 && p1==0) return kPLANE_NOT_FOUND;
00373 if (s>0 && p1==fPlanes.size()-1) return kPLANE_NOT_FOUND;
00374 for (unsigned int p2=p1+d; 1; p2+=s) {
00375 if (fPlanes[p1]->View() == fPlanes[p2]->View()) return p2;
00376 if (p2==fPlanes.size()-1) return kPLANE_NOT_FOUND;
00377 if (p2==0) return kPLANE_NOT_FOUND;
00378 }
00379 }
00380
00381
00391 const unsigned int Geometry::NextPlaneOtherView(unsigned int p1, int d) const
00392 {
00393 assert(p1<fPlanes.size());
00394
00395
00396 int s = (d>0 ? 1 : -1);
00397 if (s<0 && p1==0) return kPLANE_NOT_FOUND;
00398 if (s>0 && p1==fPlanes.size()-1) return kPLANE_NOT_FOUND;
00399 for (unsigned int p2=p1+d; 1; p2+=s) {
00400 if (fPlanes[p1]->View() != fPlanes[p2]->View()) return p2;
00401 if (p2==fPlanes.size()) return kPLANE_NOT_FOUND;
00402 if (p2==0) return kPLANE_NOT_FOUND;
00403 }
00404 }
00405
00406
00410 void Geometry::BuildMaps ()
00411 {
00412
00413 for (unsigned int i=0; i<fPlanes.size(); ++i) {
00414 fAllPlanes.insert(i);
00415 if (fPlanes[i]->View()==kX) fXplanes.insert(i);
00416 else if (fPlanes[i]->View()==kY) fYplanes.insert(i);
00417 else {
00418 throw Exception(__FILE__,__LINE__,Exception::BAD_GEO_CONFIG,
00419 "Bad plane view!");
00420 }
00421 }
00422
00423
00424 for (unsigned int i=0; i<fPlanes.size(); ++i) {
00425 const PlaneGeo* p = fPlanes[i];
00426 for (int j=0; j<p->Ncells(); ++j) {
00427
00428 if (fIdMap.find(this->Plane(i).Cell(j).Id())!=fIdMap.end()) {
00429 throw Exception(__FILE__,__LINE__,Exception::BAD_CELL_UNIQUE_ID,
00430 "Duplicate Cell UIDs");
00431 }
00432 PlaneCellPair p(i,j);
00433 fIdMap[this->Plane(i).Cell(j).Id()] = p;
00434 }
00435 }
00436 }
00437
00438
00439
00444 void Geometry::SetDetectorSize()
00445 {
00446 double dummy;
00447
00448
00449
00450
00451
00452
00453 const TGeoVolume* vvp = gGeoManager->GetVolume("vPlaneV");
00454 const TGeoVolume* hvp = gGeoManager->GetVolume("vPlaneH");
00455
00456
00457
00458 if (vvp==0) vvp = gGeoManager->GetVolume("vPlaneVIPND");
00459 if (hvp==0) hvp = gGeoManager->GetVolume("vPlaneHIPND");
00460 if (vvp==0 && hvp==0) {
00461 vvp = gGeoManager->GetVolume("vPlaneVIPND");
00462 hvp = gGeoManager->GetVolume("vPlaneHIPND");
00463 }
00464 if (vvp==0 || hvp==0) {
00465 throw Exception(__FILE__,__LINE__,
00466 Exception::BAD_GEO_CONFIG,
00467 "Unable to find shapes to set detector size");
00468 }
00469
00470 const TGeoShape* vp = vvp->GetShape();
00471 const TGeoShape* hp = hvp->GetShape();
00472 vp->GetAxisRange(3,dummy,fDetHalfHeight);
00473 hp->GetAxisRange(3,dummy,fDetHalfWidth);
00474
00475
00476
00477 double vplanez1, vplanez2;
00478 vp->GetAxisRange(2,vplanez1,vplanez2);
00479
00480
00481
00482
00483
00484
00485
00486 double xyz1[3] = {0,0,0};
00487 double xyz2[3] = {0,0,0};
00488 this->Plane(0). Cell(0).GetCenter(xyz1);
00489 this->Plane(fPlanes.size()-1).Cell(0).GetCenter(xyz2);
00490 fDetLength = (xyz2[2]-xyz1[2])+(vplanez2-vplanez1);
00491 }
00492