Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

GeoGeometry.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // GeoGeometry
00004 //
00005 // GeoGeometry is single geometry constructed using the TGeoManager
00006 //
00007 // Author:  S. Kasahara 11/03
00008 //
00009 // Based on R. Hatcher's UgliGeometry/UgliGeometry class.
00011 
00012 #include <iostream>
00013 #include <cassert>
00014 using namespace std;
00015 
00016 #include "TGeoManager.h"
00017 #include "TGeoNode.h"
00018 #include "TGeoBBox.h"
00019 
00020 #include "Conventions/Munits.h"
00021 #include "GeoGeometry/Geo.h"
00022 #include "GeoGeometry/GeoGeometry.h"
00023 #include "GeoGeometry/GeoScintPlnVolume.h"
00024 #include "GeoGeometry/GeoSteelPlnVolume.h"
00025 #include "GeoGeometry/GeoStripVolume.h"
00026 #include "GeoGeometry/GeoScintMdlVolume.h"
00027 #include "GeoGeometry/GeoStripNode.h"
00028 #include "GeoGeometry/GeoScintMdlNode.h"
00029 #include "GeoGeometry/GeoScintPlnNode.h"
00030 #include "GeoGeometry/GeoSteelPlnNode.h"
00031 #include "UgliGeometry/UgliDbiTables.h"
00032 #include "UgliGeometry/UgliDbiStructHash.h"
00033 #include "MessageService/MsgService.h"
00034 #include "Plex/PlexVetoShieldHack.h"
00035 
00036 ClassImp(GeoGeometry)
00037 
00038 CVSID("$Id: GeoGeometry.cxx,v 1.22 2005/06/27 16:47:06 schubert Exp $");
00039 
00040 //_____________________________________________________________________________
00041 GeoGeometry::GeoGeometry() : fVldRange(),fAppType(Geo::kRecons),
00042                              fScale(1),fGeoManager(0) {
00043   // Default constructor
00044 
00045   UpdateGlobalManager();
00046 
00047   for ( int ism = 0; ism < 2; ism++ ) { 
00048      fSMZMin[ism] = +999.*fScale; 
00049      fSMZMax[ism] = -999.*fScale; 
00050   }
00051   
00052   MSG("Geo",Msg::kVerbose) << "GeoGeometry def ctor @ " << this << endl;
00053 
00054 }
00055 
00056 //_____________________________________________________________________________
00057 GeoGeometry::GeoGeometry(const VldContext &vldc, Geo::EAppType apptype) : 
00058   fVldRange(),fAppType(apptype),fScale(1),fGeoManager(0) {
00059   // Normal constructor
00060   // Geometry is built for application type Geo::kRecons by default.
00061   // The application type determines the units the geometry will be built
00062   // in.  The default apptype = Geo::kRecons will build the geometry in
00063   // Minos standard units of meters.  Specifying apptype = Geo::kVMC will
00064   // build the geometry in TVirtualMC standard units of cm.
00065   
00066   UpdateGlobalManager(); // set gGeoManager to null before building new 
00067 
00068   MSG("Geo",Msg::kVerbose) << "GeoGeometry normal ctor @ " << this << endl;
00069   
00070   //MsgStream* msgeo = MsgService::Instance() -> GetStream("Geo");
00071   //msgeo -> SetLogLevel(Msg::kDebug);
00072   
00073   for ( int ism = 0; ism < 2; ism++ ) { 
00074      fSMZMin[ism] = +999.*fScale; 
00075      fSMZMax[ism] = -999.*fScale; 
00076   }
00077 
00078   fScale = Geo::GetScale(apptype);
00079 
00080   TString name = vldc.AsString("s1ac-");
00081   fGeoManager = new TGeoManager(name.Data(),"a MINOS geometry");
00082   UpdateGlobalManager(); // set gGeoManager to fGeoManager
00083   
00084   // Build all materials and detector geometry
00085   this -> BuildAll(vldc);
00086   fGeoManager->CloseGeometry();
00087 
00088   TGeoVolume* volume = fGeoManager->GetTopVolume();
00089   UpdateNodeMatrices(volume);
00090   
00091   //this -> DumpVolume("MARS");
00092   
00093   fGeoManager->SetVisLevel(3);
00094   fGeoManager->SetVisOption(0);
00095 
00096 
00097 }
00098 
00099 //_____________________________________________________________________________
00100 GeoGeometry::~GeoGeometry() {
00101   // delete all the owned sub-objects
00102 
00103   UpdateGlobalManager();
00104 
00105   MSG("Geo",Msg::kVerbose) << "GeoGeometry dtor @ " << this << endl;
00106 
00107   fPlaneMap.clear();
00108   if ( fGeoManager ) {
00109     delete fGeoManager; fGeoManager = 0;
00110   }
00111 
00112   UpdateGlobalManager(); // set gGeoManager to null to avoid further use
00113   
00114 }
00115 
00116 //_____________________________________________________________________________
00117 void GeoGeometry::Draw(Option_t* volname) {
00118   // Public. Draw this geometry from volume volname (default "HALL")
00119 
00120   UpdateGlobalManager();
00121 
00122   std::string volnamestr(volname);
00123   if (volnamestr.empty()) volnamestr = "HALL"; 
00124    
00125   MSG("Geo",Msg::kInfo) << "GeoGeometry::Draw() from top volume " 
00126                         << volnamestr.empty() << "." << endl;
00127 
00128   if ( !fGeoManager ) {
00129     MSG("Geo",Msg::kWarning) << "Null fGeoManager" << endl;
00130     return;
00131   }
00132   
00133   TGeoVolume* topVol = fGeoManager -> GetVolume(volnamestr.c_str());
00134   if ( !topVol ) {
00135     MSG("Geo",Msg::kWarning) << "No volume of name " << volnamestr.c_str() 
00136                              << endl;
00137     return;
00138   }
00139   //fGeoManager->SetTopVisible();
00140    
00141   topVol -> Draw();
00142    
00143 }
00144 
00145 //_____________________________________________________________________________
00146 void GeoGeometry::DumpVolume(std::string volname, std::string preface) const {
00147   // Print information about volume down through all daughter nodes
00148 
00149   UpdateGlobalManager();
00150 
00151   TGeoVolume* volume = fGeoManager->GetVolume(volname.c_str());
00152   if ( !volume ) {
00153     cout << "No volume of name " << volname.c_str() << "!" << endl;
00154     return;
00155   }
00156   
00157   cout << preface.c_str() << "Volume " << volume->GetName() << ", shape:" 
00158        << endl;
00159   cout << preface.c_str();
00160   volume->GetShape()->InspectShape();
00161   
00162   Int_t ndaughter = volume -> GetNdaughters();
00163   if ( ndaughter > 0 ) 
00164     cout << preface.c_str() << ndaughter << " daughter nodes:" << endl;
00165   else
00166     cout << preface.c_str() << "No daughter nodes." << endl;
00167   
00168   for ( int id = 0; id < ndaughter; id++ ) {
00169     TGeoNode* daughternode = volume->GetNode(id);
00170     cout << preface.c_str() << "  " << id << ")" << daughternode->GetName() 
00171          << endl;
00172     cout << preface.c_str() << "  ";
00173     daughternode->GetMatrix()->Print();
00174     TGeoVolume* daughtervol = daughternode->GetVolume();
00175     this -> DumpVolume(daughtervol->GetName(),preface+"  ");
00176   }
00177   
00178 }
00179 
00180 //_____________________________________________________________________________
00181 std::string GeoGeometry::GetGeoCompatibleName(std::string name) {
00182   // Public Static method to return acceptable node or volume name
00183   // Symbol "/" is replaced with "f" to avoid conflict with "/" used in paths
00184   // Symbol "-" is replaced with "h" to avoid conflict with "-" used in
00185   // composite shapes. 
00186 
00187   std::string okayname = name;
00188   // Name cannot include "/" because of ambiguity with "/" used in
00189   // path to nodes. Replace "/" with "f".
00190   unsigned int ipos = okayname.find("/");
00191   while ( ipos != std::string::npos ) {
00192     okayname.replace(ipos,1,"f");
00193     ipos = okayname.find("/");
00194   }
00195 
00196   // Name cannot include "-" because of ambiguity with "-" used in
00197   // composite shapes. Replace "-" with "h".
00198   ipos = okayname.find("-");
00199   while ( ipos != std::string::npos ) {
00200     okayname.replace(ipos,1,"h");
00201     ipos = okayname.find("-");
00202   }
00203   
00204   return okayname; 
00205 }
00206 
00207 //_____________________________________________________________________________
00208 TVector3 GeoGeometry::GetHallExtentMin() const {
00209   // Purpose:: Return the min (x,y,z) of the detector hall in global
00210   // (MARS) coordinates.
00211 
00212   UpdateGlobalManager();
00213   
00214   TGeoVolume* linrVol = fGeoManager->GetVolume("LINR");
00215   GeoNode* hallNode = dynamic_cast<GeoNode*>(linrVol->GetNode(0));
00216   TGeoVolume* hallVol = hallNode -> GetVolume();
00217   TGeoBBox* hallBox = dynamic_cast<TGeoBBox*>(hallVol->GetShape());
00218   
00219   TVector3 localXYZ(-(hallBox->GetDX()),-(hallBox->GetDY()),
00220                     -(hallBox->GetDZ()));
00221   
00222   return (hallNode -> LocalToGlobal(localXYZ));
00223 
00224 }
00225 
00226 //_____________________________________________________________________________
00227 TVector3 GeoGeometry::GetHallExtentMax() const {
00228   // Purpose:: Return the max (x,y,z) of the detector hall in global
00229   // (MARS) coordinates.
00230 
00231   UpdateGlobalManager();
00232   
00233   TGeoVolume* linrVol = fGeoManager->GetVolume("LINR");
00234   GeoNode* hallNode = dynamic_cast<GeoNode*>(linrVol->GetNode(0));
00235   TGeoVolume* hallVol = hallNode -> GetVolume();
00236   TGeoBBox* hallBox = dynamic_cast<TGeoBBox*>(hallVol->GetShape());
00237   
00238   TVector3 localXYZ(+(hallBox->GetDX()),+(hallBox->GetDY()),
00239                     +(hallBox->GetDZ()));
00240   return (hallNode -> LocalToGlobal(localXYZ));
00241 
00242 }
00243 
00244 //_____________________________________________________________________________
00245 GeoSteelPlnNode* GeoGeometry::GetNearestSteelPlnNode(Double_t z) {
00246   // Public. Purpose:: Retrieve the nearest steel node for a given z
00247   // Notes: Method not const because GetSteelNodeMap builds map and stores as
00248   // data member.
00249 
00250   UpdateGlobalManager();
00251 
00252   MSG("Geo",Msg::kDebug) << "GeoGeometry::GetNearestSteelPlnNode to z " 
00253                          << z << "." << endl;
00254   assert(fGeoManager);
00255 
00256   const std::map<Float_t,GeoSteelPlnNode*>& stnodemap = GetSteelPlnNodeMap();
00257 
00258   // Steel planes in map are all in main detector block
00259   // Ordering of planes is lo to hi
00260   std::map<Float_t,GeoSteelPlnNode*>::const_iterator steelplnItr;
00261   
00262   // Lower bound returns steel plane with z value greater than or equal to key
00263   steelplnItr = stnodemap.lower_bound(z);
00264   GeoSteelPlnNode* loplnNode = 0;
00265   GeoSteelPlnNode* hiplnNode = 0;
00266   if ( steelplnItr != stnodemap.end() ) {
00267     hiplnNode = steelplnItr->second;
00268   }
00269   if ( steelplnItr != stnodemap.begin() ) {
00270     steelplnItr--;
00271     loplnNode = steelplnItr->second;
00272   }
00273   if ( hiplnNode == 0 ) return loplnNode;
00274   else if ( loplnNode == 0 ) return hiplnNode;
00275   
00276   // Bracketed by two planes, determine which is closer
00277   Double_t xyz_global[3] = {0,0,z};
00278   Double_t lo_xyz_local[3] = {0};       
00279   loplnNode->GlobalToLocal(xyz_global,lo_xyz_local);
00280   Double_t hi_xyz_local[3] = {0};       
00281   hiplnNode->GlobalToLocal(xyz_global,hi_xyz_local);
00282 
00283   if ( TMath::Abs(lo_xyz_local[2]) < TMath::Abs(hi_xyz_local[2]) ) {
00284     return loplnNode;
00285   }
00286   
00287   return hiplnNode;
00288 
00289 }
00290 
00291 //_____________________________________________________________________________
00292 PlexPlaneId GeoGeometry::GetPlaneIdFromZ(Double_t z) const {
00293   // Purpose:: Retrieve detector plane corresponding to input z
00294   // This routine checks bounds of plane to determine if z is actually in
00295   // plane.
00296   // Use PlexPlaneId::IsValid() to determine validity of returned PlexPlaneId.
00297   // If returned plex is invalid => z not in plane.
00298  
00299   UpdateGlobalManager();
00300   
00301   MSG("Geo",Msg::kDebug) << "GeoGeometry::GetPlaneIdFromZ " << z << "."<< endl;
00302   assert(fGeoManager);
00303 
00304   PlexPlaneId invalidplex;
00305 
00306   // Move through the plane map from low to high z
00307   PlaneMapConstItr plnItr;
00308   Double_t xyz_global[3] = {0,0,z};
00309   Double_t xyz_local[3] = {0};
00310       
00311   // fPlaneMap has scint & steel planes 
00312   for ( plnItr = fPlaneMap.begin();  plnItr != fPlaneMap.end(); ++plnItr) {
00313     if ( (plnItr->first).IsVetoShield() ) continue; // No shield
00314     GeoPlnNode* plnNode = dynamic_cast<GeoPlnNode*>(plnItr -> second);
00315     plnNode->GlobalToLocal(xyz_global,xyz_local);
00316     Float_t dz  = dynamic_cast<TGeoBBox*>(plnNode->GetVolume()->GetShape())
00317                   ->GetDZ();
00318     if ( TMath::Abs(xyz_local[2]) < dz ) {
00319       return plnItr->first;
00320     }
00321     else if ( xyz_local[2]  < -dz ) {
00322       // No possibility for intersection left assuming ordered planes from
00323       // lo to hi z
00324       return invalidplex;
00325     }
00326   }
00327 
00328   return invalidplex;
00329 
00330 }
00331 
00332 //_____________________________________________________________________________
00333 const vector<GeoPlnNode*>& GeoGeometry::GetPlnNodePtrVector() {
00334   // Public. Purpose:: Return collection of ptrs for all pln nodes in detector
00335 
00336   UpdateGlobalManager();
00337 
00338   if ( fPlnNodes.empty() ) {
00339     PlaneMapConstItr plnItr;
00340     for ( plnItr = fPlaneMap.begin(); plnItr != fPlaneMap.end(); ++plnItr) {
00341       GeoPlnNode* plnNode = plnItr->second;
00342       fPlnNodes.push_back(plnNode);
00343     }
00344   }
00345   
00346   return fPlnNodes;
00347 
00348 }
00349 
00350 //_____________________________________________________________________________
00351 GeoScintPlnNode* GeoGeometry::GetScintPlnNode(PlexPlaneId planeid) const {
00352   // Public. Purpose:: Retrieve the node for a particular plane
00353 
00354   UpdateGlobalManager();
00355 
00356   GeoScintPlnNode* plnnode = 0;
00357   if ( planeid.IsSteel() ) {
00358     MSG("Geo",Msg::kWarning) 
00359       << "GetScintPlnNode called with steel plane id " 
00360       << planeid.AsString() << endl;
00361     return 0;
00362   }
00363   
00364   PlaneMapConstItr citr = fPlaneMap.find(planeid);
00365   if ( citr != fPlaneMap.end() ) {
00366     plnnode = dynamic_cast<GeoScintPlnNode*>(citr->second);
00367   }
00368   
00369   return plnnode;
00370 
00371 }
00372 
00373 //_____________________________________________________________________________
00374 const vector<GeoScintPlnNode*>& GeoGeometry::GetScintPlnNodePtrVector() {
00375   // Purpose:: Return collection of ptrs for all scint pln nodes in detector
00376 
00377   UpdateGlobalManager();
00378 
00379   if ( fScintPlnNodes.empty() ) {
00380     PlaneMapConstItr plnItr;
00381     for ( plnItr = fPlaneMap.begin(); plnItr != fPlaneMap.end(); ++plnItr ){
00382       if ( !(plnItr->first).IsSteel() ) {
00383         fScintPlnNodes.push_back(
00384                               dynamic_cast<GeoScintPlnNode*>(plnItr->second));
00385       }
00386     }
00387   }
00388 
00389   return fScintPlnNodes;
00390 
00391 }
00392 
00393 //_____________________________________________________________________________
00394 GeoSteelPlnNode* GeoGeometry::GetSteelPlnNode(PlexPlaneId planeid) const {
00395   // Public. Purpose:: Retrieve the node for a particular plane
00396 
00397   UpdateGlobalManager();
00398 
00399   GeoSteelPlnNode* plnnode = 0;
00400   if ( !planeid.IsSteel() ) {
00401     MSG("Geo",Msg::kWarning) 
00402       << "GetSteelPlnNode called with non steel plane id " 
00403       << planeid.AsString() << endl;
00404     return 0;
00405   }
00406   
00407   PlaneMapConstItr citr = fPlaneMap.find(planeid);
00408   if ( citr != fPlaneMap.end() ) {
00409     plnnode = dynamic_cast<GeoSteelPlnNode*>(citr->second);
00410   }
00411   
00412   return plnnode;
00413 
00414 }
00415 
00416 //_____________________________________________________________________________
00417 const vector<GeoSteelPlnNode*>& GeoGeometry::GetSteelPlnNodePtrVector() {
00418   // Public. Purpose:: Return collection of ptrs for all steel pln nodes 
00419   // in detector
00420 
00421   UpdateGlobalManager();
00422 
00423   if ( fSteelPlnNodes.empty() ) {
00424     PlaneMapConstItr plnItr;
00425     for ( plnItr = fPlaneMap.begin(); plnItr != fPlaneMap.end(); ++plnItr ){
00426       if ( (plnItr->first).IsSteel() ) {
00427         fSteelPlnNodes.push_back(
00428                               dynamic_cast<GeoSteelPlnNode*>(plnItr->second));
00429       }
00430     }
00431   }
00432   
00433   return fSteelPlnNodes;
00434 
00435 }
00436 
00437 //_____________________________________________________________________________
00438 const std::map<Float_t,GeoSteelPlnNode*>& GeoGeometry::GetSteelPlnNodeMap() {
00439   // Public. Purpose:: Return collection of ptrs for all steel pln nodes 
00440   // in main body of detector, key'ed by z-position. 
00441 
00442   UpdateGlobalManager();
00443 
00444   if ( fSteelPlnNodeMap.empty() ) {
00445     PlaneMapConstItr plnItr;
00446     for ( plnItr = fPlaneMap.begin(); plnItr != fPlaneMap.end(); ++plnItr ){
00447       if ( (plnItr->first).IsSteel() ) {
00448         // For caldet, need to remove floor planes?
00449         fSteelPlnNodeMap.insert(make_pair(plnItr->second->GetZ0(),
00450                              dynamic_cast<GeoSteelPlnNode*>(plnItr->second)));
00451       }
00452     }
00453   }
00454   
00455   return fSteelPlnNodeMap;
00456 
00457 }
00458 
00459 //_____________________________________________________________________________
00460 GeoStripNode* GeoGeometry::GetStripNode(const PlexStripEndId& seid) const {
00461   // Public. Purpose:: Retrieve the node for a particular strip
00462  
00463   UpdateGlobalManager();
00464 
00465   GeoStripNode* stripnode = 0;
00466 
00467   // Retrieve the plane node and then the strip node
00468   GeoScintPlnNode* planenode = this -> GetScintPlnNode(seid);
00469   if ( planenode ) {
00470     stripnode = planenode -> GetStripNode(seid);
00471   }
00472 
00473   return stripnode;
00474 
00475 }
00476 
00477 //_____________________________________________________________________________
00478 void GeoGeometry::GetTransverseExtent(PlaneView::PlaneView_t view,
00479                                       Double_t& tmin, Double_t& tmax) const {
00480   // Public. Purpose: Retrieve transverse extent of detector
00481   // based on detector type and form.  These values are currently hardwired
00482   // as in UgliGeometry::GetTransverseExtent
00483 
00484   UpdateGlobalManager();
00485 
00486   tmin = -999; tmax=-999;
00487 
00488   DetectorType::Detector_t detector 
00489     = (DetectorType::Detector_t)fVldRange.GetDetectorMask();
00490   
00491   switch (detector) {
00492   case DetectorType::kNear:
00493     switch (view ) {
00494     case PlaneView::kU:
00495       tmin = -2.10 * fScale;
00496       tmax = +2.75 * fScale;
00497     case PlaneView::kV:
00498       tmin = -2.75 * fScale;
00499       tmax = +2.10 * fScale;
00500     default:
00501       MSG("Geo",Msg::kError)
00502         << "GeoGeometry::GetTransverseExtent undefined for "
00503         << DetectorType::AsString(detector) << " view "
00504         << PlaneView::AsString(view) << endl;
00505       break;
00506     }
00507   case DetectorType::kFar:
00508     tmin = -4.0 * fScale;
00509     tmax = +4.0 * fScale;
00510     break;
00511   case DetectorType::kCalib:
00512     tmin = -0.5 * fScale;
00513     tmax = +0.5 * fScale;
00514     break;
00515   default:
00516     MSG("Geo",Msg::kError) 
00517       << "GeoGeometry::GetTransverseExtent undefined for "
00518       << DetectorType::AsString(detector) << endl;
00519     break;
00520   }
00521 
00522   Float_t fuzz = 0.5*Geo::kStripWidth*fScale;
00523   tmin = tmin - fuzz;
00524   tmax = tmax + fuzz;
00525   
00526   return;
00527     
00528 }
00529 
00530 //_____________________________________________________________________________
00531 void GeoGeometry::GetTransverseExtent(PlaneView::PlaneView_t view,
00532                                       Float_t& tmin, Float_t& tmax) const {
00533   // Public. Purpose: Retrieve transverse extent of detector in global (MARS)
00534   // coordinates.
00535 
00536   UpdateGlobalManager();
00537   
00538   Double_t tmind,tmaxd;
00539   GetTransverseExtent(view,tmind,tmaxd);
00540   tmin = (Float_t)tmind;
00541   tmax = (Float_t)tmaxd;
00542 
00543   return;
00544     
00545 }
00546 
00547 //_____________________________________________________________________________
00548 void GeoGeometry::GetZExtent(Double_t& zmin, Double_t& zmax, Int_t isup) const{
00549   // Public. Purpose: Retrieve zextent of specified isup supermodule in MARS
00550   // coordinates. If isup = -1 (default), returns zextent of entire detector.
00551  
00552   UpdateGlobalManager();
00553  
00554   // The boundaries are calculated during geometry build 
00555   zmax =-999999;
00556   zmin =+999999; 
00557   if ( isup < 0 ) {
00558     zmin = fSMZMin[0];
00559     if ( fSMZMax[1] > 0 ) zmax = fSMZMax[1];
00560     else zmax = fSMZMax[0];
00561   }
00562   else if ( isup < 2 ) {
00563     zmin = fSMZMin[isup];
00564     zmax = fSMZMax[isup];
00565   }
00566   else {
00567     MSG("Geo",Msg::kWarning) << "GetZExtent failed. SuperModule "
00568                              << isup << " undefined." << endl;
00569   }
00570 
00571   return;
00572   
00573    
00574 }
00575 
00576 //_____________________________________________________________________________
00577 void GeoGeometry::GetZExtent(Float_t& zmin, Float_t& zmax, Int_t isup) const {
00578   // Public. Purpose:: Retrieve zextent of specified isup supermodule. If 
00579   // isup = -1 (default), returns zextent of entire detector.
00580 
00581   UpdateGlobalManager();
00582   
00583   Double_t zmind,zmaxd;
00584   GetZExtent(zmind,zmaxd,isup);
00585   zmin = (Float_t)zmind;
00586   zmax = (Float_t)zmaxd;
00587 
00588   return;
00589 }
00590 
00591 //_____________________________________________________________________________
00592 bool GeoGeometry::IsCompatible(const VldContext& vldc, Geo::EAppType apptype) 
00593                                                                     const {
00594   // Public. Test if vldc and apptype are in range of this geometry
00595 
00596   UpdateGlobalManager();
00597 
00598   bool iscompatible = false;
00599   if ( fVldRange.IsCompatible(vldc) && fAppType == apptype ) 
00600                                              iscompatible = true;
00601   return iscompatible; 
00602 }
00603 
00604 //_____________________________________________________________________________
00605 void GeoGeometry::ls(Option_t *option) const {
00606    // Public. list components of this geometry
00607 
00608   UpdateGlobalManager();
00609 
00610   fGeoManager->ls(option);
00611 
00612 }
00613 
00614 //_____________________________________________________________________________
00615 void GeoGeometry::Print(Option_t* option) const {
00616    // Public. Print something about this geometry (name + vldrange)
00617 
00618   UpdateGlobalManager();
00619 
00620   std::string stoption(option);
00621   DumpVolume(stoption);
00622   
00623   cout << "GeoGeometry::Print\n" 
00624        << fVldRange.AsString() << endl;
00625   if ( fGeoManager ) 
00626     cout << "GeoManager " << fGeoManager->GetName() 
00627          << "," << fGeoManager->GetTitle() << endl;
00628   else 
00629     cout << "GeoManager not initialized." << endl;
00630 
00631 }
00632 
00633 
00634 //_____________________________________________________________________________
00635 void GeoGeometry::BuildAll(const VldContext &vldc) {
00636   // Private.  Build materials & geometry
00637 
00638   UpdateGlobalManager();
00639 
00640   MSG("Geo",Msg::kVerbose) << "GeoGeometry BuildAll " << endl;
00641   assert(fGeoManager);
00642 
00643   // Get the VldRange that fits this context
00644   BuildVldRange(vldc);
00645 
00646   if (vldc.GetDetector() == DetectorType::kUnknown) {
00647     MSG("Geo",Msg::kWarning)
00648       << "no possibility of building a geometry for " << endl
00649       << "   VldContext: " << vldc << endl;
00650     return;
00651   }
00652 
00653   // Build Detector Materials
00654   BuildMaterials(vldc);
00655 
00656   // Build Detector Geometry
00657   BuildGeometry(vldc);
00658 
00659 }
00660 
00661 //_____________________________________________________________________________
00662 void GeoGeometry::BuildVldRange(const VldContext &vldc) {
00663   // Private. Build VldRange from VldContext
00664 
00665   UpdateGlobalManager();
00666 
00667   MSG("Geo",Msg::kDebug) << "GeoGeometry BuildVldRange " << endl;
00668   
00669   // Start the VldRange covering all of time and then trim it down
00670   VldTimeStamp starttime = VldTimeStamp((time_t)0,0);
00671   VldTimeStamp endtime = VldTimeStamp(2038,1,18,0,0,0);
00672   fVldRange = VldRange(vldc.GetDetector(),vldc.GetSimFlag(),
00673                        starttime,endtime,"DBI");
00674 
00675   DbiResultPtr<UgliDbiSteelPln> steelTbl(vldc);
00676   TrimVldRange("UgliDbiSteelPln",steelTbl.GetValidityRec());
00677 
00678   DbiResultPtr<UgliDbiScintPlnStruct> scintStructTbl(vldc);
00679   TrimVldRange("UgliDbiScintPlnStruct",scintStructTbl.GetValidityRec());
00680 
00681   DbiResultPtr<UgliDbiScintPln> scintTbl(vldc);
00682   TrimVldRange("UgliDbiScintPln",scintTbl.GetValidityRec());
00683 
00684   DbiResultPtr<UgliDbiScintMdlStruct> mdlStructTbl(vldc);
00685   TrimVldRange("UgliDbiScintMdlStruct",mdlStructTbl.GetValidityRec());
00686 
00687   DbiResultPtr<UgliDbiScintMdl> mdlTbl(vldc);
00688   TrimVldRange("UgliDbiScintMdl",mdlTbl.GetValidityRec());
00689 
00690   DbiResultPtr<UgliDbiStripStruct> stripStructTbl(vldc);
00691   TrimVldRange("UgliDbiStripStruct",stripStructTbl.GetValidityRec());
00692 
00693   DbiResultPtr<UgliDbiStrip> stripTbl(vldc);
00694   TrimVldRange("UgliDbiStrip",stripTbl.GetValidityRec());
00695   
00696 }
00697 
00698 //_____________________________________________________________________________
00699 void GeoGeometry::TrimVldRange(const char* tblName,
00700                                const DbiValidityRec* dbivrec) {
00701   // Private. Trim VldRange based on DbiValidityRec range info
00702 
00703   UpdateGlobalManager();
00704 
00705   if ( dbivrec ) {
00706     fVldRange.TrimTo(dbivrec->GetVldRange());
00707   }
00708   else {
00709     MSG("Geo",Msg::kWarning) << "No DbiValidityRec for table " << tblName 
00710                              << endl;
00711   }
00712   
00713 }
00714    
00715 //_____________________________________________________________________________
00716 void GeoGeometry::BuildMaterials(const VldContext& /* vldc */) {
00717    // Private. build this geometry's materials
00718 
00719    UpdateGlobalManager();
00720 
00721    MSG("Geo",Msg::kVerbose) << "GeoGeometry BuildMaterials " << endl;
00722    assert(fGeoManager);
00723 
00724 //-----------List of Materials, Mixtures and Tracking Media--------------
00725    // Arguments: medName,medId,matId,
00726    //            isVol  (Sensitive volume flag),
00727    //            iField (User defined magnetic field, set = 2),
00728    //            fieldM (Max field value (in kGauss)),
00729    //            tMaxFd (Max angle due to field deflection(deg/step)),
00730    //            steMax (Max step allowed),
00731    //            deeMax (Max fractional energy loss in a step),
00732    //            epsil  (Tracking precision (cm)),
00733    //            stMin  (Minimum step sude to continuous processes (cm))
00734 
00735    TGeoMaterial *mat1 = new TGeoMaterial("ALUMINIUM",26.98,13,2.7);
00736    mat1->SetUniqueID(   1);
00737    new TGeoMedium("ALUMINIUM",1,1,0,0,0,20,0.1000000E+11,0.1829598,
00738                                        0.1000000E-03,0.2236820E-01);
00739 
00740    TGeoMaterial *mat2 = new TGeoMaterial("IRON",55.85,26,7.87);
00741    mat2->SetUniqueID(  2);
00742    new TGeoMedium("IRON",2,2,0,1,20,20,0.1000000E+11,0.25,
00743                                        0.1000000E-02,0.1952315E-01);
00744    new TGeoMedium("STEEL",3,2,0,0,20,20,0.1000000E+11,0.25,
00745                                        0.1000000E-02,0.1952315E-01);
00746 
00747    TGeoMixture *mat3 = new TGeoMixture("AIR",2,0.1205000E-02);
00748    mat3->SetUniqueID(  3);
00749    mat3->DefineElement(0,14.01,7,0.7);
00750    mat3->DefineElement(1,16.00,8,0.3);
00751    new TGeoMedium("AIR",4,3,0,0,0,20,0.1000000E+11,0.2488534,
00752                                           0.1000000E-03,0.7712014);
00753 
00754    TGeoMixture *mat4 = new TGeoMixture("CONCRETE",6,   2.50000    );
00755    mat4->SetUniqueID(  4);
00756    mat4->DefineElement(0,16,8,0.53);
00757    mat4->DefineElement(1,28.09,14,0.33);
00758    mat4->DefineElement(2,40.078,20,0.6300000E-01);
00759    mat4->DefineElement(3,22.99,11,0.1500000E-01);
00760    mat4->DefineElement(4,55.85,26,0.2000000E-01);
00761    mat4->DefineElement(5,26.98,13,0.4200000E-01);
00762    new TGeoMedium("CONCRETE",5,4,0,0,0,20,0.1000000E+11,0.1880915,
00763                                        0.1000000E-03,0.2108371E-01);
00764 
00765    TGeoMixture *mat5 = new TGeoMixture("ROCK",6,   2.50000    );
00766    mat5->SetUniqueID(  5);
00767    mat5->DefineElement(0,16,8,0.53);
00768    mat5->DefineElement(1,28.09,14,0.33);
00769    mat5->DefineElement(2,40.078,20,0.6300000E-01);
00770    mat5->DefineElement(3,22.99,11,0.1500000E-01);
00771    mat5->DefineElement(4,55.85,26,0.2000000E-01);
00772    mat5->DefineElement(5,26.98,13,0.4200000E-01);
00773    new TGeoMedium("ROCK",6,5,0,0,0,20,0.1000000E+11,0.1880915,
00774                                       0.1000000E-03,0.2108371E-01);
00775 
00776    TGeoMixture *mat6 = new TGeoMixture("PSTYRENE SCINT",2,   1.03200    );
00777    mat6->SetUniqueID(  6);
00778    mat6->DefineElement(0,1.00794,1,0.7742105E-01);
00779    mat6->DefineElement(1,12.011,6,0.9225789);
00780    new TGeoMedium("PSTYRENE SCINT",7,6,2,0,0,20,0.1000000E+11,0.3084481E-01,
00781                                                  0.1000000E-03,0.8242410E-02);
00782 
00783    TGeoMixture *mat7 = new TGeoMixture("COEX TIO2 PSTYRENE",4,   1.03200    );
00784    mat7->SetUniqueID( 7);
00785    mat7->DefineElement(0,1.00794,1,0.6967895E-01);
00786    mat7->DefineElement(1,12.011,6,0.8303211);
00787    mat7->DefineElement(2,44.88,22,0.5837760E-01);
00788    mat7->DefineElement(3,15.9994,8,0.4162240E-01);
00789    new TGeoMedium("COEX TIO2 PSTYRENE",8,7,0,0,0,20,0.1000000E+11,0.217354,
00790                                                0.1000000E-03,0.2307702E-01);
00791 
00792    TGeoMixture *mat8 = new TGeoMixture("FARCOIL",5,   2.34881    );
00793    mat8->SetUniqueID( 8);
00794    mat8->DefineElement(0,1.00794,1,0.1281415E-01);
00795    mat8->DefineElement(1,12.0107,6,0.6021570E-01);
00796    mat8->DefineElement(2,14.00674,7,0.1974151E-03);
00797    mat8->DefineElement(3,15.9994,8,0.2134690E-01);
00798    mat8->DefineElement(4,63.546,29,0.9054258);
00799    new TGeoMedium("FARCOIL",9,8,0,0,0,20,0.1000000E+11,0.1673649,
00800                                                0.1000000E-03,0.3520523E-01);
00801 
00802 
00803    return;
00804 
00805 }
00806 
00807 //_____________________________________________________________________________
00808 void GeoGeometry::BuildGeometry(const VldContext& vldc) {
00809   // Private. Build this geometry's hierarchy of nodes
00810 
00811   UpdateGlobalManager();
00812   
00813   MSG("Geo",Msg::kDebug) << "GeoGeometry::BuildGeometry" << endl;
00814   assert(fGeoManager);
00815 
00816   const UgliDbiTables& ugliDbiTables = UgliDbiTables(vldc);
00817   const UgliDbiGeometry* ugliDbiGeo = ugliDbiTables.GetDbiGeometry();
00818   if (!ugliDbiGeo) {
00819     MSG("Geo",Msg::kFatal) 
00820        << "No UgliDbiGeometry for " << vldc << endl;
00821     abort();
00822   }
00823 
00824   // Start with the hall, this is the widest view stored in db 
00825   const Float_t* hmin = ugliDbiGeo->GetHallXYZMin();
00826   const Float_t* hmax = ugliDbiGeo->GetHallXYZMax();
00827 
00828   // Pad x&y-dimensions because otherwise shield is cut-off 
00829   const Double_t xypad = 0.*fScale; // 0.2 meters
00830   Double_t hminsc[3] = {hmin[0]*fScale,hmin[1]*fScale,hmin[2]*fScale};
00831   Double_t hmaxsc[3] = {hmax[0]*fScale,hmax[1]*fScale,hmax[2]*fScale};
00832 
00833   // x/y/zhsiz is half-width in each dimension of hall
00834   Double_t xhsiz = 0.5*(hmaxsc[0] - hminsc[0]) + xypad;
00835   Double_t yhsiz = 0.5*(hmaxsc[1] - hminsc[1]) + xypad;
00836   Double_t zhsiz = 0.5*(hmaxsc[2] - hminsc[2]);
00837 
00838   // x/y/z0hall is center of hall
00839   Double_t x0hall = 0.5*(hmaxsc[0] + hminsc[0]);
00840   Double_t y0hall = 0.5*(hmaxsc[1] + hminsc[1]);
00841   Double_t z0hall = 0.5*(hmaxsc[2] + hminsc[2]);
00842 
00843   MSG("Geo",Msg::kDebug) << "Hall halfwidths " << xhsiz << ","
00844                          << yhsiz << "," << zhsiz << " placed at "
00845                          << x0hall << "," << y0hall << "," << z0hall << endl;
00846   
00847 
00848   // Hall
00849   TGeoMedium* medAIR    = fGeoManager->GetMedium("AIR");
00850   TGeoVolume* volHALL   = fGeoManager->MakeBox("HALL",medAIR,
00851                                                 xhsiz,yhsiz,zhsiz);
00852   volHALL-> SetVisibility(kTRUE);
00853   volHALL-> SetLineColor(kGreen);
00854 
00855   // Concrete liner pad is box with halfwidth dimensions equal
00856   // to the hall halfwidths + the liner thickness (1 m)
00857   const Double_t linerpad = 1.0*fScale; // thickness concrete liner (1 m)
00858   TGeoMedium* medCONCRETE = fGeoManager->GetMedium("CONCRETE");
00859   TGeoVolume* volLINR     = fGeoManager->MakeBox("LINR",medCONCRETE,
00860                                          xhsiz+linerpad,yhsiz+linerpad,
00861                                          zhsiz+linerpad);
00862   volLINR-> SetVisibility(kTRUE);
00863   volLINR-> SetLineColor(kYellow);
00864 
00865   // Rock shell
00866   // rock padding is 5 m thick onto half hall dimensions
00867   const Double_t rockpad = 5.0*fScale; // thickness of considered rock (5 m)
00868   Double_t absxmax = TMath::Max(TMath::Abs(hminsc[0]-xypad),
00869                                 TMath::Abs(hmaxsc[0]+xypad));
00870   Double_t absymax = TMath::Max(TMath::Abs(hminsc[1]-xypad),
00871                                 TMath::Abs(hmaxsc[1]+xypad));
00872   Double_t abszmax = TMath::Max(TMath::Abs(hminsc[2]),
00873                                 TMath::Abs(hmaxsc[2]));
00874   TGeoMedium* medROCK = fGeoManager->GetMedium("ROCK");
00875   TGeoVolume* volMARS = fGeoManager->MakeBox("MARS",medROCK,
00876                                               absxmax+rockpad,absymax+rockpad,
00877                                               abszmax+rockpad);
00878   volMARS -> SetVisibility(kTRUE);
00879   volMARS -> SetLineColor(kBlack); 
00880 
00881   // The top level volume MARS will be assigned node path "/MARS_1"
00882   // by root
00883   fGeoManager -> SetTopVolume(volMARS);
00884   // GeoNodes are owned by the TGeoManager
00885   std::string nodename = "LINR_1";
00886   std::string globalpath = "/MARS_1/" + nodename;
00887   new GeoNode(this,volLINR,new TGeoTranslation("LINR",x0hall,y0hall,z0hall),
00888               volMARS,globalpath,nodename);
00889   
00890   nodename = "HALL_1";
00891   globalpath += "/" + nodename;
00892   GeoNode* hallNode = new GeoNode(this,volHALL,gGeoIdentity,
00893                                   volLINR,globalpath,nodename);
00894 
00895   BuildDetector(vldc,hallNode);
00896   
00897 }
00898 
00899 //_____________________________________________________________________________
00900 void GeoGeometry::BuildDetector(const VldContext& vldc,
00901                                 const GeoNode* hallNode) {
00902    // Private. Build this geometry's steel+scint planes + coil
00903 
00904   UpdateGlobalManager();
00905 
00906   MSG("Geo",Msg::kDebug) << "GeoGeometry::BuildPlanes " << endl;
00907   assert(fGeoManager);
00908 
00909   DbiResultPtr<UgliDbiSteelPln> steelTbl(vldc);
00910   const UgliDbiTables& ugliDbiTables = UgliDbiTables(vldc);
00911 
00912   TGeoVolume* hallVol  = hallNode -> GetVolume();
00913   std::string hallPath = hallNode -> GetGlobalPath();
00914   
00915   // Plane db positions are stored relative to mars so need
00916   // hall global position to recalculate
00917   // Translation taken from liner, since hall placed with identity
00918   // matrix relative to liner
00919   TGeoNode* linrNode = fGeoManager->GetVolume("MARS")->GetNode(0);
00920   const Double_t* h0 = linrNode -> GetMatrix() -> GetTranslation();
00921   
00922   TGeoMedium* steelMed = fGeoManager -> GetMedium("IRON"); // has b-field
00923   TGeoMedium* airMed   = fGeoManager -> GetMedium("AIR");
00924 
00925   // Pre-build strip volumes
00926   BuildStripVolumes(vldc);
00927 
00928   Int_t plnMin[2] = {-1};
00929   Int_t plnMax[2] = {-1};
00930   Int_t nSM = GetSMPlaneLimits(vldc,plnMin,plnMax);
00931 
00932   
00933   // detx0, dety0 are used to position the coil
00934   Float_t detx0 = 0;
00935   Float_t dety0 = 0;
00936 
00937   for (unsigned int irow=0; irow < steelTbl.GetNumRows(); ++irow) {
00938 
00939     // Build steel and scint plane volumes first, then position so
00940     // that we know pair volume size.
00941 
00942     // Steel plane
00943     GeoSteelPlnVolume* stplnVolume = 0;
00944     const UgliDbiSteelPln* stRow = steelTbl.GetRow(irow);
00945     PlexPlaneId steelId = stRow -> GetPlaneId();
00946     std::string stName = GetGeoCompatibleName(steelId.AsString());
00947      
00948     if ( steelId.IsVetoShield() ) steelId =
00949       PlexVetoShieldHack::RenumberMuxToMdl(vldc,steelId);  // don't know why 
00950     else if ( steelId.GetPlane() > 485 ) continue; // because db has 0-497
00951     // Skip planes that have intentionally been placed at unphysical
00952     // locations
00953     if ( TMath::Abs(stRow->GetX0() ) > 50. ) continue;
00954     
00955     if ( irow % 20 == 0 ) {
00956       MSG("Geo",Msg::kInfo) << "Building steel row "<< stName.c_str()<< endl;
00957     } 
00958            
00959     Float_t pairhalfx = 0;
00960     Float_t pairhalfy = 0;
00961     Float_t pairhalfz = 0.5*(stRow->GetTotalZ())*fScale;
00962 
00963     if ( !steelId.IsVetoShield() ) {
00964       stplnVolume = new GeoSteelPlnVolume(this,steelId,
00965                                         stRow->GetThickness()*fScale,steelMed);
00966       stplnVolume -> SetLineColor(kRed);
00967       stplnVolume -> SetVisibility(kTRUE);
00968 
00969       pairhalfx = dynamic_cast<TGeoBBox*>(stplnVolume->GetShape())->GetDX();
00970       // This fudge is because bbox of neardetector planes only includes
00971       // plane width and not near detector offset which seems worrisome
00972       // given that this offset (asymmetry about x) is included in the
00973       // shape definition.
00974       if ( vldc.GetDetector() == Detector::kNear ) pairhalfx += 
00975                                         fScale*TMath::Abs(Geo::kNearXOffset);
00976       pairhalfy = dynamic_cast<TGeoBBox*>(stplnVolume->GetShape())->GetDY();
00977     }
00978     
00979     // Scint plane
00980     GeoScintPlnVolume* scplnVolume = 0;
00981     const UgliDbiScintPln* scRow = 0;
00982     PlexPlaneId scintId = steelId;
00983     scintId.SetIsSteel(false);
00984     std::string scName = GetGeoCompatibleName(scintId.AsString());
00985     if ( PlaneCoverage::kNoActive != steelId.GetPlaneCoverage() && 
00986          PlaneCoverage::kUnknown  != steelId.GetPlaneCoverage() ) {
00987       MSG("Geo",Msg::kVerbose) << "scint pln name " << scName.c_str() 
00988                                << endl;
00989       scRow = ugliDbiTables.GetDbiScintPlnByIndex(scintId.GetPlane());
00990     
00991       scplnVolume = new GeoScintPlnVolume(this,scintId,
00992                                           scRow->GetThickness()*fScale,
00993                                           airMed);
00994       scplnVolume -> SetVisibility(kFALSE); // deactivate when not debugging
00995       scplnVolume -> SetLineColor(kBlue);
00996 
00997       // This only works because scint planes are rotated in a way such that
00998       // width and height of bounding box don't change.
00999       pairhalfx = TMath::Max(pairhalfx,(Float_t)dynamic_cast<TGeoBBox*>
01000                              (scplnVolume->GetShape())->GetDX());
01001       pairhalfy = TMath::Max(pairhalfy,(Float_t)dynamic_cast<TGeoBBox*>
01002                              (scplnVolume->GetShape())->GetDY());
01003     }
01004 
01005     // Build pair bounding box and position according to steel plane coords
01006     std::string pairName = GetGeoCompatibleName(steelId.AsString("b"));
01007     TGeoVolume* pairVol = fGeoManager->MakeBox(pairName.c_str(),airMed,
01008                                                pairhalfx,pairhalfy,pairhalfz);
01009     pairVol -> SetVisibility(kFALSE);
01010     pairVol -> VisibleDaughters(kTRUE);
01011 
01012     TGeoRotation* stRotMatrix = new TGeoRotation(pairName.c_str(),
01013                                 stRow->GetThetaDeg(0),stRow->GetPhiDeg(0),
01014                                 stRow->GetThetaDeg(1),stRow->GetPhiDeg(1),
01015                                 stRow->GetThetaDeg(2),stRow->GetPhiDeg(2));
01016     stRotMatrix -> RegisterYourself();
01017 
01018     // Plane DB translation is relative to MARS and not hall, move to hall 
01019     // local
01020     Float_t x0pair = (stRow->GetX0())*fScale - h0[0];
01021     Float_t y0pair = (stRow->GetY0())*fScale - h0[1];
01022     Float_t z0pair = (stRow->GetZBack()-0.5*(stRow->GetTotalZ()))*fScale-h0[2];
01023     TGeoCombiTrans* pairMatrix = new TGeoCombiTrans(pairName.c_str(),
01024                                              x0pair,y0pair,z0pair,stRotMatrix);
01025     MSG("Geo",Msg::kDebug) << "Placing plane pair at " << x0pair << ","
01026                              << y0pair << "," << z0pair << endl;
01027 
01028     std::string pairPath = hallPath + "/" + pairName+"_1";
01029     new GeoNode(this,pairVol,pairMatrix,hallVol,pairPath,pairName+"_1");
01030 
01031     if ( stplnVolume ) {
01032       // Place the steel plane within the pairVol
01033       std::string stplnNodeName = stName + "_1";
01034       std::string steelPlnPath = pairPath + "/" + stplnNodeName;
01035       new GeoSteelPlnNode(this,stplnVolume,
01036                           new TGeoTranslation(stName.c_str(),0.,0.,
01037           0.5*(stRow->GetTotalZ()-stRow->GetThickness())*fScale),pairVol,
01038                           steelPlnPath,stplnNodeName,steelId);
01039       int iSM = 0;
01040       if ( nSM > 1 && steelId.GetPlane() > plnMax[0] ) iSM = 1;
01041       detx0 = x0pair; // hall coordinates
01042       dety0 = y0pair; // hall coordinates
01043       // fSMZMin/Max in MARS coordinates
01044       fSMZMin[iSM] = TMath::Min(fSMZMin[iSM],(stRow->GetZBack()
01045                               -stRow->GetTotalZ())*fScale);  
01046       fSMZMax[iSM] = TMath::Max(fSMZMax[iSM],(stRow->GetZBack())*fScale);
01047       
01048     }
01049     
01050     if ( scplnVolume ) {
01051       // Place the scint plane within the pairVol
01052       Float_t x0pln = (scRow->GetX0RelSteel())*fScale;
01053       Float_t y0pln = (scRow->GetY0RelSteel())*fScale;
01054       Float_t z0pln = 0.5*(-stRow->GetTotalZ()+scRow->GetThickness())*fScale;
01055       
01056       MSG("Geo",Msg::kVerbose) << "Placing scint pln at " << x0pln << ", "
01057                                << y0pln << "," << z0pln << endl;
01058         
01059       // Rotation matrix relative to steel
01060       // (thetax,phix) = (90, 0+zrotrelsteel)
01061       // (thetay,phiy) = (90,90+zrotrelsteel)
01062       // (thetaz,phiz) = ( 0, 0)
01063       Double_t zrotrelsteel = scRow->GetZRotRelSteelDeg();
01064       TGeoRotation* scRotMatrix = new TGeoRotation(scName.c_str(),90.,
01065                                   zrotrelsteel,90.,90.+zrotrelsteel,0.,0.);
01066       scRotMatrix -> RegisterYourself();
01067       TGeoCombiTrans* combiMatrix 
01068          = new TGeoCombiTrans(scName.c_str(),x0pln,y0pln,z0pln,scRotMatrix);
01069 
01070       std::string scplnNodeName = scName + "_1";
01071       std::string scintPlnPath = pairPath + "/" + scplnNodeName;
01072       GeoScintPlnNode* scplnNode 
01073           = new GeoScintPlnNode(this,scplnVolume,combiMatrix,pairVol,
01074                                 scintPlnPath,scplnNodeName,scintId);
01075     
01076       this -> BuildModules(ugliDbiTables, scplnNode);
01077     } 
01078   } // end of loop over all plane db rows
01079 
01080   // Build coil after all planes are positioned so that detector
01081   // limits are known
01082   DetectorType::Detector_t dettype = (DetectorType::Detector_t)
01083                                       vldc.GetDetector();
01084   switch ( dettype ) {
01085   case DetectorType::kFar:
01086     BuildFarCoil(hallNode,detx0,dety0);
01087     break;
01088   case DetectorType::kNear:
01089     BuildNearCoil(hallNode,detx0,dety0);
01090     break;
01091   default:
01092     break;
01093   }
01094 
01095   return;
01096   
01097 }
01098   
01099 //_____________________________________________________________________________
01100 Int_t GeoGeometry::GetSMPlaneLimits(const VldContext& vldc,
01101                                     Int_t* plnMin, Int_t* plnMax) {
01102   // Private, but could be public?
01103   //  Determine Super Module plane limits for specified vldc.  
01104   // Returns number of super modules.  plnMin/Max[0] is filled for
01105   // supermodule 0 and plnMin/Max[1] for supermodule 1 if applicable.
01106 
01107   DetectorType::Detector_t dettype = vldc.GetDetector();
01108   Int_t nSM = 0;
01109   switch (dettype) {
01110   case Detector::kFar: 
01111     nSM = 2;
01112     plnMin[0] = 0;
01113     plnMax[0] = 248;
01114     plnMin[1] = 249;
01115     plnMax[1] = 485;
01116     break;
01117   case Detector::kNear:
01118     nSM = 1;
01119     plnMin[0] = 0;
01120     plnMax[0] = 281;
01121     break;
01122   case Detector::kCalDet:
01123     nSM = 1;
01124     plnMin[0] = 0;
01125     plnMax[0] = 60; // main detector block, 61-64 on floor
01126     break;
01127   default:
01128     MSG("Geo",Msg::kError) 
01129     << "GetSMPlaneLimits failed for unknown detector type\n"
01130     << DetectorType::AsString(dettype) << "." << endl;
01131   } // end of switch
01132 
01133   return nSM;
01134   
01135 }
01136 
01137 //_____________________________________________________________________________
01138 void GeoGeometry::BuildNearCoil(const TGeoNode* hallNode,
01139                                 Float_t x0, Float_t y0) {
01140   // Private. Build the near detector coil. Fix me.  
01141   // x0,y0 is coil hole center in hall coordinates (assumed constant
01142   // over all planes).
01143 
01144   UpdateGlobalManager();
01145  
01146   MSG("Geo",Msg::kDebug) << "GeoGeometry::BuildNearCoil " << endl;
01147   assert(fGeoManager);
01148 
01149   TGeoMedium* medSTEEL    = fGeoManager->GetMedium("STEEL");
01150   TGeoMedium* medAIR      = fGeoManager->GetMedium("AIR");
01151   TGeoMedium* medAL       = fGeoManager->GetMedium("ALUMINIUM");
01152 
01153   TGeoVolume* hallVol = hallNode -> GetVolume();
01154 
01155   // The dimensions of the coil should be extracted from the db
01156   Float_t shalfx  = Geo::kNearSteelHoleHalfWidth*fScale; // steel, 0.18 m 
01157   Float_t shalfy  = shalfx; // steel
01158   Float_t ahalfx  = 0.13*fScale; // air, halfwidth 0.13 m
01159   Float_t ahalfy  = ahalfx; // air
01160   Float_t alhalfx = 0.1118*fScale; // aluminum
01161   Float_t alhalfy = 0.1143*fScale; // aluminum
01162  
01163   // Build coil along z-direction, extends to ends of super module
01164   Float_t zmin,zmax;
01165   GetZExtent(zmin,zmax,-1); // returned in MARS coordinates
01166   // Convert to HALL coordinates
01167   TGeoNode* linrNode = fGeoManager->GetVolume("MARS")->GetNode(0);
01168   const Double_t* h0 = linrNode -> GetMatrix() -> GetTranslation();
01169   zmin -= h0[2];
01170   zmax -= h0[2];
01171   
01172   Float_t zcoillen = zmax - zmin;
01173   TGeoVolume* BUS0 = fGeoManager->MakeBox("BUS0",medSTEEL,
01174                                            shalfx,shalfy,0.5*zcoillen);
01175   BUS0 -> SetLineColor(14);  // gray  
01176   BUS0 -> SetVisibility(kTRUE);
01177 
01178   TGeoVolume* BUA0 = fGeoManager->MakeBox("BUA0",medAIR,
01179                                            ahalfx,ahalfy,0.5*zcoillen);
01180   BUA0 -> SetLineColor(14);  
01181   BUA0 -> SetVisibility(kTRUE);
01182   BUS0 -> AddNode(BUA0,1,gGeoIdentity);
01183 
01184   TGeoVolume* BUC0 = fGeoManager->MakeBox("BUC0",medAL,
01185                                            alhalfx,alhalfy,0.5*zcoillen);
01186   BUC0 -> SetLineColor(14);  
01187   BUC0 -> SetVisibility(kTRUE);
01188   BUA0 -> AddNode(BUC0,1,gGeoIdentity);
01189 
01190   // Place inner coil in hall
01191   // Rotate first, then translate
01192   TGeoRotation *rot45 = new TGeoRotation("BUS0",90,45,90,135,0,0);
01193   rot45 -> RegisterYourself();
01194   Float_t xcoil = x0;
01195   Float_t ycoil = y0;
01196   Float_t zcoil = (zmin+zmax)/2.;
01197   hallVol -> AddNode(BUS0,1,new TGeoCombiTrans(xcoil,ycoil,zcoil,rot45));
01198 
01199   // Place return coil in hall
01200   Float_t steelhalfy = 1.9*fScale; // 1.9 m halfwidth in y direction
01201   xcoil = x0 - steelhalfy;
01202   ycoil = y0 - steelhalfy;
01203   hallVol -> AddNode(BUS0,2,new TGeoCombiTrans(xcoil,ycoil,zcoil,rot45)); 
01204 
01205   // Along xy face
01206   Float_t cos45 = 0.707107;
01207   Float_t coillenxy = steelhalfy/cos45 + 2.*shalfx;
01208   TGeoVolume* BUSXY = fGeoManager->MakeBox("BUSXY",medSTEEL,
01209                                             shalfx,0.5*coillenxy,shalfy);
01210   BUSXY -> SetLineColor(14);  // gray  
01211   BUSXY -> SetVisibility(kTRUE);
01212   TGeoVolume* BUAXY = fGeoManager->MakeBox("BUAXY",medAIR,
01213                                             ahalfx,0.5*coillenxy,ahalfy);
01214   BUAXY -> SetLineColor(14);  
01215   BUAXY -> SetVisibility(kTRUE);
01216   BUSXY -> AddNode(BUAXY,1,gGeoIdentity);
01217 
01218   TGeoVolume* BUCXY = fGeoManager->MakeBox("BUCXY",medAL,
01219                                             alhalfx,0.5*coillenxy,alhalfy);
01220   BUCXY -> SetLineColor(14);  
01221   BUCXY -> SetVisibility(kTRUE);
01222   BUAXY -> AddNode(BUCXY,1,gGeoIdentity);
01223 
01224   // Will be rotated and then translated
01225   TGeoRotation *rotneg45 = new TGeoRotation("BUSXY",90,315,90,45,0,0);
01226   rotneg45 -> RegisterYourself();
01227   xcoil = x0 - (0.5*coillenxy - shalfx)*cos45;
01228   ycoil = y0 - (0.5*coillenxy - shalfy)*cos45;
01229   zcoil = zmin - shalfy;
01230   hallVol -> AddNode(BUSXY,1,new TGeoCombiTrans(xcoil,ycoil,zcoil,rotneg45));  
01231 
01232   zcoil = zmax + shalfy;
01233   hallVol -> AddNode(BUSXY,2,new TGeoCombiTrans(xcoil,ycoil,zcoil,rotneg45));  
01234 
01235   return;
01236 
01237 }
01238 
01239 //_____________________________________________________________________________
01240 void GeoGeometry::BuildFarCoil(const TGeoNode* hallNode, 
01241                                Float_t x0, Float_t y0) {
01242   // Private. Build the far detector coil. Fix me.  
01243   // x0,y0 is coil hole center in HALL coordinates (assumed constant
01244   // over all planes).
01245 
01246   UpdateGlobalManager();
01247  
01248   MSG("Geo",Msg::kDebug) << "GeoGeometry::BuildFarCoil " << endl;
01249   assert(fGeoManager);
01250 
01251   // Guess vertical drop of coil along end planes - from y-center of coil hole
01252   // to y-center of return coil on floor.
01253   Float_t deltay = 5.*fScale; // 5 m drop, guess
01254 
01255   // These dimensions/etc. of the coil should be in the db, but for now
01256   // use hardwired values
01257   TGeoMedium* medFARCOIL = fGeoManager->GetMedium("FARCOIL");
01258   TGeoMedium* medSTEEL   = fGeoManager->GetMedium("STEEL");
01259 
01260   TGeoVolume* hallVol = hallNode -> GetVolume();
01261 
01262   // Steel shell surrounding copper coil 
01263   Float_t sRad = Geo::kFarSteelHoleRad*fScale;  // 15 cm
01264   Float_t cRad = 0.125*fScale; // copper coil radius, 12.5 cm, tdr
01265 
01266   // SM0 coil along z-direction of detector, ends at supermodule ends
01267   Float_t zmin0,zmax0;
01268   GetZExtent(zmin0,zmax0,0);
01269   // Convert to HALL coordinates
01270   TGeoNode* linrNode = fGeoManager->GetVolume("MARS")->GetNode(0);
01271   const Double_t* h0 = linrNode -> GetMatrix() -> GetTranslation();
01272   zmin0 -= h0[2];
01273   zmax0 -= h0[2];
01274 
01275   Float_t zcoillen0 = zmax0-zmin0;
01276   TGeoVolume* BUS0=fGeoManager->MakeTube("BUS0",medSTEEL,0,sRad,0.5*zcoillen0);
01277   BUS0 -> SetLineColor(14);  // gray  
01278   BUS0 -> SetVisibility(kTRUE);
01279   TGeoVolume* BUC0=fGeoManager->MakeTube("BUC0",medFARCOIL,0,cRad,
01280                                          0.5*zcoillen0);
01281   BUC0 -> SetLineColor(14);  
01282   BUC0 -> SetVisibility(kTRUE);
01283   BUS0 -> AddNode(BUC0,1,gGeoIdentity);
01284 
01285   // Place SM0 inner coil in hall
01286   Float_t z0 = 0.5*(zmin0 + zmax0);
01287   hallVol -> AddNode(BUS0,1,new TGeoTranslation("BUS0",x0,y0,z0));
01288   // Place SM0 return coil in hall
01289   hallVol -> AddNode(BUC0,1,new TGeoTranslation("BUC0",x0,y0-deltay,z0));
01290   
01291   // SM1 coil along z-direction of detector, ends at supermodule ends
01292   Float_t zmin1,zmax1;
01293   GetZExtent(zmin1,zmax1,1);
01294   // Convert to HALL coordinates
01295   zmin1 -= h0[2];
01296   zmax1 -= h0[2];
01297 
01298   Float_t zcoillen1 = zmax1-zmin1;
01299   TGeoVolume* BUS1=fGeoManager->MakeTube("BUS1",medSTEEL,0,sRad,0.5*zcoillen1);
01300   BUS1 -> SetLineColor(14);  // gray
01301   BUS1 -> SetVisibility(kTRUE);
01302   TGeoVolume* BUC1=fGeoManager->MakeTube("BUC1",medFARCOIL,
01303                                           0,cRad,0.5*zcoillen1);
01304   BUC1 -> SetLineColor(14);
01305   BUC1 -> SetVisibility(kTRUE);
01306   BUS1 -> AddNode(BUC1,1,gGeoIdentity);
01307 
01308   // Place SM1 inner coil in hall
01309   Float_t z1 = 0.5*(zmin1 + zmax1);
01310   hallVol -> AddNode(BUS1,1,new TGeoTranslation("BUS1",x0,y0,z1));
01311   // Place SM1 return coil in hall
01312   hallVol -> AddNode(BUC1,1,new TGeoTranslation("BUC1",x0,y0-deltay,z1));
01313 
01314   // Build coil volume on xy faces
01315   Float_t ycoillen = deltay + 2.*cRad;
01316   TGeoVolume* BUXY=fGeoManager->MakeTube("BUXY",medFARCOIL,
01317                                           0,cRad,0.5*ycoillen);
01318   BUXY -> SetLineColor(14); // gray  
01319   BUXY -> SetVisibility(kTRUE);
01320 
01321   // Will be rotated and then translated
01322   TGeoRotation *rot90 = new TGeoRotation("BUXY",90,0,180,0,90,90);
01323   rot90 -> RegisterYourself();
01324 
01325   Float_t xcoil = x0;
01326   Float_t ycoil = (y0 + cRad) - ycoillen/2.;
01327   hallVol -> AddNode(BUXY,1,
01328                   new TGeoCombiTrans("BUXY_1",xcoil,ycoil,zmin0-cRad,rot90));
01329   hallVol -> AddNode(BUXY,2,
01330                   new TGeoCombiTrans("BUXY_2",xcoil,ycoil,zmax0+cRad,rot90));
01331   hallVol -> AddNode(BUXY,3,
01332                   new TGeoCombiTrans("BUXY_3",xcoil,ycoil,zmin1-cRad,rot90));
01333   hallVol -> AddNode(BUXY,4,
01334                   new TGeoCombiTrans("BUXY_4",xcoil,ycoil,zmax1+cRad,rot90));
01335 
01336   return;
01337 
01338 }
01339 
01340 //_____________________________________________________________________________
01341 void GeoGeometry::BuildModules(const UgliDbiTables& ugliDbiTables,
01342                                GeoScintPlnNode* plnNode) {
01343   // Private. Purpose: Build the modules as part of the scintillator plane
01344   
01345   UpdateGlobalManager();
01346   
01347   assert(fGeoManager);
01348   
01349   TGeoMedium* medAL  = fGeoManager -> GetMedium("ALUMINIUM");
01350   TGeoMedium* medAIR = fGeoManager -> GetMedium("AIR");
01351 
01352   const PlexPlaneId& plexPlaneId = plnNode -> GetPlexPlaneId();
01353   MSG("Geo",Msg::kDebug) <<"GeoGeometry::BuildModules for scint pln  " 
01354                          << plnNode->GetName() << endl;
01355 
01356   // Global path to plane node. Used to build module global path.
01357   std::string plnPath = plnNode->GetGlobalPath();
01358 
01359   // ScintPlnStruct used to retrieve number of modules in plane  
01360   UgliDbiStructHash planestructhash(plexPlaneId);
01361   const UgliDbiScintPlnStruct* plnStruct = ugliDbiTables.fScintPlnStructTbl
01362         .GetRowByIndex(planestructhash.HashAsPlane());
01363   Int_t nmodules = plnStruct -> GetNModules();
01364   
01365   // Loop over all modules in plane
01366   for ( int imod = 0; imod < nmodules; imod++ ) {
01367     // For each module
01368     PlexScintMdlId plexModuleId(plexPlaneId,imod);
01369 
01370     std::string mdlName = GetGeoCompatibleName(plexModuleId.AsString());
01371     
01372     // Build the module volume
01373     // Ideally could just build one module of each type but alignment varies
01374     // tpos and this may cause slight size variations
01375     // So for now generate one mdl volume per module
01376     GeoScintMdlVolume* mdlVol = new GeoScintMdlVolume(this,plexModuleId,
01377                                                       ugliDbiTables,medAL,
01378                                                       medAIR);
01379  
01380     // Build the node and place it in the plane
01381     // Establish the rotational & translational matrix for the module
01382     const UgliDbiScintMdl* scModule 
01383       = ugliDbiTables.GetDbiScintMdlById(plexModuleId);
01384     Float_t tposMod = (scModule -> GetTPosRelPln())*fScale;
01385     Float_t lposMod = (scModule -> GetLPosRelPln())*fScale;
01386     Float_t zrotMod = scModule -> GetZRotRelPlnDeg(); 
01387  
01388     TGeoRotation* modRotMatrix = new TGeoRotation(mdlName.c_str(), 90.,zrotMod,
01389                                                   90.,90.+zrotMod,0.,0.);
01390     modRotMatrix -> RegisterYourself();
01391 
01392     TGeoCombiTrans* combiMatrix = new TGeoCombiTrans(mdlName.c_str(),
01393                                      lposMod,tposMod,0.,modRotMatrix);
01394     std::string mdlNodeName = mdlName + "_1";
01395 
01396     MSG("Geo",Msg::kVerbose) << "Mdl node " << mdlNodeName.c_str() 
01397                              << "tpos, lpos, zrot(deg) rel pln " 
01398                              << tposMod << "," << lposMod << "," << zrotMod 
01399                              << endl;
01400     
01401     GeoScintMdlNode* mdlNode = new GeoScintMdlNode(this,mdlVol,combiMatrix,
01402                                                    plnNode,mdlNodeName,
01403                                                    plexModuleId,
01404                                           scModule->GetClearLenEast()*fScale,
01405                                           scModule->GetClearLenWest()*fScale,
01406                                           scModule->GetWlsLenEast()*fScale,
01407                                           scModule->GetWlsLenWest()*fScale);
01408 
01409     // Add strips to module node
01410     BuildStrips(ugliDbiTables,mdlNode);
01411 
01412   }
01413   
01414 }
01415   
01416 //_____________________________________________________________________________
01417 void GeoGeometry::BuildStrips(const UgliDbiTables& ugliDbiTables,
01418                               GeoScintMdlNode* mdlNode) {
01419   // Purpose:: Build this planes's scint strips and add them as nodes to the
01420   // det plane volume
01421   // This method should be moved to GeoScintPlnVolume
01422 
01423   UpdateGlobalManager();
01424   assert(fGeoManager);
01425  
01426   PlexScintMdlId plexModuleId = mdlNode->GetPlexScintMdlId();
01427   MSG("Geo",Msg::kDebug) << "GeoGeometry::BuildStrips for module " 
01428                          << mdlNode->GetName() << endl;
01429   
01430   // Determine lo,hi strip in plane
01431   UgliDbiStructHash modulestructhash(plexModuleId);
01432   const UgliDbiScintMdlStruct* scModuleStruct 
01433        = ugliDbiTables.fScintMdlStructTbl
01434         .GetRowByIndex(modulestructhash.HashAsScintMdl());
01435   Int_t lostrip = scModuleStruct -> GetFirstStrip();
01436   Int_t histrip = scModuleStruct -> GetLastStrip();
01437 
01438   for ( int istp = lostrip; istp <= histrip; istp++ ) {
01439     // For each strip in module
01440     PlexStripEndId seid(plexModuleId,istp);
01441     std::string stpName = GetGeoCompatibleName(seid.AsString());
01442 
01443     MSG("Geo",Msg::kVerbose)  << "Strip " << istp << " name " 
01444                               << stpName.c_str() << endl;
01445     const UgliDbiStrip* scStrip = ugliDbiTables.GetDbiStripById(seid);
01446 
01447     // The strip volumes have been pre-built
01448     std::string stpVolName = GetGeoCompatibleName(seid.AsString("s"));
01449     TGeoVolume* stpVol = fGeoManager -> GetVolume(stpVolName.c_str());
01450     if ( !stpVol ) {
01451       MSG("Geo",Msg::kFatal) 
01452          << "Unable to find pre-built stripvol for volume "
01453          << stpName.c_str() << " shape name " 
01454          << stpVolName.c_str() << endl;
01455       abort();
01456     } 
01457 
01458     // Build the node and place it in the plane
01459     Float_t tposStp = (scStrip -> GetTPosRelMdl())*fScale;
01460     Float_t lposStp = (scStrip -> GetLPosRelMdl())*fScale;
01461     Float_t zrotStp = scStrip -> GetZRotRelMdlDeg();
01462     MSG("Geo",Msg::kVerbose) << "tpos, lpos, zrot(deg) rel to module " 
01463                              << tposStp << ", " << lposStp << ", " 
01464                              << zrotStp << endl;
01465 
01466     std::string stpNodeName = stpName+"_1";
01467 
01468     TGeoRotation* stpRotMatrix = new TGeoRotation(stpNodeName.c_str(), 90.,
01469                                        zrotStp,90.,90.+zrotStp,0.,0.);
01470     stpRotMatrix -> RegisterYourself();
01471     TGeoCombiTrans* combiMatrix 
01472      = new TGeoCombiTrans(stpNodeName.c_str(),lposStp,tposStp,0.,stpRotMatrix);
01473 
01474     new GeoStripNode(this,stpVol,combiMatrix,mdlNode,stpNodeName,seid);
01475 
01476   }
01477 
01478   return;
01479   
01480 }
01481 
01482 //__________________________________________________________________________ 
01483 void GeoGeometry::BuildStripVolumes(const VldContext& vldc) {
01484   // pre-build set of strip volumes for this vldc.  strip volumes will be 
01485   // placed appropriately in module volumes as nodes when planes are 
01486   // constructed.
01487 
01488   UpdateGlobalManager();
01489 
01490   MSG("Geo",Msg::kDebug) << "GeoGeometry::BuildStripVolumes " << endl;
01491   assert(fGeoManager);
01492 
01493   TGeoMedium* scintMed = fGeoManager -> GetMedium("PSTYRENE SCINT");
01494   TGeoMedium* coexMed  = fGeoManager -> GetMedium("COEX TIO2 PSTYRENE");
01495 
01496   DbiResultPtr<UgliDbiStripStruct> stripTbl(vldc);
01497   
01498   for ( unsigned int irow = 0; irow < stripTbl.GetNumRows(); irow++ ) {
01499     const UgliDbiStripStruct* sRow = stripTbl.GetRow(irow);
01500     string stpName = GetGeoCompatibleName(sRow -> GetShapeName());
01501 
01502     // Volumes will self-register with fGeoManager
01503     Float_t totallen = (sRow->GetTotalLen())*fScale;
01504     Float_t leneastpart = (sRow->GetLenEastPart())*fScale;
01505     Float_t lenwestpart = (sRow->GetLenWestPart())*fScale;
01506     // Clean up some caldet database crud
01507     if ( totallen < 1.E-4*fScale ) continue;
01508     if ( leneastpart < 1.E-4*fScale ) leneastpart = totallen;
01509     if ( lenwestpart < 1.E-4*fScale ) lenwestpart = totallen;
01510     
01511     new GeoStripVolume(this,stpName.c_str(),totallen,leneastpart,lenwestpart,
01512                                        (sRow->GetWlsLenEast())*fScale, 
01513                                        (sRow->GetWlsLenWest())*fScale, 
01514                                        (sRow->GetWlsLenBypass())*fScale,
01515                                         scintMed,coexMed);
01516   } 
01517 
01518 }
01519 
01520 //_____________________________________________________________________________
01521 void GeoGeometry::UpdateNodeMatrices(TGeoVolume* volume) {
01522   // Private method. Loop through all GeoNodes in geometry starting at volume 
01523   // and construct global matrices for use in local to global (MARS) 
01524   // coordinates
01525 
01526   UpdateGlobalManager();
01527   if (!volume) {
01528     MSG("Geo",Msg::kFatal) << "UpdateNodeMatrices called with null volume ptr "
01529                            << endl;
01530     abort();
01531   }
01532   
01533   Int_t ndaughter = volume -> GetNdaughters();
01534   for ( int id = 0; id < ndaughter; id++ ) {
01535     TGeoNode* daughternode = volume->GetNode(id);
01536     GeoNode* geonode = dynamic_cast<GeoNode*>(daughternode);
01537     if ( geonode ) geonode -> UpdateGlobalMatrix();
01538     
01539     TGeoVolume* daughtervol = daughternode->GetVolume();
01540     this -> UpdateNodeMatrices(daughtervol);
01541   }
01542 
01543 }

Generated on Thu Nov 1 15:52:36 2007 for loon by  doxygen 1.3.9.1