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

UgliGeometry.cxx

Go to the documentation of this file.
00001 
00002 // $Id: UgliGeometry.cxx,v 1.62 2005/02/17 15:27:20 rhatcher Exp $
00003 //
00004 // UgliGeometry
00005 //
00006 // UgliGeometry is single geometry
00007 //
00008 // Author:  R. Hatcher 2000.04.25
00009 //
00011 
00012 #include "UgliGeometry/UgliGeometry.h"
00013 
00014 #include "UgliGeometry/UgliLoanPool.h"  // for algorithmic stuff
00015 #include "UgliGeometry/UgliScintPlnNode.h"
00016 #include "UgliGeometry/UgliSteelPlnNode.h"
00017 
00018 #include "DatabaseInterface/DbiResultPtr.h"
00019 // for Purge
00020 #include "DatabaseInterface/DbiTableProxy.h"
00021 #include "DatabaseInterface/DbiCache.h"
00022 
00023 #include "UgliGeometry/UgliDbiTables.h"
00024 
00025 #include "UgliGeometry/UgliDbiGeometry.h"
00026 #include "UgliGeometry/UgliDbiScintPlnStruct.h"
00027 #include "UgliGeometry/UgliDbiScintMdlStruct.h"
00028 #include "UgliGeometry/UgliDbiStripStruct.h"
00029 #include "UgliGeometry/UgliDbiSteelPln.h"
00030 #include "UgliGeometry/UgliDbiScintPln.h"
00031 #include "UgliGeometry/UgliDbiScintMdl.h"
00032 #include "UgliGeometry/UgliDbiStrip.h"
00033 
00034 #include "UgliGeometry/UgliStripShape.h"
00035 #include "UgliGeometry/TNodeX.h"
00036 #include "UgliGeometry/MinosOutline.h"  // also brings in TXTRU
00037 
00038 #include "Conventions/Munits.h"
00039 #include "Plex/PlexVetoShieldHack.h"
00040 #include "Fabrication/FabPlnInstallLookup.h"
00041 
00042 #include "MessageService/MsgService.h"
00043 CVSID("$Id: UgliGeometry.cxx,v 1.62 2005/02/17 15:27:20 rhatcher Exp $");
00044 
00045 #include "TMath.h"
00046 #include "TCanvas.h"
00047 #include "TMixture.h"
00048 #include "TRotMatrix.h"
00049 #include "TBRIK.h"
00050 #include "TSPHE.h"
00051 #include "TView.h"
00052 #include "TObjArray.h"
00053 #include "TList.h"
00054 
00055 #include <cassert>
00056 #include <float.h>  // FLT_EPSILON for floating point comparison
00057 
00058 ClassImp(UgliGeometry)
00059 
00060 typedef map<PlexPlaneId,UgliPlnNode*>::const_iterator nodeItr_t;
00061 typedef map<PlexPlaneId,UgliPlnNode*>::const_reverse_iterator nodeRevItr_t;
00062 typedef pair<PlexPlaneId,UgliPlnNode*> nodePair_t;
00063 
00064 //_____________________________________________________________________________
00065 
00066 
00067 size_t BinarySearchNearestLarger(const std::vector<Double_t>& array,
00068                                    Double_t value )
00069 {
00070   // Binary search in a vector of values to locate value
00071   //
00072   // Vector is assumed to be sorted prior to this call
00073   // If match is found, function returns position of value
00074   // If no match found, function returns first element larger than value
00075   // Except if larger than last element, function returns last element + 1
00076 
00077   size_t n(array.size());
00078 
00079   // special cases
00080   if ( value > array[n-1] ) return n;  // beyond the end, nothing larger
00081   if ( value < array[0]   ) return 0;  // trivially easy
00082 
00083   size_t nabove(n+1);
00084   size_t nbelow(0);
00085   size_t middle;
00086   while ( nabove-nbelow > 1 ) {
00087     middle = (nabove+nbelow)/2;
00088     /*
00089     cout << "[" << nbelow << "," << middle << "," << nabove << "] "
00090          << " n=" << n << endl;
00091     if ( middle-1 > n-1 ) 
00092       cout << "BinarySearchNearestLarger bad middle" << endl;
00093     */
00094     Double_t vtest = array[middle-1];
00095     if ( value == vtest) return middle-1;
00096     if ( value  < vtest) nabove = middle;
00097     else                 nbelow = middle;
00098   }
00099   // fell through without a match
00100   return nabove-1;
00101          
00102 }
00103 
00104 //_____________________________________________________________________________
00105 UgliGeometry::UgliGeometry()
00106    : fFrozen(true), fAlgorithmic(false), fRootGeom(0),
00107      fCachedSteelPlnNode(0), fCachedScintPlnNode(0)
00108 {
00109    // Default constructor
00110    MSG("Ugli",Msg::kVerbose) << "UgliGeometry default ctor" << endl;
00111 }
00112 
00113 //_____________________________________________________________________________
00114 UgliGeometry::UgliGeometry(const VldContext &vldc, Bool_t frozen)
00115    : fFrozen(frozen), fAlgorithmic(false), fRootGeom(0),
00116      fCachedSteelPlnNode(0), fCachedScintPlnNode(0)
00117 {
00118    // Normal constructor
00119 
00120    fAlgorithmic = UgliDbiTables::IsAlgorithmic(vldc.GetDetector());
00121 
00122    // complete hack to keep a "global" context so that decisions about 
00123    // veto shield configuration can be made in a pseudo-vacuum.
00124    // set this *before* going to the loan pool
00125    if (vldc.GetDetector() == DetectorType::kFar) 
00126      PlexVetoShieldHack::SetDefaultContext(vldc);
00127 
00128    //MSG("Ugli",Msg::kInfo) << "UgliGeometry vldc ctor @ " << this << endl;
00129 
00130    BuildAll(vldc);
00131 }
00132 
00133 //_____________________________________________________________________________
00134 UgliGeometry::~UgliGeometry()
00135 {
00136    // delete all the owned sub-objects
00137 
00138    //MSG("Ugli",Msg::kInfo) << "UgliGeometry dtor @ " << this << endl;
00139 
00140    delete fRootGeom;    fRootGeom=0;
00141 
00142    if (CountRef()) {
00143       MSG("Ugli",Msg::kWarning)
00144          << "~UgliGeometry still had " << CountRef()
00145          << " outstanding references " << endl;
00146    }
00147 
00148 }
00149 
00150 //_____________________________________________________________________________
00151 UgliGeometry::EMINFStatus UgliGeometry::GetMINFStatus() const
00152 { return UgliGeometry::kNotNeeded; }
00153 
00154 //_____________________________________________________________________________
00155 Bool_t UgliGeometry::IsCompatible(const VldContext &vldc)
00156 {
00157    // check compatibility of this plex with a context
00158 
00159    return fVldRange.IsCompatible(vldc);
00160 
00161 }
00162 
00163 //_____________________________________________________________________________
00164 Bool_t UgliGeometry::IsCompatible(const VldContext *vldc)
00165 {
00166    // check compatibility of this plex with a context
00167 
00168    return fVldRange.IsCompatible(vldc);
00169 
00170 }
00171 
00172 //_____________________________________________________________________________
00173 UgliScintPlnNode* UgliGeometry::GetScintPlnNode(PlexPlaneId planeid) const
00174 {
00175    // get a node for a particular scint plane
00176 
00177    fRootGeom->cd();
00178    TNodeX* hallnode = dynamic_cast<TNodeX*>(fRootGeom->GetNode("hall"));
00179    if (!hallnode) {
00180       static int nmsg = 5;
00181       if (nmsg) {
00182          MSG("Ugli",Msg::kError) 
00183             << "GetScintPlnNode found no hall node" << endl;
00184          nmsg--;
00185          if (nmsg==0) MSG("Ugli",Msg::kError) 
00186             << "  ... last of these warnings" << endl;
00187       }
00188       return 0;
00189    }
00190    hallnode->cd();
00191 
00192    // ensure that plane id passed in didn't have the wrong setting for IsSteel
00193    PlexPlaneId scintplnid(planeid);
00194    if (scintplnid.IsSteel()) {
00195       static Int_t nmsg = 2;
00196       if (nmsg>0) {
00197          MSG("Ugli",Msg::kError) 
00198             << "::GetScintPlnNode passed steel plane id " 
00199             << planeid.AsString("c") << endl;
00200          nmsg--;
00201          if (nmsg==0) MSG("Ugli",Msg::kInfo) 
00202             << " ... last message " << endl;
00203       }
00204       scintplnid.SetIsSteel(kFALSE);
00205       //rwh:
00206       assert(0);
00207    }
00208 
00209    // convert veto shield id's into one-module-per-plane #'s
00210    if (scintplnid.IsVetoShield()) {
00211      VldContext vldc = 
00212        PlexVetoShieldHack::ConvertRangeToContext(GetVldRange());
00213      scintplnid = PlexVetoShieldHack::RenumberMuxToMdl(vldc,scintplnid);
00214    }
00215 
00216    if (scintplnid.GetPlaneCoverage() == PlaneCoverage::kNoActive) {
00217      static int msglimit = 20; // give up after 20 messages
00218      if (msglimit) {
00219        MSG("Ugli",Msg::kError)
00220          << "::GetScintPlnNode impossible for "
00221          << scintplnid.AsString("c")
00222          << ", THERE IS NO SCINTILLATOR!"
00223          << endl;
00224        if (--msglimit == 0)
00225          MSG("Ugli",Msg::kError)
00226            << " ... last warning of this type" << endl;
00227      }
00228      //rwh: assert(0);
00229      return 0;
00230    }
00231 
00232    // optimization under the assumption that we'll get multiple
00233    // sequential requests for same plane (on way to getting individual
00234    // strips presumably)
00235    if (fCachedScintPlnId == scintplnid) return fCachedScintPlnNode;
00236 
00237    UgliScintPlnNode* the_node =
00238 #ifdef USENODETODEPTH
00239       dynamic_cast<UgliScintPlnNode*>(hallnode->GetNodeToDepth(scintplnid.AsString("p"),1));
00240 #else
00241    //rwh:      dynamic_cast<UgliScintPlnNode*>(fPlaneTable[scintplnid]);
00242    0;
00243    // use lookup without possibility of insertion side effect
00244    typedef std::map<PlexPlaneId,UgliPlnNode*>::const_iterator planeTableItr_t;
00245    planeTableItr_t pt_itr = fPlaneTable.find(scintplnid);
00246    if (pt_itr != fPlaneTable.end()) 
00247      the_node = dynamic_cast<UgliScintPlnNode*>(pt_itr->second);
00248    if ( ! the_node ) {
00249      // perhaps the fPlaneTable needs to be refreshed
00250      RestorePlaneTable(false);
00251      pt_itr = fPlaneTable.find(scintplnid);
00252      if (pt_itr != fPlaneTable.end()) 
00253        the_node = dynamic_cast<UgliScintPlnNode*>(pt_itr->second);
00254    }
00255 #endif
00256    if ( ! the_node ) {
00257       MSG("Ugli",Msg::kError)
00258          << "GetScintPlnNode could not find pre-constructed plane " 
00259          << scintplnid.AsString("c") 
00260          << " in " << fRootGeom->GetName() << endl;
00261       the_node = 0; // new UgliScintPlnNode(this,scintplnid);
00262       // sometimes this happens when veto shield electronics were read out
00263       // before the actual scintillator was installed.
00264       //rwh: assert(0);
00265    }
00266 
00267    // update cache of this request
00268    fCachedScintPlnId   = scintplnid;
00269    fCachedScintPlnNode = the_node;
00270 
00271    return the_node;
00272 }
00273 
00274 //_____________________________________________________________________________
00275 UgliSteelPlnNode* UgliGeometry::GetSteelPlnNode(PlexPlaneId planeid) const
00276 {
00277    // get a node for a particular scint plane
00278 
00279    fRootGeom->cd();
00280    TNodeX* hallnode = dynamic_cast<TNodeX*>(fRootGeom->GetNode("hall"));
00281    if (!hallnode) {
00282       static int nmsg = 5;
00283       if (nmsg) {
00284          MSG("Ugli",Msg::kError) 
00285             << "GetSteelPlnNode found no hall node" << endl;
00286          nmsg--;
00287          if (nmsg==0) MSG("Ugli",Msg::kError) 
00288             << "  ... last of these warnings" << endl;
00289       }
00290       return 0;
00291    }
00292    hallnode->cd();
00293 
00294    // ensure that plane id passed in didn't have the wrong setting for IsSteel
00295    PlexPlaneId steelplnid(planeid);
00296    if (!steelplnid.IsSteel()) {
00297       static Int_t nmsg = 2;
00298       if (nmsg>0) {
00299          MSG("Ugli",Msg::kWarning) 
00300             << "::GetSteelPlnNode passed scint plane id " 
00301             << planeid.AsString("c") << endl;
00302          nmsg--;
00303          if (nmsg==0) MSG("Ugli",Msg::kInfo) 
00304             << " ... last message " << endl;
00305       }
00306       steelplnid.SetIsSteel(kTRUE);
00307       //rwh:
00308       assert(0);
00309    }
00310 
00311    // optimization under the assumption that we'll get multiple
00312    // sequential requests for same plane 
00313    if (fCachedSteelPlnId == steelplnid) return fCachedSteelPlnNode;
00314 
00315    UgliSteelPlnNode* the_node = 
00316 #ifdef USENODETODEPTH
00317       dynamic_cast<UgliSteelPlnNode*>(hallnode->GetNodeToDepth(steelplnid.AsString("p"),1));
00318 #else
00319    //rwh:      dynamic_cast<UgliSteelPlnNode*>(fPlaneTable[steelplnid]);
00320    0;
00321    // use lookup without possibility of insertion side effect
00322    typedef std::map<PlexPlaneId,UgliPlnNode*>::const_iterator planeTableItr_t;
00323    planeTableItr_t pt_itr = fPlaneTable.find(steelplnid);
00324    if ( pt_itr != fPlaneTable.end() )
00325      the_node = dynamic_cast<UgliSteelPlnNode*>(pt_itr->second);
00326    if ( ! the_node ) {
00327      // perhaps the fPlaneTable needs to be refreshed
00328      RestorePlaneTable(false);
00329      pt_itr = fPlaneTable.find(steelplnid);
00330      if ( pt_itr != fPlaneTable.end() )
00331        the_node = dynamic_cast<UgliSteelPlnNode*>(pt_itr->second);
00332    }
00333 #endif
00334    if ( ! the_node ) {
00335       MSG("Ugli",Msg::kError)
00336          << "GetSteelPlnNode could not find pre-constructed plane " 
00337          << steelplnid 
00338          << " in " << fRootGeom->GetName() << endl;
00339       the_node = 0; // new UgliSteelPlnNode(this,steelplnid);
00340    }
00341 
00342    // update cache of this request
00343    fCachedSteelPlnId   = steelplnid;
00344    fCachedSteelPlnNode = the_node;
00345 
00346    return the_node;
00347 }
00348 
00349 //_____________________________________________________________________________
00350 UgliStripNode* UgliGeometry::GetStripNode(PlexStripEndId seid) const
00351 {
00352    // get a node for a particular strip
00353 
00354    fRootGeom->cd();
00355    TNodeX* hallnode = dynamic_cast<TNodeX*>(fRootGeom->GetNode("hall"));
00356    if (!hallnode) {
00357       static int nmsg = 5;
00358       if (nmsg) {
00359          MSG("Ugli",Msg::kError) 
00360             << "GetStripNode found no hall node" << endl;
00361          nmsg--;
00362          if (nmsg==0) MSG("Ugli",Msg::kError) 
00363             << "  ... last of these warnings" << endl;
00364       }
00365       return 0;
00366    }
00367    hallnode->cd();
00368 
00369    PlexStripEndId geom_seid = seid;
00370    // convert veto shield id's into one-module-per-plane #'s
00371    if (geom_seid.IsVetoShield()) {
00372      VldContext vldc = 
00373        PlexVetoShieldHack::ConvertRangeToContext(GetVldRange());
00374      geom_seid = PlexVetoShieldHack::RenumberMuxToMdl(vldc,geom_seid);
00375    }
00376 
00377    UgliScintPlnNode* the_plane = GetScintPlnNode(geom_seid);
00378    if (!the_plane) return 0;
00379 
00380    return the_plane->GetStripNode(geom_seid);
00381 }
00382 
00383 //_____________________________________________________________________________
00384 const vector<UgliScintPlnNode*>& UgliGeometry::GetScintPlnNodePtrVector() const
00385 {
00386    // return collection of ptrs for all scint plane nodes in detector
00387 
00388    if (fScintPlnNodes.empty()) {
00389    
00390      nodeItr_t node_itr = fPlaneTable.begin();
00391      nodeItr_t node_end = fPlaneTable.end();
00392    
00393      while (node_itr != node_end) {
00394        nodePair_t map_pair = *node_itr;
00395        UgliScintPlnNode* scintPlnNode =
00396          dynamic_cast<UgliScintPlnNode*>(map_pair.second);
00397        if (scintPlnNode) 
00398          fScintPlnNodes.push_back(scintPlnNode);
00399        node_itr++;
00400      }
00401    }
00402 
00403    return fScintPlnNodes;
00404 }
00405 
00406 //_____________________________________________________________________________
00407 const vector<UgliSteelPlnNode*>& UgliGeometry::GetSteelPlnNodePtrVector() const
00408 {
00409    // Return collection of ptrs for all steel plane nodes in detector
00410    // Exclude FarDet Veto Shield pseudo-planes
00411 
00412    if (fNormalSteelNodes.empty()) {
00413 
00414      nodeItr_t node_itr = fPlaneTable.begin();
00415      nodeItr_t node_end = fPlaneTable.end();
00416    
00417      while (node_itr != node_end) {
00418        nodePair_t map_pair = *node_itr;
00419        UgliSteelPlnNode* steelPlnNode =
00420          dynamic_cast<UgliSteelPlnNode*>(map_pair.second);
00421        if (steelPlnNode && !steelPlnNode->GetPlexPlaneId().IsVetoShield()) 
00422          fNormalSteelNodes.push_back(steelPlnNode);
00423        node_itr++;
00424      }
00425    }
00426 
00427    return fNormalSteelNodes;
00428 }
00429 
00430 //_____________________________________________________________________________
00431 const vector<UgliPlnNode*>& UgliGeometry::GetPlnNodePtrVector() const
00432 {
00433    // return collection of ptrs for all plane nodes in detector
00434 
00435    if (fAllPlnNodes.empty()) {
00436    
00437      nodeItr_t node_itr = fPlaneTable.begin();
00438      nodeItr_t node_end = fPlaneTable.end();
00439    
00440      while (node_itr != node_end) {
00441        nodePair_t map_pair = *node_itr;
00442        UgliPlnNode* plnNode = map_pair.second;
00443        if (plnNode) fAllPlnNodes.push_back(plnNode);
00444        node_itr++;
00445      }
00446    }
00447 
00448    return fAllPlnNodes;
00449 }
00450 
00451 //_____________________________________________________________________________
00452 void UgliGeometry::Draw(Option_t * /* option */)
00453 {
00454    // draw this geometry
00455 
00456    MSG("Ugli",Msg::kInfo) << "UgliGeometry::Draw()" << endl;
00457 
00458    // placment, size (in pixels)
00459    TCanvas *uglicanvas = new TCanvas("ugli","ugli",200,10,700,700);
00460    // xymin, xymax, color, bordersize, bordermode
00461    TPad *uglipad = new TPad("ugli","ugli",0.02,0.02,0.98,0.98,0);
00462    uglipad->Draw();
00463    uglipad->cd();
00464 
00465    // create a view to assocate with the pad
00466    TView *ugliview = new TView(1);
00467    //              front   top  side  weird
00468    Float_t phi   =  90; // 90   180     60
00469    Float_t theta = 180; // 90    90    150
00470    Float_t psi   =   0; // 90    90    170
00471 
00472    ugliview->SetLongitude(phi);
00473    ugliview->SetLatitude(theta);
00474    ugliview->SetPsi(psi);
00475 
00476    Float_t zmin, zmax;
00477    Float_t t[4];
00478 
00479    GetZExtent(zmin,zmax);
00480    GetTransverseExtent(PlaneView::kU,t[0],t[1]);
00481    GetTransverseExtent(PlaneView::kV,t[2],t[3]);
00482 
00483    for (Int_t i=0; i<4; i++) t[i] = TMath::Abs(t[i]);
00484    Int_t   imax = TMath::LocMax(4,t);
00485 
00486    // sqrt(2) to account for possible UV rotation space
00487    Float_t tsize = TMath::Sqrt(2.) * t[imax];
00488 
00489    Float_t x0 = 0;
00490    Float_t y0 = 0;
00491    Float_t z0 = 0.5*(zmin+zmax);
00492 
00493    Float_t dz  = 0.5*(zmax-zmin);
00494    ugliview->SetRange(x0-tsize,y0-tsize,z0-dz,x0+tsize,y0+tsize,z0+dz);
00495 
00496    // Display UgliGeometry
00497    fRootGeom->Draw("same");
00498 
00499    uglicanvas->Update();
00500 }
00501 
00502 //_____________________________________________________________________________
00503 void UgliGeometry::Print(Option_t * /* option */) const
00504 {
00505    // print something about this geometry (name + ref counts + vldrange)
00506 
00507    MSG("Ugli",Msg::kInfo)
00508      << "  " << TObject::GetName() 
00509      << " has " << CountRef() << " references " << endl
00510      << "    " << fVldRange.AsString("a") << endl;
00511    MSG("Ugli",Msg::kInfo)
00512      << "    fRootGeom \"" << fRootGeom->GetName() << "\"" << endl;
00513 }
00514 
00515 //_____________________________________________________________________________
00516 void UgliGeometry::ls(Option_t *option) const
00517 {
00518    // list components of this geometry
00519 
00520    fRootGeom->ls(option);
00521 }
00522 
00523 //_____________________________________________________________________________
00524 void UgliGeometry::SetFrozen(Bool_t frozen) 
00525 {
00526   // setting frozen/modifiable must modify fRootGeom's name as well
00527   // to keep it unique
00528   fFrozen = frozen;
00529   if (fRootGeom) {
00530      TString name = (frozen?"Frozen":"Modifiable");
00531      name += fVldRange.AsString("s1ac-");
00532      fRootGeom->SetName(name.Data());
00533   }
00534 }
00535 
00536 //_____________________________________________________________________________
00537 void UgliGeometry::BuildAll(const VldContext &vldc)
00538 {
00539    // Build things
00540 
00541    // Get the VldRange that fits this VldContext
00542 
00543    BuildVldRange(vldc);
00544 
00545    TString name = (IsFrozen()?"Frozen":"Modifiable");
00546    name += fVldRange.AsString("s1ac-");
00547    fRootGeom = new TGeometryX(name.Data(),"a MINOS geometry");
00548    fRootGeom->cd();
00549 
00550    if (vldc.GetDetector() == DetectorType::kUnknown) {
00551       MSG("Ugli",Msg::kWarning)
00552          << "no possibility of building a geometry for " << endl
00553          << "   VldContext: " << vldc << endl;
00554       return;
00555    }
00556 
00557    // Build Materials
00558 
00559    BuildMaterials(vldc);
00560 
00561    // Build RotMatrices
00562 
00563    BuildRotMatrices(vldc);
00564 
00565    // Build Shapes
00566 
00567    BuildShapes(vldc);
00568 
00569    // Build Nodes
00570 
00571    BuildNodes(vldc);
00572 
00573    // Clear DBI cache
00574 
00575    ClearDbiCache(vldc);
00576 }
00577    
00578 //_____________________________________________________________________________
00579 void UgliGeometry::GetTransverseExtent(PlaneView::PlaneView_t view,
00580                                        Float_t& tmin, Float_t& tmax) const
00581 {
00582   // Return extent based on detector type and view
00583 
00584   Double_t tmind, tmaxd;
00585   GetTransverseExtent(view,tmind,tmaxd);
00586   tmin = (Float_t)tmind;
00587   tmax = (Float_t)tmaxd;
00588 }
00589 
00590 //_____________________________________________________________________________
00591 void UgliGeometry::GetTransverseExtent(PlaneView::PlaneView_t view,
00592                                        Double_t& tmin, Double_t& tmax) const
00593 {
00594   // Return extent based on detector type and view
00595   // *** bad form *** currently simple hard coded values!!
00596 
00597    // the VldRange describing this geometry should only have on bit set
00598    DetectorType::Detector_t detector = 
00599       (DetectorType::Detector_t) fVldRange.GetDetectorMask();
00600 
00601    switch (detector) {
00602    case DetectorType::kNear:
00603       switch (view) {
00604       case PlaneView::kU:
00605          tmin = -210. * Munits::cm;
00606          tmax = +275. * Munits::cm;      
00607          break;
00608       case PlaneView::kV:
00609          tmin = -275. * Munits::cm;
00610          tmax = +210. * Munits::cm;      
00611          break;
00612       default:
00613       MSG("Ugli",Msg::kError)
00614          << "UgliGeometry::GetTransverseExtent undefined for "
00615          << DetectorType::AsString(detector) << " view " 
00616          << PlaneView::AsString(view) << endl;
00617       break;
00618       }
00619    case DetectorType::kFar:
00620       tmin = -400. * Munits::cm;
00621       tmax = +400. * Munits::cm;
00622       break;
00623    case DetectorType::kCalib:
00624       tmin = -50. * Munits::cm;
00625       tmax = +50. * Munits::cm;
00626       break;
00627    default:
00628       MSG("Ugli",Msg::kError)
00629          << "UgliGeometry::GetTransverseExtent undefined for "
00630          << DetectorType::AsString(detector) << endl;
00631       break;
00632    }
00633 
00634 #ifdef OLDFUZZ
00635    Float_t fuzz_abs  = 10. * Munits::cm;
00636    Float_t fuzz_frac = 0.025;
00637 #else
00638    Float_t fuzz_abs  = 0.5 * 4.1 * Munits::cm;
00639    Float_t fuzz_frac = 0.0;
00640 #endif
00641    Float_t extra_per_side = 0.5*(tmax-tmin)*fuzz_frac;
00642 
00643    tmin = tmin - fuzz_abs - extra_per_side;
00644    tmax = tmax + fuzz_abs + extra_per_side;
00645 
00646 
00647 }
00648 
00649 //_____________________________________________________________________________
00650 void UgliGeometry::GetZExtent(Float_t& zmin, Float_t& zmax, Int_t isuper) const
00651 {
00652   // Return z extent
00653   // if isuper == -1 for whole detector
00654   // otherwise by supermodule (not yet supported)
00655 
00656   Double_t zmind, zmaxd;
00657   GetZExtent(zmind,zmaxd,isuper);
00658   zmin = (Float_t)zmind;
00659   zmax = (Float_t)zmaxd;
00660 }
00661 
00662 //_____________________________________________________________________________
00663 void UgliGeometry::GetZExtent(Double_t& zmin, Double_t& zmax, Int_t isuper) const
00664 {
00665   // Return z extent
00666   // if isuper == -1 for whole detector
00667   // otherwise by supermodule (not yet supported)
00668 
00669   // the VldRange describing this geometry should only have on bit set
00670   DetectorType::Detector_t det = 
00671     (DetectorType::Detector_t) fVldRange.GetDetectorMask();
00672 
00673   // protect against case where DBI built no planes
00674   RestorePlaneTable(true);
00675   if ( fPlaneTable.empty() ) {
00676     MSG("Ugli",Msg::kWarning)
00677       << "GetZExtent() No planes found." << endl
00678       << "   Perhaps this geometry was built with a bad VldContext" << endl
00679       << "   or the database lacked an appropriate table" << endl
00680       << fVldRange.AsString()
00681       << endl;
00682     
00683     Float_t spacing = 5.94*Munits::cm;
00684     
00685     switch (det) {
00686     case DetectorType::kNear:
00687       zmin =       -5.0*spacing;
00688       zmax = (float)282*spacing +  20.*Munits::cm + 5.0*spacing;
00689       break;
00690     case DetectorType::kCalDet:
00691       zmin =       -5.0*spacing;
00692       zmax =  (float)60*spacing +  20.*Munits::cm + 5.0*spacing;
00693       break;
00694     case DetectorType::kFar:
00695       zmin =       -5.0*spacing;
00696       zmax = (float)484*spacing + 125.*Munits::cm + 5.0*spacing;
00697       break;
00698     default:
00699       zmin = -5.0*spacing;
00700       zmax = 60*Munits::m;
00701       break;
00702     }
00703     // no real info ... return a guess
00704     return;
00705   }
00706 
00707   // Assumes that fPlaneTable is generally in z order
00708   // with the exception of CalDet cosmics and FarDet veto shield modules
00709   
00710   UgliPlnNode* upln_beg = fPlaneTable.begin()->second; // easy
00711 
00712   UgliPlnNode* upln_end = 0;
00713   // last "reasonable" plane needs to discount CalDet floor planes
00714   // and FarDet veto planes.  Work from the highest plane # down
00715   // until we get a reasonable view.
00716   nodeRevItr_t node_ritr = fPlaneTable.rbegin();
00717   nodeRevItr_t node_rend = fPlaneTable.rend();
00718   for ( ; node_ritr != node_rend ; ++node_ritr ) {
00719     upln_end          = node_ritr->second;
00720     PlexPlaneId plnid = upln_end->GetPlexPlaneId();
00721     PlaneView::PlaneView_t view = plnid.GetPlaneView();
00722     // continue looking if this plane has a kA or kB view (CalDet)
00723     // or stop if it finds a kU or kV view (esp. for Far w/ VetoShield)
00724     if (det == DetectorType::kCalDet){
00725       if (view != PlaneView::kA && view != PlaneView::kB) break;
00726     }
00727     else {
00728       if (view == PlaneView::kU || view == PlaneView::kV) break;
00729     }
00730   }
00731 
00732   if ( -1 != isuper ) {
00733     if ( DetectorType::kFar != det ) {
00734       MSG("Ugli",Msg::kError)
00735         << "UgliGeometry::GetZExtent does not support supermodules "
00736         << "other than -1 for " << DetectorType::AsString(det)
00737         << endl << "   return value for whole detector" << endl;
00738     }
00739     else {
00740       // look for intermediate uninstrumented plane
00741       // assumes only 2 super modules in far detector
00742 
00743       UgliPlnNode* upln_mid0 = upln_beg;  // just before uninstrumented
00744       UgliPlnNode* upln_mid1 = upln_beg;  // uninstrumented plane
00745 
00746       nodeItr_t node_itr = fPlaneTable.begin();
00747       nodeItr_t node_end = fPlaneTable.end();
00748 
00749       node_itr++; // move beyond first plane
00750       
00751       for ( ; node_itr != node_end ; node_itr++ ) {
00752         upln_mid0 = upln_mid1;
00753         upln_mid1 = node_itr->second;
00754         if (upln_mid1 == upln_end) {
00755           MSG("Ugli",Msg::kWarning)
00756             << "GetZExtent found no SM break for this geometry "
00757             << fVldRange << endl;
00758           upln_mid0 = upln_end;
00759           break; // reached the end, there isn't one
00760         }
00761         PlexPlaneId plnid = upln_mid1->GetPlexPlaneId();
00762         PlaneCoverage::PlaneCoverage_t cover = plnid.GetPlaneCoverage();
00763         if (cover == PlaneCoverage::kNoActive) break;
00764       }
00765       switch (isuper) {
00766       case 0:
00767         MSG("Ugli",Msg::kDebug)
00768           << " SM 0 upln_end set to upln_mid0" << endl;
00769         upln_end = upln_mid0;  // last before uninstrumented plane
00770         break;
00771       case 1:
00772         MSG("Ugli",Msg::kDebug)
00773           << " SM 1 upln_beg set to upln_mid1" << endl;
00774         upln_beg = upln_mid1;  // leading steel plane
00775         break;
00776       default:
00777         MSG("Ugli",Msg::kError)
00778           << "GetZExtent" << endl << " FarDet only has SM 0 and 1"
00779           << ", return value for whole detector." << endl;
00780       }
00781 
00782     } // FarDet
00783   } // specific SM
00784 
00785   zmin = upln_beg->GetZ0() - upln_beg->GetHalfThickness();
00786   MSG("Ugli",Msg::kDebug)
00787     << "GetZExtent first was " << upln_beg->GetPlexPlaneId() 
00788     << " Z0 " << upln_beg->GetZ0() << " - dz " << upln_beg->GetHalfThickness()
00789     << endl;
00790 
00791   zmax = upln_end->GetZ0() + upln_end->GetHalfThickness();
00792   MSG("Ugli",Msg::kDebug)
00793     << "GetZExtent last  was " << upln_end->GetPlexPlaneId() 
00794     << " Z0 " << upln_end->GetZ0() << " + dz " << upln_end->GetHalfThickness()
00795     << endl;
00796 
00797 #ifdef OLDFUZZ
00798    Float_t fuzz_abs  = 10. * Munits::cm;
00799    Float_t fuzz_frac = 0.025;
00800    Float_t extra_per_side = 0.5*(zmax-zmin)*fuzz_frac;
00801 
00802    zmin = zmin - fuzz_abs - extra_per_side;
00803    zmax = zmax + fuzz_abs + extra_per_side;
00804 #endif
00805 
00806 }
00807 
00808 //_____________________________________________________________________________
00809 TVector3 UgliGeometry::GetHallExtentMin() const
00810 {
00811   // return the min {x,y,z} of the detector hall
00812 
00813   TNodeX* hallnode  = dynamic_cast<TNodeX*>(fRootGeom->GetNode("hall"));
00814   TShape* hallshape = hallnode->GetShape();
00815   TBRIK*  hallbrik  = dynamic_cast<TBRIK*>(hallshape);
00816   if (!hallbrik) {
00817     MSG("Ugli",Msg::kInfo)
00818       << "UgliGeometry::GetHallExtentMin() hall is not a BRIK " << endl;
00819     return TVector3(-9999.,-9999.,-9999.);
00820   }
00821   TVector3 xyz0(hallnode->GetX(), hallnode->GetY(), hallnode->GetZ());
00822   TVector3 dxyz(hallbrik->GetDx(),hallbrik->GetDy(),hallbrik->GetDz());
00823   TVector3 result = xyz0 - dxyz;
00824   return result;
00825 
00826 }
00827 
00828 //_____________________________________________________________________________
00829 TVector3 UgliGeometry::GetHallExtentMax() const
00830 {
00831   // return the min {x,y,z} of the detector hall
00832 
00833   TNodeX* hallnode  = dynamic_cast<TNodeX*>(fRootGeom->GetNode("hall"));
00834   TShape* hallshape = hallnode->GetShape();
00835   TBRIK*  hallbrik  = dynamic_cast<TBRIK*>(hallshape);
00836   if (!hallbrik) {
00837     MSG("Ugli",Msg::kInfo)
00838       << "UgliGeometry::GetHallExtentMax() hall is not a BRIK " << endl;
00839     return TVector3(+9999.,+9999.,+9999.);
00840   }
00841   TVector3 xyz0(hallnode->GetX(), hallnode->GetY(), hallnode->GetZ());
00842   TVector3 dxyz(hallbrik->GetDx(),hallbrik->GetDy(),hallbrik->GetDz());
00843   TVector3 result = xyz0 + dxyz;
00844   return result;
00845 }
00846 
00847 //_____________________________________________________________________________
00848 void UgliGeometry::BuildVldRange(const VldContext &vldc)
00849 {
00850    // Build VldRange from VldContext
00851 
00852    MSG("Ugli",Msg::kDebug) << "UgliGeometry::BuildVldRange " << endl;
00853 
00854    DetectorType::Detector_t det = vldc.GetDetector();
00855    bool isunknown = (DetectorType::kUnknown == det);
00856    const char* src = "DBI";
00857    if (isunknown) src = "Fake (unknown detector)";
00858 
00859    // start the VldRange of covering all of time and then trim it down
00860    // each time we use a DBI table to compose some part
00861    VldTimeStamp starttime = VldTimeStamp((time_t)0,0);
00862    VldTimeStamp endtime   = VldTimeStamp(2038,1,18,0,0,0);
00863    fVldRange = VldRange(vldc.GetDetector(),vldc.GetSimFlag(),
00864                         starttime,endtime,src);
00865 
00866    // special return for unknown detector
00867    if (isunknown) return;
00868 
00869    if (fAlgorithmic) {
00870      MSG("Ugli",Msg::kInfo) 
00871        << "UgliGeometry::VldRange: Algorithmic! valid until "
00872        << endtime
00873        << endl;
00874      return;
00875    }
00876 
00877    // trim based on all the tables we'll use
00878    // this also primes the cache for all of them
00879 
00880 
00881    MSG("Ugli",Msg::kInfo) << "UgliGeometry::VldRange: UgliDbiSteelPln" 
00882                           << "                 \r" << flush;
00883    DbiResultPtr<UgliDbiSteelPln> steelTbl(vldc);
00884    TrimVldRange("UgliDbiSteelPln",steelTbl.GetValidityRec());
00885 
00886    MSG("Ugli",Msg::kInfo) << "UgliGeometry::VldRange: UgliDbiScintPlnStruct" 
00887                           << "                 \r" << flush;
00888    DbiResultPtr<UgliDbiScintPlnStruct> scintStructTbl(vldc);
00889    TrimVldRange("UgliDbiScintPlnStruct",scintStructTbl.GetValidityRec());
00890 
00891    MSG("Ugli",Msg::kInfo) << "UgliGeometry::VldRange: UgliDbiScintPln" 
00892                           << "                 \r" << flush;
00893    DbiResultPtr<UgliDbiScintPln> scintTbl(vldc);
00894    TrimVldRange("UgliDbiScintPln",scintTbl.GetValidityRec());
00895 
00896    MSG("Ugli",Msg::kInfo) << "UgliGeometry::VldRange: UgliDbiScintMdlStruct" 
00897                           << "                 \r" << flush;
00898    DbiResultPtr<UgliDbiScintMdlStruct> mdlStructTbl(vldc);
00899    TrimVldRange("UgliDbiScintMdlStruct",mdlStructTbl.GetValidityRec());
00900 
00901    MSG("Ugli",Msg::kInfo) << "UgliGeometry::VldRange: UgliDbiScintMdl" 
00902                           << "                 \r" << flush;
00903    DbiResultPtr<UgliDbiScintMdl> mdlTbl(vldc);
00904    TrimVldRange("UgliDbiScintMdl",mdlTbl.GetValidityRec());
00905 
00906    MSG("Ugli",Msg::kInfo) << "UgliGeometry::VldRange: UgliDbiStripStruct" 
00907                           << "                 \r" << flush;
00908    DbiResultPtr<UgliDbiStripStruct> stripStructTbl(vldc);
00909    TrimVldRange("UgliDbiStripStruct",stripStructTbl.GetValidityRec());
00910 
00911    MSG("Ugli",Msg::kInfo) << "UgliGeometry::VldRange: UgliDbiStrip" 
00912                           << "                 \r" << flush;
00913    DbiResultPtr<UgliDbiStrip> stripTbl(vldc);
00914    TrimVldRange("UgliDbiStrip",stripTbl.GetValidityRec());
00915 
00916    MSG("Ugli",Msg::kInfo) << "UgliGeometry::VldRange: done         " << endl;
00917 
00918 
00919 }
00920 
00921 //_____________________________________________________________________________
00922 void UgliGeometry::ClearDbiCache(const VldContext &vldc)
00923 {
00924    // Clear DBI cache of elements
00925 
00926    MSG("Ugli",Msg::kDebug) << "UgliGeometry::ClearDbiCache " << endl;
00927 
00928    // nothing to purge if we were algorithmic
00929    if (fAlgorithmic) return;
00930 
00931    // have we been configured not to do the purge?
00932    if ( ! UgliLoanPool::Instance()->PurgeDbiTableCache() ) return;
00933 
00934    // purge the cache on the tables we've used
00935 
00936    DbiCache* steelTblCache = 0;
00937    DbiCache* scintStructTblCache = 0;
00938    DbiCache* scintTblCache = 0;
00939    DbiCache* mdlStructTblCache = 0;
00940    DbiCache* mdlTblCache = 0;
00941    DbiCache* stripStructTblCache = 0;
00942    DbiCache* stripTblCache = 0;
00943 
00944    { 
00945       //
00946       // start of inner scope so that DbiResultPtr's will die, die, die
00947       // and thus Purge will see no remaining clients
00948       //
00949       
00950 
00951       MSG("Ugli",Msg::kDebug) << "UgliGeometry::GetCache: UgliDbiSteelPln" 
00952                               << "                 \r" << flush;
00953       DbiResultPtr<UgliDbiSteelPln> steelTbl(vldc);
00954       steelTblCache = steelTbl.TableProxy().GetCache();
00955 
00956       MSG("Ugli",Msg::kDebug) << "UgliGeometry::GetCache: UgliDbiScintPlnStruct" 
00957                               << "                 \r" << flush;
00958       DbiResultPtr<UgliDbiScintPlnStruct> scintStructTbl(vldc);
00959       scintStructTblCache = scintStructTbl.TableProxy().GetCache();
00960 
00961       MSG("Ugli",Msg::kDebug) << "UgliGeometry::GetCache: UgliDbiScintPln" 
00962                               << "                 \r" << flush;
00963       DbiResultPtr<UgliDbiScintPln> scintTbl(vldc);
00964       scintTblCache = scintTbl.TableProxy().GetCache();
00965 
00966       MSG("Ugli",Msg::kDebug) << "UgliGeometry::GetCache: UgliDbiScintMdlStruct" 
00967                               << "                 \r" << flush;
00968       DbiResultPtr<UgliDbiScintMdlStruct> mdlStructTbl(vldc);
00969       mdlStructTblCache = mdlStructTbl.TableProxy().GetCache();
00970 
00971       MSG("Ugli",Msg::kDebug) << "UgliGeometry::GetCache: UgliDbiScintMdl" 
00972                               << "                 \r" << flush;
00973       DbiResultPtr<UgliDbiScintMdl> mdlTbl(vldc);
00974       mdlTblCache = mdlTbl.TableProxy().GetCache();
00975 
00976       MSG("Ugli",Msg::kDebug) << "UgliGeometry::GetCache: UgliDbiStripStruct" 
00977                               << "                 \r" << flush;
00978       DbiResultPtr<UgliDbiStripStruct> stripStructTbl(vldc);
00979       stripStructTblCache = stripStructTbl.TableProxy().GetCache();
00980 
00981 
00982       MSG("Ugli",Msg::kDebug) << "UgliGeometry::GetCache: UgliDbiStrip" 
00983                               << "                 \r" << flush;
00984       DbiResultPtr<UgliDbiStrip> stripTbl(vldc);
00985       stripTblCache = stripTbl.TableProxy().GetCache();
00986 
00987       MSG("Ugli",Msg::kDebug) << "UgliGeometry::GetCache: done         " << endl;
00988    }
00989 
00990    // now there should be no active clients we can now purge 
00991    // to our heart's content
00992 
00993    MSG("Ugli",Msg::kDebug) << "UgliGeometry::PurgeCache: UgliDbiSteelPln" 
00994                            << "                 \r" << flush;
00995    if (steelTblCache) steelTblCache->Purge();
00996 
00997    MSG("Ugli",Msg::kDebug) << "UgliGeometry::PurgeCache: UgliDbiScintPlnStruct" 
00998                            << "                 \r" << flush;
00999    if (scintStructTblCache) scintStructTblCache->Purge();
01000 
01001    MSG("Ugli",Msg::kDebug) << "UgliGeometry::PurgeCache: UgliDbiScintPln" 
01002                            << "                 \r" << flush;
01003    if (scintTblCache) scintTblCache->Purge();
01004 
01005    MSG("Ugli",Msg::kDebug) << "UgliGeometry::PurgeCache: UgliDbiScintMdlStruct" 
01006                            << "                 \r" << flush;
01007    if (mdlStructTblCache) mdlStructTblCache->Purge();
01008 
01009    MSG("Ugli",Msg::kDebug) << "UgliGeometry::PurgeCache: UgliDbiScintMdl" 
01010                            << "                 \r" << flush;
01011    if (mdlTblCache) mdlTblCache->Purge();
01012 
01013    MSG("Ugli",Msg::kDebug) << "UgliGeometry::PurgeCache: UgliDbiStripStruct" 
01014                            << "                 \r" << flush;
01015    if (stripStructTblCache) stripStructTblCache->Purge();
01016 
01017 
01018    MSG("Ugli",Msg::kDebug) << "UgliGeometry::PurgeCache: UgliDbiStrip" 
01019                            << "                 \r" << flush;
01020    if (stripTblCache) stripTblCache->Purge();
01021 
01022    MSG("Ugli",Msg::kDebug) << "UgliGeometry::PurgeCache: done         " << endl;
01023    
01024 
01025 }
01026 
01027 //_____________________________________________________________________________
01028 void UgliGeometry::RestorePlaneTable(bool onlyIfEmpty) const
01029 {
01030   // Restore map of PlexPlaneId's to UgliPlnNode*'s
01031   // The contents of this might have been lost during persistency
01032   // (as of 2003-04-30 it couldn't correctly be written out)
01033   // If "onlyIfEmpty" do it only if the map is empty.
01034 
01035   if ( onlyIfEmpty && ! fPlaneTable.empty() ) return; // nothing to do
01036 
01037   MSG("Ugli",Msg::kDebug) << "UgliGeometry::RestorePlaneTable " << endl;
01038 
01039   fRootGeom->cd();
01040   TNodeX* hallnode = dynamic_cast<TNodeX*>(fRootGeom->GetNode("hall"));
01041 
01042   // loop over the nodes in the hall ... these should be planes
01043   TIter nodeInHallItr(hallnode->GetListOfNodes());
01044   TNode* nodeInHall = 0;
01045   while ( ( nodeInHall = dynamic_cast<TNode*>(nodeInHallItr()) ) ) {
01046     // these are markers and boxes containing scint+steel planes
01047     MSG("Ugli",Msg::kVerbose) 
01048       << " found " << nodeInHall->GetName() << " in hall " << endl;
01049     TIter nodeInBoxItr(nodeInHall->GetListOfNodes());
01050     TObject* nodeInBox = 0;
01051     while ( ( nodeInBox = nodeInBoxItr() ) ) {
01052       // these should be the actual planes
01053       MSG("Ugli",Msg::kVerbose) 
01054         << " found " << nodeInBox->GetName() 
01055         << " in " << nodeInHall->GetName()<< endl;
01056       UgliPlnNode* upn = dynamic_cast<UgliPlnNode*>(nodeInBox);
01057       if (upn) {
01058         fPlaneTable[upn->GetPlexPlaneId()] = upn;
01059         MSG("Ugli",Msg::kDebug) 
01060           << "UgliGeometry::RestorePlaneTable add " 
01061           << upn->GetPlexPlaneId() << endl;
01062       }
01063     }
01064   }
01065   
01066 
01067 }
01068 
01069 //_____________________________________________________________________________
01070 void UgliGeometry::BuildMaterials(const VldContext& /* vldc */)
01071 {
01072    // build this geometry's materialss
01073 
01074    MSG("Ugli",Msg::kVerbose) << "UgliGeometry BuildMaterials " << endl;
01075 
01076 //   TMaterial *mat;
01077    TMixture  *mix;
01078 
01079    // there doesn't seem to be any way to set the density (1.032)
01080    mix = new TMixture("scint","polystyrene C6H5CH-CH2",-2);
01081    mix->DefineElement(0,1.00794,1.,8.);
01082    mix->DefineElement(1,12.011,6.,8.);
01083 
01084    // loop over SteelPn, fill out material for different melts ??
01085    mix = new TMixture("steel","generic steel",2);
01086    mix->DefineElement(0,55.84999,26,.98);
01087    mix->DefineElement(1,12.01,6,.02);
01088 
01089 
01090 }
01091 
01092 //_____________________________________________________________________________
01093 void UgliGeometry::BuildRotMatrices(const VldContext& /* vldc */)
01094 {
01095    // build some basic rotation matrices
01096 
01097    // absolute first should be Identity
01098    new TRotMatrix("Identity","Identity matrix",90,0,90,90,0,0);
01099 
01100    new TRotMatrix("XY","WorldAsXY", 90.,  0., 90., 90.,  0.,  0.);
01101    new TRotMatrix("UV","WorldAsUV", 90.,-45., 90., 45.,  0.,  0.);
01102 
01103 }
01104 
01105 //_____________________________________________________________________________
01106 void UgliGeometry::BuildShapes(const VldContext& /* vldc */)
01107 {
01108    // build some basic shapes (not planes or strips)
01109 
01110    MSG("Ugli",Msg::kVerbose) << "UgliGeometry BuildShapes " << endl;
01111 
01112    // this shape is a placeholder used in constructing
01113    // planes or strips within a TNode derived object
01114    // without passing it a the final shape
01115    // make it really noticable in case there was a mistake
01116    // new TBRIK("noshape","noshape","void",0,0,0);
01117    Float_t nsx[] = {   3,   3, 1.5,-1.5,  -3,  -3,-1.5, -.5,   0,   0,
01118                      .49, .49,   0,   0,   1,   1, .51, .51,   1,   1,
01119                      .5,   -1,  -2,  -2,  -1,   1,   2,   2};
01120    Float_t nsy[] = {   0, 1.5,   3,   3, 1.5,-1.5,  -3,  -3,-3.5,  -5,
01121                       -5,  -6,  -6,  -7,  -7,  -6,  -6,  -5,  -5,  -3,
01122                       -2,  -2,  -1,   1,   2,   2,   1,   0};
01123    TXTRU *noshape = new TXTRU("noshape","noshape","void",28,2);
01124    Float_t dz = 5.94 * Munits::cm;
01125    noshape->DefineSection(0,-dz,1.,0.,0.);
01126    noshape->DefineSection(1,+dz,1.,0.,0.);
01127    for (unsigned int i=0; i < sizeof(nsx)/sizeof(Float_t); i++) 
01128       noshape->DefineVertex(i,nsx[i]*Munits::m,nsy[i]*Munits::m);
01129    noshape->SetLineColor(kRed); noshape->SetLineWidth(1);
01130 
01131 }
01132 
01133 //_____________________________________________________________________________
01134 void UgliGeometry::BuildNodes(const VldContext& vldc)
01135 {
01136    // build this geometry's hierarchy of nodes
01137 
01138    MSG("Ugli",Msg::kDebug) << "UgliGeometry::BuildNodes UgliDbiTables" << endl;
01139    const UgliDbiTables& ugliTables = 
01140      ((fAlgorithmic) ? UgliDbiTables(vldc,false) : UgliDbiTables(vldc));
01141 
01142    fRootGeom->cd();
01143    // Start building from the DBI info
01144 
01145    TShape *pshape = 0;
01146    TNodeX *pnode  = 0;
01147 
01148    bool        world_is_uv = true;
01149    const char* world_rotm  = "UV";
01150 
01151    bool force_xy = true;
01152 
01153    if (vldc.GetDetector() == DetectorType::kCalDet) {
01154       world_is_uv = false;
01155       world_rotm  = "XY";
01156    }
01157    else if (force_xy) {
01158       MSG("Ugli",Msg::kInfo)
01159          << vldc.AsString("c") << " should use Hall oriented in UV space"
01160          << " ... but we won't for now" << endl;
01161       world_is_uv = false;
01162       world_rotm  = "XY";
01163    }
01164 
01165    MSG("Ugli",Msg::kDebug) << "Build the hall" << endl;
01166    // First we need a hall
01167    const UgliDbiGeometry* geo = ugliTables.GetDbiGeometry();
01168    if (!geo) {
01169      MSG("Ugli",Msg::kFatal) 
01170        << "No UgliDbiGeometry for " << vldc << endl;
01171      return;
01172    }
01173 
01174    const Float_t* hmin = geo->GetHallXYZMin();
01175    const Float_t* hmax = geo->GetHallXYZMax();
01176 // just a test folks
01177 //      Float_t hmin[] = {-5,-5,0};
01178 //      Float_t hmax[] = {15,15,60};
01179 
01180    Float_t absxmax  = TMath::Max(TMath::Abs(hmax[0]),TMath::Abs(hmin[0]));
01181    Float_t absymax  = TMath::Max(TMath::Abs(hmax[1]),TMath::Abs(hmin[1]));
01182    Float_t abszmax  = TMath::Max(TMath::Abs(hmax[2]),TMath::Abs(hmin[2]));
01183    Float_t absxymax = TMath::Max(absxmax,absymax);
01184    Float_t sqrt2 = TMath::Sqrt(2.0);
01185    if (world_is_uv) absxymax *= sqrt2;
01186 
01187    // define the fixed frame of the (local) universe
01188    pshape = new TBRIK("universe","all the ever is","void",
01189                       absxymax,absxymax,abszmax);
01190    pnode  = new TNodeX("universe","fixed center of all",
01191                        "universe",0,0,0,"Identity");
01192    pnode->SetVisibility(0); // nothing to see here folks
01193    pnode->SetVisibility(1);      // okay for now peek a little
01194    pnode->SetLineColor(kYellow); // but unobtrusively
01195    pnode->cd();
01196 
01197    // the world might rotate in the universe (uv or xy)
01198    pshape = new TBRIK("world","the shape of the world","void",
01199                       absxymax,absxymax,abszmax);
01200    pnode  = new TNodeX("world","it depends how we look at it",
01201                        "world",0,0,0,world_rotm);
01202    pnode->SetVisibility(1);     // see the world
01203    pnode->SetLineColor(kBlack); // it's gone black!
01204    pnode->cd();
01205    
01206    // shapes use half-sizes 
01207    Double_t xhsiz  = 0.5 * (hmax[0] - hmin[0]);
01208    Double_t yhsiz  = 0.5 * (hmax[1] - hmin[1]);
01209    Double_t zhsiz  = 0.5 * (hmax[2] - hmin[2]);
01210    
01211    Double_t x0hall = 0.5 * (hmax[0] + hmin[0]);
01212    Double_t y0hall = 0.5 * (hmax[1] + hmin[1]);
01213    Double_t z0hall = 0.5 * (hmax[2] + hmin[2]);
01214    
01215    pshape = new TBRIK("hall","The Hall","void",
01216                       xhsiz,yhsiz,zhsiz);
01217    TNodeX *hall_node = new TNodeX("hall","The Hall","hall",
01218                                   x0hall,y0hall,z0hall);
01219    hall_node->cd();
01220    hall_node->SetVisibility(1);   // see the hall
01221    hall_node->SetLineColor(kRed); // it's red!
01222    
01223    
01224    // put some markers in the hall identifying +x, +y, +z
01225    Float_t rmkr = 20.*Munits::cm;
01226    if (vldc.GetDetector() == DetectorType::kCalDet) rmkr = 1.*Munits::cm;
01227    pshape = new TSPHE("axismkr","axismkr","void",rmkr);
01228    pnode  = new TNodeX("+x","+x","axismkr",
01229                        xhsiz-x0hall-rmkr,-y0hall,-zhsiz+rmkr);
01230    pnode->SetLineColor(kRed);
01231    pnode->SetVisibility(1);
01232    pnode  = new TNodeX("+y","+y","axismkr",
01233                        -x0hall,yhsiz-y0hall-rmkr,-zhsiz+rmkr);
01234    pnode->SetLineColor(kGreen);
01235    pnode->SetVisibility(1);
01236    pnode  = new TNodeX("+z","+z","axismkr",
01237                        -x0hall,-y0hall,+zhsiz-rmkr);
01238    pnode->SetLineColor(kBlue);
01239    pnode->SetVisibility(1);
01240    MSG("Ugli",Msg::kDebug) << "The Hall has been installed" << endl;
01241    
01242    // pre-build the palette of strip shapes
01243    BuildStripShapes(vldc);
01244 
01245    //
01246    // determine whether (and what) to cut on the basis of FabPlnInstall
01247    //
01248    Msg::LogLevel_t cutMsgLevel = Msg::kSynopsis;
01249    VldTimeStamp geomStartTime = vldc.GetTimeStamp();
01250    bool cutOnPlnInstall = UgliDbiTables::IsCutOnPlnInstall(vldc.GetDetector());
01251 
01252    VldContext vldc_install = vldc;
01253    Registry& config = UgliLoanPool::Instance()->GetConfig();
01254    int cutAppliesToVetoShield = false;
01255    if (vldc.GetDetector() == Detector::kFar)
01256      config.Get("CutAppliesToVetoShield",cutAppliesToVetoShield);
01257    if ( cutOnPlnInstall && vldc.GetSimFlag() != SimFlag::kData ) {
01258      int applyToMC = 0;
01259      config.Get("CutAppliesToMC",applyToMC);
01260      switch ( applyToMC ) {
01261      case 1:  
01262        cutOnPlnInstall = true;  // okay, use VldContext of MC
01263        break;  
01264      case 2:  
01265        cutOnPlnInstall = true;  // okay, but use Data VldContext
01266        vldc_install = 
01267          VldContext(vldc.GetDetector(),SimFlag::kData,vldc.GetTimeStamp());
01268        MSG("Ugli",Msg::kInfo) 
01269          << "UgliGeometry::BuildNodes use kData instead of k" 
01270          << SimFlag::AsString(vldc.GetSimFlag())
01271          << " for FabPlnInstall." << endl;
01272        break;
01273      default: 
01274        cutOnPlnInstall = false; // nope, don't apply cut to MC
01275        break;  
01276      }
01277    }
01278 
01279    TString fabCutAction = "not to cut on ";
01280    if (cutOnPlnInstall) {
01281      fabCutAction = "to cut on ";
01282      if (vldc.GetDetector() == Detector::kFar) {
01283        if (cutAppliesToVetoShield) fabCutAction += "all ";
01284        else                        fabCutAction += "non-VetoShield ";
01285      }
01286    }
01287    MSG("Ugli",Msg::kInfo) 
01288      << "UgliGeometry configured " << fabCutAction 
01289      << "FabPlnInstall entries." << endl;
01290 
01291    FabPlnInstallLookup installInfo(vldc_install);
01292    if ( cutOnPlnInstall ) {
01293      const char* level = "Synopsis";
01294      config.Get("CutMsgLevel",level);
01295      cutMsgLevel = Msg::GetLevelCode(level);
01296 
01297      // if planes went up after this time then we need to trim
01298      // the VldRange end time (ignore veto shield)
01299      const FabPlnInstall* fab = installInfo.NextInstall(geomStartTime,true);
01300      if (fab) {
01301        const VldTimeStamp  time_end  = fVldRange.GetTimeEnd();
01302        const VldTimeStamp& time_next = fab->GetInstallDate();
01303        MSG("Ugli",cutMsgLevel) 
01304            << "UgliGeometry VldRange was "
01305            << time_end.AsString("sql") << " PlnInstall::NextInstall gives "
01306            << time_next.AsString("sql") << "." << endl;
01307        if ( time_next < time_end ) {
01308          MSG("Ugli",cutMsgLevel) 
01309            << "UgliGeometry VldRange TimeEnd trimmed from "
01310            << time_end.AsString("sql") << " to "
01311            << time_next.AsString("sql") << "." << endl;
01312          fVldRange.SetTimeEnd(time_next);
01313        }
01314      }
01315      else {
01316        MSG("Ugli",Msg::kInfo) 
01317          << "UgliGeometry:  No VldRange trimming as no PlnInstall::NextInstall." 
01318          << endl;
01319      }
01320    }
01321 
01322    // 
01323    // process steel + scint planes
01324    // 
01325    unsigned int nsteel = ugliTables.GetNumSteelRows();
01326    for (unsigned int irow=0; irow < nsteel; ++irow) {
01327      
01328      const UgliDbiSteelPln* steelRow = ugliTables.GetDbiSteelPln(irow);
01329 
01330      PlexPlaneId steelid = steelRow->GetPlaneId();
01331 
01332      //
01333      // check if row should be supressed due to FabPlnInstall entry
01334      //
01335      bool checkit = true;
01336      if (steelid.IsVetoShield() && !cutAppliesToVetoShield) checkit = false;
01337      if (cutOnPlnInstall && checkit) {
01338        // asked to test installation of planes based on FabPlnInstall table
01339        // so test ...
01340        const FabPlnInstall* fab =
01341          installInfo.fPlnInstallTbl.GetRowByIndex(steelid.GetPlane());
01342        if ( fab ) {
01343          if ( fab->GetInstallDate() > geomStartTime ) {
01344            MSG("Ugli",cutMsgLevel)
01345              << endl
01346              << "UgliDbiTables has entry for " << steelid
01347              << " but FabPlnInstall says " 
01348              << fab->GetInstallDate().AsString("sql")
01349              << endl;
01350            continue;  // skip installation of this steel plane
01351          }
01352        }
01353        else {
01354          MSG("Ugli",cutMsgLevel)
01355            << endl
01356            << "UgliDbiTables has entry for " << steelid
01357            << " but no entry in FabPlnInstall " 
01358            << endl;
01359          continue;  // skip installation of this steel plane
01360        }
01361          
01362      }
01363      
01364      //         int pln = steelid.GetPlane();
01365      int vis = 1;
01366      //         vis = -1;         
01367      //         if (pln== 1 || pln== 6) vis = 1;
01368      //         if (pln==13 || pln==20) vis = 1;
01369      //         if (pln>59) vis = 1;
01370      
01371      MSG("Ugli",Msg::kDebug) << " build " << steelid.AsString("c") 
01372                              << "\r" << flush;
01373           
01374      hall_node->cd();
01375      UgliSteelPlnNode* steel = 
01376        new UgliSteelPlnNode(steelid,this,ugliTables);
01377      fPlaneTable[steelid] = steel;
01378      
01379      //rwh: hack
01380      //         char boxname[16];
01381      //         sprintf(boxname,"%s",steelid.AsString("b"));  // dNNNBvc
01382      //         this->GetNode(boxname)->SetVisibility(vis);
01383      //         boxname[4] = 'P';
01384      //         this->GetNode(boxname)->SetVisibility(vis);
01385      steel->SetVisibility(vis);
01386      TNode* box_from_steel = steel->GetParent();
01387      box_from_steel->SetVisibility(vis);
01388      
01389      if (PlaneCoverage::kNoActive == steelid.GetPlaneCoverage()) continue;
01390      if (PlaneCoverage::kUnknown  == steelid.GetPlaneCoverage()) continue;
01391      
01392      PlexPlaneId scintid = steelid;
01393      scintid.SetIsSteel(false);
01394      
01395      MSG("Ugli",Msg::kSynopsis) << " build " << scintid.AsString("c") 
01396                             << "\r" << flush;
01397 
01398      box_from_steel->cd();
01399      UgliScintPlnNode* scint =
01400        new UgliScintPlnNode(scintid,this,ugliTables);
01401      fPlaneTable[scintid] = scint;
01402      
01403      //rwh: hack
01404      //         boxname[4] = 'A';
01405      //         this->GetNode(boxname)->SetVisibility(vis);
01406      scint->SetVisibility(vis);
01407      
01408    }
01409    hall_node->cd();
01410    
01411    MSG("Ugli",Msg::kSynopsis) << endl << " build  done" << endl;
01412 
01413    //
01414    // summarize what we just built
01415    //  (veto shield entries may have been out-of-order above)
01416    //
01417    PlexPlaneId loNormal, hiNormal, loShield, hiShield;
01418    const PlexPlaneId unsetPlnId;
01419    unsigned int nmdlShieldSection[5] = {0,0,0,0,0};
01420 
01421    nodeItr_t node_itr = fPlaneTable.begin();
01422    nodeItr_t node_end = fPlaneTable.end();
01423    
01424    while (node_itr != node_end) {
01425      nodePair_t map_pair = *node_itr;
01426      PlexPlaneId aPlnId = node_itr->second->GetPlexPlaneId();
01427      node_itr++;
01428 
01429      if (!aPlnId.IsVetoShield()) {
01430        if ( loNormal == unsetPlnId ) loNormal = aPlnId;
01431        hiNormal = aPlnId;
01432      }
01433      else if ( ! aPlnId.IsSteel() ) {
01434        if ( loShield == unsetPlnId ) loShield = aPlnId;
01435        hiShield = aPlnId;
01436        // characterize the shield
01437        int ipln = aPlnId.GetPlane();
01438        int isection = (ipln - 512)/64 + 1;
01439        nmdlShieldSection[isection]++;
01440      }    
01441    }
01442 
01443    MSG("Ugli",Msg::kInfo)
01444      << "Built Normal planes: " << loNormal << " to " << hiNormal << "." << endl;
01445    if ( loShield != unsetPlnId) {
01446      MSG("Ugli",Msg::kInfo)
01447        << "Built VetoShield: " << loShield 
01448        << " to " << hiShield << "; Section/Mdls: ";
01449      for (unsigned int isec=1; isec <= 4; ++isec) {
01450        if ( nmdlShieldSection[isec] > 0 )
01451          MSG("Ugli",Msg::kInfo) 
01452            << " " << isec << "/" << nmdlShieldSection[isec];
01453      }
01454      MSG("Ugli",Msg::kInfo) << "." << endl;
01455    }
01456    else if ( vldc.GetDetector() == Detector::kFar )
01457      MSG("Ugli",Msg::kInfo) << "Built No VetoShield sections." << endl;
01458 }
01459 
01460 
01461 //_____________________________________________________________________________
01462 void UgliGeometry::BuildStripShapes(const VldContext& vldc)
01463 {
01464    // build this geometry's strip shapes
01465 
01466    MSG("Ugli",Msg::kDebug) << "UgliGeometry::BuildStripShapes " << endl;
01467 
01468    DbiResultPtr<UgliDbiStripStruct> stripTbl(vldc);
01469    TrimVldRange("UgliDbiStripStruct",stripTbl.GetValidityRec());
01470 
01471       for (unsigned int irow=0; irow < stripTbl.GetNumRows(); ++irow) {
01472          const UgliDbiStripStruct* sRow = stripTbl.GetRow(irow);
01473          string sname = sRow->GetShapeName();
01474 
01475          // self-registering with TGeometry ... this isn't a memory leak
01476          new UgliStripShape(sname.c_str(),sRow->GetTotalLen(),
01477                             sRow->GetWlsLenEast(),sRow->GetWlsLenWest(),
01478                             sRow->GetLenEastPart(),sRow->GetLenWestPart(),
01479                             sRow->GetWlsLenBypass());
01480       }
01481 
01482 
01483 }
01484 
01485 //_____________________________________________________________________________
01486 PlexPlaneId UgliGeometry::GetPlaneIdFromZ(Double_t z) const
01487 {
01488   // Return the PlexPlaneId for the last (normal) plane 
01489   // with a back face *downstream* of z
01490 
01491   // For now do it the dumb way with a simple loop
01492   // eventually optimization can use a binary search
01493 
01494   // make sure that the map is filled (may have been lost in persistency)
01495   RestorePlaneTable(true);
01496 
01497   nodeRevItr_t node_itr = fPlaneTable.rbegin();
01498   nodeRevItr_t node_end = fPlaneTable.rend();
01499   UgliPlnNode *uplane = 0, *prev_uplane = 0;
01500   for ( ; node_itr != node_end ; ++node_itr ) {
01501     uplane = node_itr->second;
01502     PlexPlaneId plnid  = uplane->GetPlexPlaneId();
01503     PlaneView::PlaneView_t view = plnid.GetPlaneView();
01504     // continue looking if this plane has a kA or kB view (CalDet)
01505     // or if veto shield view (FarDet)
01506     // "unknown" is okay because that means uninstrumented plane    
01507     if (view == PlaneView::kA || view == PlaneView::kB) continue;
01508     if (view > PlaneView::kUnknown ) continue;
01509     Float_t zback = uplane->GetZ0() + uplane->GetHalfThickness();
01510     if ( ! prev_uplane ) prev_uplane = uplane;
01511     if ( z > zback ) return prev_uplane->GetPlexPlaneId();
01512     prev_uplane = uplane;
01513   }
01514   return uplane->GetPlexPlaneId();
01515 
01516 }
01517 
01518 //_____________________________________________________________________________
01519 UgliSteelPlnNode* UgliGeometry::GetNearestSteelPlnNode(Double_t z) const
01520 {
01521    // Return the UgliSteelPlnNode* that is nearest to the given z position.
01522   
01523 
01524    const std::vector<UgliSteelPlnNode*>& steelNodes = 
01525      GetSteelPlnNodePtrVector();
01526    size_t nplns = steelNodes.size();
01527 
01528    // deal with some special cases
01529    if ( nplns == 0) {
01530      // no steel, no luck!
01531      MSG("Ugli",Msg::kError)
01532        << "GetNearestSteelPlnNode was passed 0 UgliSteelPlnNode's"
01533        << endl;
01534      return 0;
01535    }
01536    else if ( nplns == 1 ) return steelNodes[0];  // only one plane, that's it!
01537 
01538 
01539    if ( fZSteelPlnMidPoint.empty() ) {
01540      // we'll just assume vector of steel pln's is ordered in z
01541      // and also plane #.  Each entry is the mid-point z between
01542      // two steel planes faces (zMid is above the plane # with the same index)
01543      UgliSteelPlnNode* steelNode = steelNodes[0];
01544      Double_t dz        = steelNode->GetHalfThickness();
01545      Double_t z0        = steelNode->GetZ0();
01546      Double_t zDownSide = z0 - dz;
01547      Double_t zUpSide   = z0 + dz;
01548      for ( size_t indx = 1; indx < nplns; ++indx ) {
01549        Double_t zUpSideLast = zUpSide;
01550        UgliSteelPlnNode* steelNode = steelNodes[indx];
01551        dz        = steelNode->GetHalfThickness();
01552        z0        = steelNode->GetZ0();
01553        zDownSide = z0 - dz;
01554        zUpSide   = z0 + dz;
01555        Double_t zMid = 0.5 * ( zUpSideLast + zDownSide );
01556        fZSteelPlnMidPoint.push_back(zMid);
01557        /*
01558        cout << setprecision(18);
01559        cout << "Midpoint between " << (indx-1) << " and " << indx
01560             << " " << steelNode->GetPlexPlaneId().AsString("C") 
01561             << " z_mid = " << zMid
01562             << endl;
01563        */
01564      }
01565    }  // fZSteelPlnMidPoint is filled
01566 
01567    size_t index = BinarySearchNearestLarger(fZSteelPlnMidPoint,z);
01568    return steelNodes[index];
01569    
01570 }
01571 
01572 //_____________________________________________________________________________
01573 void UgliGeometry::TrimVldRange(const char* tblName, 
01574                                 const DbiValidityRec* dbivrec)
01575 { 
01576    // Trim VldRange based on DbiValidityRec range info
01577 
01578    if (dbivrec) {
01579       fVldRange.TrimTo(dbivrec->GetVldRange());
01580    } else {
01581       MSG("Ugli",Msg::kWarning) 
01582          << "No DbiValidityRec for table " << tblName << endl;
01583    }
01584 }
01585 
01586 //_____________________________________________________________________________

Generated on Thu Nov 1 15:54:00 2007 for loon by  doxygen 1.3.9.1