00001
00002
00003
00004
00005
00006
00007
00009 #include "Swimmer/SwimGeo.h"
00010 #include <iostream>
00011 #include <string>
00012
00013 #include "Swimmer/SwimPlaneInterface.h"
00014 #include "Swimmer/SwimParticle.h"
00015 #include "Swimmer/SwimStepData.h"
00016
00017 #include "Plex/PlexPlaneId.h"
00018 #include "UgliGeometry/UgliGeomHandle.h"
00019 #include "UgliGeometry/UgliScintPlnHandle.h"
00020 #include "UgliGeometry/UgliSteelPlnHandle.h"
00021 #include "MessageService/MsgService.h"
00022
00023 #include "TMath.h"
00024
00025 CVSID("$Id: SwimGeo.cxx,v 1.20 2007/11/11 04:37:27 rhatcher Exp $");
00026 using std::vector;
00027 using std::pair;
00028 static const double kInvSqrt2 = TMath::Sqrt(0.5);
00029
00030
00031 SwimGeo* SwimGeo::fInstance = 0;
00032
00033
00034
00035 SwimGeo *SwimGeo::Instance(const VldContext& vldc)
00036 {
00037
00038
00039
00040 if (fInstance && (fInstance->fVldRange).IsCompatible(vldc)) return fInstance;
00041
00042
00043 if (fInstance) {
00044 MSG("Swim",Msg::kDebug)
00045 << "SwimGeo kill version for range " << fInstance->fVldRange << endl;
00046 delete fInstance;
00047 }
00048 fInstance = new SwimGeo(vldc);
00049
00050 return fInstance;
00051 }
00052
00053
00054
00055 SwimGeo::SwimGeo(const VldContext& vldc) :
00056 fNInterfaces(0),
00057 fNextPlaneZ(0.0*Munits::m)
00058 {
00059
00060
00061
00062
00063
00064 MSG("Swim",Msg::kDebug) << "SwimGeo created for " << vldc << endl;
00065 fVld=vldc;
00066 SwimPlaneInterface *spi=0;
00067 UgliGeomHandle ugh(vldc);
00068 fVldRange = ugh.GetVldRange();
00069
00070 std::vector<UgliPlnHandle> uph_vec = ugh.GetPlnHandleVector();
00071
00072 for (unsigned int i=0; i < uph_vec.size(); ++i) {
00073 UgliPlnHandle uph = uph_vec[i];
00074 PlexPlaneId plnid = uph.GetPlexPlaneId();
00075 PlaneView::PlaneView_t view = plnid.GetPlaneView();
00076 if (PlaneView::kA == view && PlaneView::kB == view) continue;
00077 if (view > PlaneView::kUnknown) continue;
00078 SwimGeo::SwimMaterial_t plnmat =
00079 (plnid.IsSteel()) ? SwimGeo::kSteel : SwimGeo::kScint;
00080 Double_t z0 = uph.GetZ0();
00081 Double_t dz = uph.GetHalfThickness();
00082 spi = new SwimPlaneInterface(z0-dz,SwimGeo::kAir,plnmat);
00083 fInterface.Add(spi);
00084 spi = new SwimPlaneInterface(z0+dz,plnmat,SwimGeo::kAir);
00085 fInterface.Add(spi);
00086
00087 MSG("Swim",Msg::kDebug)
00088 << " add " << plnid.AsString("c") << " " << AsString(plnmat)
00089 << " z [" << z0-dz << "," << z0+dz << "]" << endl;
00090 }
00091
00092 fInterface.Sort();
00093 fNInterfaces=fInterface.GetLast()+1;
00094 if(fNInterfaces>5000)
00095 MSG("Swim",Msg::kFatal) << " Interface list not long enough in SwimGeo.h " << endl;
00096 for(Int_t i=0;i<fNInterfaces;i++){
00097 fInterfaceList[i]= dynamic_cast<SwimPlaneInterface *>(fInterface.At(i));
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 fFarCoilRadius = 12*Munits::cm;
00120 fFarOuterCollarRadius = 17*Munits::cm;
00121 fFarInnerCollarRadius = 13*Munits::cm;
00122 fFarEndSM1Z = 14.5*Munits::m;
00123 fFarBegSM2Z = 16*Munits::m;
00124
00125
00126 fNearCoilLength = 24*Munits::cm;
00127 fNearOuterCollarLength = 34*Munits::cm;
00128 fNearInnerCollarLength = 26*Munits::cm;
00129 fNearCoil = InitNearCoil();
00130 fNearInnerCollar = InitNearInnerCollar();
00131 fNearOuterCollar = InitNearOuterCollar();
00132
00133 MSG("Swim",Msg::kDebug)<<"Far Coil Radius = "<<fFarCoilRadius<<endl;
00134 MSG("Swim",Msg::kDebug)<<"Far Inner Coil Radius = "<<fFarInnerCollarRadius<<endl;
00135 MSG("Swim",Msg::kDebug)<<"Far Outer Collar Radius = "<<fFarOuterCollarRadius<<endl;
00136
00137 if (MsgService::Instance()->IsActive("Swim",Msg::kDebug)) Print();
00138 }
00139
00140
00141 void SwimGeo::Print(Option_t * ) const
00142 {
00143
00144 MsgStream& msg = MSGSTREAM("Swim",Msg::kInfo);
00145
00146 double prevz = 0.0;
00147 for (int i=0; i <= fInterface.GetLast(); ++i) {
00148 SwimPlaneInterface *spi =
00149 dynamic_cast<SwimPlaneInterface*>(fInterface.At(i));
00150 if ( ! spi ) continue;
00151 spi->Print("0");
00152 double thisz = spi->GetZ();
00153 msg << " dz = " << thisz - prevz << endl;
00154 prevz = thisz;
00155 }
00156 }
00157
00158
00159
00160 SwimPlaneInterface* SwimGeo::GetInterface(Double_t z, Int_t idir,
00161 SwimGeo::SwimMaterial_t material) const
00162 {
00163 Int_t iLow=0;
00164 Int_t iHi=fNInterfaces;
00165 Int_t iMid=0;
00166 while( (iHi-iLow)>1){
00167 iMid=(iLow+iHi) >> 1;
00168 SwimPlaneInterface *spi = fInterfaceList[iMid];
00169
00170 if(z>=spi->GetZ())
00171 iLow=iMid;
00172 else
00173 iHi=iMid;
00174 }
00175 Int_t ibeg=0;
00176 Int_t iend=0;
00177 Int_t idirection=0;
00178 if (idir==0) {
00179 ibeg = iHi;
00180 iend = fNInterfaces;
00181 idirection = 1;
00182 }
00183 else {
00184 ibeg = iLow;
00185 iend = -1;
00186 idirection = -1;
00187 }
00188 for (Int_t i=ibeg; i!=iend; i+=idirection) {
00189 SwimPlaneInterface *spi = fInterfaceList[i];
00190 Double_t spiZ=spi->GetZ();
00191 if (spi->GetMaterialBefore() == material ||
00192 spi->GetMaterialAfter() == material ) {
00193 if (idir==0 && spiZ > z ) {
00194 return spi;
00195 }
00196 else if(idir==1 && spiZ < z){
00197 return spi;
00198 }
00199 }
00200 }
00201 MSG("SwimGeo",Msg::kFatal)
00202 << "Could not find " << AsString(material) << " interface "
00203 << z << " " << idir << " " << ibeg
00204 << " " << iend << endl;
00205
00206 return 0;
00207 }
00208
00209
00210
00211 SwimGeo::SwimMaterial_t SwimGeo::GetSwimMaterial(const TVector3 xyz, bool zDir)
00212 {
00213
00214
00215
00216
00217
00218
00219
00220
00221 Int_t iLow=0;
00222 Int_t iHi=fNInterfaces;
00223 Int_t iMid=0;
00224 Double_t xyzZ=xyz.Z();
00225 while( (iHi-iLow)>1){
00226 iMid=(iLow+iHi)>>1;
00227 SwimPlaneInterface *spi = fInterfaceList[iMid];
00228 if(xyzZ>=spi->GetZ())
00229 iLow=iMid;
00230 else
00231 iHi=iMid;
00232 }
00233
00234 Int_t ibeg=0;
00235 Int_t iend=0;
00236 Int_t idirection=0;
00237 if (zDir==1) {
00238 ibeg = iHi;
00239 iend = fNInterfaces;
00240 idirection = 1;
00241 }
00242 else {
00243 ibeg = iLow;
00244 iend = -1;
00245 idirection = -1;
00246 }
00247
00248
00249 for (int i=ibeg; i!=iend; i+=idirection) {
00250 SwimPlaneInterface *spi = fInterfaceList[i];
00251 Double_t spiZ=spi->GetZ();
00252 if (zDir && spiZ > xyz.Z() ) {
00253 fNextPlaneZ = spi->GetZ();
00254 switch (spi->GetMaterialBefore() ) {
00255 case kAir: return kAir;
00256 case kScint: return kScint;
00257 case kSteel: return kSteel;
00258 default: break;
00259 }
00260 }
00261 else if (!zDir && spi->GetZ() < xyz.Z() ) {
00262 fNextPlaneZ = spi->GetZ();
00263 switch (spi->GetMaterialAfter() ) {
00264 case kAir: return kAir;
00265 case kScint: return kScint;
00266 case kSteel: return kSteel;
00267 default: break;
00268 }
00269 }
00270 }
00271
00272 fNextPlaneZ = 0.0;
00273 return kError;
00274 }
00275
00276
00277
00278 SwimGeo::SwimMaterial_t SwimGeo::GetSwimMaterial(const TVector3 xyz, bool zDir, SwimStepData& stepdata)
00279 {
00280
00281
00282 if(SetNextPlaneZ(xyz,zDir,stepdata)) {
00283
00284
00285 if(IsInsideCoil( xyz , fVld.GetDetector()) &&
00286 fVld.GetDetector()==Detector::kNear )return kCoil_near;
00287 if(IsInsideCoil( xyz ,fVld.GetDetector()) &&
00288 fVld.GetDetector()==Detector::kFar )return kCoil_far;
00289 if(IsInsideOuterCollar( xyz ,fVld.GetDetector()) ) {
00290 if( IsInsideInnerCollar(xyz,fVld.GetDetector())) return kAir;
00291 else return kSteel;
00292 }
00293
00294
00295
00296
00297 SwimPlaneInterface *spi = fInterfaceList[stepdata.GetSPI()];
00298 if(zDir) {
00299 switch (spi->GetMaterialBefore()) {
00300 case kAir: return kAir;
00301 case kScint: return kScint;
00302 case kSteel: return kSteel;
00303 default: break;
00304 }
00305 }
00306 else if(!zDir) {
00307 switch (spi->GetMaterialAfter()) {
00308 case kAir: return kAir;
00309 case kScint: return kScint;
00310 case kSteel: return kSteel;
00311 default: break;
00312 }
00313 }
00314 return kError;
00315 }
00316
00317 else return kError;
00318
00319 }
00320
00321
00322
00323 Bool_t SwimGeo::SetNextPlaneZ(const TVector3 xyz,bool zDir,SwimStepData& stepdata)
00324 {
00325
00326 int ibeg;
00327 int iend;
00328 int idirection;
00329 int i;
00330
00331
00332 if ( stepdata.GetSPI() == -1 ) {
00333
00334 Int_t iLow=0;
00335 Int_t iHi=fNInterfaces;
00336 Int_t iMid=0;
00337 Double_t z = xyz.Z();
00338 while( (iHi-iLow)>1){
00339 iMid=(iLow+iHi) >> 1;
00340 SwimPlaneInterface *spi = fInterfaceList[iMid];
00341 if(z>=spi->GetZ())
00342 iLow=iMid;
00343 else
00344 iHi=iMid;
00345 }
00346
00347 if (zDir) {
00348 stepdata.SetSPI(iHi);
00349 } else {
00350 stepdata.SetSPI(iLow);
00351 }
00352 }
00353
00354 ibeg = stepdata.GetSPI();
00355 if (zDir) {
00356 iend = fNInterfaces;
00357 idirection = 1;
00358 }
00359 else {
00360 iend = -1;
00361 idirection = -1;
00362 }
00363
00364 for (i=ibeg; i!=iend; i+=idirection) {
00365 SwimPlaneInterface *spi = fInterfaceList[i];
00366 Double_t spiZ=spi->GetZ();
00367 Double_t xyzZ=xyz.Z();
00368
00369 if (zDir && spiZ > xyzZ ) {
00370 stepdata.SetSPI(i);
00371 fNextPlaneZ = spiZ;
00372 return true;
00373 }
00374 else if (!zDir && spiZ < xyzZ ) {
00375 stepdata.SetSPI(i);
00376 fNextPlaneZ = spiZ;
00377 return true;
00378 }
00379 }
00380
00381
00382
00383 fNextPlaneZ = 0.0;
00384 return false;
00385 }
00386
00387
00388
00389 double SwimGeo::DistToNextPlane(const TVector3 xyz, const TVector3 dxyz)
00390 {
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 return TMath::Abs((fNextPlaneZ-xyz.Z())/dxyz.Z());
00404
00405 }
00406
00408
00409 vector< pair<Double_t,Double_t> > SwimGeo::InitNearCoil(){
00410
00411
00412 vector< pair<Double_t,Double_t> > v;
00413 Double_t a=fNearInnerCollarLength;
00414 Double_t b=fNearCoilLength;
00415
00416
00417
00418
00419
00420 Double_t rx=-b*kInvSqrt2;
00421 Double_t ry=-(a-b)*kInvSqrt2;
00422
00423 Double_t lx=b*kInvSqrt2;
00424 Double_t ly=-(a-b)*kInvSqrt2;
00425
00426 Double_t ux=0;
00427 Double_t uy=(2*b-a)*kInvSqrt2;
00428
00429 Double_t bx=0;
00430 Double_t by=-a*kInvSqrt2;
00431
00432 v.push_back(pair<Double_t,Double_t>(lx,ly));
00433 v.push_back(pair<Double_t,Double_t>(ux,uy));
00434 v.push_back(pair<Double_t,Double_t>(rx,ry));
00435 v.push_back(pair<Double_t,Double_t>(bx,by));
00436 v.push_back(pair<Double_t,Double_t>(lx,ly));
00437
00438 MSG("Swim",Msg::kDebug)<<"In Beams Eye View "<<endl;
00439 MSG("Swim",Msg::kDebug)<<"Near Coil Top(X,Y) = "<<ux<<","<<uy<<endl;
00440 MSG("Swim",Msg::kDebug)<<"Near Coil Left(X,Y) = "<<lx<<","<<ly<<endl;
00441 MSG("Swim",Msg::kDebug)<<"Near Coil Bottom(X,Y) = "<<bx<<","<<by<<endl;
00442 MSG("Swim",Msg::kDebug)<<"Near Coil Right(X,Y) = "<<rx<<","<<ry<<endl;
00443 return v;
00444 }
00445
00446
00447
00448 vector< pair<Double_t,Double_t> > SwimGeo::InitNearOuterCollar(){
00449
00450 vector< pair<Double_t,Double_t> > v;
00451 Double_t s=fNearOuterCollarLength*kInvSqrt2;
00452
00453
00454
00455 v.push_back(pair<Double_t,Double_t>(s,0));
00456 v.push_back(pair<Double_t,Double_t>(0,s));
00457 v.push_back(pair<Double_t,Double_t>(-s,0));
00458 v.push_back(pair<Double_t,Double_t>(0,-s));
00459 v.push_back(pair<Double_t,Double_t>(s,0));
00460
00461 MSG("Swim",Msg::kDebug)<<"Near Collar Top(X,Y) = "<<0<<","<<s<<endl;
00462 MSG("Swim",Msg::kDebug)<<"Near Collar Left(X,Y) = "<<s<<","<<0<<endl;
00463 MSG("Swim",Msg::kDebug)<<"Near Collar Bottom(X,Y) = "<<0<<","<<-s<<endl;
00464 MSG("Swim",Msg::kDebug)<<"Near Collar Right(X,Y) = "<<-s<<","<<0<<endl;
00465
00466 return v;
00467 }
00468
00469 vector< pair<Double_t,Double_t> > SwimGeo::InitNearInnerCollar(){
00470
00471 vector< pair<Double_t,Double_t> > v;
00472 Double_t s=fNearInnerCollarLength*kInvSqrt2;
00473
00474
00475
00476 v.push_back(pair<Double_t,Double_t>(s,0));
00477 v.push_back(pair<Double_t,Double_t>(0,s));
00478 v.push_back(pair<Double_t,Double_t>(-s,0));
00479 v.push_back(pair<Double_t,Double_t>(0,-s));
00480 v.push_back(pair<Double_t,Double_t>(s,0));
00481
00482 MSG("Swim",Msg::kDebug)<<"Near Air Top(X,Y) = "<<0<<","<<s<<endl;
00483 MSG("Swim",Msg::kDebug)<<"Near Air Left(X,Y) = "<<s<<","<<0<<endl;
00484 MSG("Swim",Msg::kDebug)<<"Near Air Bottom(X,Y) = "<<0<<","<<-s<<endl;
00485 MSG("Swim",Msg::kDebug)<<"Near Air Right(X,Y) = "<<-s<<","<<0<<endl;
00486
00487 return v;
00488 }
00489
00490
00491
00492 Bool_t SwimGeo::IsInsideCoil(TVector3 xyz, Detector::Detector_t dt)
00493 {
00494
00495 Double_t x = xyz.X();
00496 Double_t y = xyz.Y();
00497 Double_t z = xyz.Z();
00498
00499 Double_t r=TMath::Sqrt(x*x+y*y);
00500 if ( dt == Detector::kNear ) {
00501
00502 if( IsInside(x,y,fNearCoil) ) return true;
00503
00504 }
00505 else if ( dt == Detector::kFar ) {
00506
00507 if( r < fFarCoilRadius && z > fFarBegSM2Z && z < fFarEndSM1Z ) return true;
00508
00509 }
00510
00511 return false;
00512
00513 }
00514
00515
00516
00517 Bool_t SwimGeo::IsInsideOuterCollar(TVector3 xyz, Detector::Detector_t dt)
00518 {
00519 Double_t x = xyz.X();
00520 Double_t y = xyz.Y();
00521 Double_t z = xyz.Z();
00522
00523 Double_t r=TMath::Sqrt(x*x+y*y);
00524
00525
00526 if ( dt == Detector::kNear ) {
00527
00528 if( IsInside(x,y,fNearOuterCollar) ) return true;
00529
00530 }
00531 else if ( dt == Detector::kFar ) {
00532
00533 if( r < fFarOuterCollarRadius && z > fFarBegSM2Z && z < fFarEndSM1Z ) return true;
00534
00535 }
00536
00537 return false;
00538 }
00539
00540 Bool_t SwimGeo::IsInsideInnerCollar(TVector3 xyz, Detector::Detector_t dt)
00541 {
00542 Double_t x = xyz.X();
00543 Double_t y = xyz.Y();
00544 Double_t z = xyz.Z();
00545
00546 Double_t r=TMath::Sqrt(x*x+y*y);
00547
00548 if ( dt == Detector::kNear ) {
00549
00550 if( IsInside(x,y,fNearInnerCollar) ) return true;
00551 }
00552
00553 else if ( dt == Detector::kFar ) {
00554
00555 if( r < fFarInnerCollarRadius && z > fFarBegSM2Z && z < fFarEndSM1Z ) return true;
00556 }
00557 return false;
00558 }
00559
00560
00561
00562 bool SwimGeo::IsInside(Double_t xp, Double_t yp,
00563 const vector< pair<Double_t,Double_t> >& v) const
00564 {
00565
00566
00567 Double_t xint;
00568 Int_t inter = 0;
00569 Int_t np=v.size();
00570 for (Int_t i=0;i<np-1;i++) {
00571 if (v[i].second == v[i+1].second) continue;
00572 if (yp <= v[i].second && yp <= v[i+1].second) continue;
00573 if (v[i].second < yp && v[i+1].second < yp) continue;
00574 xint = v[i].first
00575 + (yp-v[i].second)*(v[i+1].first-v[i].first)/(v[i+1].second-v[i].second);
00576 if (xp < xint) inter++;
00577 }
00578 if (inter%2) return true;
00579 return false;
00580 }
00582
00583 double SwimGeo::GetSwimMaterialDensity(SwimGeo::SwimMaterial_t mat)
00584 {
00585 switch (mat) {
00586 case (SwimGeo::kAir): return 0.001*Munits::g/(Munits::cm3);
00587 case (SwimGeo::kScint): return MinosMaterial::Density(MinosMaterial::ePolystyreneMinos)*Munits::g/(Munits::cm3);
00588 case (SwimGeo::kSteel): return MinosMaterial::Density(MinosMaterial::eIronMinos)*Munits::g/(Munits::cm3);
00589 case (SwimGeo::kAluminum): return 2.699*Munits::g/(Munits::cm3);
00590 case (SwimGeo::kCopper): return 8.96*Munits::g/(Munits::cm3);
00591 case (SwimGeo::kHydrogen): return 0.063*Munits::g/(Munits::cm3);
00592 case (SwimGeo::kOxygen): return 1.140*Munits::g/(Munits::cm3);
00593 case (SwimGeo::kWater): return 1.0*Munits::g/(Munits::cm3);
00594 case (SwimGeo::kCarbon): return 2.265*Munits::g/(Munits::cm3);
00595 case (SwimGeo::kNitrogen): return 0.808*Munits::g/(Munits::cm3);
00596 case (SwimGeo::kCoil_near):
00597
00598
00599 return 2.35731*Munits::g/(Munits::cm3);
00600
00601 case (SwimGeo::kCoil_far):
00602
00603 return 2.3488*Munits::g/(Munits::cm3);
00604 case (SwimGeo::kError): return 0.0*Munits::g/(Munits::cm3);
00605 default: return 0.0*Munits::g/(Munits::cm3);
00606 };
00607 }