13 #include "Acts/Surfaces/AnnulusBounds.hpp"
14 #include "Acts/Utilities/TrackHelpers.hpp"
16 using namespace Acts::UnitLiterals;
21 MeasurementToTrackParticleDecorationAlg::MeasurementToTrackParticleDecorationAlg(
const std::string &
name,
22 ISvcLocator *pSvcLocator) :
79 return StatusCode::SUCCESS;
124 std::optional<ActsTrk::TrackContainer::ConstTrackProxy> >::
value);
125 std::optional<ActsTrk::TrackContainer::ConstTrackProxy> optional_track = *link_to_track;
127 if ( not optional_track.has_value() ) {
128 ATH_MSG_WARNING(
"Invalid track link for particle " << track_particle->index() <<
". Skipping track..");
132 ATH_MSG_DEBUG(
"Track link found for track particle with index " << track_particle->index());
133 ActsTrk::TrackContainer::ConstTrackProxy track = optional_track.value();
135 std::vector<int>& regions{measurementRegionHandle(*track_particle)};
136 regions.reserve(track.nMeasurements());
137 std::vector<int>&
detectors{measurementDetectorHandle(*track_particle)};
138 detectors.reserve(track.nMeasurements());
139 std::vector<int>&
layers{measurementLayerHandle(*track_particle)};
140 layers.reserve(track.nMeasurements());
141 std::vector<int>& types{measurementTypeHandle(*track_particle)};
142 types.reserve(track.nMeasurements());
143 std::vector<float>& predchi2s{chi2HitPredictedHandle(*track_particle)};
144 predchi2s.reserve(track.nMeasurements());
145 std::vector<float>& filtchi2s{chi2HitFilteredHandle(*track_particle)};
146 filtchi2s.reserve(track.nMeasurements());
148 std::vector<int>& sizesPhi{measurementPhiWidthHandle(*track_particle)};
149 sizesPhi.reserve(track.nMeasurements());
150 std::vector<int>& sizesEta{measurementEtaWidthHandle(*track_particle)};
151 sizesEta.reserve(track.nMeasurements());
152 std::vector<float>& residualsLocX{residualLocXhandle(*track_particle)};
153 residualsLocX.reserve(track.nMeasurements());
154 std::vector<float>& pullsLocX{pullLocXhandle(*track_particle)};
155 pullsLocX.reserve(track.nMeasurements());
156 std::vector<float>& measurementsLocX{measurementLocXhandle(*track_particle)};
157 measurementsLocX.reserve(track.nMeasurements());
158 std::vector<float>& trackParametersLocX{trackParameterLocXhandle(*track_particle)};
159 trackParametersLocX.reserve(track.nMeasurements());
160 std::vector<float>& measurementsLocCovX{measurementLocCovXhandle(*track_particle)};
161 measurementsLocCovX.reserve(track.nMeasurements());
162 std::vector<float>& trackParametersLocCovX{trackParameterLocCovXhandle(*track_particle)};
163 trackParametersLocCovX.reserve(track.nMeasurements());
164 std::vector<float>& residualsLocY{residualLocYhandle(*track_particle)};
165 residualsLocY.reserve(track.nMeasurements());
166 std::vector<float>& pullsLocY{pullLocYhandle(*track_particle)};
167 pullsLocY.reserve(track.nMeasurements());
168 std::vector<float>& measurementsLocY{measurementLocYhandle(*track_particle)};
169 measurementsLocY.reserve(track.nMeasurements());
170 std::vector<float>& trackParametersLocY{trackParameterLocYhandle(*track_particle)};
171 trackParametersLocY.reserve(track.nMeasurements());
172 std::vector<float>& measurementsLocCovY{measurementLocCovYhandle(*track_particle)};
173 measurementsLocCovY.reserve(track.nMeasurements());
174 std::vector<float>& trackParametersLocCovY{trackParameterLocCovYhandle(*track_particle)};
175 trackParametersLocCovY.reserve(track.nMeasurements());
177 for (
const auto state : track.trackStatesReversed()) {
179 auto flag = state.typeFlags();
181 bool anyHit =
flag.test(Acts::TrackStateFlag::HoleFlag) or
flag.test(Acts::TrackStateFlag::MeasurementFlag);
183 ATH_MSG_DEBUG(
"--- This is not a hit measurement, skipping...");
193 float chi2_hit_predicted = -999.;
194 float chi2_hit_filtered = -999.;
197 float residualLocX = -999.;
198 float pullLocX = -999.;
199 float measurementLocX = -999.;
200 float trackParameterLocX = -999.;
201 float measurementLocCovX = -999.;
202 float trackParameterLocCovX = -999;
203 float residualLocY = -999.;
204 float pullLocY = -999.;
205 float measurementLocY = -999.;
206 float trackParameterLocY = -999.;
207 float measurementLocCovY = -999.;
208 float trackParameterLocCovY = -999.;
209 bool isAnnulusBound =
false;
212 if (
flag.test(Acts::TrackStateFlag::HoleFlag)) {
213 type = MeasurementType::HOLE;
215 }
else if (
flag.test(Acts::TrackStateFlag::OutlierFlag)) {
216 type = MeasurementType::OUTLIER;
219 type = MeasurementType::HIT;
224 if (state.hasReferenceSurface() and state.referenceSurface().associatedDetectorElement()) {
226 if (!detectorElement) {
227 ATH_MSG_WARNING(
"--- TrackState reference surface returned an invalid associated detector element");
231 if (!siliconDetectorElement) {
232 ATH_MSG_WARNING(
"--- TrackState associated detector element is not silicon");
236 const Acts::AnnulusBounds* annulusBounds =
dynamic_cast<const Acts::AnnulusBounds*
>(&(state.referenceSurface().bounds()));
237 isAnnulusBound = annulusBounds ? true :
false;
239 if (siliconDetectorElement) {
241 if (siliconDetectorElement->
isPixel()) {
243 int layer_disk = pixel_id->
layer_disk(detectorIdentifier);
245 if (pixel_id->
barrel_ec(detectorIdentifier) == 0) {
246 if (layer_disk == 0) {
247 detector = Subdetector::INNERMOST_PIXEL;
254 }
else if (siliconDetectorElement->
isSCT()) {
257 region = sct_id->
barrel_ec(detectorIdentifier) == 0 ?
260 }
else ATH_MSG_WARNING(
"--- Unknown detector type - It is not pixel nor strip detecor element!");
262 }
else ATH_MSG_WARNING(
"--- Missing reference surface or associated detector element!");
268 if (
type == MeasurementType::OUTLIER ||
type == MeasurementType::HIT) {
272 if (
type == MeasurementType::HIT) {
273 chi2_hit_filtered = state.chi2();
276 if (state.hasUncalibratedSourceLink()) {
281 if (!state.hasSmoothed() || !state.hasProjector())
285 const auto &calibratedParameters = state.effectiveCalibrated();
286 const auto &calibratedCovariance = state.effectiveCalibratedCovariance();
291 bool evaluateUnbiased = (!
flag.test(Acts::TrackStateFlag::OutlierFlag));
293 if (evaluateUnbiased) {
294 ATH_MSG_DEBUG(
"--- Good for unbiased parameters evaluation!");
295 type = MeasurementType::UNBIASED;
297 if (state.hasUncalibratedSourceLink()) {
298 ATLASUncalibSourceLink sourceLink = state.getUncalibratedSourceLink().template get<ATLASUncalibSourceLink>();
309 ATH_MSG_DEBUG(
"xAOD::UncalibratedMeasurement is neither xAOD::PixelCluster nor xAOD::StripCluster");
314 const auto& [unbiasedParameters, unbiasedCovariance] =
315 evaluateUnbiased ? Acts::calculateUnbiasedParametersCovariance(state) : std::make_pair(state.parameters(), state.covariance());
317 measurementLocX = calibratedParameters[Acts::eBoundLoc0];
318 measurementLocCovX = calibratedCovariance(Acts::eBoundLoc0, Acts::eBoundLoc0);
320 if (!isAnnulusBound) {
322 trackParameterLocX = unbiasedParameters[Acts::eBoundLoc0];
323 residualLocX = (measurementLocX - trackParameterLocX) / 1_um;
324 trackParameterLocCovX = unbiasedCovariance(Acts::eBoundLoc0, Acts::eBoundLoc0);
329 float locR = unbiasedParameters[Acts::eBoundLoc0];
330 float covR = unbiasedCovariance(Acts::eBoundLoc0,Acts::eBoundLoc0);
331 float locphi = unbiasedParameters[Acts::eBoundLoc1];
332 float covphi = unbiasedCovariance(Acts::eBoundLoc1,Acts::eBoundLoc1);
333 float covRphi = unbiasedCovariance(Acts::eBoundLoc0,Acts::eBoundLoc1);
335 trackParameterLocX = locphi;
336 residualLocX =
locR * (measurementLocX - trackParameterLocX) / 1_um;
338 trackParameterLocCovX =
locR*
locR*covphi + locphi*locphi*covR + 2*locphi*
locR*covRphi;
341 measurementLocCovX =
locR*
locR * measurementLocCovX;
344 pullLocX =
evaluatePull(residualLocX, measurementLocCovX,
345 trackParameterLocCovX, evaluateUnbiased);
347 if (state.calibratedSize() == 2) {
348 measurementLocY = calibratedParameters[Acts::eBoundLoc1];
349 trackParameterLocY = unbiasedParameters[Acts::eBoundLoc1];
350 residualLocY = (measurementLocY - trackParameterLocY) / 1_um;
351 measurementLocCovY = calibratedCovariance(Acts::eBoundLoc1, Acts::eBoundLoc1);
352 trackParameterLocCovY = unbiasedCovariance(Acts::eBoundLoc1, Acts::eBoundLoc1);
353 pullLocY =
evaluatePull(residualLocY, measurementLocCovY,
354 trackParameterLocCovY, evaluateUnbiased);
359 else if (
type == MeasurementType::HOLE) {
362 auto pred = state.predicted();
363 trackParameterLocX = pred[Acts::eBoundLoc0];
364 trackParameterLocY = pred[Acts::eBoundLoc1];
369 regions.push_back(region);
372 types.push_back(
type);
373 predchi2s.push_back(chi2_hit_predicted);
374 filtchi2s.push_back(chi2_hit_filtered);
375 sizesPhi.push_back(sizePhi);
376 sizesEta.push_back(sizeEta);
377 residualsLocX.push_back(residualLocX);
378 pullsLocX.push_back(pullLocX);
379 measurementsLocX.push_back(measurementLocX);
380 trackParametersLocX.push_back(trackParameterLocX);
381 measurementsLocCovX.push_back(measurementLocCovX);
382 trackParametersLocCovX.push_back(trackParameterLocCovX);
383 residualsLocY.push_back(residualLocY);
384 pullsLocY.push_back(pullLocY);
385 measurementsLocY.push_back(measurementLocY);
386 trackParametersLocY.push_back(trackParameterLocY);
387 measurementsLocCovY.push_back(measurementLocCovY);
388 trackParametersLocCovY.push_back(trackParameterLocCovY);
395 return StatusCode::SUCCESS;
400 auto pred = state.predicted();
401 auto predC = state.predictedCovariance();
403 return Acts::visit_measurement(
404 state.calibratedSize(),
405 [&]<std::size_t measdim>(std::integral_constant<std::size_t, measdim>) {
406 Acts::FixedBoundSubspaceHelper<measdim> subspaceHelper =
407 state.template projectorSubspaceHelper<measdim>();
410 auto H = subspaceHelper.projector();
412 const auto calibrated = state.template calibrated<measdim>();
413 const auto calibratedCov = state.template calibratedCovariance<measdim>();
415 auto residual = (H * pred - calibrated).eval();
416 auto rescov = (H * predC * H.transpose() + calibratedCov).eval();
418 return ((residual.transpose() * rescov.inverse() * residual).eval())(0,0);
427 const float measurementCovariance,
428 const float trackParameterCovariance,
429 const bool evaluateUnbiased)
const {
430 float correlation = evaluateUnbiased ? 1. : -1.;
431 float residualCovariance = measurementCovariance + correlation*trackParameterCovariance;
432 if (residualCovariance<=0.) {
434 ATH_MSG_DEBUG(
"--- Total covariance for pull evaluation is non-positive! Returning pulls = 0!");
437 return 0.001 *
residual/std::sqrt(residualCovariance);