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
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
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);
00082 phi_temp = phi;
00083
00084
00085 LocalError rotErr = localErr.rotate(-phi);
00086 float semi1 = sqrt(rotErr.xx());
00087 float semi2 = sqrt(rotErr.yy());
00088 absoluteTolerance = std::max(semi1,semi2);
00089 }
00090 }
00091
00092
00093 double trajectorySegmentLength = (point2-point1).mag();
00094
00095
00096
00097
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
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
00153
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
00163
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
00169
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 }