diff --git a/Trigger/TrigTools/TrigInDetTrackFitter/CMakeLists.txt b/Trigger/TrigTools/TrigInDetTrackFitter/CMakeLists.txt index 15628d4f29ba6199818c3e3d8b468ce900cf0462..f8b430ae84ccf36f7434176a4ed0052575489f64 100644 --- a/Trigger/TrigTools/TrigInDetTrackFitter/CMakeLists.txt +++ b/Trigger/TrigTools/TrigInDetTrackFitter/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration # Declare the package name: atlas_subdir( TrigInDetTrackFitter ) @@ -7,4 +7,4 @@ atlas_subdir( TrigInDetTrackFitter ) atlas_add_component( TrigInDetTrackFitter src/*.cxx src/components/*.cxx - LINK_LIBRARIES AthenaBaseComps AtlasDetDescr GaudiKernel InDetIdentifier InDetPrepRawData InDetRIO_OnTrack MagFieldConditions MagFieldElements StoreGateLib TrigInDetEvent TrigInDetToolInterfacesLib TrkDistributedKalmanFilterLib TrkEventPrimitives TrkParameters TrkPrepRawData TrkRIO_OnTrack TrkSurfaces TrkToolInterfaces TrkTrack ) + LINK_LIBRARIES AthenaBaseComps AtlasDetDescr GaudiKernel InDetIdentifier InDetPrepRawData InDetRIO_OnTrack MagFieldConditions MagFieldElements StoreGateLib InDetReadoutGeometry PixelReadoutGeometryLib SCT_ReadoutGeometry TrigInDetEvent TrigInDetToolInterfacesLib TrkDistributedKalmanFilterLib TrkEventPrimitives TrkParameters TrkPrepRawData TrkRIO_OnTrack TrkSurfaces TrkToolInterfaces TrkTrack ) diff --git a/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetRoadPredictorTool.cxx b/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetRoadPredictorTool.cxx index cd98a01cd074f714e21a9d6764fe79b6d537675b..bf826083b75aa81cac929eef28c42e7812c4b452 100644 --- a/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetRoadPredictorTool.cxx +++ b/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetRoadPredictorTool.cxx @@ -10,6 +10,10 @@ #include "TrkParameters/TrackParameters.h" #include "TrkPrepRawData/PrepRawData.h" #include "TrkSpacePoint/SpacePoint.h" +#include "PixelReadoutGeometry/PixelDetectorManager.h" +#include "SCT_ReadoutGeometry/SCT_DetectorManager.h" +#include "InDetIdentifier/PixelID.h" + #include "TrigInDetRoadPredictorTool.h" @@ -19,6 +23,8 @@ #include "TrkSurfaces/Surface.h" #include "InDetPrepRawData/PixelCluster.h" + + TrigInDetRoadPredictorTool::TrigInDetRoadPredictorTool(const std::string& t, const std::string& n, const IInterface* p ): AthAlgTool(t,n,p) @@ -28,15 +34,412 @@ TrigInDetRoadPredictorTool::TrigInDetRoadPredictorTool(const std::string& t, StatusCode TrigInDetRoadPredictorTool::initialize() { + StatusCode sc = m_layerNumberTool.retrieve(); + if(sc.isFailure()) { + ATH_MSG_ERROR("Could not retrieve "<<m_layerNumberTool); + return sc; + } else { + ATH_MSG_INFO("Detector layer structure has "<<m_layerNumberTool->maxNumberOfUniqueLayers()<<" unique layers"); + } + + ATH_CHECK( m_fieldCondObjInputKey.initialize()); + ATH_CHECK( detStore()->retrieve(m_pixelManager, "ITkPixel") ); + ATH_CHECK( detStore()->retrieve(m_stripManager, "ITkStrip") ); + ATH_CHECK( detStore()->retrieve(m_pixelId, "PixelID") ); + ATH_CHECK( detStore()->retrieve(m_stripId, "SCT_ID") ); + buildDetectorDescription(); + + return StatusCode::SUCCESS; } +void TrigInDetRoadPredictorTool::addNewElement(unsigned int layerID, short phi_idx, short eta_idx, const InDetDD::SiDetectorElement* p) { + + unsigned int hash = p->identifyHash(); + + DetectorElementDescription ded(hash); + + //find corners in the global c.s. + + float de_len = 0.5*p->design().length(); + float de_wmax = 0.5*p->design().maxWidth(); + float de_wmin = 0.5*p->design().minWidth(); + + float dPhi[4] = {de_wmax, de_wmin, -de_wmin, -de_wmax};//locX + float dEta[4] = {de_len, -de_len, -de_len, de_len}; //locY + + const Amg::Vector3D& C = p->center(); + const Amg::Vector3D& PhiAx = p->phiAxis(); + const Amg::Vector3D& EtaAx = p->etaAxis(); + + for(int ic=0; ic<4; ic++) { + float x = C.x() + PhiAx.x()*dPhi[ic] + EtaAx.x()*dEta[ic]; + float y = C.y() + PhiAx.y()*dPhi[ic] + EtaAx.y()*dEta[ic]; + float z = C.z() + PhiAx.z()*dPhi[ic] + EtaAx.z()*dEta[ic]; + ded.m_c[ic][0] = std::sqrt(x*x+y*y);//r + ded.m_c[ic][1] = z; + ded.m_c[ic][2] = std::atan2(y,x);//phi + } + + auto& L = (*m_layerMap.find(layerID)).second; + + short prim_idx = L.m_mappingType != 2 ? phi_idx : eta_idx; + short sec_idx = L.m_mappingType != 2 ? eta_idx : phi_idx; + + if(L.m_mappingType == 0) {//barrel: primary index is phi, eta/z is secondary + ded.m_ref = C.z(); + ded.m_index = sec_idx; + ded.m_minBound = ded.m_c[0][1]; + ded.m_maxBound = ded.m_c[0][1]; + for(int ic=1;ic<4;ic++) { + if(ded.m_minBound > ded.m_c[ic][1]) ded.m_minBound = ded.m_c[ic][1]; + if(ded.m_maxBound < ded.m_c[ic][1]) ded.m_maxBound = ded.m_c[ic][1]; + } + } + + if(L.m_mappingType == 1) {//pixel endcap layers : primary index is phi, eta/R is secondary + ded.m_ref = C.perp(); + ded.m_index = sec_idx; + ded.m_minBound = ded.m_c[0][0]; + ded.m_maxBound = ded.m_c[0][0]; + for(int ic=1;ic<4;ic++) { + if(ded.m_minBound > ded.m_c[ic][0]) ded.m_minBound = ded.m_c[ic][0]; + if(ded.m_maxBound < ded.m_c[ic][0]) ded.m_maxBound = ded.m_c[ic][0]; + } + } + + if(L.m_mappingType == 2) {//strip endcaps: primary index is R, phi is secondary, layers are double + ded.m_ref = std::atan2(C.y(),C.x()); + ded.m_index = sec_idx; + ded.m_minBound = ded.m_c[0][2]; + ded.m_maxBound = ded.m_c[0][2]; + for(int ic=1;ic<4;ic++) { + if(ded.m_minBound > ded.m_c[ic][2]) ded.m_minBound = ded.m_c[ic][2]; + if(ded.m_maxBound < ded.m_c[ic][2]) ded.m_maxBound = ded.m_c[ic][2]; + } + } + + //put DetEl description into the corresponding collection + + int detColIdx = 0; + + if(L.m_nSubLayers == 2 && (hash % 2) != 0) {//double layer, odd detector elements + detColIdx = 1; + } + + if(L.m_colls[ detColIdx].find(prim_idx) == L.m_colls[ detColIdx].end()) { + + float primBounds[2] = {0,0}; + if(L.m_mappingType == 2) { + primBounds[0] = p->rMin(); + primBounds[1] = p->rMax(); + } + else { + primBounds[0] = p->phiMin(); + primBounds[1] = p->phiMax(); + } + + DetectorElementsCollection dc(prim_idx, primBounds[0], primBounds[1]); + L.m_colls[ detColIdx].insert(std::make_pair(prim_idx, dc)); + } + + (*L.m_colls[detColIdx].find(prim_idx)).second.m_vDE.push_back(ded); + +} + + +void TrigInDetRoadPredictorTool::buildDetectorDescription() { + + const std::vector<short>& vPixelL = *(m_layerNumberTool->pixelLayers()); + const std::vector<TrigInDetSiLayer>& SiL = *(m_layerNumberTool->layerGeometry()); + + for(int hash = 0; hash<static_cast<int>(m_pixelId->wafer_hash_max()); hash++) { + + Identifier offlineId = m_pixelId->wafer_id(hash); + short barrel_ec = m_pixelId->barrel_ec(offlineId); + if(std::abs(barrel_ec)>2) continue;//no DBM needed + + unsigned int layerID = SiL.at(vPixelL.at(hash)).m_subdet; + unsigned int volumeID = layerID / 1000; + + if(m_layerMap.find(layerID) == m_layerMap.end()) { + + int nSubLayers = 1; + unsigned int mappingType = 1; + + if(barrel_ec == 0) mappingType = 0; + else { + if(volumeID == 12 || volumeID == 14) mappingType = 2; + } + m_layerMap.try_emplace(layerID, layerID, nSubLayers, mappingType); + } + + short phi_index = m_pixelId->phi_module(offlineId); + short eta_index = m_pixelId->eta_module(offlineId); + + addNewElement(layerID, phi_index, eta_index, m_pixelManager->getDetectorElement(hash)); + } + + const std::vector<short>& vStripL = *(m_layerNumberTool->sctLayers()); + + for(int hash = 0; hash<static_cast<int>(m_stripId->wafer_hash_max()); hash++) { + + Identifier offlineId = m_stripId->wafer_id(hash); + short barrel_ec = m_stripId->barrel_ec(offlineId); + if(std::abs(barrel_ec)>2) continue; + + unsigned int layerID = SiL.at(vStripL.at(hash)).m_subdet; + unsigned int volumeID = layerID / 1000; + + if(m_layerMap.find(layerID) == m_layerMap.end()) { + int nSubLayers = 2;//strip layers are double + unsigned int mappingType = 1; + + if(barrel_ec == 0) mappingType = 0; + else { + if(volumeID == 12 || volumeID == 14) mappingType = 2; + } + m_layerMap.try_emplace(layerID, layerID, nSubLayers, mappingType); + } + + short phi_index = m_stripId->phi_module(offlineId); + short eta_index = m_stripId->eta_module(offlineId); + + addNewElement(layerID, phi_index, eta_index, m_stripManager->getDetectorElement(hash)); + } + + //building hit boxes + + createHitBoxes(); + +} + +void TrigInDetRoadPredictorTool::createHitBoxes() { + + const float margin_r = 3.0; + const float margin_z = 3.0; + + for(const auto& l : m_layerMap) { + + unsigned int layerID = l.first; + unsigned int volumeID = layerID / 1000; + + const auto& L = l.second; + + float minR = 1e8;// vert0 + float minZ = 1e8;// vert1 + float maxR = -1e8;// vert2 + float maxZ = -1e8;// vert3 + + float vert[4][2]; //z,r + + memset(&vert[0][0],0,sizeof(vert)); + + for(int iSL = 0; iSL < L.m_nSubLayers;iSL++) { + for(const auto& deColl : L.m_colls[iSL]) { + for(const auto& de : deColl.second.m_vDE) { + for(int ic=0;ic<4;ic++) { + float r = de.m_c[ic][0]; + float z = de.m_c[ic][1]; + if(r < minR) { + minR = r; + vert[0][0] = z; + vert[0][1] = r; + } + if(z < minZ) { + minZ = z; + vert[1][0] = z; + vert[1][1] = r; + } + if(r > maxR) { + maxR = r; + vert[2][0] = z; + vert[2][1] = r; + } + if(z > maxZ) { + maxZ = z; + vert[3][0] = z; + vert[3][1] = r; + } + } + } + } + } + minR -= margin_r; + vert[0][1] -= margin_r; + minZ -= margin_z; + vert[1][0] -= margin_z; + maxR += margin_r; + vert[2][1] += margin_r; + maxZ += margin_z; + vert[3][0] += margin_z; + + int new_layer_index = -1; + LayerBoundary lb; + new_layer_index = m_lBoundaries.size(); + lb.m_index = new_layer_index; + lb.m_lay_id = layerID; + lb.m_nVertices = 5; + + if(volumeID == 73 || volumeID == 75 || volumeID == 77) {//negative inclined + lb.m_z = {vert[3][0], vert[2][0], vert[1][0], vert[0][0], vert[3][0]}; + lb.m_r = {vert[3][1], vert[2][1], vert[1][1], vert[0][1], vert[3][1]}; + } + else if(volumeID == 93 || volumeID == 95 || volumeID == 97) {//positive inclined + lb.m_z = {vert[2][0], vert[1][0], vert[0][0], vert[3][0], vert[2][0]}; + lb.m_r = {vert[2][1], vert[1][1], vert[0][1], vert[3][1], vert[2][1]}; + } + else {//all other layers + lb.m_z = {maxZ, minZ, minZ, maxZ, maxZ}; + lb.m_r = {maxR, maxR, minR, minR, maxR}; + } + + m_lBoundaries.push_back(lb); + + bool volExists = false; + + for(auto& v : m_vBoundaries) { + if(v.m_vol_id == (int)volumeID) { + volExists = true;//update corners + if(v.m_zr[0] > minZ) v.m_zr[0] = minZ; + if(v.m_zr[1] < maxZ) v.m_zr[1] = maxZ; + if(v.m_zr[2] > minR) v.m_zr[2] = minR; + if(v.m_zr[3] < maxR) v.m_zr[3] = maxR; + v.m_layers.push_back(new_layer_index); + break; + } + } + if(!volExists) {//add a new volume with 4 corners + VolumeBoundary vb; + vb.m_layers.push_back(new_layer_index); + vb.m_index = m_vBoundaries.size(); + vb.m_vol_id = volumeID; + vb.m_zr[0] = minZ; + vb.m_zr[1] = maxZ; + vb.m_zr[2] = minR; + vb.m_zr[3] = maxR; + m_vBoundaries.push_back(vb); + } + } +} + +void TrigInDetRoadPredictorTool::findDetectorElements(unsigned int layerID, const SearchInterval& searchArea, + std::vector<unsigned int>& vIDs, bool hasHit) const { + + const float road_width_rz = hasHit ? m_min_rz_rw : m_max_rz_rw; + const float road_width_rphi = hasHit ? m_min_rphi_rw : m_max_rphi_rw; + + float phi_test = searchArea.m_phi; + float phi_res = road_width_rphi/searchArea.m_r; + + if(phi_res > m_max_phi_rw) phi_res = m_max_phi_rw; + if(phi_res < m_min_phi_rw) phi_res = m_min_phi_rw; + + float phi_min = phi_test - phi_res; + float phi_max = phi_test + phi_res; + + const auto& L = (*m_layerMap.find(layerID)).second; + + if(L.m_mappingType != 2) { // primary index is Phi, secondary is Z or R + + float rz_test_m = searchArea.getMinR(); + float rz_test_p = searchArea.getMaxR(); + + if(L.m_mappingType == 0) { + rz_test_m = searchArea.getMinZ(); + rz_test_p = searchArea.getMaxZ(); + } + + rz_test_m -= road_width_rz; + rz_test_p += road_width_rz; + + for(int iSubL = 0; iSubL < L.m_nSubLayers;iSubL++) { + + for(const auto& prim : L.m_colls[iSubL]) { + + const auto& slice = prim.second; + + float f1 = slice.m_minCoord; + float f2 = slice.m_maxCoord; + + if(std::abs(f2 - f1) < M_PI) { + if(phi_max < f1) continue; + if(phi_min > f2) continue; + } + else {// +/- pi boundary + std::swap(f2, f1); + if(phi_test < 0 && phi_min > f1) continue; + if(phi_test > 0 && phi_max < f2) continue; + } + + for(const auto& de : slice.m_vDE) { + + float p1 = de.m_minBound; + float p2 = de.m_maxBound; + + if(rz_test_p < p1) break; + if(rz_test_m > p2) continue; + + if (! (rz_test_p < p1 || rz_test_m > p2)) vIDs.push_back(de.m_hash); + } + } + } + } + else { //Strip endcaps: primary R, secondary Phi + + float r_test_m = searchArea.getMinR() - road_width_rz; + float r_test_p = searchArea.getMaxR() + road_width_rz; + + for(int iSubL = 0; iSubL < L.m_nSubLayers;iSubL++) { + + for(const auto& prim : L.m_colls[iSubL]) { + + const auto& slice = prim.second; + + float r1 = slice.m_minCoord; + float r2 = slice.m_maxCoord; + + if(r_test_p < r1) break; + if(r_test_m > r2) continue; + + if (! (r_test_p < r1 || r_test_m > r2)) { + + for(const auto& de : slice.m_vDE) { + + float f1 = de.m_minBound; + float f2 = de.m_maxBound; + + if(f2 - f1 < M_PI) { + if(phi_max < f1) continue; + if(phi_min > f2) continue; + } + else {// +/- pi boundary + if(phi_test < 0 && phi_min > f1) continue; + if(phi_test > 0 && phi_max < f2) continue; + } + vIDs.push_back(de.m_hash); + } + } + } + } + } + +} + -int TrigInDetRoadPredictorTool::getRoad(const std::vector<const Trk::SpacePoint*>& seed, std::vector<const InDetDD::SiDetectorElement*>& road, const EventContext& ctx) const { + +int TrigInDetRoadPredictorTool::getRoad(const std::vector<const Trk::SpacePoint*>& seed, + std::vector<const InDetDD::SiDetectorElement*>& road, + const EventContext& ctx) const { + + const float MAX_R = 1030.0;//detector envelope + const float MAX_Z = 3000.0;//detector envelope + const float maxCornerDist = 15.0; + //1. get magnetic field MagField::AtlasFieldCache fieldCache; @@ -51,17 +454,271 @@ int TrigInDetRoadPredictorTool::getRoad(const std::vector<const Trk::SpacePoint* road.clear(); - unsigned int seedSize = seed.size(); + unsigned int nSP = seed.size(); - if(seedSize < 3) return -2; + if(nSP < 3) return -2; - //2. adding spacepoints' DEs - - for(unsigned int spIdx=0;spIdx<seedSize;spIdx++) { - const Trk::PrepRawData* prd = seed.at(spIdx)->clusterList().first; + std::vector<unsigned int> seedHashes; + + for(unsigned int spIdx=0;spIdx<nSP;spIdx++) { + const auto& sp = seed.at(spIdx); + const Trk::PrepRawData* prd = sp->clusterList().first; const InDet::PixelCluster* pPixelHit = dynamic_cast<const InDet::PixelCluster*>(prd); - road.push_back(pPixelHit->detectorElement()); + unsigned int hash = pPixelHit->detectorElement()->identifyHash(); + seedHashes.push_back(hash); + } + + std::vector<std::array<float,2> > zr; + zr.resize(nSP+2); + + for(unsigned int spIdx=0;spIdx<nSP;spIdx++) { + const auto& sp = seed.at(spIdx); + zr[spIdx+1][0] = sp->globalPosition().z(); + zr[spIdx+1][1] = sp->globalPosition().perp(); + } + + //adding the first point at beamline + + zr[0][0] = zr[1][0] - zr[1][1]*(zr[2][0]-zr[1][0])/(zr[2][1]-zr[1][1]); + zr[0][1] = 0; + + //adding the last point at detector exit + float zlast = zr[nSP-1][0] + (MAX_R - zr[nSP-1][1])*(zr[nSP][0]-zr[nSP-1][0])/(zr[nSP][1]-zr[nSP-1][1]); + float rlast = MAX_R; + + if (std::fabs(zlast) > MAX_Z) { + if(zlast > 0) zlast = MAX_Z; + else zlast = -MAX_Z; + rlast = zr[nSP-1][1] + (zlast - zr[nSP-1][0])*(zr[nSP][1]-zr[nSP-1][1])/(zr[nSP][0]-zr[nSP-1][0]); + } + zr[nSP+1][0] = zlast; + zr[nSP+1][1] = rlast; + + std::map<unsigned int, SearchInterval> rzIntervals; + + for(unsigned int k1 = 0;k1<zr.size()-1;k1++) {//loop over trajectory segments + + unsigned int k2 = k1+1; + + float z1 = zr[k1][0]; + float r1 = zr[k1][1]; + float z2 = zr[k2][0]; + float r2 = zr[k2][1]; + float dz21 = z2-z1; + float dr21 = r2-r1; + float L = std::sqrt(dz21*dz21 + dr21*dr21); + float invL = 1.0/L; + float sinF = dr21*invL; + float cosF = dz21*invL; + + for(const auto& vb : m_vBoundaries) { + + if (z1 < vb.m_zr[0] && z2 < vb.m_zr[0]) continue; + if (z1 > vb.m_zr[1] && z2 > vb.m_zr[1]) continue; + if (r1 < vb.m_zr[2] && r2 < vb.m_zr[2]) continue; + if (r1 > vb.m_zr[3] && r2 > vb.m_zr[3]) continue; + + //corners: + + float zc[4] = {vb.m_zr[0], vb.m_zr[1], vb.m_zr[1], vb.m_zr[0]}; + float rc[4] = {vb.m_zr[2], vb.m_zr[2], vb.m_zr[3], vb.m_zr[3]}; + + int nUp(0), nDn(0); + + float minDistances[4]; + + for (int ic=0;ic<4;ic++) { + minDistances[ic] = (rc[ic] - r1)*cosF - (zc[ic] - z1)*sinF; + } + + float minH = std::abs(minDistances[0]); + + for (int ic=0;ic<4;ic++) { + float h = minDistances[ic]; + if (h <=0) nDn += 1; + else nUp += 1; + if(std::abs(h) < minH) minH = std::abs(h); + } + + if (nUp == 4 || nDn == 4) { + if(minH > maxCornerDist) {//the closest corner is still too far + continue; + } + } + + //search through layers inside the volume + + for(auto lIdx : vb.m_layers) { + const auto& lb = m_lBoundaries.at(lIdx); + for(int s1=0;s1<lb.m_nVertices-1;s1++) { + int s2 = s1 + 1; + + float h1 = (lb.m_r[s1] - r1)*cosF - (lb.m_z[s1] - z1)*sinF; + float h2 = (lb.m_r[s2] - r1)*cosF - (lb.m_z[s2] - z1)*sinF; + if (h1*h2 > 0) continue; + float l1 = (lb.m_z[s1] - z1)*cosF + (lb.m_r[s1] - r1)*sinF; + float l2 = (lb.m_z[s2] - z1)*cosF + (lb.m_r[s2] - r1)*sinF; + if (l1 < 0 && l2 < 0) continue; + if (l1 > L && l2 > L) continue; + float lx = (l1 + (l2-l1)*h1/(h1-h2))*invL; + + if (lx < 0 || lx > 1) continue; + float zx = z2*lx + (1-lx)*z1; + float rx = r2*lx + (1-lx)*r1; + + auto radItr = rzIntervals.find(lb.m_lay_id); + + if(radItr == rzIntervals.end()) { + rzIntervals.insert(std::make_pair(lb.m_lay_id, SearchInterval(zx, rx))); + } + else { + (*radItr).second.addPoint(zx, rx); + } + } + } + } } - return 0; + //3. parabolic extrapolation in r-phi + + unsigned int sp1Idx = 0; + unsigned int sp3Idx = nSP-1; + unsigned int sp2Idx = (sp3Idx+sp1Idx)/2; + + //3a. Converting XY coords to UV coords + + float uv_coords[2][2]; + + float dx = seed.at(sp3Idx)->globalPosition().x() - seed.at(sp2Idx)->globalPosition().x(); + float dy = seed.at(sp3Idx)->globalPosition().y() - seed.at(sp2Idx)->globalPosition().y(); + + uv_coords[1][0] = -std::sqrt(dx*dx + dy*dy); + uv_coords[1][1] = 0.0; + + float cos_theta = dx/(-uv_coords[1][0]); + float sin_theta = dy/(-uv_coords[1][0]); + + float rot_matrix[2][2]; + float inv_rot_matrix[2][2]; + + rot_matrix[0][0] = cos_theta; + rot_matrix[0][1] = sin_theta; + rot_matrix[1][0] = -sin_theta; + rot_matrix[1][1] = cos_theta; + + inv_rot_matrix[0][0] = cos_theta; + inv_rot_matrix[0][1] = -sin_theta; + inv_rot_matrix[1][0] = sin_theta; + inv_rot_matrix[1][1] = cos_theta; + + float sp3_coords[3]; + sp3_coords[0] = seed.at(sp3Idx)->globalPosition().x(); + sp3_coords[1] = seed.at(sp3Idx)->globalPosition().y(); + sp3_coords[2] = seed.at(sp3Idx)->globalPosition().z(); + + //UV-coordinates of the XY origin (0,0) + + float u_c = rot_matrix[0][0]*(0-sp3_coords[0]) + rot_matrix[0][1]*(0-sp3_coords[1]); + float v_c = rot_matrix[1][0]*(0-sp3_coords[0]) + rot_matrix[1][1]*(0-sp3_coords[1]); + + int sign_up = u_c < 0 ? 1 : -1; + + //transforming SP1 + + float dR1[2]; + + dR1[0] = seed.at(sp1Idx)->globalPosition().x() - sp3_coords[0]; + dR1[1] = seed.at(sp1Idx)->globalPosition().y() - sp3_coords[1]; + + uv_coords[0][0] = rot_matrix[0][0]*dR1[0] + rot_matrix[0][1]*dR1[1]; + uv_coords[0][1] = rot_matrix[1][0]*dR1[0] + rot_matrix[1][1]*dR1[1]; + + //3b. parameters of the parabola in the u-v c.s. + + float a = uv_coords[0][1]/(uv_coords[0][0]*(uv_coords[0][0]-uv_coords[1][0])); + float b = -a*uv_coords[1][0]; // b = -a*x2 + + //3c. calculate impact point radii + + std::vector<unsigned int> pixelHashIds; + std::vector<unsigned int> stripHashIds; + + for(auto& ip : rzIntervals) { + + float R = ip.second.getAverageRadius(); + + float R2 = R*R; + + float dRv = R2-v_c*v_c; + + if(dRv < 0) continue;//no intersection with the circle + + float u_p = u_c + sign_up*std::sqrt(dRv); + + float v_p = b*u_p + a*u_p*u_p; + float dv2 = (v_p-v_c)*(v_p-v_c); + + if (R2-dv2<0) continue; // check for intersection between v=v_p and the circle + + float u_star = u_c + sign_up*std::sqrt(R2-dv2); + float v_star = b*u_star + a*u_star*u_star; + + float x_star = inv_rot_matrix[0][0]*u_star + inv_rot_matrix[0][1]*v_star + sp3_coords[0]; + float y_star = inv_rot_matrix[1][0]*u_star + inv_rot_matrix[1][1]*v_star + sp3_coords[1]; + + ip.second.m_r = std::sqrt(x_star*x_star + y_star*y_star); + ip.second.m_phi = std::atan2(y_star, x_star); + + if(ip.first > 15000) {//assuming Pixel-only seeds + + bool hasHit = false; + + for(unsigned int i=1;i<nSP-1;i++) { + + float dpr = ip.second.m_r - zr[i][1]; + float dpz = ip.second.m_z - zr[i][0]; + float dist = std::sqrt(dpr*dpr + dpz*dpz); + if(dist < maxCornerDist) { + hasHit = true; + break; + } + } + findDetectorElements(ip.first, ip.second, pixelHashIds, hasHit); + } + else { + findDetectorElements(ip.first, ip.second, stripHashIds, false); + } + } + + std::set<unsigned int> pixelHashSet(pixelHashIds.begin(), pixelHashIds.end()); + + for(auto id : seedHashes) { + if(pixelHashSet.find(id) == pixelHashSet.end()) pixelHashIds.push_back(id); + } + + std::vector<std::pair<float, const InDetDD::SiDetectorElement*> > theRoad; + + for(auto hash_id : pixelHashIds) { + const InDetDD::SiDetectorElement *p = m_pixelManager->getDetectorElement(hash_id); + if(p == nullptr) continue; + const Amg::Vector3D& C = p->center(); + float dist = std::sqrt(C(0)*C(0) + C(1)*C(1) + C(2)*C(2)); + theRoad.push_back(std::make_pair(dist,p)); + } + + for(auto hash_id : stripHashIds) { + const InDetDD::SiDetectorElement *p = m_stripManager->getDetectorElement(hash_id); + if(p == nullptr) continue; + const Amg::Vector3D& C = p->center(); + float dist = std::sqrt(C(0)*C(0) + C(1)*C(1) + C(2)*C(2)); + theRoad.push_back(std::make_pair(dist,p)); + } + + std::sort(theRoad.begin(), theRoad.end()); + + for(const auto & dp : theRoad) { + road.push_back(dp.second); + } + + return (int)theRoad.size(); } diff --git a/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetRoadPredictorTool.h b/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetRoadPredictorTool.h index 0796ba21f6c4db6b09e7b67f806c073c36d5d734..9ee21f1a9fce999eff8d5e57ba1849478c9b3904 100644 --- a/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetRoadPredictorTool.h +++ b/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetRoadPredictorTool.h @@ -10,31 +10,147 @@ #include "GaudiKernel/ServiceHandle.h" #include "TrigInDetToolInterfaces/ITrigInDetRoadPredictorTool.h" +#include "TrigInDetToolInterfaces/ITrigL2LayerNumberTool.h" // MagField cache #include "MagFieldConditions/AtlasFieldCacheCondObj.h" #include "MagFieldElements/AtlasFieldCache.h" +#include <fstream> +#include <array> +#include <map> + +namespace InDetDD { + class PixelDetectorManager; + class SCT_DetectorManager; +} + namespace Trk { class SpacePoint; } +class PixelID; +class SCT_ID; + class TrigInDetRoadPredictorTool: public AthAlgTool, virtual public ITrigInDetRoadPredictorTool { public: TrigInDetRoadPredictorTool( const std::string&, const std::string&, const IInterface* ); + virtual StatusCode initialize() override; - virtual int getRoad(const std::vector<const Trk::SpacePoint*>&, std::vector<const InDetDD::SiDetectorElement*>&, const EventContext&) const override; + virtual int getRoad(const std::vector<const Trk::SpacePoint*>&, std::vector<const InDetDD::SiDetectorElement*>&, + const EventContext&) const override; private: + + struct DetectorElementDescription { + DetectorElementDescription(unsigned int h) : m_hash(h) {}; + unsigned int m_hash; + short m_index; + float m_ref;//z or Phi + float m_c[4][3]; + float m_minBound, m_maxBound; + }; + + struct DetectorElementsCollection { + DetectorElementsCollection(short idx, float min, float max) : m_index(idx), m_minCoord(min), m_maxCoord(max) {}; + short m_index; + float m_minCoord, m_maxCoord; //phi or R + std::vector<DetectorElementDescription> m_vDE; + }; + + struct LayerDescription { + LayerDescription(unsigned int id, int nSL, unsigned int mType) : m_id(id), m_nSubLayers(nSL), m_mappingType(mType) {}; + unsigned int m_id; + int m_nSubLayers; + unsigned int m_mappingType; + std::map<short, DetectorElementsCollection> m_colls[2]; + }; + + + struct SearchInterval { + SearchInterval(float z, float r) : m_r(0.0), m_z(0.0), m_phi(0.0) { + m_vZx.push_back(z); + m_vRx.push_back(r); + } + + void addPoint(float z, float r) { + m_vZx.push_back(z); + m_vRx.push_back(r); + } + + float getAverageRadius() { + return std::accumulate(m_vRx.begin(), m_vRx.end(), 0)/m_vRx.size(); + } + + float getAverageZ() { + return std::accumulate(m_vZx.begin(), m_vZx.end(), 0)/m_vZx.size(); + } + + float getMinZ() const { + return *std::min_element( m_vZx.begin(), m_vZx.end()); + } + + float getMaxZ() const { + return *std::max_element( m_vZx.begin(), m_vZx.end()); + } + + float getMinR() const { + return *std::min_element( m_vRx.begin(), m_vRx.end()); + } + + float getMaxR() const { + return *std::max_element( m_vRx.begin(), m_vRx.end()); + } + + std::vector<float> m_vZx; + std::vector<float> m_vRx; + float m_r; + float m_z; + float m_phi; + }; - Gaudi::Property<int> m_nClustersMin {this, "nClustersMin", 7, "Minimum number of clusters on track"}; + struct VolumeBoundary { + int m_index; + float m_zr[4]; + int m_vol_id; + std::vector<int> m_layers; + }; + struct LayerBoundary { + int m_index, m_lay_id, m_nVertices; + std::vector<float> m_z; + std::vector<float> m_r; + }; + + void buildDetectorDescription(); + void createHitBoxes(); + + void addNewElement(unsigned int, short, short, const InDetDD::SiDetectorElement*); + void findDetectorElements(unsigned int, const SearchInterval&, std::vector<unsigned int>&, bool) const; + + ToolHandle<ITrigL2LayerNumberTool> m_layerNumberTool {this, "LayerNumberTool", "TrigL2LayerNumberToolITk"}; + + Gaudi::Property<float> m_min_rz_rw {this, "MinRzRoadWidth", 3.0, "Minimum rz road width"}; + Gaudi::Property<float> m_max_rz_rw {this, "MaxRzRoadWidth", 15.0, "Maximum rz road width"}; + Gaudi::Property<float> m_min_rphi_rw {this, "MinRPhiRoadWidth", 3.0, "Minimum rphi road width"}; + Gaudi::Property<float> m_max_rphi_rw {this, "MaxRPhiRoadWidth", 15.0, "Maximum rphi road width"}; + Gaudi::Property<float> m_min_phi_rw {this, "MinPhiRoadWidth", 0.05, "Minimum phi road width"}; + Gaudi::Property<float> m_max_phi_rw {this, "MaxPhiRoadWidth", 0.1, "Maximum phi road width"}; + SG::ReadCondHandleKey<AtlasFieldCacheCondObj> m_fieldCondObjInputKey{ this, "AtlasFieldCacheCondObj", "fieldCondObj", "Name of the Magnetic Field conditions object key"}; - + + std::vector<VolumeBoundary> m_vBoundaries; + std::vector<LayerBoundary> m_lBoundaries; + std::map<unsigned int, LayerDescription> m_layerMap; + + const InDetDD::PixelDetectorManager* m_pixelManager{nullptr}; + const InDetDD::SCT_DetectorManager* m_stripManager{nullptr}; + const PixelID* m_pixelId{nullptr}; + const SCT_ID* m_stripId{nullptr}; }; #endif diff --git a/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetTrackFollowingTool.cxx b/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetTrackFollowingTool.cxx index baff86aa16cc2ccaeefde2ccd0ff4723f62677d2..4274ff26280fec60adff5a1b87847204fe599d6e 100644 --- a/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetTrackFollowingTool.cxx +++ b/Trigger/TrigTools/TrigInDetTrackFitter/src/TrigInDetTrackFollowingTool.cxx @@ -261,7 +261,7 @@ double TrigInDetTrackFollowingTool::processHit(const InDet::SCT_Cluster* pPRD, i const Trk::PrepRawData* TrigInDetTrackFollowingTool::updateTrackState(const InDet::PixelCluster* pInputHit, const InDet::PixelClusterCollection* pColl, TrigFTF_ExtendedTrackState& ets) const { const InDet::PixelCluster* bestHit = pInputHit; - + if(pColl == nullptr && pInputHit == nullptr) return nullptr; double resid[2]; double invcov[3]; @@ -317,7 +317,7 @@ const Trk::PrepRawData* TrigInDetTrackFollowingTool::updateTrackState(const InDe const Trk::PrepRawData* TrigInDetTrackFollowingTool::updateTrackState(const InDet::SCT_Cluster* pInputHit, const InDet::SCT_ClusterCollection* pColl, int shape, TrigFTF_ExtendedTrackState& ets) const { const InDet::SCT_Cluster* bestHit = pInputHit; - + if(pColl == nullptr && pInputHit == nullptr) return nullptr; double resid, invcov; double H[2];//linearized observation matrix