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  Cluster2D
struct  HitInXZ
struct  segmentCreationInfo
struct  TubeEnds

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

using Muon::DCMathSegmentMaker::EtaPhiHitsPair = std::pair<std::vector<const MuonClusterOnTrack*>, std::vector<const MuonClusterOnTrack*> >

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 1284 of file DCMathSegmentMaker.cxx.

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

◆ 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 1149 of file DCMathSegmentMaker.cxx.

1153 {
1154 // clear result vectors
1155
1156 // convert segment parameters + x position from road
1157 const TrkDriftCircleMath::Line& line = segment.line();
1158 TrkDriftCircleMath::TransformToLine toLineml1(line);
1159 TrkDriftCircleMath::TransformToLine toLineml2(line);
1160 if (segment.hasCurvatureParameters()) {
1161 // ml2 segment direction
1162 double ml2phi = line.phi() - segment.deltaAlpha();
1163 TrkDriftCircleMath::LocVec2D ml2dir(std::cos(ml2phi), std::sin(ml2phi));
1164 // ml2 segment position
1165 const TrkDriftCircleMath::LocVec2D ml1LocPos = multiGeo->tubePosition(0, multiGeo->nlay(), 0);
1166 const TrkDriftCircleMath::LocVec2D ml2LocPos = multiGeo->tubePosition(1, 1, 0);
1167 double chamberMidPtY = (ml1LocPos.y() + ml2LocPos.y()) / 2.0;
1168 TrkDriftCircleMath::LocVec2D ml2pos(segment.deltab(), chamberMidPtY);
1169 // construct the new ml2 segment line & transform
1170 const TrkDriftCircleMath::Line ml2line(ml2pos, ml2dir);
1171 TrkDriftCircleMath::TransformToLine tmptoLine(ml2line);
1172 // set the ml2 line
1173 toLineml2 = tmptoLine;
1174 }
1175
1176 for (TrkDriftCircleMath::DCOnTrack& dcit : segment.dcs()) {
1177 if (dcit.state() == TrkDriftCircleMath::DCOnTrack::Delta) { deltaVec.insert(dcit.rot()->identify()); }
1178
1179 if (dcit.state() == TrkDriftCircleMath::DCOnTrack::OutOfTime) { outoftimeVec.insert(dcit.rot()->identify()); }
1180
1181 if (dcit.state() != TrkDriftCircleMath::DCOnTrack::OnTrack) continue;
1182
1183 const MdtDriftCircleOnTrack* riodc{dcit.rot()};
1184
1185 // choose which line to use (ml1 or ml2)
1186 TrkDriftCircleMath::TransformToLine toLine = toLineml1;
1187 if (m_idHelperSvc->mdtIdHelper().multilayer(riodc->identify()) == 2) toLine = toLineml2;
1188 // calculate position of hit in line frame
1189 TrkDriftCircleMath::LocVec2D pointOnHit = toLine.toLine(dcit.position());
1190
1191 // calculate position of hit on line in line frame
1192 TrkDriftCircleMath::LocVec2D pointOnLine(pointOnHit.x(), 0.);
1193
1194 // transform back to local AMDB coordinates
1195 TrkDriftCircleMath::LocVec2D pointOnLineAMDB = toLine.toLocal(pointOnLine);
1196
1197 // get position along wire from ROT
1198 Amg::Vector3D posAlong = gToStation * riodc->globalPosition();
1199
1200 // set yz components
1201 posAlong[1] = pointOnLineAMDB.x();
1202 posAlong[2] = pointOnLineAMDB.y();
1203
1204 // back to global
1205 Amg::Vector3D mdtGP = amdbToGlobal * posAlong;
1206
1207 const Trk::StraightLineSurface* surf = dynamic_cast<const Trk::StraightLineSurface*>(&riodc->associatedSurface());
1208 if (!surf) {
1209 ATH_MSG_WARNING(" dynamic cast to StraightLineSurface failed for mdt!!! ");
1210 continue;
1211 }
1212
1213 // calculate Amg::Vector2D using surf to obtain sign
1214 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
1215 if (!surf->globalToLocal(mdtGP, gdir, locPos)) ATH_MSG_WARNING(" globalToLocal failed ");
1216
1217 // calculate side
1219
1220 std::unique_ptr<MdtDriftCircleOnTrack> nonconstDC;
1221 bool hasT0 = segment.hasT0Shift();
1222 if (!hasT0 || m_mdtCreatorT0.empty()) {
1223 // ATH_MSG_VERBOSE(" recalibrate MDT hit");
1224 nonconstDC.reset(m_mdtCreator->createRIO_OnTrack(*riodc->prepRawData(), mdtGP, &gdir, 0., nullptr, beta, 0.));
1225 if (hasT0) ATH_MSG_WARNING("Attempted to change t0 without a properly configured MDT creator tool. ");
1226 } else {
1227 ATH_MSG_VERBOSE(" recalibrate MDT hit with shift " << segment.t0Shift()<<" "<<m_printer->print(*riodc));
1228 nonconstDC.reset(m_mdtCreatorT0->createRIO_OnTrack(*riodc->prepRawData(), mdtGP, &gdir, segment.t0Shift()));
1229 }
1230
1231 if (!nonconstDC) {
1233 continue;
1234 }
1235 ATH_MSG_VERBOSE("Post calibrated hit "<<m_printer->print(*nonconstDC));
1236
1237 // update the drift radius after recalibration, keep error
1238 TrkDriftCircleMath::DriftCircle new_dc(dcit.position(), std::abs(nonconstDC->driftRadius()), dcit.dr(), dcit.drPrecise(),
1239 dcit.driftState(), dcit.id(),
1240 nonconstDC.get());
1241 TrkDriftCircleMath::DCOnTrack new_dc_on_track(new_dc, dcit.residual(), dcit.errorTrack());
1242 dcit = std::move(new_dc_on_track);
1243
1244 if (hasT0) {
1245 if (msgLvl(MSG::VERBOSE)) {
1246 double shift = riodc->driftTime() - nonconstDC->driftTime();
1247 ATH_MSG_VERBOSE(" t0 shift " << segment.t0Shift() << " from hit " << shift << " recal " << nonconstDC->driftRadius()
1248 << " t " << nonconstDC->driftTime() << " from fit " << dcit.r() << " old "
1249 << riodc->driftRadius() << " t " << riodc->driftTime());
1250 if (std::abs(std::abs(nonconstDC->driftRadius()) - std::abs(dcit.r())) > 0.1 && nonconstDC->driftRadius() < 19. &&
1251 nonconstDC->driftRadius() > 1.) {
1252 ATH_MSG_WARNING("Detected invalid recalibration after T0 shift");
1253 }
1254 }
1255 }
1256 m_mdtCreator->updateSign(*nonconstDC, side);
1257 double dist = pointOnHit.x();
1258 rioDistVec.emplace_back(dist, std::move(nonconstDC));
1259 }
1260 }
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
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 1689 of file DCMathSegmentMaker.cxx.

