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

BfldCache.cxx

Go to the documentation of this file.
00001 
00002 // $Id: BfldCache.cxx,v 1.30 2008/03/19 04:29:31 rhatcher Exp $
00003 // 
00004 // BfldCache 
00005 // 
00006 // BfldCache caches info for the BfldHandler
00007 //
00008 // Author:  R. Hatcher 2000.06.20
00009 //
00011 
00012 #include "BField/BfldCache.h"
00013 #include "BField/BfldLoanPool.h"
00014 
00015 #include "Plex/PlexPlaneId.h"
00016 #include "Conventions/Munits.h"
00017 
00018 #include "MessageService/MsgService.h"
00019 CVSID("$Id: BfldCache.cxx,v 1.30 2008/03/19 04:29:31 rhatcher Exp $");
00020 
00021 ClassImp(BfldCache)
00022 
00023 #include <cassert>
00024 #include <float.h>  // FLT_EPSILON for floating point comparison
00025 #include <iomanip>
00026 
00027 //_____________________________________________________________________________
00028 // Utility functions
00029 
00030 bool BFieldWithinZ(Double_t z, Double_t zmin, Double_t zmax)
00031 { 
00032   return ( z >= zmin && z <= zmax ); 
00033 }
00034 bool BFieldOutsideZ(Double_t z, Double_t zmin, Double_t zmax)
00035 { 
00036   return ( z < zmin || z > zmax ); 
00037 }
00038 
00039 #if 0
00040 static std::ostream& operator<<(std::ostream& os, const TVector3& tv3)
00041 {
00042   int w=9, p=4; // 1mm precision
00043   int prec = os.precision();
00044   os << "[" << setw(w)   << setprecision(p) << tv3.x()
00045      << "," << setw(w)   << setprecision(p) << tv3.y()
00046      << "," << setw(w+1) << setprecision(p) << tv3.z()
00047      << "]";
00048   os << resetiosflags(ios::floatfield);  // reset to "%g" format
00049   os << setprecision(prec);  // restore precision
00050   return os;
00051 }
00052 #endif
00053 
00054 //_____________________________________________________________________________
00055 BfldCache::BfldCache()
00056   : fRef(0), fSteelCache(), fSteelZmin(+9999.), fSteelZmax(-9999.),
00057     fDbiMapEntries(0), fPlaneMapCache(0)
00058 {
00059    MSG("Bfld",Msg::kDebug) << "BfldCache - default ctor" << endl;
00060    InitFlags();
00061 }
00062 
00063 //_____________________________________________________________________________
00064 BfldCache::BfldCache(const VldContext& vldc)
00065   : fDetector(vldc.GetDetector()), fRef(0), fUgliGeomHandle(vldc),
00066     fSteelCache(), fSteelZmin(+9999.), fSteelZmax(-9999.), 
00067     fDoLocalTransform(0), fInZTest(0), fZTolerance(0),
00068     fPlaneMaps(vldc,0,Dbi::kDisabled),
00069     fDbiMapEntries(fPlaneMaps.GetNumRows()),
00070     fPlaneMapCache(0), 
00071     fFindWasInSteel(false), fPosInSteel(-999.,-999.,-9999.),
00072     fWasHigh(0), fWasLow(0), fSumHigh(0), fSumLow(0)
00073 {
00074    InitFlags();
00075    fVldRange = fUgliGeomHandle.GetVldRange();
00076    MSG("Bfld",Msg::kDebug) << " BfldCache vldc " << vldc 
00077                            << "  geometry " << fVldRange << endl;
00078    const DbiValidityRec* dbivrec = fPlaneMaps.GetValidityRec();
00079    if (dbivrec) {
00080      fVldRange.TrimTo(dbivrec->GetVldRange());
00081      MSG("Bfld",Msg::kDebug) << "BfldCache range trimed to " 
00082                              << fVldRange << endl;
00083    }
00084 
00085    if ( Detector::kUnknown == fDetector ) {
00086      // this happens for the case of UseEverywhere
00087      VldTimeStamp start = VldTimeStamp(1970, 1, 1, 0, 0, 0);
00088      VldTimeStamp end   = VldTimeStamp(2038, 1,18,19,14, 6);
00089      fVldRange = VldRange(fDetector,
00090                           vldc.GetSimFlag(),
00091                           start,
00092                           end,
00093                           "fake");
00094      MSG("Bfld",Msg::kDebug) << "BfldCache ctor with no detector "  << endl;
00095    }
00096    
00097    FillSMZLimits(); 
00098 }
00099 
00100 //_____________________________________________________________________________
00101 void BfldCache::InitFlags()
00102 {
00103    // Initialize configuration flags from BfldLoanPool
00104 
00105    // get access to the BfldLoanPool
00106    BfldLoanPool *loanpool = BfldLoanPool::Instance();
00107 
00108    fDoLocalTransform = loanpool->GetDefaultDoLocalTransform();
00109    fInZTest          = loanpool->GetDefaultRequireInZTest();
00110    fZTolerance       = loanpool->GetDefaultZTolerance();
00111    MSG("Bfld",Msg::kSynopsis)
00112      << "BfldCache DoLocalTransform=" << fDoLocalTransform 
00113      << " InZTest=" << fInZTest
00114      << " ZTolerance=" << (fZTolerance/Munits::mm) << "mm"
00115      << endl;
00116 
00117 }
00118 
00119 //_____________________________________________________________________________
00120 BfldCache::~BfldCache()
00121 {
00122   if (fRef) {
00123     MSG("Bfld",Msg::kInfo) << "~BfldCache with " << fRef 
00124                            << " outstanding references." << endl
00125                            << "     using geometry" 
00126                            << fUgliGeomHandle.GetVldRange() << endl;
00127 
00128   }
00129   MSG("Bfld",Msg::kDebug) << "~BfldCache geometry" 
00130                           << fUgliGeomHandle.GetVldRange() << endl;
00131 
00132   Double_t avgHigh = 0;
00133   if (fWasHigh) avgHigh = fSumHigh/fWasHigh;
00134   Double_t avgLow = 0;
00135   if (fWasLow) avgLow = fSumLow/fWasLow;
00136 
00137   MSG("Bfld",Msg::kInfo) << "~BfldCache " 
00138                          << " z outside steel " 
00139                          << fWasHigh << " high avg=" << avgHigh << ", " 
00140                          << fWasLow << " low avg=" << avgLow << endl;
00141 
00142 
00143 }
00144 
00145 //_____________________________________________________________________________
00146 const BfldDbiPlaneMap* BfldCache::FindPlaneMap(TVector3& position,
00147                                                      Bool_t isUVZ)
00148 {
00149    SetSteelAndPlaneMapCache(position,isUVZ);
00150    return fPlaneMapCache;
00151 }
00152 
00153 #ifdef OBSOLETE_METHOD
00154 //_____________________________________________________________________________
00155 const BfldDbiPlaneMap* BfldCache::FindPlaneMapFromId(PlexPlaneId plnid)
00156 {
00157    InvalidateCaches();
00158    SetPlaneMapCache(plnid);
00159    if (plnid.IsSteel() && ! plnid.IsNull() ) {
00160      fSteelCache = fUgliGeomHandle.GetSteelPlnHandle(plnid);
00161      SetSteelLimits();
00162    }
00163    return fPlaneMapCache;
00164 }
00165 #endif
00166 
00167 //_____________________________________________________________________________
00168 void BfldCache::SetSteelLimits()
00169 {
00170    // Fill fSteelZmin/fSteelZmax for given fSteelCache
00171    if (fSteelCache.IsValid()) {
00172      Double_t z0 = fSteelCache.GetZ0();
00173      Double_t dz = fSteelCache.GetHalfThickness() + FLT_EPSILON + fZTolerance;
00174      fSteelZmin = z0 - dz;
00175      fSteelZmax = z0 + dz;
00176    }
00177    else {
00178      fSteelZmin = +9999.;
00179      fSteelZmax = -9999.;
00180    }
00181 }
00182 
00183 //_____________________________________________________________________________
00184 void BfldCache::SetPlaneMapCache(PlexPlaneId steelid)
00185 {
00186    // Fill fPlaneMapCache entry for this steel
00187 
00188    // avoid DBI lookup if possible
00189    if ( fPlaneMapCache && fPlaneMapCache->GetPlaneId() == steelid) return;
00190 
00191    fPlaneMapCache = 0;
00192 
00193    if (fDbiMapEntries > 0) {
00194      const BfldDbiPlaneMap* planemap = 
00195        fPlaneMaps.GetRowByIndex(steelid.GetPlane());
00196     
00197      if (planemap) fPlaneMapCache = planemap;
00198    }
00199 }
00200 
00201 //_____________________________________________________________________________
00202 void BfldCache::InvalidateCaches()
00203 {
00204    // Invalidate fSteelCache, fSteelZmin/max, fPlaneMapCache
00205    fSteelCache    = UgliSteelPlnHandle();
00206    fSteelZmin     = +9999.;
00207    fSteelZmax     = -9999.;
00208    fPlaneMapCache = 0;
00209 
00210 }
00211 
00212 //_____________________________________________________________________________
00213 void BfldCache::SetSteelAndPlaneMapCache(TVector3& posGlobal, Bool_t isUVZ)
00214 {
00215    // Fill fSteelCache and PlaneMap entry for this position.
00216    // Assumes that B is only important within steel
00217    // Assumes that the plane is perpendicular to z direction
00218    // i.e. no rotation out of the x-y plane
00219 
00220    fFindWasInSteel = true;
00221    Double_t z = posGlobal.z();
00222 
00223    // Try the cache first
00224    if ( fSteelCache.IsValid() && BFieldWithinZ(z,fSteelZmin,fSteelZmax) ) {
00225      //MSG("Bfld",Msg::kVerbose) 
00226      //  << "SetSteelAndPlaneMapCacheFromZ hit cache!" << endl;
00227    }
00228    else {
00229      // Ask the geometry
00230      fSteelCache = fUgliGeomHandle.GetNearestSteelPlnHandle(z);
00231      SetSteelLimits();
00232      SetPlaneMapCache(fSteelCache.GetPlexPlaneId());
00233      MSG("Bfld",Msg::kDebug) << "Asked geometry for NearestSteelPln " << endl;
00234 
00235      if ( ! fSteelCache.IsValid() ) 
00236        MSG("Bfld",Msg::kError) 
00237          << "Asked geometry for NearestSteelPln for z= " << z 
00238          << ", got invalid UgliGeomSteelPln" 
00239          << endl;
00240    }
00241 
00242    //MSG("Bfld",Msg::kInfo)
00243    //    << " posGlobal " << posGlobal << " fPosInSteel " 
00244    //    << fPosInSteel << endl;
00245 
00246 
00247    // InZTest:
00248    //   0 = no test that z is within range of a plane
00249    //   1 = return (nearest) valid UgliSteelPlnHandle, but complain
00250    //  >1 = return (nearest) valid UgliSteelPlnHandle (quietly)
00251    //       in this case set fPositionInSteel = false
00252    if ( fInZTest == 0) return;
00253    // DoLocalTransform:
00254    //   0 = no Global <--> Local transform
00255    //   1 = do only for shifts (ie.  Global->Local position but not field)
00256    //   2 = do for shifts and rotations (ie. transform returned field)
00257    if ( fDoLocalTransform <= 0 ) {
00258      fPosInSteel = posGlobal;
00259      if ( ! BFieldOutsideZ(z,fSteelZmin,fSteelZmax) ) return;
00260    } else {
00261      // use the in-the-steel local coord to determine if we're in "z"
00262      // note Ugli uses globalInXYZ, while BField uses isUVZ
00263      fPosInSteel = fSteelCache.GlobalToLocal(posGlobal,!isUVZ);
00264      Double_t hdzlimit = fSteelCache.GetHalfThickness()+FLT_EPSILON+fZTolerance;
00265      if ( TMath::Abs(fPosInSteel.z()) <= hdzlimit )  return;
00266    }
00267 
00268    // currently this returns "nearest steel" when outside the steel
00269    // but for coil we should always return either upstream or downstream
00270    // steel depending on Near/Far (which is which ... think hard)
00271    // be careful of falling off the ends
00272    fFindWasInSteel = false;
00273    
00274    if ( fInZTest < 2 ) {
00275      
00276      Double_t z0 = fSteelCache.GetZ0();
00277      Double_t ht = fSteelCache.GetHalfThickness();
00278      //Double_t dz = (z>z0) ? z-(z0+ht) : (z0-ht)-z;
00279      Double_t dz = 0;
00280      const char* side;
00281      if ( z > z0 ) {
00282        side = "high";
00283        dz = z-(z0+ht);
00284        fWasHigh++;
00285        fSumHigh += dz;
00286      } else {
00287        side = "low";
00288        dz = (z0-ht)-z;
00289        fWasLow++;
00290        fSumLow += dz;
00291      }
00292      
00293      MAXMSG("Bfld",Msg::kWarning,10) 
00294        << "Geom returned plane " << fSteelCache.GetPlexPlaneId() << endl
00295        << " but z " << z << " is not within " << ht << " of " << z0
00296        << " (" << dz << " too " << side << ")" << endl;
00297      
00298    }
00299    //if (fInZTest>1) InvalidateCaches();
00300 
00301 }   
00302 
00303 //_____________________________________________________________________________
00304 void BfldCache::FillSMZLimits()
00305 {
00306    // Determine z range of SM
00307 
00308    fSMZLimits[0] = fSMZLimits[2] = -1.0e6;
00309    fSMZLimits[1] = fSMZLimits[3] = +1.0e6;
00310 
00311    int ipln[4] = { 0, 0, 0, 0};
00312 
00313    switch (fDetector) {
00314    case Detector::kFar: 
00315      {
00316        ipln[0] = 0;
00317        ipln[1] = PlexPlaneId::LastPlaneFarSM0();
00318        ipln[2] = PlexPlaneId::LastPlaneFarSM0()+1;
00319        ipln[3] = PlexPlaneId::LastPlaneFarSM1();
00320        break;
00321      }
00322    case Detector::kNear:
00323      {
00324        ipln[0] = 0;
00325        ipln[1] = PlexPlaneId::LastPlaneNearSpect();
00326        ipln[2] = PlexPlaneId::LastPlaneNearSpect();
00327        ipln[3] = PlexPlaneId::LastPlaneNearSpect();
00328        break;
00329      }
00330    default:
00331      {
00332        return; // ! no SM at all, use defaults
00333      }
00334    }
00335 
00336    for (int indx = 0; indx < 4; ++indx) {
00337      PlexPlaneId steelid(fDetector,ipln[indx],true);
00338      UgliSteelPlnHandle uph = fUgliGeomHandle.GetSteelPlnHandle(steelid);
00339      if ( ! uph.IsValid() ) continue; // in case of no geometry
00340      Double_t dz = uph.GetHalfThickness();
00341      if ( 0 == indx || 2 == indx ) dz = -dz;
00342      fSMZLimits[indx] = uph.GetZ0() + dz;
00343    }
00344 
00345 }
00346 
00347 //_____________________________________________________________________________
00348 Ugli::SMRegion_t BfldCache::InSMRegion(const TVector3& pos, Bool_t isUVZ )
00349 {
00350    // Determine if the this position is within the SuperModules
00351    // If in XY region of "flange" then consider it part of SM if
00352    // within dz of SM.
00353    // Return:
00354    //      -1 = upstream
00355    //       1 = in SM1
00356    //       0 = in gap
00357    //       2 = in SM2
00358    //      -2 = downstream
00359 
00360    Double_t dz = 3.4 * Munits::cm;  // extra z in the area of the collar
00361 
00362    Double_t z = pos.Z();
00363 
00364    // definitely in a SM
00365    if ( z >= fSMZLimits[0] && z <= fSMZLimits[1] ) return Ugli::kInSM1; // 1
00366    if ( z >= fSMZLimits[2] && z <= fSMZLimits[3] ) return Ugli::kInSM2; // 2
00367 
00368    // definitely not in a SM
00369    if ( z < fSMZLimits[0]-dz ) return Ugli::kUpstream;   // -1
00370    if ( z > fSMZLimits[1]+dz && z < fSMZLimits[2]-dz ) return Ugli::kSMGap; // 0
00371    if ( z > fSMZLimits[3]+dz ) return Ugli::kDownstream; // -2
00372 
00373    // in region where flange might be part of SM
00374    bool inFlange = ( InXYRegion(pos,isUVZ) <= Ugli::kFlange );
00375    if ( z < fSMZLimits[0] ) {
00376      if ( inFlange ) return Ugli::kInSM1;      //  1
00377      else            return Ugli::kUpstream  ; // -1;
00378    }
00379    if ( Detector::kNear == fDetector ) {
00380      if ( inFlange ) return Ugli::kInSM1;      //  1
00381      else            return Ugli::kDownstream; // -2;
00382    } else { // far
00383      if ( z > fSMZLimits[3] ) {
00384        if ( inFlange ) return Ugli::kInSM2;      //  2;
00385        else            return Ugli::kDownstream; // -2;
00386      }
00387      // FarDet gap
00388      if ( ! inFlange ) return Ugli::kSMGap; // 0;
00389      if ( z < 0.5*(fSMZLimits[1]+fSMZLimits[2]) ) return Ugli::kInSM1; // 1
00390      else                                         return Ugli::kInSM2; // 2
00391    }
00392    return Ugli::kSMGap; // 0
00393 }
00394 
00395 //_____________________________________________________________________________
00396 Ugli::XYRegion_t BfldCache::InXYRegion(const TVector3& pos, Bool_t isUVZ )
00397 {
00398   // Determine if x-y is outside flange area ...
00399   // NearDet is square in UV, diamond in XY
00400   // FarDet is round
00401 
00402   // this should really be part of UgliGeom
00403 
00404   // inside "coil" return 0... not implemented yet
00405   const Double_t rCoil    = 0.0;  // inside this return 0
00406   const Double_t rThroat  = 13.0 * Munits::cm; // inside this return 1
00407   const Double_t rNeck    = 14.0 * Munits::cm; // inside this return 2
00408   const Double_t rHole    = 15.0 * Munits::cm; // inside this return 3
00409   const Double_t rFlange  = 17.0 * Munits::cm; // inside this return 4
00410   // outside return 5
00411 
00412   Double_t rlimit[5] = { rCoil, rThroat, rNeck, rHole, rFlange };
00413   int indx;
00414 
00415   switch (fDetector) {
00416   case Detector::kNear:
00417     {
00418       Double_t u, v;
00419       if (isUVZ) {
00420         u = pos.X();
00421         v = pos.Y();
00422       } else {
00423         Ugli::xy2uv(fDetector,pos.X(),pos.Y(),u,v);
00424       }
00425       for ( indx = Ugli::kCoil; indx <= Ugli::kFlange; ++indx ) {
00426         if ( TMath::Abs(u) < rlimit[indx] &&
00427              TMath::Abs(v) < rlimit[indx]     ) return (Ugli::XYRegion_t)indx;
00428       }
00429       break;
00430     }
00431   case Detector::kFar:
00432     {
00433       Double_t r = pos.Perp();
00434       for ( indx = Ugli::kCoil; indx <= Ugli::kFlange; ++indx ) {
00435         if ( r < rlimit[indx] ) return (Ugli::XYRegion_t)indx;
00436       }
00437     }
00438   default:
00439     return Ugli::kSteel;
00440   }
00441   return Ugli::kSteel;
00442 }
00443 //_____________________________________________________________________________
00444 Int_t BfldCache::GetDefaultMapVariant(const VldContext& vldc)
00445 {
00446    // Return default map (for context)
00447 
00448   // no real data ...
00449   Int_t indx = 0;
00450   Int_t variant;
00451   switch (vldc.GetDetector()) {
00452   case (Detector::kNear):
00453     {
00454       switch (vldc.GetSimFlag()) {
00455       case (SimFlag::kMC):
00456       case (SimFlag::kReroot):
00457         variant = (indx==0) ? 160 : 0; break;
00458       default:
00459         variant = (indx==0) ? 160 : 0; break;
00460       }
00461       break;
00462     }
00463   case (Detector::kFar):
00464     {
00465       switch (vldc.GetSimFlag()) {
00466       case (SimFlag::kMC):
00467       case (SimFlag::kReroot):
00468         variant = (indx==0) ? 208 : 0; break;
00469       default:
00470         variant = (indx==0) ? 208 : 0; break;
00471       }
00472       break;
00473     }
00474   default:                      variant =    0; break;
00475   } 
00476 
00477   return variant;
00478 }
00479 
00480 //_____________________________________________________________________________
00481 Double_t BfldCache::GetDefaultScale(const VldContext& vldc)
00482 {
00483    // Lookup scale factor for this plane
00484 
00485   // no real data ...
00486   Double_t scale;
00487   switch (vldc.GetDetector()) {
00488   case (Detector::kNear):   scale =  1.0; break;
00489   case (Detector::kFar):    scale =  1.0; break;
00490   default:                      scale =    0; break;
00491   } 
00492 
00493   return scale;
00494 }
00495 
00496 //_____________________________________________________________________________
00497 void BfldCache::Print(Option_t * /* option */) const
00498 {
00499   MSG("Bfld",Msg::kInfo) 
00500     << " RefCnt=" << setw(2) << fRef
00501     << " " << fVldRange << endl
00502     << "       DoLocalTransform=" << fDoLocalTransform
00503     << "    InZTest=" << fInZTest
00504     << "    ZTolerance=" << (fZTolerance/Munits::mm) << "mm"
00505     << endl;
00506 }
00507 
00508 
00509 //_____________________________________________________________________________

Generated on Mon Feb 15 11:06:25 2010 for loon by  doxygen 1.3.9.1