44import hashlib
55import os
66import shutil
7+ import subprocess
78import tarfile
89import tempfile
910from collections import namedtuple
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
3334def 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
182194def 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
193210def 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 ()} ".
216233This may take a while but only needs to be done once.
217234You can override the default location by calling `application_directory(path)` or `application_directory(temp=True)` to use a temporary directory.
218235The 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
244261def 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