ATLAS Offline Software
Loading...
Searching...
No Matches
Muon::DCMathSegmentMaker Class Reference

Implementation of a IMuonSegmentMaker. More...

#include <DCMathSegmentMaker.h>

Inheritance diagram for Muon::DCMathSegmentMaker:
Collaboration diagram for Muon::DCMathSegmentMaker:

Classes

struct  HitInXZ
struct  Cluster2D
struct  TubeEnds
struct  segmentCreationInfo

Public Types

using EtaPhiHitsPair = std::pair<std::vector<const MuonClusterOnTrack*>, std::vector<const MuonClusterOnTrack*> >
using IdHitMap = std::map<Identifier, EtaPhiHitsPair>
using ChIdHitMap = std::map<Identifier, IdHitMap>
using ClusterVec = std::vector<Cluster2D>
using ClusterVecPair = std::pair<ClusterVec, ClusterVec>

Public Member Functions

virtual ~DCMathSegmentMaker ()=default
virtual StatusCode initialize ()
void find (const std::vector< const Trk::RIO_OnTrack * > &rios, Trk::SegmentCollection *segColl=nullptr) const
 find segments starting from a list of RIO_OnTrack objects, implementation of IMuonSegmentMaker interface routine.
void find (const std::vector< const Trk::RIO_OnTrack * > &rios1, const std::vector< const Trk::RIO_OnTrack * > &rios2) const
 find segments starting from a list of RIO_OnTrack objects in multiple chambers, implementation of IMuonSegmentMaker interface routine Will call:
void find (const std::vector< const MdtDriftCircleOnTrack * > &mdts, const std::vector< const MuonClusterOnTrack * > &clusters, Trk::SegmentCollection *segColl=nullptr) const
 find segments starting from:
void find (const Amg::Vector3D &gpos, const Amg::Vector3D &gdir, const std::vector< const MdtDriftCircleOnTrack * > &mdts, const std::vector< const MuonClusterOnTrack * > &clusters, bool hasPhiMeasurements=false, Trk::SegmentCollection *segColl=nullptr, double momentum=1e9, double sinAngleCut=0, double beta=1.) const
 find segments starting from:
void find (const Trk::TrackRoad &road, const std::vector< std::vector< const MdtDriftCircleOnTrack * > > &mdts, const std::vector< std::vector< const MuonClusterOnTrack * > > &clusters, Trk::SegmentCollection *segColl, bool hasPhiMeasurements=false, double momentum=1e9) const
 find segments starting from:

Private Member Functions

bool errorScalingRegion (const Identifier &id) const
 apply error scaling for low mometum tracks
double errorScaleFactor (const Identifier &id, double curvature, bool hasPhiMeasurements) const
 calculate error scaling factor
std::vector< IdentifiercalculateHoles (const EventContext &ctx, Identifier chid, const Amg::Vector3D &gpos, const Amg::Vector3D &gdir, bool hasMeasuredCoordinate, std::set< Identifier > &deltaVec, std::set< Identifier > &outoftimeVec, const std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec) const
TrkDriftCircleMath::DCVec createDCVec (const std::vector< const MdtDriftCircleOnTrack * > &mdts, double errorScale, std::set< Identifier > &chamberSet, double &phimin, double &phimax, TrkDriftCircleMath::DCStatistics &dcStatistics, const Amg::Transform3D &gToStation, const Amg::Transform3D &amdbToGlobal) const
ClusterVecPair create1DClusters (const std::vector< const MuonClusterOnTrack * > &clusters) const
ClusterVecPair create2DClusters (const std::vector< const MuonClusterOnTrack * > &clusters) const
ClusterVecPair createSpacePoints (const ChIdHitMap &chIdHitMap) const
ClusterVecPair createSpacePoints (const IdHitMap &gasGapHitMap) const
Cluster2D createSpacePoint (const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const MuonClusterOnTrack *phiHit) const
Cluster2D createRpcSpacePoint (const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const std::vector< const MuonClusterOnTrack * > &phiHits) const
Cluster2D createTgcSpacePoint (const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const MuonClusterOnTrack *phiHit) const
TrkDriftCircleMath::CLVec createClusterVec (const Identifier &chid, ClusterVec &spVec, const Amg::Transform3D &gToStation) const
void associateMDTsToSegment (const Amg::Vector3D &gdir, TrkDriftCircleMath::Segment &segment, const TrkDriftCircleMath::ChamberGeometry *multiGeo, const Amg::Transform3D &gToStation, const Amg::Transform3D &amdbToGlobal, std::set< Identifier > &deltaVec, std::set< Identifier > &outoftimeVec, std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec, double beta=1.) const
std::pair< std::pair< int, int >, bool > associateClustersToSegment (const TrkDriftCircleMath::Segment &segment, const Identifier &chid, const Amg::Transform3D &gToStation, ClusterVecPair &spVecs, double phimin, double phimax, std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec) const
TrkDriftCircleMath::MdtChamberGeometry createChamberGeometry (const Identifier &chid, const Amg::Transform3D &gToStation) const
const MdtDriftCircleOnTrackfindFirstRotInChamberWithMostHits (const std::vector< const MdtDriftCircleOnTrack * > &mdts) const
bool updateSegmentPhi (const Amg::Vector3D &gpos, const Amg::Vector3D &gdir, Amg::Vector2D &segLocPos, Trk::LocalDirection &segLocDir, Trk::PlaneSurface &surf, const std::vector< const Trk::MeasurementBase * > &rots, double phimin, double phimax) const
bool checkBoundsInXZ (double xline, double zline, double dXdZ, const std::vector< HitInXZ > &hits) const
 check whether all hits are in bounds in the XZ plane
TubeEnds localTubeEnds (const MdtDriftCircleOnTrack &mdt, const Amg::Transform3D &gToSegment, const Amg::Transform3D &segmentToG) const
 calculate positions of tube ends
bool checkPhiConsistency (double phi, double phimin, double phimax) const
 check whether phi is consistent with segment phi
Amg::Vector3D updateDirection (double linephi, const Trk::PlaneSurface &surf, const Amg::Vector3D &roaddir, bool isCurvedSegment) const
 update the global direction, keeping the phi of the input road direction but using the local angle YZ
std::unique_ptr< MuonSegmentcreateSegment (const EventContext &ctx, TrkDriftCircleMath::Segment &segment, const Identifier &chid, const Amg::Vector3D &roadpos, const Amg::Vector3D &roaddir2, const std::vector< const MdtDriftCircleOnTrack * > &mdts, bool hasPhiMeasurements, segmentCreationInfo &sInfo, double beta=1.) const
const MdtPrepDatafindMdt (const EventContext &ctx, const Identifier &id) const

Static Private Member Functions

static DataVector< const Trk::MeasurementBasecreateROTVec (std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec)
static double distanceToSegment (const TrkDriftCircleMath::Segment &segment, const Amg::Vector3D &hitPos, const Amg::Transform3D &gToStation)
static std::pair< double, double > residualAndPullWithSegment (const TrkDriftCircleMath::Segment &segment, const Cluster2D &spacePoint, const Amg::Transform3D &gToStation)
static void updatePhiRanges (double phiminNew, double phimaxNew, double &phiminRef, double &phimaxRef)
 update phi ranges

Private Attributes

SG::ReadCondHandleKey< MuonGM::MuonDetectorManagerm_DetectorManagerKey
 pointers to IdHelpers
ServiceHandle< Muon::IMuonIdHelperSvcm_idHelperSvc
ServiceHandle< IMuonEDMHelperSvcm_edmHelperSvc
ToolHandle< IMdtDriftCircleOnTrackCreatorm_mdtCreator
ToolHandle< IMdtDriftCircleOnTrackCreatorm_mdtCreatorT0
ToolHandle< IMuonClusterOnTrackCreatorm_clusterCreator
ToolHandle< IMuonCompetingClustersOnTrackCreatorm_compClusterCreator
PublicToolHandle< MuonEDMPrinterToolm_printer
ToolHandle< IMdtSegmentFinderm_segmentFinder
ToolHandle< IMuonSegmentFittingToolm_segmentFitter
ToolHandle< IMuonSegmentSelectionToolm_segmentSelectionTool
ToolHandle< IDCSLFitProviderm_dcslFitProvider
Gaudi::Property< double > m_sinAngleCut {this, "SinAngleCut", 0.2}
Gaudi::Property< bool > m_doGeometry {this, "DoGeometry", true}
Gaudi::Property< bool > m_curvedErrorScaling {this, "CurvedErrorScaling", true}
Gaudi::Property< bool > m_doSpacePoints {this, "UseTriggerSpacePoints", true}
Gaudi::Property< bool > m_createCompetingROTsEta {this, "CreateCompetingROTsEta", true}
Gaudi::Property< bool > m_createCompetingROTsPhi {this, "CreateCompetingROTsPhi", true}
Gaudi::Property< bool > m_refitParameters {this, "RefitSegment", false}
Gaudi::Property< bool > m_addUnassociatedPhiHits {this, "AddUnassociatedPhiHits", false}
Gaudi::Property< bool > m_strictRoadDirectionConsistencyCheck {this, "StrictRoadDirectionConsistencyCheck", true}
Gaudi::Property< double > m_maxAssociateClusterDistance {this, "MaxAssociateClusterDistance", 3000.}
Gaudi::Property< bool > m_allMdtHoles {this, "AllMdtHoles", false}
Gaudi::Property< bool > m_removeDeltas {this, "RemoveDeltasFromSegmentQuality", true}
Gaudi::Property< bool > m_reject1DTgcSpacePoints {this,"Reject1DTgcSpacePoints", true }
Gaudi::Property< bool > m_usePreciseError {this, "UsePreciseError", false}
Gaudi::Property< bool > m_outputFittedT0 {this, "OutputFittedT0", false}
Gaudi::Property< double > m_preciseErrorScale {this, "PreciseErrorScale", 2.}
Gaudi::Property< bool > m_doTimeOutChecks {this, "UseTimeOutGard", false}
Gaudi::Property< bool > m_recoverBadRpcCabling {this, "RecoverBadRpcCabling", false}
Gaudi::Property< bool > m_updatePhiUsingPhiHits {this, "UpdatePhiUsingPhiHits", false}
Gaudi::Property< bool > m_assumePointingPhi {this, "AssumePointingPhi", false }
Gaudi::Property< bool > m_redo2DFit {this, "Redo2DFit", true}
SG::ReadHandleKey< Muon::MdtPrepDataContainerm_mdtKey {this, "MdtPrepDataContainer", "MDT_DriftCircles"}
SG::ReadCondHandleKey< Muon::MuonIntersectGeoDatam_chamberGeoKey {this, "ChamberGeoKey", "MuonStationIntersects", "Pointer to hole search service"}

Detailed Description

Implementation of a IMuonSegmentMaker.

For more details look at the mainpage of this package.

Definition at line 96 of file DCMathSegmentMaker.h.

Member Typedef Documentation

◆ ChIdHitMap

Definition at line 102 of file DCMathSegmentMaker.h.

◆ ClusterVec

Definition at line 158 of file DCMathSegmentMaker.h.

◆ ClusterVecPair

◆ EtaPhiHitsPair

Definition at line 99 of file DCMathSegmentMaker.h.

◆ IdHitMap

Constructor & Destructor Documentation

◆ ~DCMathSegmentMaker()

virtual Muon::DCMathSegmentMaker::~DCMathSegmentMaker ( )
virtualdefault

Member Function Documentation

◆ associateClustersToSegment()

std::pair< std::pair< int, int >, bool > Muon::DCMathSegmentMaker::associateClustersToSegment ( const TrkDriftCircleMath::Segment & segment,
const Identifier & chid,
const Amg::Transform3D & gToStation,
ClusterVecPair & spVecs,
double phimin,
double phimax,
std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > & rioDistVec ) const
private

calculate distance to segment

Definition at line 1285 of file DCMathSegmentMaker.cxx.

