20#include "Acts/Utilities/RangeXD.hpp"
26 double yCross = (y0 + loc.
location().
z() * tanBeta);
27 return (loc.
minY() < yCross && yCross < loc. maxY());
44 const std::array<double, 2>& chambEdges) {
46 if (chambEdges[0] <= seedEdges[0] && chambEdges[1] >= seedEdges[1]) {
50 else if (chambEdges[0]<= seedEdges[0]) {
51 return (chambEdges[1] - seedEdges[0]) / (seedEdges[1] - seedEdges[0]);
54 else if (chambEdges[1] >= seedEdges[1]) {
55 return (seedEdges[1] - chambEdges[0]) / (seedEdges[1] - seedEdges[0]);
58 else if (seedEdges[0] <= chambEdges[0] && seedEdges[1] >= chambEdges[1]) {
59 return (chambEdges[1] - chambEdges[0]) / (seedEdges[1] - seedEdges[0]);
70 return StatusCode::SUCCESS;
80 ATH_CHECK(writeMaxima.
record(std::make_unique<EtaHoughMaxContainer>()));
93 for (
auto& [station, stationHoughBuckets] : data.houghSetups) {
95 for (
auto& bucket : stationHoughBuckets) {
99 writeMaxima->push_back(std::make_unique<HoughMaximum>(std::move(
max)));
105 return (*a->parentBucket()) < (*b->parentBucket());
107 return StatusCode::SUCCESS;
114 ATH_MSG_DEBUG(
"Load " << spacePoints.size() <<
" space point buckets");
119 std::vector<HoughSetupForBucket>& buckets = data.houghSetups[bucket->front()->msSector()];
121 const Amg::Transform3D globToLoc{hs.bucket->msSector()->globalToLocalTransform(gctx)};
122 Amg::Vector3D leftSide = globToLoc.translation() - (hs.bucket->coveredMin() * Amg::Vector3D::UnitY());
123 Amg::Vector3D rightSide = globToLoc.translation() - (hs.bucket->coveredMax() * Amg::Vector3D::UnitY());
126 double zmin{1.e9}, zmax{-1.e9};
127 for (
const std::shared_ptr<MuonR4::SpacePoint> &
sp : *bucket) {
128 zmin = std::min(zmin,
sp->localPosition().z());
129 zmax = std::max(zmax,
sp->localPosition().z());
131 const double z = 0.5*(zmin + zmax);
136 hs.searchWindowTanAngle = {tanThetaLeft, tanThetaRight};
141 for (
const std::shared_ptr<MuonR4::SpacePoint> & hit : *bucket){
143 double y0l = hit->localPosition().y() - hit->localPosition().z() * tanThetaLeft;
144 double y0r = hit->localPosition().y() - hit->localPosition().z() * tanThetaRight;
149 hs.searchWindowIntercept = {
ymin,
ymax};
153 switch (hit->
type()){
156 return dc->status() == Muon::MdtDriftCircleStatus::MdtStatusDriftTime;
171 HoughPlaneConfig cfg;
178 data.houghPlane = std::make_unique<HoughPlane>(cfg);
179 data.peakFinder = std::make_unique<ActsPeakFinderForMuon>(peakFinderCfg);
185 int expectedPrecisionChambers{0}, seenPrecisionChambers{0};
186 bool hasTrig =
false;
188 std::unordered_set<const MuonGMR4::MuonReadoutElement*> seenChambers{};
189 std::set<std::pair<int,int>> seenLayers;
192 std::array<double, 2> tubeExtend{halfX, -halfX};
194 auto addSeenHit = [&tubeExtend, &seenLayers, &seenChambers](
const SpacePoint&
sp,
196 const double sensorL,
197 const int mL,
const int layer){
198 seenLayers.emplace(mL, layer);
199 seenChambers.insert(
re);
200 tubeExtend[0] = std::min(tubeExtend[0],
sp.localPosition().x() - sensorL);
201 tubeExtend[1] = std::max(tubeExtend[1],
sp.localPosition().x() + sensorL);
203 for (
const SpacePoint* SP : maximum.hitIdentifiers){
204 ATH_MSG_VERBOSE(__func__<<
"() - "<<__LINE__<<
" Maximum has associated hit in "
211 addSeenHit(*SP,
re, 0.5*
re->activeTubeLength(dc->measurementHash()),
212 re->multilayer(), dc->tubeLayer());
216 addSeenHit(*SP,
re, 0.5*
re->stripLayer(clust->measurementHash()).design().stripLength(clust->channelNumber()),
217 re->multilayer(), clust->gasGap());
221 addSeenHit(*SP,
re, 0.5*
re->stripLayer(clust->measurementHash()).design().stripLength(clust->channelNumber()),
222 re->multilayer(), clust->gasGap());
232 ATH_MSG_VERBOSE(__func__<<
"() - "<<__LINE__<<
" maximum does not cross "
233 <<
m_idHelperSvc->toStringDetEl(muonChamber.readoutEle()->identify()));
237 <<
m_idHelperSvc->toStringDetEl(muonChamber.readoutEle()->identify())<<
", "
238 <<(*muonChamber.bounds())<<
", @: "<<
Amg::toString(muonChamber.location()));
243 const bool hasHit = seenChambers.count(muonChamber.readoutEle());
249 ++seenPrecisionChambers;
254 }
else if (precTech) {
257 const double lowL = muonChamber.width(maximum.y + muonChamber.location().z() * maximum.x);
258 const std::array<double, 2> chambEdges{muonChamber.location().x() - lowL,
259 muonChamber.location().x() + lowL};
262 if (coverage < 0.95){
263 ATH_MSG_VERBOSE(__func__<<
"() - "<<__LINE__<<
" Reject chamber due to partial coverage: "<<coverage
264 <<
", chamb extend: "<<chambEdges[0]<<
"-"<<chambEdges[1]
265 <<
", tube extend: "<<tubeExtend[0]<<
"-"<<tubeExtend[1]
266 <<
", "<<(*muonChamber.readoutEle()->msSector()->bounds()));
272 ++expectedPrecisionChambers;
276 int minLayers = seenLayers.size() / 2 + 1;
278 int minSeenPrecisionChambers = (expectedPrecisionChambers > 1) + 1;
282 minSeenPrecisionChambers = 1;
285 ", seen prec: "<<seenPrecisionChambers<<
", required: "<<minSeenPrecisionChambers
286 <<
" -- layers: "<<seenLayers.size()<<
", required: "<<
minLayers);
289 return seenPrecisionChambers >= minSeenPrecisionChambers && (int)seenLayers.size() >=
minLayers;
296 primitives.push_back(
MuonValR4::drawBox(chamber.minY(), chamber.minZ(), chamber.maxY(), chamber.maxZ(), kGray+2));
299 const Identifier detId{chamber.readoutEle()->identify()};
301 std::string chLabel = std::format(
"{:}{:1d}{:}{:2d}",
m_idHelperSvc->stationNameString(detId),
303 switch (chamber.readoutEle()->detectorType()) {
305 chLabel += std::format(
"M{:1d}",
m_idHelperSvc->mdtIdHelper().multilayer(detId));
313 primitives.push_back(
MuonValR4::drawLabel(std::format(
"{} Segment seed", (seedPassedSelection) ?
"Accepted" :
"Rejected"),0.05,0.03,12));
314 m_visionTool->visualizeSeed(ctx, seed,
"#eta-HoughSeed", std::move(primitives));
319 <<
" with " << maxima.size() <<
" maxima found");
322 primitivesForAcc.push_back(
MuonValR4::drawLabel( std::format(
"Event: {:}, chamber : {:} nMaximaFound : {:}", ctx.eventID().event_number(), bucket.bucket->
msSector()->
identString(), maxima.size() ),0.05,0.06,12));
326 for (
const auto&
max : maxima) {
327 unsigned nPrec{0}, nTotal{0};
328 unsigned nPrecCentreBin{0}, nTotalCentreBin{0};
337 auto toBins = [&data](
double x,
double y){
338 return std::make_pair(
339 Acts::HoughTransformUtils::binIndex(data.currAxisRanges.xMin, data.currAxisRanges.xMax, data.houghPlane->nBinsX(),
x),
340 Acts::HoughTransformUtils::binIndex(data.currAxisRanges.yMin, data.currAxisRanges.yMax, data.houghPlane->nBinsY(),
y)
344 auto accumulatorBins = toBins(
max.x,
max.y);
345 for (
const HoughHitType& hit : data.houghPlane->hitIds(accumulatorBins.first, accumulatorBins.second)) {
350 primitivesForAcc.push_back(
MuonValR4::drawLabel(std::format(
"Maximum at (tanTheta, y0) = ({:.2f}, {:.1f}) with {}/{} (precWIsland/totalWIsland) and {}/{} (precWCentre/totalWCentre)",
max.x,
max.y, nPrec, nTotal, nPrecCentreBin, nTotalCentreBin),0.05,0.03 - iMax*0.01,10));
354 m_visionTool->visualizeAccumulator(ctx, *data.houghPlane, data.currAxisRanges, maxima,
355 "EtaHoughAccumulator", std::move(primitivesForAcc));
365 <<
", with hits in the bucket in "<< bucket.bucket->
coveredMin()
367 <<
". The bucket found a search range of ("
368 <<bucket.searchWindowTanAngle.first<<
" - "
369 <<bucket.searchWindowTanAngle.second<<
") and ("
370 <<bucket.searchWindowIntercept.first<<
" - "
371 <<bucket.searchWindowIntercept.second
374 double chamberCenter = 0.5 * (bucket.searchWindowIntercept.first +
375 bucket.searchWindowIntercept.second);
382 searchStart = std::min(searchStart, bucket.searchWindowIntercept.first -
384 searchEnd = std::max(searchEnd, bucket.searchWindowIntercept.second +
387 double tanThetaMean = 0.5 * (bucket.searchWindowTanAngle.first +
388 bucket.searchWindowTanAngle.second);
389 double searchStartTanTheta = tanThetaMean - 0.5 * data.houghPlane->nBinsX() *
m_targetResoTanTheta;
390 double searchEndTanTheta = tanThetaMean + 0.5 * data.houghPlane->nBinsX() *
m_targetResoTanTheta;
391 searchStartTanTheta = std::min(searchStartTanTheta, bucket.searchWindowTanAngle.first -
393 searchEndTanTheta = std::max(searchEndTanTheta, bucket.searchWindowTanAngle.second +
396 data.currAxisRanges = Acts::HoughTransformUtils::HoughAxisRanges{
397 searchStartTanTheta, searchEndTanTheta, searchStart, searchEnd};
399 data.houghPlane->reset();
400 for (
const SpacePointBucket::value_type& hit : *(bucket.bucket)) {
405 <<
":\n Mean tanBeta was "<<tanThetaMean
406 <<
" and my intercept "<<chamberCenter
407 <<
", with hits in the bucket in "<< bucket.bucket->
coveredMin()
409 <<
". The bucket found a search range of ("
410 <<bucket.searchWindowTanAngle.first<<
" - "
411 <<bucket.searchWindowTanAngle.second<<
") and ("
412 <<bucket.searchWindowIntercept.first<<
" - "
413 <<bucket.searchWindowIntercept.second
414 <<
") , and my final search range is ["
415 <<searchStartTanTheta<<
" - "<<searchEndTanTheta
416 <<
"] and ["<<searchStart<<
" - "<<searchEnd
421 auto maxima = data.peakFinder->findPeaks(*(data.houghPlane), data.currAxisRanges);
428 if (maxima.empty()) {
435 std::set<HoughHitType> seenHits;
438 for (
const auto&
max : maxima) {
440 <<
") with " <<
max.hitIdentifiers.size() <<
" hits");
443 bool maxPassSelection =
true;
444 unsigned int nPrec{0};
445 auto toBins = [&data](
double x,
double y){
446 return std::make_pair(
447 Acts::HoughTransformUtils::binIndex(data.currAxisRanges.xMin, data.currAxisRanges.xMax, data.houghPlane->nBinsX(),
x),
448 Acts::HoughTransformUtils::binIndex(data.currAxisRanges.yMin, data.currAxisRanges.yMax, data.houghPlane->nBinsY(),
y)
452 auto accumulatorBins = toBins(
max.x,
max.y);
453 for (
const HoughHitType& hit : data.houghPlane->hitIds(accumulatorBins.first, accumulatorBins.second)) {
454 auto res = seenHits.emplace(hit);
461 std::vector<HoughHitType> hitList{
max.hitIdentifiers.begin(),
max.hitIdentifiers.end()};
465 ATH_MSG_VERBOSE(
"Did not pass nPrecisionHit cuts or seedQuality cuts. Number of precision hits in the centre bin of maxima " << nPrec <<
" (required " <<
m_nPrecHitCut <<
")");
466 maxPassSelection =
false;
475 size_t nHits = hitList.size();
481 std::ranges::stable_sort(hitList, sorter);
487 if (maxPassSelection) data.maxima.emplace_back(houghMax);
502 using namespace std::placeholders;
517 const unsigned precisionLayerIndex = (dc->readoutElement()->multilayer() * 10 + dc->tubeLayer());
532 const double tanBeta,
533 const double interceptY)
const {
534 const Amg::Vector3D maxPos = interceptY * Amg::Vector3D::UnitY();
535 const Amg::Vector3D maxDir = Acts::makeDirectionFromAxisTangents(0., tanBeta);
537 for (
const SpacePointBucket::value_type& hit : *bucket.bucket) {
538 if (hit->measuresEta()){
544 const double distAlongStrip = std::abs(dir.dot(SeedingAux::extrapolateToPlane(maxPos,maxDir, *hit) - pos));
545 const double stripL = std::sqrt(hit->covariance()[Acts::toUnderlying(AxisDefs::etaCov)]);
547 hitList.push_back(hit.get());
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
std::pair< std::vector< unsigned int >, bool > res
static const uint32_t nHits
Readout element to describe the Monitored Drift Tube (Mdt) chambers Mdt chambers usually comrpise out...
MuonReadoutElement is an abstract class representing the geometry of a muon detector.
std::string identString() const
Returns a string encoding the chamber index & the sector of the MS sector.
double halfXLong() const
Long-extend of the chamber in the x-direction at positive Y.
Data class to represent an eta maximum in hough space.
Representation of a segment seed (a fully processed hough maximum) produced by the hough transform.
: The muon space point bucket represents a collection of points that will bre processed together in t...
const MuonGMR4::SpectrometerSector * msSector() const
returns th associated muonChamber
double coveredMin() const
lower interval value covered by the bucket
double coveredMax() const
upper interval value covered by the bucket
MuonGMR4::SpectrometerSector::chamberLocation chamberLocation
const std::vector< chamberLocation > & chamberLocations() const
returns the list of all tracking chambers in the bucket for fast navigation
The SpacePointPerLayerSorter sort two given space points by their layer Identifier.
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
const Identifier & identify() const
: Identifier of the primary measurement
xAOD::UncalibMeasType type() const
const xAOD::MuonMeasurement * primaryMeasurement() const
unsigned nEtaInstanceCounts() const
How many space points have been built in total with the same eta prd.
bool measuresEta() const
: Does the space point contain an eta measurement
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
virtual const MuonGMR4::MuonReadoutElement * readoutElement() const =0
Returns the pointer to the associated readout element.
virtual xAOD::UncalibMeasType type() const =0
Returns the type of the measurement type as a simple enumeration.
DetectorType
Simple enum to Identify the Type of the ACTS sub detector.
@ Mm
Maybe not needed in the migration.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
double houghWidthStrip(double tanBeta, const MuonR4::HoughHitType &strip, double targetReso)
Uncertainty parametrisation for strip measurements.
double houghParamMdtRight(double tanBeta, const MuonR4::HoughHitType &dc)
right-side straight line parametrisation for drift circles
double houghParamStrip(double tanBeta, const MuonR4::HoughHitType &strip)
straight line parametrisation for strip detector measurements
double houghWidthMdt(double tanBeta, const MuonR4::HoughHitType &dc, double targetReso)
uncertainty parametrisation for drift circles
double houghParamMdtLeft(double tanBeta, const MuonR4::HoughHitType &dc)
left-side straight line parametrisation for drift circles
This header ties the generic definitions in this package.
double proximity(const SpacePoint *dc, double y0, double tanBeta)
constexpr double chamberCoverage(const std::array< double, 2 > &seedEdges, const std::array< double, 2 > &chambEdges)
Calculates how much of the unkknown coordinate along the tube range is covered by the chamber of inte...
bool passesThrough(const SpacePointBucket::chamberLocation &loc, double y0, double tanBeta)
constexpr unsigned minLayers
HoughEventData_impl< ActsPeakFinderForMuon, ActsPeakFinderForMuonCfg > HoughEventData
Acts::HoughTransformUtils::PeakFinders::IslandsAroundMaxConfig ActsPeakFinderForMuonCfg
const SpacePoint * HoughHitType
DataVector< SpacePointBucket > SpacePointContainer
Abrivation of the space point container type.
std::unique_ptr< TLatex > drawLabel(const std::string &text, const double xPos, const double yPos, const double textSize=18, const bool useNDC=true, const int color=kBlack)
Create a TLatex label,.
std::unique_ptr< TBox > drawBox(const Amg::Vector3D &boxCenter, const double boxWidth, const double boxHeight, const int color=kGreen+2, const int fillStyle=hollowFilling, const int view=objViewEta)
Creates a box for drawing, e.g strip measurements.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
MdtDriftCircle_v1 MdtDriftCircle
sTgcMeasurement_v1 sTgcMeasurement
double minY() const
Returns the minimum y covered by the chamber location.
const Amg::Vector3D & location() const
Returns the location.