Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 189 additions & 0 deletions edm4hep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,194 @@ datatypes:
/// Set the position covariance matrix value for the two passed dimensions
void setCovMatrix(float value, edm4hep::Cartesian dimI, edm4hep::Cartesian dimJ) { getCovMatrix().setValue(value, dimI, dimJ); }

edm4hep::TrackerHitLocal:
Description: "Sensor-local tracker hit"
Author: "EDM4hep authors"
Members:
- uint64_t cellID // ID of the sensor that created this hit
- int32_t type // type of raw data hit, use depends on writer
- float time [ns] // time of the hit (depends on measurement type)
- edm4hep::Vector3d position [mm] // global hit position (depends on measurement type)

VectorMembers:
- float measurement // Entries in the measurement value vector
- float covariance // Entries in the measurement covariance vector. Order is column major

ExtraCode:
includes: "#include <edm4hep/utils/SubspaceIndexUtils.hpp>"
declaration: |
/// Number of active subspace dimensions
/// @return The number of active subspace dimensions
std::size_t getSize() const {
return getSubspaceIndices().size();
}


/// Get the value for the passed subspace index
/// @param valueIndex The index of the value
/// @return The value
float getValue(std::size_t valueIndex) const {
const auto dim = getSize();
auto values = getMeasurement();
if (values.size() != dim) {
throw std::runtime_error("Measurement vector size mismatch");
}

if (valueIndex >= dim) {
throw std::runtime_error("Measurement index out of range");
}
return values[valueIndex];
}

/// Get covariance value for the two passed matrix indices
/// @param indexI The first index
/// @param indexJ The second index
/// @return The covariance value
float getCov(std::size_t indexI, std::size_t indexJ) const {
auto cov = getCovariance();
const auto dim = getSize();
if (indexI >= dim || indexJ >= dim) {
throw std::runtime_error("Covariance index out of range");
}
if (cov.size() != dim * dim) {
throw std::runtime_error("Covariance matrix size mismatch");
}
const auto offset = indexJ * dim + indexI;
return cov[offset];
}

/// Decode and return the subspace indices stored in the type field
/// @return The subspace indices
std::vector<std::uint8_t> getSubspaceIndices() const {
return ActsPodioEdm::detail::decodeIndices(getType());
}

/// Find the measurement-vector index for an enum-coded subspace coordinate
///
/// @tparam E Enum type whose underlying value encodes a subspace index
/// @param enumVal The enum value to look up
/// @return The position in the measurement/covariance vector
/// @throws std::runtime_error if enumVal is not in the active subspace
template <typename E> requires std::is_enum_v<E>
std::size_t findSubspaceIndex(E enumVal) const {
const auto indices = getSubspaceIndices();
return ActsPodioEdm::detail::findSubspaceIndex(
std::span<const std::uint8_t>{indices}, enumVal);
}

/// Get measurement value for an enum-coded subspace coordinate
///
/// Equivalent to getValue(findSubspaceIndex(enumVal)).
///
/// @tparam E Enum type whose underlying value encodes a subspace index
/// @param enumVal The enum value identifying the coordinate
/// @return The measurement value
template <typename E> requires std::is_enum_v<E>
float getValue(E enumVal) const {
return getValue(findSubspaceIndex(enumVal));
}

/// Get covariance value for two enum-coded subspace coordinates
///
/// Equivalent to getCov(findSubspaceIndex(enumI), findSubspaceIndex(enumJ)).
///
/// @tparam E Enum type whose underlying value encodes a subspace index
/// @param enumI The first coordinate's enum value
/// @param enumJ The second coordinate's enum value
/// @return The covariance value at (enumI, enumJ)
template <typename E> requires std::is_enum_v<E>
float getCov(E enumI, E enumJ) const {
return getCov(findSubspaceIndex(enumI), findSubspaceIndex(enumJ));
}

// --- edm4hep::TrackerHit interface stubs (not implemented) ---