1287 {
1288 typedef IdDataVec<std::pair<double, Cluster2D> > GasGapData;
1289 typedef IdDataVec<GasGapData> ChamberData;
1290 typedef std::vector<ChamberData> ChamberDataVec;
1291 ChamberDataVec chamberDataVec;
1292 bool isEndcap = m_idHelperSvc->isEndcap(chid);
1293
1294 // keep track of the number of eta/phi hits on the segment
1295 bool refit = false;
1296 std::pair<std::pair<int, int>, bool> netaPhiHits(std::make_pair(0, 0), false);
1297 if (segment.clusters().empty()) return netaPhiHits;
1298
1299 std::vector<const Trk::MeasurementBase*> phiHits;
1300
1301 // only refit if there are sufficient phi hits and no multiple phi hits per surface
1302 refit = true;
1303
1304 // keep track of detector elements which space points added to the track
1305 std::set<Identifier> detElOnSegments;
1306 std::set<MuonStationIndex::PhiIndex> phiIndices;
1307
1308 ATH_MSG_DEBUG(" Associating clusters: " << segment.clusters().size() << " number of space points " << spVecs.first.size());
1309
1310 // associate space points and sort them per detector element and gas gap
1311 for (const TrkDriftCircleMath::Cluster& clust : segment.clusters()) {
1312
1313 const Cluster2D& spacePoint = spVecs.first[clust.index()];
1314 ATH_MSG_VERBOSE(" accessing cluster: " << clust.index()<<", "
1315 <<m_idHelperSvc->toString(spacePoint.identify()));
1316 // skip corrupt space points
1317 if (spacePoint.corrupt()) {
1318 ATH_MSG_DEBUG(" Found corrupt space point: index " << clust.index());
1319 continue;
1320 }
1321 // reject TGC clusters that are not 2D
1322 if (m_reject1DTgcSpacePoints && !spacePoint.is2D() && m_idHelperSvc->isTgc(spacePoint.identify())) {
1323 ATH_MSG_DEBUG(" Rejecting 1D tgc space point " << m_idHelperSvc->toString(spacePoint.identify()));
1324 continue;
1325 }
1326 if (m_assumePointingPhi && spacePoint.is2D() && !checkPhiConsistency(spacePoint.globalPos.phi(), phimin, phimax)) {
1327 ATH_MSG_DEBUG(" Inconsistent phi angle, dropping space point: phi " << spacePoint.globalPos.phi() << " range " << phimin
1328 << " " << phimax);
1329 continue;
1330 }
1331
1332 std::pair<double, double> resPull = residualAndPullWithSegment(segment, spacePoint, gToStation);
1333
1334 // if empty or new chamber, add chamber
1335 if (chamberDataVec.empty() || chamberDataVec.back().id != spacePoint.detElId) {
1336 detElOnSegments.insert(spacePoint.detElId);
1337 chamberDataVec.emplace_back(spacePoint.detElId);
1338 MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(spacePoint.detElId);
1339 phiIndices.insert(phiIndex);
1340 }
1341
1342 // reference to current chamber data
1343 ChamberData& chamber = chamberDataVec.back();
1344
1345 // if same detector element
1346 if (spacePoint.detElId == chamber.id) {
1347 // if chamber empty or new gas gap, add gasp gap
1348 if (chamber.data.empty() || chamber.data.back().id != spacePoint.gasGapId) {
1349 chamber.data.emplace_back(spacePoint.gasGapId);
1350 }
1351 }
1352
1353 // reference to current gas gap data
1354 GasGapData& gasGap = chamber.data.back();
1355 gasGap.data.emplace_back(resPull.second, spacePoint);
1356 }
1357
1358 // calculate the distance between the first and last station, use r in barrel and z in endcaps
1359 double posFirstPhiStation{FLT_MAX}, posLastPhiStation{0.};
1360
1361 // loop over chambers and create competing ROTs per chamber
1362 for (ChamberData& chamb : chamberDataVec) {
1363 // select best clusters per gas gap in chamber
1364 std::list<const Trk::PrepRawData*> etaClusterVec{}, phiClusterVec{};
1365 std::unordered_set<Identifier> etaIds;
1366 // loop over gas gaps
1367 for (GasGapData& gasGap : chamb.data) {
1368 // sort space points by their pull with the segment
1369 std::ranges::sort(gasGap.data, SortClByPull());
1370
1371 // select all space points with a pull that is within 1 of the best pull
1372 double bestPull = std::abs(gasGap.data.front().first);
1373
1374 // count number of associated clusters in gas gap
1375 unsigned int nassociatedSp = 0;
1376 GasGapData::EntryVec::const_iterator cl_it = gasGap.data.begin();
1377 while (cl_it != gasGap.data.end() && std::abs(cl_it->first) - bestPull < 1.) {
1378 const Cluster2D& sp = cl_it->second;
1380 double dist = distanceToSegment(segment, sp.globalPos, gToStation);
1381 ATH_MSG_VERBOSE(" selected space point: " << m_idHelperSvc->toString(sp.identify()) << " pull "
1382 << std::abs(cl_it->first) << " distance to segment " << dist << " phi "
1383 << sp.globalPos.phi());
1384
1385 // here keep open the option not to create CompetingMuonClustersOnTrack
1386 if (sp.etaHit) {
1387 if (etaIds.insert(sp.etaHit->identify()).second) {
1388 // BI rpc measurements have 2D coordinates
1390 sp.etaHit->prepRawData()->localCovariance().cols() == 1) {
1391 etaClusterVec.push_back(sp.etaHit->prepRawData());
1392 } else {
1393 rioDistVec.emplace_back(dist, sp.etaHit->uniqueClone());
1394 ++netaPhiHits.first.first;
1395 }
1396 }
1397 }
1398 if (!sp.phiHits.empty()) {
1400 // can have multiple phi hits per cluster, loop over phi hits and add them
1401 std::ranges::transform(sp.phiHits, std::back_inserter(phiClusterVec),
1402 [](const Muon::MuonClusterOnTrack* clus){
1403 return clus->prepRawData();
1404 });
1405 } else {
1406 // can have multiple phi hits per cluster, loop over phi hits and add them
1407 for (const MuonClusterOnTrack* phi_hit : sp.phiHits) {
1408 rioDistVec.emplace_back(dist, phi_hit->uniqueClone());
1409 ++netaPhiHits.first.second;
1410 phiHits.push_back(phi_hit);
1411
1412 // calculate position
1413 double phiPos = isEndcap ? std::abs(phi_hit->globalPosition().z()) : phi_hit->globalPosition().perp();
1414 posFirstPhiStation = std::min(phiPos, posFirstPhiStation);
1415 posLastPhiStation = std::max(phiPos, posLastPhiStation);
1416 }
1417 if (sp.phiHits.size() > 1) refit = false;
1418 }
1419 }
1420 ++nassociatedSp;
1421 ++cl_it;
1422 }
1423 // multiple clusters in same gas gap, don't refit
1424 if (!m_createCompetingROTsPhi && nassociatedSp > 1) refit = false;
1425 }
1426
1428 // create competing ROT for eta hits
1429 if (!etaClusterVec.empty()) {
1430 std::unique_ptr<const CompetingMuonClustersOnTrack> etaCompCluster = m_compClusterCreator->createBroadCluster(etaClusterVec, 0.);
1431 if (!etaCompCluster) {
1432 ATH_MSG_DEBUG(" failed to create competing ETA ROT " << etaClusterVec.size());
1433 } else {
1434 double dist = distanceToSegment(segment, etaCompCluster->globalPosition(), gToStation);
1435 ++netaPhiHits.first.first;
1436 if (msgLvl(MSG::VERBOSE)) {
1437 ATH_MSG_VERBOSE(" selected cluster: " << m_idHelperSvc->toString(etaClusterVec.front()->identify()));
1438 for (unsigned int i = 0; i < etaCompCluster->containedROTs().size(); ++i) {
1440 " content: " << m_idHelperSvc->toString(etaCompCluster->containedROTs()[i]->identify()));
1441 }
1442 }
1443 rioDistVec.emplace_back(dist, std::move(etaCompCluster));
1444 }
1445 }
1446 }
1447
1449 // create competing ROT for phi hits
1450 if (!phiClusterVec.empty()) {
1451 std::unique_ptr<const CompetingMuonClustersOnTrack> phiCompCluster = m_compClusterCreator->createBroadCluster(phiClusterVec, 0.);
1452 if (!phiCompCluster) {
1453 ATH_MSG_DEBUG(" failed to create competing PHI ROT " << phiClusterVec.size());
1454 } else {
1455 double dist = distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation);
1456 phiHits.push_back(phiCompCluster.get());
1457
1458 ++netaPhiHits.first.second;
1459
1460 if (msgLvl(MSG::VERBOSE)) {
1461 ATH_MSG_VERBOSE(" selected cluster: " << m_idHelperSvc->toString(phiClusterVec.front()->identify()));
1462 for (unsigned int i = 0; i < phiCompCluster->containedROTs().size(); ++i) {
1464 " content: " << m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify()));
1465 }
1466 }
1467
1468
1469 // calculate position
1470 double phiPos = isEndcap ? std::abs(phiCompCluster->globalPosition().z()) :
1471 phiCompCluster->globalPosition().perp();
1472 posFirstPhiStation = std::min(phiPos,posFirstPhiStation);
1473 posLastPhiStation = std::max(phiPos,posLastPhiStation);
1474 rioDistVec.emplace_back(dist, std::move(phiCompCluster));
1475
1476 }
1477 }
1478 }
1479 }
1480
1481 // add phi hits that were not associated with an eta hit (only in barrel)
1482 if ((!spVecs.second.empty() || m_recoverBadRpcCabling) && m_addUnassociatedPhiHits && !isEndcap) {
1483 TrkDriftCircleMath::ResidualWithSegment resWithSegment(segment);
1484
1485 std::map<Identifier, std::list<const Trk::PrepRawData*> > phiClusterMap;
1486
1487 std::set<const MuonClusterOnTrack*> selectedClusters;
1488 std::vector<const Cluster2D*> phiClusters;
1489 phiClusters.reserve(spVecs.second.size());
1490
1491 // create lists of PrepRawData per detector element
1492 for (const Cluster2D& phi_clus :spVecs.second) {
1493 if (!phi_clus.phiHit || phi_clus.corrupt()) {
1494 ATH_MSG_WARNING(" phi clusters without phi hit!!");
1495 continue;
1496 }
1497 phiClusters.push_back(&phi_clus);
1498 selectedClusters.insert(phi_clus.phiHit);
1499 }
1500
1501 unsigned int recoveredUnassociatedPhiHits(0);
1503 // now loop over 2D space points and add the phi hits to the list if the detEl is not yet added to the
1504 // segment
1505 for (const Cluster2D& rpc_clust : spVecs.first) {
1506 // skip clusters without phi hit
1507 if (!rpc_clust.phiHit || rpc_clust.corrupt()) continue;
1508
1509 // skip clusters in detector elements that are already associated (ok as this is only done for RPC)
1510 if (detElOnSegments.count(rpc_clust.detElId)) continue;
1511
1512 MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(rpc_clust.detElId);
1513 // skip clusters in detector layer
1514 if (phiIndices.count(phiIndex)) continue;
1515
1516 bool wasFound = false;
1517 for (const MuonClusterOnTrack* phi_hit : rpc_clust.phiHits) {
1518 // now to avoid duplicate also skip if the given ROT is already in the list
1519 if (!selectedClusters.insert(phi_hit).second) {
1520 // flag as found
1521 wasFound = true;
1522
1523 // just because I'm paranoid, remove the hits from this cluster that were already inserted up to
1524 // here
1525 for (const MuonClusterOnTrack* erase_me : rpc_clust.phiHits) {
1526 if (erase_me == phi_hit) break;
1527 selectedClusters.erase(erase_me);
1528 }
1529 break;
1530 }
1531 }
1532 if (wasFound) continue;
1533
1534 // if we get here we should add the hit
1535 phiClusters.push_back(&rpc_clust);
1536 ++recoveredUnassociatedPhiHits;
1537 }
1538 }
1539
1540 unsigned int addedPhiHits(0);
1541 for (const Cluster2D* phi_clus : phiClusters) {
1542 const Identifier& detElId = phi_clus->detElId;
1543
1544 // check that detector element is not already added to segment
1545 if (detElOnSegments.count(detElId)) continue;
1546
1548 // skip clusters in detector layer
1549 if (phiIndices.count(phiIndex)) continue;
1550
1551 // calculate local cluster position
1552 Amg::Vector3D locPos = gToStation * phi_clus->globalPos;
1553
1554 // calculate intersect of segment with cluster
1555 TrkDriftCircleMath::Cluster cl(TrkDriftCircleMath::LocVec2D(locPos.y(), locPos.z()), 1.);
1556 double residual = resWithSegment.residual(cl);
1557 double segError = std::sqrt(resWithSegment.trackError2(cl));
1558 const MuonGM::RpcReadoutElement* detEl = dynamic_cast<const MuonGM::RpcReadoutElement*>(phi_clus->phiHit->detectorElement());
1559 if (!detEl) {
1560 ATH_MSG_WARNING("found RPC prd without RpcReadoutElement");
1561 continue;
1562 }
1563
1564 // perform bound check
1565 double stripLength = detEl->StripLength(1);
1566 bool inBounds = std::abs(residual) < 0.5 * stripLength + 2. + segError;
1567 if (msgLvl(MSG::DEBUG)) {
1568 ATH_MSG_DEBUG(" Unassociated " << m_idHelperSvc->toString(phi_clus->phiHit->identify()) << " pos x " << cl.position().x()
1569 << " pos y " << cl.position().y() << " : residual " << residual << " strip half length "
1570 << 0.5 * stripLength << " segment error " << segError);
1571 if (inBounds)
1572 ATH_MSG_DEBUG(" inBounds");
1573 else
1574 ATH_MSG_DEBUG(" outBounds");
1575 }
1576 if (inBounds) {
1577 // can have multiple phi hits per cluster, loop over phi hits and add them
1578 std::list<const Trk::PrepRawData*>& cham_hits{phiClusterMap[detElId]};
1579 std::transform(phi_clus->phiHits.begin(), phi_clus->phiHits.end(), std::back_inserter(cham_hits),
1580 [](const MuonClusterOnTrack* clus){
1581 return clus->prepRawData();
1582 });
1583 }
1584 }
1585
1586 // loop over detector elements and created competing ROTs
1587 for (const auto& [phi_id, prds] : phiClusterMap) {
1588 if (prds.empty()) {
1589 ATH_MSG_WARNING(" chamber without phi hits " << m_idHelperSvc->toString(phi_id));
1590 continue;
1591 }
1592
1593 std::unique_ptr<const CompetingMuonClustersOnTrack> phiCompCluster = m_compClusterCreator->createBroadCluster(prds, 0.);
1594 if (!phiCompCluster) {
1595 ATH_MSG_DEBUG(" failed to create competing PHI ROT " << prds.size());
1596 } else {
1597 double dist = distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation);
1598
1599 if (std::abs(dist) > m_maxAssociateClusterDistance) {
1600
1601 ATH_MSG_VERBOSE(" rejected unassociated cluster: " << m_idHelperSvc->toString(prds.front()->identify())
1602 << " distance to segment " << dist);
1603 continue;
1604 }
1605 phiHits.push_back(phiCompCluster.get());
1606 ++netaPhiHits.first.second;
1607 ++addedPhiHits;
1608 if (msgLvl(MSG::VERBOSE)) {
1609 ATH_MSG_VERBOSE(" selected unassociated cluster: " << m_idHelperSvc->toString(prds.front()->identify())
1610 << " distance to segment " << dist);
1611 for (unsigned int i = 0; i < phiCompCluster->containedROTs().size(); ++i) {
1613 " content: " << m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify()));
1614 }
1615 }
1616 rioDistVec.emplace_back(dist, std::move(phiCompCluster));
1617 }
1618 }
1619 ATH_MSG_VERBOSE("Added " << addedPhiHits << " unass phi hits out of " << spVecs.second.size()
1620 << " phi hits without eta hit and " << recoveredUnassociatedPhiHits << " with unassociated eta hit ");
1621 }
1622
1623 // calculate distance between first and last phi trigger hit, refit if there is a good constraint on phi
1624 double phiDistanceMax = posLastPhiStation - posFirstPhiStation;
1625 if (isEndcap && phiDistanceMax < 1000.)
1626 refit = false;
1627 else if (phiDistanceMax < 400.)
1628 refit = false;
1629
1630 netaPhiHits.second = refit;
1631 return netaPhiHits;
1632 }
Scalar perp() const
perp method - perpendicular length
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sp
size_t size() const
Number of registered mappings.
virtual const Amg::Vector3D & globalPosition() const override
Returns global position.
double StripLength(bool measphi) const
returns the strip length for the phi or eta plane
Gaudi::Property< bool > m_addUnassociatedPhiHits
Gaudi::Property< bool > m_recoverBadRpcCabling
Gaudi::Property< bool > m_createCompetingROTsEta
static double distanceToSegment(const TrkDriftCircleMath::Segment &segment, const Amg::Vector3D &hitPos, const Amg::Transform3D &gToStation)
Gaudi::Property< bool > m_reject1DTgcSpacePoints
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
ToolHandle< IMuonCompetingClustersOnTrackCreator > m_compClusterCreator
Gaudi::Property< bool > m_createCompetingROTsPhi
Gaudi::Property< double > m_maxAssociateClusterDistance
Gaudi::Property< bool > m_assumePointingPhi
static std::pair< double, double > residualAndPullWithSegment(const TrkDriftCircleMath::Segment &segment, const Cluster2D &spacePoint, const Amg::Transform3D &gToStation)
bool checkPhiConsistency(double phi, double phimin, double phimax) const
check whether phi is consistent with segment phi
Eigen::Matrix< double, 3, 1 > Vector3D
PhiIndex
enum to classify the different phi layers in the muon spectrometer
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
unsigned int phiIndex(float phi, float binsize)
calculate phi index for a given phi
Definition EtaPhiLUT.cxx:23

◆ associateMDTsToSegment()

void Muon::DCMathSegmentMaker::associateMDTsToSegment ( const Amg::Vector3D & gdir,
TrkDriftCircleMath::Segment & segment,
const TrkDriftCircleMath::ChamberGeometry * multiGeo,
const Amg::Transform3D & gToStation,
const Amg::Transform3D & amdbToGlobal,
std::set< Identifier > & deltaVec,
std::set< Identifier > & outoftimeVec,
std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > & rioDistVec,
double beta = 1. ) const
private

Definition at line 1150 of file DCMathSegmentMaker.cxx.

1154 {
1155 // clear result vectors
1156
1157 // convert segment parameters + x position from road
1158 const TrkDriftCircleMath::Line& line = segment.line();
1159 TrkDriftCircleMath::TransformToLine toLineml1(line);
1160 TrkDriftCircleMath::TransformToLine toLineml2(line);
1161 if (segment.hasCurvatureParameters()) {
1162 // ml2 segment direction
1163 double ml2phi = line.phi() - segment.deltaAlpha();
1164 TrkDriftCircleMath::LocVec2D ml2dir(std::cos(ml2phi), std::sin(ml2phi));
1165 // ml2 segment position
1166 const TrkDriftCircleMath::LocVec2D ml1LocPos = multiGeo->tubePosition(0, multiGeo->nlay(), 0);
1167 const TrkDriftCircleMath::LocVec2D ml2LocPos = multiGeo->tubePosition(1, 1, 0);
1168 double chamberMidPtY = (ml1LocPos.y() + ml2LocPos.y()) / 2.0;
1169 TrkDriftCircleMath::LocVec2D ml2pos(segment.deltab(), chamberMidPtY);
1170 // construct the new ml2 segment line & transform
1171 const TrkDriftCircleMath::Line ml2line(ml2pos, ml2dir);
1172 TrkDriftCircleMath::TransformToLine tmptoLine(ml2line);
1173 // set the ml2 line
1174 toLineml2 = tmptoLine;
1175 }
1176
1177 for (TrkDriftCircleMath::DCOnTrack& dcit : segment.dcs()) {
1178 if (dcit.state() == TrkDriftCircleMath::DCOnTrack::Delta) { deltaVec.insert(dcit.rot()->identify()); }
1179
1180 if (dcit.state() == TrkDriftCircleMath::DCOnTrack::OutOfTime) { outoftimeVec.insert(dcit.rot()->identify()); }
1181
1182 if (dcit.state() != TrkDriftCircleMath::DCOnTrack::OnTrack) continue;
1183
1184 const MdtDriftCircleOnTrack* riodc{dcit.rot()};
1185
1186 // choose which line to use (ml1 or ml2)
1187 TrkDriftCircleMath::TransformToLine toLine = toLineml1;
1188 if (m_idHelperSvc->mdtIdHelper().multilayer(riodc->identify()) == 2) toLine = toLineml2;
1189 // calculate position of hit in line frame
1190 TrkDriftCircleMath::LocVec2D pointOnHit = toLine.toLine(dcit.position());
1191
1192 // calculate position of hit on line in line frame
1193 TrkDriftCircleMath::LocVec2D pointOnLine(pointOnHit.x(), 0.);
1194
1195 // transform back to local AMDB coordinates
1196 TrkDriftCircleMath::LocVec2D pointOnLineAMDB = toLine.toLocal(pointOnLine);
1197
1198 // get position along wire from ROT
1199 Amg::Vector3D posAlong = gToStation * riodc->globalPosition();
1200
1201 // set yz components
1202 posAlong[1] = pointOnLineAMDB.x();
1203 posAlong[2] = pointOnLineAMDB.y();
1204
1205 // back to global
1206 Amg::Vector3D mdtGP = amdbToGlobal * posAlong;
1207
1208 const Trk::StraightLineSurface* surf = dynamic_cast<const Trk::StraightLineSurface*>(&riodc->associatedSurface());
1209 if (!surf) {
1210 ATH_MSG_WARNING(" dynamic cast to StraightLineSurface failed for mdt!!! ");
1211 continue;
1212 }
1213
1214 // calculate Amg::Vector2D using surf to obtain sign
1215 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
1216 if (!surf->globalToLocal(mdtGP, gdir, locPos)) ATH_MSG_WARNING(" globalToLocal failed ");
1217
1218 // calculate side
1220
1221 std::unique_ptr<MdtDriftCircleOnTrack> nonconstDC;
1222 bool hasT0 = segment.hasT0Shift();
1223 if (!hasT0 || m_mdtCreatorT0.empty()) {
1224 // ATH_MSG_VERBOSE(" recalibrate MDT hit");
1225 nonconstDC.reset(m_mdtCreator->createRIO_OnTrack(*riodc->prepRawData(), mdtGP, &gdir, 0., nullptr, beta, 0.));
1226 if (hasT0) ATH_MSG_WARNING("Attempted to change t0 without a properly configured MDT creator tool. ");
1227 } else {
1228 ATH_MSG_VERBOSE(" recalibrate MDT hit with shift " << segment.t0Shift()<<" "<<m_printer->print(*riodc));
1229 nonconstDC.reset(m_mdtCreatorT0->createRIO_OnTrack(*riodc->prepRawData(), mdtGP, &gdir, segment.t0Shift()));
1230 }
1231
1232 if (!nonconstDC) {
1234 continue;
1235 }
1236 ATH_MSG_VERBOSE("Post calibrated hit "<<m_printer->print(*nonconstDC));
1237
1238 // update the drift radius after recalibration, keep error
1239 TrkDriftCircleMath::DriftCircle new_dc(dcit.position(), std::abs(nonconstDC->driftRadius()), dcit.dr(), dcit.drPrecise(),
1240 dcit.driftState(), dcit.id(),
1241 nonconstDC.get());
1242 TrkDriftCircleMath::DCOnTrack new_dc_on_track(new_dc, dcit.residual(), dcit.errorTrack());
1243 dcit = std::move(new_dc_on_track);
1244
1245 if (hasT0) {
1246 if (msgLvl(MSG::VERBOSE)) {
1247 double shift = riodc->driftTime() - nonconstDC->driftTime();
1248 ATH_MSG_VERBOSE(" t0 shift " << segment.t0Shift() << " from hit " << shift << " recal " << nonconstDC->driftRadius()
1249 << " t " << nonconstDC->driftTime() << " from fit " << dcit.r() << " old "
1250 << riodc->driftRadius() << " t " << riodc->driftTime());
1251 if (std::abs(std::abs(nonconstDC->driftRadius()) - std::abs(dcit.r())) > 0.1 && nonconstDC->driftRadius() < 19. &&
1252 nonconstDC->driftRadius() > 1.) {
1253 ATH_MSG_WARNING("Detected invalid recalibration after T0 shift");
1254 }
1255 }
1256 }
1257 m_mdtCreator->updateSign(*nonconstDC, side);
1258 double dist = pointOnHit.x();
1259 rioDistVec.emplace_back(dist, std::move(nonconstDC));
1260 }
1261 }
virtual const Amg::Vector3D & globalPosition() const override final
Returns the global Position.
double driftRadius() const
Returns the value of the drift radius.
double driftTime() const
Returns the value of the drift time used to obtain the drift radius.
virtual const Trk::StraightLineSurface & associatedSurface() const override final
Returns the surface on which this measurement was taken.
virtual const MdtPrepData * prepRawData() const override final
Returns the PrepRawData used to create this corrected measurement.
PublicToolHandle< MuonEDMPrinterTool > m_printer
ToolHandle< IMdtDriftCircleOnTrackCreator > m_mdtCreator
ToolHandle< IMdtDriftCircleOnTrackCreator > m_mdtCreatorT0
virtual LocVec2D tubePosition(unsigned int ml, unsigned int lay, unsigned int tube) const =0
virtual unsigned int nlay() const =0
@ OutOfTime
delta electron
Definition DCOnTrack.h:22
double y() const
Returns the y coordinate of the vector.
Definition LocVec2D.h:29
double x() const
Returns the x coordinate of the vector.
Definition LocVec2D.h:27
LocVec2D toLocal(const LocVec2D &pos) const
LocVec2D toLine(const LocVec2D &pos) const
Identifier identify() const
return the identifier -extends MeasurementBase
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const override final
Specified for StraightLineSurface: GlobalToLocal method without dynamic memory allocation This method...
Eigen::Matrix< double, 2, 1 > Vector2D
virtual void shift(size_t pos, ptrdiff_t offs) override
Shift the elements of the container.
DriftCircleSide
Enumerates the 'side' of the wire on which the tracks passed (i.e.
@ RIGHT
the drift radius is positive (see Trk::AtaStraightLine)
@ LEFT
the drift radius is negative (see Trk::AtaStraightLine)
@ driftRadius
trt, straws
Definition ParamDefs.h:53

◆ calculateHoles()

std::vector< Identifier > Muon::DCMathSegmentMaker::calculateHoles ( const EventContext & ctx,
Identifier chid,
const Amg::Vector3D & gpos,
const Amg::Vector3D & gdir,
bool hasMeasuredCoordinate,
std::set< Identifier > & deltaVec,
std::set< Identifier > & outoftimeVec,
const std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > & rioDistVec ) const
private

Definition at line 1691 of file DCMathSegmentMaker.cxx.

1693 {
1694 // calculate crossed tubes
1695 SG::ReadCondHandle<Muon::MuonIntersectGeoData> InterSectSvc{m_chamberGeoKey, ctx};
1696 if (!InterSectSvc.isValid()) {
1697 ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object");
1698 return {};
1699 }
1700 SG::ReadCondHandle<MuonGM::MuonDetectorManager> detMgr{m_DetectorManagerKey,ctx};
1701 const MuonGM::MuonDetectorManager* MuonDetMgr = detMgr.cptr();
1702
1703 const MuonStationIntersect intersect = InterSectSvc->tubesCrossedByTrack(MuonDetMgr, chid, gpos, gdir);
1704
1705 // set to identify the hit on the segment
1706 std::set<Identifier> hitsOnSegment, chambersOnSegment;
1707 int firstLayer{-1}, lastLayer{-1};
1708 for (const std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) {
1709 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(rdit.second.get());
1710 if (!mdt) continue;
1711 const Identifier id = mdt->identify();
1712 int layer = (m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1) + 4 * (m_idHelperSvc->mdtIdHelper().multilayer(id) - 1);
1713 if (firstLayer == -1)
1714 firstLayer = layer;
1715 else
1716 lastLayer = layer;
1717
1718 hitsOnSegment.insert(id);
1719 chambersOnSegment.insert(m_idHelperSvc->chamberId(id));
1720 }
1721
1722 // cross check for cosmic case
1723 if (firstLayer > lastLayer) { std::swap(firstLayer, lastLayer); }
1724 ATH_MSG_VERBOSE(" Tube layer ranges: " << firstLayer << " -- " << lastLayer << " crossed tubes "
1725 << intersect.tubeIntersects().size());
1726 // clear hole vector
1727 std::vector<Identifier> holeVec;
1728 for (const MuonTubeIntersect& tint : intersect.tubeIntersects()) {
1729 if (!chambersOnSegment.count(m_idHelperSvc->chamberId(tint.tubeId))) {
1730 ATH_MSG_VERBOSE(" chamber not on segment, not counting tube " << tint.rIntersect << " l " << tint.xIntersect << " "
1731 << m_idHelperSvc->toString(tint.tubeId));
1732 continue;
1733 }
1734
1735 const Identifier& id = tint.tubeId;
1736 int layer = (m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1) + 4 * (m_idHelperSvc->mdtIdHelper().multilayer(id) - 1);
1737
1738 bool notBetweenHits = layer < firstLayer || layer > lastLayer;
1739 double distanceCut = hasMeasuredCoordinate ? -20 : -200.;
1740 double innerRadius = MuonDetMgr->getMdtReadoutElement(id)->innerTubeRadius();
1741 if (notBetweenHits && (std::abs(tint.rIntersect) > innerRadius || (!m_allMdtHoles && tint.xIntersect > distanceCut))) {
1742 ATH_MSG_VERBOSE(" not counting tube: distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect
1743 << " " << m_idHelperSvc->toString(tint.tubeId));
1744 continue;
1745 }
1746 // check whether there is a hit in this tube
1747 if (hitsOnSegment.count(tint.tubeId)) {
1748 ATH_MSG_VERBOSE(" tube on segment: distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect
1749 << " " << m_idHelperSvc->toString(tint.tubeId));
1750 continue;
1751 }
1752 // check whether there is a delta electron in this tube
1753 if (m_removeDeltas) {
1754 if (deltaVec.count(tint.tubeId)) {
1755 ATH_MSG_VERBOSE(" removing delta, distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect
1756 << " " << m_idHelperSvc->toString(tint.tubeId));
1757 continue;
1758 }
1759
1760 const MdtPrepData* prd = findMdt(ctx, id);
1761 if (prd && std::abs(prd->localPosition()[Trk::locR]) < std::abs(tint.rIntersect)) {
1762 ATH_MSG_VERBOSE(" found and removed delta, distance to wire " << tint.rIntersect << " dist to tube end "
1763 << tint.xIntersect << " "
1764 << m_idHelperSvc->toString(tint.tubeId));
1765 continue;
1766 }
1767 }
1768 ATH_MSG_VERBOSE((outoftimeVec.count(tint.tubeId) ? "Out-of-time" : "hole") << " distance to wire "
1769 << tint.rIntersect << " dist to tube end " << tint.xIntersect << " "
1770 << m_idHelperSvc->toString(tint.tubeId)<<(notBetweenHits ? "outside hits" : "between hits"));
1771
1772 holeVec.push_back(tint.tubeId);
1773 }
1774 return holeVec;
1775 }
#define ATH_MSG_ERROR(x)
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
const MdtReadoutElement * getMdtReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Gaudi::Property< bool > m_removeDeltas
Gaudi::Property< bool > m_allMdtHoles
SG::ReadCondHandleKey< Muon::MuonIntersectGeoData > m_chamberGeoKey
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_DetectorManagerKey
pointers to IdHelpers
const MdtPrepData * findMdt(const EventContext &ctx, const Identifier &id) const
const_pointer_type cptr()
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
@ layer
Definition HitInfo.h:79
@ locR
Definition ParamDefs.h:44
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)

