Skip to content

Commit

Permalink
Merge pull request #483 from OpenGATE/consolidate5
Browse files Browse the repository at this point in the history
Consolidate 5
  • Loading branch information
tbaudier authored Oct 14, 2024
2 parents 0679fd2 + f48b2ff commit d21491a
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 69 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -397,10 +397,6 @@ jobs:
if [[ ${{ matrix.os }} == "ubuntu-latest" ]]; then
path=`opengate_library_path.py -p site_packages`
export LD_LIBRARY_PATH="${path}/opengate_core.libs":${LD_LIBRARY_PATH}
path=`opengate_library_path.py -p libG4processes`
export LD_PRELOAD=${path}:${LD_PRELOAD}
path=`opengate_library_path.py -p libG4geometry`
export LD_PRELOAD=${path}:${LD_PRELOAD}
fi
if [[ ${{ matrix.os }} == "windows-latest" ]]; then
path=`opengate_library_path.py -p site_packages`
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ See the [User Guide](https://opengate-python.readthedocs.io/en/latest/user_guide

### How to install (short version)

*Compatible with Python 3.9, 3.10, 3.11, 3.12. On Windows multithreading, Qt visualization and the "spawn new subprocess" are not (yet) available.*
*Compatible with Python 3.9, 3.10, 3.11, 3.12. On Windows multithreading and Qt visualization are not (yet) available.*

First, create an environment (not mandatory but highly advised)

Expand All @@ -23,7 +23,7 @@ source opengate_env/bin/activate
or you can use the conda environment.

```
conda create --name opengate_env python=3.9
conda create --name opengate_env python=3.12
conda activate opengate_env
```

Expand All @@ -33,6 +33,8 @@ pip install --upgrade pip
pip install --pre opengate
```

*Warning* while it is still beta, the `--pre` option is needed.

If you already installed the packages and want to upgrade to the latest version:

```
Expand All @@ -44,19 +46,24 @@ Once installed, you can run all tests:
opengate_tests
````

**WARNING** The first time you run this command, the geant4 data and the test data will be downloaded. If the download fails (on some systems), try to add the following command before running opengate_tests:
**WARNING (1)** The first time you run this command, the geant4 data and the test data will be downloaded. If the download fails (on some systems), try to add the following command before running opengate_tests:
````
export GIT_SSL_NO_VERIFY=1
````

All tests are in the folder [here](https://github.com/OpenGATE/opengate/tree/master/opengate/tests/src). The test data (binary files) are stored, for technical reasons, in this git: https://gitlab.in2p3.fr/opengamgate/gam_tests_data (which is stored as a git submodule).

**WARNING** Some tests (e.g. test034) needs [gaga-phsp](https://github.com/dsarrut/gaga-phsp) which needs [pytorch](https://pytorch.org/) that cannot really be automatically installed by the previous pip install (at least we don't know how to do). So, in order to run those tests, you will have to install both PyTorch and gaga-phsp first with
**WARNING (2)** Some tests (e.g. test034) needs [gaga-phsp](https://github.com/dsarrut/gaga-phsp) which needs [pytorch](https://pytorch.org/) that cannot really be automatically installed by the previous pip install (at least we don't know how to do). So, in order to run those tests, you will have to install both PyTorch and gaga-phsp first with
````
pip install torch
pip install gaga-phsp
````

**WARNING (3)** With some linux systems (not all), you may encounter an error similar to “cannot allocate memory in static TLS block”. In that case, you must add a specific path to the linker as follows:
````
export LD_PRELOAD=<path to libG4processes>:<path to libG4geometry>:${LD_PRELOAD}
````

The documentation is here: https://opengate-python.readthedocs.io/en/latest/user_guide.html

The test history can be visualized here: https://opengate.github.io/opengate_tests_results/
Expand Down
8 changes: 3 additions & 5 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ project(opengate_core)

set(CMAKE_CXX_STANDARD 17)

# Enable Position Independent Code for all targets (-fPIC)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# Need Geant4
find_package(Geant4 REQUIRED OPTIONAL_COMPONENTS qt)
include(${Geant4_USE_FILE})
Expand Down Expand Up @@ -103,13 +106,8 @@ if (WIN32)
endif ()
endif ()

# correct one on OSX
#target_link_libraries(opengate_core PRIVATE pybind11::module ${Geant4_LIBRARIES} Threads::Threads ${ITK_LIBRARIES})

# additional utilities
target_include_directories(opengate_core PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/external/)

#set(CMAKE_VERBOSE_MAKEFILE on)
target_link_libraries(opengate_core PRIVATE pybind11::module ${Geant4_LIBRARIES} Threads::Threads ${ITK_LIBRARIES} fmt::fmt-header-only)

# Do not not add ${PYTHON_LIBRARIES}) here (seg fault)
46 changes: 16 additions & 30 deletions core/opengate_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,37 +41,23 @@ def get_libG4_path(lib):
"site-packages" in pathCurrentFile
): # opengate_core is installed using wheel (for "pip install -e .", the paths are different)
reloadPython = False
if (
"LD_LIBRARY_PATH" not in os.environ
or os.path.join(get_site_packages_dir(), "opengate_core.libs")
not in os.environ["LD_LIBRARY_PATH"]
):
reloadPython = True
# if (
# "LD_LIBRARY_PATH" not in os.environ
# or os.path.join(get_site_packages_dir(), "opengate_core.libs")
# not in os.environ["LD_LIBRARY_PATH"]
# ):
# reloadPython = True

if (
"LD_PRELOAD" not in os.environ
or get_libG4_path("processes") not in os.environ["LD_PRELOAD"]
or get_libG4_path("geometry") not in os.environ["LD_PRELOAD"]
):
reloadPython = True

if reloadPython:
print(
"opengate_core is not detected. Be sure to execute these lines before to run python:"
)
print(
"export LD_LIBRARY_PATH="
+ os.path.join(get_site_packages_dir(), "opengate_core.libs")
+ ":${LD_LIBRARY_PATH}"
)
print(
"export LD_PRELOAD="
+ get_libG4_path("processes")
+ ":"
+ get_libG4_path("geometry")
+ ":${LD_PRELOAD}"
)
sys.exit(-1)
# if reloadPython:
# print(
# "opengate_core is not detected. Be sure to execute these lines before to run python:"
# )
# print(
# "export LD_LIBRARY_PATH="
# + os.path.join(get_site_packages_dir(), "opengate_core.libs")
# + ":${LD_LIBRARY_PATH}"
# )
# sys.exit(-1)
elif sys.platform == "win32":
print(os.path.dirname(pathCurrentFile))
os.add_dll_directory(os.path.dirname(pathCurrentFile))
Expand Down
48 changes: 25 additions & 23 deletions opengate/__init__.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
# This file handles the way opengate is imported.
import os
import sys

"""
import colored
import threading
print(
colored.stylize(
f"Importing opengate (thread " f"{threading.get_native_id()}) ... ",
colored.fore("dark_gray"),
),
end="",
flush=True,
)
print(colored.stylize("done", colored.fore("dark_gray")))
"""

# the following modules are imported respecting the package structure
# they will be available via
# `import opengate`
# `opengate.xxx.yyy`
# Modules that are mainly for internal use, such as runtiming.py or uisessions.py
# are not automatically imported. If a user needs them, s/he must import
# them specifically, e.g. `import opengate.uisessions`

def restart_with_glibc_tunables():
"""
Restart the current process with GLIBC_TUNABLES set.
"""
# tunables_value = "glibc.rtld.optional_static_tls=2048000"
tunables_value = "glibc.rtld.optional_static_tls=1500000"

# Check if the environment variable is already set correctly
if os.environ.get("GLIBC_TUNABLES") != tunables_value:
# Set the environment variable
new_env = os.environ.copy()
new_env["GLIBC_TUNABLES"] = tunables_value

# Restart the process with the new environment
os.execve(sys.executable, [sys.executable] + sys.argv, new_env)

# Exit the current process
sys.exit()


if sys.platform.startswith("linux"):
restart_with_glibc_tunables()

# subpackages
import opengate.sources

import opengate.geometry
import opengate.geometry.materials
import opengate.geometry.solids
import opengate.geometry.utility
import opengate.geometry.volumes

import opengate.actors
import opengate.contrib

Expand Down
85 changes: 85 additions & 0 deletions opengate/contrib/phantoms/jaszczak.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from opengate.contrib.phantoms.nemaiec import dump_bg_activity
from opengate.utility import g4_units


def add_phantom_material(simulation):
elems = ["H", "C", "O"]
w = [0.080538, 0.599848, 0.319614]
gcm3 = g4_units.g_cm3
simulation.volume_manager.material_database.add_material_weights(
"JASZCZAK_PMMA", elems, w, 1.19 * gcm3
)


def add_jaszczak_phantom(simulation, name="jaszczak", check_overlap=False):
# https://www.meditest.fr/documentation/4.pdf
# unit
add_phantom_material(simulation)

# check overlap only for debug
original_check_overlap_flag = simulation.check_volumes_overlap
simulation.check_volumes_overlap = check_overlap

# Outside structure
jaszczak, internal_cylinder = add_jaszczak_body(simulation, name)
jaszczak.material = "JASZCZAK_PMMA"

simulation.check_volumes_overlap = original_check_overlap_flag
return jaszczak, internal_cylinder


def add_jaszczak_body(sim, name):
cm = g4_units.cm
mm = g4_units.mm
deg = g4_units.deg
white = [1, 1, 1, 1]
thickness = 3.2 * mm

# main cylinder interior
external_cylinder = sim.add_volume("Tubs", name=f"{name}_cylinder")
external_cylinder.rmax = 21.6 * cm / 2.0 + thickness
external_cylinder.rmin = 0
external_cylinder.dz = 18.6 * cm / 2 + thickness * 2
external_cylinder.sphi = 0 * deg
external_cylinder.dphi = 360 * deg
external_cylinder.material = "JASZCZAK_PMMA"
external_cylinder.color = white

# main cylinder interior
internal_cylinder = sim.add_volume("Tubs", name=f"{name}_internal_cylinder")
internal_cylinder.mother = external_cylinder.name
internal_cylinder.rmax = 21.6 * cm / 2
internal_cylinder.rmin = 0
internal_cylinder.dz = 18.6 * cm / 2
internal_cylinder.sphi = 0 * deg
internal_cylinder.dphi = 360 * deg
internal_cylinder.material = "G4_AIR"

return external_cylinder, internal_cylinder


def add_background_source(
simulation, jaszczak_name, src_name, activity_bqml, verbose=False
):
# source
bg = simulation.add_source("GenericSource", f"{jaszczak_name}_{src_name}")
bg.mother = f"{jaszczak_name}_internal_cylinder"
v = simulation.volume_manager.volumes[bg.mother]
v_info = v.solid_info
# (1 cm3 = 1 mL)
"""
# no need to confine yet, nothing inside the cylinder -> should be done later
bg.position.type = "box"
bg.position.size = simulation.volume_manager.volumes[bg.mother].bounding_box_size
# this source is confined only within the mother volume, it does not include daughter volumes
# it is a tubs inside the box
bg.position.confine = bg.mother
"""
bg.particle = "e+"
bg.energy.type = "F18"
bg.activity = activity_bqml * v_info.cubic_volume

if verbose:
s = dump_bg_activity(simulation, jaszczak_name, src_name)
print(s)
return bg, v_info.cubic_volume
4 changes: 3 additions & 1 deletion opengate/contrib/phantoms/nemaiec.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def add_iec_phantom(
create_material(simulation)

# check overlap only for debug
original_check_overlap_flag = simulation.check_volumes_overlap
simulation.check_volumes_overlap = check_overlap

# Outside structure
Expand All @@ -64,6 +65,7 @@ def add_iec_phantom(
simulation, name, thickness_z, sphere_starting_angle, toggle_sphere_order
)

simulation.check_volumes_overlap = original_check_overlap_flag
return iec


Expand Down Expand Up @@ -544,7 +546,7 @@ def get_n_samples_from_ratio(n, ratio):
return n_samples


def compute_sphere_centers_and_volumes(sim, name):
def compute_sphere_centers_and_volumes_OLD_NEVER_CALLED(sim, name):
spheres_diam = [10, 13, 17, 22, 28, 37]
centers = []
volumes = []
Expand Down
4 changes: 2 additions & 2 deletions opengate/tests/src/test015_iec_phantom_4.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

# main options
sim.check_volumes_overlap = True
sim.random_seed = "auto" # 123456789
sim.random_seed = 87456321
sim.output_dir = paths.output
sim.progress_bar = True

Expand Down Expand Up @@ -74,7 +74,7 @@
axis="y",
tolerance=50,
ignore_value=0,
sum_tolerance=1.0,
sum_tolerance=1.1,
sad_profile_tolerance=3.0,
)

Expand Down

0 comments on commit d21491a

Please sign in to comment.