Prepares the input by the fit by collecting the measurements on the segment &.
Fetch the measurements from the segment & find the first segment which has phi hits
Ensure that the drift signs from the fit are stamped onto the Uncalibrated measurements
The middle or outer segment provide the phi information. Not so easy becasue we want to Take the y0 & precision direction from the inner segment but the phi & x0 from a straight line extrapolation onto the plane
Extrapolate the seed segment onto the inner plane. We want to take the precision intercept from the inner segment and the non-precision intercept from the extrapolated segment
139 {
140 const EventContext& ctx{*calContext.get<const EventContext*>()};
142 measurements.reserve(100);
149 if (
msgLvl(MSG::VERBOSE)) {
150 std::stringstream sstr{};
154 <<
", "<<
m->numDimensions()<<
", "
155 <<
", "<<surf.geometryId()<<
" @ "<<
Amg::toString(surf.localToGlobalTransform(tgContext))<<std::endl;
156 }
158 <<
", direction: "<<
Amg::toString(segment->direction()) <<
" eta " << segment->direction().eta() <<
" phi " << segment->direction().phi() <<
"\n"<<sstr.str());
159 }
160 measurements.insert(measurements.end(),
161 std::make_move_iterator(segMeasurements.begin()),
162 std::make_move_iterator(segMeasurements.end()));
163
164
165 if (!refSeg && !isNswSegment(*segment) &&
167 refSeg = segment;
168 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Set reference segment");
169 }
170 }
171
172 if(!refSeg){
174 if (isNswSegment(*segment) &&
176 refSeg = segment;
177 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - NSW is the best what we have apparently....");
178 break;
179 }
180 }
181 }
182
183 if (!refSeg || measurements.empty()) {
185 <<" - No reference segment passing seeding quality "<<
186 (refSeg != nullptr)<<" was found. #"<<measurements.size()<<" measurements. ");
187 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
188 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
189 }
190 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - "<<measurements.size()<<
" measurements");
194 <<
", dir: "<<
Amg::toString(seedDir) <<
" eta " << seedDir.eta() <<
" phi "
195 << (seedDir.phi() /Gaudi::Units::degree) );
196
199 if (!volume) {
201 <<" - Failed to find tracking volume for any seed measurement");
202 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
203 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
204 }
205 if (volume->motherVolume() && volume->motherVolume()->isAlignable()) {
206 volume = volume->motherVolume();
207 }
209 <<" - Bounding volume "<<volume->volumeName()
210 <<
", trf: "<<
Amg::toString(volume->localToGlobalTransform(tgContext))
211 <<", bounds: "<<volume->volumeBounds());
218 const Amg::Transform3D toFirstTrf = firstSurf.localToGlobalTransform(tgContext).inverse();
219 const Amg::Vector3D locFrontSegPos = toFirstTrf * frontSegPos;
220 if (!volume->inside(tgContext, frontSegPos)) {
222 <<" not inside mother volume: "<<volume->volumeName()<<", "
223 <<
Amg::toString(volume->globalToLocalTransform(tgContext)*frontSegPos)
224 <<", bounds: "<<volume->volumeBounds()<<", "
227 }
228
232 const Acts::MultiIntersection firstIsect = firstSurf.intersect(tgContext, seedPos, seedDir,
233 Acts::BoundaryTolerance::Infinite());
234 const Amg::Vector3D locAtFirst = toFirstTrf * firstIsect.at(0).position();
235 if (firstSurf.type() == Acts::Surface::SurfaceType::Straw) {
236 const auto& bounds = static_cast<const Acts::LineBounds&>(firstSurf.bounds());
237 using enum Acts::LineBounds::BoundValues;
238
240 const Amg::Vector3D locStartPos{locFrontSegPos.x(), locFrontSegPos.y(),
241 std::clamp(locAtFirst.z(), -bounds.get(eHalfLengthZ), bounds.get(eHalfLengthZ))};
242 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - The first surface is a straw "
244 seedPos = firstSurf.localToGlobalTransform(tgContext) * locStartPos;
245 } else if (firstSurf.type() == Acts::Surface::SurfaceType::Plane) {
246 if (isNswSegment(*frontSegment)) {
247 seedPos = frontSegPos;
248 }
249 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - The first surface is a straw "
251 }
252
254 }
255
256
257 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Using seed measurement "
259 << " with volume id " << volId);
260
262 if (!boundSurf) {
263 ATH_MSG_WARNING(__func__<<
"() "<<__LINE__<<
" - Failed to find boundary surface for tracking volume");
264 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
265 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
266 }
267 std::shared_ptr<const Acts::Surface> targetSurf{};
268
269 auto propagteToBoundary = [&](const Acts::Surface& volBoundary) -> Acts::Result<Amg::Vector3D> {
270
272 auto pIsect = intersectPlane(seedPos, seedDir,
trf.linear().col(2),
trf.translation());
274 if (pIsect.pathLength() > Acts::s_epsilon || !pIsect.isValid()) {
276 <<" is forward "<<pIsect.pathLength()<<" or invalid "<<(!pIsect.isValid())
277 <<" within volume "<<volume->inside(tgContext, pIsect.position()));
278 return Acts::Result<Amg::Vector3D>::failure(std::make_error_code(std::errc::invalid_argument));
279 }
280 Acts::Result<Amg::Vector2D> locPos = volBoundary.globalToLocal(tgContext, pIsect.position(),
281 Amg::Vector3D::Zero());
282 if (!locPos.ok()){
283 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Intersection is not on surface "<<
285 return Acts::Result<Amg::Vector3D>::failure(std::make_error_code(std::errc::invalid_argument));
286 }
287 if (!volBoundary.insideBounds(*locPos)) {
288 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Intersection is outside the boundaries: "<<
290 return Acts::Result<Amg::Vector3D>::failure(std::make_error_code(std::errc::invalid_argument));
291 }
292 targetSurf = volBoundary.getSharedPtr();
293 return Acts::Result<Amg::Vector3D>::success(pIsect.position());
294 };
295
296
297 auto pIsect = propagteToBoundary(*boundSurf);
298 if (!pIsect.ok() && volume->isAlignable()) {
299 const Acts::VolumePlacementBase* placement = volume->volumePlacement();
300 for (std::size_t portal = 0; !pIsect.ok() && portal< placement->nPortalPlacements(); ++portal) {
301 pIsect = propagteToBoundary(placement->portalPlacement(portal)->surface());
302 }
303 }
304 if (!pIsect.ok()) {
305 ATH_MSG_WARNING(__func__<<
"() "<<__LINE__<<
" Cannot create valid start parameters from seed "<<seed);
306
307 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
308 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
309 }
312 auto initialPars = Acts::BoundTrackParameters::create(tgContext, targetSurf, fourPos,
313 seedDir, qOverP,
314 Acts::BoundMatrix::Identity(),
315 Acts::ParticleHypothesis::muon());
316 return std::make_pair(std::move(initialPars), std::move(measurements));
317
318 }
bool msgLvl(const MSG::Level lvl) const
std::vector< const xAOD::UncalibratedMeasurement * > MeasVec_t
const MeasVec & measurements() const
Returns the associated measurements.
Amg::Vector3D direction() const
Returns the direction as Amg::Vector.
constexpr double energyToActs(const double athenaE)
Converts an energy scalar from Athena to Acts units.
Acts::Vector4 convertPosToActs(const Amg::Vector3D &athenaPos, const double athenaTime=0.)
Converts a position vector & time from Athena units into Acts units.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
const Acts::Surface * bottomBoundary(const Acts::TrackingVolume &volume)
Returns the boundary surface parallel to the x-y plane at negative local z.
Parameters localSegmentPars(const xAOD::MuonSegment &seg)
Returns the localSegPars decoration from a xAODMuon::Segment.
std::string printID(const xAOD::MuonSegment &seg)
Print the chamber ID of a segment, e.g.
std::vector< const xAOD::UncalibratedMeasurement * > collectMeasurements(const xAOD::MuonSegment &segment, bool skipOutlier=true)
Helper function to extract the measurements from the segment.
Acts::GeometryIdentifier volumeId(const Acts::Surface &surface)
Returns the identifier of the volume in which the surface is embedded.
const xAOD::UncalibratedMeasurement * firstMeasurement(const xAOD::MuonSegment &segment, const bool skipOutlier=true)
Retrieves the first measurement associated with the segment.
Amg::Vector3D atFirstSurface(const Acts::GeometryContext &gctx, const xAOD::MuonSegment &segment, const bool skipOutlier=true)
Expresses the segment position on the surface of the first measurement.
std::string print(const cont_t &container)
Print a space point container to string.
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::Segment.
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.
const Identifier & identify(const UncalibratedMeasurement *meas)
Returns the associated identifier from the muon measurement.
MuonSegment_v1 MuonSegment
Reference the current persistent version:
const Acts::Surface & muonSurface(const UncalibratedMeasurement *meas)
Returns the associated Acts surface to the measurement.