◆ checkBoundsInXZ()

bool Muon::DCMathSegmentMaker::checkBoundsInXZ ( double xline,
double zline,
double dXdZ,
const std::vector< HitInXZ > & hits ) const
private

check whether all hits are in bounds in the XZ plane

Definition at line 1826 of file DCMathSegmentMaker.cxx.

1827 {
1828 bool ok = true;
1829
1830 // look over hits and check whether all are in bounds
1831 for (const HitInXZ& hit : hits) {
1832 bool outBounds = false;
1833 double locExX = xline + dXdZ * (hit.z - zline);
1834 if (hit.isMdt && (locExX < hit.xmin - 1. || locExX > hit.xmax + 1.)) {
1835 ok = false;
1836 outBounds = true;
1837 if (!msgLvl(MSG::DEBUG)) break;
1838 }
1839
1840 if (outBounds && msgLvl(MSG::DEBUG)) {
1841 ATH_MSG_DEBUG(" " << std::setw(65) << m_idHelperSvc->toString(hit.id) << " pos (" << std::setw(6) << (int)hit.x << ","
1842 << std::setw(6) << (int)hit.z << ") ex pos " << std::setw(6) << (int)locExX << " min " << std::setw(6)
1843 << (int)hit.xmin << " max " << std::setw(6) << (int)hit.xmax << " phimin " << std::setw(6)
1844 << hit.phimin << " phimax " << std::setw(6) << hit.phimax << " outBounds, cross-check");
1845 }
1846 }
1847 return ok;
1848 }

◆ checkPhiConsistency()

bool Muon::DCMathSegmentMaker::checkPhiConsistency ( double phi,
double phimin,
double phimax ) const
private

check whether phi is consistent with segment phi

Definition at line 2102 of file DCMathSegmentMaker.cxx.

2102 {
2103 // only if assuming pointing phi
2104 if (!m_assumePointingPhi) return true;
2105
2106 bool phiOk = true;
2107 double offset = 0.05;
2108 if (phimin * phimax < 0.) {
2109 if (phi < 0.) {
2110 if (phi > -1.1) {
2111 if (phi < phimin - offset) phiOk = false;
2112 } else {
2113 if (phi > phimin + offset) phiOk = false;
2114 }
2115 } else {
2116 if (phi > 1.1) {
2117 if (phi < phimax - offset) phiOk = false;
2118 } else {
2119 if (phi > phimax + offset) phiOk = false;
2120 }
2121 }
2122 } else {
2123 if (phi < phimin - offset || phi > phimax + offset) phiOk = false;
2124 }
2125 return phiOk;
2126 }
Scalar phi() const
phi method

◆ create1DClusters()

DCMathSegmentMaker::ClusterVecPair Muon::DCMathSegmentMaker::create1DClusters ( const std::vector< const MuonClusterOnTrack * > & clusters) const
private

Definition at line 695 of file DCMathSegmentMaker.cxx.

695 {
696 // if empty return
697 if (clusters.empty()) return {};
698 // some useful typedefs...
699
700 // create a vector to hold the clusters
701 ClusterVec clVec;
702 ClusterVec phiVec;
703 clVec.reserve(clusters.size());
704
705 for (const MuonClusterOnTrack* clust : clusters) {
706 const Identifier id = clust->identify();
707 const Identifier gasGapId = m_idHelperSvc->gasGapId(id);
708
709 if (m_idHelperSvc->measuresPhi(id)) {
710 phiVec.push_back(createSpacePoint(gasGapId, nullptr, clust));
711 if (phiVec.back().corrupt()) phiVec.pop_back();
712 } else {
713 clVec.push_back(createSpacePoint(gasGapId, clust, nullptr));
714 if (clVec.back().corrupt()) clVec.pop_back();
715 }
716 }
717
718 return ClusterVecPair(clVec, phiVec);
719 }
std::vector< Cluster2D > ClusterVec
Cluster2D createSpacePoint(const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const MuonClusterOnTrack *phiHit) const
std::pair< ClusterVec, ClusterVec > ClusterVecPair

◆ create2DClusters()

DCMathSegmentMaker::ClusterVecPair Muon::DCMathSegmentMaker::create2DClusters ( const std::vector< const MuonClusterOnTrack * > & clusters) const
private

Definition at line 721 of file DCMathSegmentMaker.cxx.

721 {
722 // if empty return
723 if (clusters.empty()) return {};
724
725 ChIdHitMap gasGapHitMap;
726 for (const MuonClusterOnTrack* clus: clusters) {
727 const Identifier id = clus->identify();
728 ATH_MSG_VERBOSE(" new trigger hit " << m_idHelperSvc->toString(id));
729
730 const Identifier chId = m_idHelperSvc->chamberId(id);
731 const Identifier gasGapId = m_idHelperSvc->gasGapId(id);
732 // eta hits first than phi hits
733 if (!m_idHelperSvc->measuresPhi(id))
734 gasGapHitMap[chId][gasGapId].first.push_back(clus);
735 else
736 gasGapHitMap[chId][gasGapId].second.push_back(clus);
737 }
738
739 return createSpacePoints(gasGapHitMap);
740 }
std::map< Identifier, IdHitMap > ChIdHitMap
ClusterVecPair createSpacePoints(const ChIdHitMap &chIdHitMap) const

◆ createChamberGeometry()

TrkDriftCircleMath::MdtChamberGeometry Muon::DCMathSegmentMaker::createChamberGeometry ( const Identifier & chid,
const Amg::Transform3D & gToStation ) const
private

Definition at line 1074 of file DCMathSegmentMaker.cxx.

1075 {
1076 /* calculate chamber geometry
1077 it takes as input:
1078 distance between the first and second tube in the chamber within a layer along the tube layer (tube distance)
1079 distance between the first tube in the first layer and the first tube in the second layer along the tube layer
1080 (tube stagering) distance between the first and second layer perpendicular to the tube layers (layer distance)
1081 position of the first hit in ml 0 and ml 1 (2D in plane)
1082 total number of multilayers
1083 total number of layers
1084 total number of tubes per layer for each multilayer
1085 an identifier uniquely identifying the chamber
1086 */
1087
1088 Amg::Vector3D firstTubeMl0{Amg::Vector3D::Zero()};
1089 Amg::Vector3D firstTubeMl1{Amg::Vector3D::Zero()};
1090
1091 // get id
1092 int eta = m_idHelperSvc->mdtIdHelper().stationEta(chid);
1093 int phi = m_idHelperSvc->mdtIdHelper().stationPhi(chid);
1094 int name = m_idHelperSvc->mdtIdHelper().stationName(chid);
1095
1096 SG::ReadCondHandle<MuonGM::MuonDetectorManager> DetectorManagerHandle{m_DetectorManagerKey};
1097 const MuonGM::MuonDetectorManager* MuonDetMgr{*DetectorManagerHandle};
1098 if (!MuonDetMgr) {
1099 ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object");
1100 return {};
1101 }
1102
1103 // get detEL for first ml (always there)
1104 const MuonGM::MdtReadoutElement* detEl1 =
1105 MuonDetMgr->getMdtReadoutElement(m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 1));
1106 const MuonGM::MdtReadoutElement* detEl2 = nullptr;
1107 int ntube2 = 0;
1108 // number of multilayers in chamber
1109 int nml = detEl1->nMDTinStation();
1110
1111 // treament of chambers with two ml
1112 if (nml == 2) {
1113 Identifier firstIdml1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 2, 1, 1);
1114 detEl2 = MuonDetMgr->getMdtReadoutElement(firstIdml1);
1115 firstTubeMl1 = gToStation * (detEl2->surface(firstIdml1).center());
1116 ntube2 = detEl2->getNtubesperlayer();
1117 }
1118
1119 // number of layers and tubes
1120 int nlay = detEl1->getNLayers();
1121 int ntube1 = detEl1->getNtubesperlayer();
1122
1123 // position first tube in ml 0
1124 Identifier firstIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 1);
1125 firstTubeMl0 = gToStation * (detEl1->surface(firstIdml0).center());
1126
1127 // position second tube in ml 0
1128 Identifier secondIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 2);
1129 Amg::Vector3D secondTubeMl0 = gToStation * (detEl1->surface(secondIdml0).center());
1130
1131 TrkDriftCircleMath::LocVec2D firstTube0(firstTubeMl0.y(), firstTubeMl0.z());
1132 TrkDriftCircleMath::LocVec2D firstTube1(firstTubeMl1.y(), firstTubeMl1.z());
1133
1134 // position first tube ml 0 and 1
1135 Identifier firstIdml0lay1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 2, 1);
1136 Amg::Vector3D firstTubeMl0lay1 = gToStation * (detEl1->surface(firstIdml0lay1).center());
1137
1138 double tubeDist = (secondTubeMl0 - firstTubeMl0).y(); // distance between tube in a given layer
1139 double tubeStage = (firstTubeMl0lay1 - firstTubeMl0).y(); // tube stagering distance
1140 double layDist = (firstTubeMl0lay1 - firstTubeMl0).z(); // distance between layers
1141
1142 TrkDriftCircleMath::MdtChamberGeometry mdtgeo(chid, m_idHelperSvc.get(), nml, nlay, ntube1, ntube2, firstTube0, firstTube1, tubeDist, tubeStage,
1143 layDist, detEl1->surface().center().theta());
1144
1145 if (msgLvl(MSG::VERBOSE)) mdtgeo.print(msgStream());
1146
1147 return mdtgeo;
1148 }
Scalar eta() const
pseudorapidity method
#define y
#define z
unsigned int nMDTinStation() const
How many MDT chambers are in the station.
int getNLayers() const
Returns the number of tube layers inside the multilayer.
int getNtubesperlayer() const
Returns the number of tubes in each tube layer.
virtual const Trk::Surface & surface() const override final
Return surface associated with this detector element.
const Amg::Vector3D & center() const
Returns the center position of the Surface.

◆ createClusterVec()

TrkDriftCircleMath::CLVec Muon::DCMathSegmentMaker::createClusterVec ( const Identifier & chid,
ClusterVec & spVec,
const Amg::Transform3D & gToStation ) const
private

Definition at line 979 of file DCMathSegmentMaker.cxx.

980 {
982
983 const int chPhi = m_idHelperSvc->mdtIdHelper().stationPhi(chid);
984
985 // loop over clusters
986 int index{-1};
987 cls.reserve(spVec.size());
988 for (const Cluster2D& clust : spVec) {
989 ++index;
990 const MuonClusterOnTrack* meas = clust.etaHit ? clust.etaHit : clust.phiHit;
991 // construct cluster id
992 const Identifier id = meas->identify();
993 const int measuresPhi = m_idHelperSvc->measuresPhi(id);
994 const int eta = m_idHelperSvc->stationEta(id);
995 const int phi = m_idHelperSvc->stationPhi(id);
996 const int isTgc = m_idHelperSvc->isTgc(id);
997 const int name = isTgc ? m_idHelperSvc->tgcIdHelper().stationName(id) : m_idHelperSvc->rpcIdHelper().stationName(id);
998 if (!isTgc) {
999 if (chPhi != phi) {
1000 ATH_MSG_VERBOSE(" Discarding cluster, wrong station phi " << m_idHelperSvc->toString(id));
1001 continue;
1002 }
1003 }
1004 TrkDriftCircleMath::ClusterId clid{name, eta, phi, isTgc, measuresPhi};
1005
1006 // calculate local cluster position
1007 Amg::Vector3D locPos = gToStation * clust.globalPos;
1008 TrkDriftCircleMath::LocVec2D lp(locPos.y(), locPos.z());
1009
1010 if (std::abs(lp.y()) > m_maxAssociateClusterDistance) {
1011 ATH_MSG_VERBOSE(" Discarding cluster with large distance from chamber " << m_idHelperSvc->toString(id));
1012 continue;
1013 }
1014 ATH_MSG_VERBOSE(" " << m_idHelperSvc->toString(id) << " clid: " << clid.id() << " central phi "
1015 << meas->detectorElement()->center().phi() << " index " << index);
1016 cls.emplace_back(lp, clust.error, clid, meas, index);
1017 }
1018 return cls;
1019 }
virtual const MuonGM::MuonClusterReadoutElement * detectorElement() const override=0
Returns the detector element, associated with the PRD of this class.
virtual const Amg::Vector3D & center() const override
Return the center of the element.
str index
Definition DeMoScan.py:362

