Skip to content

Commit

Permalink
new structure to handle MCH processing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
pillot authored and aphecetche committed Jan 30, 2023
1 parent 124b9ff commit de715d1
Show file tree
Hide file tree
Showing 21 changed files with 541 additions and 120 deletions.
7 changes: 7 additions & 0 deletions Detectors/MUON/MCH/Base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

o2_add_library(MCHBase
SOURCES
src/Error.cxx
src/ErrorMap.cxx
src/MathiesonOriginal.cxx
src/PreCluster.cxx
Expand All @@ -30,6 +31,12 @@ o2_add_test(trackable
PUBLIC_LINK_LIBRARIES O2::MCHBase
LABELS muon;mch)

o2_add_test(error
SOURCES src/testError.cxx
COMPONENT_NAME mch
PUBLIC_LINK_LIBRARIES O2::MCHBase
LABELS muon;mch)

o2_add_test(errormap
SOURCES src/testErrorMap.cxx
COMPONENT_NAME mch
Expand Down
97 changes: 97 additions & 0 deletions Detectors/MUON/MCH/Base/include/MCHBase/Error.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/**
* @file Error.h
* @brief definition of the MCH processing errors
* @author Philippe Pillot, Subatech
*/

#ifndef O2_MCH_BASE_ERROR_H
#define O2_MCH_BASE_ERROR_H

#include <cstdint>
#include <map>
#include <string>

namespace o2::mch
{

/** groups of MCH processing errors, each group corresponding to a processing units */
enum class ErrorGroup : uint8_t {
Unassigned,
Decoding,
Filtering,
TimeClustering,
PreClustering,
Clustering,
Tracking
};

namespace internal
{
/**
* @brief helper function to construct the error type GID (not supposed to be used outside of this header)
* @details - the 8 most significant bits identify the error group
* - the other bits identify the error type within the group
* @param group group to which this error belongs
* @param id error UID within this group
*/
constexpr uint32_t buildTypeGID(ErrorGroup group, uint32_t id) { return (static_cast<uint32_t>(group) << 24) + id; }
} // namespace internal

/** types of MCH processing errors */
enum class ErrorType : uint32_t {
PreClustering_MultipleDigitsInSamePad = internal::buildTypeGID(ErrorGroup::PreClustering, 0),
PreClustering_LostDigit = internal::buildTypeGID(ErrorGroup::PreClustering, 1),
Clustering_TooManyLocalMaxima = internal::buildTypeGID(ErrorGroup::Clustering, 0),
Tracking_TooManyCandidates = internal::buildTypeGID(ErrorGroup::Tracking, 0),
Tracking_TooLong = internal::buildTypeGID(ErrorGroup::Tracking, 1)
};

/**
* returns the group to which this error type belongs
* @param error error type
*/
constexpr ErrorGroup errorGroup(ErrorType error) { return static_cast<ErrorGroup>(static_cast<uint32_t>(error) >> 24); }

/** generic structure to handle MCH processing errors */
struct Error {
static const std::map<ErrorGroup, std::string> groupNames; ///< names of known error group
static const std::map<ErrorType, std::string> typeNames; ///< names of known error type
static const std::map<ErrorType, std::string> typeDescriptions; ///< descriptions of known error type

ErrorType type{0}; ///< type of processing error
uint32_t id0 = 0; ///< additional descriptor used for certain error types
uint32_t id1 = 0; ///< additional descriptor used for certain error types
uint64_t count = 0; ///< number of occurences

/**
* returns the known error type names within the given group
* @param group error group
*/
static const std::map<ErrorType, std::string> getTypeNames(ErrorGroup group);

/** returns the group to which this error belongs */
ErrorGroup getGroup() const { return o2::mch::errorGroup(type); }
/** returns the name of the group to which this error belongs */
std::string getGroupName() const;
/** returns the type name of this error */
std::string getTypeName() const;
/** returns the type description of this error */
std::string getTypeDescription() const;
/** returns the error message corresponding to this error */
std::string asString() const;
};

} // namespace o2::mch

#endif // O2_MCH_BASE_ERROR_H
73 changes: 40 additions & 33 deletions Detectors/MUON/MCH/Base/include/MCHBase/ErrorMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,58 +12,65 @@
#ifndef O2_MCH_BASE_ERROR_MAP_H_H
#define O2_MCH_BASE_ERROR_MAP_H_H

#include <map>
#include <set>
#include <cstdint>
#include <functional>
#include <map>

#include <gsl/span>

#include "MCHBase/Error.h"

namespace o2::mch
{

/** A container class to summarize errors encountered during processing.
*
* The interface is :
* add(errorType, id0, id1)
/** @brief A container class to summarize errors encountered during processing.
*
* where errorType, id0 and id1 are integers (unsigned, 32 bits wide)
* @details The main interface is :
* add(errorType, id0, id1[, count])
*
* ErrorMap stores the number of times the add method has been
* called for the {errorType,id0,id1} triplet.
*
* The exact meaning of the triplet members is left to the client of ErrorMap.
* where errorType is the type of the error and id0 and id1 are additional
* descriptors, whose meaning depends on the error type (see Error.h/cxx)
*
* additional interfaces are provided to add and access the errors,
* or execute a function on all or some of them
*/
class ErrorMap
{
public:
/* ErrorFunction is a function that receive a triplet {errorType,id0,id1)
* and the number of times (count) that triplet has been seen.
*/
using ErrorFunction = std::function<void(uint32_t errorType,
uint32_t id0,
uint32_t id1,
uint64_t count)>;
using ErrorFunction = std::function<void(Error error)>;

/** increment the count of the {errorType,id0,id1} triplet by n */
void add(ErrorType errorType, uint32_t id0, uint32_t id1, uint64_t n = 1);
/** add or increment this error */
void add(Error error);
/** add or increment these errors */
void add(gsl::span<const Error> errors);
/** add or increment these errors */
void add(const ErrorMap& errors);

/** erase all encountered errors */
void clear() { mErrors.clear(); }

/* increment the count of the {errorType,id0,id1} triplet by one.*/
void add(uint32_t errorType, uint32_t id0, uint32_t id1);
/** return the number of encountered types of error */
uint64_t getNumberOfErrorTypes() const { return mErrors.size(); }
/** return the total number of encountered errors */
uint64_t getNumberOfErrors() const;
/** return the total number of encountered errors of a given type */
uint64_t getNumberOfErrors(ErrorType type) const;
/** return the total number of encountered errors of a given group */
uint64_t getNumberOfErrors(ErrorGroup group) const;

/* execute function f on all {errorType,id0,id1} triplets.
*
* The function is passed the triplet and the corresponding occurence count
* of that triplet.
*/
/** execute function f on all encountered errors */
void forEach(ErrorFunction f) const;
/** execute function f on all encountered errors of a given type */
void forEach(ErrorType type, ErrorFunction f) const;
/** execute function f on all encountered errors of a given group */
void forEach(ErrorGroup group, ErrorFunction f) const;

private:
std::map<uint32_t, std::map<uint64_t, uint64_t>> mErrorCounts;
std::map<ErrorType, std::map<uint64_t, Error>> mErrors{}; ///< map of encountered errors
};

/* convenience function to get the number of error types */
uint64_t numberOfErrorTypes(const ErrorMap& em);

/* convenience function to get the total number of errors */
uint64_t totalNumberOfErrors(const ErrorMap& em);

}; // namespace o2::mch
} // namespace o2::mch

#endif
105 changes: 105 additions & 0 deletions Detectors/MUON/MCH/Base/src/Error.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/**
* @file Error.cxx
* @brief implementation of the MCH processing errors
* @author Philippe Pillot, Subatech
*/

#include "MCHBase/Error.h"

#include <fmt/format.h>

namespace o2::mch
{

const std::map<ErrorGroup, std::string> Error::groupNames = {
{ErrorGroup::Unassigned, "Unassigned"},
{ErrorGroup::Decoding, "Decoding"},
{ErrorGroup::Filtering, "Filtering"},
{ErrorGroup::TimeClustering, "TimeClustering"},
{ErrorGroup::PreClustering, "PreClustering"},
{ErrorGroup::Clustering, "Clustering"},
{ErrorGroup::Tracking, "Tracking"}};

const std::map<ErrorType, std::string> Error::typeNames = {
{ErrorType::PreClustering_MultipleDigitsInSamePad, "MultipleDigitsInSamePad"},
{ErrorType::PreClustering_LostDigit, "LostDigit"},
{ErrorType::Clustering_TooManyLocalMaxima, "TooManyLocalMaxima"},
{ErrorType::Tracking_TooManyCandidates, "TooManyCandidates"},
{ErrorType::Tracking_TooLong, "TooLong"}};

const std::map<ErrorType, std::string> Error::typeDescriptions = {
{ErrorType::PreClustering_MultipleDigitsInSamePad, "multiple digits on the same pad"},
{ErrorType::PreClustering_LostDigit, "lost digit"},
{ErrorType::Clustering_TooManyLocalMaxima, "too many local maxima"},
{ErrorType::Tracking_TooManyCandidates, "too many track candidates"},
{ErrorType::Tracking_TooLong, "too long"}};

const std::map<ErrorType, std::string> Error::getTypeNames(ErrorGroup group)
{
std::map<ErrorType, std::string> groupTypeNames{};
for (const auto& typeName : typeNames) {
if (errorGroup(typeName.first) == group) {
groupTypeNames.emplace(typeName);
}
}
return groupTypeNames;
}

std::string Error::getGroupName() const
{
const auto itName = groupNames.find(getGroup());
if (itName != groupNames.end()) {
return itName->second;
}
return "Unknown";
}

std::string Error::getTypeName() const
{
const auto itName = typeNames.find(type);
if (itName != typeNames.end()) {
return itName->second;
}
return "Unknown";
}

std::string Error::getTypeDescription() const
{
const auto itDescription = typeDescriptions.find(type);
if (itDescription != typeDescriptions.end()) {
return itDescription->second;
}
return "";
}

std::string Error::asString() const
{
auto description = fmt::format("{} error: {}", getGroupName(), getTypeDescription());

// add extra description when relevant
switch (type) {
case ErrorType::PreClustering_MultipleDigitsInSamePad:
description += fmt::format(" (DE {} pad {})", id0, id1);
break;
case ErrorType::Clustering_TooManyLocalMaxima:
description += fmt::format(" (DE {})", id0);
break;
default:
break;
}

return description + fmt::format(": seen {} time{}", count, count > 1 ? "s" : "");
}

} // namespace o2::mch
Loading

0 comments on commit de715d1

Please sign in to comment.