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

UgliGeometry.cxx

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

Generated on Sat Nov 21 22:48:01 2009 for loon by  doxygen 1.3.9.1