/// @throws std::logic_error always — quality is not used in TrackerHitLocal
std::int32_t getQuality() const {
throw std::logic_error("getQuality() is not implemented in TrackerHitLocal");
}

/// @throws std::logic_error always — eDep is not used in TrackerHitLocal
float getEDep() const {
throw std::logic_error("getEDep() is not implemented in TrackerHitLocal");
}

/// @throws std::logic_error always — eDepError is not used in TrackerHitLocal
float getEDepError() const {
throw std::logic_error("getEDepError() is not implemented in TrackerHitLocal");
}

MutableExtraCode:
includes: "#include <edm4hep/utils/SubspaceIndexUtils.hpp>"
declaration: |
/// Set the value for the passed measurement-vector index
/// @param val The value to set
/// @param valueIndex The index of the value
void setValue(float val, std::size_t valueIndex) {
const auto dim = getSize();
if (m_obj->m_measurement->size() != dim) {
throw std::runtime_error("Measurement vector not initialized - call setSubspaceIndices first");
}
if (valueIndex >= dim) {
throw std::runtime_error("Measurement index out of range");
}
(*m_obj->m_measurement)[valueIndex] = val;
}

/// Set the covariance value for the two passed matrix indices
/// @param val The value to set
/// @param indexI The first index
/// @param indexJ The second index
void setCov(float val, std::size_t indexI, std::size_t indexJ) {
const auto dim = getSize();
if (m_obj->m_covariance->size() != dim * dim) {
throw std::runtime_error("Covariance vector not initialized - call setSubspaceIndices first");
}
if (indexI >= dim || indexJ >= dim) {
throw std::runtime_error("Covariance index out of range");
}
const auto offset = indexJ * dim + indexI;
(*m_obj->m_covariance)[offset] = val;
}

/// Encode and store subspace indices into the type field
/// @param indices The subspace indices
/// @note This will initialize the measurement and covariance vectors if they are not already initialized
void setSubspaceIndices(std::span<const std::uint8_t> indices) {
setType(ActsPodioEdm::detail::encodeIndices(indices));
m_obj->m_measurement->assign(indices.size(), 0.f);
m_obj->m_covariance->assign(indices.size() * indices.size(), 0.f);
m_obj->data.measurement_begin = 0u;
m_obj->data.measurement_end = indices.size();
m_obj->data.covariance_begin = 0u;
m_obj->data.covariance_end = indices.size() * indices.size();
}

/// Set measurement value for an enum-coded subspace coordinate
///
/// Equivalent to setValue(val, findSubspaceIndex(enumVal)).
///
/// @tparam E Enum type whose underlying value encodes a subspace index
/// @param val The value to set
/// @param enumVal The enum value identifying the coordinate
template <typename E> requires std::is_enum_v<E>
void setValue(float val, E enumVal) {
setValue(val, findSubspaceIndex(enumVal));
}

/// Set covariance value for two enum-coded subspace coordinates
///
/// Equivalent to setCov(val, findSubspaceIndex(enumI), findSubspaceIndex(enumJ)).
///
/// @tparam E Enum type whose underlying value encodes a subspace index
/// @param val The value to set
/// @param enumI The first coordinate's enum value
/// @param enumJ The second coordinate's enum value
template <typename E> requires std::is_enum_v<E>
void setCov(float val, E enumI, E enumJ) {
setCov(val, findSubspaceIndex(enumI), findSubspaceIndex(enumJ));
}

edm4hep::RawTimeSeries:
Description: "Raw data of a detector readout"
Author: "EDM4hep authors"
Expand Down Expand Up @@ -680,6 +868,7 @@ interfaces:
- edm4hep::TrackerHit3D
- edm4hep::TrackerHitPlane
- edm4hep::SenseWireHit
- edm4hep::TrackerHitLocal

links:
edm4hep::RecoMCParticleLink:
Expand Down
121 changes: 121 additions & 0 deletions utils/include/edm4hep/utils/SubspaceIndexUtils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// This file is part of the ACTS project.
//
// Copyright (C) 2016 CERN for the benefit of the ACTS project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

