Skip to content

Commit

Permalink
feat: Add covfie magnetic field plugin (#3479)
Browse files Browse the repository at this point in the history
This commit adds a new Acts plugin that adds support for magnetic fields implemented using the covfie library.

This commit is based on #3117.

Closes #3117.

Depends on #3478.

Virtually all credit goes to @fredevb.

Co-authored-by: Fred <[email protected]>
  • Loading branch information
stephenswat and fredevb authored Aug 29, 2024
1 parent 3b32e5d commit 809b378
Show file tree
Hide file tree
Showing 15 changed files with 653 additions and 2 deletions.
3 changes: 3 additions & 0 deletions Examples/Python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,11 @@ endif()
if(ACTS_BUILD_PLUGIN_TRACCC)
target_link_libraries(ActsPythonBindings PUBLIC ActsPluginDetray)
target_sources(ActsPythonBindings PRIVATE src/Detray.cpp)
target_link_libraries(ActsPythonBindings PUBLIC ActsPluginCovfie)
target_sources(ActsPythonBindings PRIVATE src/Covfie.cpp)
else()
target_sources(ActsPythonBindings PRIVATE src/DetrayStub.cpp)
target_sources(ActsPythonBindings PRIVATE src/CovfieStub.cpp)
endif()

if(ACTS_BUILD_PLUGIN_ACTSVG)
Expand Down
55 changes: 55 additions & 0 deletions Examples/Python/src/Covfie.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// This file is part of the Acts project.
//
// Copyright (C) 2021 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 http://mozilla.org/MPL/2.0/.

#include "Acts/Plugins/Covfie/FieldConversion.hpp"
#include "Acts/Plugins/Python/Utilities.hpp"

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace py = pybind11;
using namespace pybind11::literals;

namespace Acts::Python {

namespace {
template <typename field_t>
void declareCovfieField(py::module& m, const std::string& fieldName) {
using view_t = typename field_t::view_t;
m.def("toView",
[](const field_t& field) { return typename field_t::view_t(field); });
py::class_<field_t, std::shared_ptr<field_t>>(m, fieldName.c_str());
py::class_<view_t, std::shared_ptr<view_t>>(
m, (fieldName + std::string("View")).c_str())
.def("at", &view_t::template at<float, float, float>);
}
} // namespace

void addCovfie(Context& ctx) {
auto main = ctx.get("main");
auto m = main.def_submodule("covfie", "Submodule for covfie conversion");

declareCovfieField<Acts::CovfiePlugin::ConstantField>(m,
"CovfieConstantField");
declareCovfieField<Acts::CovfiePlugin::InterpolatedField>(
m, "CovfieAffineLinearStridedField");

m.def("makeCovfieField",
py::overload_cast<const Acts::InterpolatedMagneticField&>(
&Acts::CovfiePlugin::covfieField));
m.def("makeCovfieField", py::overload_cast<const Acts::ConstantBField&>(
&Acts::CovfiePlugin::covfieField));
m.def("makeCovfieField",
py::overload_cast<const Acts::MagneticFieldProvider&,
Acts::MagneticFieldProvider::Cache&,
const std::array<std::size_t, 3>&,
const Acts::Vector3&, const Acts::Vector3&>(
&Acts::CovfiePlugin::covfieField));
}

} // namespace Acts::Python
13 changes: 13 additions & 0 deletions Examples/Python/src/CovfieStub.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This file is part of the Acts project.
//
// Copyright (C) 2021 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 http://mozilla.org/MPL/2.0/.

#include "Acts/Plugins/Python/Utilities.hpp"

namespace Acts::Python {
void addCovfie(Context& /* ctx */) {}
} // namespace Acts::Python
2 changes: 2 additions & 0 deletions Examples/Python/src/ModuleEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ void addSvg(Context& ctx);
void addObj(Context& ctx);
void addOnnx(Context& ctx);
void addOnnxNeuralCalibrator(Context& ctx);
void addCovfie(Context& ctx);

} // namespace Acts::Python

Expand Down Expand Up @@ -148,4 +149,5 @@ PYBIND11_MODULE(ActsPythonBindings, m) {
addSvg(ctx);
addOnnx(ctx);
addOnnxNeuralCalibrator(ctx);
addCovfie(ctx);
}
7 changes: 7 additions & 0 deletions Examples/Python/tests/helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@
except ImportError:
onnxEnabled = False

try:
from acts import covfie

covfieEnabled = True
except ImportError:
covfieEnabled = False


try:
import acts.examples
Expand Down
63 changes: 63 additions & 0 deletions Examples/Python/tests/test_covfie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import pathlib, acts, acts.examples
import pytest

from helpers import covfieEnabled


@pytest.mark.skipif(not covfieEnabled, reason="Covfie plugin not available")
def test_constant_field_conversion():
from acts import covfie

v = acts.Vector3(1, 2, 3)
af = acts.ConstantBField(v)
cf = covfie.makeCovfieField(af)
view = covfie.toView(cf)
points = [(0, 0, 1), (1, 1, 1), (1, 0, 2)]
for x, y, z in points:
assert view.at(x, y, z) == [1, 2, 3]


@pytest.mark.skipif(not covfieEnabled, reason="Covfie plugin not available")
def test_root_field_conversion():
from acts import covfie

