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
136 {
137 const EventContext& ctx{*calContext.get<const EventContext*>()};
139 measurements.reserve(100);
146 if (
msgLvl(MSG::VERBOSE)) {
147 std::stringstream sstr{};
151 <<
", "<<
m->numDimensions()<<
", "
152 <<
", "<<surf.geometryId()<<
" @ "<<
Amg::toString(surf.localToGlobalTransform(tgContext))<<std::endl;
153 }
155 <<
", direction: "<<
Amg::toString(segment->direction()) <<
" eta " << segment->direction().eta() <<
" phi " << segment->direction().phi() <<
"\n"<<sstr.str());
156 }
157 measurements.insert(measurements.end(),
158 std::make_move_iterator(segMeasurements.begin()),
159 std::make_move_iterator(segMeasurements.end()));
160
161
162 if (!refSeg && !isNswSegment(*segment) &&
164 refSeg = segment;
165 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Set reference segment");
166 }
167 }
168
169 if(!refSeg){
171 if (isNswSegment(*segment) &&
173 refSeg = segment;
174 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - NSW is the best what we have apparently....");
175 break;
176 }
177 }
178 }
179
180 if (!refSeg || measurements.empty()) {
182 <<" - No reference segment passing seeding quality "<<
183 (refSeg != nullptr)<<" was found. #"<<measurements.size()<<" measurements. ");
184 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
185 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
186 }
187 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - "<<measurements.size()<<
" measurements");
191 <<
", dir: "<<
Amg::toString(seedDir) <<
" eta " << seedDir.eta() <<
" phi "
192 << (seedDir.phi() /Gaudi::Units::degree) );
193
196 if (!volume) {
198 <<" - Failed to find tracking volume for any seed measurement");
199 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
200 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
201 }
202 if (volume->motherVolume() && volume->motherVolume()->isAlignable()) {
203 volume = volume->motherVolume();
204 }
206 <<" - Bounding volume "<<volume->volumeName()
207 <<
", trf: "<<
Amg::toString(volume->localToGlobalTransform(tgContext))
208 <<", bounds: "<<volume->volumeBounds());
215 const Amg::Transform3D toFirstTrf = firstSurf.localToGlobalTransform(tgContext).inverse();
216 const Amg::Vector3D locFrontSegPos = toFirstTrf * frontSegPos;
217 if (!volume->inside(tgContext, frontSegPos)) {
219 <<" not inside mother volume: "<<volume->volumeName()<<", "
220 <<
Amg::toString(volume->globalToLocalTransform(tgContext)*frontSegPos)
221 <<", bounds: "<<volume->volumeBounds()<<", "
224 }
225
229 const Acts::MultiIntersection firstIsect = firstSurf.intersect(tgContext, seedPos, seedDir,
230 Acts::BoundaryTolerance::Infinite());
231 const Amg::Vector3D locAtFirst = toFirstTrf * firstIsect.at(0).position();
232 if (firstSurf.type() == Acts::Surface::SurfaceType::Straw) {
233 const auto& bounds = static_cast<const Acts::LineBounds&>(firstSurf.bounds());
234 using enum Acts::LineBounds::BoundValues;
235
237 const Amg::Vector3D locStartPos{locFrontSegPos.x(), locFrontSegPos.y(),
238 std::clamp(locAtFirst.z(), -bounds.get(eHalfLengthZ), bounds.get(eHalfLengthZ))};
239 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - The first surface is a straw "
241 seedPos = firstSurf.localToGlobalTransform(tgContext) * locStartPos;
242 } else if (firstSurf.type() == Acts::Surface::SurfaceType::Plane) {
243 if (isNswSegment(*frontSegment)) {
244 seedPos = frontSegPos;
245 }
246 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - The first surface is a straw "
248 }
249
251 }
252
253
254 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Using seed measurement "
256 << " with volume id " << volId);
257
259 if (!boundSurf) {
260 ATH_MSG_WARNING(__func__<<
"() "<<__LINE__<<
" - Failed to find boundary surface for tracking volume");
261 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
262 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
263 }
264 std::shared_ptr<const Acts::Surface> targetSurf{};
265
266 auto propagteToBoundary = [&](const Acts::Surface& volBoundary) -> Acts::Result<Amg::Vector3D> {
267
269 auto pIsect = intersectPlane(seedPos, seedDir,
trf.linear().col(2),
trf.translation());
271 if (pIsect.pathLength() > Acts::s_epsilon || !pIsect.isValid()) {
273 <<" is forward "<<pIsect.pathLength()<<" or invalid "<<(!pIsect.isValid())
274 <<" within volume "<<volume->inside(tgContext, pIsect.position()));
275 return Acts::Result<Amg::Vector3D>::failure(std::make_error_code(std::errc::invalid_argument));
276 }
277 Acts::Result<Amg::Vector2D> locPos = volBoundary.globalToLocal(tgContext, pIsect.position(),
278 Amg::Vector3D::Zero());
279 if (!locPos.ok()){
280 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Intersection is not on surface "<<
282 return Acts::Result<Amg::Vector3D>::failure(std::make_error_code(std::errc::invalid_argument));
283 }
284 if (!volBoundary.insideBounds(*locPos)) {
285 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Intersection is outside the boundaries: "<<
287 return Acts::Result<Amg::Vector3D>::failure(std::make_error_code(std::errc::invalid_argument));
288 }
289 targetSurf = volBoundary.getSharedPtr();
290 return Acts::Result<Amg::Vector3D>::success(pIsect.position());
291 };
292
293
294 auto pIsect = propagteToBoundary(*boundSurf);
295 if (!pIsect.ok() && volume->isAlignable()) {
296 const Acts::VolumePlacementBase* placement = volume->volumePlacement();
297 for (std::size_t portal = 0; !pIsect.ok() && portal< placement->nPortalPlacements(); ++portal) {
298 pIsect = propagteToBoundary(placement->portalPlacement(portal)->surface());
299 }
300 }
301 if (!pIsect.ok()) {
302 ATH_MSG_WARNING(__func__<<
"() "<<__LINE__<<
" Cannot create valid start parameters from seed "<<seed);
303
304 return std::make_pair(OptBoundPars_t::failure(std::make_error_code(std::errc::invalid_argument)),
305 std::vector<const xAOD::UncalibratedMeasurement_v1*>{});
306 }
309 *mfContext.get<const AtlasFieldCacheCondObj*>(), seed));
310 auto initialPars = Acts::BoundTrackParameters::create(tgContext, targetSurf, fourPos,
311 seedDir, qOverP,
312 Acts::BoundMatrix::Identity(),
313 Acts::ParticleHypothesis::muon());
314 return std::make_pair(std::move(initialPars), std::move(measurements));
315
316 }
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.