CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/Geometry/CSCGeometry/src/CSCLayerGeometry.cc

Go to the documentation of this file.
00001 // This is CSCLayerGeometry.cc
00002 
00003 #include <Geometry/CSCGeometry/interface/CSCGeometry.h>
00004 #include <Geometry/CSCGeometry/interface/CSCLayerGeometry.h>
00005 
00006 #include <Geometry/CSCGeometry/src/CSCUngangedStripTopology.h>
00007 #include <Geometry/CSCGeometry/src/CSCGangedStripTopology.h>
00008 #include <Geometry/CSCGeometry/src/CSCWireGroupPackage.h>
00009 
00010 
00011 #include <FWCore/MessageLogger/interface/MessageLogger.h>
00012 
00013 #include "CLHEP/Units/GlobalSystemOfUnits.h"
00014 
00015 #include <algorithm>
00016 #include <iostream>
00017 #include <cmath> // for M_PI_2 via math.h, as long as appropriate compiler flag switched on to allow acces
00018 
00019 // Complicated initialization list since the chamber Bounds passed in must have its thickness reset to that of the layer
00020 // Note for half-widths, t + b = 2w and the TPB only has accessors for t and w so b = 2w - t
00021 
00022 CSCLayerGeometry::CSCLayerGeometry( const CSCGeometry* geom, int iChamberType,
00023          const TrapezoidalPlaneBounds& bounds,
00024          int nstrips, float stripOffset, float stripPhiPitch,
00025          float whereStripsMeet, float extentOfStripPlane, float yCentreOfStripPlane,
00026          const CSCWireGroupPackage& wg, float wireAngleInDegrees, double yOfFirstWire, float hThickness )
00027   :   TrapezoidalPlaneBounds( bounds.widthAtHalfLength() - bounds.width()/2., bounds.width()/2., bounds.length()/2., hThickness ), 
00028       theWireTopology( 0 ), theStripTopology( 0 ), 
00029       hBottomEdge( bounds.widthAtHalfLength() - bounds.width()/2. ), 
00030       hTopEdge( bounds.width()/2. ), apothem( bounds.length()/2. ),  
00031       myName( "CSCLayerGeometry" ), chamberType( iChamberType ) {
00032 
00033   LogTrace("CSCLayerGeometry|CSC") << myName <<": being constructed, this=" << this;
00034 
00035   // Ganged strips in ME1A?
00036   bool gangedME1A = ( iChamberType == 1 && geom->gangedStrips() );
00037 
00038   CSCStripTopology* aStripTopology = 
00039         new CSCUngangedStripTopology(nstrips, stripPhiPitch,
00040             extentOfStripPlane, whereStripsMeet, stripOffset, yCentreOfStripPlane );
00041 
00042   if ( gangedME1A ) {
00043     theStripTopology = new CSCGangedStripTopology( *aStripTopology, 16 );
00044     delete aStripTopology;
00045   }
00046   else {
00047     theStripTopology = aStripTopology;
00048   }
00049 
00050   if ( ! geom->realWireGeometry() ) {
00051     // Approximate ORCA_8_8_0 and earlier calculated geometry...
00052     float wangler = wireAngleInDegrees*degree; // convert angle to radians
00053     float wireCos = cos(wangler);
00054     float wireSin = sin(wangler);
00055     float y2 = apothem * wireCos + hBottomEdge * fabs(wireSin);
00056     float wireSpacing = wg.wireSpacing/10.; // in cm
00057     float wireOffset = -y2 + wireSpacing/2.;
00058     yOfFirstWire = wireOffset/wireCos;
00059   }
00060 
00061   theWireTopology = new CSCWireTopology( wg, yOfFirstWire, wireAngleInDegrees );
00062   LogTrace("CSCLayerGeometry|CSC") << myName <<": constructed: "<< *this;
00063 } 
00064 
00065 CSCLayerGeometry::CSCLayerGeometry(const CSCLayerGeometry& melg) :
00066   TrapezoidalPlaneBounds(melg.hBottomEdge, melg.hTopEdge, melg.apothem,
00067                          0.5 * melg.thickness() ),
00068   theWireTopology(0), theStripTopology(0), 
00069   hBottomEdge(melg.hBottomEdge), hTopEdge(melg.hTopEdge),
00070   apothem(melg.apothem), chamberType(melg.chamberType) 
00071 {
00072   // CSCStripTopology is abstract, so need clone()
00073   if (melg.theStripTopology) theStripTopology = melg.theStripTopology->clone();
00074   // CSCWireTopology is concrete, so direct copy
00075   if (melg.theWireTopology) theWireTopology = new CSCWireTopology(*(melg.theWireTopology));
00076 }
00077 
00078 CSCLayerGeometry& CSCLayerGeometry::operator=(const CSCLayerGeometry& melg)
00079 {
00080   if ( &melg != this ) {
00081     delete theStripTopology;
00082     if ( melg.theStripTopology )
00083       theStripTopology=melg.theStripTopology->clone();
00084     else
00085       theStripTopology=0;
00086 
00087     delete theWireTopology;
00088     if ( melg.theWireTopology )
00089       theWireTopology=new CSCWireTopology(*(melg.theWireTopology));
00090     else
00091       theWireTopology=0;
00092 
00093     hBottomEdge     = melg.hBottomEdge;
00094     hTopEdge        = melg.hTopEdge;
00095     apothem         = melg.apothem;
00096   }
00097   return *this;
00098 }
00099 
00100 CSCLayerGeometry::~CSCLayerGeometry()
00101 {
00102   LogTrace("CSCLayerGeometry|CSC") << myName << ": being destroyed, this=" << this << 
00103     "\nDeleting theStripTopology=" << theStripTopology << 
00104     " and theWireTopology=" << theWireTopology;
00105   delete theStripTopology;
00106   delete theWireTopology;
00107 }
00108 
00109 
00110 LocalPoint 
00111 CSCLayerGeometry::stripWireIntersection( int strip, float wire ) const
00112 {
00113   // This allows _float_ wire no. so that we can calculate the
00114   // intersection of a strip with the mid point of a wire group 
00115   // containing an even no. of wires (which is not an actual wire),
00116   // as well as for a group containing an odd no. of wires.
00117 
00118   // Equation of wire and strip as straight lines in local xy
00119   // y = mx + c where m = tan(angle w.r.t. x axis)
00120   // At the intersection x = -(cs-cw)/(ms-mw)
00121   // At y=0, 0 = ms * xOfStrip(strip) + cs => cs = -ms*xOfStrip
00122   // At x=0, yOfWire(wire) = 0 + cw => cw = yOfWire
00123 
00124   float ms = tan( stripAngle(strip) );
00125   float mw = tan( wireAngle() );
00126   float xs = xOfStrip(strip);
00127   float xi = ( ms * xs + yOfWire(wire) ) / ( ms - mw );
00128   float yi = ms * (xi - xs );
00129 
00130   return LocalPoint(xi, yi);
00131 }
00132 
00133 LocalPoint CSCLayerGeometry::stripWireGroupIntersection( int strip, int wireGroup) const
00134 {
00135   // middleWire is only an actual wire for a group with an odd no. of wires
00136   float middleWire = middleWireOfGroup( wireGroup );
00137   return stripWireIntersection(strip, middleWire);
00138 }
00139 
00140 float CSCLayerGeometry::stripAngle(int strip) const 
00141 {
00142   // Cleverly subtly change meaning of stripAngle once more.
00143   // In TrapezoidalStripTopology it is angle measured
00144   // counter-clockwise from y axis. 
00145   // In APTST and RST it is angle measured 
00146   // clockwise from y axis.
00147   // Output of this function is measured counter-clockwise 
00148   // from x-axis, so it is a conventional 2-dim azimuthal angle
00149   // in the (x,y) local coordinates
00150 
00151   // We want angle at centre of strip (strip N covers
00152   // *float* range N-1 to N-epsilon)
00153 
00154   return M_PI_2 - theStripTopology->stripAngle(strip-0.5);
00155 }
00156 
00157 LocalPoint CSCLayerGeometry::localCenterOfWireGroup( int wireGroup ) const {
00158 
00159   // It can use CSCWireTopology::yOfWireGroup for y,
00160   // But x requires mixing with 'extent' of wire plane
00161 
00162   // If the wires are NOT tilted, default to simple calculation...
00163   if ( fabs(wireAngle() ) < 1.E-6 )  {
00164     float y = yOfWireGroup( wireGroup );
00165     return LocalPoint( 0., y );
00166   }
00167   else {
00168     // w is "wire" at the center of the wire group
00169     float w = middleWireOfGroup( wireGroup );
00170     std::vector<float> store = theWireTopology->wireValues( w );
00171     return LocalPoint( store[0], store[1] );
00172   }
00173 }
00174 
00175 float CSCLayerGeometry::lengthOfWireGroup( int wireGroup ) const {
00176   // Return length of 'wire' in the middle of the wire group
00177    float w = middleWireOfGroup( wireGroup );
00178    std::vector<float> store = theWireTopology->wireValues( w );
00179    return store[2];
00180 }
00181 
00182 std::pair<LocalPoint, float> CSCLayerGeometry::possibleRecHitPosition( float s, int w1, int w2 ) const {
00183         
00184   LocalPoint sw1 = intersectionOfStripAndWire( s, w1 );
00185   LocalPoint sw2 = intersectionOfStripAndWire( s, w2 );
00186                 
00187   // Average the two points
00188   LocalPoint midpt( (sw1.x()+sw2.x())/2., (sw1.y()+sw2.y())/2 );
00189         
00190   // Length of strip crossing this group of wires
00191   float length = sqrt( (sw1.x()-sw2.x())*(sw1.x()-sw2.x()) + 
00192                      (sw1.y()-sw2.y())*(sw1.y()-sw2.y()) );
00193         
00194   return std::pair<LocalPoint,float>( midpt, length );
00195 }
00196 
00197 LocalPoint CSCLayerGeometry::intersectionOfStripAndWire( float s, int w) const {
00198         
00199   std::pair<float, float> pw = theWireTopology->equationOfWire( static_cast<float>(w) );
00200   std::pair<float, float> ps = theStripTopology->equationOfStrip( s );
00201   LocalPoint sw = intersectionOfTwoLines( ps, pw );
00202         
00203   // If point falls outside wire plane, at extremes in local y, 
00204   // replace its y by that of appropriate edge of wire plane
00205   if ( !(theWireTopology->insideYOfWirePlane( sw.y() ) ) ) {
00206      float y  = theWireTopology->restrictToYOfWirePlane( sw.y() );
00207      // and adjust x to match new y
00208      float x = sw.x() + (y - sw.y())*tan(theStripTopology->stripAngle(s));
00209      sw = LocalPoint(x, y);
00210   }
00211         
00212   return sw;
00213 }
00214 
00215 LocalPoint CSCLayerGeometry::intersectionOfTwoLines( std::pair<float, float> p1, std::pair<float, float> p2 ) const {
00216 
00217   // Calculate the point of intersection of two straight lines (in 2-dim)
00218   // input arguments are pair(m1,c1) and pair(m2,c2) where m=slope, c=intercept (y=mx+c)
00219   // BEWARE! Do not call with m1 = m2 ! No trapping !
00220 
00221   float m1 = p1.first;
00222   float c1 = p1.second;
00223   float m2 = p2.first;
00224   float c2 = p2.second;
00225   float x = (c2-c1)/(m1-m2);
00226   float y = (m1*c2-m2*c1)/(m1-m2);
00227   return LocalPoint( x, y );
00228 }
00229 
00230 
00231 LocalError CSCLayerGeometry::localError( int strip, float sigmaStrip, float sigmaWire ) const {
00232   // Input sigmas are expected to be in _distance units_
00233   // - uncertainty in strip measurement (typically from Gatti fit, value is in local x units)
00234   // - uncertainty in wire measurement (along direction perpendicular to wires)
00235 
00236   float wangle   = this->wireAngle();
00237   float strangle = this->stripAngle( strip );
00238 
00239   float sinAngdif  = sin(strangle-wangle);
00240   float sinAngdif2 = sinAngdif * sinAngdif;
00241   
00242   float du = sigmaStrip/sin(strangle); // sigmaStrip is just x-component of strip error
00243   float dv = sigmaWire;
00244 
00245   // The notation is
00246   // wsins = wire resol  * sin(strip angle)
00247   // wcoss = wire resol  * cos(strip angle)
00248   // ssinw = strip resol * sin(wire angle)
00249   // scosw = strip resol * cos(wire angle)
00250 
00251   float wsins = dv * sin(strangle);
00252   float wcoss = dv * cos(strangle);
00253   float ssinw = du * sin(wangle);
00254   float scosw = du * cos(wangle);
00255 
00256   float dx2 = (scosw*scosw + wcoss*wcoss)/sinAngdif2;
00257   float dy2 = (ssinw*ssinw + wsins*wsins)/sinAngdif2;
00258   float dxy = (scosw*ssinw + wcoss*wsins)/sinAngdif2;
00259           
00260   return LocalError(dx2, dxy, dy2);
00261 }
00262 
00263 bool CSCLayerGeometry::inside( const Local3DPoint& lp ) const {
00264   bool result = false;
00265   const float epsilon = 1.e-06;
00266   if ( fabs( lp.z() ) < thickness()/2. ) { // thickness of TPB is that of gas layer
00267     std::pair<float, float> ylims = yLimitsOfStripPlane();
00268     if ( (lp.y() > ylims.first) && (lp.y() < ylims.second) ) {
00269       // 'strip' returns float value between 0. and float(Nstrips) and value outside
00270       // is set to 0. or float(Nstrips)... add a conservative precision of 'epsilon'
00271       if ( ( theStripTopology->strip(lp) > epsilon ) && 
00272            ( theStripTopology->strip(lp) < (numberOfStrips() - epsilon) ) ) result = true;
00273     }
00274   }
00275   return result;
00276 }
00277 
00278 bool CSCLayerGeometry::inside( const Local2DPoint& lp ) const {
00279   LocalPoint lp2( lp.x(), lp.y(), 0. );
00280   return inside( lp2 );
00281 }
00282 
00283 bool CSCLayerGeometry::inside( const Local3DPoint& lp, const LocalError& le, float scale ) const {
00284   // Effectively consider that the LocalError components extend the area which is acceptable.
00285   // Form a little box centered on the point, with x, y diameters defined by the errors
00286   // and require that ALL four corners of the box fall outside the strip region for failure
00287 
00288   // Note that LocalError is 2-dim x,y and doesn't supply a z error
00289   float deltaX = scale*sqrt(le.xx());
00290   float deltaY = scale*sqrt(le.yy());
00291 
00292   LocalPoint lp1( lp.x()-deltaX, lp.y()-deltaY, lp.z() );
00293   LocalPoint lp2( lp.x()-deltaX, lp.y()+deltaY, lp.z() );
00294   LocalPoint lp3( lp.x()+deltaX, lp.y()+deltaY, lp.z() );
00295   LocalPoint lp4( lp.x()+deltaX, lp.y()-deltaY, lp.z() );
00296 
00297   return ( inside(lp1) || inside(lp2) || inside(lp3) || inside(lp4) );
00298 }
00299 
00300 void CSCLayerGeometry::setTopology( CSCStripTopology * newTopology ) {
00301    delete theStripTopology;
00302    theStripTopology = newTopology;
00303 }
00304 
00305 std::ostream & operator<<(std::ostream & stream, const CSCLayerGeometry & lg) {
00306   stream << "LayerGeometry " << std::endl
00307          << "------------- " << std::endl
00308          << "numberOfStrips               " << lg.numberOfStrips() << std::endl
00309          << "numberOfWires                " << lg.numberOfWires() << std::endl
00310          << "numberOfWireGroups           " << lg.numberOfWireGroups() << std::endl
00311          << "wireAngle  (rad)             " << lg.wireAngle() << std::endl
00312     //         << "wireAngle  (deg)      " << lg.theWireAngle << std::endl
00313     //         << "sin(wireAngle)        " << lg.theWireSin << std::endl
00314     //         << "cos(wireAngle)        " << lg.theWireCos << std::endl
00315          << "wirePitch                    " << lg.wirePitch() << std::endl
00316          << "stripPitch                   " << lg.stripPitch() << std::endl
00317     //         << "numberOfWiresPerGroup " << lg.theNumberOfWiresPerGroup << std::endl
00318     //         << "numberOfWiresInLastGroup " << lg.theNumberOfWiresInLastGroup << std::endl
00319     //         << "wireOffset            " << lg.theWireOffset << std::endl
00320     //         << "whereStripsMeet       " << lg.whereStripsMeet << std::endl;
00321          << "hBottomEdge                  " << lg.hBottomEdge << std::endl
00322          << "hTopEdge                     " << lg.hTopEdge << std::endl
00323          << "apothem                      " << lg.apothem << std::endl
00324          << "length (should be 2xapothem) " << lg.length() << std::endl
00325          << "thickness                    " << lg.thickness() << std::endl;
00326     return stream;
00327 }
00328