1691 {
1692 // calculate crossed tubes
1693 SG::ReadCondHandle<Muon::MuonIntersectGeoData> InterSectSvc{m_chamberGeoKey, ctx};
1694 if (!InterSectSvc.isValid()) {
1695 ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object");
1696 return {};
1697 }
1698 SG::ReadCondHandle<MuonGM::MuonDetectorManager> detMgr{m_DetectorManagerKey,ctx};
1699 const MuonGM::MuonDetectorManager* MuonDetMgr = detMgr.cptr();
1700
1701 const MuonStationIntersect intersect = InterSectSvc->tubesCrossedByTrack(MuonDetMgr, chid, gpos, gdir);
1702
1703 // set to identify the hit on the segment
1704 std::set<Identifier> hitsOnSegment, chambersOnSegment;
1705 int firstLayer{-1}, lastLayer{-1};
1706 for (const std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) {
1707 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(rdit.second.get());
1708 if (!mdt) continue;
1709 const Identifier id = mdt->identify();
1710 int layer = (m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1) + 4 * (m_idHelperSvc->mdtIdHelper().multilayer(id) - 1);
1711 if (firstLayer == -1)
1712 firstLayer = layer;
1713 else
1714 lastLayer = layer;
1715
1716 hitsOnSegment.insert(id);
1717 chambersOnSegment.insert(m_idHelperSvc->chamberId(id));
1718 }
1719
1720 // cross check for cosmic case
1721 if (firstLayer > lastLayer) { std::swap(firstLayer, lastLayer); }
1722 ATH_MSG_VERBOSE(" Tube layer ranges: " << firstLayer << " -- " << lastLayer << " crossed tubes "
1723 << intersect.tubeIntersects().size());
1724 // clear hole vector
1725 std::vector<Identifier> holeVec;
1726 for (const MuonTubeIntersect& tint : intersect.tubeIntersects()) {
1727 if (!chambersOnSegment.count(m_idHelperSvc->chamberId(tint.tubeId))) {
1728 ATH_MSG_VERBOSE(" chamber not on segment, not counting tube " << tint.rIntersect << " l " << tint.xIntersect << " "
1729 << m_idHelperSvc->toString(tint.tubeId));
1730 continue;
1731 }
1732
1733 const Identifier& id = tint.tubeId;
1734 int layer = (m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1) + 4 * (m_idHelperSvc->mdtIdHelper().multilayer(id) - 1);
1735
1736 bool notBetweenHits = layer < firstLayer || layer > lastLayer;
1737 double distanceCut = hasMeasuredCoordinate ? -20 : -200.;
1738 double innerRadius = MuonDetMgr->getMdtReadoutElement(id)->innerTubeRadius();
1739 if (notBetweenHits && (std::abs(tint.rIntersect) > innerRadius || (!m_allMdtHoles && tint.xIntersect > distanceCut))) {
1740 ATH_MSG_VERBOSE(" not counting tube: distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect
1741 << " " << m_idHelperSvc->toString(tint.tubeId));
1742 continue;
1743 }
1744 // check whether there is a hit in this tube
1745 if (hitsOnSegment.count(tint.tubeId)) {
1746 ATH_MSG_VERBOSE(" tube on segment: distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect
1747 << " " << m_idHelperSvc->toString(tint.tubeId));
1748 continue;
1749 }
1750 // check whether there is a delta electron in this tube
1751 if (m_removeDeltas) {
1752 if (deltaVec.count(tint.tubeId)) {
1753 ATH_MSG_VERBOSE(" removing delta, distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect
1754 << " " << m_idHelperSvc->toString(tint.tubeId));
1755 continue;
1756 }
1757
1758 const MdtPrepData* prd = findMdt(ctx, id);
1759 if (prd && std::abs(prd->localPosition()[Trk::locR]) < std::abs(tint.rIntersect)) {
1760 ATH_MSG_VERBOSE(" found and removed delta, distance to wire " << tint.rIntersect << " dist to tube end "
1761 << tint.xIntersect << " "
1762 << m_idHelperSvc->toString(tint.tubeId));
1763 continue;
1764 }
1765 }
1766 ATH_MSG_VERBOSE((outoftimeVec.count(tint.tubeId) ? "Out-of-time" : "hole") << " distance to wire "
1767 << tint.rIntersect << " dist to tube end " << tint.xIntersect << " "
1768 << m_idHelperSvc->toString(tint.tubeId)<<(notBetweenHits ? "outside hits" : "between hits"));
1769
1770 holeVec.push_back(tint.tubeId);
1771 }
1772 return holeVec;
1773 }
#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 1824 of file DCMathSegmentMaker.cxx.

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

