Skip to content

Commit

Permalink
Make the Vertex have a proper type bitfield instead of a primary
Browse files Browse the repository at this point in the history
…field (key4hep#329)

* Add bit field utility functions

* Use bit field utilities in MCParticle

* Make the Vertex primary field a proper type bitfield

* Keep existing function name for less downstream breakage

* Fix ExtraCode to actually get it generated properly

* Add more utility functionality for checking / setting bitfields

* Fix README links
  • Loading branch information
tmadlener authored Jul 8, 2024
1 parent aa83ff0 commit f824ed1
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 29 deletions.
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
/// 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

0 comments on commit f824ed1

Please sign in to comment.