current_file_path = pathlib.Path(__file__).resolve().parent
p = (
current_file_path.parent.parent.parent
/ "thirdparty"
/ "OpenDataDetector"
/ "data"
/ "odd-bfield.root"
)

af = acts.examples.MagneticFieldMapXyz(str(p))
bc = acts.MagneticFieldContext()
fc = af.makeCache(bc)

cf = covfie.makeCovfieField(af)
view = covfie.toView(cf)
points = [
(9300.0, 4700.0, 11200.0),
(9999.0, 9999.0, 14300.0),
(-2900.0, -4700.0, 5200.0),
(-2900.0, -4800.0, 9100.0),
(-2900.0, -5200.0, -8800.0),
(-4400.0, 4800.0, -12700.0),
(-6600.0, 1900.0, 7700.0),
(-9700.0, -900.0, 12700.0),
(-9999.0, -9999.0, -13000.0),
(9999.0, 0, 14900.0),
]

error_margin_half_width = 0.0001
for x, y, z in points:
val = af.getField(acts.Vector3(x, y, z), fc)
Bx1, By1, Bz1 = val[0], val[1], val[2]

Bx2, By2, Bz2 = tuple(view.at(x, y, z))

assert (
abs(Bx1 - Bx2) < error_margin_half_width
and abs(By1 - By2) < error_margin_half_width
and abs(Bz1 - Bz2) < error_margin_half_width
)
1 change: 1 addition & 0 deletions Plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_component_if(Legacy PluginLegacy ACTS_BUILD_PLUGIN_LEGACY)
add_component_if(Onnx PluginOnnx ACTS_BUILD_PLUGIN_ONNX)
add_component_if(ExaTrkX PluginExaTrkX ACTS_BUILD_PLUGIN_EXATRKX)
add_component_if(Detray PluginDetray ACTS_BUILD_PLUGIN_TRACCC)
add_component_if(Covfie PluginCovfie ACTS_BUILD_PLUGIN_TRACCC)

# dependent plugins. depend either on a independent plugins or on one another
add_component_if(TGeo PluginTGeo ACTS_BUILD_PLUGIN_TGEO)
Expand Down
16 changes: 16 additions & 0 deletions Plugins/Covfie/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
add_library(ActsPluginCovfie SHARED src/FieldConversion.cpp)

target_include_directories(
ActsPluginCovfie
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_link_libraries(ActsPluginCovfie PUBLIC ActsCore covfie::core)

install(
TARGETS ActsPluginCovfie
EXPORT ActsPluginCovfieTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(DIRECTORY include/Acts DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
64 changes: 64 additions & 0 deletions Plugins/Covfie/include/Acts/Plugins/Covfie/FieldConversion.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// This file is part of the Acts project.
//
// Copyright (C) 2023 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 http://mozilla.org/MPL/2.0/.

#pragma once

#include <covfie/core/algebra/affine.hpp>
#include <covfie/core/backend/primitive/array.hpp>
#include <covfie/core/backend/primitive/constant.hpp>
#include <covfie/core/backend/transformer/affine.hpp>
#include <covfie/core/backend/transformer/clamp.hpp>
#include <covfie/core/backend/transformer/linear.hpp>
#include <covfie/core/backend/transformer/strided.hpp>
#include <covfie/core/field.hpp>
#include <covfie/core/field_view.hpp>
#include <covfie/core/parameter_pack.hpp>

// acts includes
#include "Acts/MagneticField/BFieldMapUtils.hpp"
#include "Acts/MagneticField/ConstantBField.hpp"
#include "Acts/MagneticField/MagneticFieldProvider.hpp"

namespace Acts::CovfiePlugin {

using BuilderBackend =
covfie::backend::strided<covfie::vector::size3,
covfie::backend::array<covfie::vector::float3>>;

using InterpolatedField = covfie::field<covfie::backend::clamp<
covfie::backend::affine<covfie::backend::linear<BuilderBackend>>>>;

using ConstantField = covfie::field<
covfie::backend::constant<covfie::vector::float3, covfie::vector::float3>>;

/// @brief Creates a covfie field from an interpolated magnetic field.
/// @param magneticField The acts interpolated magnetic field.
/// @return An affine linear strided covfie field.
InterpolatedField covfieField(
const Acts::InterpolatedMagneticField& magneticField);

/// @brief Creates a covfie field from a constant B field.
/// @param magneticField The acts constant magnetic field.
/// @return A constant covfie field.
ConstantField covfieField(const Acts::ConstantBField& magneticField);

/// @brief Creates a covfie field from a magnetic field provider by sampling it.
/// The field must be defined within min (inclusive) and max (inclusive).
/// @param magneticField The acts magnetic field provider.
/// @param cache The acts cache.
/// @param nPoints 3D array of containing the number of bins for each axis.
/// @param min (min_x, min_y, min_z)
/// @param max (max_x, max_y, max_z)
/// @return An affine linear strided covfie field.
InterpolatedField covfieField(const Acts::MagneticFieldProvider& magneticField,
Acts::MagneticFieldProvider::Cache& cache,
const std::array<std::size_t, 3>& nPoints,
const Acts::Vector3& min,
const Acts::Vector3& max);

} // namespace Acts::CovfiePlugin
Loading

0 comments on commit 809b378

Please sign in to comment.