20 #include "Acts/Definitions/Units.hpp"
21 #include "Acts/Geometry/TrackingGeometry.hpp"
22 #include "Acts/Geometry/GeometryIdentifier.hpp"
23 #include "Acts/MagneticField/MagneticFieldProvider.hpp"
24 #include "Acts/Surfaces/Surface.hpp"
25 #include "Acts/TrackFinding/CombinatorialKalmanFilter.hpp"
26 #include "Acts/Surfaces/PerigeeSurface.hpp"
27 #include "Acts/Utilities/TrackHelpers.hpp"
28 #include "Acts/TrackFitting/MbfSmoother.hpp"
59 ISvcLocator *pSvcLocator)
128 return StatusCode::FAILURE;
134 return StatusCode::FAILURE;
140 return StatusCode::FAILURE;
156 auto magneticField = std::make_unique<ATLASMagneticFieldWrapper>();
160 detail::Navigator::Config
config{trackingGeometry};
161 config.resolvePassive =
false;
162 config.resolveMaterial =
true;
163 config.resolveSensitive =
true;
171 std::vector<double> absEtaEdges;
174 absEtaEdges.reserve(2
ul);
175 absEtaEdges.push_back(0.0);
176 absEtaEdges.push_back(std::numeric_limits<double>::infinity());
186 auto setCut = [](
auto &cfgVal,
const auto &
cuts,
size_t ind) ->
void
193 Acts::TrackSelector::EtaBinnedConfig trackSelectorCfg{std::move(absEtaEdges)};
196 assert(trackSelectorCfg.cutSets.size() == 1);
197 trackSelectorCfg.cutSets[0].absEtaMin =
m_absEtaMin;
198 trackSelectorCfg.cutSets[0].absEtaMax =
m_absEtaMax;
201 for (
auto &
cfg : trackSelectorCfg.cutSets)
227 std::move(extrapolator),
230 Acts::TrackSelector{trackSelectorCfg}};
232 m_trackFinder = std::make_unique<CKF_pimpl>(std::move(ckfConfig));
234 trackFinder().
ckfExtensions.updater.connect<&ActsTrk::detail::FitterHelperFunctions::gainMatrixUpdate<detail::RecoTrackStateContainer>>();
237 return StatusCode::SUCCESS;
245 return StatusCode::SUCCESS;
263 std::vector<const ActsTrk::SeedContainer *> seedContainers;
264 std::size_t total_seeds = 0;
268 std::vector<const xAOD::UncalibratedMeasurementContainer *> uncalibratedMeasurementContainers;
269 std::size_t total_measurements = 0;
274 ATH_CHECK(detectorElementToGeometryIdMap.isValid());
280 std::vector< const InDet::SiDetectorElementStatus *> det_el_status_arr;
281 const std::vector<const InDetDD::SiDetectorElementCollection*> &det_el_collections =volumeIdToDetectorElementCollMap->
collections();
282 det_el_status_arr.resize( det_el_collections.size(),
nullptr);
286 const std::vector<const InDetDD::SiDetectorElementCollection*>::const_iterator
287 det_el_col_iter =
std::find(det_el_collections.begin(),
288 det_el_collections.end(),
290 det_el_status_arr.at(det_el_col_iter - det_el_collections.begin()) = det_el_status.
cptr();
298 for (std::size_t icontainer = 0; icontainer < uncalibratedMeasurementContainers.size(); ++icontainer) {
301 *uncalibratedMeasurementContainers[icontainer],
302 **detectorElementToGeometryIdMap);
303 if (measurementIndexContainersSize > 0
ul)
304 measurementIndex.
addMeasurements(*uncalibratedMeasurementContainers[icontainer]);
316 for (std::size_t icontainer = 0; icontainer < seedContainers.size(); ++icontainer)
318 duplicateSeedDetector.
addSeeds(icontainer, *seedContainers[icontainer], measurementIndex);
325 std::vector<const InDetDD::SiDetectorElementCollection*> detElementsCollections;
326 std::size_t total_detElems = 0;
334 event_stat.resize(m_stat.size());
337 for (std::size_t icontainer = 0; icontainer < seedContainers.size(); ++icontainer)
340 **detectorElementToGeometryIdMap,
344 duplicateSeedDetector,
345 *seedContainers.at(icontainer),
346 *detElementsCollections.at(icontainer),
353 ATH_MSG_DEBUG(
" \\__ Created " << tracksContainer.size() <<
" tracks");
355 mon_nTracks = tracksContainer.size();
367 ATH_CHECK(trackContainerHandle.record(std::move(constTracksContainer)));
368 if (!trackContainerHandle.isValid())
371 return StatusCode::FAILURE;
374 return StatusCode::SUCCESS;
378 const auto& bottom_sp = seed.sp().front();
380 const double r = bottom_sp->radius();
381 const double z = std::abs(bottom_sp->z());
386 return r > rBoundary ||
z > zBoundary;
401 measurementSelector->
connect(&
options.extensions.createTrackStates);
403 return measurementSelector;
418 std::size_t typeIndex,
419 const char *seedType,
431 .calib = Acts::CalibrationContext()
437 Acts::VectorTrackContainer trackBackend;
438 Acts::VectorMultiTrajectory trackStateBackend;
445 std::size_t category_i = 0;
447 auto stopBranchProxy = [&](
const detail::RecoTrackContainer::TrackProxy &track,
449 return stopBranch(track, trackState, trackSelectorCfg, detContext.geometry, measurementIndex, typeIndex, event_stat[category_i]);
451 options.extensions.branchStopper.connect(stopBranchProxy);
454 Acts::ActorList<Acts::MaterialInteractor>>
455 extrapolationOptions(detContext.geometry, detContext.magField);
457 Acts::TrackExtrapolationStrategy extrapolationStrategy =
461 ATH_MSG_DEBUG(
"Invoke track finding with " << seeds.
size() <<
' ' << seedType <<
" seeds.");
463 std::size_t nPrinted = 0;
464 auto printSeed = [&](
unsigned int iseed,
const Acts::BoundTrackParameters &seedParameters,
bool isKF =
false)
470 ATH_MSG_INFO(
"CKF results for " << seeds.
size() <<
' ' << seedType <<
" seeds:");
472 m_trackStatePrinter->printSeed(detContext.geometry, *seeds[iseed], seedParameters, measurementIndex, iseed, isKF);
476 for (
unsigned int iseed = 0; iseed < seeds.
size(); ++iseed)
481 tracksContainerTemp.
clear();
485 const bool useTopSp = reverseSearch && !refitSeeds;
487 auto getSeedCategory = [
this, useTopSp](std::size_t typeIndex,
const ActsTrk::Seed& seed) -> std::size_t {
488 const xAOD::SpacePoint* sp = useTopSp ? seed.sp().back() : seed.sp().front();
490 double etaSeed = std::atanh(
pos[2] /
pos.norm());
494 const bool isDupSeed = duplicateSeedDetector.
isDuplicate(typeIndex, iseed);
496 ATH_MSG_DEBUG(
"skip " << seedType <<
" seed " << iseed <<
" - already found");
497 category_i = getSeedCategory(typeIndex, seed);
503 options.propagatorPlainOptions.direction = reverseSearch ? Acts::Direction::Backward() : Acts::Direction::Forward();
504 secondOptions.propagatorPlainOptions.direction =
options.propagatorPlainOptions.direction.invert();
505 options.targetSurface = reverseSearch ? pSurface.get() :
nullptr;
506 secondOptions.targetSurface = reverseSearch ? nullptr : pSurface.get();
510 auto retrieveSurfaceFunction =
511 [
this, &detElements] (
const ActsTrk::Seed& seed,
bool useTopSp) ->
const Acts::Surface& {
512 const xAOD::SpacePoint* sp = useTopSp ? seed.sp().back() : seed.sp().front();
520 std::optional<Acts::BoundTrackParameters> optTrackParams =
526 retrieveSurfaceFunction);
528 if (!optTrackParams) {
529 ATH_MSG_DEBUG(
"Failed to estimate track parameters for seed " << iseed);
531 category_i = getSeedCategory(typeIndex, seed);
538 Acts::BoundTrackParameters *initialParameters = &(*optTrackParams);
539 printSeed(iseed, *initialParameters);
540 if (isDupSeed)
continue;
547 std::unique_ptr<Acts::BoundTrackParameters> refitSeedParameters;
549 refitSeedParameters =
doRefit(ctx, seed, *initialParameters, detContext, detectorElementToGeoId, reverseSearch);
550 if (refitSeedParameters.get() ==
nullptr) {
554 if (refitSeedParameters.get() != initialParameters) {
555 initialParameters = refitSeedParameters.get();
556 printSeed(iseed, *initialParameters,
true);
567 ATH_MSG_WARNING(
"Track finding failed for " << seedType <<
" seed " << iseed <<
" with error" <<
result.error());
570 auto &tracksForSeed =
result.value();
579 if (!track.hasReferenceSurface()) {
580 auto extrapolationResult = Acts::extrapolateTrackToReferenceSurface(
581 track, *pSurface,
trackFinder().extrapolator, extrapolationOptions,
582 extrapolationStrategy,
logger());
583 if (!extrapolationResult.ok()) {
585 << iseed <<
" and " << track.index()
586 <<
" failed with error " << extrapolationResult.error()
587 <<
" dropping track candidate.");
592 Acts::trimTrack(track,
true,
true,
true,
true);
593 Acts::calculateTrackQuantities(track);
596 for (
const auto trackState : track.trackStatesReversed()) {
605 auto selectPixelStripCountsFinal = [
this](
const detail::RecoTrackContainer::TrackProxy &track) {
609 return enoughMeasurementsPS && !tooManyHolesPS && !tooManyOutliersPS;
611 if (
trackFinder().trackSelector.isValidTrack(track) &&
612 selectPixelStripCountsFinal(track)) {
616 storeSeedInfo(tracksContainerTemp, track, duplicateSeedDetector, measurementIndex);
620 auto destProxy = tracksContainer.getTrack(tracksContainer.addTrack());
621 destProxy.copyFrom(track,
true);
624 auto [nShared, nBadTrackMeasurements] = sharedHits.
computeSharedHits(destProxy, tracksContainer, measurementIndex);
625 if (nBadTrackMeasurements > 0)
626 ATH_MSG_ERROR(
"computeSharedHits: " << nBadTrackMeasurements <<
" track measurements not found in input for " << seedType <<
" seed " << iseed <<
" track");
627 ATH_MSG_DEBUG(
"found " << destProxy.nSharedHits() <<
" shared hits in " << seedType <<
" seed " << iseed <<
" track");
634 m_trackStatePrinter->printTrack(detContext.geometry, tracksContainer, destProxy, measurementIndex);
638 ATH_MSG_DEBUG(
"Track " << ntracks <<
" from " << seedType <<
" seed " << iseed <<
" failed track selection");
640 m_trackStatePrinter->printTrack(detContext.geometry, tracksContainerTemp, track, measurementIndex,
true);
645 std::size_t nfirst = 0;
646 for (
TrkProxy &firstTrack : tracksForSeed) {
647 auto smoothingResult = Acts::smoothTrack(detContext.geometry, firstTrack,
logger(), Acts::MbfSmoother());
648 if (!smoothingResult.ok()) {
650 << iseed <<
" and first track " << firstTrack.index()
651 <<
" failed with error " << smoothingResult.error());
655 const std::size_t nsecond =
661 ATH_MSG_DEBUG(
"No viable result from second track finding for " << seedType <<
" seed " << iseed <<
" track " << nfirst);
670 ATH_MSG_DEBUG(
"Track finding found no track candidates for " << seedType <<
" seed " << iseed);
672 }
else if (ntracks >= 2) {
681 return StatusCode::SUCCESS;
687 const Acts::PerigeeSurface* pSurface)
const {
688 Acts::PropagatorPlainOptions plainOptions{detContext.
geometry, detContext.
magField};
689 Acts::PropagatorPlainOptions plainSecondOptions{detContext.
geometry, detContext.
magField};
692 plainOptions.direction = Acts::Direction::Forward();
695 plainSecondOptions.direction = plainOptions.direction.invert();
699 trackFinder().ckfExtensions, plainOptions, pSurface);
704 options.extensions, plainSecondOptions, pSurface);
705 secondOptions.targetSurface = pSurface;
706 secondOptions.skipPrePropagationUpdate =
true;
708 return {
options, secondOptions, std::move(measurementSelector)};
712 const detail::RecoTrackContainer::TrackProxy &track,
713 const detail::RecoTrackContainer::TrackStateProxy &trackState,
714 const Acts::TrackSelector::EtaBinnedConfig &trackSelectorCfg,
715 const Acts::GeometryContext &tgContext,
717 const std::size_t typeIndex,
718 EventStats::value_type &event_stat_category_i)
const {
727 measurementIndex,
true);
731 return BranchStopperResult::Continue;
734 const auto &
parameters = trackState.hasFiltered() ? trackState.filtered()
735 : trackState.predicted();
737 const auto &cutSet =
getCuts(eta);
746 <<
pT <<
" after " << track.nMeasurements()
748 return BranchStopperResult::StopAndDrop;
754 !(std::abs(eta) < trackSelectorCfg.absEtaEdges.back() +
758 << eta <<
" after " << track.nMeasurements()
760 return BranchStopperResult::StopAndDrop;
763 bool enoughMeasurements = (track.nMeasurements() >= cutSet.minMeasurements);
764 bool tooManyHoles = (track.nHoles() > cutSet.maxHoles);
765 bool tooManyOutliers = (track.nOutliers() > cutSet.maxOutliers);
768 auto [enoughMeasurementsPS, tooManyHolesPS, tooManyOutliersPS] =
770 enoughMeasurements = enoughMeasurements && enoughMeasurementsPS;
771 tooManyHoles = tooManyHoles || tooManyHolesPS;
772 tooManyOutliers = tooManyOutliers || tooManyOutliersPS;
775 if (!(tooManyHoles || tooManyOutliers)) {
776 return BranchStopperResult::Continue;
779 if (!enoughMeasurements) {
785 << (enoughMeasurements ?
"keep" :
"drop")
786 <<
" branch with nHoles=" << track.nHoles() <<
" ("
789 <<
" strip), nOutliers=" << track.nOutliers() <<
" ("
792 <<
"), nMeasurements=" << track.nMeasurements() <<
" ("
797 << (enoughMeasurements ?
"keep" :
"drop")
798 <<
" branch with nHoles=" << track.nHoles()
799 <<
", nOutliers=" << track.nOutliers()
800 <<
", nMeasurements=" << track.nMeasurements());
803 return enoughMeasurements ? BranchStopperResult::StopAndKeep
804 : BranchStopperResult::StopAndDrop;
812 Acts::GeometryContext &tgContext,
813 const bool reverseSearch)
const {
814 std::size_t
count = 0;
816 std::optional<detail::RecoTrackStateContainerProxy> firstMeasurement;
817 for (
auto st : trackProxy.trackStatesReversed()) {
818 bool isMeasurement = st.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag);
819 bool isOutlier = st.typeFlags().test(Acts::TrackStateFlag::OutlierFlag);
823 if (isMeasurement && !isOutlier) {
824 firstMeasurement = st;
828 if (!firstMeasurement.has_value()) {
834 if (!secondInitialParameters.referenceSurface().insideBounds(secondInitialParameters.localPosition())) {
838 auto rootBranch = tracksContainerTemp.makeTrack();
839 rootBranch.copyFrom(trackProxy,
false);
843 auto secondResult =
trackFinder().
ckf.findTracks(secondInitialParameters,
options, tracksContainerTemp, rootBranch);
845 if (not secondResult.ok()) {
850 auto originalFirstMeasurementPrevious = firstMeasurement->previous();
852 auto &secondTracksForSeed = secondResult.value();
853 for (
auto &secondTrack : secondTracksForSeed) {
854 secondTrack.reverseTrackStates(
true);
856 firstMeasurement->previous() = secondTrack.outermostTrackState().index();
857 secondTrack.tipIndex() = trackProxy.tipIndex();
861 auto secondSmoothingResult = Acts::smoothTrack(tgContext, secondTrack,
logger());
862 if (!secondSmoothingResult.ok()) {
866 secondTrack.reverseTrackStates(
true);
875 firstMeasurement->previous() = originalFirstMeasurementPrevious;
881 const Acts::TrackSelector::Config&
885 return (!(std::abs(eta) < trackSelectorCfg.absEtaEdges.back())) ? trackSelectorCfg.cutSets.back()
886 : (std::abs(eta) < trackSelectorCfg.absEtaEdges.front()) ? trackSelectorCfg.cutSets.front()
887 : trackSelectorCfg.getCuts(eta);
897 const auto lastMeasurementIndex = track.tipIndex();
900 tracksContainer.trackStateContainer().visitBackwards(
901 lastMeasurementIndex,
902 [&duplicateSeedDetector,&measurementIndex](
const detail::RecoTrackStateContainer::ConstTrackStateProxy &state) ->
void
905 if (not state.hasUncalibratedSourceLink())
909 auto sl = state.getUncalibratedSourceLink().template get<ATLASUncalibSourceLink>();
917 if (trackState.hasReferenceSurface()) {
918 if (
const auto *actsDetElem =
dynamic_cast<const ActsDetectorElement *
>(trackState.referenceSurface().associatedDetectorElement())) {
920 if (detElem->isPixel()) {
922 }
else if (detElem->isSCT()) {
934 tracksContainer.addColumn<
unsigned int>(
"nPixelHits");
935 tracksContainer.addColumn<
unsigned int>(
"nStripHits");
936 tracksContainer.addColumn<
unsigned int>(
"nPixelHoles");
937 tracksContainer.addColumn<
unsigned int>(
"nStripHoles");
938 tracksContainer.addColumn<
unsigned int>(
"nPixelOutliers");
939 tracksContainer.addColumn<
unsigned int>(
"nStripOutliers");
955 Acts::ConstTrackStateType typeFlags,
959 if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) {
961 }
else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) {
963 }
else if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) {
967 if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) {
969 }
else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) {
971 }
else if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) {
979 const detail::RecoTrackContainer::TrackProxy &
other)
995 ATH_MSG_WARNING(
"mismatched hit count: total (" << track.nMeasurements()
1003 ATH_MSG_WARNING(
"mismatched outlier count: total (" << track.nOutliers()
1011 bool enoughMeasurements =
true, tooManyHoles =
false, tooManyOutliers =
false;
1013 std::size_t
etaBin = (std::abs(eta) < trackSelectorCfg.absEtaEdges.front()) ? 0
1014 : (std::abs(eta) >= trackSelectorCfg.absEtaEdges.back()) ? trackSelectorCfg.absEtaEdges.size() - 1
1015 : trackSelectorCfg.binIndex(eta);
1016 auto cutMin = [
etaBin](std::size_t
val,
const std::vector<std::size_t> &cutSet) {
1017 return !cutSet.empty() && (
val < (
etaBin < cutSet.size() ? cutSet[
etaBin] : cutSet.back()));
1019 auto cutMax = [
etaBin](std::size_t
val,
const std::vector<std::size_t> &cutSet) {
1020 return !cutSet.empty() && (
val > (
etaBin < cutSet.size() ? cutSet[
etaBin] : cutSet.back()));
1028 return {enoughMeasurements, tooManyHoles, tooManyOutliers};
1043 ATH_MSG_FATAL(
"Eta bins for statistics counter not in ascending order.");
1054 std::lock_guard<std::mutex> lock(m_mutex);
1055 std::size_t category_i = 0;
1056 for (
const std::array<unsigned int, kNStat> &src_stat : event_stat)
1058 std::array<std::size_t, kNStat> &dest_stat = m_stat[category_i++];
1059 for (std::size_t
i = 0;
i < src_stat.size(); ++
i)
1061 assert(
i < dest_stat.size());
1062 dest_stat[
i] += src_stat[
i];
1072 std::vector<std::string> stat_labels =
1078 std::make_pair(
kNoTrack,
"Cannot find track"),
1086 std::make_pair(
kNoSecond,
"Tracks failing second CKF"),
1091 assert(stat_labels.size() ==
kNStat);
1097 std::vector<std::string> eta_labels;
1099 for (std::size_t eta_bin_i = 0; eta_bin_i <
m_statEtaBins.size() + 2; ++eta_bin_i)
1108 std::vector<std::size_t>
stat =
1109 TableUtils::createCounterArrayWithProjections<std::size_t>(
nSeedCollections(),
1114 std::size_t stat_stride =
1118 std::size_t eta_stride =
1122 std::stringstream table_out;
1128 for (std::size_t stat_i = 0; stat_i <
kNStat; ++stat_i)
1130 std::size_t dest_idx_offset = stat_i * stat_stride;
1136 .dumpHeader(stat_i == 0)
1137 .dumpFooter(stat_i + 1 ==
kNStat)
1138 .separateLastRow(
true)
1139 .minLabelWidth(max_label_width)
1140 .labelPrefix(stat_labels.at(stat_i));
1150 std::size_t dest_idx_offset = eta_bin_i * eta_stride;
1154 eta_labels.at(eta_bin_i))
1161 << table_out.str());
1167 auto [ratio_labels, ratio_def] =
1169 std::vector<TableUtils::SummandDefinition>{
1202 for (std::size_t ratio_i = 0; ratio_i < ratio_labels.size(); ++ratio_i)
1205 ratio_i * ratio_stride,
1211 .dumpHeader(ratio_i == 0)
1212 .dumpFooter(ratio_i + 1 == ratio_labels.size())
1213 .separateLastRow(
true)
1214 .minLabelWidth(max_label_width)
1215 .labelPrefix(ratio_labels.at(ratio_i));
1222 (
m_statEtaBins.size() + 1) * ratio_eta_stride + 0 * ratio_stride,
1228 .minLabelWidth(max_label_width)
1232 eta_labels.erase(eta_labels.end() - 1);
1233 constexpr std::size_t ratio_i = 3;
1235 ratio_i * ratio_stride,
1243 .separateLastRow(
false)
1244 .minLabelWidth(max_label_width)
1245 .labelPrefix(ratio_labels.at(ratio_i));
1249 << table_out.str());
1255 std::vector<float>::const_iterator bin_iter = std::upper_bound(
m_statEtaBins.begin(),
1259 assert(category_i < m_stat.size());
1265 std::size_t
out = 0
u;
1270 assert(category_i <
stat.size());
1271 out +=
stat[category_i][counter_i];
1282 ATH_MSG_ERROR(
"Outlier chi2 cut off provided but number of elements does not agree with"
1283 " chi2 cut off for measurements which however is required: "
1285 return StatusCode::FAILURE;
1290 chi2CutOffOutlier.push_back( std::make_pair(
static_cast<float>(elm),
1301 return StatusCode::SUCCESS ;
1305 const std::vector< const InDet::SiDetectorElementStatus *> &det_el_status_arr,
1307 const Acts::TrackingGeometry *
1309 ATH_CHECK(acts_tracking_geometry !=
nullptr);
1311 using Counter =
struct {
unsigned int n_volumes, n_volumes_with_status, n_missing_detector_elements, n_detector_elements, n_disabled_detector_elements;};
1313 acts_tracking_geometry->visitVolumes([&
counter,
1314 &volume_id_to_det_el_coll,
1317 this](
const Acts::TrackingVolume *volume_ptr) {
1319 if (!volume_ptr)
return;
1322 det_el_status = det_el_status_arr.at(volume_id_to_det_el_coll.
collecionMap().at(volume_ptr->geometryId().volume()));
1323 if (det_el_status) {
1324 ++
counter.n_volumes_with_status;
1325 volume_ptr->visitSurfaces([&
counter, det_el_status, &measurements,
this](
const Acts::Surface *surface_ptr) {
1326 if (!surface_ptr)
return;
1327 const Acts::Surface &surface = *surface_ptr;
1328 const Acts::DetectorElementBase*detector_element = surface.associatedDetectorElement();
1329 if (detector_element) {
1330 ++
counter.n_detector_elements;
1333 ActsTrk::detail::MeasurementRange old_range = measurements.markSurfaceInsensitive(surface_ptr->geometryId());
1334 if (!old_range.empty()) {
1335 auto geoid_to_string = [](const Acts::GeometryIdentifier &id) -> std::string {
1336 std::stringstream amsg;
1340 std::string a_msg ( geoid_to_string(surface_ptr->geometryId()));
1341 ATH_MSG_WARNING(
"Reject " << (old_range.elementEndIndex() - old_range.elementBeginIndex())
1342 <<
" measurements because surface " << a_msg);
1344 ++
counter.n_disabled_detector_elements;
1350 ++
counter.n_missing_detector_elements;
1354 <<
" disabled detector elements " <<
counter.n_disabled_detector_elements
1355 <<
" / " <<
counter.n_detector_elements
1356 <<
" missing detector elements "
1357 <<
counter.n_missing_detector_elements);
1358 return StatusCode::SUCCESS;