◆ createDCVec()

TrkDriftCircleMath::DCVec Muon::DCMathSegmentMaker::createDCVec ( const std::vector< const MdtDriftCircleOnTrack * > & mdts,
double errorScale,
std::set< Identifier > & chamberSet,
double & phimin,
double & phimax,
TrkDriftCircleMath::DCStatistics & dcStatistics,
const Amg::Transform3D & gToStation,
const Amg::Transform3D & amdbToGlobal ) const
private

Definition at line 1021 of file DCMathSegmentMaker.cxx.

1024 {
1026 dcs.reserve(mdts.size());
1027 /* ******** Mdt hits ******** */
1028 bool firstMdt = true;
1029
1030 for (const MdtDriftCircleOnTrack* rot : mdts) {
1031
1032 Identifier id = rot->identify();
1033 Identifier elId = m_idHelperSvc->mdtIdHelper().elementID(id);
1034
1035 // calculate local AMDB position
1036 Amg::Vector3D locPos = gToStation * rot->prepRawData()->globalPosition();
1037 TrkDriftCircleMath::LocVec2D lpos(locPos.y(), locPos.z());
1038
1039 double r = rot->localParameters()[Trk::locR];
1040 double dr = Amg::error(rot->localCovariance(), Trk::locR) * errorScale;
1041
1042 // create identifier
1043 TrkDriftCircleMath::MdtId mdtid(m_idHelperSvc->mdtIdHelper().isBarrel(id), m_idHelperSvc->mdtIdHelper().multilayer(id) - 1,
1044 m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1, m_idHelperSvc->mdtIdHelper().tube(id) - 1);
1045
1046 //
1047 double preciseError = dr;
1048 if (m_usePreciseError) { preciseError = m_preciseErrorScale * (0.23 * std::exp(-std::abs(r) / 6.06) + 0.0362); }
1049 // create new DriftCircle
1050 TrkDriftCircleMath::DriftCircle dc(lpos, r, dr, preciseError, TrkDriftCircleMath::DriftCircle::InTime, mdtid, rot);
1051
1052 TubeEnds tubeEnds = localTubeEnds(*rot, gToStation, amdbToGlobal);
1053 if (firstMdt) {
1054 phimin = tubeEnds.phimin;
1055 phimax = tubeEnds.phimax;
1056 firstMdt = false;
1057 } else {
1058 updatePhiRanges(tubeEnds.phimin, tubeEnds.phimax, phimin, phimax);
1059 }
1060
1061 ATH_MSG_VERBOSE(" new MDT hit " << m_idHelperSvc->toString(id) << " x " << lpos.x() << " y " << lpos.y() << " time "
1062 << rot->driftTime() << " r " << r << " dr " << dr << " phi range " << tubeEnds.phimin << " "
1063 << tubeEnds.phimax<<" precise error "<<preciseError);
1064 dcs.push_back(std::move(dc));
1065
1066 chamberSet.insert(elId);
1067
1068 ++dcStatistics[rot->prepRawData()->detectorElement()];
1069 }
1070
1071 return dcs;
1072 }
Gaudi::Property< double > m_preciseErrorScale
TubeEnds localTubeEnds(const MdtDriftCircleOnTrack &mdt, const Amg::Transform3D &gToSegment, const Amg::Transform3D &segmentToG) const
calculate positions of tube ends
static void updatePhiRanges(double phiminNew, double phimaxNew, double &phiminRef, double &phimaxRef)
update phi ranges
Gaudi::Property< bool > m_usePreciseError
@ InTime
drift time too small to be compatible with drift spectrum
Definition DriftCircle.h:27
int r
Definition globals.cxx:22
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
std::vector< DriftCircle > DCVec

◆ createROTVec()

DataVector< const Trk::MeasurementBase > Muon::DCMathSegmentMaker::createROTVec ( std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > & rioDistVec)
staticprivate

Definition at line 1657 of file DCMathSegmentMaker.cxx.

1658 {
1659 // sort hits according to they distance to the segment position
1660 std::sort(rioDistVec.begin(), rioDistVec.end(), SortByDistanceToSegment());
1661
1662 DataVector<const Trk::MeasurementBase> rioVec{SG::OWN_ELEMENTS};
1663 rioVec.reserve(rioDistVec.size());
1664 for (std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) { rioVec.push_back(std::move(rdit.second)); }
1665 rioDistVec.clear();
1666 return rioVec;
1667 }
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
@ OWN_ELEMENTS
this data object owns its elements
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.

◆ createRpcSpacePoint()

DCMathSegmentMaker::Cluster2D Muon::DCMathSegmentMaker::createRpcSpacePoint ( const Identifier & gasGapId,
const MuonClusterOnTrack * etaHit,
const std::vector< const MuonClusterOnTrack * > & phiHits ) const
private

Definition at line 918 of file DCMathSegmentMaker.cxx.

919 {
920 // create vector to store phi hits after removal of duplicate hits
921 std::vector<const MuonClusterOnTrack*> cleanPhihits;
922 cleanPhihits.reserve(phiHits.size());
923
924 double error{1.}, lpx{0.}, lpy{0.};
925 // case one hit missing. Take position and error of the available hit
926 if (!etaHit) {
927 lpx = phiHits.front()->localParameters()[Trk::locX];
928 error = Amg::error(phiHits.front()->localCovariance(), Trk::locX);
929 // loop over phi hits, remove duplicate phi hits
930 Identifier prevId;
931 for (const MuonClusterOnTrack* clus : phiHits) {
932 // remove duplicate phi hits
933 if (clus->identify() == prevId) continue;
934 prevId = clus->identify();
935 cleanPhihits.push_back(clus);
936 }
937 } else if (phiHits.empty()) {
938 lpx = etaHit->localParameters()[Trk::locX];
939 error = Amg::error(etaHit->localCovariance(), Trk::locX);
940 } else if (etaHit && !phiHits.empty()) {
941 lpx = etaHit->localParameters()[Trk::locX];
942 error = Amg::error(etaHit->localCovariance(), Trk::locX);
943
944 ATH_MSG_DEBUG(" RPC space point: error " << error << " stripWith " << error * M_SQRT2 << std::endl
945 << " " << m_idHelperSvc->toString(etaHit->identify()));
946
947 double minPos{1e9}, maxPos{-1e9};
948 Identifier prevId;
949
950 // loop over phi hits, calculate average position + cluster width, remove duplicate phi hits
951 for (const MuonClusterOnTrack* phiHit : phiHits) {
952 // remove duplicate phi hits
953 if (phiHit->identify() == prevId) continue;
954 prevId = phiHit->identify();
955
956 // calculate phi hit position in local eta hit reference frame
957 Amg::Vector2D phiLocPos{Amg::Vector2D::Zero()};
958 if (etaHit->associatedSurface().globalToLocal(phiHit->globalPosition(), phiHit->globalPosition(), phiLocPos)) {
959 lpy = phiLocPos[Trk::locY];
960 minPos = std::min(minPos, lpy);
961 maxPos = std::max(maxPos, lpy);
962 ATH_MSG_DEBUG(" " << m_idHelperSvc->toString(phiHit->identify()));
963 cleanPhihits.push_back(phiHit);
964 }
965 }
966 if (cleanPhihits.size() > 1)
967 ATH_MSG_DEBUG(" multiple phi hits: nhits " << cleanPhihits.size() << " cl width " << maxPos - minPos);
968 } else {
969 ATH_MSG_DEBUG(" ARRRGGG got two empty pointers!!! ");
970 }
971 Identifier detElId = m_idHelperSvc->detElId(gasGapId);
972 if (std::abs(error) < 0.001) {
973 ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId));
974 error = 1.;
975 }
976 return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, !cleanPhihits.empty() ? cleanPhihits : phiHits);
977 }
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37

◆ createSegment()

std::unique_ptr< MuonSegment > Muon::DCMathSegmentMaker::createSegment ( const EventContext & ctx,
TrkDriftCircleMath::Segment & segment,
const Identifier & chid,
const Amg::Vector3D & roadpos,
const Amg::Vector3D & roaddir2,
const std::vector< const MdtDriftCircleOnTrack * > & mdts,
bool hasPhiMeasurements,
segmentCreationInfo & sInfo,
double beta = 1. ) const
private

Use linearity of the sin at leading order to check that the angular differences are either 0 or PI

Copy hits into vector

recalculate global direction and position

Definition at line 228 of file DCMathSegmentMaker.cxx.

