36 double pull{std::numeric_limits<double>::max()};
37 std::unique_ptr<Trk::TrackParameters> pars{};
38 std::unique_ptr<Muon::MuonClusterOnTrack> clus{};
40 using ClusterLayerMap = std::map<Identifier, PullCluster>;
49 return m_trk.trackStateOnSurfaces()->begin();
52 return m_trk.trackStateOnSurfaces()->end();
82 std::unique_ptr<Trk::TrackStates> outVec = std::make_unique<Trk::TrackStates>();
83 for (std::unique_ptr<const Trk::TrackStateOnSurface>&
tsos :
m_newStates){
84 outVec->push_back(std::move(
tsos));
91 declareInterface<IMuonHoleRecoveryTool>(
this);
119 return StatusCode::SUCCESS;
127 if (msVol.
inside(pars->position())) {
140 ATH_MSG_VERBOSE(
"The track state does not have an associated measurement");
157 std::set<Identifier> layerIds{};
164 layerIds.insert(measId);
168 if (!comp) {
continue; }
189 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(track.info(), recovState.
releaseStates(),
190 track.fitQuality() ? track.fitQuality()->uniqueClone() :
nullptr);
196 std::set<Identifier> chambInStation{};
220 NewTrackStates& newStates, std::set<Identifier>& knownLayers)
const {
223 std::set<Identifier> chHoles =
holesInMdtChamber(ctx, pars.position(), pars.momentum().unit(), chId, knownLayers);
225 if (chHoles.empty())
return;
228 bool addedState{
false};
239 if (!surf.
globalToLocal(exPars->position(), exPars->momentum(), locPos)) {
244 chHoles.erase(mdtPrd->identify());
250 std::unique_ptr<MdtDriftCircleOnTrack> mdtROT{
m_mdtRotCreator->createRIO_OnTrack(*mdtPrd,
253 if (!mdtROT)
continue;
261 std::optional<const Trk::ResidualPull> resPull{
m_pullCalculator->residualPull(mdtROT.get(),
264 if (!resPull) {
continue; }
266 const double pull = resPull->pull().front();
267 const double radialResidual = std::abs(mdtROT->localParameters()[
Trk::locR]) -
268 std::abs(exPars->parameters()[
Trk::locR]);
270 unsigned int hitFlag = 1;
275 else if (radialResidual > 0.)
286 newStates.emplace_back(std::move(tsos));
290 if (prevDC->
identify() != mdtPrd->identify()) {
291 newStates.emplace_back(std::move(tsos));
293 ATH_MSG_DEBUG(
"Two hits recorded for the same tube "<<std::endl<<
294 " *** current: "<<
m_printer->print(*tsos->measurementOnTrack())<<std::endl<<
295 " *** previous: "<<
m_printer->print(*prevDC));
296 std::optional<Trk::ResidualPull> prevPullObj{
m_pullCalculator->residualPull(prevDC,
297 tsos->trackParameters(),
299 const double prevPull = prevPullObj->pull().front();
301 if (std::abs(pull) < std::abs(prevPull) ||
304 newStates.back() = std::move(tsos);
309 chHoles.erase(mdtPrd->identify());
310 knownLayers.insert(mdtPrd->identify());
327 NewTrackStates& states, std::set<Identifier>& knownLayers)
const {
341 states.insert(states.end(), std::make_move_iterator(recovered.begin()),
342 std::make_move_iterator(recovered.end()));
345 const EventContext& ctx,
347 std::set<Identifier>& layIds,
359 ATH_MSG_ERROR(
"Null pointer to the read MuonDetectorManager conditions object");
379 const Identifier& chId,
const std::set<Identifier>& tubeIds)
const {
383 ATH_MSG_ERROR(
"Failed to retrieve chamber intersection service");
384 throw std::runtime_error(
"No chamber intersection service");
391 MuonStationIntersect intersect = interSectSvc->tubesCrossedByTrack(MuonDetMgr, chId, position, direction);
394 std::set<Identifier> holes;
395 for (
unsigned int ii = 0; ii < intersect.tubeIntersects().size(); ++ii) {
398 if (tubeIds.count(tint.
tubeId)) {
continue; }
408 holes.insert(tint.
tubeId);
415 const std::set<Identifier>& gasGapIds)
const {
416 std::vector<const Prd*> collectedHits{};
418 ATH_MSG_DEBUG(
"No container configured for "<<
typeid(Prd).name());
419 return collectedHits;
423 ATH_MSG_FATAL(
"Failed to load prep data collection "<<key.fullKey());
424 throw std::runtime_error(
"Invalid prepdata container");
427 std::set<IdentifierHash> chamberIds{};
428 std::transform(gasGapIds.begin(), gasGapIds.end(),
429 std::inserter(chamberIds, chamberIds.end()),
431 return m_idHelperSvc->moduleHash(id);
435 if (!prdColl)
continue;
436 collectedHits.reserve(collectedHits.size() + prdColl->
size());
437 for (
const Prd* prd: *prdColl) {
438 bool appendPrd{
false};
439 if constexpr (std::is_same<Prd, MdtPrepData>::value) {
440 appendPrd = gasGapIds.count(prd->identify());
442 appendPrd = gasGapIds.count(
m_idHelperSvc->layerId(prd->identify()));
446 collectedHits.push_back(prd);
452 if constexpr(std::is_same<Prd, MdtPrepData>::value) {
453 std::sort(collectedHits.begin(), collectedHits.end(), [](
const Prd*
a,
const Prd* b){
454 return a->identify() < b->identify();
457 return collectedHits;
460 const std::set<Identifier>& knownLayers)
const {
461 std::set<Identifier> holeGaps{};
468 if (!knownLayers.count(layerId)) holeGaps.insert(layerId);
473 for (
int ml : {1 ,2}) {
476 if (!knownLayers.count(layerId)) holeGaps.insert(layerId);
482 for (
int ml : {1, 2}) {
483 for (
const channelType
chType : {channelType::Strip,
489 if (!knownLayers.count(layerId)) holeGaps.insert(layerId);
495 const int gapMax{idHelper.
gasGapMax(detElId)};
496 for (
int gasgap = idHelper.
gasGapMin(detElId);
497 gasgap < gapMax; ++gasgap){
498 for (
int measPhi: {0,1}) {
500 if (gapMax == 3 && gasgap ==2 && measPhi == 1)
continue;
502 if (!knownLayers.count(layerId)) holeGaps.insert(layerId);
507 const int doubZ{idHelper.
doubletZ(detElId)};
508 const int gapMax{idHelper.
gasGapMax(detElId)};
509 for (
int phiGap = idHelper.
doubletPhi(detElId);
511 for (
int gap = idHelper.
gasGapMin(detElId);
512 gap <= gapMax; ++gap) {
513 for (
int measPhi: {0, 1}) {
515 if (!knownLayers.count(layerId)) holeGaps.insert(layerId);
521 for (
int layer = 1; layer <= 4; ++ layer) {
522 for (
bool measPhi: {
false,
true}) {
524 if (!knownLayers.count(layId)) holeGaps.insert(layId);
534 std::set<Identifier>& knownLayers)
const {
536 const std::set<Identifier> missingLayers =
getHoleLayerIds(detElId, knownLayers);
537 std::vector<const Prd*> prdCandidates =
loadPrepDataHits(ctx, prdKey, missingLayers);
539 using LayerParsMap = std::map<Identifier, std::unique_ptr<Trk::TrackParameters>>;
540 LayerParsMap parsAtSurfMap{};
541 for (
const Identifier& holeId : missingLayers) {
544 std::unique_ptr<Trk::TrackParameters> pars =
m_extrapolator->extrapolateDirectly(ctx, parsInChamb, surf,
556 bool inbounds{
false};
557 if constexpr(std::is_same<Prd, MMPrepData>::value) {
565 <<
" is outside of the chamber "<<
Amg::toString(locExPos, 2));
568 parsAtSurfMap[holeId] = std::move(pars);
570 ClusterLayerMap bestClusterInLay;
572 for (
const Prd* hit : prdCandidates) {
575 LayerParsMap::const_iterator pars_itr = parsAtSurfMap.find(layId);
576 if (pars_itr == parsAtSurfMap.end()) {
579 const std::unique_ptr<Trk::TrackParameters>& parsInLay{pars_itr->second};
580 std::unique_ptr<MuonClusterOnTrack> calibClus{};
581 if constexpr(std::is_same<Prd, CscPrepData>::value) {
583 parsInLay->position(),
584 parsInLay->momentum().unit()));
587 parsInLay->position(),
588 parsInLay->momentum().unit()));
590 if (!calibClus)
continue;
592 if constexpr (std::is_same<Prd, sTgcPrepData>::value) {
608 const double xPull = padDist.x() / xCov;
609 const double yPull = padDist.y() / yCov;
613 <<
" covariance: ("<<xCov<<
", "<<yCov<<
")"
614 <<
" pull: ("<<xPull<<
","<<yPull<<
").");
618 const double pull = std::hypot(xPull, yPull);
621 PullCluster& bestClus = bestClusterInLay[layId];
622 if (bestClus.pull < pull)
continue;
623 bestClus.pull = pull;
624 bestClus.clus = std::move(calibClus);
625 bestClus.pars = parsInLay->uniqueClone();
631 std::optional<const Trk::ResidualPull> resPull{
634 if (!resPull || resPull->pull().empty()) {
638 const double pull = std::abs(resPull->pull().front());
641 if (pull > pullCut)
continue;
643 PullCluster& bestClus = bestClusterInLay[layId];
644 if (bestClus.pull < pull)
continue;
645 bestClus.pull = pull;
646 bestClus.clus = std::move(calibClus);
647 bestClus.pars = parsInLay->uniqueClone();
651 for (
auto& [layerId, foundClus]: bestClusterInLay) {
654 std::move(foundClus.pars),
656 recoveredStates.emplace_back(std::move(tsos));
657 knownLayers.insert(layerId);
658 parsAtSurfMap[layerId].reset();
661 for (
auto& [layerId, exPars] : parsAtSurfMap) {
662 if (!exPars)
continue;
666 return recoveredStates;
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
sTgcIdHelper::sTgcChannelTypes chType
Identifier channelID(int stationName, int stationEta, int stationPhi, int chamberLayer, int wireLayer, int measuresPhi, int strip) const
DataModel_detail::const_iterator< DataVector > const_iterator
size_type size() const noexcept
Returns the number of elements in the collection.
This is a "hash" representation of an Identifier.
bool is_valid() const
Check if id is in a valid state.
static int tubeLayerMax()
int numberOfMultilayers(const Identifier &id) const
static int tubeLayerMin()
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int tubeLayer, int tube) const
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
An MMReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station con...
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const RpcReadoutElement * getRpcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
const MdtReadoutElement * getMdtReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
const MMReadoutElement * getMMReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
const TgcReadoutElement * getTgcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
const sTgcReadoutElement * getsTgcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
const CscReadoutElement * getCscReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Class for competing MuonClusters, it extends the Trk::CompetingRIOsOnTrack base class.
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
Class to represent measurements from the Monitored Drift Tubes.
Base class for Muon cluster RIO_OnTracks.
Template to hold collections of MuonPrepRawData objects.
static std::unique_ptr< Trk::TrackStateOnSurface > createHoleTSOS(std::unique_ptr< Trk::TrackParameters > pars)
create a hole TSOS, takes ownership of the pointers
static std::unique_ptr< Trk::TrackStateOnSurface > createMeasTSOS(std::unique_ptr< Trk::MeasurementBase > meas, std::unique_ptr< Trk::TrackParameters > pars, Trk::TrackStateOnSurface::TrackStateOnSurfaceType type)
create a TSOS with a measurement, takes ownership of the pointers
Identifier channelID(int stationName, int stationEta, int stationPhi, int doubletR, int doubletZ, int doubletPhi, int gasGap, int measuresPhi, int strip) const
int doubletPhi(const Identifier &id) const
static int doubletPhiMax()
int doubletZ(const Identifier &id) const
const_pointer_type cptr()
Property holding a SG store/key/clid from which a ReadHandle is made.
bool isPresent() const
Is the referenced object present in SG?
static int gasGapMax(bool triplet)
Identifier channelID(int stationName, int stationEta, int stationPhi, int gasGap, int isStrip, int channel) const
@ MuonSpectrometerEntryLayer
Tracking Volume which defines the entrance surfaces of the MS.
This class is the pure abstract base class for all fittable tracking measurements.
Identifier identify() const
return the identifier -extends MeasurementBase
@ Unbiased
RP with track state that has measurement not included.
Class for a StraightLineSurface in the ATLAS detector to describe dirft tube and straw like detectors...
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...
virtual bool insideBounds(const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const override final
This surface calls the iside method of the bouns.
Abstract Base Class for tracking surfaces.
virtual bool insideBounds(const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const =0
virtual methods to be overwritten by the inherited surfaces
represents the track state (measurement, material, fit parameters and quality) at a surface.
const MeasurementBase * measurementOnTrack() const
returns MeasurementBase const overload
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
bool type(const TrackStateOnSurfaceType type) const
Use this method to find out if the TSoS is of a certain type: i.e.
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
@ Hole
A hole on the track - this is defined in the following way.
This is the base class for all tracking detector elements with read-out relevant information.
virtual const Surface & surface() const =0
Return surface associated with this detector element.
Base class for all volumes inside the tracking realm, it defines the interface for inherited Volume c...
bool inside(const Amg::Vector3D &gp, double tol=0.) const
Inside() method for checks.
int channelType(const Identifier &id) const
int channel(const Identifier &id) const override
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channelType, int channel) const
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
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 ...
bool hasPositiveDiagElems(const AmgSymMatrix(N) &mat)
Returns true if all diagonal elements of the covariance matrix are finite aka sane in the above defin...
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
ChIndex
enum to classify the different chamber layers in the muon spectrometer
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
MuonChamberHoleRecoveryTool::NewTrackStates NewTrackStates
MuonPrepDataContainer< MuonPrepDataCollection< PrdType > > MuonPrepDataContainerT
@ MdtStatusDriftTime
The tube produced a vaild measurement.
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)
ParametersBase< TrackParametersDim, Charged > TrackParameters
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
Parameters defining the design of the readout sTGC pads.
Amg::Vector2D distanceToPad(const Amg::Vector2D &pos, int channel) const