CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_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.;
00080          if(xy == 0 && denom==0) phi = M_PI_4;
00081          else phi = 0.5 * atan2(2.*xy,denom); // angle of MAJOR axis
00082          // Unrotate the error ellipse to get the semimajor and minor axes. Then place points on
00083          // the endpoints of semiminor an seminajor axes on original(rotated) error ellipse.
00084          LocalError rotErr = localErr.rotate(-phi); // xy covariance of rotErr should be zero
00085          float semi1 = sqrt(rotErr.xx());
00086          float semi2 = sqrt(rotErr.yy());
00087          absoluteTolerance = std::max(semi1,semi2);
00088       }
00089    }
00090    
00091    // distance between the points.
00092    double trajectorySegmentLength = (point2-point1).mag();
00093 
00094    // we need to find the angle that covers all points. 
00095    // if it's bigger than 180 degree, we are inside
00096    // otherwise we are outside, i.e. the volume is not crossed
00097    bool allBehind = true;
00098    bool allTooFar = true;
00099    std::vector<GlobalPoint>::const_iterator p = points.first;
00100    if ( p == points.second ) {
00101       edm::LogWarning("TrackAssociator") << "calo geometry for element " << id.rawId() << "is empty. Ignored"; 
00102       return false; 
00103    }
00104    LocalPoint localPoint = plane->toLocal(*p);
00105    double minPhi = localPoint.phi();
00106    double maxPhi = localPoint.phi();
00107    if ( localPoint.z() < 0 ) 
00108      allTooFar = false;
00109    else {  
00110       allBehind = false;
00111       if ( localPoint.z() < trajectorySegmentLength )  allTooFar = false;
00112    }
00113    ++p;
00114    for (; p!=points.second; ++p){
00115       localPoint = plane->toLocal(*p);
00116       double localPhi = localPoint.phi();
00117       if ( localPoint.z() < 0 ) 
00118         allTooFar = false;
00119       else {  
00120          allBehind = false;
00121          if ( localPoint.z() < trajectorySegmentLength )  allTooFar = false;
00122       }
00123       if ( localPhi >= minPhi && localPhi <= maxPhi ) continue;
00124       if ( localPhi+2*M_PI >= minPhi && localPhi+2*M_PI <= maxPhi ) continue;
00125       if ( localPhi-2*M_PI >= minPhi && localPhi-2*M_PI <= maxPhi ) continue;
00126       // find the closest limit
00127       if ( localPhi > maxPhi ){
00128          double delta1 = fabs(localPhi-maxPhi);
00129          double delta2 = fabs(localPhi-2*M_PI-minPhi);
00130          if ( delta1 < delta2 )
00131            maxPhi = localPhi;
00132          else
00133            minPhi = localPhi-2*M_PI;
00134          continue;
00135       }
00136       if ( localPhi < minPhi ){
00137          double delta1 = fabs(localPhi-minPhi);
00138          double delta2 = fabs(localPhi+2*M_PI-maxPhi);
00139          if ( delta1 < delta2 )
00140            minPhi = localPhi;
00141          else
00142            maxPhi = localPhi+2*M_PI;
00143          continue;
00144       }
00145       cms::Exception("FatalError") << "Algorithm logic error - this should never happen. Problems with trajectory-volume matching.";
00146    }
00147    if ( allBehind ) return false;
00148    if ( allTooFar ) return false;
00149    if ( fabs(maxPhi-minPhi)>M_PI ) return true;
00150    
00151    // now if the tolerance is positive, check how far we are 
00152    // from the closest line segment
00153    if (absoluteTolerance < 0 ) return false;
00154    double distanceToClosestLineSegment = 1e9;
00155    std::vector<GlobalPoint>::const_iterator i,j;
00156    for ( i = points.first; i != points.second; ++i )
00157      for ( j = i+1; j != points.second; ++j )
00158        {
00159           LocalPoint p1(plane->toLocal(*i));
00160           LocalPoint p2(plane->toLocal(*j));
00161           // now we deal with high school level math to get
00162           // the triangle paramaters
00163           double side1squared = p1.perp2();
00164           double side2squared = p2.perp2();
00165           double side3squared = (p2.x()-p1.x())*(p2.x()-p1.x()) + (p2.y()-p1.y())*(p2.y()-p1.y());
00166           double area = fabs(p1.x()*p2.y()-p2.x()*p1.y())/2;
00167           // all triangle angles must be smaller than 90 degree
00168           // otherwise the projection is out of the line segment
00169           if ( side1squared + side2squared > side3squared &&
00170                side2squared + side3squared > side1squared &&
00171                side1squared + side3squared > side1squared )
00172             {
00173                double h(2*area/sqrt(side3squared));
00174                if ( h < distanceToClosestLineSegment ) distanceToClosestLineSegment = h;
00175             }
00176           else
00177             {
00178                if ( sqrt(side1squared) < distanceToClosestLineSegment ) distanceToClosestLineSegment = sqrt(side1squared);
00179                if ( sqrt(side2squared) < distanceToClosestLineSegment ) distanceToClosestLineSegment = sqrt(side2squared);
00180             }
00181        }
00182    if ( distanceToClosestLineSegment < absoluteTolerance ) return true;
00183    return false;
00184 }
00185 
00186 void CaloDetIdAssociator::setGeometry(const DetIdAssociatorRecord& iRecord)
00187 {
00188   edm::ESHandle<CaloGeometry> geometryH;
00189   iRecord.getRecord<CaloGeometryRecord>().get(geometryH);
00190   setGeometry(geometryH.product());
00191 }
00192 
00193 void CaloDetIdAssociator::check_setup() const
00194 {
00195   DetIdAssociator::check_setup();
00196   if (geometry_==0) throw cms::Exception("CaloGeometry is not set");
00197 }
00198    
00199 GlobalPoint CaloDetIdAssociator::getPosition(const DetId& id) const {
00200   return geometry_->getSubdetectorGeometry(id)->getGeometry(id)->getPosition();
00201 }
00202    
00203 const std::vector<DetId>& CaloDetIdAssociator::getValidDetIds(unsigned int subDectorIndex) const 
00204 {
00205   if ( subDectorIndex!=0 ) cms::Exception("FatalError") << "Calo sub-dectors are all handle as one sub-system, but subDetectorIndex is not zero.\n";
00206   return geometry_->getValidDetIds(DetId::Calo, 1);
00207 }
00208    
00209 std::pair<DetIdAssociator::const_iterator, DetIdAssociator::const_iterator> 
00210 CaloDetIdAssociator::getDetIdPoints(const DetId& id) const 
00211 {
00212   const CaloSubdetectorGeometry* subDetGeom = geometry_->getSubdetectorGeometry(id);
00213   if(! subDetGeom){
00214     LogDebug("TrackAssociator") << "Cannot find sub-detector geometry for " << id.rawId() <<"\n";
00215     return std::pair<const_iterator,const_iterator>(dummy_.end(),dummy_.end());
00216   }
00217   const CaloCellGeometry* cellGeom = subDetGeom->getGeometry(id);
00218   if(! cellGeom) {
00219     LogDebug("TrackAssociator") << "Cannot find CaloCell geometry for " << id.rawId() <<"\n";
00220     return std::pair<const_iterator,const_iterator>(dummy_.end(),dummy_.end());
00221   } 
00222   const CaloCellGeometry::CornersVec& cor (cellGeom->getCorners() ) ; 
00223   return std::pair<const_iterator,const_iterator>( cor.begin(), cor.end() ) ;
00224 }