231 {
232 bool isEndcap = m_idHelperSvc->isEndcap(chid);
233 // find all curved segments
234 MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chid);
235
236 static constexpr std::array<ChIndex ,4> statWithField{ChIndex::BIL, ChIndex::BML, ChIndex::BMS, ChIndex::BOL};
237 const bool isCurvedSegment = segment.hasCurvatureParameters() &&
238 std::ranges::find(statWithField, chIndex) != statWithField.end();
239
240 // remove segments with too few hits
241 if (segment.hitsOnTrack() < 3) return nullptr;
242
243 // convert segment parameters + x position from road
244 const TrkDriftCircleMath::Line& line = segment.line();
245
246 ATH_MSG_DEBUG("New segment: chi2 " << segment.chi2() << " ndof " << segment.ndof() << " line " << line.position().x() << ","
247 << line.position().y() << " phi " << line.phi() << " associated clusters "
248 << segment.clusters().size());
249
250 // local position along x from road
251 Amg::Vector3D lroadpos = sInfo.globalTrans * roadpos;
252 Amg::Vector3D lroaddir = sInfo.globalTrans.linear() * roaddir2;
253
254 // local x position of first tube used if no phi measurement is present
255 double lxroad = 0.;
256
257 if (hasPhiMeasurements) {
258 // calculate local position of segment along tube using the road
259 // calculate intersect pattern measurement plane
260 double sphi = 0.;
261 double cphi = lroaddir.x();
262 // swap local y and z in the endcaps
263 if (isEndcap) {
264 sphi = lroaddir.y();
265 lxroad = lroadpos.x() + (-lroadpos.y() + line.position().x()) * cphi / absmax(sphi, std::numeric_limits<double>::min());
266 } else {
267 sphi = lroaddir.z();
268 lxroad = lroadpos.x() + (-lroadpos.z() + line.position().y()) * cphi / absmax(sphi, std::numeric_limits<double>::min());
269 }
270
271 double shortestTubeLen = 1e9;
272 // loop over hits and get the shortest tube on the segment
273 for (const TrkDriftCircleMath::DCOnTrack& driftCircle : segment.dcs()) {
275
276 const MdtDriftCircleOnTrack* riodc{driftCircle.rot()};
277 int lay = m_idHelperSvc->mdtIdHelper().tubeLayer(riodc->identify());
278 int tube = m_idHelperSvc->mdtIdHelper().tube(riodc->identify());
279 double tubelen = 0.5 * riodc->prepRawData()->detectorElement()->getActiveTubeLength(lay, tube);
280 if (tubelen < shortestTubeLen) shortestTubeLen = tubelen;
281 }
282 // if the predicted position lies outside the chamber move it back inside
283 if (std::abs(lxroad) > shortestTubeLen) {
284 ATH_MSG_DEBUG("coordinates far outside chamber! using global position of first hit ");
285 if (lxroad < 0.) shortestTubeLen *= -1.;
286 lxroad = shortestTubeLen;
287 }
288 } else {
289 lxroad = (sInfo.globalTrans * mdts[0]->prepRawData()->detectorElement()->surface(mdts[0]->identify()).center()).x();
290 }
291
292 // calculate local direction vector
293 Amg::Vector3D lpos(lxroad, line.position().x(), line.position().y());
294
295 // global position segment
296 Amg::Vector3D gpos = sInfo.amdbTrans * lpos;
297
298 // create new surface
299 Amg::Transform3D surfaceTransform(sInfo.amdbTrans.rotation());
300 surfaceTransform.pretranslate(gpos);
301 double surfDim = 500.;
302 std::unique_ptr<Trk::PlaneSurface> surf = std::make_unique<Trk::PlaneSurface>(surfaceTransform, surfDim, surfDim);
303
304 // measurements
305 Amg::Vector2D segLocPos{Amg::Vector2D::Zero()};
306 double linephi = line.phi();
307
308 // now update the global direction using the local precision angle of the segment and the global phi angle of the
309 // road.
310 Amg::Vector3D gdir = updateDirection(linephi, *surf, roaddir2, isCurvedSegment);
311
312 // extract RIO_OnTracks
313 std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>> > rioDistVec; // vector to store the distance of a ROT to the segment
314
315 // associate MDT hits to segment
316 std::set<Identifier> deltaVec;
317 std::set<Identifier> outoftimeVec;
318
319 associateMDTsToSegment(gdir, segment, sInfo.geom, sInfo.globalTrans, sInfo.amdbTrans, deltaVec, outoftimeVec, rioDistVec, beta);
320 std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>> garbage_collector;
321
322 TrkDriftCircleMath::DCSLHitSelector hitSelector;
323
324 if (m_redo2DFit && !isCurvedSegment) {
325 // refit segment after recalibration
326 TrkDriftCircleMath::DCSLFitter defaultFitter;
327 TrkDriftCircleMath::Segment result(TrkDriftCircleMath::Line{0.,0.,0.}, TrkDriftCircleMath::DCOnTrackVec());
328 bool goodFit = defaultFitter.fit(result, line, segment.dcs(), hitSelector.selectHitsOnTrack(segment.dcs()));
329 if (goodFit) {
330 if (std::abs(xAOD::P4Helpers::deltaPhi(segment.line().phi(), result.line().phi())) > 0.01 ||
331 std::abs(segment.line().x0() - result.line().x0()) > 0.01 ||
332 std::abs(segment.line().y0() - result.line().y0()) > 0.01) {
333 // update local position and global
334 linephi = result.line().phi();
335 lpos[1] = result.line().position().x();
336 lpos[2] = result.line().position().y();
337 gpos = sInfo.amdbTrans * lpos;
338
339 // recreate surface
340 surfaceTransform = Amg::Transform3D(sInfo.amdbTrans.rotation());
341 surfaceTransform.pretranslate(gpos);
342 surf = std::make_unique<Trk::PlaneSurface>(surfaceTransform, surfDim, surfDim);
343
344 // finally update global direction
345 gdir = updateDirection(linephi, *surf, roaddir2, isCurvedSegment);
346 }
347 }
348 }
349
350 // create local segment direction
351 Trk::LocalDirection segLocDir;
352 surf->globalToLocalDirection(gdir, segLocDir);
353 if (segLocDir.angleYZ() == 0 && segLocDir.angleXZ() == 0) {
354 ATH_MSG_DEBUG("invalid local direction");
355 return nullptr;
356 }
357
358 // sanity checks
359 const double diff_phi = xAOD::P4Helpers::deltaPhi(roaddir2.phi(), gdir.phi());
360 const double diff_prec = xAOD::P4Helpers::deltaPhi(linephi, segLocDir.angleYZ());
362 if (std::min(std::abs(diff_phi), std::abs( std::abs(diff_phi) - M_PI)) > 1.e-3 ||
363 std::min(std::abs(diff_prec), std::abs(std::abs(diff_prec) - M_PI)) > 1.e-3) {
364 ATH_MSG_WARNING(" ALARM updated angles wrong: diff phi " << diff_phi << " prec " << diff_prec << " phi rdir " << roaddir2.phi()
365 << " gdir " << gdir.phi() << " lphi " << linephi << " seg "
366 << segLocDir.angleYZ());
367 }
368
369 // associate Clusters to segment, uses spVecs to get clusters
370 std::pair<std::pair<int, int>, bool> netaPhiHits =
371 associateClustersToSegment(segment, chid, sInfo.globalTrans, sInfo.clusters, sInfo.phimin, sInfo.phimax, rioDistVec);
372
373 if (rioDistVec.empty()){
374 ATH_MSG_VERBOSE("No measurements were collected.");
375 return nullptr;
376
377 }
379 auto meas_for_fit = [&rioDistVec] () {
380 std::vector<const Trk::MeasurementBase*> out{};
381 out.reserve(rioDistVec.size());
382 std::sort(rioDistVec.begin(), rioDistVec.end(), SortByDistanceToSegment());
383 for (const std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>& ele : rioDistVec) out.push_back(ele.second.get());
384 return out;
385 };
386
387
388 double dlocx{1000.}, dangleXZ{1000.}, qoverp{-99999.}, dqoverp{-99999.};
389 bool hasMeasuredCoordinate = false;
390 if (m_refitParameters && netaPhiHits.second) {
391 ATH_MSG_DEBUG(" distance between first and last phi hit sufficient to perform 4D fit: phi " << gdir.phi() << " theta "
392 << gdir.theta());
393
394 std::unique_ptr<Trk::Track> track{m_segmentFitter->fit(gpos, gdir, *surf, meas_for_fit())};
395
396 if (track) {
397 if (isCurvedSegment && track->perigeeParameters() && track->perigeeParameters()->covariance()) {
398 qoverp = track->perigeeParameters()->parameters()[Trk::qOverP];
399 dqoverp = Amg::error(*track->perigeeParameters()->covariance(), Trk::qOverP);
400 }
401 hasMeasuredCoordinate = true;
402 // hack to update the second coordinate errors
403 Amg::MatrixX updatedCov(5, 5);
404 updatedCov.setZero();
405 m_segmentFitter->updateSegmentParameters(*track, *surf, segLocPos, segLocDir, updatedCov);
406 if (Amg::error(updatedCov, Trk::locX) > 0 && Amg::error(updatedCov, Trk::phi) > 0.) {
407 dlocx = Amg::error(updatedCov, Trk::locX);
408 dangleXZ = Amg::error(updatedCov, Trk::phi); // hack (2): phi not always angleXZ
409 } else {
410 ATH_MSG_WARNING(" Corrupt error matrix returned from fitter " << Amg::toString(updatedCov));
411 }
412
414 surf->localToGlobal(segLocPos, gdir, gpos);
415 surf->localToGlobalDirection(segLocDir, gdir);
416
417 if (track->measurementsOnTrack() && rioDistVec.size() != track->measurementsOnTrack()->size()) {
418 if (track->measurementsOnTrack()->empty()) {
419 ATH_MSG_DEBUG("No measurements survived");
420 return nullptr;
421 }
422 ATH_MSG_DEBUG(" ROT vector size changed after fit, updating ");
423 garbage_collector = std::move(rioDistVec);
424 rioDistVec.reserve(track->measurementsOnTrack()->size());
425 const Trk::TrackParameters* firstPars = nullptr;
426 for (const Trk::TrackStateOnSurface* tsit : *track->trackStateOnSurfaces()) {
427 const Trk::TrackParameters* pars = tsit->trackParameters();
428 if (!pars) continue;
429 if (!firstPars) firstPars = pars;
430
431 // check whether state is a measurement, skip outliers if they are not MDT
432 const Trk::MeasurementBase* meas = tsit->measurementOnTrack();
433 if (!meas) continue;
434 if (tsit->type(Trk::TrackStateOnSurface::Outlier) && !dynamic_cast<const MdtDriftCircleOnTrack*>(meas)) continue;
435 double dist = (pars->position() - firstPars->position()).dot(firstPars->momentum().unit());
436 rioDistVec.emplace_back(dist, meas->uniqueClone());
437 }
438 }
439 } else {
440 ATH_MSG_DEBUG(" refit of segment failed!! ");
441 netaPhiHits.second = false;
442 }
443 }
444
445 // optional update of phi position and direction, only performed if the segment was not refitted and there are phi
446 // hits
447 if (m_updatePhiUsingPhiHits && !netaPhiHits.second) {
448 if (updateSegmentPhi(gpos, gdir, segLocPos, segLocDir, *surf, meas_for_fit(), sInfo.phimin, sInfo.phimax)) {
449 surf->localToGlobal(segLocPos, gpos, gpos);
450 surf->localToGlobalDirection(segLocDir, gdir);
451 hasMeasuredCoordinate = true;
452 dlocx = 100.;
453 dangleXZ = 0.1;
454 }
455 }
456
457 if (msgLvl(MSG::DEBUG)) {
458 std::vector<const Trk::MeasurementBase*> debug_meas = meas_for_fit();
459 ATH_MSG_DEBUG(" number of hits " << debug_meas.size() << " of which trigger " << netaPhiHits.first.first << " eta and "
460 << netaPhiHits.first.second << " phi ");
461 for (const Trk::MeasurementBase* mit : debug_meas) {
462 const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(mit);
463 if (rot) {
464 ATH_MSG_DEBUG(m_idHelperSvc->toString(rot->identify()));
465 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(rot);
466 if (mdt)
467 ATH_MSG_DEBUG(std::setprecision(4)
468 << " radius " << std::setw(6) << mdt->driftRadius() << " time " << std::setw(6) << mdt->driftTime());
469 continue;
470 }
471 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(mit);
472 if (crot) {
473 ATH_MSG_DEBUG(m_idHelperSvc->toString(crot->rioOnTrack(0).identify())
474 << " comp rot with hits " << crot->containedROTs().size());
475 continue;
476 }
477 ATH_MSG_WARNING("failed to dynamic_cast to ROT ");
478 }
479 }
480 // recalculate holes
481 std::vector<Identifier> holeVec = calculateHoles(ctx, chid, gpos, gdir, hasMeasuredCoordinate, deltaVec, outoftimeVec, rioDistVec);
482
483 // currently not taking into account masked channels
484 if (!outoftimeVec.empty()) holeVec.insert(holeVec.end(), std::make_move_iterator(outoftimeVec.begin()),
485 std::make_move_iterator(outoftimeVec.end()));
486 MuonSegmentQuality* quality = new MuonSegmentQuality(segment.chi2(), segment.ndof(), holeVec);
487
488 const TrkDriftCircleMath::DCSLFitter* dcslFitter = m_dcslFitProvider->getFitter();
489 TrkDriftCircleMath::Segment result(TrkDriftCircleMath::Line{0., 0., 0.}, TrkDriftCircleMath::DCOnTrackVec());
490 if (dcslFitter && !segment.hasT0Shift() && m_outputFittedT0) {
491 if (!dcslFitter->fit(result, segment.line(), segment.dcs(), hitSelector.selectHitsOnTrack(segment.dcs()))) {
492 ATH_MSG_DEBUG(" T0 refit failed ");
493 } else {
494 ATH_MSG_DEBUG(" Fitted T0 " << result.t0Shift()<<" is valid "<<result.hasT0Shift());
495 }
496 }
497 bool hasFittedT0 = false;
498 double fittedT0{0}, errorFittedT0{1.};
499 if (m_outputFittedT0 && (segment.hasT0Shift() || (dcslFitter && result.hasT0Shift()))) {
500 hasFittedT0 = true;
501 if (segment.hasT0Shift()) {
502 fittedT0 = segment.t0Shift();
503 errorFittedT0 = segment.t0Error();
504 } else if (dcslFitter && result.hasT0Shift()) {
505 fittedT0 = result.t0Shift();
506 errorFittedT0 = result.t0Error();
507 } else {
508 ATH_MSG_WARNING(" Failed to access fitted t0 ");
509 hasFittedT0 = false;
510 }
511 }
512 // create new segment
513 std::unique_ptr<MuonSegment> msegment;
514 if (isCurvedSegment) { // curved segments
515 if (qoverp == -99999.) {
516 double charge = gpos.z() * std::tan(gdir.theta());
517 charge = charge / std::abs(charge);
518 // if the curved segment was not refit, then use a momentum estimate
519 constexpr double BILALPHA(28.4366), BMLALPHA(62.8267), BMSALPHA(53.1259), BOLALPHA(29.7554);
520 if (chIndex == ChIndex::BIL) {
521 qoverp = (charge * segment.deltaAlpha()) / BILALPHA;
522 dqoverp = M_SQRT2 * segment.dtheta() / BILALPHA;
523 } else if (chIndex == ChIndex::BML) {
524 qoverp = (charge * segment.deltaAlpha()) / BMLALPHA;
525 dqoverp = M_SQRT2 * segment.dtheta() / BMLALPHA;
526 } else if (chIndex == ChIndex::BMS) {
527 qoverp = (charge * segment.deltaAlpha()) / BMSALPHA;
528 dqoverp = M_SQRT2 * segment.dtheta() / BMSALPHA;
529 } else if (chIndex == ChIndex::BOL) {
530 qoverp = (charge * segment.deltaAlpha()) / BOLALPHA;
531 dqoverp = M_SQRT2 * segment.dtheta() / BOLALPHA;
532 }
533 }
535 covMatrix.setIdentity();
536 covMatrix(0, 0) = dlocx * dlocx;
537 covMatrix(1, 1) = segment.dy0() * segment.dy0();
538 covMatrix(2, 2) = dangleXZ * dangleXZ;
539 covMatrix(3, 3) = segment.dtheta() * segment.dtheta();
540 covMatrix(4, 4) = dqoverp * dqoverp;
541
542 std::vector<Trk::DefinedParameter> defPars;
543 defPars.emplace_back(segLocPos[Trk::loc1], Trk::loc1);
544 defPars.emplace_back(segLocPos[Trk::loc2], Trk::loc2);
545 defPars.emplace_back(gdir.phi(), Trk::phi);
546 defPars.emplace_back(gdir.theta(), Trk::theta);
547 defPars.emplace_back(qoverp, Trk::qOverP);
548 Trk::LocalParameters segLocPar(defPars);
549 msegment = std::make_unique<MuonSegment>(
550 std::move(segLocPar),
551 std::move(covMatrix),
552 surf.release(),
553 createROTVec(rioDistVec),
554 quality,
556 } else { // straight segments
557 // errors (for now no correlations)
559 covMatrix.setIdentity();
560 covMatrix(0, 0) = dlocx * dlocx;
561 covMatrix(1, 1) = segment.dy0() * segment.dy0();
562 covMatrix(2, 2) = dangleXZ * dangleXZ;
563 covMatrix(3, 3) = segment.dtheta() * segment.dtheta();
564 msegment =
565 std::make_unique<MuonSegment>(segLocPos,
566 segLocDir,
567 std::move(covMatrix),
568 surf.release(),
569 createROTVec(rioDistVec),
570 quality,
572 }
573
574 if (hasFittedT0) msegment->setT0Error(fittedT0, errorFittedT0);
575
576 // check whether segment satisfies minimum quality criteria
577 int segmentQuality = m_segmentSelectionTool->quality(*msegment);
578
579 if (msgLvl(MSG::DEBUG)) {
580 ATH_MSG_DEBUG(m_printer->print(*msegment) << " quality " << segmentQuality);
581 if (segmentQuality < 0) ATH_MSG_DEBUG(" BAD segment ");
582 if (hasFittedT0) ATH_MSG_DEBUG(" T0 " << fittedT0);
583 if (isCurvedSegment) ATH_MSG_DEBUG(" Curved " << fittedT0);
584 }
585 if (segmentQuality < 0) { return nullptr; }
586 return msegment;
587 }
#define M_PI
double charge(const T &p)
Definition AtlasPID.h:997
Gaudi::Property< bool > m_updatePhiUsingPhiHits
ToolHandle< IDCSLFitProvider > m_dcslFitProvider
Amg::Vector3D updateDirection(double linephi, const Trk::PlaneSurface &surf, const Amg::Vector3D &roaddir, bool isCurvedSegment) const
update the global direction, keeping the phi of the input road direction but using the local angle YZ
ToolHandle< IMuonSegmentSelectionTool > m_segmentSelectionTool
Gaudi::Property< bool > m_outputFittedT0
ToolHandle< IMuonSegmentFittingTool > m_segmentFitter
Gaudi::Property< bool > m_redo2DFit
Gaudi::Property< bool > m_refitParameters
bool updateSegmentPhi(const Amg::Vector3D &gpos, const Amg::Vector3D &gdir, Amg::Vector2D &segLocPos, Trk::LocalDirection &segLocDir, Trk::PlaneSurface &surf, const std::vector< const Trk::MeasurementBase * > &rots, double phimin, double phimax) const
void associateMDTsToSegment(const Amg::Vector3D &gdir, TrkDriftCircleMath::Segment &segment, const TrkDriftCircleMath::ChamberGeometry *multiGeo, const Amg::Transform3D &gToStation, const Amg::Transform3D &amdbToGlobal, std::set< Identifier > &deltaVec, std::set< Identifier > &outoftimeVec, std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec, double beta=1.) const
std::pair< std::pair< int, int >, bool > associateClustersToSegment(const TrkDriftCircleMath::Segment &segment, const Identifier &chid, const Amg::Transform3D &gToStation, ClusterVecPair &spVecs, double phimin, double phimax, std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec) const
static DataVector< const Trk::MeasurementBase > createROTVec(std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec)
std::vector< Identifier > calculateHoles(const EventContext &ctx, Identifier chid, const Amg::Vector3D &gpos, const Amg::Vector3D &gdir, bool hasMeasuredCoordinate, std::set< Identifier > &deltaVec, std::set< Identifier > &outoftimeVec, const std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec) const
virtual bool fit(Segment &result, const Line &line, const DCOnTrackVec &dcs, double t0Seed=-99999.) const
const HitSelection selectHitsOnTrack(const DCOnTrackVec &dcs) const
double x0() const
Definition Line.h:63
double phi() const
Definition Line.h:62
double y0() const
Definition Line.h:64
double angleXZ() const
access method for angle of local XZ projection
double angleYZ() const
access method for angle of local YZ projection
std::unique_ptr< MeasurementBase > uniqueClone() const
NVI Clone giving up unique pointer.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Affine3d Transform3D
ChIndex chIndex(const std::string &index)
convert ChIndex name string to enum
ChIndex
enum to classify the different chamber layers in the muon spectrometer
std::vector< DCOnTrack > DCOnTrackVec
Definition DCOnTrack.h:59
@ driftCircle
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ loc2
generic first and second local coordinate
Definition ParamDefs.h:35
@ phi
Definition ParamDefs.h:75
@ loc1
Definition ParamDefs.h:34
ParametersBase< TrackParametersDim, Charged > TrackParameters
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
const Identifier & identify(const UncalibratedMeasurement *meas)
Returns the associated identifier from the muon measurement.

◆ createSpacePoint()

DCMathSegmentMaker::Cluster2D Muon::DCMathSegmentMaker::createSpacePoint ( const Identifier & gasGapId,
const MuonClusterOnTrack * etaHit,
const MuonClusterOnTrack * phiHit ) const
private

Definition at line 845 of file DCMathSegmentMaker.cxx.

846 {
847 bool isEndcap = m_idHelperSvc->isEndcap(gasGapId);
848 double error{1.}, lpx{0.}, lpy{0.};
849 // case one hit missing. Take position and error of the available hit
850 if (!etaHit) {
851 if (!phiHit) {
852 ATH_MSG_WARNING("Both eta and phi hits missing");
853 error = 0;
854 } else {
855 lpx = phiHit->localParameters()[Trk::locX];
856 error = Amg::error(phiHit->localCovariance(), Trk::locX);
857 }
858 } else if (!phiHit) {
859 lpx = etaHit->localParameters()[Trk::locX];
860 error = Amg::error(etaHit->localCovariance(), Trk::locX);
861 } else if (etaHit && phiHit) {
862 if (isEndcap) {
863 return createTgcSpacePoint(gasGapId, etaHit, phiHit);
864 } else {
865 std::vector<const MuonClusterOnTrack*> phiVec{phiHit};
866 return createRpcSpacePoint(gasGapId, etaHit, phiVec);
867 }
868 }
869 Identifier detElId = m_idHelperSvc->detElId(gasGapId);
870 if (std::abs(error) < 0.001) {
871 ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId));
872 error = 0.;
873 }
874 return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, phiHit);
875 }
Cluster2D createTgcSpacePoint(const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const MuonClusterOnTrack *phiHit) const
Cluster2D createRpcSpacePoint(const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const std::vector< const MuonClusterOnTrack * > &phiHits) const

◆ createSpacePoints() [1/2]

DCMathSegmentMaker::ClusterVecPair Muon::DCMathSegmentMaker::createSpacePoints ( const ChIdHitMap & chIdHitMap) const
private

Definition at line 742 of file DCMathSegmentMaker.cxx.

742 {
743 // vector to store output
744 ClusterVec spacePoints{}, phiVec{};
745 spacePoints.reserve(20);
746 phiVec.reserve(20);
747 // loop over chambers
748 for ( const auto& [id, gasGapHits] : chIdHitMap) {
749 // create clusters per chamber and copy them in to result vector
751 std::copy(std::make_move_iterator(cls.first.begin()),
752 std::make_move_iterator(cls.first.end()), std::back_inserter(spacePoints));
753 std::copy(std::make_move_iterator(cls.second.begin()),
754 std::make_move_iterator(cls.second.end()), std::back_inserter(phiVec));
755 }
756
757 return std::make_pair(std::move(spacePoints), std::move(phiVec));
758 }

◆ createSpacePoints() [2/2]

DCMathSegmentMaker::ClusterVecPair Muon::DCMathSegmentMaker::createSpacePoints ( const IdHitMap & gasGapHitMap) const
private

Definition at line 760 of file DCMathSegmentMaker.cxx.

760 {
761 ClusterVec spacePoints{}, phiVec{};
762 bool isEndcap = m_idHelperSvc->isEndcap((*(gasGapHitMap.begin())).first);
763
764 ATH_MSG_VERBOSE(" creating Space points for " << gasGapHitMap.size() << " gas gaps ");
765
766 for (const auto& [gasGapId, etaPhiHits] : gasGapHitMap) {
767 // flag whether phi hits are matched with a eta hit
768 std::vector<bool> flagPhihit(etaPhiHits.second.size(), 0);
769
770 // store Identifier of previous hit to remove duplicates
771 Identifier prevEtaId;
772
773 ATH_MSG_VERBOSE(" New gasgap " << m_idHelperSvc->toString(gasGapId) << " neta " << etaPhiHits.first.size() << " nphi "
774 << etaPhiHits.second.size());
775
776 for (const MuonClusterOnTrack* etaHit : etaPhiHits.first) {
777 // check whether we are not dealing with a duplicate hit
778 if (etaHit->identify() == prevEtaId) continue;
779 prevEtaId = etaHit->identify();
780
781 ATH_MSG_VERBOSE(" Eta hit " << m_idHelperSvc->toString(etaHit->identify()));
782
783 if (isEndcap) {
784 // check whether match with phi hits was found
785 bool foundSP = false;
786 Identifier prevPhiId;
787 int phi_idx{-1};
788 for (const MuonClusterOnTrack* phiHit : etaPhiHits.second) {
789 // check for duplicate phi hits
790 ++phi_idx;
791 if (phiHit->identify() == prevPhiId) continue;
792 prevPhiId = phiHit->identify();
793
794 ATH_MSG_VERBOSE(" Phi hit " << m_idHelperSvc->toString(phiHit->identify()));
795
796 Cluster2D sp = createTgcSpacePoint(gasGapId, etaHit, phiHit);
797 if (sp.corrupt()) continue;
798 spacePoints.push_back(std::move(sp));
799 // mark as used
800 foundSP = true;
801 flagPhihit[phi_idx] = true;
802 }
803
804 // add single eta hit if not matching phi hit was found
805 if (!foundSP) {
806 Cluster2D sp = createSpacePoint(gasGapId, etaHit, nullptr);
807 if (sp.corrupt()) continue;
808 spacePoints.push_back(std::move(sp));
809 }
810 } else {
811 Cluster2D sp = createRpcSpacePoint(gasGapId, etaHit, etaPhiHits.second);
812 if (sp.corrupt()) continue;
813 // flag all phi hits, not very elegant, but works
814 flagPhihit = std::vector<bool>(etaPhiHits.second.size(), 1);
815 spacePoints.push_back(std::move(sp));
816 }
817 }
818 if (isEndcap) {
819 // loop over flag vector and add unmatched phi hits to phiVec;
820 Identifier prevPhiId;
821 for (unsigned int i = 0; i < flagPhihit.size(); ++i) {
822 if (flagPhihit[i]) continue;
823
824 // check for duplicate phi hits
825 if (etaPhiHits.second[i]->identify() == prevPhiId) continue;
826 prevPhiId = etaPhiHits.second[i]->identify();
827
828 Cluster2D sp = createTgcSpacePoint(gasGapId, nullptr, etaPhiHits.second[i]);
829 if (sp.corrupt()) continue;
830 phiVec.push_back(std::move(sp));
831 }
832 } else if (etaPhiHits.first.empty() && !etaPhiHits.second.empty()) {
833 // if there were no eta hits create one phi spacePoint of all phi hits in gasgap
834 Cluster2D sp = createRpcSpacePoint(gasGapId, nullptr, etaPhiHits.second);
835 if (sp.corrupt()) continue;
836 phiVec.push_back(std::move(sp));
837 }
838 }
839
840 ATH_MSG_VERBOSE(" Creating space points, number of gas-gaps " << gasGapHitMap.size() << " space points " << spacePoints.size());
841
842 return std::make_pair(std::move(spacePoints), std::move(phiVec));
843 }

◆ createTgcSpacePoint()

DCMathSegmentMaker::Cluster2D Muon::DCMathSegmentMaker::createTgcSpacePoint ( const Identifier & gasGapId,
const MuonClusterOnTrack * etaHit,
const MuonClusterOnTrack * phiHit ) const
private

Definition at line 877 of file DCMathSegmentMaker.cxx.

