From 7215a171c19aad32d7de7e750c1f5319a1b3a6ff Mon Sep 17 00:00:00 2001 From: tmadlener Date: Wed, 26 Jun 2024 11:53:46 +0200 Subject: [PATCH 1/7] Add bit field utility functions --- test/utils/CMakeLists.txt | 2 +- test/utils/test_bit_utils.cpp | 25 +++++++++++++++++++++++++ utils/include/edm4hep/utils/bit_utils.h | 16 ++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 test/utils/test_bit_utils.cpp create mode 100644 utils/include/edm4hep/utils/bit_utils.h diff --git a/test/utils/CMakeLists.txt b/test/utils/CMakeLists.txt index fb84ecda3..af80e6e4a 100644 --- a/test/utils/CMakeLists.txt +++ b/test/utils/CMakeLists.txt @@ -16,7 +16,7 @@ endif() include(Catch) add_executable(unittests_edm4hep - test_kinematics.cpp test_vector_utils.cpp test_covmatrix_utils.cpp test_PIDHandler.cpp) + test_kinematics.cpp test_vector_utils.cpp test_covmatrix_utils.cpp test_PIDHandler.cpp test_bit_utils.cpp) target_link_libraries(unittests_edm4hep edm4hep EDM4HEP::utils Catch2::Catch2 Catch2::Catch2WithMain) diff --git a/test/utils/test_bit_utils.cpp b/test/utils/test_bit_utils.cpp new file mode 100644 index 000000000..11731c88d --- /dev/null +++ b/test/utils/test_bit_utils.cpp @@ -0,0 +1,25 @@ +#include "edm4hep/utils/bit_utils.h" + +#include +#include + +#include +#include + +// The integet types that we us as type fields in EDM4hep +using BitFieldTypes = std::tuple; + +TEMPLATE_LIST_TEST_CASE("Bitfield utils set and get", "[bit_utils]", BitFieldTypes) { + using namespace edm4hep; + auto bitField = TestType{}; + + for (auto i = 0u; i < sizeof(TestType) * 8; ++i) { + REQUIRE_FALSE(utils::checkBit(bitField, i)); + } + + bitField = utils::setBit(bitField, 3, true); + REQUIRE(utils::checkBit(bitField, 3)); + + bitField = utils::setBit(bitField, 3, false); + REQUIRE_FALSE(utils::checkBit(bitField, 3)); +} diff --git a/utils/include/edm4hep/utils/bit_utils.h b/utils/include/edm4hep/utils/bit_utils.h new file mode 100644 index 000000000..0ec72a1f7 --- /dev/null +++ b/utils/include/edm4hep/utils/bit_utils.h @@ -0,0 +1,16 @@ +#ifndef EDM4HEP_UTILS_BIT_UTILS_HH +#define EDM4HEP_UTILS_BIT_UTILS_HH + +namespace edm4hep::utils { +template +constexpr T setBit(T bits, int bitNum, bool value) { + return (bits & ~(1 << bitNum)) | (value << bitNum); +} + +template +constexpr bool checkBit(T bits, int bitNum) { + return bits & (0x1 << bitNum); +} +} // namespace edm4hep::utils + +#endif // EDM4HEP_UTILS_BIT_UTILS_HH From 0e0222ca67e341eaf99dc3e4e454befcbb829d92 Mon Sep 17 00:00:00 2001 From: tmadlener Date: Wed, 26 Jun 2024 12:03:58 +0200 Subject: [PATCH 2/7] Use bit field utilities in MCParticle --- edm4hep.yaml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/edm4hep.yaml b/edm4hep.yaml index dbaa09f7a..53a972231 100644 --- a/edm4hep.yaml +++ b/edm4hep.yaml @@ -264,18 +264,18 @@ datatypes: MutableExtraCode: includes: "#include " declaration: " - int32_t set_bit(int32_t val, int num, bool bitval){ return (val & ~(1<\n" declaration: " // define the bit positions for the simulation flag\n static const int BITCreatedInSimulation = 30;\n @@ -291,21 +291,21 @@ datatypes: getMomentum()[2]*getMomentum()[2] + getMass()*getMass() ) ;} \n /// True if the particle has been created by the simulation program (rather than the generator). \n - bool isCreatedInSimulation() const { return ( getSimulatorStatus() & ( 0x1 << BITCreatedInSimulation )) ; } \n + bool isCreatedInSimulation() const { return utils::checkBit(getSimulatorStatus(), BITCreatedInSimulation); } \n /// True if the particle is the result of a backscatter from a calorimeter shower. \n - bool isBackscatter() const { return ( getSimulatorStatus() & ( 0x1 << BITBackscatter )) ; } \n + bool isBackscatter() const { return utils::checkBit(getSimulatorStatus(), BITBackscatter); } \n /// True if the particle's vertex is not the endpoint of the parent particle. \n - bool vertexIsNotEndpointOfParent() const { return ( getSimulatorStatus() & ( 0x1 << BITVertexIsNotEndpointOfParent )) ; } \n + bool vertexIsNotEndpointOfParent() const { return utils::checkBit(getSimulatorStatus(), BITVertexIsNotEndpointOfParent); } \n /// True if the particle has interacted in a tracking region. \n - bool isDecayedInTracker() const { return ( getSimulatorStatus() & ( 0x1 << BITDecayedInTracker )) ; } \n + bool isDecayedInTracker() const { return utils::checkBit(getSimulatorStatus(), BITDecayedInTracker); } \n /// True if the particle has interacted in a calorimeter region. \n - bool isDecayedInCalorimeter() const { return ( getSimulatorStatus() & ( 0x1 << BITDecayedInCalorimeter )) ; } \n + bool isDecayedInCalorimeter() const { return utils::checkBit(getSimulatorStatus(), BITDecayedInCalorimeter); } \n /// True if the particle has left the world volume undecayed. \n - bool hasLeftDetector() const { return ( getSimulatorStatus() & ( 0x1 << BITLeftDetector )) ; }\n + bool hasLeftDetector() const { return utils::checkBit(getSimulatorStatus(), BITLeftDetector); }\n /// True if the particle has been stopped by the simulation program. \n - bool isStopped() const { return ( getSimulatorStatus() & ( 0x1 << BITStopped )) ; } \n + bool isStopped() const { return utils::checkBit(getSimulatorStatus(), BITStopped); } \n /// True if the particle has been overlayed by the simulation (or digitization) program.\n - bool isOverlay() const { return ( getSimulatorStatus() & ( 0x1 << BITOverlay )) ; } \n + bool isOverlay() const { return utils::checkBit(getSimulatorStatus(), BITOverlay); } \n " From a78e88231b389ac068b22d8beaf3d71861c798fb Mon Sep 17 00:00:00 2001 From: tmadlener Date: Wed, 26 Jun 2024 12:04:43 +0200 Subject: [PATCH 3/7] Make the Vertex primary field a proper type bitfield --- edm4hep.yaml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/edm4hep.yaml b/edm4hep.yaml index 53a972231..e0063222b 100644 --- a/edm4hep.yaml +++ b/edm4hep.yaml @@ -537,7 +537,7 @@ datatypes: Description: "Vertex" Author: "EDM4hep authors" Members: - - int32_t primary // boolean flag, if vertex is the primary vertex of the event + - uint32_t type // Flagword that defines the type of the vertex, see reserved bits for more information - float chi2 // chi-squared of the vertex fit - int32_t ndf // number of degrees of freedom of the vertex fit - edm4hep::Vector3f position // [mm] position of the vertex @@ -548,16 +548,34 @@ datatypes: OneToOneRelations: - edm4hep::ReconstructedParticle associatedParticle // reconstructed particle associated to this vertex ExtraCode: - includes: "#include " + includes: "#include \n + #include \n" declaration: " /// Get the position covariance matrix value for the two passed dimensions\n float getCovMatrix(edm4hep::Cartesian dimI, edm4hep::Cartesian dimJ) const { return getCovMatrix().getValue(dimI, dimJ); }\n + // Reserved bits for the type flagword\n + static constexpr int BITPrimaryVertex = 1;\n + static constexpr int BITSecondaryVertex = 2;\n + static constexpr int BITTertiaryVertex = 2;\n + + /// Check if this is a primary vertex\n + bool isPrimary() const { return utils::checkBit(getType(), BITPrimaryVertex); }\n + /// Check if this is a secondary vertex\n + bool isSecondary() const { return utils::checkBit(getType(), BITSecondaryVertex); }\n + /// Check if this is a tertiary vertex\n + bool isTertiary() const { return utils::checkBit(getType(), BITTertiaryVertex); }\n " MutableExtraCode: - includes: "#include " declaration: " /// Set the position covariance matrix value for the two passed dimensions\n void setCovMatrix(float value, edm4hep::Cartesian dimI, edm4hep::Cartesian dimJ) { getCovMatrix().setValue(value, dimI, dimJ); }\n + + /// Set the primary vertex flag for this vertex + void setPrimaryVertex(bool value=true) { setType(utils::setBit(getType(), BITPrimaryVertex, value)); }\n + /// Set the secondary vertex flag for this vertex + void setSecondaryVertex(bool value=true) { setType(utils::setBit(getType(), BITSecondaryVertex, value)); }\n + /// Set the tertiary vertex flag for this vertex + void setTertiaryVertex(bool value=true) { setType(utils::setBit(getType(), BITTertiaryVertex, value)); }\n " #------- ReconstructedParticle From dd63ead6115bf8f3b05e3e02cfeb7d95ed1e20a5 Mon Sep 17 00:00:00 2001 From: tmadlener Date: Thu, 27 Jun 2024 11:52:17 +0200 Subject: [PATCH 4/7] Keep existing function name for less downstream breakage --- edm4hep.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/edm4hep.yaml b/edm4hep.yaml index e0063222b..851e77347 100644 --- a/edm4hep.yaml +++ b/edm4hep.yaml @@ -571,11 +571,11 @@ datatypes: void setCovMatrix(float value, edm4hep::Cartesian dimI, edm4hep::Cartesian dimJ) { getCovMatrix().setValue(value, dimI, dimJ); }\n /// Set the primary vertex flag for this vertex - void setPrimaryVertex(bool value=true) { setType(utils::setBit(getType(), BITPrimaryVertex, value)); }\n + void setPrimary(bool value=true) { setType(utils::setBit(getType(), BITPrimaryVertex, value)); }\n /// Set the secondary vertex flag for this vertex - void setSecondaryVertex(bool value=true) { setType(utils::setBit(getType(), BITSecondaryVertex, value)); }\n + void setSecondary(bool value=true) { setType(utils::setBit(getType(), BITSecondaryVertex, value)); }\n /// Set the tertiary vertex flag for this vertex - void setTertiaryVertex(bool value=true) { setType(utils::setBit(getType(), BITTertiaryVertex, value)); }\n + void setTertiary(bool value=true) { setType(utils::setBit(getType(), BITTertiaryVertex, value)); }\n " #------- ReconstructedParticle From d411b6bdc7c498dccf486aada6aa6c3e20c50e4c Mon Sep 17 00:00:00 2001 From: tmadlener Date: Thu, 27 Jun 2024 12:03:11 +0200 Subject: [PATCH 5/7] Fix ExtraCode to actually get it generated properly --- edm4hep.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/edm4hep.yaml b/edm4hep.yaml index 851e77347..b9d51801b 100644 --- a/edm4hep.yaml +++ b/edm4hep.yaml @@ -570,11 +570,11 @@ datatypes: /// Set the position covariance matrix value for the two passed dimensions\n void setCovMatrix(float value, edm4hep::Cartesian dimI, edm4hep::Cartesian dimJ) { getCovMatrix().setValue(value, dimI, dimJ); }\n - /// Set the primary vertex flag for this vertex + /// Set the primary vertex flag for this vertex\n void setPrimary(bool value=true) { setType(utils::setBit(getType(), BITPrimaryVertex, value)); }\n - /// Set the secondary vertex flag for this vertex + /// Set the secondary vertex flag for this vertex\n void setSecondary(bool value=true) { setType(utils::setBit(getType(), BITSecondaryVertex, value)); }\n - /// Set the tertiary vertex flag for this vertex + /// Set the tertiary vertex flag for this vertex\n void setTertiary(bool value=true) { setType(utils::setBit(getType(), BITTertiaryVertex, value)); }\n " From fba94a4b109d0032f6efaea63aad4b951ccca2ee Mon Sep 17 00:00:00 2001 From: tmadlener Date: Fri, 28 Jun 2024 10:36:16 +0200 Subject: [PATCH 6/7] Add more utility functionality for checking / setting bitfields --- test/utils/test_bit_utils.cpp | 42 ++++++++++++ utils/include/edm4hep/utils/bit_utils.h | 87 +++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 4 deletions(-) diff --git a/test/utils/test_bit_utils.cpp b/test/utils/test_bit_utils.cpp index 11731c88d..be8e23ac9 100644 --- a/test/utils/test_bit_utils.cpp +++ b/test/utils/test_bit_utils.cpp @@ -20,6 +20,48 @@ TEMPLATE_LIST_TEST_CASE("Bitfield utils set and get", "[bit_utils]", BitFieldTyp bitField = utils::setBit(bitField, 3, true); REQUIRE(utils::checkBit(bitField, 3)); + bitField = utils::setBit(bitField, 4, true); + REQUIRE(utils::checkBit(bitField, 3)); + REQUIRE(utils::checkBit(bitField, 4)); + bitField = utils::setBit(bitField, 3, false); REQUIRE_FALSE(utils::checkBit(bitField, 3)); + REQUIRE(utils::checkBit(bitField, 4)); +} + +TEMPLATE_LIST_TEST_CASE("Bitfield utils set multiple", "[bit_utils]", BitFieldTypes) { + using namespace edm4hep; + auto bitField = TestType{}; + bitField = utils::setBits(bitField, true, 3, 4, 7); + + REQUIRE(utils::checkBit(bitField, 3)); + REQUIRE(utils::checkBit(bitField, 4)); + REQUIRE(utils::checkBit(bitField, 7)); + REQUIRE_FALSE(utils::checkBit(bitField, 1)); + REQUIRE_FALSE(utils::checkBit(bitField, 2)); + REQUIRE_FALSE(utils::checkBit(bitField, 5)); + REQUIRE_FALSE(utils::checkBit(bitField, 6)); + REQUIRE_FALSE(utils::checkBit(bitField, 8)); +} + +TEMPLATE_LIST_TEST_CASE("Bitfield utils check all ", "[bit_utils]", BitFieldTypes) { + using namespace edm4hep; + auto bitField = TestType{}; + bitField = utils::setBits(bitField, true, 3, 4, 7); + + REQUIRE(utils::checkAllBits(bitField, 7, 3, 4)); + REQUIRE(utils::checkAllBits(bitField, 3, 4)); + REQUIRE_FALSE(utils::checkAllBits(bitField, 2, 3, 4, 7)); + REQUIRE_FALSE(utils::checkAllBits(bitField, 2, 3, 4)); +} + +TEMPLATE_LIST_TEST_CASE("Bitfield utils check any ", "[bit_utils]", BitFieldTypes) { + using namespace edm4hep; + auto bitField = TestType{}; + bitField = utils::setBits(bitField, true, 3, 4, 7); + + REQUIRE(utils::checkAnyBits(bitField, 3, 4)); + REQUIRE(utils::checkAnyBits(bitField, 3)); + REQUIRE(utils::checkAnyBits(bitField, 1, 2, 3)); + REQUIRE_FALSE(utils::checkAnyBits(bitField, 1, 2, 6, 8)); } diff --git a/utils/include/edm4hep/utils/bit_utils.h b/utils/include/edm4hep/utils/bit_utils.h index 0ec72a1f7..f23fa2bce 100644 --- a/utils/include/edm4hep/utils/bit_utils.h +++ b/utils/include/edm4hep/utils/bit_utils.h @@ -1,16 +1,95 @@ #ifndef EDM4HEP_UTILS_BIT_UTILS_HH #define EDM4HEP_UTILS_BIT_UTILS_HH +#include + namespace edm4hep::utils { + +/// Set a bit in the passed bitfield to the desired value +/// +/// @tparam T any integer type that can be used as a bitfield, typically an +/// unsigned integer type +/// +/// @param bitfield The bitfield for which the bit should be set +/// @param bit The bit (number) that should be set +/// @param value The value to which the bit should be set +/// +/// @returns The new value of the bitfield after setting bits template -constexpr T setBit(T bits, int bitNum, bool value) { - return (bits & ~(1 << bitNum)) | (value << bitNum); +constexpr T setBit(T bitfield, int bit, bool value) { + return (bitfield & ~(0x1 << bit)) | (value << bit); +} + +/// Set multiple bits to one desired value in the passed bitfield +/// +/// @tparam T any integer type that can be used as a bitfield, typically an +/// unsigned integer type +/// @tparam Bits A variable number of bits (numbers) that should be set +/// +/// @param bitfield The bitfield for which the bit should be set +/// @param value The value to which the bit should be set +/// @param bits The bits that should be set +template +constexpr T setBits(T bitfield, bool value, Bits... bits) { + static_assert((std::is_same_v && ...), "All bit numbers to set must be integers"); + static_assert(sizeof...(bits) > 0, "Need at least one bit to set"); + + for (auto n : {bits...}) { + bitfield = setBit(bitfield, n, value); + } + return bitfield; } +/// Check if a bit is set in the bitfield +/// +/// @tparam T any integer type that can be used as a bitfield, typically an +/// unsigned integer type +/// +/// @param bitfield The bitfield that should be checked +/// @param bit The bit (number) that should be checked +/// +/// @returns true if the passed bit is set in the bitfield and false otherwise template -constexpr bool checkBit(T bits, int bitNum) { - return bits & (0x1 << bitNum); +constexpr bool checkBit(T bitfield, int bit) { + return bitfield & (0x1 << bit); } + +/// Check if all the passed bits are set in the bitfield +/// +/// @tparam T any integer type that can be used as a bitfield, typically an +/// unsigned integer type +/// @tparam Bits A variable number of bits (numbers) that should be checked +/// +/// @param bitfield The bitfield that should be checked +/// @param bits The bits that should be checked +/// +/// @returns true if all the passed bits are set in the bitfield and false +/// otherwise +template +constexpr bool checkAllBits(T bitfield, Bits... bits) { + static_assert((std::is_same_v && ...), "All bit numbers to set must be integers"); + static_assert(sizeof...(bits) > 0, "Need at least one bit to check"); + return (true && ... && checkBit(bitfield, bits)); +} + +/// Check if any of the passed bits is set in the bitfield +/// +/// @tparam T any integer type that can be used as a bitfield, typically an +/// unsigned integer type +/// @tparam Bits A variable number of bits (numbers) that should be checked +/// +/// @param bitfield The bitfield that should be checked +/// @param bits The bits that should be checked +/// +/// @returns true if any of the passed bits is set in the bitfield and false +/// otherwise +template +constexpr bool checkAnyBits(T bitfield, Bits... bits) { + static_assert((std::is_same_v && ...), "All bit numbers to set must be integers"); + static_assert(sizeof...(bits) > 0, "Need at least one bit to check"); + return (false || ... || checkBit(bitfield, bits)); +} + } // namespace edm4hep::utils #endif // EDM4HEP_UTILS_BIT_UTILS_HH From 9ed34fcff3304e4e0f251cc2effbf9d9e2b72e1b Mon Sep 17 00:00:00 2001 From: tmadlener Date: Mon, 8 Jul 2024 15:41:17 +0200 Subject: [PATCH 7/7] Fix README links --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 28914657b..e5953c7ba 100644 --- a/README.md +++ b/README.md @@ -26,29 +26,29 @@ A generic event data model for future HEP collider experiments. | [CaloHitContribution](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L355) | [SimCalorimeterHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L367) | [RawCalorimeterHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L379) | | [CalorimeterHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L388) | [ParticleID](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L400) | [Cluster](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L415) | | [TrackerHit3D](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L447) | [TrackerHitPlane](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L473) | [RawTimeSeries](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L503) | -| [Track](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L517) | [Vertex](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L536) | [ReconstructedParticle](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L564) | -| [TimeSeries](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L666) | [RecDqdx](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L678) | | +| [Track](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L517) | [Vertex](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L536) | [ReconstructedParticle](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L582) | +| [TimeSeries](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L684) | [RecDqdx](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L696) | | **Associations** | | | | |-|-|-| -| [MCRecoParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L602) | [MCRecoCaloAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L611) | [MCRecoTrackerAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L620) | -| [MCRecoCaloParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L629) | [MCRecoClusterParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L638) | [MCRecoTrackParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L647) | -| [RecoParticleVertexAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L656) | | | +| [MCRecoParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L620) | [MCRecoCaloAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L629) | [MCRecoTrackerAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L638) | +| [MCRecoCaloParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L647) | [MCRecoClusterParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L656) | [MCRecoTrackParticleAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L665) | +| [RecoParticleVertexAssociation](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L674) | | | **Generator related (meta-)data** | | | | |-|-|-| -| [GeneratorEventParameters](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L690) | | | -| [GeneratorPdfInfo](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L707) | | | +| [GeneratorEventParameters](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L708) | | | +| [GeneratorPdfInfo](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L725) | | | **Interfaces** | | | | |-|-|-| -| [TrackerHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L718) | | | +| [TrackerHit](https://github.com/key4hep/EDM4hep/blob/main/edm4hep.yaml#L736) | | | The tests and examples in the `tests` directory show how to read, write, and use these types in your code.