main.utils
1import os 2import shutil 3import subprocess 4import platform 5import sys 6from PyQt6.QtCore import QStandardPaths, QCoreApplication 7from pathlib import Path 8 9 10def get_bin_path(name): 11 """ 12 Locate the executable path for a given binary name across different environments. 13 14 This function attempts to find the full path of an executable following these steps: 15 1. Check if running from a PyInstaller bundle (using `sys._MEIPASS`). 16 2. Check if the binary exists in the same directory as the current script. 17 3. Search the system PATH using `shutil.which()`. 18 19 Args: 20 name (str): The base name of the executable (without extension). 21 22 Returns: 23 str: The absolute path to the executable. 24 25 Raises: 26 FileNotFoundError: If the executable cannot be found. 27 """ 28 if not name or not str(name).strip(): 29 raise ValueError(QCoreApplication.translate("Utils", "Tool name not provided")) 30 31 exe_name = f"{name}.exe" if platform.system() == "Windows" else name 32 33 # Case 1: Running from a PyInstaller bundle 34 if hasattr(sys, "_MEIPASS"): 35 candidate = os.path.join(sys._MEIPASS, name, exe_name) 36 if os.path.exists(candidate): 37 return candidate 38 39 # Case 2: Located next to the script or executable 40 candidate = os.path.join(os.path.dirname(__file__), name, exe_name) 41 if os.path.exists(candidate): 42 return candidate 43 44 # Case 3: Found in the system PATH 45 path = shutil.which(exe_name) 46 if path: 47 return path 48 49 raise FileNotFoundError(QCoreApplication.translate("Utils", "Could not find executable: {exe_name}").format(exe_name=exe_name)) 50 51 52def get_app_dir(): 53 """ 54 Get the writable directory used to store user-specific application data. 55 56 On all operating systems, this directory is located under the user's home folder 57 (e.g., `~/GliAAns-UI` on Linux and macOS, or `C:\\Users\\<User>\\GliAAns-UI` on Windows). 58 59 Returns: 60 pathlib.Path: The absolute path to the application data directory. 61 """ 62 base = Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.HomeLocation)) / "GliAAns-UI" 63 64 try: 65 base.mkdir(parents=True, exist_ok=True) 66 except PermissionError: 67 raise 68 except OSError as e: 69 # Errno 30 = read-only filesystem, 13 = forbidden 70 if getattr(e, "errno", None) in (13, 30): 71 raise PermissionError(QCoreApplication.translate("Utils", "Error while creating the app working directory")) from e 72 raise 73 74 return base 75 76 77def resource_path(relative_path): 78 """ 79 Resolve the absolute path to a resource file. 80 81 Works in both development environments and PyInstaller-built executables. 82 83 Args: 84 relative_path (str): The relative path to the resource file. 85 86 Returns: 87 str: The absolute path to the resource file. 88 """ 89 if hasattr(sys, "_MEIPASS"): 90 return os.path.join(sys._MEIPASS, relative_path) 91 return os.path.join(os.path.dirname(__file__), relative_path) 92 93 94def get_shell_path(): 95 """ 96 Retrieve the system PATH from the user's login shell environment. 97 98 This is necessary because on Unix-based systems (macOS, Linux), GUI applications 99 do not always inherit the user's shell environment (especially when launched from 100 the desktop or a shortcut). 101 102 Behavior by platform: 103 - **macOS:** Uses the default login shell (`zsh`) to read PATH. 104 - **Linux:** Reads from the user's current shell (usually `bash`). 105 - **Windows:** Returns the PATH from the current environment. 106 107 Returns: 108 str: The PATH environment variable as a string. 109 """ 110 system = platform.system() 111 112 try: 113 if system == "Darwin": # macOS 114 result = subprocess.run( 115 ["/bin/zsh", "-l", "-c", "echo $PATH"], 116 capture_output=True, 117 text=True, 118 check=True 119 ) 120 return result.stdout.strip() 121 122 elif system == "Linux": # Linux 123 shell = os.environ.get("SHELL", "/bin/bash") 124 result = subprocess.run( 125 [shell, "-l", "-c", "echo $PATH"], 126 capture_output=True, 127 text=True, 128 check=True 129 ) 130 return result.stdout.strip() 131 132 elif system == "Windows": # Windows 133 return os.environ.get("PATH", "") 134 135 # Fallback for unknown platforms 136 return os.environ.get("PATH", "") 137 138 except Exception as e: 139 print(f"Error while retrieving PATH from shell: {e}") 140 return os.environ.get("PATH", "") 141 142 143def setup_fsl_env(): 144 """ 145 Load environment variables for FSL (FMRIB Software Library). 146 147 This function runs a shell command to source the FSL configuration script 148 (`fsl.sh`) and extract the environment variables `FSLDIR` and `FSLOUTPUTTYPE`. 149 150 Returns: 151 tuple[str, str]: A tuple containing: 152 - `FSLDIR`: The root installation directory of FSL. 153 - `FSLOUTPUTTYPE`: The default FSL output format (e.g., NIFTI_GZ). 154 155 Raises: 156 RuntimeError: If FSLDIR or FSLOUTPUTTYPE cannot be retrieved. 157 """ 158 result = subprocess.run( 159 ["/bin/zsh", "-l", "-c", "source $FSLDIR/etc/fslconf/fsl.sh && echo $FSLDIR && echo $FSLOUTPUTTYPE"], 160 capture_output=True, 161 text=True, 162 check=True 163 ) 164 165 lines = result.stdout.strip().splitlines() 166 if len(lines) < 2: 167 raise RuntimeError("Could not read FSLDIR and FSLOUTPUTTYPE") 168 169 fsldir, fsloutputtype = lines[0], lines[1] 170 return fsldir, fsloutputtype 171 172def get_dl_python_executable(): 173 """Returns the path of the Python in venv deep learning.""" 174 base_dir = Path(sys.executable).parent 175 176 python_path = base_dir / ".venv-dl" / "bin" / "python" 177 178 if not python_path.exists(): 179 raise FileNotFoundError(f"Python DL environment not found: {python_path}") 180 181 return str(python_path) 182 183def get_script_path(script_relative_path): 184 """Returns the absolute path of a deep learning script.""" 185 base_dir = Path(sys.executable).parent 186 script_path = base_dir / script_relative_path 187 return str(script_path)
11def get_bin_path(name): 12 """ 13 Locate the executable path for a given binary name across different environments. 14 15 This function attempts to find the full path of an executable following these steps: 16 1. Check if running from a PyInstaller bundle (using `sys._MEIPASS`). 17 2. Check if the binary exists in the same directory as the current script. 18 3. Search the system PATH using `shutil.which()`. 19 20 Args: 21 name (str): The base name of the executable (without extension). 22 23 Returns: 24 str: The absolute path to the executable. 25 26 Raises: 27 FileNotFoundError: If the executable cannot be found. 28 """ 29 if not name or not str(name).strip(): 30 raise ValueError(QCoreApplication.translate("Utils", "Tool name not provided")) 31 32 exe_name = f"{name}.exe" if platform.system() == "Windows" else name 33 34 # Case 1: Running from a PyInstaller bundle 35 if hasattr(sys, "_MEIPASS"): 36 candidate = os.path.join(sys._MEIPASS, name, exe_name) 37 if os.path.exists(candidate): 38 return candidate 39 40 # Case 2: Located next to the script or executable 41 candidate = os.path.join(os.path.dirname(__file__), name, exe_name) 42 if os.path.exists(candidate): 43 return candidate 44 45 # Case 3: Found in the system PATH 46 path = shutil.which(exe_name) 47 if path: 48 return path 49 50 raise FileNotFoundError(QCoreApplication.translate("Utils", "Could not find executable: {exe_name}").format(exe_name=exe_name))
Locate the executable path for a given binary name across different environments.
This function attempts to find the full path of an executable following these steps:
- Check if running from a PyInstaller bundle (using
sys._MEIPASS). - Check if the binary exists in the same directory as the current script.
- Search the system PATH using
shutil.which().
Args: name (str): The base name of the executable (without extension).
Returns: str: The absolute path to the executable.
Raises: FileNotFoundError: If the executable cannot be found.
53def get_app_dir(): 54 """ 55 Get the writable directory used to store user-specific application data. 56 57 On all operating systems, this directory is located under the user's home folder 58 (e.g., `~/GliAAns-UI` on Linux and macOS, or `C:\\Users\\<User>\\GliAAns-UI` on Windows). 59 60 Returns: 61 pathlib.Path: The absolute path to the application data directory. 62 """ 63 base = Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.HomeLocation)) / "GliAAns-UI" 64 65 try: 66 base.mkdir(parents=True, exist_ok=True) 67 except PermissionError: 68 raise 69 except OSError as e: 70 # Errno 30 = read-only filesystem, 13 = forbidden 71 if getattr(e, "errno", None) in (13, 30): 72 raise PermissionError(QCoreApplication.translate("Utils", "Error while creating the app working directory")) from e 73 raise 74 75 return base
Get the writable directory used to store user-specific application data.
On all operating systems, this directory is located under the user's home folder
(e.g., ~/GliAAns-UI on Linux and macOS, or C:\Users\<User>\GliAAns-UI on Windows).
Returns: pathlib.Path: The absolute path to the application data directory.
78def resource_path(relative_path): 79 """ 80 Resolve the absolute path to a resource file. 81 82 Works in both development environments and PyInstaller-built executables. 83 84 Args: 85 relative_path (str): The relative path to the resource file. 86 87 Returns: 88 str: The absolute path to the resource file. 89 """ 90 if hasattr(sys, "_MEIPASS"): 91 return os.path.join(sys._MEIPASS, relative_path) 92 return os.path.join(os.path.dirname(__file__), relative_path)
Resolve the absolute path to a resource file.
Works in both development environments and PyInstaller-built executables.
Args: relative_path (str): The relative path to the resource file.
Returns: str: The absolute path to the resource file.
95def get_shell_path(): 96 """ 97 Retrieve the system PATH from the user's login shell environment. 98 99 This is necessary because on Unix-based systems (macOS, Linux), GUI applications 100 do not always inherit the user's shell environment (especially when launched from 101 the desktop or a shortcut). 102 103 Behavior by platform: 104 - **macOS:** Uses the default login shell (`zsh`) to read PATH. 105 - **Linux:** Reads from the user's current shell (usually `bash`). 106 - **Windows:** Returns the PATH from the current environment. 107 108 Returns: 109 str: The PATH environment variable as a string. 110 """ 111 system = platform.system() 112 113 try: 114 if system == "Darwin": # macOS 115 result = subprocess.run( 116 ["/bin/zsh", "-l", "-c", "echo $PATH"], 117 capture_output=True, 118 text=True, 119 check=True 120 ) 121 return result.stdout.strip() 122 123 elif system == "Linux": # Linux 124 shell = os.environ.get("SHELL", "/bin/bash") 125 result = subprocess.run( 126 [shell, "-l", "-c", "echo $PATH"], 127 capture_output=True, 128 text=True, 129 check=True 130 ) 131 return result.stdout.strip() 132 133 elif system == "Windows": # Windows 134 return os.environ.get("PATH", "") 135 136 # Fallback for unknown platforms 137 return os.environ.get("PATH", "") 138 139 except Exception as e: 140 print(f"Error while retrieving PATH from shell: {e}") 141 return os.environ.get("PATH", "")
Retrieve the system PATH from the user's login shell environment.
This is necessary because on Unix-based systems (macOS, Linux), GUI applications do not always inherit the user's shell environment (especially when launched from the desktop or a shortcut).
Behavior by platform:
- macOS: Uses the default login shell (
zsh) to read PATH. - Linux: Reads from the user's current shell (usually
bash). - Windows: Returns the PATH from the current environment.
Returns: str: The PATH environment variable as a string.
144def setup_fsl_env(): 145 """ 146 Load environment variables for FSL (FMRIB Software Library). 147 148 This function runs a shell command to source the FSL configuration script 149 (`fsl.sh`) and extract the environment variables `FSLDIR` and `FSLOUTPUTTYPE`. 150 151 Returns: 152 tuple[str, str]: A tuple containing: 153 - `FSLDIR`: The root installation directory of FSL. 154 - `FSLOUTPUTTYPE`: The default FSL output format (e.g., NIFTI_GZ). 155 156 Raises: 157 RuntimeError: If FSLDIR or FSLOUTPUTTYPE cannot be retrieved. 158 """ 159 result = subprocess.run( 160 ["/bin/zsh", "-l", "-c", "source $FSLDIR/etc/fslconf/fsl.sh && echo $FSLDIR && echo $FSLOUTPUTTYPE"], 161 capture_output=True, 162 text=True, 163 check=True 164 ) 165 166 lines = result.stdout.strip().splitlines() 167 if len(lines) < 2: 168 raise RuntimeError("Could not read FSLDIR and FSLOUTPUTTYPE") 169 170 fsldir, fsloutputtype = lines[0], lines[1] 171 return fsldir, fsloutputtype
Load environment variables for FSL (FMRIB Software Library).
This function runs a shell command to source the FSL configuration script
(fsl.sh) and extract the environment variables FSLDIR and FSLOUTPUTTYPE.
Returns:
tuple[str, str]: A tuple containing:
- FSLDIR: The root installation directory of FSL.
- FSLOUTPUTTYPE: The default FSL output format (e.g., NIFTI_GZ).
Raises: RuntimeError: If FSLDIR or FSLOUTPUTTYPE cannot be retrieved.
173def get_dl_python_executable(): 174 """Returns the path of the Python in venv deep learning.""" 175 base_dir = Path(sys.executable).parent 176 177 python_path = base_dir / ".venv-dl" / "bin" / "python" 178 179 if not python_path.exists(): 180 raise FileNotFoundError(f"Python DL environment not found: {python_path}") 181 182 return str(python_path)
Returns the path of the Python in venv deep learning.
184def get_script_path(script_relative_path): 185 """Returns the absolute path of a deep learning script.""" 186 base_dir = Path(sys.executable).parent 187 script_path = base_dir / script_relative_path 188 return str(script_path)
Returns the absolute path of a deep learning script.