879 {
880 double error{1.}, lpx{0.}, lpy{0.};
881 Identifier detElId = m_idHelperSvc->detElId(gasGapId);
882 // case one hit missing. Take position and error of the available hit
883 if (!etaHit) {
884 lpx = phiHit->localParameters()[Trk::locX];
885 error = Amg::error(phiHit->localCovariance(), Trk::locX);
886 } else if (!phiHit) {
887 lpx = etaHit->localParameters()[Trk::locX];
888 error = Amg::error(etaHit->localCovariance(), Trk::locX);
889 } else if (etaHit && phiHit) {
890 // get orientation angle of strip to rotate back from local frame to strip
891 // copy code from ROT creator
892 const MuonGM::TgcReadoutElement* detEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(etaHit->detectorElement());
893 const Amg::Vector3D lSpacePoint = Amg::getRotateZ3D(-90 * Gaudi::Units::deg) * detEl->localSpacePoint(phiHit->identify(),
894 etaHit->globalPosition(),
895 phiHit->globalPosition());
896
897
898 lpx = lSpacePoint.x();
899 lpy = lSpacePoint.y();
900 error = Amg::error(etaHit->localCovariance(), Trk::locX);
901 if (error <= std::numeric_limits<double>::epsilon()) {
902 ATH_MSG_WARNING(" Unphysical error assigned for " << m_idHelperSvc->toString(etaHit->identify()));
903 if (etaHit->prepRawData())
904 ATH_MSG_WARNING(" PRD error " << Amg::error(etaHit->prepRawData()->localCovariance(), Trk::locX));
905 }
906 ATH_MSG_DEBUG(" TGC space point: error " << error << " stripWith " << error * M_SQRT2 << std::endl
907 << " " << m_idHelperSvc->toString(etaHit->identify()) << std::endl
908 << " " << m_idHelperSvc->toString(phiHit->identify()));
909 }
910 if (std::abs(error) < 0.001) {
911 ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId));
912 error = 1.;
913 }
914 ATH_MSG_VERBOSE("New space point for "<<m_idHelperSvc->toStringGasGap(gasGapId)<<" at ("<<lpx<<","<<lpy<<")");
915 return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, phiHit);
916 }
virtual const MuonCluster * prepRawData() const override=0
Returns the Trk::PrepRawData - is a MuonCluster in this scope.
Amg::Vector3D localSpacePoint(const Identifier &stripId, const Amg::Vector3D &etaHitPos, const Amg::Vector3D &phiHitPos) const
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis

◆ distanceToSegment()

double Muon::DCMathSegmentMaker::distanceToSegment ( const TrkDriftCircleMath::Segment & segment,
const Amg::Vector3D & hitPos,
const Amg::Transform3D & gToStation )
staticprivate

Definition at line 1634 of file DCMathSegmentMaker.cxx.

1635 {
1636 const TrkDriftCircleMath::Line& line = segment.line();
1637 TrkDriftCircleMath::TransformToLine toLine(line);
1638 double cos_sinLine = cot(line.phi());
1639
1640 // calculate local AMDB position
1641 Amg::Vector3D locPos = gToStation * hitPos;
1642
1643 TrkDriftCircleMath::LocVec2D lpos(locPos.y(), locPos.z());
1644
1645 // calculate distance of segment to measurement surface
1646 double delta_y = lpos.y() - line.position().y();
1647
1648 // calculate position of hit in line frame
1649 TrkDriftCircleMath::LocVec2D lineSurfaceIntersect(delta_y * cos_sinLine + line.position().x(), lpos.y());
1650
1651 // calculate position of hit in line frame
1652 TrkDriftCircleMath::LocVec2D pointOnHit = toLine.toLine(lineSurfaceIntersect);
1653
1654 return pointOnHit.x();
1655 }

◆ errorScaleFactor()

double Muon::DCMathSegmentMaker::errorScaleFactor ( const Identifier & id,
double curvature,
bool hasPhiMeasurements ) const
private

calculate error scaling factor

Definition at line 644 of file DCMathSegmentMaker.cxx.

644 {
645 double scale = 1.;
646 if (!m_curvedErrorScaling) return scale;
647
648 if (!errorScalingRegion(id)) return scale;
649
650 double scaleMax = 5.;
651 if (m_curvedErrorScaling && curvature > 2) {
652 scale = std::min(scaleMax, 1. + curvature / 10000);
653 ATH_MSG_DEBUG(" rescaled errors " << scale << " curvature " << curvature);
654 }
655 scale *= 2;
656
657 // rescale errors is no phi measurement was found
658 if (!hasPhiMeasurements) {
659 double phiScale = 1.;
660 // rescale errors
661 int stRegion = m_idHelperSvc->mdtIdHelper().stationRegion(id);
662 if (stRegion == 0)
663 phiScale = 2.; // inner
664 else if (stRegion == 1)
665 phiScale = 2.5; // extended
666 else if (stRegion == 2)
667 phiScale = 2.5; // middle
668 else
669 phiScale = 3.; // outer
670 scale = std::sqrt(scale*scale + phiScale*phiScale);
671 ATH_MSG_DEBUG(" rescaled error for missing phi road " << scale);
672 }
673
674 return scale;
675 }
bool errorScalingRegion(const Identifier &id) const
apply error scaling for low mometum tracks
Gaudi::Property< bool > m_curvedErrorScaling

◆ errorScalingRegion()

bool Muon::DCMathSegmentMaker::errorScalingRegion ( const Identifier & id) const
private

apply error scaling for low mometum tracks

Definition at line 677 of file DCMathSegmentMaker.cxx.

679 {
680 // simple division of MuonSpectrometer in regions using barrel/endcap seperation plus
681 // inner/middle/outer seperation
682
683 bool isEndcap = m_idHelperSvc->isEndcap(id);
684
685 if (isEndcap) {
686 std::string stName = m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(id));
687 if (stName[1] == 'I') return true;
688
689 } else {
690 return true;
691 }
692 return false;
693 }
const std::string & stName(StIndex index)
convert StIndex into a string

◆ find() [1/5]

void Muon::DCMathSegmentMaker::find ( const Amg::Vector3D & gpos,
const Amg::Vector3D & gdir,
const std::vector< const MdtDriftCircleOnTrack * > & mdts,
const std::vector< const MuonClusterOnTrack * > & clusters,
bool hasPhiMeasurements = false,
Trk::SegmentCollection * segColl = nullptr,
double momentum = 1e9,
double sinAngleCut = 0,
double beta = 1. ) const

find segments starting from:

  • an estimate of the global position and direction of the particle in the chamber
  • a list of MdtDriftCircleOnTrack
  • a list of MuonClusterOnTrack
  • a boolean to indicate whether the external prediction should be used to set the \( \phi \)-direction of the segment
  • an estimate of the momentum of the particle

The global direction is used to perform a seeded search for segments.

Definition at line 85 of file DCMathSegmentMaker.cxx.

88 {
89 const EventContext& ctx = Gaudi::Hive::currentContext();
91 ATH_MSG_DEBUG("Timeout reached. Aborting sequence.");
92 return;
93 }
94
95 ATH_MSG_DEBUG("In find, passed " << mdts.size() << " MDTs & "<<clusters.size()<<" clusters");
96
97 if (mdts.size() < 3) return;
98
99 const MdtDriftCircleOnTrack* firstRot = findFirstRotInChamberWithMostHits(mdts);
100
101 if (!firstRot) { return; }
102
103 const MuonGM::MdtReadoutElement* detEl = firstRot->detectorElement();
104
105 if (!detEl) {
106 ATH_MSG_WARNING(" no MdtReadoutElement found, returning 0 ");
107 return;
108 }
109
110 // identifier
111 Identifier chid = firstRot->identify();
112
113 // endcap or barrel
114 bool isEndcap = m_idHelperSvc->mdtIdHelper().isEndcap(chid);
115
116 // global to local transformation for chamber
117 Amg::Transform3D gToStation = detEl->GlobalToAmdbLRSTransform();
118
119 // define axis of chamber in global coordinates
120 Amg::Transform3D amdbToGlobal = detEl->AmdbLRSToGlobalTransform();
121
122 // transform nominal pointing chamber position into surface frame
123 Amg::Vector3D globalDirCh{detEl->center()};
124 Amg::Vector3D dirCh(gToStation.linear() * globalDirCh);
125 double chamber_angleYZ = std::atan2(dirCh.z(), dirCh.y());
126
127 Amg::Vector3D roaddir2 = roaddir;
128 double dotprod = globalDirCh.perp() * std::sin(roaddir2.theta()) + globalDirCh.z() * std::cos(roaddir2.theta());
129 if (dotprod < 0) roaddir2 = -roaddir2;
130
131 // transform the global direction into the surface frame
132 Amg::Vector3D d(gToStation.linear() * roaddir2);
133 // calculate the local road angles in the surface frame
134 double road_angleXZ = std::atan2(d.z(), d.x());
135 double road_angleYZ = std::atan2(d.z(), d.y());
136
137 if (!hasPhiMeasurements) road_angleXZ = M_PI; // if no phi, take phi perpendicular to plane
138 ATH_MSG_VERBOSE("global road pos "<<Amg::toString(roadpos)<<", global road dir " << Amg::toString(roaddir2) << " XZ " << road_angleXZ << " YZ " << road_angleYZ << " isEndcap "
139 << isEndcap << " central phi " << detEl->center().phi() << " r " << detEl->center().perp()
140 << " z " << detEl->center().z());
141
142 // rescale errors for low momentum
143 double errorScale = errorScaleFactor(chid, momentum, hasPhiMeasurements);
144
145 /* ***** create cluster hits ******** */
146 ATH_MSG_DEBUG(" adding clusters " << clusters.size());
147 ClusterVecPair spVecs;
148 if (m_doSpacePoints)
149 spVecs = create2DClusters(clusters);
150 else
151 spVecs = create1DClusters(clusters);
152 TrkDriftCircleMath::CLVec cls = createClusterVec(chid, spVecs.first, gToStation);
153
154 /* ***** create MDT hits ************ */
155 if (msgLvl(MSG::VERBOSE)) {
156 std::stringstream sstr{};
157 for (const MdtDriftCircleOnTrack* mdt : mdts)
158 sstr<<m_printer->print(*mdt)<<std::endl;
159 ATH_MSG_VERBOSE(" adding mdts " << mdts.size()<<std::endl<<sstr.str());
160 }
161
162 // set to get Identifiers of chambers with hits
163 std::set<Identifier> chamberSet;
164 double phimin{-9999}, phimax{9999};
165 TrkDriftCircleMath::DCStatistics dcStatistics; // statistics on chamber occupancy
166 TrkDriftCircleMath::DCVec dcs = createDCVec(mdts, errorScale, chamberSet, phimin, phimax, dcStatistics, gToStation, amdbToGlobal);
167
168 // create geometry
169 std::shared_ptr<const TrkDriftCircleMath::ChamberGeometry> multiGeo;
170 if (m_doGeometry) {
171 ATH_MSG_VERBOSE(" using chamber geometry with #chambers " << chamberSet.size());
172 // vector to store chamber geometries
173 std::vector<TrkDriftCircleMath::MdtChamberGeometry> geos{};
174
175 // loop over chambers
176 geos.reserve(chamberSet.size());
177 for (const Identifier& id : chamberSet) {
178 ATH_MSG_VERBOSE("Chamber: "<<m_idHelperSvc->toStringChamber(id));
179 geos.push_back(createChamberGeometry(id, gToStation));
180 }
181 // create new geometry
182 multiGeo = std::make_unique<TrkDriftCircleMath::MdtMultiChamberGeometry>(geos);
183
184
185 }
186
187 double angle = m_sinAngleCut;
188 if (sinAngleCut > 0) angle = sinAngleCut;
189 TrkDriftCircleMath::Road road(TrkDriftCircleMath::LocVec2D{0.,0.}, road_angleYZ, chamber_angleYZ, angle);
190
191 // call segment finder
192 TrkDriftCircleMath::SegVec segs = m_segmentFinder->findSegments(dcs, cls, road, dcStatistics, multiGeo.get());
193
194 if (msgLvl(MSG::VERBOSE)) {
195 std::stringstream sstr{};
196 unsigned int seg_n{0};
197 for (const TrkDriftCircleMath::Segment& seg: segs) {
198 constexpr double toDeg = 1./Gaudi::Units::degree;
199 sstr<<"Segment number "<<seg_n<<" is at ("<<seg.line().x0()<<","<<seg.line().y0()<<") pointing to "<<seg.line().phi()*toDeg<<" chi2: "<<
200 (seg.chi2()/seg.ndof())<<"("<<seg.ndof()<<")"<<std::endl;
201 sstr<<"Mdt measurements: "<<seg.dcs().size()<<std::endl;
202 for (const TrkDriftCircleMath::DCOnTrack & mdt_meas : seg.dcs()){
203 sstr<<" **** "<<m_printer->print(*mdt_meas.rot());
204 sstr<<" ("<<mdt_meas.state()<<")"<<std::endl;
205 }
206 sstr<<"Cluster measurements "<<seg.clusters().size()<<std::endl;
207 for (const TrkDriftCircleMath::Cluster& clus: seg.clusters()) {
208 sstr<<" ---- "<<m_printer->print(*clus.rot())<<std::endl;
209 }
210 sstr<<std::endl;
211 ++seg_n;
212 }
213 ATH_MSG_VERBOSE("Found " << segs.size() << " segments "<<std::endl<<sstr.str());
214 }
215
216 // return
217 if (segs.empty()) { return; }
218
219 // loop over segments
220 segmentCreationInfo sInfo(spVecs, multiGeo.get(), gToStation, amdbToGlobal, phimin, phimax);
221 for (TrkDriftCircleMath::Segment& seg : segs) {
222 std::unique_ptr<MuonSegment> segment = createSegment(ctx, seg, chid, roadpos, roaddir2, mdts, hasPhiMeasurements, sInfo, beta);
223 if (segment) segColl->push_back(segment.release());
224 }
225 ATH_MSG_DEBUG(" Done ");
226 }
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
static Timeout & instance()
Get reference to Timeout singleton.
Definition Timeout.h:64
virtual const MuonGM::MdtReadoutElement * detectorElement() const override final
Returns the detector element, assoicated with the PRD of this class.
virtual const Amg::Vector3D & center(const Identifier &) const override final
Return the center of the surface associated with this identifier In the case of silicon it returns th...
Gaudi::Property< bool > m_doSpacePoints
std::unique_ptr< MuonSegment > createSegment(const EventContext &ctx, TrkDriftCircleMath::Segment &segment, const Identifier &chid, const Amg::Vector3D &roadpos, const Amg::Vector3D &roaddir2, const std::vector< const MdtDriftCircleOnTrack * > &mdts, bool hasPhiMeasurements, segmentCreationInfo &sInfo, double beta=1.) const
ClusterVecPair create1DClusters(const std::vector< const MuonClusterOnTrack * > &clusters) const
Gaudi::Property< bool > m_doGeometry
Gaudi::Property< double > m_sinAngleCut
TrkDriftCircleMath::MdtChamberGeometry createChamberGeometry(const Identifier &chid, const Amg::Transform3D &gToStation) const
Gaudi::Property< bool > m_doTimeOutChecks
const MdtDriftCircleOnTrack * findFirstRotInChamberWithMostHits(const std::vector< const MdtDriftCircleOnTrack * > &mdts) const
TrkDriftCircleMath::CLVec createClusterVec(const Identifier &chid, ClusterVec &spVec, const Amg::Transform3D &gToStation) const
ClusterVecPair create2DClusters(const std::vector< const MuonClusterOnTrack * > &clusters) const
double errorScaleFactor(const Identifier &id, double curvature, bool hasPhiMeasurements) const
calculate error scaling factor
ToolHandle< IMdtSegmentFinder > m_segmentFinder
TrkDriftCircleMath::DCVec createDCVec(const std::vector< const MdtDriftCircleOnTrack * > &mdts, double errorScale, std::set< Identifier > &chamberSet, double &phimin, double &phimax, TrkDriftCircleMath::DCStatistics &dcStatistics, const Amg::Transform3D &gToStation, const Amg::Transform3D &amdbToGlobal) const

◆ find() [2/5]

void Muon::DCMathSegmentMaker::find ( const std::vector< const MdtDriftCircleOnTrack * > & mdts,
const std::vector< const MuonClusterOnTrack * > & clusters,
Trk::SegmentCollection * segColl = nullptr ) const

find segments starting from:

Implementation of IMuonSegmentMaker interface routine

Will call:

std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, const std::vector<const MdtDriftCircleOnTrack*>& mdts, const std::vector<const MuonClusterOnTrack*>& clusters, bool hasPhiMeasurements, double momentum );

Definition at line 608 of file DCMathSegmentMaker.cxx.

609 {
610 if (mdts.empty()) return;
611
612 const MdtDriftCircleOnTrack* mdt = mdts.front();
613 if (!mdt) return;
614
615 bool hasPhiMeasurements = false;
616 Amg::Vector3D gpos = mdt->globalPosition();
617 Amg::Vector3D gdir = gpos.unit();
618 find(gpos, gdir, mdts, clusters, hasPhiMeasurements, segColl);
619 }
void find(const std::vector< const Trk::RIO_OnTrack * > &rios, Trk::SegmentCollection *segColl=nullptr) const
find segments starting from a list of RIO_OnTrack objects, implementation of IMuonSegmentMaker interf...

◆ find() [3/5]

void Muon::DCMathSegmentMaker::find ( const std::vector< const Trk::RIO_OnTrack * > & rios,
Trk::SegmentCollection * segColl = nullptr ) const

find segments starting from a list of RIO_OnTrack objects, implementation of IMuonSegmentMaker interface routine.

Will call:

std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, const std::vector<const MdtDriftCircleOnTrack*>& mdts, const std::vector<const MuonClusterOnTrack*>& clusters, bool hasPhiMeasurements);

Definition at line 589 of file DCMathSegmentMaker.cxx.

589 {
590 std::vector<const MdtDriftCircleOnTrack*> mdts;
591 std::vector<const MuonClusterOnTrack*> clusters;
592
593 for (const Trk::RIO_OnTrack* it : rios) {
594 Identifier id = it->identify();
595 if (m_idHelperSvc->isMdt(id)) {
596 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(it);
597 if (!mdt) { ATH_MSG_WARNING("failed dynamic_cast, not a MDT but hit has MDT id!!!"); }
598 mdts.push_back(mdt);
599 } else if (m_idHelperSvc->isTrigger(id)) {
600 const MuonClusterOnTrack* clus = dynamic_cast<const MuonClusterOnTrack*>(it);
601 if (!clus) { ATH_MSG_WARNING("failed dynamic_cast, not a cluster but hit has RPC/TGC id!!!"); }
602 clusters.push_back(clus);
603 }
604 }
605 find(mdts, clusters, segColl);
606 }

◆ find() [4/5]

