Skip to content
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
12 changes: 12 additions & 0 deletions core/opengate_core/g4_bindings/pyG4Material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ void init_G4Material(py::module &m) {
.def("AddElementByNumberOfAtoms", &G4Material::AddElementByNumberOfAtoms)
.def("AddElementByMassFraction", &G4Material::AddElementByMassFraction)

// Expose both native G4Material::AddElement overloads. The G4double
// overload interprets its second argument as a mass fraction, whereas
// the G4int overload interprets it as the number of atoms. Explicit
// overload selection is required because both methods have the same
// C++ name and must remain distinguishable to pybind11.
.def("AddElement",
py::overload_cast<G4Element *, G4double>(&G4Material::AddElement),
py::arg("element"), py::arg("fraction"))
.def("AddElement",
py::overload_cast<G4Element *, G4int>(&G4Material::AddElement),
py::arg("element"), py::arg("natoms"))

.def("GetElementFraction",
[](G4Material &ma, int i) -> double {
return ma.GetFractionVector()[i];
Expand Down
74 changes: 74 additions & 0 deletions core/opengate_core/g4_bindings/pyG4Tet.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// pyG4Tet.cpp (FIXED v2 for Geant4 11.1.x)
// - Avoids calling G4Tet::CheckDegeneracy (non-static in this Geant4)
// - Provides a simple geometric degeneracy test based on tetra volume
//
// Place this file into: opengate_core/g4_bindings/pyG4Tet.cpp

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

#include <array>
#include <cmath>
#include <memory>
#include <stdexcept>

#include "G4String.hh"
#include "G4Tet.hh"
#include "G4ThreeVector.hh"

namespace py = pybind11;

// Simple degeneracy check: |6V| = | dot( (b-a), cross((c-a),(d-a)) ) |
static bool tet_is_degenerate(const G4ThreeVector &a, const G4ThreeVector &b,
const G4ThreeVector &c, const G4ThreeVector &d,
double eps = 1e-12) {
const auto ab = b - a;
const auto ac = c - a;
const auto ad = d - a;
const double sixV = ab.dot(ac.cross(ad));
return std::abs(sixV) <= eps;
}

void init_G4Tet(py::module &m) {

py::class_<G4Tet, std::unique_ptr<G4Tet>>(m, "G4Tet")
// NOTE: Geant4 11.1.x constructor is:
// G4Tet(name, p1,p2,p3,p4, G4bool* degeneracyFlag = nullptr)
.def(
py::init([](const std::string &name, const std::array<double, 3> &p1,
const std::array<double, 3> &p2,
const std::array<double, 3> &p3,
const std::array<double, 3> &p4) {
G4bool deg = false;
auto *t = new G4Tet(G4String(name.c_str()),
G4ThreeVector(p1[0], p1[1], p1[2]),
G4ThreeVector(p2[0], p2[1], p2[2]),
G4ThreeVector(p3[0], p3[1], p3[2]),
G4ThreeVector(p4[0], p4[1], p4[2]), &deg);
// If Geant4 says degenerate, delete and throw
if (deg) {
delete t;
throw std::runtime_error(
"G4Tet: degenerate tetrahedron (Geant4 degeneracyFlag=true)");
}
return t;
}),
py::arg("name"), py::arg("p1"), py::arg("p2"), py::arg("p3"),
py::arg("p4"))
.def("GetCubicVolume", &G4Tet::GetCubicVolume)
.def("Inside", &G4Tet::Inside);

// Standalone helper: purely geometric degeneracy test
m.def(
"tet_is_degenerate",
[](const std::array<double, 3> &p1, const std::array<double, 3> &p2,
const std::array<double, 3> &p3, const std::array<double, 3> &p4,
double eps) {
return tet_is_degenerate(G4ThreeVector(p1[0], p1[1], p1[2]),
G4ThreeVector(p2[0], p2[1], p2[2]),
G4ThreeVector(p3[0], p3[1], p3[2]),
G4ThreeVector(p4[0], p4[1], p4[2]), eps);
},
py::arg("p1"), py::arg("p2"), py::arg("p3"), py::arg("p4"),
py::arg("eps") = 1e-12);
}
26 changes: 26 additions & 0 deletions core/opengate_core/opengate_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,11 @@ void init_G4TriangularFacet(py::module &m);

void init_G4QuadrangularFacet(py::module &m);

// Added binding declaration: expose Geant4's single tetrahedron solid
// (G4Tet) to Python. This is distinct from the OpenGATE tetrahedral mesh
// builder declared below.
void init_G4Tet(py::module &);

// geometry/volume
void init_G4PVPlacement(py::module &);

Expand Down Expand Up @@ -400,6 +405,14 @@ void init_GateBooleanFilter(py::module &);

void init_GateAttributeComparisonFilter(py::module &);

// Added filter binding declaration: select steps by the copy number of their
// pre-step touchable.
void init_GateCopyNumberFilter(py::module &);

// Added OpenGATE geometry binding declaration: build a parameterised
// tetrahedral mesh from TetGen .node and .ele files.
void init_GateTetrahedralMesh(py::module &);

// Gate actors
void init_GateDoseActor(py::module &m);

Expand Down Expand Up @@ -714,6 +727,10 @@ PYBIND11_MODULE(opengate_core, m) {
init_G4TriangularFacet(m);
init_G4QuadrangularFacet(m);

// Added module registration: make g4.G4Tet and its helper binding available
// after importing opengate_core.
init_G4Tet(m);

init_G4PVPlacement(m);
init_G4TouchableHistory(m);
init_G4NavigationHistory(m);
Expand Down Expand Up @@ -782,6 +799,15 @@ PYBIND11_MODULE(opengate_core, m) {
init_GateTrackCreatorProcessFilter(m);
init_GateBooleanFilter(m);
init_GateAttributeComparisonFilter(m);

// Added module registration: expose g4.GateCopyNumberFilter to the Python
// CopyNumberFilter wrapper in opengate/actors/filters.py.
init_GateCopyNumberFilter(m);

// Added module registration: expose the TetGen-based parameterised mesh
// builders implemented in opengate_lib.
init_GateTetrahedralMesh(m);

init_itk_image(m);
init_GateImageNestedParameterisation(m);
init_GateRepeatParameterisation(m);
Expand Down
Loading
Loading