◆ checkPhiConsistency()

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

check whether phi is consistent with segment phi

Definition at line 2100 of file DCMathSegmentMaker.cxx.

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

◆ create1DClusters()

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

Definition at line 694 of file DCMathSegmentMaker.cxx.

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

720 {
721 // if empty return
722 if (clusters.empty()) return {};
723
724 ChIdHitMap gasGapHitMap;
725 for (const MuonClusterOnTrack* clus: clusters) {
726 const Identifier id = clus->identify();
727 ATH_MSG_VERBOSE(" new trigger hit " << m_idHelperSvc->toString(id));
728
729 const Identifier chId = m_idHelperSvc->chamberId(id);
730 const Identifier gasGapId = m_idHelperSvc->gasGapId(id);
731 // eta hits first than phi hits
732 if (!m_idHelperSvc->measuresPhi(id))
733 gasGapHitMap[chId][gasGapId].first.push_back(clus);
734 else
735 gasGapHitMap[chId][gasGapId].second.push_back(clus);
736 }
737
738 return createSpacePoints(gasGapHitMap);
739 }
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 1073 of file DCMathSegmentMaker.cxx.

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

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

1023 {
1025 dcs.reserve(mdts.size());
1026 /* ******** Mdt hits ******** */
1027 bool firstMdt = true;
1028
1029 for (const MdtDriftCircleOnTrack* rot : mdts) {
1030
1031 Identifier id = rot->identify();
1032 Identifier elId = m_idHelperSvc->mdtIdHelper().elementID(id);
1033
1034 // calculate local AMDB position
1035 Amg::Vector3D locPos = gToStation * rot->prepRawData()->globalPosition();
1036 TrkDriftCircleMath::LocVec2D lpos(locPos.y(), locPos.z());
1037
1038 double r = rot->localParameters()[Trk::locR];
1039 double dr = Amg::error(rot->localCovariance(), Trk::locR) * errorScale;
1040
1041 // create identifier
1042 TrkDriftCircleMath::MdtId mdtid(m_idHelperSvc->mdtIdHelper().isBarrel(id), m_idHelperSvc->mdtIdHelper().multilayer(id) - 1,
1043 m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1, m_idHelperSvc->mdtIdHelper().tube(id) - 1);
1044
1045 //
1046 double preciseError = dr;
1047 if (m_usePreciseError) { preciseError = m_preciseErrorScale * (0.23 * std::exp(-std::abs(r) / 6.06) + 0.0362); }
1048 // create new DriftCircle
1049 TrkDriftCircleMath::DriftCircle dc(lpos, r, dr, preciseError, TrkDriftCircleMath::DriftCircle::InTime, mdtid, rot);
1050
1051 TubeEnds tubeEnds = localTubeEnds(*rot, gToStation, amdbToGlobal);
1052 if (firstMdt) {
1053 phimin = tubeEnds.phimin;
1054 phimax = tubeEnds.phimax;
1055 firstMdt = false;
1056 } else {
1057 updatePhiRanges(tubeEnds.phimin, tubeEnds.phimax, phimin, phimax);
1058 }
1059
1060 ATH_MSG_VERBOSE(" new MDT hit " << m_idHelperSvc->toString(id) << " x " << lpos.x() << " y " << lpos.y() << " time "
1061 << rot->driftTime() << " r " << r << " dr " << dr << " phi range " << tubeEnds.phimin << " "
1062 << tubeEnds.phimax<<" precise error "<<preciseError);
1063 dcs.push_back(std::move(dc));
1064
1065 chamberSet.insert(elId);
1066
1067 ++dcStatistics[rot->prepRawData()->detectorElement()];
1068 }
1069
1070 return dcs;
1071 }
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 1655 of file DCMathSegmentMaker.cxx.