#pragma once

#include <cstddef>
#include <cstdint>
#include <format>
#include <span>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <vector>

namespace ActsPodioEdm::detail {

/// Encoded index type for local measurement subspace coordinates.
using SubspaceIndex = std::uint8_t;
/// Largest allowed local subspace index value.
constexpr std::uint8_t kMaxSubspaceIndex = 6u;
/// Maximum number of coordinates in an encoded local subspace.
constexpr std::size_t kMaxSubspaceSize = 6u;

/// Encode a list of bound parameter indices into a 32-bit integer.
///
/// This function bit-packs up to `kMaxSubspaceSize` parameter indices into a
/// single 32-bit unsigned integer for storage in EDM4hep format.
///
/// Bit layout:
/// - Bits 0-3: Number of indices (size)
/// - Bits 4-7: First index
/// - Bits 8-11: Second index
/// - Bits 12-15: Third index
/// - (and so on, up to `kMaxSubspaceSize` indices total)
///
/// @param indices Span of parameter indices to encode (max
/// `kMaxSubspaceSize` elements)
/// @return Packed 32-bit unsigned integer containing all indices
inline std::int32_t encodeIndices(std::span<const std::uint8_t> indices) {
if (indices.size() > kMaxSubspaceSize) {
throw std::runtime_error(
std::format("Number of indices exceeds maximum of {} for EDM4hep",
kMaxSubspaceSize));
}

std::int32_t result = 0;
std::uint8_t shift = 0;
result |= (indices.size() << 0);
shift += 4;

for (std::uint8_t index : indices) {
if (index > kMaxSubspaceIndex) {
throw std::runtime_error(std::format(
"Index out of range: maximum allowed is {}", kMaxSubspaceIndex));
}
result |= (static_cast<std::int32_t>(index) << shift);
shift += 4;
}
return result;
}

/// Decode a 32-bit integer back into a list of bound parameter indices.
///
/// This function unpacks a bit-packed integer (created by encodeIndices) back
/// into the original list of parameter indices. See encodeIndices for the bit
/// layout specification.
///
/// @param type Packed 32-bit unsigned integer containing encoded indices
/// @return Vector of decoded parameter indices (each in
/// `[0, kMaxSubspaceIndex]`)
inline std::vector<SubspaceIndex> decodeIndices(std::int32_t type) {
std::vector<SubspaceIndex> result;
std::uint8_t size = type & 0xF;
if (size > kMaxSubspaceSize) {
throw std::runtime_error(
std::format("Number of indices exceeds maximum of {} for EDM4hep",
kMaxSubspaceSize));
}
result.resize(size);
for (std::size_t i = 0; i < result.size(); ++i) {
result[i] = (type >> ((i + 1) * 4)) & 0xF;
if (result[i] > kMaxSubspaceIndex) {
throw std::runtime_error(std::format(
"Index out of range: maximum allowed is {}", kMaxSubspaceIndex));
}
}
return result;
}

/// Find the measurement-vector position of an enum-coded subspace coordinate.
///
/// Searches @p indices for the given enum value (cast to SubspaceIndex) and
/// returns its position. This position is the index into the measurement and
/// covariance vectors stored in a TrackerHitLocal.
///
/// @tparam E Enum type whose underlying value encodes a subspace index
/// @param indices Active subspace indices (e.g. from decodeIndices())
/// @param enumVal The enum value to look up
/// @return Position of @p enumVal in @p indices
/// @throws std::runtime_error if @p enumVal is not present in @p indices
template <typename E>
requires std::is_enum_v<E>
inline std::size_t findSubspaceIndex(std::span<const SubspaceIndex> indices,
E enumVal) {
const auto target = static_cast<SubspaceIndex>(enumVal);
for (std::size_t i = 0; i < indices.size(); ++i) {
if (indices[i] == target) {
return i;
}
}
throw std::runtime_error(
std::format("Enum value {} not found in subspace indices",
static_cast<int>(enumVal)));
}

} // namespace ActsPodioEdm::detail
Loading