CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/src/TrackingTools/TrackAssociator/plugins/CaloDetIdAssociator.cc

Go to the documentation of this file.
00001 #include "CaloDetIdAssociator.h"
00002 #include "DataFormats/GeometrySurface/interface/Plane.h"
00003 bool CaloDetIdAssociator::crossedElement(const GlobalPoint& point1,
00004                                          const GlobalPoint& point2,
00005                                          const DetId& id,
00006                                          const double toleranceInSigmas,
00007                                          const SteppingHelixStateInfo* initialState
00008                                          ) const
00009 {
00010    const std::pair<const_iterator,const_iterator>& points = getDetIdPoints(id);
00011    // fast check
00012    bool xLess(false), xIn(false), xMore(false);
00013    bool yLess(false), yIn(false), yMore(false);
00014    bool zLess(false), zIn(false), zMore(false);
00015    double xMin(point1.x()), xMax(point2.x());
00016    double yMin(point1.y()), yMax(point2.y());
00017    double zMin(point1.z()), zMax(point2.z());
00018    if ( xMin>xMax ) std::swap(xMin,xMax);
00019    if ( yMin>yMax ) std::swap(yMin,yMax);
00020    if ( zMin>zMax ) std::swap(zMin,zMax);
00021    for ( std::vector<GlobalPoint>::const_iterator it = points.first;
00022          it != points.second; ++it ){
00023      if ( it->x()<xMin ){
00024        xLess = true;
00025      } else {
00026        if ( it->x()>xMax )
00027          xMore = true;
00028        else
00029          xIn = true;
00030      }
00031      if ( it->y()<yMin ){
00032        yLess = true;
00033      } else {
00034        if ( it->y()>yMax )
00035          yMore = true;
00036        else
00037          yIn = true;
00038      }
00039      if ( it->z()<zMin ){
00040        zLess = true;
00041      } else {
00042        if ( it->z()>zMax )
00043          zMore = true;
00044        else
00045          zIn = true;
00046      }
00047    }
00048    if ( ( (xLess && !xIn && !xMore) || (!xLess && !xIn && xMore) ) ||
00049         ( (yLess && !yIn && !yMore) || (!yLess && !yIn && yMore) ) ||
00050         ( (zLess && !zIn && !zMore) || (!zLess && !zIn && zMore) ) ) return false;
00051 
00052    // Define plane normal to the trajectory direction at the first point
00053    GlobalVector vector = (point2-point1).unit();
00054    float r21 = 0;
00055    float r22 = vector.z()/sqrt(1-pow(vector.x(),2));
00056    float r23 = -vector.y()/sqrt(1-pow(vector.x(),2));
00057    float r31 = vector.x();
00058    float r32 = vector.y();
00059    float r33 = vector.z();
00060    float r11 = r22*r33-r23*r32;
00061    float r12 = r23*r31;
00062    float r13 = -r22*r31;
00063    
00064    Surface::RotationType rotation(r11, r12, r13,
00065                                   r21, r22, r23,
00066                                   r31, r32, r33);
00067    Plane::PlanePointer plane = Plane::build(point1, rotation);
00068    double absoluteTolerance = -1;
00069    if ( toleranceInSigmas>0 && initialState ){
00070       TrajectoryStateOnSurface tsos = initialState->getStateOnSurface(*plane);
00071       if ( tsos.isValid() and tsos.hasError()) {
00072          LocalError localErr = tsos.localError().positionError();
00073          localErr.scale(toleranceInSigmas); 
00074          float xx = localErr.xx();
00075          float xy = localErr.xy();
00076          float yy = localErr.yy();
00077 
00078          float denom = yy - xx;
00079          float phi = 0., phi_temp=0.;
00080          if(xy == 0 && denom==0) phi = M_PI_4;
00081          else phi = 0.5 * atan2(2.*xy,denom); // angle of MAJOR axis
00082          phi_temp = phi;
00083          // Unrotate the error ellipse to get the semimajor and minor axes. Then place points on
00084          // the endpoints of semiminor an seminajor axes on original(rotated) error ellipse.
00085          LocalError rotErr = localErr.rotate(-phi); // xy covariance of rotErr should be zero
00086          float semi1 = sqrt(rotErr.xx());
00087          float semi2 = sqrt(rotErr.yy());
00088          absoluteTolerance = std::max(semi1,semi2);
00089       }
00090    }
00091    
00092    // distance between the points.
00093    double trajectorySegmentLength = (point2-point1).mag();
00094 
00095    // we need to find the angle that covers all points. 
00096    // if it's bigger than 180 degree, we are inside
00097    // otherwise we are outside, i.e. the volume is not crossed
00098    bool allBehind = true;
00099    bool allTooFar = true;
00100    std::vector<GlobalPoint>::const_iterator p = points.first;
00101    if ( p == points.second ) {
00102       edm::LogWarning("TrackAssociator") << "calo geometry for element " << id.rawId() << "is empty. Ignored"; 
00103       return false; 
00104    }
00105    LocalPoint localPoint = plane->toLocal(*p);
00106    double minPhi = localPoint.phi();
00107    double maxPhi = localPoint.phi();
00108    if ( localPoint.z() < 0 ) 
00109      allTooFar = false;
00110    else {  
00111       allBehind = false;
00112       if ( localPoint.z() < trajectorySegmentLength )  allTooFar = false;
00113    }
00114    ++p;
00115    for (; p!=points.second; ++p){
00116       localPoint = plane->toLocal(*p);
00117       double localPhi = localPoint.phi();
00118       if ( localPoint.z() < 0 ) 
00119         allTooFar = false;
00120       else {  
00121          allBehind = false;
00122          if ( localPoint.z() < trajectorySegmentLength )  allTooFar = false;
00123       }
00124       if ( localPhi >= minPhi && localPhi <= maxPhi ) continue;
00125       if ( localPhi+2*M_PI >= minPhi && localPhi+2*M_PI <= maxPhi ) continue;
00126       if ( localPhi-2*M_PI >= minPhi && localPhi-2*M_PI <= maxPhi ) continue;
00127       // find the closest limit
00128       if ( localPhi > maxPhi ){
00129          double delta1 = fabs(localPhi-maxPhi);
00130          double delta2 = fabs(localPhi-2*M_PI-minPhi);
00131          if ( delta1 < delta2 )
00132            maxPhi = localPhi;
00133          else
00134            minPhi = localPhi-2*M_PI;
00135          continue;
00136       }
00137       if ( localPhi < minPhi ){
00138          double delta1 = fabs(localPhi-minPhi);
00139          double delta2 = fabs(localPhi+2*M_PI-maxPhi);
00140          if ( delta1 < delta2 )
00141            minPhi = localPhi;
00142          else
00143            maxPhi = localPhi+2*M_PI;
00144          continue;
00145       }
00146       cms::Exception("FatalError") << "Algorithm logic error - this should never happen. Problems with trajectory-volume matching.";
00147    }
00148    if ( allBehind ) return false;
00149    if ( allTooFar ) return false;
00150    if ( fabs(maxPhi-minPhi)>M_PI ) return true;
00151    
00152    // now if the tolerance is positive, check how far we are 
00153    // from the closest line segment
00154    if (absoluteTolerance < 0 ) return false;
00155    double distanceToClosestLineSegment = 1e9;
00156    std::vector<GlobalPoint>::const_iterator i,j;
00157    for ( i = points.first; i != points.second; ++i )
00158      for ( j = i+1; j != points.second; ++j )
00159        {
00160           LocalPoint p1(plane->toLocal(*i));
00161           LocalPoint p2(plane->toLocal(*j));
00162           // now we deal with high school level math to get
00163           // the triangle paramaters
00164           double side1squared = p1.perp2();
00165           double side2squared = p2.perp2();
00166           double side3squared = (p2.x()-p1.x())*(p2.x()-p1.x()) + (p2.y()-p1.y())*(p2.y()-p1.y());
00167           double area = fabs(p1.x()*p2.y()-p2.x()*p1.y())/2;
00168           // all triangle angles must be smaller than 90 degree
00169           // otherwise the projection is out of the line segment
00170           if ( side1squared + side2squared > side3squared &&
00171                side2squared + side3squared > side1squared &&
00172                side1squared + side3squared > side1squared )
00173             {
00174                double h(2*area/sqrt(side3squared));
00175                if ( h < distanceToClosestLineSegment ) distanceToClosestLineSegment = h;
00176             }
00177           else
00178             {
00179                if ( sqrt(side1squared) < distanceToClosestLineSegment ) distanceToClosestLineSegment = sqrt(side1squared);
00180                if ( sqrt(side2squared) < distanceToClosestLineSegment ) distanceToClosestLineSegment = sqrt(side2squared);
00181             }
00182        }
00183    if ( distanceToClosestLineSegment < absoluteTolerance ) return true;
00184    return false;
00185 }
00186 
00187 void CaloDetIdAssociator::setGeometry(const DetIdAssociatorRecord& iRecord)
00188 {
00189   edm::ESHandle<CaloGeometry> geometryH;
00190   iRecord.getRecord<CaloGeometryRecord>().get(geometryH);
00191   setGeometry(geometryH.product());
00192 }
00193 
00194 void CaloDetIdAssociator::check_setup() const
00195 {
00196   DetIdAssociator::check_setup();
00197   if (geometry_==0) throw cms::Exception("CaloGeometry is not set");
00198 }
00199    
00200 GlobalPoint CaloDetIdAssociator::getPosition(const DetId& id) const {
00201   return geometry_->getSubdetectorGeometry(id)->getGeometry(id)->getPosition();
00202 }
00203    
00204 const std::vector<DetId>& CaloDetIdAssociator::getValidDetIds(unsigned int subDectorIndex) const 
00205 {
00206   if ( subDectorIndex!=0 ) cms::Exception("FatalError") << "Calo sub-dectors are all handle as one sub-system, but subDetectorIndex is not zero.\n";
00207   return geometry_->getValidDetIds(DetId::Calo, 1);
00208 }
00209    
00210 std::pair<DetIdAssociator::const_iterator, DetIdAssociator::const_iterator> 
00211 CaloDetIdAssociator::getDetIdPoints(const DetId& id) const 
00212 {
00213   const CaloSubdetectorGeometry* subDetGeom = geometry_->getSubdetectorGeometry(id);
00214   if(! subDetGeom){
00215     LogDebug("TrackAssociator") << "Cannot find sub-detector geometry for " << id.rawId() <<"\n";
00216     return std::pair<const_iterator,const_iterator>(dummy_.end(),dummy_.end());
00217   }
00218   const CaloCellGeometry* cellGeom = subDetGeom->getGeometry(id);
00219   if(! cellGeom) {
00220     LogDebug("TrackAssociator") << "Cannot find CaloCell geometry for " << id.rawId() <<"\n";
00221     return std::pair<const_iterator,const_iterator>(dummy_.end(),dummy_.end());
00222   } 
00223   const CaloCellGeometry::CornersVec& cor (cellGeom->getCorners() ) ; 
00224   return std::pair<const_iterator,const_iterator>( cor.begin(), cor.end() ) ;
00225 }