Skip to content

Commit e4bf9b9

Browse files
ci: Use geant4 conda in CI on more platforms (#79)
* use geant4 conda in CI on more platforms * attempt to fix CI * style: pre-commit fixes * check datasets * update datasets to make conda work * renaming of application data dir * style: pre-commit fixes * fix bad getter for geant4 data path * style: pre-commit fixes * fix bad getter for geant4 data path * fix bad getter for geant4 data path * style: pre-commit fixes * install datasets * style: pre-commit fixes * address pip version warning * fix bad command --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 5744708 commit e4bf9b9

File tree

3 files changed

+80
-33
lines changed

3 files changed

+80
-33
lines changed

.github/workflows/build-test.yaml

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@ env:
2020

2121
jobs:
2222
install-with-geant4-from-conda:
23-
name: Install with conda
24-
runs-on: ubuntu-latest
23+
name: Install dependencies with conda
24+
runs-on: ${{ matrix.os }}
25+
timeout-minutes: 60
26+
strategy:
27+
fail-fast: false
28+
matrix:
29+
os: [ubuntu-latest, macos-latest] # Geant4 is not available on conda for windows TODO: update this when it is
2530
defaults:
2631
run:
2732
shell: bash -l {0}
@@ -32,29 +37,50 @@ jobs:
3237
auto-update-conda: true
3338
python-version: 3.12
3439

35-
- name: Install Geant4 using conda
40+
- name: Install Geant4 and cmake using conda
41+
run: |
42+
conda install -c conda-forge cmake ninja geant4=${{ env.GEANT4_VERSION }}
43+
44+
- name: Install additional dependencies (Ubuntu)
45+
if: matrix.os == 'ubuntu-latest'
3646
run: |
37-
conda install -c conda-forge geant4=11.2.2 cmake ninja gxx_linux-64
47+
conda install -c conda-forge gxx_linux-64
48+
49+
- name: Install additional dependencies (MacOS)
50+
if: matrix.os == 'macos-latest'
51+
run: |
52+
conda install -c conda-forge clang_osx-64
3853
3954
- name: Print versions
4055
run: |
4156
conda --version
57+
cmake --version
58+
59+
echo "Geant4: ${{ env.GEANT4_VERSION }}"
60+
4261
geant4-config --version
62+
geant4-config --check-datasets
63+
64+
- name: Install datasets if missing # Shouldn't they be available after the conda install?
65+
run: |
66+
geant4-config --install-datasets
67+
geant4-config --check-datasets
4368
4469
- name: Checkout
4570
uses: actions/checkout@v4
4671

4772
- name: pip install the package from source
4873
run: |
49-
python -m pip install .
74+
python -m pip install .[test]
5075
python -c "import geant4_python_application; print(geant4_python_application.version)"
5176
52-
- name: Run example notebooks
77+
- name: Check datasets are accessible # Datasets should have been installed by the conda package, and should be accessible
5378
run: |
54-
python -m pip install jupyter nbconvert matplotlib
55-
for notebook in $(find examples -name '*.ipynb'); do
56-
jupyter nbconvert --to notebook --execute --inplace $notebook
57-
done
79+
python -c "import geant4_python_application as g4; g4.files.datasets.check_datasets(throw=True)"
80+
81+
- name: Run tests
82+
run: |
83+
python -m pytest -vv --reruns 3 --reruns-delay 30 --only-rerun "(?i)http|timeout|connection|socket|resolve"
5884
5985
build-geant4:
6086
name: Build Geant4 on ${{ matrix.os }}
@@ -200,6 +226,7 @@ jobs:
200226

201227
- name: pip install the package
202228
run: |
229+
python -m pip install --upgrade pip
203230
python -m pip install .[test]
204231
git tag
205232
python -c "import geant4_python_application; print(geant4_python_application.version)"

src/geant4_python_application/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
from geant4_python_application._version import version, version_tuple
99
from geant4_python_application.application import Application
1010
from geant4_python_application.detector import Detector
11-
from geant4_python_application.files.datasets import data_directory, install_datasets
11+
from geant4_python_application.files.datasets import (
12+
application_data_directory as data_directory,
13+
)
14+
from geant4_python_application.files.datasets import install_datasets
1215
from geant4_python_application.files.directories import application_directory
1316
from geant4_python_application.gdml import basic_gdml
1417

src/geant4_python_application/files/datasets.py

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import hashlib
55
import os
66
import shutil
7+
import subprocess
78
import tarfile
89
import tempfile
910
from collections import namedtuple
@@ -20,7 +21,7 @@
2021
# It is discouraged to use the python package directory to store data
2122
# data_dir = os.path.join(os.path.dirname(__file__), "geant4/data")
2223
# another idea is to use 'platformdirs' to store data in a platform-specific location
23-
def data_directory() -> str:
24+
def application_data_directory() -> str:
2425
return os.path.join(
2526
geant4_python_application.application_directory(),
2627
geant4_python_application.__name__,
@@ -31,7 +32,21 @@ def data_directory() -> str:
3132

3233

3334
def geant4_data_directory() -> str:
34-
return os.environ["GEANT4_DATA_DIR"]
35+
try:
36+
# capture stdout, save into a str
37+
geant4_prefix = subprocess.run(
38+
["geant4-config", "--prefix"], capture_output=True, check=False
39+
)
40+
geant4_data_path = os.path.join(
41+
geant4_prefix.stdout.decode().strip(), "share", "Geant4", "data"
42+
)
43+
if not os.path.exists(geant4_data_path):
44+
return ""
45+
46+
return geant4_data_path
47+
48+
except FileNotFoundError:
49+
return ""
3550

3651

3752
# the datasets versions should be updated with each Geant4 version (remember to update the checksum too!)
@@ -164,14 +179,11 @@ def _download_extract_dataset(dataset: Dataset, pbar: tqdm):
164179

165180
f.seek(0)
166181
with tarfile.open(fileobj=f, mode="r:gz") as tar:
167-
tar.extractall(data_directory())
182+
tar.extractall(application_data_directory())
168183

169184

170-
def missing_datasets(directory: str | None = None) -> list[Dataset]:
171-
if directory is None:
172-
directory = data_directory()
185+
def missing_datasets(directory: str) -> list[Dataset]:
173186
datasets_to_download = []
174-
175187
for dataset in datasets:
176188
path = os.path.join(directory, dataset.name + dataset.version)
177189
if not os.path.exists(path):
@@ -180,7 +192,12 @@ def missing_datasets(directory: str | None = None) -> list[Dataset]:
180192

181193

182194
def check_datasets(throw: bool = False) -> bool:
183-
datasets_to_download = missing_datasets()
195+
datasets_to_download = missing_datasets(directory=application_data_directory())
196+
if datasets_to_download:
197+
# if not found in the application data directory, try to find them in the Geant4 installation data directory
198+
if geant4_data_directory():
199+
datasets_to_download = missing_datasets(directory=geant4_data_directory())
200+
184201
if datasets_to_download:
185202
if throw:
186203
raise RuntimeError(
@@ -192,27 +209,27 @@ def check_datasets(throw: bool = False) -> bool:
192209

193210
def install_datasets(show_progress: bool = True):
194211
# first try to see if the datasets are installed in the application directory
195-
datasets_to_download = missing_datasets()
212+
datasets_to_download = missing_datasets(directory=application_data_directory())
196213
if not datasets_to_download:
197214
# datasets are installed in application directory
198-
os.environ["GEANT4_DATA_DIR"] = data_directory()
215+
os.environ["GEANT4_DATA_DIR"] = application_data_directory()
199216
return
200217

201-
# check if the datasets are present in the corresponding Geant4 directory
202-
if "GEANT4_DATA_DIR" in os.environ and not bool(
203-
missing_datasets(os.environ["GEANT4_DATA_DIR"])
204-
):
205-
# return
206-
...
218+
if geant4_data_directory():
219+
datasets_to_download = missing_datasets(directory=geant4_data_directory())
220+
if not datasets_to_download:
221+
# datasets are installed in Geant4 data directory, no need to install them in the application data directory
222+
os.environ["GEANT4_DATA_DIR"] = geant4_data_directory()
223+
return
207224

208-
# download and extract the datasets
209-
os.environ["GEANT4_DATA_DIR"] = data_directory()
225+
# download and extract the datasets to the application data directory
226+
os.environ["GEANT4_DATA_DIR"] = application_data_directory()
210227

211-
os.makedirs(data_directory(), exist_ok=True)
228+
os.makedirs(application_data_directory(), exist_ok=True)
212229
if show_progress:
213230
print(
214231
f"""
215-
Geant4 datasets will be installed to "{data_directory()}".
232+
Geant4 datasets will be installed to "{application_data_directory()}".
216233
This may take a while but only needs to be done once.
217234
You can override the default location by calling `application_directory(path)` or `application_directory(temp=True)` to use a temporary directory.
218235
The following Geant4 datasets will be installed: {", ".join([f"{dataset.name}@v{dataset.version}" for dataset in datasets_to_download])}"""
@@ -236,13 +253,13 @@ def install_datasets(show_progress: bool = True):
236253

237254
if show_progress:
238255
total_size_gb = sum(
239-
fp.stat().st_size for fp in Path(data_directory()).rglob("*")
256+
fp.stat().st_size for fp in Path(application_data_directory()).rglob("*")
240257
) / (1024**3)
241258
print(f"Geant4 datasets size on disk after extraction: {total_size_gb:.2f}GB")
242259

243260

244261
def uninstall_datasets():
245-
dir_to_remove = os.path.dirname(data_directory())
262+
dir_to_remove = os.path.dirname(application_data_directory())
246263
package_dir = os.path.dirname(__file__)
247264

248265
if not os.path.relpath(package_dir, dir_to_remove).startswith(".."):

0 commit comments

Comments
 (0)