1656 {
1657 // sort hits according to they distance to the segment position
1658 std::sort(rioDistVec.begin(), rioDistVec.end(), SortByDistanceToSegment());
1659
1660 DataVector<const Trk::MeasurementBase> rioVec{SG::OWN_ELEMENTS};
1661 rioVec.reserve(rioDistVec.size());
1662 for (std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) { rioVec.push_back(std::move(rdit.second)); }
1663 rioDistVec.clear();
1664 return rioVec;
1665 }
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

◆ createRpcSpacePoint()

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

Definition at line 917 of file DCMathSegmentMaker.cxx.

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

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

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

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

◆ createSpacePoints() [2/2]

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

Definition at line 759 of file DCMathSegmentMaker.cxx.

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

◆ createTgcSpacePoint()

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

Definition at line 876 of file DCMathSegmentMaker.cxx.

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

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

◆ errorScaleFactor()

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

calculate error scaling factor

Definition at line 643 of file DCMathSegmentMaker.cxx.

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

678 {
679 // simple division of MuonSpectrometer in regions using barrel/endcap seperation plus
680 // inner/middle/outer seperation
681
682 bool isEndcap = m_idHelperSvc->isEndcap(id);
683
684 if (isEndcap) {
685 std::string stName = m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(id));
686 if (stName[1] == 'I') return true;
687
688 } else {
689 return true;
690 }
691 return false;
692 }
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 84 of file DCMathSegmentMaker.cxx.

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