void Muon::DCMathSegmentMaker::find ( const std::vector< const Trk::RIO_OnTrack * > & rios1,
const std::vector< const Trk::RIO_OnTrack * > & rios2 ) const

find segments starting from a list of RIO_OnTrack objects in multiple chambers, implementation of IMuonSegmentMaker interface routine Will call:

std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, const std::vector<const MdtDriftCircleOnTrack*>& mdts, const std::vector<const MuonClusterOnTrack*>& clusters, bool hasPhiMeasurements);

Definition at line 621 of file DCMathSegmentMaker.cxx.

622 {
623 std::vector<const Trk::RIO_OnTrack*> rios = rios1;
624 rios.insert(rios.end(), rios2.begin(), rios2.end());
625 find(rios);
626 }

◆ find() [5/5]

void Muon::DCMathSegmentMaker::find ( const Trk::TrackRoad & road,
const std::vector< std::vector< const MdtDriftCircleOnTrack * > > & mdts,
const std::vector< std::vector< const MuonClusterOnTrack * > > & clusters,
Trk::SegmentCollection * segColl,
bool hasPhiMeasurements = false,
double momentum = 1e9 ) const

find segments starting from:

Implementation of IMuonSegmentMaker interface routine

Will call:

std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, const std::vector<const MdtDriftCircleOnTrack*>& mdts, const std::vector<const MuonClusterOnTrack*>& clusters, bool hasPhiMeasurements, double momentum );

Definition at line 628 of file DCMathSegmentMaker.cxx.

630 {
631 // copy all mdt hits into one vector
632 std::vector<const MdtDriftCircleOnTrack*> all_mdts;
633 for (const std::vector<const MdtDriftCircleOnTrack*>& circle_vec : mdts) { std::copy(circle_vec.begin(), circle_vec.end(), std::back_inserter(all_mdts)); }
634
635 // copy all clusters into one vector
636 std::vector<const MuonClusterOnTrack*> all_clus;
637 for ( const std::vector<const MuonClusterOnTrack*>& clus_vec : clusters) { std::copy(clus_vec.begin(), clus_vec.end(), std::back_inserter(all_clus)); }
638
639 const Amg::Vector3D& gpos = road.globalPosition();
640 const Amg::Vector3D& gdir = road.globalDirection();
641 find(gpos, gdir, all_mdts, all_clus, hasPhiMeasurements, segColl, momentum, road.deltaEta());
642 }
const Amg::Vector3D & globalPosition() const
Get the global position of the road.
Definition TrackRoad.h:137
double deltaEta() const
Get the width of the road in the eta direction.
Definition TrackRoad.h:149
const Amg::Vector3D & globalDirection() const
Get the global direction of the road.
Definition TrackRoad.h:143

◆ findFirstRotInChamberWithMostHits()

const MdtDriftCircleOnTrack * Muon::DCMathSegmentMaker::findFirstRotInChamberWithMostHits ( const std::vector< const MdtDriftCircleOnTrack * > & mdts) const
private

Definition at line 1796 of file DCMathSegmentMaker.cxx.

1797 {
1798 int hitsInChamberWithMostHits = 0;
1799 std::map<Identifier, int> hitsPerChamber;
1800 int currentSector = -1;
1801 const MdtDriftCircleOnTrack* rotInChamberWithMostHits = nullptr;
1802
1803 // loop over all MDTs and count number of MDTs per chamber
1804 for (const MdtDriftCircleOnTrack* rot : mdts) {
1805 if (!rot) {
1806 ATH_MSG_WARNING(" rot not a MdtDriftCircleOnTrack ");
1807 continue;
1808 }
1809 Identifier chId = m_idHelperSvc->chamberId(rot->identify());
1810 int sector = m_idHelperSvc->sector(chId);
1811 if (currentSector == -1) {
1812 currentSector = sector;
1813 } else if (sector != currentSector) {
1814 return nullptr;
1815 }
1816 int& hitsInCh = hitsPerChamber[chId];
1817 ++hitsInCh;
1818 if (hitsInCh > hitsInChamberWithMostHits) {
1819 hitsInChamberWithMostHits = hitsInCh;
1820 rotInChamberWithMostHits = rot;
1821 }
1822 }
1823 return rotInChamberWithMostHits;
1824 }

◆ findMdt()

const MdtPrepData * Muon::DCMathSegmentMaker::findMdt ( const EventContext & ctx,
const Identifier & id ) const
private

Definition at line 1777 of file DCMathSegmentMaker.cxx.

1777 {
1778 IdentifierHash colHash;
1779 if (m_idHelperSvc->mdtIdHelper().get_module_hash(m_idHelperSvc->chamberId(id), colHash)){
1780 ATH_MSG_VERBOSE("Invalid Mdt identifier "<<m_idHelperSvc->toString(id));
1781 return nullptr;
1782 }
1783 SG::ReadHandle<Muon::MdtPrepDataContainer> MdtCont{m_mdtKey, ctx};
1784 if (!MdtCont.isValid()) {
1785 ATH_MSG_WARNING("Cannot retrieve MdtPrepDataContainer ");
1786 return nullptr;
1787 }
1788 const MdtPrepDataCollection* collptr = MdtCont->indexFindPtr(colHash);
1789 if (!collptr) return nullptr;
1790 for (const MdtPrepData* prd : *collptr) {
1791 if (prd->identify() == id) return prd;
1792 }
1793 return nullptr;
1794 }
SG::ReadHandleKey< Muon::MdtPrepDataContainer > m_mdtKey
virtual bool isValid() override final
Can the handle be successfully dereferenced?
MuonPrepDataCollection< MdtPrepData > MdtPrepDataCollection

◆ initialize()

StatusCode Muon::DCMathSegmentMaker::initialize ( )
virtual

Definition at line 64 of file DCMathSegmentMaker.cxx.

64 {
65 ATH_CHECK(m_mdtKey.initialize(m_removeDeltas && !m_mdtKey.empty()));
66 // retrieve MuonDetectorManager
67 ATH_CHECK(m_DetectorManagerKey.initialize());
68 ATH_CHECK(m_mdtCreator.retrieve());
69 ATH_CHECK(m_mdtCreatorT0.retrieve(DisableTool{m_mdtCreatorT0.empty()}));
70 ATH_CHECK(m_clusterCreator.retrieve());
72 ATH_CHECK(m_idHelperSvc.retrieve());
73 ATH_CHECK(m_printer.retrieve());
74 ATH_CHECK(m_edmHelperSvc.retrieve());
75 ATH_CHECK(m_segmentFinder.retrieve());
77 ATH_CHECK(m_segmentFitter.retrieve(DisableTool{!m_refitParameters}));
78 ATH_CHECK(m_dcslFitProvider.retrieve(DisableTool{m_dcslFitProvider.empty()}));
79
80 // initialise for data handles
81 ATH_CHECK(m_chamberGeoKey.initialize());
82 return StatusCode::SUCCESS;
83 }
#define ATH_CHECK
Evaluate an expression and check for errors.
ToolHandle< IMuonClusterOnTrackCreator > m_clusterCreator
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc

◆ localTubeEnds()

DCMathSegmentMaker::TubeEnds Muon::DCMathSegmentMaker::localTubeEnds ( const MdtDriftCircleOnTrack & mdt,
const Amg::Transform3D & gToSegment,
const Amg::Transform3D & segmentToG ) const
private

calculate positions of tube ends

Definition at line 2050 of file DCMathSegmentMaker.cxx.

2051 {
2052 TubeEnds tubeEnds;
2053 const Identifier& id = mdt.identify();
2054 Amg::Vector3D lpos = gToSegment * mdt.prepRawData()->globalPosition();
2055
2056 // use readout and hv side as the surface frame is not that of the chamber
2057 Amg::Vector3D lropos = gToSegment * mdt.prepRawData()->detectorElement()->ROPos(id);
2058 Amg::Vector3D lhvpos = lpos + (lpos - lropos);
2059
2060 // rescale to correctly take into account active tube length
2061 double tubeLen = (lropos - lhvpos).mag();
2062 double activeTubeLen =
2063 mdt.detectorElement()->getActiveTubeLength(m_idHelperSvc->mdtIdHelper().tubeLayer(id), m_idHelperSvc->mdtIdHelper().tube(id));
2064 double scaleFactor = activeTubeLen / tubeLen;
2065 lropos[0] = scaleFactor * lropos.x();
2066 lhvpos[0] = scaleFactor * lhvpos.x();
2067
2068 tubeEnds.lxmin = std::min(lropos.x(), lhvpos.x());
2069 tubeEnds.lxmax = std::max(lropos.x(), lhvpos.x());
2070
2071 Amg::Vector3D ropos = segmentToG * lropos;
2072 Amg::Vector3D hvpos = segmentToG * lhvpos;
2073 const double phiRO = ropos.phi();
2074 const double phiHV = hvpos.phi();
2075 tubeEnds.phimin = std::min(phiRO, phiHV);
2076 tubeEnds.phimax = std::max(phiRO, phiHV);
2077 return tubeEnds;
2078 }
Scalar mag() const
mag method
double getActiveTubeLength(const int tubeLayer, const int tube) const

◆ residualAndPullWithSegment()

std::pair< double, double > Muon::DCMathSegmentMaker::residualAndPullWithSegment ( const TrkDriftCircleMath::Segment & segment,
const Cluster2D & spacePoint,
const Amg::Transform3D & gToStation )
staticprivate

Definition at line 1669 of file DCMathSegmentMaker.cxx.

1671 {
1672 const TrkDriftCircleMath::Line& line = segment.line();
1673 double cos_sinLine = cot(line.phi());
1674
1675 // calculate sp postion in AMDB reference frame
1676 Amg::Vector3D locPos = gToStation * spacePoint.globalPos;
1677 TrkDriftCircleMath::LocVec2D lpos(locPos.y(), locPos.z());
1678
1679 // calculate distance of segment to measurement surface
1680 double delta_y = lpos.y() - line.position().y();
1681
1682 // calculate position of hit in line frame
1683 TrkDriftCircleMath::LocVec2D lineSurfaceIntersect(delta_y * cos_sinLine + line.position().x(), lpos.y());
1684
1685 // calculate position of hit in line frame
1686 double residual = lpos.x() - lineSurfaceIntersect.x();
1687 double pull = residual / spacePoint.error;
1688 return std::make_pair(residual, pull);
1689 }

◆ updateDirection()

Amg::Vector3D Muon::DCMathSegmentMaker::updateDirection ( double linephi,
const Trk::PlaneSurface & surf,
const Amg::Vector3D & roaddir,
bool isCurvedSegment ) const
private

update the global direction, keeping the phi of the input road direction but using the local angle YZ

Definition at line 2128 of file DCMathSegmentMaker.cxx.

2129 {
2130 // Local direction along precision measurement (0, dy, dz)
2131 Trk::LocalDirection segLocDirs(M_PI_2, linephi);
2132 Amg::Vector3D gdirs;
2133 surf.localToGlobalDirection(segLocDirs, gdirs);
2134 // Local direction in plane (1,0,0)
2135 Trk::LocalDirection segLocDiro(0., M_PI_2);
2136 Amg::Vector3D gdiro;
2137 surf.localToGlobalDirection(segLocDiro, gdiro);
2138
2139 // recalculate the value of the local XZ angle for the give YZ angle of the segment such that the global phi
2140 // direction remains unchanged
2141 double dx = std::sin(gdirs.theta()) * std::cos(gdirs.phi());
2142 double dy = std::sin(gdirs.theta()) * std::sin(gdirs.phi());
2143 double dz = std::cos(gdirs.theta());
2144
2145 // vector gdiro
2146
2147 double dxo = std::sin(gdiro.theta()) * std::cos(gdiro.phi());
2148 double dyo = std::sin(gdiro.theta()) * std::sin(gdiro.phi());
2149 double dzo = std::cos(gdiro.theta());
2150
2151 // solve system real direction = A * gdir + B * gdiro
2152 // phi global constraint: (1)*sin(phi road) - (2)*cos(phi road) = 0
2153 // ( A * dx + B * dxo ) sin (phi ) - (A * dy + B *dyo ) cos (phi) = 0
2154 // A ( dx sin - dy cos ) + B (dx0 sin -dy0 cos) = A * a0 + B * b0 = 0
2155 // psi = atan (-b0 , a0)
2156
2157 double a0 = dx * std::sin(roaddir.phi()) - dy * std::cos(roaddir.phi());
2158 double b0 = dxo * std::sin(roaddir.phi()) - dyo * std::cos(roaddir.phi());
2159 if (b0 < 1e-8 && b0 > 0) b0 = 1e-8;
2160 if (b0 > -1e-8 && b0 < 0) b0 = -1e-8;
2161 double dxn = dx - a0 * dxo / b0;
2162 double dyn = dy - a0 * dyo / b0;
2163 double dzn = dz - a0 * dzo / b0;
2164 double norm = std::sqrt(dxn * dxn + dyn * dyn + dzn * dzn);
2165
2166 // flip the sign if the direction NOT parallel to road
2167 if (m_assumePointingPhi) {
2168 if (dxn * roaddir.x() + dyn * roaddir.y() + dzn * roaddir.z() < 0.) { norm = -norm; }
2169 } else {
2170 if (dxn * roaddir.x() + dyn * roaddir.y() < 0.) { norm = -norm; }
2171 }
2172
2173 if (isCurvedSegment) norm = norm / 2.;
2174
2175 //
2176 // Follow segment fit direction
2177 //
2178 dxn = dxn / norm;
2179 dyn = dyn / norm;
2180 dzn = dzn / norm;
2181
2182 return Amg::Vector3D(dxn, dyn, dzn);
2183 }
void localToGlobalDirection(const Trk::LocalDirection &locdir, Amg::Vector3D &globdir) const
This method transforms a local direction wrt the plane to a global direction.
double a0
Definition globals.cxx:27

◆ updatePhiRanges()

void Muon::DCMathSegmentMaker::updatePhiRanges ( double phiminNew,
double phimaxNew,
double & phiminRef,
double & phimaxRef )
staticprivate

update phi ranges

Definition at line 2080 of file DCMathSegmentMaker.cxx.

2080 {
2081 // check whether we are at the boundary where phi changes sign
2082 if (phiminRef * phimaxRef < 0.) {
2083 if (phiminRef < -1.1) {
2084 if (phiminRef > phiminNew) phiminRef = phiminNew;
2085 if (phimaxRef < phimaxNew) phimaxRef = phimaxNew;
2086 } else {
2087 if (phiminRef < phiminNew) phiminRef = phiminNew;
2088 if (phimaxRef > phimaxNew) phimaxRef = phimaxNew;
2089 }
2090 } else {
2091 // if not life is 'easy'
2092 if (phiminRef < 0.) {
2093 if (phiminRef < phiminNew) phiminRef = phiminNew;
2094 if (phimaxRef > phimaxNew) phimaxRef = phimaxNew;
2095 } else {
2096 if (phiminRef > phiminNew) phiminRef = phiminNew;
2097 if (phimaxRef < phimaxNew) phimaxRef = phimaxNew;
2098 }
2099 }
2100 }

◆ updateSegmentPhi()

bool Muon::DCMathSegmentMaker::updateSegmentPhi ( const Amg::Vector3D & gpos,
const Amg::Vector3D & gdir,
Amg::Vector2D & segLocPos,
Trk::LocalDirection & segLocDir,
Trk::PlaneSurface & surf,
const std::vector< const Trk::MeasurementBase * > & rots,
double phimin,
double phimax ) const
private

Definition at line 1850 of file DCMathSegmentMaker.cxx.

