Skip to content

Commit

Permalink
Merge branch 'main' into seeding-monitoring
Browse files Browse the repository at this point in the history
  • Loading branch information
LuisFelipeCoelho authored Nov 15, 2022
2 parents 42fc998 + b018119 commit 2f297d5
Show file tree
Hide file tree
Showing 9 changed files with 319 additions and 43 deletions.
12 changes: 11 additions & 1 deletion Core/include/Acts/Seeding/SeedFinder.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ void SeedFinder<external_spacepoint_t, platform_t>::createSeedsForGroup(
float varianceRM = spM->varianceR();
float varianceZM = spM->varianceZ();

/// check if spM is outside our radial region of interest
// check if spM is outside our radial region of interest
if (m_config.useVariableMiddleSPRange) {
if (rM < rMiddleSPRange.min()) {
continue;
Expand Down Expand Up @@ -80,6 +80,16 @@ void SeedFinder<external_spacepoint_t, platform_t>::createSeedsForGroup(
}
continue;
}
} else {
if (rM > m_config.rMaxMiddle) {
continue;
}
if (rM < m_config.rMinMiddle) {
if (m_config.forceRadialSorting) {
break;
}
continue;
}
}

state.compatTopSP.clear();
Expand Down
12 changes: 9 additions & 3 deletions Core/include/Acts/Seeding/SeedFinderConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,20 @@ struct SeedFinderConfig {
float deltaRMaxBottomSP = std::numeric_limits<float>::quiet_NaN();
// radial bin size for filling space point grid
float binSizeR = 1. * Acts::UnitConstants::mm;
// force sorting in R in space point grid bins

// force sorting of middle SPs in radius
bool forceRadialSorting = false;

// radial range for middle SP
std::vector<std::vector<float>> rRangeMiddleSP;
bool useVariableMiddleSPRange = false;
// variable range based on SP radius
bool useVariableMiddleSPRange = true;
float deltaRMiddleMinSPRange = 10. * Acts::UnitConstants::mm;
float deltaRMiddleMaxSPRange = 10. * Acts::UnitConstants::mm;
// range defined in vector for each z region
std::vector<std::vector<float>> rRangeMiddleSP;
// range defined by rMinMiddle and rMaxMiddle
float rMinMiddle = 60.f * Acts::UnitConstants::mm;
float rMaxMiddle = 120.f * Acts::UnitConstants::mm;

// cut to the maximum value of delta z between SPs
float deltaZMax =
Expand Down
36 changes: 27 additions & 9 deletions Core/include/Acts/Seeding/SeedFinderOrthogonal.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -458,15 +458,6 @@ void SeedFinderOrthogonal<external_spacepoint_t>::processFromMiddleSP(
*/
std::vector<internal_sp_t *> bottom_lh_v, bottom_hl_v, top_lh_v, top_hl_v;

/*
* Cut: Ensure that the middle spacepoint lies within a valid r-region for
* middle points.
*/
if (middle.radius() > m_config.rMaxMiddle ||
middle.radius() < m_config.rMinMiddle) {
return;
}

/*
* Calculate the search ranges for bottom and top candidates for this middle
* space point.
Expand Down Expand Up @@ -663,13 +654,23 @@ void SeedFinderOrthogonal<external_spacepoint_t>::createSeeds(
* take each external spacepoint, allocate a corresponding internal space
* point, and save it in a vector.
*/
Acts::Extent rRangeSPExtent;
std::vector<internal_sp_t *> internalSpacePoints;
for (const external_spacepoint_t *p : spacePoints) {
internalSpacePoints.push_back(new InternalSpacePoint<external_spacepoint_t>(
*p, {p->x(), p->y(), p->z()}, {0.0, 0.0},
{p->varianceR(), p->varianceZ()}));
// store x,y,z values in extent
rRangeSPExtent.extend({p->x(), p->y(), p->z()});
}

// variable middle SP radial region of interest
const Acts::Range1D<float> rMiddleSPRange(
std::floor(rRangeSPExtent.min(Acts::binR) / 2) * 2 +
m_config.deltaRMiddleMinSPRange,
std::floor(rRangeSPExtent.max(Acts::binR) / 2) * 2 -
m_config.deltaRMiddleMaxSPRange);

/*
* Construct the k-d tree from these points. Note that this not consume or
* take ownership of the points.
Expand All @@ -681,6 +682,23 @@ void SeedFinderOrthogonal<external_spacepoint_t>::createSeeds(
* seeing what happens if we take them to be our middle spacepoint.
*/
for (const typename tree_t::pair_t &middle_p : tree) {
internal_sp_t &middle = *middle_p.second;
auto rM = middle.radius();

/*
* Cut: Ensure that the middle spacepoint lies within a valid r-region for
* middle points.
*/
if (m_config.useVariableMiddleSPRange) {
if (rM < rMiddleSPRange.min() || rM > rMiddleSPRange.max()) {
continue;
}
} else {
if (rM > m_config.rMaxMiddle || rM < m_config.rMinMiddle) {
continue;
}
}

processFromMiddleSP(tree, out_cont, middle_p);
}

Expand Down
8 changes: 8 additions & 0 deletions Core/include/Acts/Seeding/SeedFinderOrthogonalConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ struct SeedFinderOrthogonalConfig {
// which will make seeding very slow!
float rMin = 33 * Acts::UnitConstants::mm;

// radial range for middle SP
// variable range based on SP radius
bool useVariableMiddleSPRange = true;
float deltaRMiddleMinSPRange = 10. * Acts::UnitConstants::mm;
float deltaRMiddleMaxSPRange = 10. * Acts::UnitConstants::mm;
// range defined in vector for each z region
std::vector<std::vector<float>> rRangeMiddleSP;
// range defined by rMinMiddle and rMaxMiddle
float rMinMiddle = 60.f * Acts::UnitConstants::mm;
float rMaxMiddle = 120.f * Acts::UnitConstants::mm;

Expand Down
145 changes: 119 additions & 26 deletions Core/include/Acts/Utilities/Delegate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,49 +12,69 @@

#include <cassert>
#include <functional>
#include <memory>
#include <type_traits>

namespace Acts {

template <typename>
/// Ownership enum for @c Delegate
enum class DelegateType { Owning, NonOwning };

// Specialization needed for defaulting ownership and for R(Args...) syntax
template <typename, DelegateType = DelegateType::NonOwning>
class Delegate;

/// Delegate type that allows type erasure of a callable without allocation and
/// with a single level of indirection.
/// This type can support:
/// Delegate type that allows type erasure of a callable without allocation
/// and with a single level of indirection. This type can support:
/// - a free function pointer
/// - a pointer to a member function alongside an instance pointer
/// @note @c Delegate does not assume ownership of the instance.
/// You need to ensure that the lifetime of the callable
/// instance is longer than that of the @c Delegate.
/// @note @c Delegate by default does not assume ownership of the instance.
/// In that case You need to ensure that the lifetime of the callable
/// instance is longer than that of the @c Delegate. If you set @c O
/// to @c DelegateType::Owning, it will assume ownership.
/// @note Currently @c Delegate only supports callables that are ``const``
/// @tparam R Return type of the function signature
/// @tparam O Ownership type of the delegate: Owning or NonOwning
/// @tparam Args Types of the arguments of the function signatures
///
template <typename R, typename... Args>
class Delegate<R(Args...)> {
template <typename R, DelegateType O, typename... Args>
class Delegate<R(Args...), O> {
static constexpr DelegateType kOwnership = O;

/// Alias of the return type
using return_type = R;
/// Alias to the function pointer type this class will store
using function_type = return_type (*)(const void *, Args...);

using function_ptr_type = return_type (*)(Args...);

using deleter_type = void (*)(const void *);

template <typename T, typename C>
using isSignatureCompatible =
decltype(std::declval<T &>() = std::declval<C>());

using OwningDelegate = Delegate<R(Args...), DelegateType::Owning>;
using NonOwningDelegate = Delegate<R(Args...), DelegateType::NonOwning>;
template <typename T>
using isNoFunPtr = std::enable_if_t<
not std::is_convertible_v<std::decay_t<T>, function_type>>;
not std::is_convertible_v<std::decay_t<T>, function_type> and
not std::is_same_v<std::decay_t<T>, OwningDelegate> and
not std::is_same_v<std::decay_t<T>, NonOwningDelegate>>;

public:
Delegate() = default;

Delegate(Delegate &&) = default;
Delegate &operator=(Delegate &&) = default;
Delegate(const Delegate &) = default;
Delegate &operator=(const Delegate &) = default;

/// Constructor with an explicit runtime callable
/// @param callable The runtime value of the callable
/// @note The function signature requires the first argument of the callable is `const void*`.
/// i.e. if the signature of the delegate is `void(int)`, the callable's
/// signature has to be `void(const void*, int)`.
/// i.e. if the signature of the delegate is `void(int)`, the
/// callable's signature has to be `void(const void*, int)`.
Delegate(function_type callable) { connect(callable); }

/// Constructor with a possibly stateful function object.
Expand All @@ -75,8 +95,8 @@ class Delegate<R(Args...)> {
/// Assignment operator with an explicit runtime callable
/// @param callable The runtime value of the callable
/// @note The function signature requires the first argument of the callable is `const void*`.
/// i.e. if the signature of the delegate is `void(int)`, the callable's
/// signature has to be `void(const void*, int)`.
/// i.e. if the signature of the delegate is `void(int)`, the
/// callable's signature has to be `void(const void*, int)`.
void operator=(function_type callable) { connect(callable); }

/// Assignment operator with possibly stateful function object.
Expand All @@ -99,7 +119,7 @@ class Delegate<R(Args...)> {
/// @tparam Callable The compile-time free function pointer
template <auto Callable>
void connect() {
m_payload = nullptr;
m_payload.payload = nullptr;

static_assert(
Concepts::is_detected<isSignatureCompatible, function_ptr_type,
Expand All @@ -122,18 +142,20 @@ class Delegate<R(Args...)> {
connect<&Callable::operator(), Callable>(&callable);
}

/// Connection with rvalue reference is deleted, should catch assignment from
/// temporary objects and thus invalid pointers
/// Connection with rvalue reference is deleted, should catch assignment
/// from temporary objects and thus invalid pointers
template <typename Callable, typename = isNoFunPtr<Callable>>
void connect(Callable &&) = delete;

/// Connect anything that is assignable to the function pointer
/// @param callable The runtime value of the callable
/// @note The function signature requires the first argument of the callable is `const void*`.
/// i.e. if the signature of the delegate is `void(int)`, the callable's
/// signature has to be `void(const void*, int)`.
/// i.e. if the signature of the delegate is `void(int)`, the
/// callable's signature has to be `void(const void*, int)`.
void connect(function_type callable) {
m_payload = nullptr;
if constexpr (kOwnership == DelegateType::NonOwning) {
m_payload.payload = nullptr;
}
m_function = callable;
}

Expand All @@ -143,7 +165,8 @@ class Delegate<R(Args...)> {
/// @param instance The instance on which the member function pointer should be called on
/// @note @c Delegate does not assume owner ship over @p instance. You need to ensure
/// it's lifetime is longer than that of @c Delegate.
template <auto Callable, typename Type>
template <auto Callable, typename Type, DelegateType T = kOwnership,
typename = std::enable_if_t<T == DelegateType::NonOwning>>
void connect(const Type *instance) {
using member_ptr_type = return_type (Type::*)(Args...) const;

Expand All @@ -152,7 +175,39 @@ class Delegate<R(Args...)> {
"Callable given does not correspond exactly to required call "
"signature");

m_payload = instance;
m_payload.payload = instance;

m_function = [](const void *payload, Args... args) -> return_type {
assert(payload != nullptr && "Payload is required, but not set");
const auto *concretePayload = static_cast<const Type *>(payload);
return std::invoke(Callable, concretePayload,
std::forward<Args>(args)...);
};
}

/// Connect a member function to be called on an instance
/// @tparam Callable The compile-time member function pointer
/// @tparam Type The type of the instance the member function should be called on
/// @param instance The instance on which the member function pointer should be called on
/// @note @c Delegate assumes owner ship over @p instance.
template <auto Callable, typename Type>
void connect(std::unique_ptr<const Type> instance) {
using member_ptr_type = return_type (Type::*)(Args...) const;
static_assert(Concepts::is_detected<isSignatureCompatible, member_ptr_type,
decltype(Callable)>::value,
"Callable given does not correspond exactly to required call "
"signature");

if constexpr (kOwnership == DelegateType::Owning) {
m_payload.payload = std::unique_ptr<const void, deleter_type>(
instance.release(), [](const void *payload) {
const auto *concretePayload = static_cast<const Type *>(payload);
delete concretePayload;
});
} else {
m_payload.payload = instance.release();
}

m_function = [](const void *payload, Args... args) -> return_type {
assert(payload != nullptr && "Payload is required, but not set");
const auto *concretePayload = static_cast<const Type *>(payload);
Expand All @@ -166,7 +221,8 @@ class Delegate<R(Args...)> {
/// @return Return value of the contained function
return_type operator()(Args... args) const {
assert(connected() && "Delegate is not connected");
return std::invoke(m_function, m_payload, std::forward<Args>(args)...);
return std::invoke(m_function, m_payload.ptr(),
std::forward<Args>(args)...);
}

/// Return whether this delegate is currently connected
Expand All @@ -179,14 +235,51 @@ class Delegate<R(Args...)> {

/// Disconnect this delegate, meaning it cannot be called anymore
void disconnect() {
m_payload = nullptr;
m_payload.clear();
m_function = nullptr;
}

private:
/// Stores the instance pointer
const void *m_payload{nullptr};
// Deleter that does not do anything
static void noopDeleter(const void *) {}

/// @cond

// Payload object without a deleter
struct NonOwningPayload {
void clear() { payload = nullptr; }

const void *ptr() const { return payload; }

const void *payload{nullptr};
};

// Payload object with a deleter
struct OwningPayload {
void clear() { payload.reset(); }

const void *ptr() const { return payload.get(); }

std::unique_ptr<const void, deleter_type> payload{nullptr, &noopDeleter};
};

/// Stores the instance pointer and maybe a deleter
std::conditional_t<kOwnership == DelegateType::NonOwning, NonOwningPayload,
OwningPayload>
m_payload;

/// @endcond

/// Stores the function pointer wrapping the compile time function pointer given in @c connect().
function_type m_function{nullptr};
};

template <typename>
class OwningDelegate;

/// Alias for an owning delegate
template <typename R, typename... Args>
class OwningDelegate<R(Args...)>
: public Delegate<R(Args...), DelegateType::Owning> {};

} // namespace Acts
2 changes: 1 addition & 1 deletion Examples/Algorithms/TrackFinding/src/SeedingAlgorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ ActsExamples::ProcessCode ActsExamples::SeedingAlgorithm::execute(
auto finder = Acts::SeedFinder<SimSpacePoint>(m_cfg.seedFinderConfig,
m_cfg.seedFinderOptions);

/// variable middle SP radial region of interest
// variable middle SP radial region of interest
const Acts::Range1D<float> rMiddleSPRange(
std::floor(rRangeSPExtent.min(Acts::binR) / 2) * 2 +
m_cfg.seedFinderConfig.deltaRMiddleMinSPRange,
Expand Down
2 changes: 2 additions & 0 deletions Examples/Python/python/acts/examples/reconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,8 @@ def addSeeding(
interactionPointCut=seedFinderConfigArg.interactionPointCut,
deltaZMax=seedFinderConfigArg.deltaZMax,
maxPtScattering=seedFinderConfigArg.maxPtScattering,
rRangeMiddleSP=seedFinderConfigArg.rRangeMiddleSP,
useVariableMiddleSPRange=seedFinderConfigArg.useVariableMiddleSPRange,
seedConfirmation=seedFinderConfigArg.seedConfirmation,
centralSeedConfirmationRange=seedFinderConfigArg.centralSeedConfirmationRange,
forwardSeedConfirmationRange=seedFinderConfigArg.forwardSeedConfirmationRange,
Expand Down
Loading

0 comments on commit 2f297d5

Please sign in to comment.