00001
00002
00003
00004
00005
00006
00007
00008
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>
00025 #include <iomanip>
00026
00027
00028
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;
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);
00049 os << setprecision(prec);
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
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
00104
00105
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
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
00187
00188
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
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
00216
00217
00218
00219
00220 fFindWasInSteel = true;
00221 Double_t z = posGlobal.z();
00222
00223
00224 if ( fSteelCache.IsValid() && BFieldWithinZ(z,fSteelZmin,fSteelZmax) ) {
00225
00226
00227 }
00228 else {
00229
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
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 if ( fInZTest == 0) return;
00253
00254
00255
00256
00257 if ( fDoLocalTransform <= 0 ) {
00258 fPosInSteel = posGlobal;
00259 if ( ! BFieldOutsideZ(z,fSteelZmin,fSteelZmax) ) return;
00260 } else {
00261
00262
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
00269
00270
00271
00272 fFindWasInSteel = false;
00273
00274 if ( fInZTest < 2 ) {
00275
00276 Double_t z0 = fSteelCache.GetZ0();
00277 Double_t ht = fSteelCache.GetHalfThickness();
00278
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
00300
00301 }
00302
00303
00304 void BfldCache::FillSMZLimits()
00305 {
00306
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;
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;
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
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 Double_t dz = 3.4 * Munits::cm;
00361
00362 Double_t z = pos.Z();
00363
00364
00365 if ( z >= fSMZLimits[0] && z <= fSMZLimits[1] ) return Ugli::kInSM1;
00366 if ( z >= fSMZLimits[2] && z <= fSMZLimits[3] ) return Ugli::kInSM2;
00367
00368
00369 if ( z < fSMZLimits[0]-dz ) return Ugli::kUpstream;
00370 if ( z > fSMZLimits[1]+dz && z < fSMZLimits[2]-dz ) return Ugli::kSMGap;
00371 if ( z > fSMZLimits[3]+dz ) return Ugli::kDownstream;
00372
00373
00374 bool inFlange = ( InXYRegion(pos,isUVZ) <= Ugli::kFlange );
00375 if ( z < fSMZLimits[0] ) {
00376 if ( inFlange ) return Ugli::kInSM1;
00377 else return Ugli::kUpstream ;
00378 }
00379 if ( Detector::kNear == fDetector ) {
00380 if ( inFlange ) return Ugli::kInSM1;
00381 else return Ugli::kDownstream;
00382 } else {
00383 if ( z > fSMZLimits[3] ) {
00384 if ( inFlange ) return Ugli::kInSM2;
00385 else return Ugli::kDownstream;
00386 }
00387
00388 if ( ! inFlange ) return Ugli::kSMGap;
00389 if ( z < 0.5*(fSMZLimits[1]+fSMZLimits[2]) ) return Ugli::kInSM1;
00390 else return Ugli::kInSM2;
00391 }
00392 return Ugli::kSMGap;
00393 }
00394
00395
00396 Ugli::XYRegion_t BfldCache::InXYRegion(const TVector3& pos, Bool_t isUVZ )
00397 {
00398
00399
00400
00401
00402
00403
00404
00405 const Double_t rCoil = 0.0;
00406 const Double_t rThroat = 13.0 * Munits::cm;
00407 const Double_t rNeck = 14.0 * Munits::cm;
00408 const Double_t rHole = 15.0 * Munits::cm;
00409 const Double_t rFlange = 17.0 * Munits::cm;
00410
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
00447
00448
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
00484
00485
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 * ) 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