1853 {
1854 bool hasUpdated = false;
1855
1856 const Amg::Transform3D& segmentToGlobal = surf.transform();
1857 Amg::Transform3D gToSegment = surf.transform().inverse();
1858 Amg::Vector3D ldir = gToSegment * gdir;
1859
1860 // ensure that we can extrapolate
1861 if (ldir.z() < 0.0001) return false;
1862
1863 double dXdZ = ldir.x() / ldir.z();
1864 Amg::Vector3D lsegPos = gToSegment * gpos;
1865 double xline = lsegPos.x();
1866 double zline = lsegPos.z();
1867 ATH_MSG_VERBOSE(" Associated hits " << rots.size() << " angleXZ " << 90. * segLocDir.angleXZ() / (M_PI_2) << " dXdZ " << dXdZ
1868 << " seg Pos (" << xline << " " << zline << ") " << segLocPos);
1869
1870 std::vector<HitInXZ> hits;
1871 hits.reserve(rots.size());
1872
1873 unsigned int nphiHits(0);
1874 const HitInXZ* firstPhiHit{nullptr}, *lastPhiHit{nullptr};
1875
1876 for (const Trk::MeasurementBase* meas : rots) {
1877 Identifier id = m_edmHelperSvc->getIdentifier(*meas);
1878 if (!id.is_valid()) continue;
1879 Amg::Vector3D lpos{Amg::Vector3D::Zero()};
1880 double lxmin{0}, lxmax{0}, phimin{0}, phimax{0};
1881 bool isMdt = m_idHelperSvc->isMdt(id);
1882 bool measuresPhi = m_idHelperSvc->measuresPhi(id);
1883 if (isMdt) {
1884 lpos.setZero();
1885 const MdtDriftCircleOnTrack* mdt = static_cast<const MdtDriftCircleOnTrack*>(meas);
1886 TubeEnds tubeEnds = localTubeEnds(*mdt, gToSegment, segmentToGlobal);
1887
1888 lxmin = tubeEnds.lxmin;
1889 lxmax = tubeEnds.lxmax;
1890 phimin = tubeEnds.phimin;
1891 phimax = tubeEnds.phimax;
1892 } else {
1893 lpos = gToSegment * meas->globalPosition();
1894 lxmin = lpos.x() - 5 * Amg::error(meas->localCovariance(), Trk::locX);
1895 lxmax = lpos.x() + 5 * Amg::error(meas->localCovariance(), Trk::locX);
1896
1897 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(meas);
1898 if (!measuresPhi) {
1899 if (crot) {
1900 const MuonGM::RpcReadoutElement* detEl =
1901 dynamic_cast<const MuonGM::RpcReadoutElement*>(crot->containedROTs().front()->prepRawData()->detectorElement());
1902 if (detEl) {
1903 // perform bound check
1904 double stripLength = detEl->StripLength(0);
1905 lxmin = lpos.x() - 0.5 * stripLength;
1906 lxmax = lpos.x() + 0.5 * stripLength;
1907 }
1908 }
1909 Amg::Vector3D locPosition = lpos;
1910 locPosition[0] = lxmin;
1911 Amg::Vector3D globalPos = segmentToGlobal * locPosition;
1912 double phi1 = globalPos.phi();
1913
1914 locPosition[0] = lxmax;
1915 globalPos = segmentToGlobal * locPosition;
1916 double phi2 = globalPos.phi();
1917 phimin = std::min(phi1, phi2);
1918 phimax = std::max(phi1, phi2);
1919
1920 } else {
1921 if (m_idHelperSvc->isTgc(id)) {
1922 // need some special tricks for TGC phi hits as their reference plane can be rotated
1923 // with respect to the MDT frame
1924
1925 // get orientation angle of strip to rotate back from local frame to strip
1926 // copy code from ROT creator
1927 int stripNo = m_idHelperSvc->tgcIdHelper().channel(id);
1928 int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(id);
1929 if (!crot) {
1930 ATH_MSG_WARNING("dynamic cast failed for CompetingMuonClustersOnTrack");
1931 continue;
1932 }
1933 auto detEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(crot->containedROTs().front()->prepRawData()->detectorElement());
1934
1935 // transform the two points inth
1936 const Amg::Vector3D segFrame_StripDir = gToSegment.linear()* detEl->stripDir(gasGap, stripNo);
1937 const Amg::Vector3D segFrame_stripPos = gToSegment * detEl->channelPos(id);
1938
1939 lpos = segFrame_stripPos +
1940 Amg::intersect<3>(lsegPos, ldir, segFrame_stripPos, segFrame_StripDir).value_or(0) * segFrame_StripDir;
1941
1942 ATH_MSG_VERBOSE(" In seg frame: phi pos " << Amg::toString(lsegPos)
1943 << " shifted pos " << Amg::toString(segFrame_StripDir)
1944 << " intersect with segment " << Amg::toString(lpos));
1945 }
1946 Amg::Vector3D globalPos = segmentToGlobal * lpos;
1947 phimin = globalPos.phi();
1948 phimax = phimin;
1949
1950 // check whether phi is consistent with segment phi range
1951 bool phiOk = checkPhiConsistency(phimin, seg_phimin, seg_phimax);
1952 if (!phiOk) {
1953 ATH_MSG_DEBUG(" Inconsistent phi " << phimin << " range " << seg_phimin << " " << seg_phimax);
1954 }
1955 }
1956 }
1957
1958 hits.emplace_back(id, isMdt, measuresPhi, lpos.x(), lpos.z(), lxmin, lxmax, phimin, phimax);
1959 if (measuresPhi) {
1960 ++nphiHits;
1961 if (!firstPhiHit)
1962 firstPhiHit = &hits.back();
1963 else {
1964 double distPhiHits = std::abs(firstPhiHit->z - hits.back().z);
1965 if (distPhiHits > 500.) {
1966 lastPhiHit = &hits.back();
1967 } else {
1968 // not count this phi hit
1969 --nphiHits;
1970 ATH_MSG_DEBUG(" close phi hits, distance " << distPhiHits);
1971 }
1972 }
1973 }
1974 if (msgLvl(MSG::VERBOSE)) {
1975 double locExX = xline + dXdZ * (lpos.z() - zline);
1976 ATH_MSG_VERBOSE(" " << std::setw(65) << m_idHelperSvc->toString(id) << " pos (" << std::setw(6) << (int)lpos.x() << ","
1977 << std::setw(6) << (int)lpos.z() << ") ex pos " << std::setw(6) << (int)locExX << " min "
1978 << std::setw(6) << (int)lxmin << " max " << std::setw(6) << (int)lxmax << " phimin " << std::setw(6)
1979 << phimin << " phimax " << std::setw(6) << phimax);
1980 if (lpos.x() < lxmin || lpos.x() > lxmax) ATH_MSG_VERBOSE(" outBounds");
1981 }
1982 }
1983
1984 if (nphiHits == 1) {
1985 if (!firstPhiHit) {
1986 ATH_MSG_WARNING(" Pointer to first phi hit not set, this should not happen! ");
1987 } else {
1988 if (xline != firstPhiHit->x) {
1989 hasUpdated = true;
1990
1991 // use phi position of the phi hit
1992 xline = firstPhiHit->x;
1993 zline = firstPhiHit->z;
1994
1995 if (m_assumePointingPhi) {
1996 Amg::Vector3D ipLocPos = gToSegment.translation();
1997 ATH_MSG_VERBOSE(" IP position in local frame " << ipLocPos);
1998
1999 double dz = ipLocPos.z() - zline;
2000 if (std::abs(dz) > 0.001) {
2001 ATH_MSG_VERBOSE(" hit (" << xline << "," << zline << ") IP (" << ipLocPos.x() << "," << ipLocPos.z()
2002 << ") dXdZ " << (ipLocPos.x() - xline) / dz << " old " << dXdZ);
2003 dXdZ = (ipLocPos.x() - xline) / dz;
2004 }
2005 }
2006 }
2007 }
2008 } else if (nphiHits == 2) {
2009 if (!firstPhiHit || !lastPhiHit) {
2010 ATH_MSG_WARNING(" Pointer to one of the two phi hit not set, this should not happen! ");
2011 } else {
2012 double dz = lastPhiHit->z - firstPhiHit->z;
2013 // use phi position of the first hit
2014 xline = firstPhiHit->x;
2015 zline = firstPhiHit->z;
2016 if (std::abs(dz) > 300.) {
2017 double dx = lastPhiHit->x - firstPhiHit->x;
2018 hasUpdated = true;
2019
2020 // if the two hits are far enough apart, also use the direction of the line connecting the two hits.
2021 dXdZ = dx / dz;
2022 }
2023 }
2024 } else {
2025 // in all other cases just rotate until the MDTs are ok
2026 }
2027
2028 if (hasUpdated) {
2029 // move segment to position of phi hit
2030 double segX = xline - dXdZ * zline;
2031
2032 // finally check whether now everything is in bounds
2033 bool ok = checkBoundsInXZ(segX, 0., dXdZ, hits);
2034 if (!ok) {
2035 // give WARNING and give up for now
2036 ATH_MSG_DEBUG("still several out of bounds hits after rotation: posx(" << segX << ") dXdZ " << dXdZ
2037 << " keeping old result ");
2038 }
2039
2040 // update segment parameters
2041 double alphaYZ = segLocDir.angleYZ();
2042 double alphaXZ = std::atan2(1, dXdZ);
2043
2044 segLocPos[Trk::locX] = segX;
2045 segLocDir = Trk::LocalDirection(alphaXZ, alphaYZ);
2046 }
2047 return hasUpdated;
2048 }
bool checkBoundsInXZ(double xline, double zline, double dXdZ, const std::vector< HitInXZ > &hits) const
check whether all hits are in bounds in the XZ plane
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.

Member Data Documentation

◆ m_addUnassociatedPhiHits

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_addUnassociatedPhiHits {this, "AddUnassociatedPhiHits", false}
private

Definition at line 409 of file DCMathSegmentMaker.h.

409{this, "AddUnassociatedPhiHits", false}; //<! if there are phi hits without associated eta hit add them to segment

◆ m_allMdtHoles

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_allMdtHoles {this, "AllMdtHoles", false}
private

Definition at line 414 of file DCMathSegmentMaker.h.

414{this, "AllMdtHoles", false}; //<! add all mdt holes without bound checks / flag to decide whether to apply bound checks during the hole search

◆ m_assumePointingPhi

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_assumePointingPhi {this, "AssumePointingPhi", false }
private

Definition at line 424 of file DCMathSegmentMaker.h.

424{this, "AssumePointingPhi", false };

◆ m_chamberGeoKey

SG::ReadCondHandleKey<Muon::MuonIntersectGeoData> Muon::DCMathSegmentMaker::m_chamberGeoKey {this, "ChamberGeoKey", "MuonStationIntersects", "Pointer to hole search service"}
private

Definition at line 430 of file DCMathSegmentMaker.h.

430{this, "ChamberGeoKey", "MuonStationIntersects", "Pointer to hole search service"};

◆ m_clusterCreator

ToolHandle<IMuonClusterOnTrackCreator> Muon::DCMathSegmentMaker::m_clusterCreator
private
Initial value:
{
this,
"MuonClusterCreator",
"Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator",
}

Definition at line 366 of file DCMathSegmentMaker.h.

366 {
367 this,
368 "MuonClusterCreator",
369 "Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator",
370 }; //<! cluster rio ontrack creator

◆ m_compClusterCreator

ToolHandle<IMuonCompetingClustersOnTrackCreator> Muon::DCMathSegmentMaker::m_compClusterCreator
private
Initial value:
{
this,
"MuonCompetingClustersCreator",
"Muon::TriggerChamberClusterOnTrackCreator/TriggerChamberClusterOnTrackCreator",
}

Definition at line 371 of file DCMathSegmentMaker.h.

371 {
372 this,
373 "MuonCompetingClustersCreator",
374 "Muon::TriggerChamberClusterOnTrackCreator/TriggerChamberClusterOnTrackCreator",
375 }; //<! competing clusters rio ontrack creator

◆ m_createCompetingROTsEta

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_createCompetingROTsEta {this, "CreateCompetingROTsEta", true}
private

Definition at line 406 of file DCMathSegmentMaker.h.

406{this, "CreateCompetingROTsEta", true}; //<! create competing ROTs for the clusters

◆ m_createCompetingROTsPhi

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_createCompetingROTsPhi {this, "CreateCompetingROTsPhi", true}
private

Definition at line 407 of file DCMathSegmentMaker.h.

407{this, "CreateCompetingROTsPhi", true}; //<! create competing ROTs for the clusters

◆ m_curvedErrorScaling

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_curvedErrorScaling {this, "CurvedErrorScaling", true}
private

Definition at line 404 of file DCMathSegmentMaker.h.

404{this, "CurvedErrorScaling", true}; //<! rescale errors for low momenta

◆ m_dcslFitProvider

ToolHandle<IDCSLFitProvider> Muon::DCMathSegmentMaker::m_dcslFitProvider
private
Initial value:
{
this,
"DCFitProvider",
"",
}

Definition at line 396 of file DCMathSegmentMaker.h.

396 {
397 this,
398 "DCFitProvider",
399 "",
400 };

◆ m_DetectorManagerKey

SG::ReadCondHandleKey<MuonGM::MuonDetectorManager> Muon::DCMathSegmentMaker::m_DetectorManagerKey
private
Initial value:
{
this,
"DetectorManagerKey",
"MuonDetectorManager",
"Key of input MuonDetectorManager condition data",
}

pointers to IdHelpers

Definition at line 337 of file DCMathSegmentMaker.h.

337 {
338 this,
339 "DetectorManagerKey",
340 "MuonDetectorManager",
341 "Key of input MuonDetectorManager condition data",
342 };

◆ m_doGeometry

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_doGeometry {this, "DoGeometry", true}
private

Definition at line 403 of file DCMathSegmentMaker.h.

403{this, "DoGeometry", true}; //<! use chamber geometry in segment finding

◆ m_doSpacePoints

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_doSpacePoints {this, "UseTriggerSpacePoints", true}
private

Definition at line 405 of file DCMathSegmentMaker.h.

405{this, "UseTriggerSpacePoints", true}; //<! use cluster space points for association

◆ m_doTimeOutChecks

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_doTimeOutChecks {this, "UseTimeOutGard", false}
private

Definition at line 420 of file DCMathSegmentMaker.h.

420{this, "UseTimeOutGard", false};

◆ m_edmHelperSvc

ServiceHandle<IMuonEDMHelperSvc> Muon::DCMathSegmentMaker::m_edmHelperSvc
private
Initial value:
{
this,
"edmHelper",
"Muon::MuonEDMHelperSvc/MuonEDMHelperSvc",
"Handle to the service providing the IMuonEDMHelperSvc interface",
}

Definition at line 349 of file DCMathSegmentMaker.h.

349 {
350 this,
351 "edmHelper",
352 "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc",
353 "Handle to the service providing the IMuonEDMHelperSvc interface",
354 }; //<! edm helper tool

◆ m_idHelperSvc

ServiceHandle<Muon::IMuonIdHelperSvc> Muon::DCMathSegmentMaker::m_idHelperSvc
private
Initial value:
{
this,
"MuonIdHelperSvc",
"Muon::MuonIdHelperSvc/MuonIdHelperSvc",
}

Definition at line 344 of file DCMathSegmentMaker.h.

344 {
345 this,
346 "MuonIdHelperSvc",
347 "Muon::MuonIdHelperSvc/MuonIdHelperSvc",
348 };

◆ m_maxAssociateClusterDistance

Gaudi::Property<double> Muon::DCMathSegmentMaker::m_maxAssociateClusterDistance {this, "MaxAssociateClusterDistance", 3000.}
private

Definition at line 412 of file DCMathSegmentMaker.h.

412{this, "MaxAssociateClusterDistance", 3000.}; //<! maximum distance for clusters to be associated to segment (default: 3000

◆ m_mdtCreator

ToolHandle<IMdtDriftCircleOnTrackCreator> Muon::DCMathSegmentMaker::m_mdtCreator
private
Initial value:
{
this,
"MdtCreator",
"Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator",
}

Definition at line 356 of file DCMathSegmentMaker.h.

356 {
357 this,
358 "MdtCreator",
359 "Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator",
360 }; //<! mdt rio ontrack creator

◆ m_mdtCreatorT0

ToolHandle<IMdtDriftCircleOnTrackCreator> Muon::DCMathSegmentMaker::m_mdtCreatorT0
private
Initial value:
{
this,
"MdtCreatorT0",
"Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator",
}

Definition at line 361 of file DCMathSegmentMaker.h.

361 {
362 this,
363 "MdtCreatorT0",
364 "Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator",
365 }; //<! mdt rio ontrack creator

◆ m_mdtKey

SG::ReadHandleKey<Muon::MdtPrepDataContainer> Muon::DCMathSegmentMaker::m_mdtKey {this, "MdtPrepDataContainer", "MDT_DriftCircles"}
private

Definition at line 428 of file DCMathSegmentMaker.h.

428{this, "MdtPrepDataContainer", "MDT_DriftCircles"};

◆ m_outputFittedT0

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_outputFittedT0 {this, "OutputFittedT0", false}
private

Definition at line 418 of file DCMathSegmentMaker.h.

418{this, "OutputFittedT0", false};

◆ m_preciseErrorScale

Gaudi::Property<double> Muon::DCMathSegmentMaker::m_preciseErrorScale {this, "PreciseErrorScale", 2.}
private

Definition at line 419 of file DCMathSegmentMaker.h.

419{this, "PreciseErrorScale", 2.};

◆ m_printer

PublicToolHandle<MuonEDMPrinterTool> Muon::DCMathSegmentMaker::m_printer
private
Initial value:
{
this,
"EDMPrinter",
"Muon::MuonEDMPrinterTool/MuonEDMPrinterTool",
}

Definition at line 376 of file DCMathSegmentMaker.h.

376 {
377 this,
378 "EDMPrinter",
379 "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool",
380 }; //<! printer helper tool

◆ m_recoverBadRpcCabling

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_recoverBadRpcCabling {this, "RecoverBadRpcCabling", false}
private

Definition at line 422 of file DCMathSegmentMaker.h.

422{this, "RecoverBadRpcCabling", false};

◆ m_redo2DFit

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_redo2DFit {this, "Redo2DFit", true}
private

Definition at line 425 of file DCMathSegmentMaker.h.

425{this, "Redo2DFit", true};

◆ m_refitParameters

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_refitParameters {this, "RefitSegment", false}
private

Definition at line 408 of file DCMathSegmentMaker.h.

408{this, "RefitSegment", false}; //<! refit segment if there are sufficient phi hits and update the segment parameters

◆ m_reject1DTgcSpacePoints

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_reject1DTgcSpacePoints {this,"Reject1DTgcSpacePoints", true }
private

Definition at line 416 of file DCMathSegmentMaker.h.

416{this,"Reject1DTgcSpacePoints", true }; //<! remove 1D tgc space points / reject TGC eta hits that are not associated with a phi hit in the same gas gap

◆ m_removeDeltas

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_removeDeltas {this, "RemoveDeltasFromSegmentQuality", true}
private

Definition at line 415 of file DCMathSegmentMaker.h.

415{this, "RemoveDeltasFromSegmentQuality", true}; //<! do not add delta electrons to MuonSegmentQuality::holes

◆ m_segmentFinder

ToolHandle<IMdtSegmentFinder> Muon::DCMathSegmentMaker::m_segmentFinder
private
Initial value:
{
this,
"MdtSegmentFinder",
"Muon::MdtMathSegmentFinder/MdtMathSegmentFinder",
}

Definition at line 381 of file DCMathSegmentMaker.h.

381 {
382 this,
383 "MdtSegmentFinder",
384 "Muon::MdtMathSegmentFinder/MdtMathSegmentFinder",
385 }; //<! segment finder tool

◆ m_segmentFitter

ToolHandle<IMuonSegmentFittingTool> Muon::DCMathSegmentMaker::m_segmentFitter
private
Initial value:
{
this,
"SegmentFitter",
"Muon::MuonSegmentFittingTool/MuonSegmentFittingTool",
}

Definition at line 386 of file DCMathSegmentMaker.h.

386 {
387 this,
388 "SegmentFitter",
389 "Muon::MuonSegmentFittingTool/MuonSegmentFittingTool",
390 }; //<! segment fitting tool

◆ m_segmentSelectionTool

ToolHandle<IMuonSegmentSelectionTool> Muon::DCMathSegmentMaker::m_segmentSelectionTool
private
Initial value:
{
this,
"SegmentSelector",
"Muon::MuonSegmentSelectionTool/MuonSegmentSelectionTool",
}

Definition at line 391 of file DCMathSegmentMaker.h.

391 {
392 this,
393 "SegmentSelector",
394 "Muon::MuonSegmentSelectionTool/MuonSegmentSelectionTool",
395 }; //<! segment selection tool

◆ m_sinAngleCut

Gaudi::Property<double> Muon::DCMathSegmentMaker::m_sinAngleCut {this, "SinAngleCut", 0.2}
private

Definition at line 402 of file DCMathSegmentMaker.h.

402{this, "SinAngleCut", 0.2}; //<! cut on the angle between the segment and the prediction

◆ m_strictRoadDirectionConsistencyCheck

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_strictRoadDirectionConsistencyCheck {this, "StrictRoadDirectionConsistencyCheck", true}
private

Definition at line 410 of file DCMathSegmentMaker.h.

410{this, "StrictRoadDirectionConsistencyCheck", true}; //<! check if direction of road is consistent with IP (default: true),

◆ m_updatePhiUsingPhiHits

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_updatePhiUsingPhiHits {this, "UpdatePhiUsingPhiHits", false}
private

Definition at line 423 of file DCMathSegmentMaker.h.

423{this, "UpdatePhiUsingPhiHits", false};

◆ m_usePreciseError

Gaudi::Property<bool> Muon::DCMathSegmentMaker::m_usePreciseError {this, "UsePreciseError", false}
private

Definition at line 417 of file DCMathSegmentMaker.h.

417{this, "UsePreciseError", false};

The documentation for this class was generated from the following files: