Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the Vertex have a proper type bitfield instead of a primary field #329

Merged
merged 7 commits into from
Jul 8, 2024
Merged
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
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
58 changes: 38 additions & 20 deletions edm4hep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -264,18 +264,18 @@ datatypes:
MutableExtraCode:
includes: "#include <cmath>"
declaration: "
int32_t set_bit(int32_t val, int num, bool bitval){ return (val & ~(1<<num)) | (bitval << num); } \n
void setCreatedInSimulation(bool bitval) { setSimulatorStatus( set_bit( getSimulatorStatus() , BITCreatedInSimulation , bitval ) ) ; } \n
void setBackscatter(bool bitval) { setSimulatorStatus( set_bit( getSimulatorStatus() , BITBackscatter , bitval ) ) ; } \n
void setVertexIsNotEndpointOfParent(bool bitval) { setSimulatorStatus( set_bit( getSimulatorStatus() , BITVertexIsNotEndpointOfParent , bitval ) ) ; } \n
void setDecayedInTracker(bool bitval) { setSimulatorStatus( set_bit( getSimulatorStatus() , BITDecayedInTracker , bitval ) ) ; } \n
void setDecayedInCalorimeter(bool bitval) { setSimulatorStatus( set_bit( getSimulatorStatus() , BITDecayedInCalorimeter , bitval ) ) ; } \n
void setHasLeftDetector(bool bitval) { setSimulatorStatus( set_bit( getSimulatorStatus() , BITLeftDetector , bitval ) ) ; } \n
void setStopped(bool bitval) { setSimulatorStatus( set_bit( getSimulatorStatus() , BITStopped , bitval ) ) ; } \n
void setOverlay(bool bitval) { setSimulatorStatus( set_bit( getSimulatorStatus() , BITOverlay , bitval ) ) ; } \n
void setCreatedInSimulation(bool bitval) { setSimulatorStatus( utils::setBit( getSimulatorStatus() , BITCreatedInSimulation , bitval ) ) ; } \n
void setBackscatter(bool bitval) { setSimulatorStatus( utils::setBit( getSimulatorStatus() , BITBackscatter , bitval ) ) ; } \n
void setVertexIsNotEndpointOfParent(bool bitval) { setSimulatorStatus( utils::setBit( getSimulatorStatus() , BITVertexIsNotEndpointOfParent , bitval ) ) ; } \n
void setDecayedInTracker(bool bitval) { setSimulatorStatus( utils::setBit( getSimulatorStatus() , BITDecayedInTracker , bitval ) ) ; } \n
void setDecayedInCalorimeter(bool bitval) { setSimulatorStatus( utils::setBit( getSimulatorStatus() , BITDecayedInCalorimeter , bitval ) ) ; } \n
void setHasLeftDetector(bool bitval) { setSimulatorStatus( utils::setBit( getSimulatorStatus() , BITLeftDetector , bitval ) ) ; } \n
void setStopped(bool bitval) { setSimulatorStatus( utils::setBit( getSimulatorStatus() , BITStopped , bitval ) ) ; } \n
void setOverlay(bool bitval) { setSimulatorStatus( utils::setBit( getSimulatorStatus() , BITOverlay , bitval ) ) ; } \n
"

ExtraCode:
includes: "#include <edm4hep/utils/bit_utils.h>\n"
declaration: "
// define the bit positions for the simulation flag\n
static const int BITCreatedInSimulation = 30;\n
Expand All @@ -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
"


Expand Down Expand Up @@ -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
Expand All @@ -548,16 +548,34 @@ datatypes:
OneToOneRelations:
- edm4hep::ReconstructedParticle associatedParticle // reconstructed particle associated to this vertex
ExtraCode:
includes: "#include <edm4hep/Constants.h>"
includes: "#include <edm4hep/Constants.h>\n
#include <edm4hep/utils/bit_utils.h>\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
tmadlener marked this conversation as resolved.
Show resolved Hide resolved

/// 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 <edm4hep/Constants.h>"
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\n
void setPrimary(bool value=true) { setType(utils::setBit(getType(), BITPrimaryVertex, value)); }\n
/// 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\n
void setTertiary(bool value=true) { setType(utils::setBit(getType(), BITTertiaryVertex, value)); }\n
"

#------- ReconstructedParticle
Expand Down
2 changes: 1 addition & 1 deletion test/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
67 changes: 67 additions & 0 deletions test/utils/test_bit_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "edm4hep/utils/bit_utils.h"

#include <catch2/catch_template_test_macros.hpp>
#include <catch2/catch_test_macros.hpp>

#include <cstdint>
#include <tuple>

// The integet types that we us as type fields in EDM4hep
using BitFieldTypes = std::tuple<int32_t, uint32_t, int64_t, int16_t, uint64_t>;

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, 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));
}
95 changes: 95 additions & 0 deletions utils/include/edm4hep/utils/bit_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#ifndef EDM4HEP_UTILS_BIT_UTILS_HH
#define EDM4HEP_UTILS_BIT_UTILS_HH

#include <type_traits>

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 <typename T>
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 <typename T, typename... Bits>
constexpr T setBits(T bitfield, bool value, Bits... bits) {
static_assert((std::is_same_v<Bits, int> && ...), "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 <typename T>
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 <typename T, typename... Bits>
constexpr bool checkAllBits(T bitfield, Bits... bits) {
static_assert((std::is_same_v<Bits, int> && ...), "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 <typename T, typename... Bits>
constexpr bool checkAnyBits(T bitfield, Bits... bits) {
static_assert((std::is_same_v<Bits, int> && ...), "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
Loading