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

UgliStripNode.cxx

Go to the documentation of this file.
00001 
00002 // $Id: UgliStripNode.cxx,v 1.41 2007/02/04 05:04:45 rhatcher Exp $
00003 //
00004 // UgliStripNode
00005 //
00006 // UgliStripNode is handle to a single strip
00007 //
00008 // Author:  R. Hatcher 2000.11.15
00009 //
00011 
00012 #include "UgliGeometry/UgliStripNode.h"
00013 
00014 #include "UgliGeometry/UgliGeometry.h"
00015 #include "UgliGeometry/TGeometryX.h"
00016 #include "UgliGeometry/UgliScintMdlNode.h"
00017 #include "UgliGeometry/UgliScintPlnNode.h"
00018 
00019 #include "Plex/PlexVetoShieldHack.h"
00020 
00021 #include "MessageService/MsgService.h"
00022 CVSID("$Id: UgliStripNode.cxx,v 1.41 2007/02/04 05:04:45 rhatcher Exp $");
00023 
00024 #include "TMath.h"
00025 
00026 #ifdef UGLI_USE_EXODUS
00027 #include "RerootExodus/RerootExodus.h"
00028 #include "REROOT_Classes/REROOT_CellPos.h"
00029 int isABside(PlaneView::PlaneView_t view, StripEnd::StripEnd_t end) {
00030 // determine if GMINOS A side (0) or B side (1)
00031 // don't call this with end other than kEast or kWest
00032 // return 2 if non-sensical
00033    
00034    if (end != StripEnd::kEast && end != StripEnd::kWest) {
00035       MSG("Ugli",Msg::kWarning) 
00036          << "isABside view \"" << PlaneView::AsString(view) << "\" "
00037          << " end \"" << StripEnd::AsString(end) << "\"" << endl;
00038       return 2;
00039    }
00040 
00041    switch (view) {
00042    case PlaneView::kU: 
00043       return (end == StripEnd::kEast) ? 0 : 1 ;
00044    case PlaneView::kV: 
00045       return (end == StripEnd::kEast) ? 1 : 0 ;
00046    case PlaneView::kY: 
00047       return (end == StripEnd::kEast) ? 0 : 1 ;
00048    case PlaneView::kX: 
00049       return (end == StripEnd::kDown) ? 1 : 0 ;
00050    case PlaneView::kA: 
00051       return (end == StripEnd::kEast) ? 0 : 1 ;
00052    case PlaneView::kB: 
00053       return (end == StripEnd::kDown) ? 1 : 0 ;
00054    default:
00055       MSG("Ugli",Msg::kWarning) 
00056          << "isABside view \"" << PlaneView::AsString(view) << "\" "
00057          << " end \"" << StripEnd::AsString(end) << "\"" << endl;
00058       return 2;
00059    }
00060 }
00061 #endif
00062 
00063 #include "UgliGeometry/UgliDbiTables.h"
00064 
00065 #include "Conventions/Munits.h"
00066 #include "TBRIK.h"
00067 
00068 #include <cassert>
00069 
00070 const Float_t huge_length = 1.0e30;
00071 const char* noshapeName = "noshape";
00072 
00073 ClassImp(UgliStripNode)
00074 
00075 //_____________________________________________________________________________
00076 #ifdef DEBUGSTUFF
00077 // A helper function for outputting TVector3's in a convenient format
00078 std::ostream& operator<<(std::ostream& os, const TVector3& tv3) 
00079 {
00080   int prec = os.precision();
00081   os << "[" << setw(11) << setprecision(6) << tv3.x() 
00082      << "," << setw(11) << setprecision(6) << tv3.y() 
00083      << "," << setw(11) << setprecision(6) << tv3.z() 
00084      << "]";
00085   os << resetiosflags(ios::floatfield);  // reset to "%g" format
00086   os << setprecision(prec); // restore precision
00087   return os;
00088 }
00089 #endif
00090 //_____________________________________________________________________________
00091 UgliStripNode::UgliStripNode()
00092   : fUgliGeometry(0)
00093 {
00094    // Default constructor (for i/o)
00095 }
00096 
00097 //_____________________________________________________________________________
00098 UgliStripNode::~UgliStripNode()
00099 {
00100    // destructor should delete any owned objects
00101    if (CountRef()) {
00102       MSG("Ugli",Msg::kWarning)
00103          << "~UgliStripNode still had " << CountRef()
00104          << " outstanding references " << endl;
00105    }
00106 }
00107 
00108 //_____________________________________________________________________________
00109 UgliStripNode::UgliStripNode(const PlexStripEndId seid,
00110                              UgliScintMdlNode *mdlnode,
00111                              const UgliDbiTables& ugliTables)
00112    : TNodeX(seid.AsString("c"),seid.AsString("c"),noshapeName), //note below
00113      fUgliGeometry(mdlnode->GetUgliGeometry()), fSEId(seid)     
00114 {
00115    // DBI driven ctor under UgliScintMdlNodes
00116 
00117    SetParent(mdlnode);
00118 
00119    fMirrorMask = 0;
00120    if (seid.GetDetector() == Detector::kNear) 
00121       fMirrorMask = StripEnd::kEast;
00122 
00123    // NOTE: we set the shape name here because seid.AsString
00124    // uses a static space such that having both "s" and "c"
00125    // options on the initialization line means we only see one
00126    // of the two possibilities
00127    fShape = fUgliGeometry->GetShape(seid.AsString("s"));
00128 
00129    UgliStripShape* sshape = dynamic_cast<UgliStripShape*>(fShape);
00130    if (!sshape) {
00131       gGeometry->ls("s");
00132       const char* name = "(nil)";
00133       if (fShape) name = fShape->GetName();
00134       MSG("Ugli",Msg::kWarning)
00135          << "ctor for " << seid.AsString("c") 
00136          << "(" << GetName() << "," << GetTitle() << ")" 
00137          << endl
00138          << "   found shape wasn't the UgliStripShape " 
00139          << seid.AsString("s") 
00140          << " instead was named " << name << endl;
00141    }
00142 
00143    unsigned int stripstruct_indx = UgliDbiStructHash(seid).HashAsStrip();
00144    const UgliDbiStripStruct *stripStructRow = 
00145       ugliTables.fStripStructTbl.GetRowByIndex(stripstruct_indx);
00146    int inmdl = stripStructRow->GetInModule();
00147 
00148    // for now some module level info lives at this level
00149    // since we don't have modules to ask
00150    const UgliDbiScintMdl *mdlRow = 
00151       ugliTables.GetDbiScintMdlById(PlexScintMdlId(seid,inmdl));
00152    if (!mdlRow) {
00153       MSG("Ugli",Msg::kError)
00154          << "UgliStripNode ctor failed to get UgliDbiScintMdl" 
00155          << PlexScintMdlId(seid,inmdl)
00156          << endl;
00157       return;
00158    }
00159 
00160    const UgliDbiStrip *stripRow = ugliTables.GetDbiStripById(seid);
00161    if (!stripRow) {
00162       MSG("Ugli",Msg::kError)
00163          << "UgliStripNode ctor failed to get UgliDbiStrip" 
00164          << seid
00165          << endl;
00166       return;
00167    }
00168    // for now we're positioning ourselves in the plane
00169    // as there are no modules
00170    if (mdlRow->GetZRotRelPlnDeg() != 0) 
00171       MSG("Ugli",Msg::kWarning)
00172          << " module  " << mdlRow->GetScintMdlId()
00173          << ", " << mdlRow->GetModule()
00174          << " has rotation of " << mdlRow->GetZRotRelPlnDeg()
00175          << " degrees, but we're not placing strip in module" << endl
00176          << "     rotation is effectively ignored" << endl;
00177    Float_t tpos = stripRow->GetTPosRelMdl();
00178    Float_t lpos = stripRow->GetLPosRelMdl();
00179 
00180    SetLTPosRelMdl(lpos,tpos);
00181    
00182    if (!seid.IsValid()) {
00183       static int nmsg = 20;
00184       if (nmsg) {
00185         MSG("Ugli",Msg::kInfo) 
00186           << "UgliStripNode::ctor: "
00187           << seid.AsString("c") << " @ "
00188           << " tpos " << tpos << " = " 
00189           << mdlRow->GetTPosRelPln() << " + " << stripRow->GetTPosRelMdl()
00190           << endl
00191           << "  not a valid strip: "
00192           << "  seid.IsValid() " << (int)seid.IsValid()
00193           // << ", encoded 0x" << hex << seid.GetEncoded() << dec 
00194           // << ", masked out plane 0x" << hex << (seid.GetEncoded()&maskPlexIdPlane) << dec 
00195           // << ", !=mask is " << hex << (int)((seid.GetEncoded()&maskPlexIdPlane)!=maskPlexIdPlane) << dec 
00196           << endl;
00197         nmsg--;
00198         if (nmsg==0) 
00199           MSG("Ugli",Msg::kInfo) << "  ... last message of this type." << endl;
00200       }
00201    }
00202 
00203    Float_t zrot = stripRow->GetZRotRelMdlRad();
00204    SetZRotRelMdlRad(zrot);
00205 
00206    SetLineColor(18);  // a nice light gray
00207    SetVisibility(0);  // visible
00208 //   if (seid.GetStrip()%8 != 0) SetVisibility(0);
00209 
00210 }
00211 
00212 //_____________________________________________________________________________
00213 void UgliStripNode::SetZRotRelMdlRad(Float_t radians)
00214 {
00215    // set the rotation matrix for this strip
00216    // limit ourselves to -xx.x mrad
00217 
00218    // build the rotation matrices as we need them so we can share
00219    // if we expect a range of +/- 4cm at the furthest extreme of the far
00220    // theta = asin(4cm/400cm) ~ .01 rad = 10mrad
00221    // if we limit ourself to +/- 0.1 mrad then the smallest non-zero
00222    // deviation is .04cm which should be sufficient
00223    const float rad2mrad = 1000.;
00224    const float mrad2rad = 0.001;
00225 
00226    const char* rname = "Identity";
00227    char rname_mrad[16];
00228    if (radians != 0) {
00229       sprintf(rname_mrad,"%+5.1fmrad",radians*rad2mrad);
00230       rname = rname_mrad;
00231    }
00232    TRotMatrix* rotm = fUgliGeometry->GetRotMatrix(rname);
00233    if (!rotm) {
00234       Double_t zrot_trunc;
00235       sscanf(rname,"%5lf",&zrot_trunc);
00236       zrot_trunc *= Ugli::rad2deg * mrad2rad;
00237       MSG("Ugli",Msg::kDebug) 
00238          << "UgliStripNode::SetZRotRelMdlRad no rotm '" 
00239          << rname << "' zrot = " 
00240          << zrot_trunc << " deg" << endl;
00241       Double_t deg90 = 90;
00242       rotm = new TRotMatrix(rname,rname,deg90,zrot_trunc,deg90,
00243                             zrot_trunc+deg90,0,0);
00244    }
00245    fMatrix = rotm;
00246 }
00247 
00248 //_____________________________________________________________________________
00249 
00250 void UgliStripNode::IncrementRef()
00251 {
00252    fRef++; 
00253    fUgliGeometry->IncrementRef();
00254 //   cout << fSEId.AsString("c") << " ++ ref to " << fRef << endl;
00255    SetVisibility(1);
00256 }
00257 
00258 void UgliStripNode::DecrementRef()
00259 { 
00260    fRef--; 
00261    fUgliGeometry->DecrementRef();
00262 //   cout << fSEId.AsString("c") << " -- ref to " << fRef 
00263 //        << ( (!fRef) ? " make invisible" : " " ) << endl;
00264    if (!fRef) SetVisibility(0);
00265 }
00266 
00267 //_____________________________________________________________________________
00268 Float_t UgliStripNode::GetHalfLength() const
00269 { 
00270    // get the strip's half length
00271    TBRIK* brik = dynamic_cast<TBRIK*>(fShape);
00272    if (brik) return brik->GetDx(); else return 0;
00273 }
00274 
00275 //_____________________________________________________________________________
00276 Float_t UgliStripNode::GetHalfThickness() const
00277 { 
00278    // get the strip's half length
00279    TBRIK* brik = dynamic_cast<TBRIK*>(fShape);
00280    if (brik) return brik->GetDz(); else return 0;
00281 }
00282 
00283 //_____________________________________________________________________________
00284 Float_t UgliStripNode::GetHalfWidth() const
00285 { 
00286    // get the strip's half length
00287    TBRIK* brik = dynamic_cast<TBRIK*>(fShape);
00288    if (brik) return brik->GetDy(); else return 0;
00289 }
00290 //_____________________________________________________________________________
00291 Float_t UgliStripNode::GetTPos(Float_t orthCoord) const
00292 { 
00293    // get the strip's tpos offset
00294    // orthCoord is the position in the orthogonal view, this allows one to
00295    // include rotation corrections.
00296    // if orthCoord>1000 use the center of the strip
00297 
00298    PlaneView::PlaneView_t view = fSEId.GetPlaneView();
00299    bool viewIsUV = PlaneView::kU==view || PlaneView::kV==view;
00300    Detector::Detector_t detector = fSEId.GetDetector();
00301 
00302    const Double_t rsqrt2 = 1.0/TMath::Sqrt(2.);
00303    const TVector3 dir_x(1.,0.,0.);
00304    const TVector3 dir_y(0.,1.,0.);
00305    const TVector3 dir_u(rsqrt2,rsqrt2,0.);
00306    const TVector3 dir_v(-rsqrt2,rsqrt2,0.);
00307    const TVector3 dir_u_caldet(1.,0.,0.);
00308    const TVector3 dir_v_caldet(0.,1.,0.);
00309    const TVector3 dir_a(0.,0.,1.);
00310    const TVector3 dir_b(1.,0.,0.);
00311 
00312    TVector3 dir_tpos, dir_orthCoord;
00313 
00314    switch (view) {
00315    case PlaneView::kX:
00316      dir_tpos = dir_x; dir_orthCoord = dir_y;
00317      break;
00318    case PlaneView::kY:
00319      dir_tpos = dir_y; dir_orthCoord = dir_x;
00320      break;
00321    case PlaneView::kU:
00322      if (Detector::kCalib != detector) {
00323        dir_tpos = dir_u; dir_orthCoord = dir_v;
00324      } else {
00325        dir_tpos = dir_u_caldet; dir_orthCoord = dir_v_caldet;
00326      }
00327      break;
00328    case PlaneView::kV:
00329      if (Detector::kCalib != detector) {
00330        dir_tpos = dir_v; dir_orthCoord = dir_u;
00331      } else {
00332        dir_tpos = dir_v_caldet; dir_orthCoord = dir_u_caldet;
00333      }
00334      break;
00335    case PlaneView::kA:
00336      dir_tpos = dir_a;
00337      break;
00338    case PlaneView::kB:
00339      dir_tpos = dir_b;
00340      break;
00341    case PlaneView::kVSTopFlat:
00342    case PlaneView::kVSTopEastSlant:
00343    case PlaneView::kVSTopWestSlant:
00344    case PlaneView::kVSWallOnEdge:
00345    case PlaneView::kVSWallEastSlant:
00346    case PlaneView::kVSWallWestSlant:
00347      MSG("Ugli",Msg::kError)
00348        << "UgliStripNode::GetTPos() not meaningful for veto shield strips "
00349        << fSEId << endl;
00350      return huge_length;
00351      break;
00352    default:
00353       MSG("Ugli",Msg::kWarning)
00354          << "UgliStripNode::GetTPos unknown view " 
00355          << PlaneView::AsString(fSEId.GetPlaneView())
00356          << " in " << fSEId
00357          << endl;
00358       return huge_length;
00359    }
00360 
00361    //cout << " " << fSEId.AsString("c");
00362 
00363    Float_t alongLength = 0.0;  // for wild orthCoord choose *strip* center
00364    if (orthCoord < 1000. && viewIsUV) {
00365      // orthCoord is sensible and we're a U or V plane
00366      // so we need to translate that orthogonal position
00367      // into a position along the strip in order to do rotation corrections
00368 
00369      TVector3 gstrip_center  = GlobalPos(0.,kFALSE);
00370      TVector3 gstrip_plusend = GlobalPos(1.,kFALSE);
00371      TVector3 gstrip_dir = gstrip_plusend - gstrip_center;
00372 
00373      TVector3 tpos_base = orthCoord * dir_orthCoord;
00374      Double_t z = this->GetScintMdlNode()->GetScintPlnNode()->GetZ0();
00375      tpos_base.SetZ(z);
00376 
00377      // aliases, just 'cause it's easier to translate the formula
00378      TVector3& base_s = gstrip_center;
00379      TVector3& dir_s  = gstrip_dir;
00380      TVector3& base_t = tpos_base;
00381      TVector3& dir_t  = dir_tpos;
00382      
00383      TVector3 txs  = dir_t.Cross(dir_s);
00384      TVector3 dpst = base_s - base_t;
00385      TVector3 dpxs = dpst.Cross(dir_s);
00386      Float_t  t    = dpxs.Dot(txs) / txs.Mag2();
00387 
00388      return t;
00389 
00390      /* 
00391         // the unnecessarily hard way ...
00392         TVector3 sxt  = dir_s.Cross(dir_t);
00393         TVector3 dpts = base_t - base_s;
00394         TVector3 dpxt = dpts.Cross(dir_t);
00395         Float_t  s    = dpxt.Dot(sxt) / sxt.Mag2();
00396         
00397         alongLength  = s;
00398      */
00399 
00400    }
00401    TVector3 globalpos = GlobalPos(alongLength,kFALSE);
00402    //return   globalpos.Dot(dir_tpos);
00403    Float_t tpos = globalpos.Dot(dir_tpos);
00404    //cout << " return " << tpos << endl;
00405    return  tpos;
00406 }
00407 
00408 //_____________________________________________________________________________
00409 Float_t UgliStripNode::TotalAttenuation(const StripEnd::StripEnd_t /* end */,
00410                                         const Float_t /* alongLength */) const
00411 { 
00412    // get the attenuation from some point towards pixel at one end
00413    MSG("Ugli",Msg::kFatal)
00414       << "UgliStripNode::GetTotalAttenuation not yet implemented" << endl;
00415    return 0;
00416 }
00417 
00418 //_____________________________________________________________________________
00419 TVector3 UgliStripNode::GlobalPos(const Float_t alongLength,
00420                                   const Bool_t onWLS) const
00421 { 
00422    // get the position based on distance along centerline *or* WLS fiber
00423    // global position is assumed to be in XYZ (hall) coordinates
00424 
00425    if (onWLS) {
00426       MSG("Ugli",Msg::kFatal)
00427          << "UgliStripNode::GlobalPos not yet implemented with onWLS=kTRUE" << endl;
00428       return LocalToGlobal(TVector3(alongLength,0.,0.));
00429    } else {
00430       return LocalToGlobal(TVector3(alongLength,0.,0.));
00431    }
00432 }
00433 
00434 //_____________________________________________________________________________
00435 TVector3 UgliStripNode::GlobalToLocal(const TVector3& global) const
00436 { 
00437    // get the local position based on global position
00438    // global position is assumed to be in XYZ (hall) coordinates
00439 
00440    Double_t gxyz[3], lxyz[3];
00441 
00442    gxyz[0] = global.X();
00443    gxyz[1] = global.Y();
00444    gxyz[2] = global.Z();
00445 
00446    // deal with fact that TNode::Master2Local isn't declared const
00447    UgliStripNode* self = const_cast<UgliStripNode*>(this);
00448    self->cd();
00449    self->UpdateMatrix();
00450    self->Master2Local(gxyz,lxyz);
00451 
00452    return TVector3(lxyz[0],lxyz[1],lxyz[2]);
00453 }
00454 
00455 //_____________________________________________________________________________
00456 TVector3 UgliStripNode::LocalToGlobal(const TVector3& local) const
00457 { 
00458    // get the global position based on local position
00459    // global position is assumed to be in XYZ (hall) coordinates
00460 
00461    Double_t gxyz[3], lxyz[3];
00462 
00463    lxyz[0] = local.X();
00464    lxyz[1] = local.Y();
00465    lxyz[2] = local.Z();
00466 
00467    // deal with fact that TNode::Local2Master isn't declared const
00468    UgliStripNode* self = const_cast<UgliStripNode*>(this);
00469    self->cd();
00470    self->UpdateMatrix();
00471    self->Local2Master(lxyz,gxyz);
00472 
00473    return TVector3(gxyz[0],gxyz[1],gxyz[2]);
00474 }
00475 
00476 //_____________________________________________________________________________
00477 Float_t UgliStripNode::DistanceAlong(const PlexStripEndId& orthogonalStrip) const
00478 { 
00479    // Get the distance along a strip represented by orthogonal strip.
00480    // Note this is relative to the strip's local co-ordinate system
00481    // origin (which for NearDet is not along the U or V axis), so
00482    // one can use it for attenuation corrections but not directly
00483    // for TPos position information.
00484   
00485    // The closest approach ponts on the "s" and "t" lines are:
00486    //    xyz_t(i) = base_t(i) + t*dir_t(i) for i=0..2 {x,y,z} 
00487    //    xyz_o(i) = base_o(i) + o*dir_o(i) for i=0..2 {x,y,z}
00488    // where base_x is  LocalToGlobal(TVector3(0,0,0))
00489    // and   dir_x  is (LocalToGlobal(TVector3(1,0,0))-base_x)
00490    //
00491    // Finding the intersection or closest appraoch of two skew lines
00492    // algorithm was adapted from:
00493    //   Graphic Gems, ed. Andrew S. Glassner, pg 304
00494    //   ISBN 0-12-286165-5   T385.G697(1990)
00495    //
00496    const Double_t farAway = 1.0e25;
00497 
00498    UgliStripNode* otherNode = GetUgliGeometry()->GetStripNode(orthogonalStrip);
00499 
00500    if ( ! otherNode ) {
00501      MSG("Ugli",Msg::kError)
00502        << "UgliStripNode::DistanceAlong(), other strip " 
00503        << orthogonalStrip << " does not exist" << endl;
00504      return farAway;
00505    }
00506    
00507    // s=this, t=other
00508    TVector3 baseThis  = this->GlobalPos(0.,false);
00509    TVector3 dirThis   = this->GlobalPos(1.,false) - baseThis;
00510    
00511    TVector3 baseOther = otherNode->GlobalPos(0.,false);
00512    TVector3 dirOther  = otherNode->GlobalPos(1.,false) - baseOther;
00513    
00514    TVector3 dirCross  = dirThis.Cross(dirOther);
00515    Double_t vxvm2 = dirCross.Mag2();
00516    if (0.0 == vxvm2) {
00517      // exactly parallel strips!
00518      return farAway;
00519    }
00520    
00521    TVector3 dp   = baseOther - baseThis;
00522    TVector3 dpxv = dp.Cross(dirOther);
00523    Double_t s = dpxv.Dot(dirCross) / vxvm2;
00524    
00525    return s;   
00526 }
00527 
00528 //_____________________________________________________________________________
00529 TVector3 UgliStripNode::Intersection(const PlexStripEndId& orthogonalStrip) const
00530 { 
00531    // get the 3-space "intersection" of two strips
00532 
00533    // The closest approach ponts on the "s" and "t" lines are:
00534    //    xyz_t(i) = base_t(i) + t*dir_t(i) for i=0..2 {x,y,z} 
00535    //    xyz_o(i) = base_o(i) + o*dir_o(i) for i=0..2 {x,y,z}
00536    // where base_x is  LocalToGlobal(TVector3(0,0,0))
00537    // and   dir_x  is (LocalToGlobal(TVector3(1,0,0))-base_x)
00538    //
00539    // Finding the intersection or closest appraoch of two skew lines
00540    // algorithm was adapted from:
00541    //   Graphic Gems, ed. Andrew S. Glassner, pg 304
00542    //   ISBN 0-12-286165-5   T385.G697(1990)
00543    //
00544    const Double_t farAway = 1.0e25;
00545    const TVector3 farAway3(farAway,farAway,farAway);
00546 
00547    UgliStripNode* otherNode = GetUgliGeometry()->GetStripNode(orthogonalStrip);
00548    
00549    if ( ! otherNode ) {
00550      MSG("Ugli",Msg::kError)
00551        << "UgliStripNode::Intersection() other strip " 
00552        << orthogonalStrip << " does not exist" << endl;
00553      return farAway3;
00554    }
00555    
00556    // s=this, t=other
00557    TVector3 baseThis  = this->GlobalPos(0.,false);
00558    TVector3 dirThis   = this->GlobalPos(1.,false) - baseThis;
00559    
00560    TVector3 baseOther = otherNode->GlobalPos(0.,false);
00561    TVector3 dirOther  = otherNode->GlobalPos(1.,false) - baseOther;
00562    
00563    TVector3 dirCross  = dirThis.Cross(dirOther);
00564    Double_t vxvm2 = dirCross.Mag2();
00565    if (0.0 == vxvm2) {
00566      // Exactly parallel strips!
00567      return 0.5*(baseThis+baseOther) + farAway*dirThis;
00568    }
00569    
00570    TVector3 dp   = baseOther - baseThis;
00571    TVector3 dpxvThis = dp.Cross(dirOther);
00572    Double_t s = dpxvThis.Dot(dirCross) / vxvm2;
00573    
00574    TVector3 thisPoint = baseThis + s*dirThis;
00575 
00576    dirCross *= -1;
00577    dp       *= -1;
00578    TVector3 dpxvOther = dp.Cross(dirThis);
00579    Double_t t = dpxvOther.Dot(dirCross) / vxvm2;
00580 
00581    TVector3 otherPoint = baseOther + t*dirOther;
00582 
00583    return 0.5*(thisPoint+otherPoint);
00584 }
00585 
00586 //_____________________________________________________________________________
00587 Float_t UgliStripNode::PartialLength(const StripEnd::StripEnd_t end) const
00588 {
00589    // return the (total) length of one of the parts of a split strip
00590    // (if strip is not split return total length regardless of end)
00591 
00592    // this is, to be proper, info of the strip shape
00593    UgliStripShape* strip_shape = GetUgliStripShape();
00594 
00595    if (strip_shape) {
00596 
00597       switch (end) {
00598       case StripEnd::kNegative: 
00599       case StripEnd::kPositive: 
00600          return strip_shape->GetLenPart(end);
00601          break;
00602       default: return huge_length;
00603       }
00604    }
00605    
00606    MSG("Ugli",Msg::kWarning) << "PartialLength() " << endl
00607       << "  shape isn't a UgliStripShape" << endl;
00608 
00609    // fake up a context from the range
00610    VldContext vldc = BackConstructVldContext();
00611 
00612    DbiResultPtr<UgliDbiStripStruct> stripStructTbl(vldc);
00613    unsigned int stripstruct_indx = UgliDbiStructHash(fSEId).HashAsStrip();
00614    const UgliDbiStripStruct *stripStructRow = 
00615       stripStructTbl.GetRowByIndex(stripstruct_indx);
00616 
00617    if (stripStructRow) {
00618       switch (end) {
00619       case StripEnd::kEast: 
00620          return stripStructRow->GetLenEastPart();
00621          break;
00622       case StripEnd::kWest: 
00623          return stripStructRow->GetLenWestPart();
00624           break;
00625       default: return huge_length;
00626       }
00627    } 
00628 
00629    MSG("Ugli",Msg::kWarning) 
00630      << " PartialLength() missing UgliDbiStripStruct" << endl;
00631    return huge_length;
00632 
00633 }
00634 
00635 //_____________________________________________________________________________
00636 Float_t UgliStripNode::WlsPigtail(const StripEnd::StripEnd_t end) const
00637 {
00638    // return the length of the WLS pigtail
00639 
00640    // this is, to be proper, info of the strip shape
00641    UgliStripShape* strip_shape = GetUgliStripShape();
00642    UgliScintMdlNode* mdl = dynamic_cast<UgliScintMdlNode*>(fParent);
00643 
00644    if (strip_shape && mdl) {
00645 
00646       switch (end) {
00647       case StripEnd::kNegative: 
00648       case StripEnd::kPositive: 
00649          return 
00650             strip_shape->GetWls(end) + 
00651             mdl->GetExtraWlsFiber(end);
00652          break;
00653       default: return huge_length;
00654       }
00655    }
00656    
00657    MSG("Ugli",Msg::kWarning) << "WlsPigtail() " << endl
00658       << "  shape isn't a UgliStripShape or parent isn't a UgliScintMdlNode" << endl;
00659 
00660    // fake up a context from the range
00661    VldContext vldc = BackConstructVldContext();
00662 
00663    DbiResultPtr<UgliDbiStripStruct> stripStructTbl(vldc);
00664    unsigned int stripstruct_indx = UgliDbiStructHash(fSEId).HashAsStrip();
00665    const UgliDbiStripStruct *stripStructRow = 
00666       stripStructTbl.GetRowByIndex(stripstruct_indx);
00667    int inmdl = stripStructRow->GetInModule();
00668 
00669    DbiResultPtr<UgliDbiScintMdl> mdlTbl(vldc);
00670    int mdl_indx = UgliDbiScintMdl::HashToIndex(PlexScintMdlId(fSEId,inmdl));
00671    const UgliDbiScintMdl *mdlRow = mdlTbl.GetRowByIndex(mdl_indx);
00672 
00673    if (stripStructRow && mdlRow) {
00674       switch (end) {
00675       case StripEnd::kEast: 
00676          return 
00677             stripStructRow->GetWlsLenEast() +
00678             mdlRow->GetWlsLenEast();
00679          break;
00680       case StripEnd::kWest: 
00681          return 
00682             stripStructRow->GetWlsLenWest() +
00683             mdlRow->GetWlsLenWest();
00684          break;
00685       default: return huge_length;
00686       }
00687    } 
00688 #ifdef UGLI_USE_EXODUS
00689    else if (fUgliGeometry->GetVldRange().GetSimMask() & SimFlag::kReroot) {
00690 
00691       REROOT_CellPos *cellpos = RerootExodus::GetCellPos(fSEId);
00692       if (!cellpos) {
00693          MSG("Ugli",Msg::kWarning) 
00694             << "No CellPos for " << fSEId.AsString() << endl;
00695          return huge_length;
00696       }
00697 
00698       Float_t fWlsPigtail[3];
00699       fWlsPigtail[0] = cellpos->FiberTailA() * Munits::cm;
00700       fWlsPigtail[1] = cellpos->FiberTailB() * Munits::cm;
00701       fWlsPigtail[2] = huge_length;
00702       PlaneView::PlaneView_t view = fSEId.GetPlaneView();
00703 
00704       return fWlsPigtail[isABside(view,end)];
00705       
00706    }
00707 #endif
00708    MSG("Ugli",Msg::kWarning) 
00709      << " WlsPigtail() missing info: " << endl
00710      << "     stripStructRow " << stripStructRow
00711      << " MdlRow " << mdlRow << endl;
00712    return huge_length;
00713 
00714 }
00715 
00716 //_____________________________________________________________________________
00717 Float_t UgliStripNode::WlsBypass() const
00718 {
00719    // return the length of the WLS of the central bypass
00720 
00721    // this is, to be proper, info of the strip shape
00722    UgliStripShape* strip_shape = GetUgliStripShape();
00723 
00724    if (strip_shape) return strip_shape->GetWlsLenBypass();
00725    
00726    MSG("Ugli",Msg::kWarning) << "WlsBypass() " << endl
00727       << "  shape isn't a UgliStripShape" << endl;
00728 
00729    // fake up a context from the range
00730    VldContext vldc = BackConstructVldContext();
00731 
00732    DbiResultPtr<UgliDbiStripStruct> stripStructTbl(vldc);
00733    unsigned int stripstruct_indx = UgliDbiStructHash(fSEId).HashAsStrip();
00734    const UgliDbiStripStruct *stripStructRow = 
00735       stripStructTbl.GetRowByIndex(stripstruct_indx);
00736 
00737    if (stripStructRow) return stripStructRow->GetWlsLenBypass();
00738 
00739    MSG("Ugli",Msg::kWarning) 
00740      << " WlsBypass() missing UgliDbiStripStruct " << endl;
00741 
00742    return 0.0;
00743 
00744 }
00745 
00746 //_____________________________________________________________________________
00747 Float_t UgliStripNode::ClearFiber(const StripEnd::StripEnd_t end) const
00748 {
00749 
00750    UgliScintMdlNode* mdl = dynamic_cast<UgliScintMdlNode*>(fParent);
00751 
00752    if (mdl) return mdl->GetClearFiber(end);
00753       
00754    MSG("Ugli",Msg::kWarning) << "ClearFiber() " << endl
00755                              << "  parent isn't a UgliScintMdlNode" << endl;
00756 
00757    // fake up a context from the range
00758    VldContext vldc = BackConstructVldContext();
00759 
00760    DbiResultPtr<UgliDbiStripStruct> stripStructTbl(vldc);
00761    unsigned int stripstruct_indx = UgliDbiStructHash(fSEId).HashAsStrip();
00762    const UgliDbiStripStruct *stripStructRow = 
00763       stripStructTbl.GetRowByIndex(stripstruct_indx);
00764    int inmdl = stripStructRow->GetInModule();
00765 
00766    DbiResultPtr<UgliDbiScintMdl> mdlTbl(vldc);
00767    int mdl_indx = UgliDbiScintMdl::HashToIndex(PlexScintMdlId(fSEId,inmdl));
00768    const UgliDbiScintMdl *mdlRow = mdlTbl.GetRowByIndex(mdl_indx);
00769 
00770    if (mdlRow) {
00771       switch (end) {
00772       case StripEnd::kEast: return mdlRow->GetClearLenEast(); break;
00773       case StripEnd::kWest: return mdlRow->GetClearLenWest(); break;
00774       default: return huge_length;
00775       }
00776    }
00777 #ifdef UGLI_USE_EXODUS
00778    else if (fUgliGeometry->GetVldRange().GetSimMask() & SimFlag::kReroot) {
00779 
00780       REROOT_CellPos *cellpos = RerootExodus::GetCellPos(fSEId);
00781       if (!cellpos) {
00782          MSG("Ugli",Msg::kWarning) 
00783             << "No CellPos for " << fSEId.AsString() << endl;
00784          return huge_length;
00785       }
00786 
00787       Float_t fClearFiber[3];
00788       fClearFiber[0] = cellpos->ClearFiberA() * Munits::cm;
00789       fClearFiber[1] = cellpos->ClearFiberB() * Munits::cm;
00790       fClearFiber[2] = huge_length;
00791       PlaneView::PlaneView_t view = fSEId.GetPlaneView();
00792 
00793       return fClearFiber[isABside(view,end)];
00794 
00795    }
00796 #endif
00797    MSG("Ugli",Msg::kWarning) 
00798      << " ClearFiber() missing info:  MdlRow " << mdlRow << endl;
00799    return huge_length;
00800 
00801 }
00802 
00803 //_____________________________________________________________________________
00804 VldContext UgliStripNode::BackConstructVldContext() const
00805 {
00806    // build a fake VldContext from the VldRange
00807    // so we can access the DBI
00808 
00809    VldRange vrng = fUgliGeometry->GetVldRange();
00810    int det = vrng.GetDetectorMask();
00811    int sim = vrng.GetSimMask();
00812    // trim "det" and "sim" down to single bit
00813    for (int i=0; i<32; ++i) {
00814       int bit = 1<<i;
00815       if (det&bit) det=bit;
00816       if (sim&bit) sim=bit;
00817    }
00818    
00819    return VldContext((Detector::Detector_t)det,
00820                      (SimFlag::SimFlag_t)sim,
00821                      vrng.GetTimeStart());
00822 
00823 }
00824 
00825 //_____________________________________________________________________________
00826 // inlining this causes circular dependencies
00827 
00828 //inline 
00829 UgliScintMdlNode* UgliStripNode::GetScintMdlNode(void) const
00830 {  return dynamic_cast<UgliScintMdlNode*>(fParent); }
00831 
00832 //_____________________________________________________________________________

Generated on Mon Feb 15 11:07:49 2010 for loon by  doxygen 1.3.9.1