Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Geometry.cxx

Go to the documentation of this file.
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   // If our current geometry doesn't match request, get rid of it
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   // Build a new geometry if we need to
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   // Test if the gdml file can be openned using exactly the name we've
00088   // been passed
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     // Failed to resolve the file name
00111     throw Exception(__FILE__, __LINE__, Exception::FILE_NOT_FOUND,
00112                     "GDML file not found.");
00113   }
00114 
00115   // Open the GDML file
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; // near det: surface ~130m up from det. center
00214   case 1: return 9.94E2;  // far det: surface ~10m up from det. center
00215   case 2: return -1.966E2;  // IPND: surface ~2 meter below det, center
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   // Explore the next layer down
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   // Return the user's choice, fall back on all planes
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   // March along from p1 in the direction d until we find a match
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   // March along from p1 in the direction d until we find a match
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   // Sets which list planes by view
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   // Unique Id -> cell map
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       // Assert that the cell ids are in fact unique
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   // Compute the height and width based on the sizes of the vertical
00449   // and horizontal planes. Remember, in the local plane frame z goes
00450   // along the length of the modules. Hence the use of axis=3 to get
00451   // the detector height (from the vertical planes) and width (from
00452   // the horizontal planes).
00453   const TGeoVolume* vvp = gGeoManager->GetVolume("vPlaneV");
00454   const TGeoVolume* hvp = gGeoManager->GetVolume("vPlaneH");
00455 
00456   // Handle the case of the IPND where the volumes are names slightly
00457   // different accounting for the different widths of the modules.
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   // Remember -- in the local plane coordinate frame, the "depth" is
00476   // along y, hence axis=2. In the world coordinate this is along z.
00477   double vplanez1, vplanez2;
00478   vp->GetAxisRange(2,vplanez1,vplanez2);
00479   
00480   // Compute the detector length based on the center positions of
00481   // cells in the first and last plane. Adjust to account for the
00482   // plane widths. This ajustment works if the vertical and horizontal
00483   // planes have the same depth, or if the detector begins and ends
00484   // with vertical planes. As of the TDR both of these conditions was
00485   // true for all the NOvA detectors.
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 

Generated on Mon Dec 1 02:35:18 2008 for NOvA Offline by  doxygen 1.3.9.1