608 {
609 if (mdts.empty()) return;
610
611 const MdtDriftCircleOnTrack* mdt = mdts.front();
612 if (!mdt) return;
613
614 bool hasPhiMeasurements = false;
615 Amg::Vector3D gpos = mdt->globalPosition();
616 Amg::Vector3D gdir = gpos.unit();
617 find(gpos, gdir, mdts, clusters, hasPhiMeasurements, segColl);
618 }
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 588 of file DCMathSegmentMaker.cxx.

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

◆ 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 620 of file DCMathSegmentMaker.cxx.

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

◆ 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 627 of file DCMathSegmentMaker.cxx.

629 {
630 // copy all mdt hits into one vector
631 std::vector<const MdtDriftCircleOnTrack*> all_mdts;
632 for (const std::vector<const MdtDriftCircleOnTrack*>& circle_vec : mdts) { std::copy(circle_vec.begin(), circle_vec.end(), std::back_inserter(all_mdts)); }
633
634 // copy all clusters into one vector
635 std::vector<const MuonClusterOnTrack*> all_clus;
636 for ( const std::vector<const MuonClusterOnTrack*>& clus_vec : clusters) { std::copy(clus_vec.begin(), clus_vec.end(), std::back_inserter(all_clus)); }
637
638 const Amg::Vector3D& gpos = road.globalPosition();
639 const Amg::Vector3D& gdir = road.globalDirection();
640 find(gpos, gdir, all_mdts, all_clus, hasPhiMeasurements, segColl, momentum, road.deltaEta());
641 }
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 1794 of file DCMathSegmentMaker.cxx.

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

◆ findMdt()

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

Definition at line 1775 of file DCMathSegmentMaker.cxx.

1775 {
1776 IdentifierHash colHash;
1777 if (m_idHelperSvc->mdtIdHelper().get_module_hash(m_idHelperSvc->chamberId(id), colHash)){
1778 ATH_MSG_VERBOSE("Invalid Mdt identifier "<<m_idHelperSvc->toString(id));
1779 return nullptr;
1780 }
1781 SG::ReadHandle<Muon::MdtPrepDataContainer> MdtCont{m_mdtKey, ctx};
1782 if (!MdtCont.isValid()) {
1783 ATH_MSG_WARNING("Cannot retrieve MdtPrepDataContainer ");
1784 return nullptr;
1785 }
1786 const MdtPrepDataCollection* collptr = MdtCont->indexFindPtr(colHash);
1787 if (!collptr) return nullptr;
1788 for (const MdtPrepData* prd : *collptr) {
1789 if (prd->identify() == id) return prd;
1790 }
1791 return nullptr;
1792 }
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 63 of file DCMathSegmentMaker.cxx.

63 {
64 ATH_CHECK(m_mdtKey.initialize(m_removeDeltas && !m_mdtKey.empty()));
65 // retrieve MuonDetectorManager
66 ATH_CHECK(m_DetectorManagerKey.initialize());
67 ATH_CHECK(m_mdtCreator.retrieve());
68 ATH_CHECK(m_mdtCreatorT0.retrieve(DisableTool{m_mdtCreatorT0.empty()}));
69 ATH_CHECK(m_clusterCreator.retrieve());
71 ATH_CHECK(m_idHelperSvc.retrieve());
72 ATH_CHECK(m_printer.retrieve());
73 ATH_CHECK(m_edmHelperSvc.retrieve());
74 ATH_CHECK(m_segmentFinder.retrieve());
76 ATH_CHECK(m_segmentFitter.retrieve(DisableTool{!m_refitParameters}));
77 ATH_CHECK(m_dcslFitProvider.retrieve(DisableTool{m_dcslFitProvider.empty()}));
78
79 // initialise for data handles
80 ATH_CHECK(m_chamberGeoKey.initialize());
81 return StatusCode::SUCCESS;
82 }
#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 2048 of file DCMathSegmentMaker.cxx.

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

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

◆ 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 2126 of file DCMathSegmentMaker.cxx.

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

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

◆ 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 1848 of file DCMathSegmentMaker.cxx.

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