16 #include "Acts/Surfaces/AnnulusBounds.hpp" 
   17 #include "Acts/Utilities/TrackHelpers.hpp" 
   19 using namespace Acts::UnitLiterals;
 
   24     MeasurementToTrackParticleDecorationAlg::MeasurementToTrackParticleDecorationAlg(
const std::string &
name,
 
   25                                              ISvcLocator *pSvcLocator) :
 
   59         return StatusCode::SUCCESS;
 
  104                            std::optional<ActsTrk::TrackContainer::ConstTrackProxy> >::
value);
 
  105             std::optional<ActsTrk::TrackContainer::ConstTrackProxy> optional_track = *link_to_track;
 
  107             if ( not optional_track.has_value() ) {
 
  108           ATH_MSG_WARNING(
"Invalid track link for particle  " << track_particle->index() << 
". Skipping track..");
 
  112             ATH_MSG_DEBUG(
"Track link found for track particle with index  " << track_particle->index());
 
  113             ActsTrk::TrackContainer::ConstTrackProxy 
track = optional_track.value();
 
  115         std::vector<int>& regions{measurementRegionHandle(*track_particle)};
 
  116             regions.reserve(
track.nMeasurements());
 
  117             std::vector<int>& 
detectors{measurementDetectorHandle(*track_particle)};
 
  119             std::vector<int>& 
layers{measurementLayerHandle(*track_particle)};
 
  121             std::vector<int>& types{measurementTypeHandle(*track_particle)};
 
  122             types.reserve(
track.nMeasurements());
 
  123         std::vector<float>& predchi2s{chi2HitPredictedHandle(*track_particle)};
 
  124         predchi2s.reserve(
track.nMeasurements());
 
  125         std::vector<float>& filtchi2s{chi2HitFilteredHandle(*track_particle)};
 
  126         filtchi2s.reserve(
track.nMeasurements());
 
  128         std::vector<int>& sizesPhi{measurementPhiWidthHandle(*track_particle)};
 
  129             sizesPhi.reserve(
track.nMeasurements());
 
  130             std::vector<int>& sizesEta{measurementEtaWidthHandle(*track_particle)};
 
  131             sizesEta.reserve(
track.nMeasurements());
 
  132             std::vector<float>& residualsLocX{residualLocXhandle(*track_particle)};
 
  133             residualsLocX.reserve(
track.nMeasurements());
 
  134             std::vector<float>& pullsLocX{pullLocXhandle(*track_particle)};
 
  135             pullsLocX.reserve(
track.nMeasurements());
 
  136             std::vector<float>& measurementsLocX{measurementLocXhandle(*track_particle)};
 
  137             measurementsLocX.reserve(
track.nMeasurements());
 
  138             std::vector<float>& trackParametersLocX{trackParameterLocXhandle(*track_particle)};
 
  139             trackParametersLocX.reserve(
track.nMeasurements());
 
  140             std::vector<float>& measurementsLocCovX{measurementLocCovXhandle(*track_particle)};
 
  141             measurementsLocCovX.reserve(
track.nMeasurements());
 
  142             std::vector<float>& trackParametersLocCovX{trackParameterLocCovXhandle(*track_particle)};
 
  143             trackParametersLocCovX.reserve(
track.nMeasurements());
 
  144             std::vector<float>& residualsLocY{residualLocYhandle(*track_particle)};
 
  145             residualsLocY.reserve(
track.nMeasurements());
 
  146             std::vector<float>& pullsLocY{pullLocYhandle(*track_particle)};
 
  147             pullsLocY.reserve(
track.nMeasurements());
 
  148             std::vector<float>& measurementsLocY{measurementLocYhandle(*track_particle)};
 
  149             measurementsLocY.reserve(
track.nMeasurements());
 
  150             std::vector<float>& trackParametersLocY{trackParameterLocYhandle(*track_particle)};
 
  151             trackParametersLocY.reserve(
track.nMeasurements());
 
  152             std::vector<float>& measurementsLocCovY{measurementLocCovYhandle(*track_particle)};
 
  153             measurementsLocCovY.reserve(
track.nMeasurements());
 
  154             std::vector<float>& trackParametersLocCovY{trackParameterLocCovYhandle(*track_particle)};
 
  155             trackParametersLocCovY.reserve(
track.nMeasurements());
 
  157             for (
const auto state : 
track.trackStatesReversed()) {
 
  159                 auto flag = state.typeFlags();
 
  161                 bool anyHit = 
flag.test(Acts::TrackStateFlag::HoleFlag) or 
flag.test(Acts::TrackStateFlag::MeasurementFlag);
 
  163                     ATH_MSG_DEBUG(
"--- This is not a hit measurement, skipping...");
 
  173         float chi2_hit_predicted = -999.;
 
  174         float chi2_hit_filtered = -999.;
 
  177                 float residualLocX = -999.;
 
  178         float pullLocX = -999.;
 
  179         float measurementLocX = -999.;
 
  180         float trackParameterLocX = -999.;
 
  181         float measurementLocCovX = -999.;
 
  182         float trackParameterLocCovX = -999;
 
  183                 float residualLocY = -999.;
 
  184         float pullLocY = -999.;
 
  185         float measurementLocY = -999.;
 
  186         float trackParameterLocY = -999.;
 
  187         float measurementLocCovY = -999.;
 
  188         float trackParameterLocCovY = -999.;
 
  189         bool isAnnulusBound = 
false;
 
  192         if (
flag.test(Acts::TrackStateFlag::HoleFlag)) {
 
  193           type = MeasurementType::HOLE;
 
  195                 } 
else if (
flag.test(Acts::TrackStateFlag::OutlierFlag)) {
 
  196           type = MeasurementType::OUTLIER;
 
  199           type = MeasurementType::HIT;
 
  204         if (state.hasReferenceSurface() and state.referenceSurface().associatedDetectorElement()) {
 
  206             if (!detectorElement) {
 
  207               ATH_MSG_WARNING(
"--- TrackState reference surface returned an invalid associated detector element");
 
  211             if (!siliconDetectorElement) {
 
  212               ATH_MSG_WARNING(
"--- TrackState associated detector element is not silicon");
 
  216             const Acts::AnnulusBounds* annulusBounds = 
dynamic_cast<const Acts::AnnulusBounds*
>(&(state.referenceSurface().bounds()));
 
  217                     isAnnulusBound = annulusBounds ? true : 
false;
 
  219                     if (siliconDetectorElement) {
 
  221                         if (siliconDetectorElement->
isPixel()) {
 
  223                             int layer_disk = pixel_id->
layer_disk(detectorIdentifier);
 
  225                             if (pixel_id->
barrel_ec(detectorIdentifier) == 0) {
 
  226                               if (layer_disk == 0) {
 
  227                                 detector = Subdetector::INNERMOST_PIXEL;
 
  234                         } 
else if (siliconDetectorElement->
isSCT()) {
 
  237               region =  sct_id->
barrel_ec(detectorIdentifier) == 0 ?
 
  240                         } 
else ATH_MSG_WARNING(
"--- Unknown detector type - It is not pixel nor strip detecor element!");
 
  242                 } 
else ATH_MSG_WARNING(
"--- Missing reference surface or associated detector element!");
 
  248         if (
type == MeasurementType::OUTLIER || 
type == MeasurementType::HIT) {
 
  252           if (
type == MeasurementType::HIT) {
 
  253             chi2_hit_filtered = state.chi2();
 
  256           if (state.hasUncalibratedSourceLink()) {
 
  261           if (!state.hasSmoothed() || !state.hasProjector())
 
  265           const auto &calibratedParameters = state.effectiveCalibrated();
 
  266           const auto &calibratedCovariance = state.effectiveCalibratedCovariance();
 
  271           bool evaluateUnbiased = (!
flag.test(Acts::TrackStateFlag::OutlierFlag));
 
  273           if (evaluateUnbiased) {
 
  274                     ATH_MSG_DEBUG(
"--- Good for unbiased parameters evaluation!");
 
  275                     type = MeasurementType::UNBIASED;
 
  277                     if (state.hasUncalibratedSourceLink()) {
 
  278               ATLASUncalibSourceLink sourceLink = state.getUncalibratedSourceLink().template get<ATLASUncalibSourceLink>();
 
  289             ATH_MSG_DEBUG(
"xAOD::UncalibratedMeasurement is neither xAOD::PixelCluster nor xAOD::StripCluster");
 
  294           const auto& [unbiasedParameters, unbiasedCovariance] =
 
  295             evaluateUnbiased ? Acts::calculateUnbiasedParametersCovariance(state) : std::make_pair(state.parameters(), state.covariance());
 
  297           measurementLocX = calibratedParameters[Acts::eBoundLoc0];
 
  298           measurementLocCovX = calibratedCovariance(Acts::eBoundLoc0, Acts::eBoundLoc0);
 
  300           if (!isAnnulusBound) {
 
  302             trackParameterLocX = unbiasedParameters[Acts::eBoundLoc0];
 
  303             residualLocX = (measurementLocX - trackParameterLocX) / 1_um; 
 
  304             trackParameterLocCovX = unbiasedCovariance(Acts::eBoundLoc0, Acts::eBoundLoc0);
 
  309             float locR    = unbiasedParameters[Acts::eBoundLoc0];
 
  310             float covR    = unbiasedCovariance(Acts::eBoundLoc0,Acts::eBoundLoc0);
 
  311             float locphi  = unbiasedParameters[Acts::eBoundLoc1];
 
  312             float covphi  = unbiasedCovariance(Acts::eBoundLoc1,Acts::eBoundLoc1);
 
  313             float covRphi = unbiasedCovariance(Acts::eBoundLoc0,Acts::eBoundLoc1);
 
  315             trackParameterLocX = locphi;
 
  316             residualLocX = 
locR * (measurementLocX - trackParameterLocX) / 1_um;
 
  318             trackParameterLocCovX = 
locR*
locR*covphi + locphi*locphi*covR + 2*locphi*
locR*covRphi;
 
  321             measurementLocCovX = 
locR*
locR * measurementLocCovX;
 
  324           pullLocX = 
evaluatePull(residualLocX, measurementLocCovX,
 
  325                       trackParameterLocCovX, evaluateUnbiased);
 
  327           if (state.calibratedSize() == 2) {
 
  328             measurementLocY = calibratedParameters[Acts::eBoundLoc1];
 
  329             trackParameterLocY = unbiasedParameters[Acts::eBoundLoc1];
 
  330             residualLocY = (measurementLocY - trackParameterLocY) / 1_um;
 
  331             measurementLocCovY = calibratedCovariance(Acts::eBoundLoc1, Acts::eBoundLoc1);
 
  332             trackParameterLocCovY = unbiasedCovariance(Acts::eBoundLoc1, Acts::eBoundLoc1);
 
  333             pullLocY = 
evaluatePull(residualLocY, measurementLocCovY,
 
  334                         trackParameterLocCovY, evaluateUnbiased);
 
  339         else if (
type == MeasurementType::HOLE) {
 
  342           auto pred = state.predicted();
 
  343           trackParameterLocX = pred[Acts::eBoundLoc0];
 
  344           trackParameterLocY = pred[Acts::eBoundLoc1];
 
  349         regions.push_back(region);
 
  352                 types.push_back(
type);
 
  353         predchi2s.push_back(chi2_hit_predicted);
 
  354         filtchi2s.push_back(chi2_hit_filtered);
 
  355                 sizesPhi.push_back(sizePhi);
 
  356                 sizesEta.push_back(sizeEta);
 
  357                 residualsLocX.push_back(residualLocX);
 
  358                 pullsLocX.push_back(pullLocX);
 
  359                 measurementsLocX.push_back(measurementLocX);
 
  360                 trackParametersLocX.push_back(trackParameterLocX);
 
  361                 measurementsLocCovX.push_back(measurementLocCovX);
 
  362                 trackParametersLocCovX.push_back(trackParameterLocCovX);
 
  363                 residualsLocY.push_back(residualLocY);
 
  364                 pullsLocY.push_back(pullLocY);
 
  365                 measurementsLocY.push_back(measurementLocY);
 
  366                 trackParametersLocY.push_back(trackParameterLocY);
 
  367                 measurementsLocCovY.push_back(measurementLocCovY);
 
  368                 trackParametersLocCovY.push_back(trackParameterLocCovY);
 
  375         return StatusCode::SUCCESS;
 
  380     auto pred  = state.predicted();
 
  381     auto predC = state.predictedCovariance();
 
  383     return Acts::visit_measurement(
 
  384       state.calibratedSize(),
 
  385       [&]<std::size_t measdim>(std::integral_constant<std::size_t, measdim>) {
 
  386         Acts::FixedBoundSubspaceHelper<measdim> subspaceHelper =
 
  387             state.template projectorSubspaceHelper<measdim>();
 
  390         auto H = subspaceHelper.projector();
 
  392         const auto calibrated    = state.template calibrated<measdim>();
 
  393         const auto calibratedCov = state.template calibratedCovariance<measdim>();
 
  395         auto residual = (H * pred - calibrated).eval();
 
  396         auto rescov   = (H * predC * H.transpose() + calibratedCov).eval();
 
  398         return ((residual.transpose() * rescov.inverse() * residual).eval())(0,0);
 
  407                                   const float measurementCovariance,
 
  408                                   const float trackParameterCovariance,
 
  409                                   const bool evaluateUnbiased)
 const {
 
  410     float correlation = evaluateUnbiased ? 1. : -1.;
 
  411     float residualCovariance = measurementCovariance + correlation*trackParameterCovariance;
 
  412     if (residualCovariance<=0.) {
 
  414       ATH_MSG_DEBUG(
"--- Total covariance for pull evaluation is non-positive! Returning pulls = 0!");
 
  417     return 0.001 * 
residual/std::sqrt(residualCovariance);