From e13fe90c3a31729a5c11c906d58047d00358436f Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sun, 19 Oct 2025 12:50:54 +0200 Subject: [PATCH 01/15] rm dedicated gpu --- README.md | 33 ++++++++--------- first_breaks/utils/cuda.py | 7 ---- pyproject.toml | 24 ++++++++++-- pyproject_gpu.toml | 76 -------------------------------------- 4 files changed, 36 insertions(+), 104 deletions(-) delete mode 100644 pyproject_gpu.toml diff --git a/README.md b/README.md index b54d53b..6784bbe 100644 --- a/README.md +++ b/README.md @@ -83,30 +83,29 @@ The latest model was trained similarly, but: # Installation -Library is available in [PyPI](https://pypi.org/project/first-breaks-picking/): +The easiest way to install: ```shell -pip install -U first-breaks-picking +pip install -U first-breaks-picking[standard] ``` -### GPU support +With a `standard` installation, you can run a desktop application and all calculations will be done using the CPU. -You can use the capabilities of GPU (discrete, not integrated with CPU) to significantly reduce picking time. Before started, check -[here](https://developer.nvidia.com/cuda-gpus) that your GPU is CUDA compatible. - -Install GPU supported version of library: +Other installation methods: ```shell -pip install -U first-breaks-picking-gpu -``` +# CPU, NO desktop application +pip install -U first-breaks-picking[engine-cpu] + +# CUDA accelerated, NO desktop application +pip install -U first-breaks-picking[engine-cuda] -The following steps are operating system dependent and must be performed manually: +# CPU + desktop application, same as `standard` +pip install -U first-breaks-picking[engine-cpu,desktop] + +# CUDA accelerated + desktop application +pip install -U first-breaks-picking[engine-cuda,desktop] +``` -- Install [latest NVIDIA drivers](https://www.nvidia.com/Download/index.aspx). -- Install [CUDA toolkit](https://developer.nvidia.com/cuda-downloads). -**The version must be between 11.x, starting with 11.6. -Version 12 also may work, but versions >=11.6 are recommended**. -- Install ZLib and CuDNN: -[Windows](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#install-windows) and -[Linux](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#install-linux). +We use `onnxruntime` as engine for neural network. You can find the engine's dependencies on the [official page](https://onnxruntime.ai/docs/install/). ### Compiled desktop application diff --git a/first_breaks/utils/cuda.py b/first_breaks/utils/cuda.py index e68eae9..bea8e74 100644 --- a/first_breaks/utils/cuda.py +++ b/first_breaks/utils/cuda.py @@ -75,13 +75,6 @@ def is_onnx_cuda_initializable() -> bool: return False -# def is_zlib_installed() -> bool: -# if is_windows(): -# for path in os.environ["PATH"].split(";"): -# if Path(path) / "zlibwapi.dll": -# pass - - def is_onnx_cuda_available() -> bool: return is_onnx_gpu_version_installed() and is_onnx_cuda_initializable() diff --git a/pyproject.toml b/pyproject.toml index 56ed85e..d1c2c10 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,14 +42,30 @@ dependencies = [ "requests>=2.28.2", "numpy (>=1.24.2,<2.0.0)", "pandas>=2.0.0", - "PyQt5>=5.15.9", - "pyqtgraph>=0.13.3", "tqdm>=4.65.0", "click>=8.1.3", "pydantic>=2.0.3", - "pytest>=7.3.2", +] + +[project.optional-dependencies] +engine-cpu = ["onnxruntime>=1.20"] +engine-cuda = ["onnxruntime-gpu[cuda]>=1.20"] + +desktop = [ + "PyQt5>=5.15.9", + "pyqtgraph>=0.13.3", +] + +standard = [ + "onnxruntime>=1.20", + "PyQt5>=5.15.9", + "pyqtgraph>=0.13.3", +] + +dev = [ + "pre-commit", + "pytest", "pytest-qt>=4.4.0", - "onnxruntime>=1.14.1" ] diff --git a/pyproject_gpu.toml b/pyproject_gpu.toml deleted file mode 100644 index c0e8eb4..0000000 --- a/pyproject_gpu.toml +++ /dev/null @@ -1,76 +0,0 @@ -[build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" - -[project] -name = "first-breaks-picking-gpu" -dynamic = ["version"] -description = "Project is devoted to pick waves that are the first to be detected on a seismogram with neural network (CUDA accelerated)" -readme = {file = "README.md", content-type = "text/markdown"} - -requires-python = ">=3.12" -authors = [ - {name = "Aleksei Tarasov", email = "aleksei.v.tarasov@gmail.com"}, - {name = "Aleksei Tarasov"}, -] -urls = {Homepage = "https://github.com/DaloroAT/first_breaks_picking"} -keywords = [ - "seismic", - "first-breaks", - "computer-vision", - "deep-learning", - "segmentation", - "data-science" -] -license = {file = "LICENSE"} -classifiers = [ - "Environment :: Console", - "Environment :: X11 Applications :: Qt", - "Operating System :: OS Independent", - "License :: OSI Approved :: Apache Software License", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "Topic :: Scientific/Engineering :: Artificial Intelligence", - "Topic :: Scientific/Engineering :: Image Recognition", - "Programming Language :: Python", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", -] -entry-points = {console_scripts = {first-breaks-picking = "first_breaks.cli:cli_commands"}} -dependencies = [ - "requests>=2.28.2", - "numpy (>=1.24.2,<2.0.0)", - "pandas>=2.0.0", - "PyQt5>=5.15.9", - "pyqtgraph>=0.13.3", - "tqdm>=4.65.0", - "click>=8.1.3", - "pydantic>=2.0.3", - "pytest>=7.3.2", - "pytest-qt>=4.4.0", - "onnxruntime-gpu>=1.14.1" -] - - -[tool.setuptools.dynamic] -version = {file = "first_breaks/VERSION"} - - -[tool.setuptools.packages.find] -exclude = ["first_breaks._pytorch*"] -include = ["first_breaks*"] - - -[tool.briefcase] -project_name = "FirstBreaksPickingGPU" -bundle = "com.example" -version = "0.8.0" -url = "https://github.com/DaloroAT/first_breaks_picking" -license = {file = "LICENSE"} - -[tool.briefcase.app.first_breaks] -formal_name = "FirstBreaksPickingGPU" -#description = "Project is devoted to pick waves that are the first to be detected on a seismogram with neural network" -#icon = "src/mypysideapp/resources/appicon" # Briecase will choose the right extension depending the os (png,ico,...) -sources = ['first_breaks'] \ No newline at end of file From 03b4380bd03163bf8a6f464cd6a68d8e69a35c9f Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sun, 19 Oct 2025 13:26:25 +0200 Subject: [PATCH 02/15] wip --- .github/workflows/release-workflow.yaml | 178 +++++++++++++----------- .github/workflows/tests-workflow.yaml | 2 +- .github/workflows/tomls.yaml | 25 ---- Makefile | 11 -- checks.py | 116 --------------- pyproject.toml | 2 - 6 files changed, 99 insertions(+), 235 deletions(-) delete mode 100644 .github/workflows/tomls.yaml delete mode 100644 checks.py diff --git a/.github/workflows/release-workflow.yaml b/.github/workflows/release-workflow.yaml index 7b105ee..c1f575a 100644 --- a/.github/workflows/release-workflow.yaml +++ b/.github/workflows/release-workflow.yaml @@ -47,83 +47,101 @@ jobs: echo "tagname=v$VER" >> "$GITHUB_OUTPUT" fi - publish_assets: - name: Build and publish assets - needs: autotag - if: ${{ needs.autotag.outputs.tagcreated == 'yes' }} - runs-on: windows-latest - strategy: - matrix: - type: ['CPU'] - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - - name: Check versions - shell: bash - run: | - pip install tomli - python checks.py - - - name: Setup for ${{ matrix.type }} Build - shell: pwsh - env: - BUILD_TYPE: ${{ matrix.type }} - run: | - if ($env:BUILD_TYPE -eq 'GPU') { - Move-Item -Path .\pyproject_gpu.toml -Destination .\pyproject.toml -Force - } - - - name: ${{ matrix.type }} - Install Wheels - shell: bash - run: | - python -m pip install --upgrade pip - python -m pip install --upgrade setuptools wheel build twine - python -m build --sdist --wheel - - - name: ${{ matrix.type }} - Upload to PyPI - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PY_PI_TOKEN }} - shell: bash - run: twine upload dist/* - - - name: ${{ matrix.type }} - Install Builder - run: | - python -m pip install briefcase - # Install WiX v5 CLI (required by recent Briefcase) - dotnet tool install --global wix --version 5.* - echo "$env:USERPROFILE\.dotnet\tools" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - - name: ${{ matrix.type }} - Create Package - shell: pwsh - run: | - Remove-Item -Path .\build -Recurse -Force - briefcase create - - - name: ${{ matrix.type }} - Build Package - shell: pwsh - run: briefcase build - - - name: ${{ matrix.type }} - Create Installer MSI - shell: pwsh - run: | - briefcase package --adhoc-sign --packaging-format msi - Remove-Item -Path .\dist\*.wixpdb -Force - - name: ${{ matrix.type }} - Create Installer ZIP - shell: pwsh - run: briefcase package --adhoc-sign --packaging-format zip - - - name: ${{ matrix.type }} - Upload assets to GitHub Release - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - tag: ${{ needs.autotag.outputs.tagname }} - file_glob: true - file: dist/* - overwrite: true + publish_wheels: + name: Publish PyPI + needs: autotag + if: ${{ needs.autotag.outputs.tagcreated == 'yes' }} + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install Wheels + shell: bash + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools wheel build twine + python -m build --sdist --wheel + + - name: Upload to PyPI + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PY_PI_TOKEN }} + shell: bash + run: twine upload dist/* + + - name: Upload to GitHub Release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ needs.autotag.outputs.tagname }} + file_glob: true + file: dist/* + overwrite: true + +# +# publish_assets: +# name: Build and publish assets +# needs: autotag +# if: ${{ needs.autotag.outputs.tagcreated == 'yes' }} +# runs-on: windows-latest +# strategy: +# matrix: +# type: ['CPU'] +# steps: +# - name: Checkout +# uses: actions/checkout@v4 +# +# - name: Set up Python +# uses: actions/setup-python@v5 +# with: +# python-version: "3.12" +# +# - name: Setup for ${{ matrix.type }} Build +# shell: pwsh +# env: +# BUILD_TYPE: ${{ matrix.type }} +# run: | +# if ($env:BUILD_TYPE -eq 'GPU') { +# Move-Item -Path .\pyproject_gpu.toml -Destination .\pyproject.toml -Force +# } +# +# - name: ${{ matrix.type }} - Install Builder +# run: | +# python -m pip install briefcase +# # Install WiX v5 CLI (required by recent Briefcase) +# dotnet tool install --global wix --version 5.* +# echo "$env:USERPROFILE\.dotnet\tools" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append +# +# - name: ${{ matrix.type }} - Create Package +# shell: pwsh +# run: | +# Remove-Item -Path .\build -Recurse -Force +# briefcase create +# +# - name: ${{ matrix.type }} - Build Package +# shell: pwsh +# run: briefcase build +# +# - name: ${{ matrix.type }} - Create Installer MSI +# shell: pwsh +# run: | +# briefcase package --adhoc-sign --packaging-format msi +# Remove-Item -Path .\dist\*.wixpdb -Force +# - name: ${{ matrix.type }} - Create Installer ZIP +# shell: pwsh +# run: briefcase package --adhoc-sign --packaging-format zip +# +# - name: ${{ matrix.type }} - Upload assets to GitHub Release +# uses: svenstaro/upload-release-action@v2 +# with: +# repo_token: ${{ secrets.GITHUB_TOKEN }} +# tag: ${{ needs.autotag.outputs.tagname }} +# file_glob: true +# file: dist/* +# overwrite: true diff --git a/.github/workflows/tests-workflow.yaml b/.github/workflows/tests-workflow.yaml index ed3e3c2..e8703ea 100644 --- a/.github/workflows/tests-workflow.yaml +++ b/.github/workflows/tests-workflow.yaml @@ -33,7 +33,7 @@ jobs: - name: Install project run: | python -m pip install --upgrade pip - pip install -e . + pip install .[standard] - name: Tests run: make run_tests diff --git a/.github/workflows/tomls.yaml b/.github/workflows/tomls.yaml deleted file mode 100644 index fe5ab0c..0000000 --- a/.github/workflows/tomls.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: Tomls - - -on: - pull_request: - branches: - - main - push: - branches: - - main - - -jobs: - tests: - runs-on: ubuntu-24.04 - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.12.0" - - name: Checks - run: | - python checks.py \ No newline at end of file diff --git a/Makefile b/Makefile index 87a9dd3..533a3f3 100644 --- a/Makefile +++ b/Makefile @@ -6,14 +6,3 @@ run_precommit: run_tests: pytest -sv --disable-warnings tests -.PHONY: build_wheel -build_wheel: - python -m pip install --upgrade pip - python -m pip install --upgrade twine - pip install --upgrade pip setuptools wheel - rm -rf dist build first_breaks_picking.egg-info - python setup.py sdist bdist_wheel - -.PHONY: upload_to_pip -upload_to_pip: build_wheel - twine upload dist/* diff --git a/checks.py b/checks.py deleted file mode 100644 index 4bc3d5b..0000000 --- a/checks.py +++ /dev/null @@ -1,116 +0,0 @@ -from pathlib import Path - -import tomllib - - -def compare_main_and_gpu_tomls() -> None: - with open(Path(__file__).parent / "pyproject.toml", "rb") as fin: - pyproject_main = tomllib.load(fin) - - with open(Path(__file__).parent / "pyproject_gpu.toml", "rb") as fin: - pyproject_gpu = tomllib.load(fin) - - deps_main = set(pyproject_main["project"].pop("dependencies")) - deps_gpu = set(pyproject_gpu["project"].pop("dependencies")) - - # Analyse onnx version - - onnx_main = [dep for dep in deps_main if dep.startswith("onnxruntime")] - onnx_gpu = [dep for dep in deps_gpu if dep.startswith("onnxruntime-gpu")] - - if not onnx_main: - raise EnvironmentError( - "'onnxruntime' is not in dependencies in 'pyproject.toml'" - ) - - if not onnx_gpu: - raise EnvironmentError( - "'onnxruntime-gpu' is not in dependencies in 'pyproject_gpu.toml'" - ) - - onnx_main = onnx_main[0] - onnx_gpu = onnx_gpu[0] - - onnx_main = onnx_main.split(">=") - onnx_gpu = onnx_gpu.split(">=") - - if not onnx_main or not onnx_gpu: - raise EnvironmentError( - "Please, fix versions for 'onnxruntime' and 'onnxruntime-gpu'" - ) - - if onnx_main[1] != onnx_gpu[1]: - raise EnvironmentError( - "Versions of 'onnxruntime' and 'onnxruntime-gpu' are different" - ) - - # Compare other deps - - difference = deps_main.symmetric_difference(deps_gpu) - - if not ( - all("onnxruntime" in dep for dep in difference) - and (deps_main - difference) == (deps_gpu - difference) - ): - raise EnvironmentError("Only difference between 'onnxruntime' is available") - - # Compare project names - - project_name_main = pyproject_main["project"].pop("name") - project_name_gpu = pyproject_gpu["project"].pop("name") - - if project_name_main + "-gpu" != project_name_gpu: - raise EnvironmentError( - f"Wrong project names: {project_name_main} and {project_name_gpu}" - ) - - # Compare app names - - app_name_main = pyproject_main["tool"]["briefcase"].pop("project_name") - app_name_gpu = pyproject_gpu["tool"]["briefcase"].pop("project_name") - - if app_name_main + "GPU" != app_name_gpu: - raise EnvironmentError(f"Wrong app names: {app_name_main} and {app_name_gpu}") - - app_formal_name_main = pyproject_main["tool"]["briefcase"]["app"][ - "first_breaks" - ].pop("formal_name") - app_formal_name_gpu = pyproject_gpu["tool"]["briefcase"]["app"]["first_breaks"].pop( - "formal_name" - ) - - if app_formal_name_main + "GPU" != app_formal_name_gpu: - raise EnvironmentError( - f"Wrong app names: {app_formal_name_main} and {app_formal_name_gpu}" - ) - - # Compare rest of the tomls - - del pyproject_main["project"]["description"] - del pyproject_gpu["project"]["description"] - - if pyproject_main != pyproject_gpu: - raise EnvironmentError("Main config and gpu config are different") - - print("TOMLs are correct") - - -def compare_versions_of_repo() -> None: - with open(Path(__file__).parent / "first_breaks/VERSION", "r") as fin: - project_version = fin.read() - - with open(Path(__file__).parent / "pyproject.toml", "rb") as fin: - briefcase_version = tomllib.load(fin)["tool"]["briefcase"]["version"] - - if project_version != briefcase_version: - raise EnvironmentError( - f"Version in 'briefcase' config and version of project are different. " - f"Briefcase: {briefcase_version}, project: {project_version}" - ) - - print("Versions are the same") - - -if __name__ == "__main__": - compare_main_and_gpu_tomls() - compare_versions_of_repo() diff --git a/pyproject.toml b/pyproject.toml index d1c2c10..f1b6a54 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,6 +87,4 @@ license = {file = "LICENSE"} [tool.briefcase.app.first_breaks] formal_name = "FirstBreaksPicking" -#description = "Project is devoted to pick waves that are the first to be detected on a seismogram with neural network" -#icon = "src/mypysideapp/resources/appicon" # Briecase will choose the right extension depending the os (png,ico,...) sources = ['first_breaks'] \ No newline at end of file From 0c588f6f44b4875c391217ffe476f5796fe510f2 Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 1 Nov 2025 10:59:17 +0100 Subject: [PATCH 03/15] refactor devices --- first_breaks/__init__.py | 6 ++ first_breaks/data_models/dependent.py | 2 +- .../desktop/settings_processing_widget.py | 12 +-- first_breaks/picking/picker_onnx.py | 11 ++- first_breaks/utils/cuda.py | 86 ------------------- first_breaks/utils/engine.py | 58 +++++++++++++ pyproject.toml | 7 +- 7 files changed, 80 insertions(+), 102 deletions(-) delete mode 100644 first_breaks/utils/cuda.py create mode 100644 first_breaks/utils/engine.py diff --git a/first_breaks/__init__.py b/first_breaks/__init__.py index 8613008..799cacf 100644 --- a/first_breaks/__init__.py +++ b/first_breaks/__init__.py @@ -3,6 +3,12 @@ from pathlib import Path from sys import platform +try: + # try to load torch first to get access to CUDA and CuDNN + import torch +except Exception: + pass + def is_windows() -> bool: return "win" in platform diff --git a/first_breaks/data_models/dependent.py b/first_breaks/data_models/dependent.py index 7660ea1..b05a418 100644 --- a/first_breaks/data_models/dependent.py +++ b/first_breaks/data_models/dependent.py @@ -7,7 +7,7 @@ from first_breaks.data_models.independent import DefaultModel, TraceBytePosition from first_breaks.sgy.headers import Headers, TraceHeaders from first_breaks.sgy.reader import SGY -from first_breaks.utils.cuda import get_recommended_device +from first_breaks.utils.engine import get_recommended_device TRACE_HEADER_NAMES = [v[1] for v in TraceHeaders().headers_schema] diff --git a/first_breaks/desktop/settings_processing_widget.py b/first_breaks/desktop/settings_processing_widget.py index b816650..e4d3804 100644 --- a/first_breaks/desktop/settings_processing_widget.py +++ b/first_breaks/desktop/settings_processing_widget.py @@ -38,7 +38,7 @@ from first_breaks.desktop.combobox_with_mapping import QComboBoxMapping from first_breaks.desktop.radioset_widget import QRadioSetWidget from first_breaks.desktop.utils import QHSeparationLine, set_geometry -from first_breaks.utils.cuda import ONNX_CUDA_AVAILABLE, get_recommended_device +from first_breaks.utils.engine import get_recommended_device, is_onnx_cuda_available if HIGH_DPI: QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) @@ -318,24 +318,24 @@ class DeviceLine(QComboBoxMapping, _Extras): CPU_INEDX = 1 def __init__(self, device: str = DEFAULTS.device): - if device == "cuda" and ONNX_CUDA_AVAILABLE: + if device == "cuda" and is_onnx_cuda_available(): current_value = device else: current_value = "cpu" - if not ONNX_CUDA_AVAILABLE: + if not is_onnx_cuda_available(): cuda_postfix = "(CUDA drivers or CUDA compatible app are not installed)" else: cuda_postfix = "" super().__init__( - {self.CUDA_INDEX: [f"GPU/CUDA {cuda_postfix}", "cuda"], self.CPU_INEDX: ["CPU", "cpu"]}, + {self.CUDA_INDEX: [f"GPU/CUDA {cuda_postfix}", Device], self.CPU_INEDX: ["CPU", "cpu"]}, current_value=current_value, ) - if not ONNX_CUDA_AVAILABLE: + if not is_onnx_cuda_available(): item = self.model().item(self.CUDA_INDEX) - if not ONNX_CUDA_AVAILABLE: + if not is_onnx_cuda_available(): item.setFlags(item.flags() & ~Qt.ItemIsEnabled) def dict(self) -> Dict[str, Any]: diff --git a/first_breaks/picking/picker_onnx.py b/first_breaks/picking/picker_onnx.py index e80a68e..d32d29a 100644 --- a/first_breaks/picking/picker_onnx.py +++ b/first_breaks/picking/picker_onnx.py @@ -8,7 +8,10 @@ from first_breaks.picking.picks import Picks from first_breaks.picking.task import Task from first_breaks.picking.utils import preprocess_gather -from first_breaks.utils.cuda import ONNX_DEVICE2PROVIDER, get_recommended_device +from first_breaks.utils.engine import ( + ONNX_DEVICE2PROVIDER, + get_recommended_device, +) from first_breaks.utils.utils import ( calc_hash, chunk_iterable, @@ -87,7 +90,7 @@ def __init__( batch_size: int = 1, ): super().__init__(show_progressbar=show_progressbar) - assert device in ["cpu", "cuda"] + assert device in ONNX_DEVICE2PROVIDER.keys() if model_path is None: model_path = download_model_onnx() @@ -114,10 +117,6 @@ def is_heatmap_available(self) -> bool: def init_model(self) -> None: sess_opt = ort.SessionOptions() sess_opt.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL - if self.device == "cuda": - sess_opt = ort.SessionOptions() - sess_opt.intra_op_num_threads = 2 - sess_opt.inter_op_num_threads = 2 self.model = ort.InferenceSession( str(self.model_path), providers=[ONNX_DEVICE2PROVIDER[self.device]], diff --git a/first_breaks/utils/cuda.py b/first_breaks/utils/cuda.py deleted file mode 100644 index bea8e74..0000000 --- a/first_breaks/utils/cuda.py +++ /dev/null @@ -1,86 +0,0 @@ -import numpy as np -import onnxruntime as ort - -from first_breaks import is_windows - -ONNX_DEVICE2PROVIDER = {"cuda": "CUDAExecutionProvider", "cpu": "CPUExecutionProvider"} - - -def is_onnx_gpu_version_installed() -> bool: - try: - return ONNX_DEVICE2PROVIDER["cuda"] in ort.get_available_providers() - except Exception: - return False - - -def _colorize(txt: str) -> str: - _blue_code = "\033[94m" - _reset = "\033[0m" - - return f"{_blue_code}{txt}{_reset}" - - -GPU_USSAGE_MESSAGE = """ -Before using GPU acceleration, check https://developer.nvidia.com/cuda-gpus that your GPU is CUDA compatible. -""" - - -CUDA_INSTALLATION_MESSAGE = f""" -Install CUDA Toolkit in one of the following ways: -\t1) Using the official website https://developer.nvidia.com/cuda-toolkit-archive. Select one \ -of 11.6, 11.7, 11.8 versions. Version 12 also may work, but versions >=11.6 are recommended. -\t2) Using Conda {_colorize('conda install -c anaconda "cudatoolkit>=11.6,<12"')}. -""" - - -_CUDNN_LINUX_URL = "https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#install-linux" -_CUDNN_WINDOWS_URL = "https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#install-windows" - -CUDNN_INSTALLATION_MESSAGE = f""" -Install cuDNN toolkit in one of the following ways: -\t1) Using official website {_CUDNN_WINDOWS_URL if is_windows() else _CUDNN_LINUX_URL}. -\t2) Using Conda {_colorize('conda install -c anaconda "cudnn=8.2"')}. -""" - - -_ZLIB_LIBUX_URL = "https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#install-zlib-linux" -_ZLIB_WINDOWS_URL = "https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#install-zlib-windows" - -ZLIB_INSTALLATION_MESSAGE = f""" -Install ZLib {_ZLIB_WINDOWS_URL if is_windows() else _ZLIB_LIBUX_URL}. -""" - - -FULL_INSTALLATION_MESSAGE = "".join( - [GPU_USSAGE_MESSAGE, CUDA_INSTALLATION_MESSAGE, CUDNN_INSTALLATION_MESSAGE, ZLIB_INSTALLATION_MESSAGE] -) - - -def raise_onnx_cuda_init(add_installation_instruction: bool = True) -> None: - try: - ort.OrtValue.ortvalue_from_numpy(np.array([0], dtype=np.float32), "cuda", 0) - except Exception as exc: - if add_installation_instruction: - err_message = f"{str(exc)}\n" f"{'_' * 20}\n" f"Recommendations:\n" f"{FULL_INSTALLATION_MESSAGE}" - raise type(exc)(err_message).with_traceback(exc.__traceback__) - else: - raise exc - - -def is_onnx_cuda_initializable() -> bool: - try: - raise_onnx_cuda_init() - return True - except Exception: - return False - - -def is_onnx_cuda_available() -> bool: - return is_onnx_gpu_version_installed() and is_onnx_cuda_initializable() - - -ONNX_CUDA_AVAILABLE = is_onnx_cuda_available() - - -def get_recommended_device() -> str: - return "cuda" if ONNX_CUDA_AVAILABLE else "cpu" diff --git a/first_breaks/utils/engine.py b/first_breaks/utils/engine.py new file mode 100644 index 0000000..6f4c752 --- /dev/null +++ b/first_breaks/utils/engine.py @@ -0,0 +1,58 @@ +from enum import Enum + +import numpy as np +import onnxruntime as ort + + +class Engine(Enum): + CUDA = "cuda" + OPENVINO = "openvino" + CPU = "cpu" + + +ONNX_DEVICE2PROVIDER = { + Engine.CUDA.value: "CUDAExecutionProvider", + Engine.OPENVINO.value: "OpenVINOExecutionProvider", + Engine.CPU.value: "CPUExecutionProvider", +} + + +FULL_INSTALLATION_MESSAGE = """ +\nCheck requirements for installed onnxruntime:\n" +1) https://onnxruntime.ai/docs/install/ +2) https://onnxruntime.ai/docs/execution-providers/ +""" + + +def raise_onnx_device_init(device: str) -> None: + try: + print(device) + ort.OrtValue.ortvalue_from_numpy(np.array([0], dtype=np.float32), device, 0) + except Exception as exc: + err_message = f"{str(exc)}\n" f"{'_' * 20}\n" f"Recommendations:\n" f"{FULL_INSTALLATION_MESSAGE}" + raise type(exc)(err_message).with_traceback(exc.__traceback__) + + +def is_onnx_device_available(device: str) -> bool: + try: + raise_onnx_device_init(device=device) + return True + except Exception: + return False + + +def is_onnx_cuda_available() -> bool: + return is_onnx_device_available(Engine.CUDA.value) + + +def is_onnx_openvino_available() -> bool: + return is_onnx_device_available(Engine.OPENVINO.value) + + +def get_recommended_device() -> str: + if is_onnx_cuda_available(): + return Engine.CUDA.value + elif is_onnx_openvino_available(): + return Engine.OPENVINO.value + else: + return Engine.CPU.value diff --git a/pyproject.toml b/pyproject.toml index f1b6a54..9492836 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,8 +48,9 @@ dependencies = [ ] [project.optional-dependencies] -engine-cpu = ["onnxruntime>=1.20"] -engine-cuda = ["onnxruntime-gpu[cuda]>=1.20"] +engine-cpu = ["onnxruntime>=1.23"] +engine-cuda = ["onnxruntime-gpu[cuda,cudnn]>=1.23"] +engine-openvino = ["onnxruntime-openvino>=1.23", "openvino>=2025"] desktop = [ "PyQt5>=5.15.9", @@ -57,7 +58,7 @@ desktop = [ ] standard = [ - "onnxruntime>=1.20", + "onnxruntime>=1.23", "PyQt5>=5.15.9", "pyqtgraph>=0.13.3", ] From db09d8e4d0ee9b91a139671df382a33cc35c8288 Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 1 Nov 2025 11:09:35 +0100 Subject: [PATCH 04/15] change settings widget --- first_breaks/data_models/dependent.py | 2 +- .../desktop/settings_processing_widget.py | 35 +++++++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/first_breaks/data_models/dependent.py b/first_breaks/data_models/dependent.py index b05a418..73895ff 100644 --- a/first_breaks/data_models/dependent.py +++ b/first_breaks/data_models/dependent.py @@ -72,6 +72,6 @@ def sync_source_and_sgy(self) -> "SGYModel": class Device(DefaultModel): - device: Literal["cpu", "cuda"] = Field( + device: Literal["cpu", "cuda", "openvino"] = Field( get_recommended_device(), description="Device to compute first breaks" ) # type: ignore diff --git a/first_breaks/desktop/settings_processing_widget.py b/first_breaks/desktop/settings_processing_widget.py index e4d3804..65e15bf 100644 --- a/first_breaks/desktop/settings_processing_widget.py +++ b/first_breaks/desktop/settings_processing_widget.py @@ -38,7 +38,12 @@ from first_breaks.desktop.combobox_with_mapping import QComboBoxMapping from first_breaks.desktop.radioset_widget import QRadioSetWidget from first_breaks.desktop.utils import QHSeparationLine, set_geometry -from first_breaks.utils.engine import get_recommended_device, is_onnx_cuda_available +from first_breaks.utils.engine import ( + Engine, + get_recommended_device, + is_onnx_cuda_available, + is_onnx_openvino_available, +) if HIGH_DPI: QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) @@ -315,28 +320,36 @@ def dict(self) -> Dict[str, Any]: class DeviceLine(QComboBoxMapping, _Extras): CUDA_INDEX = 0 - CPU_INEDX = 1 + OPENVINO_INDEX = 1 + CPU_INDEX = 2 def __init__(self, device: str = DEFAULTS.device): - if device == "cuda" and is_onnx_cuda_available(): - current_value = device - else: - current_value = "cpu" - if not is_onnx_cuda_available(): cuda_postfix = "(CUDA drivers or CUDA compatible app are not installed)" else: cuda_postfix = "" + if not is_onnx_openvino_available(): + openvino_postfix = "(OpenVino or OpenVino compatible app are not installed)" + else: + openvino_postfix = "" + super().__init__( - {self.CUDA_INDEX: [f"GPU/CUDA {cuda_postfix}", Device], self.CPU_INEDX: ["CPU", "cpu"]}, - current_value=current_value, + { + self.CUDA_INDEX: [f"CUDA {cuda_postfix}", Engine.CUDA.value], + self.OPENVINO_INDEX: [f"OpenVino {openvino_postfix}", Engine.OPENVINO.value], + self.CPU_INDEX: ["CPU", Engine.CPU.value], + }, + current_value=device, ) if not is_onnx_cuda_available(): item = self.model().item(self.CUDA_INDEX) - if not is_onnx_cuda_available(): - item.setFlags(item.flags() & ~Qt.ItemIsEnabled) + item.setFlags(item.flags() & ~Qt.ItemIsEnabled) + + if not is_onnx_openvino_available(): + item = self.model().item(self.OPENVINO_INDEX) + item.setFlags(item.flags() & ~Qt.ItemIsEnabled) def dict(self) -> Dict[str, Any]: return {"device": self.value()} From 4add95fb112deece26826603dc7fd6742e5811aa Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 1 Nov 2025 11:30:11 +0100 Subject: [PATCH 05/15] minor --- first_breaks/__init__.py | 5 +++-- first_breaks/utils/engine.py | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/first_breaks/__init__.py b/first_breaks/__init__.py index 799cacf..ec77531 100644 --- a/first_breaks/__init__.py +++ b/first_breaks/__init__.py @@ -44,6 +44,9 @@ def patch_pathenv_with_default_gpu_paths() -> None: os.environ["PATH"] = separator.join([os.environ["PATH"]] + extra_potential_paths) +patch_pathenv_with_default_gpu_paths() + + if is_windows(): base = os.path.dirname(sys.executable) app_pkgs = os.path.join(base, "app_packages") @@ -63,5 +66,3 @@ def patch_pathenv_with_default_gpu_paths() -> None: import onnxruntime as ort - -patch_pathenv_with_default_gpu_paths() diff --git a/first_breaks/utils/engine.py b/first_breaks/utils/engine.py index 6f4c752..e9dced1 100644 --- a/first_breaks/utils/engine.py +++ b/first_breaks/utils/engine.py @@ -26,7 +26,6 @@ class Engine(Enum): def raise_onnx_device_init(device: str) -> None: try: - print(device) ort.OrtValue.ortvalue_from_numpy(np.array([0], dtype=np.float32), device, 0) except Exception as exc: err_message = f"{str(exc)}\n" f"{'_' * 20}\n" f"Recommendations:\n" f"{FULL_INSTALLATION_MESSAGE}" From c61e4dbab84a5accf70f65ba9a2dbfe2190b8ac6 Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Fri, 7 Nov 2025 16:43:45 +0100 Subject: [PATCH 06/15] minor --- first_breaks/__init__.py | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/first_breaks/__init__.py b/first_breaks/__init__.py index ec77531..135a8db 100644 --- a/first_breaks/__init__.py +++ b/first_breaks/__init__.py @@ -22,31 +22,6 @@ def is_macos() -> bool: return "darwin" in platform -def patch_pathenv_with_default_gpu_paths() -> None: - if is_windows(): - extra_potential_paths = [] - extra_potential_paths.extend(list(Path(r"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA").glob("*"))) - extra_potential_paths.extend(list(Path(r"C:\Program Files\NVIDIA GPU Computing Toolkit").glob("*"))) - extra_potential_paths.extend(list(Path(r"C:\Program Files\NVIDIA\CUDNN").glob("*"))) - extra_potential_paths = [str(p) for p in extra_potential_paths] - separator = ";" - elif is_linux(): - extra_potential_paths = [ - "/usr/local/cuda", - "/usr/include", - "/lib/x86_64-linux-gnu", - ] - separator = ":" - else: - extra_potential_paths = [] - separator = ":" - - os.environ["PATH"] = separator.join([os.environ["PATH"]] + extra_potential_paths) - - -patch_pathenv_with_default_gpu_paths() - - if is_windows(): base = os.path.dirname(sys.executable) app_pkgs = os.path.join(base, "app_packages") @@ -66,3 +41,7 @@ def patch_pathenv_with_default_gpu_paths() -> None: import onnxruntime as ort + +import onnxruntime + +onnxruntime.preload_dlls() From a21a2cda099e1bde4ea3f7fe33c940de9afb4be3 Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Fri, 7 Nov 2025 18:09:55 +0100 Subject: [PATCH 07/15] fix fourier filtering --- first_breaks/utils/fourier_transforms.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/first_breaks/utils/fourier_transforms.py b/first_breaks/utils/fourier_transforms.py index a77ae48..185cce7 100644 --- a/first_breaks/utils/fourier_transforms.py +++ b/first_breaks/utils/fourier_transforms.py @@ -93,6 +93,9 @@ def build_amplitude_filter( amp_filter += fall_part + if f1_f2 and f3_f4: + amp_filter -= 1 + if filter_type == "reject": amp_filter = 1 - amp_filter From b52bfc912feec88fcf662e541c17078d7af40409 Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 8 Nov 2025 14:44:42 +0100 Subject: [PATCH 08/15] new structure --- .github/workflows/release-workflow.yaml | 127 ++++++++++++------------ first_breaks/VERSION | 2 +- pyproject.toml | 38 ++++++- 3 files changed, 100 insertions(+), 67 deletions(-) diff --git a/.github/workflows/release-workflow.yaml b/.github/workflows/release-workflow.yaml index c1f575a..119de1b 100644 --- a/.github/workflows/release-workflow.yaml +++ b/.github/workflows/release-workflow.yaml @@ -2,7 +2,7 @@ name: Release on: push: - branches: [main] +# branches: [main] paths: ['first_breaks/VERSION'] @@ -84,64 +84,67 @@ jobs: file: dist/* overwrite: true -# -# publish_assets: -# name: Build and publish assets -# needs: autotag -# if: ${{ needs.autotag.outputs.tagcreated == 'yes' }} -# runs-on: windows-latest -# strategy: -# matrix: -# type: ['CPU'] -# steps: -# - name: Checkout -# uses: actions/checkout@v4 -# -# - name: Set up Python -# uses: actions/setup-python@v5 -# with: -# python-version: "3.12" -# -# - name: Setup for ${{ matrix.type }} Build -# shell: pwsh -# env: -# BUILD_TYPE: ${{ matrix.type }} -# run: | -# if ($env:BUILD_TYPE -eq 'GPU') { -# Move-Item -Path .\pyproject_gpu.toml -Destination .\pyproject.toml -Force -# } -# -# - name: ${{ matrix.type }} - Install Builder -# run: | -# python -m pip install briefcase -# # Install WiX v5 CLI (required by recent Briefcase) -# dotnet tool install --global wix --version 5.* -# echo "$env:USERPROFILE\.dotnet\tools" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append -# -# - name: ${{ matrix.type }} - Create Package -# shell: pwsh -# run: | -# Remove-Item -Path .\build -Recurse -Force -# briefcase create -# -# - name: ${{ matrix.type }} - Build Package -# shell: pwsh -# run: briefcase build -# -# - name: ${{ matrix.type }} - Create Installer MSI -# shell: pwsh -# run: | -# briefcase package --adhoc-sign --packaging-format msi -# Remove-Item -Path .\dist\*.wixpdb -Force -# - name: ${{ matrix.type }} - Create Installer ZIP -# shell: pwsh -# run: briefcase package --adhoc-sign --packaging-format zip -# -# - name: ${{ matrix.type }} - Upload assets to GitHub Release -# uses: svenstaro/upload-release-action@v2 -# with: -# repo_token: ${{ secrets.GITHUB_TOKEN }} -# tag: ${{ needs.autotag.outputs.tagname }} -# file_glob: true -# file: dist/* -# overwrite: true + + publish_assets: + name: Build and publish assets + needs: autotag + if: ${{ needs.autotag.outputs.tagcreated == 'yes' }} + runs-on: windows-latest + strategy: + matrix: + flavor: [ cpu, cuda, openvino ] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install Briefcase & WiX 5 + shell: pwsh + run: | + python -m pip install --upgrade pip + python -m pip install "briefcase==0.3.25" + dotnet tool install --global wix --version 5.* + echo "$env:USERPROFILE\.dotnet\tools" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Map flavor → app name + id: map + shell: pwsh + run: | + $app = switch ("${{ matrix.flavor }}") { + "cpu" { "fb_cpu" } + "cuda" { "fb_cuda" } + "openvino" { "fb_openvino" } + } + echo "APP=$app" >> $env:GITHUB_OUTPUT + + - name: Create + shell: pwsh + run: briefcase create windows --app ${{ steps.map.outputs.APP }} + + - name: Build + shell: pwsh + run: briefcase build windows --app ${{ steps.map.outputs.APP }} -r + + - name: Package MSI + shell: pwsh + run: | + briefcase package windows --app ${{ steps.map.outputs.APP }} --adhoc-sign --packaging-format msi + Remove-Item -Path .\dist\*.wixpdb -Force + + - name: Package ZIP + shell: pwsh + run: briefcase package windows --app ${{ steps.map.outputs.APP }} --adhoc-sign --packaging-format zip + + + - name: Upload assets to GitHub Release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ needs.autotag.outputs.tagname }} + file_glob: true + file: dist/* + overwrite: true diff --git a/first_breaks/VERSION b/first_breaks/VERSION index 8adc70f..13070be 100644 --- a/first_breaks/VERSION +++ b/first_breaks/VERSION @@ -1 +1 @@ -0.8.0 \ No newline at end of file +0.9.0a1 \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 9492836..d1a632d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,10 +82,40 @@ include = ["first_breaks*"] [tool.briefcase] project_name = "FirstBreaksPicking" bundle = "com.example" -version = "0.8.0" +version = "0.9.0a1" url = "https://github.com/DaloroAT/first_breaks_picking" license = {file = "LICENSE"} -[tool.briefcase.app.first_breaks] -formal_name = "FirstBreaksPicking" -sources = ['first_breaks'] \ No newline at end of file +# CPU build +[tool.briefcase.app.fb_cpu] +formal_name = "FirstBreaksPicking (CPU)" +description = "Seismic first-breaks picking (CPU)" +sources = ["first_breaks"] +requires = [ + "PyQt5>=5.15.9", + "pyqtgraph>=0.13.3", + "onnxruntime>=1.23", +] + +# CUDA build +[tool.briefcase.app.fb_cuda] +formal_name = "FirstBreaksPicking (CUDA)" +description = "Seismic first-breaks picking (CUDA)" +sources = ["first_breaks"] +requires = [ + "PyQt5>=5.15.9", + "pyqtgraph>=0.13.3", + "onnxruntime-gpu[cuda,cudnn]>=1.23", +] + +# OpenVINO build +[tool.briefcase.app.fb_openvino] +formal_name = "FirstBreaksPicking (OpenVINO)" +description = "Seismic first-breaks picking (OpenVINO)" +sources = ["first_breaks"] +requires = [ + "PyQt5>=5.15.9", + "pyqtgraph>=0.13.3", + "onnxruntime-openvino>=1.23", + "openvino>=2025", +] \ No newline at end of file From 1db844ee5aa81e5980646a5026130d2fb71463a5 Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 8 Nov 2025 16:48:27 +0100 Subject: [PATCH 09/15] new release --- .github/workflows/release-workflow.yaml | 12 ++----- fbcpu/__init__.py | 0 fbcpu/__main__.py | 2 ++ fbcuda/__init__.py | 0 fbcuda/__main__.py | 2 ++ fbopenvino/__init__.py | 0 fbopenvino/__main__.py | 2 ++ first_breaks/VERSION | 2 +- first_breaks/desktop/main_gui.py | 3 +- pyproject.toml | 42 ++++++++++--------------- 10 files changed, 28 insertions(+), 37 deletions(-) create mode 100644 fbcpu/__init__.py create mode 100644 fbcpu/__main__.py create mode 100644 fbcuda/__init__.py create mode 100644 fbcuda/__main__.py create mode 100644 fbopenvino/__init__.py create mode 100644 fbopenvino/__main__.py diff --git a/.github/workflows/release-workflow.yaml b/.github/workflows/release-workflow.yaml index 119de1b..94dae33 100644 --- a/.github/workflows/release-workflow.yaml +++ b/.github/workflows/release-workflow.yaml @@ -115,9 +115,9 @@ jobs: shell: pwsh run: | $app = switch ("${{ matrix.flavor }}") { - "cpu" { "fb_cpu" } - "cuda" { "fb_cuda" } - "openvino" { "fb_openvino" } + "cpu" { "fbcpu" } + "cuda" { "fbcuda" } + "openvino" { "fbopenvino" } } echo "APP=$app" >> $env:GITHUB_OUTPUT @@ -129,12 +129,6 @@ jobs: shell: pwsh run: briefcase build windows --app ${{ steps.map.outputs.APP }} -r - - name: Package MSI - shell: pwsh - run: | - briefcase package windows --app ${{ steps.map.outputs.APP }} --adhoc-sign --packaging-format msi - Remove-Item -Path .\dist\*.wixpdb -Force - - name: Package ZIP shell: pwsh run: briefcase package windows --app ${{ steps.map.outputs.APP }} --adhoc-sign --packaging-format zip diff --git a/fbcpu/__init__.py b/fbcpu/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fbcpu/__main__.py b/fbcpu/__main__.py new file mode 100644 index 0000000..5372e83 --- /dev/null +++ b/fbcpu/__main__.py @@ -0,0 +1,2 @@ +import runpy +runpy.run_module("first_breaks", run_name="__main__") \ No newline at end of file diff --git a/fbcuda/__init__.py b/fbcuda/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fbcuda/__main__.py b/fbcuda/__main__.py new file mode 100644 index 0000000..5372e83 --- /dev/null +++ b/fbcuda/__main__.py @@ -0,0 +1,2 @@ +import runpy +runpy.run_module("first_breaks", run_name="__main__") \ No newline at end of file diff --git a/fbopenvino/__init__.py b/fbopenvino/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fbopenvino/__main__.py b/fbopenvino/__main__.py new file mode 100644 index 0000000..5372e83 --- /dev/null +++ b/fbopenvino/__main__.py @@ -0,0 +1,2 @@ +import runpy +runpy.run_module("first_breaks", run_name="__main__") \ No newline at end of file diff --git a/first_breaks/VERSION b/first_breaks/VERSION index 13070be..da7f625 100644 --- a/first_breaks/VERSION +++ b/first_breaks/VERSION @@ -1 +1 @@ -0.9.0a1 \ No newline at end of file +0.9.0a2 \ No newline at end of file diff --git a/first_breaks/desktop/main_gui.py b/first_breaks/desktop/main_gui.py index a81497a..cd8b9ca 100644 --- a/first_breaks/desktop/main_gui.py +++ b/first_breaks/desktop/main_gui.py @@ -169,7 +169,7 @@ def __init__(self, use_open_gl: bool = True, show: bool = True): # type: ignore hide_on_close=True, **self.plotseis_settings.model_dump(), ) - self.settings_processing_widget.hide() + self.settings_processing_widget.setEnabled(False) self.settings_processing_widget.export_plotseis_settings_signal.connect(self.update_plotseis_settings) self.settings_processing_widget.export_picking_settings_signal.connect(self.pick_fb) @@ -284,6 +284,7 @@ def update_plot(self, refresh_view: bool = False) -> None: self.graph.plot_picks(picks) def show_settings_processing_window(self) -> None: + self.settings_processing_widget.setEnabled(True) self.settings_processing_widget.show() self.settings_processing_widget.focusWidget() diff --git a/pyproject.toml b/pyproject.toml index d1a632d..db74a8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,40 +82,30 @@ include = ["first_breaks*"] [tool.briefcase] project_name = "FirstBreaksPicking" bundle = "com.example" -version = "0.9.0a1" +version = "0.9.0a2" url = "https://github.com/DaloroAT/first_breaks_picking" license = {file = "LICENSE"} +author = "Aleksei Tarasov" +author_email = "aleksei.v.tarasov@gmail.com" +long_description = "Project is devoted to pick waves that are the first to be detected on a seismogram with neural network" # CPU build -[tool.briefcase.app.fb_cpu] +[tool.briefcase.app.fbcpu] formal_name = "FirstBreaksPicking (CPU)" -description = "Seismic first-breaks picking (CPU)" -sources = ["first_breaks"] -requires = [ - "PyQt5>=5.15.9", - "pyqtgraph>=0.13.3", - "onnxruntime>=1.23", -] +description = "Desktop app for seismic first-breaks-picking (CPU)" +sources = ["fbcpu"] +requires = [ ".[engine-cpu,desktop]" ] # CUDA build -[tool.briefcase.app.fb_cuda] +[tool.briefcase.app.fbcuda] formal_name = "FirstBreaksPicking (CUDA)" -description = "Seismic first-breaks picking (CUDA)" -sources = ["first_breaks"] -requires = [ - "PyQt5>=5.15.9", - "pyqtgraph>=0.13.3", - "onnxruntime-gpu[cuda,cudnn]>=1.23", -] +description = "Desktop app for seismic first-breaks-picking (CUDA)" +sources = ["fbcuda"] +requires = [ ".[engine-cuda,desktop]" ] # OpenVINO build -[tool.briefcase.app.fb_openvino] +[tool.briefcase.app.fbopenvino] formal_name = "FirstBreaksPicking (OpenVINO)" -description = "Seismic first-breaks picking (OpenVINO)" -sources = ["first_breaks"] -requires = [ - "PyQt5>=5.15.9", - "pyqtgraph>=0.13.3", - "onnxruntime-openvino>=1.23", - "openvino>=2025", -] \ No newline at end of file +description = "Desktop app for seismic first-breaks-picking (OpenVINO)" +sources = ["fbopenvino"] +requires = [ ".[engine-openvino,desktop]" ] \ No newline at end of file From 5ba1688d40676b631fc52428c8ecb299b28e6b5e Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 8 Nov 2025 17:18:42 +0100 Subject: [PATCH 10/15] cuda supported engine without cuda libs --- .github/workflows/release-workflow.yaml | 3 ++- fbcudasystem/__init__.py | 0 fbcudasystem/__main__.py | 2 ++ first_breaks/VERSION | 2 +- pyproject.toml | 16 ++++++++++++---- 5 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 fbcudasystem/__init__.py create mode 100644 fbcudasystem/__main__.py diff --git a/.github/workflows/release-workflow.yaml b/.github/workflows/release-workflow.yaml index 94dae33..d96fc40 100644 --- a/.github/workflows/release-workflow.yaml +++ b/.github/workflows/release-workflow.yaml @@ -92,7 +92,7 @@ jobs: runs-on: windows-latest strategy: matrix: - flavor: [ cpu, cuda, openvino ] + flavor: [ cpu, cuda, cudasystem, openvino ] steps: - name: Checkout uses: actions/checkout@v4 @@ -117,6 +117,7 @@ jobs: $app = switch ("${{ matrix.flavor }}") { "cpu" { "fbcpu" } "cuda" { "fbcuda" } + "cudasystem" { "fbcudasystem" } "openvino" { "fbopenvino" } } echo "APP=$app" >> $env:GITHUB_OUTPUT diff --git a/fbcudasystem/__init__.py b/fbcudasystem/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fbcudasystem/__main__.py b/fbcudasystem/__main__.py new file mode 100644 index 0000000..5372e83 --- /dev/null +++ b/fbcudasystem/__main__.py @@ -0,0 +1,2 @@ +import runpy +runpy.run_module("first_breaks", run_name="__main__") \ No newline at end of file diff --git a/first_breaks/VERSION b/first_breaks/VERSION index da7f625..f93e85f 100644 --- a/first_breaks/VERSION +++ b/first_breaks/VERSION @@ -1 +1 @@ -0.9.0a2 \ No newline at end of file +0.9.0a3 \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index db74a8f..f86c7b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ dependencies = [ [project.optional-dependencies] engine-cpu = ["onnxruntime>=1.23"] engine-cuda = ["onnxruntime-gpu[cuda,cudnn]>=1.23"] +engine-cuda-system = ["onnxruntime-gpu>=1.23"] engine-openvino = ["onnxruntime-openvino>=1.23", "openvino>=2025"] desktop = [ @@ -82,7 +83,7 @@ include = ["first_breaks*"] [tool.briefcase] project_name = "FirstBreaksPicking" bundle = "com.example" -version = "0.9.0a2" +version = "0.9.0a3" url = "https://github.com/DaloroAT/first_breaks_picking" license = {file = "LICENSE"} author = "Aleksei Tarasov" @@ -91,21 +92,28 @@ long_description = "Project is devoted to pick waves that are the first to be de # CPU build [tool.briefcase.app.fbcpu] -formal_name = "FirstBreaksPicking (CPU)" +formal_name = "FirstBreaksPicking-CPU" description = "Desktop app for seismic first-breaks-picking (CPU)" sources = ["fbcpu"] requires = [ ".[engine-cpu,desktop]" ] # CUDA build [tool.briefcase.app.fbcuda] -formal_name = "FirstBreaksPicking (CUDA)" +formal_name = "FirstBreaksPicking-CUDA" description = "Desktop app for seismic first-breaks-picking (CUDA)" sources = ["fbcuda"] requires = [ ".[engine-cuda,desktop]" ] +# CUDA build without CUDA+CuDNN libs +[tool.briefcase.app.fbcudasystem] +formal_name = "FirstBreaksPicking-CUDASystem" +description = "Desktop app for seismic first-breaks-picking (CUDA System)" +sources = ["fbcudasystem"] +requires = [ ".[engine-cuda,desktop]" ] + # OpenVINO build [tool.briefcase.app.fbopenvino] -formal_name = "FirstBreaksPicking (OpenVINO)" +formal_name = "FirstBreaksPicking-OpenVINO" description = "Desktop app for seismic first-breaks-picking (OpenVINO)" sources = ["fbopenvino"] requires = [ ".[engine-openvino,desktop]" ] \ No newline at end of file From 82d472834d5dd2b5a9f498ea9b4e47b2fdca356d Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 8 Nov 2025 17:23:42 +0100 Subject: [PATCH 11/15] cuda supported engine without cuda libs --- first_breaks/VERSION | 2 +- pyproject.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/first_breaks/VERSION b/first_breaks/VERSION index f93e85f..8998ed3 100644 --- a/first_breaks/VERSION +++ b/first_breaks/VERSION @@ -1 +1 @@ -0.9.0a3 \ No newline at end of file +0.9.0a4 \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index f86c7b1..bed959f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,7 @@ include = ["first_breaks*"] [tool.briefcase] project_name = "FirstBreaksPicking" bundle = "com.example" -version = "0.9.0a3" +version = "0.9.0a4" url = "https://github.com/DaloroAT/first_breaks_picking" license = {file = "LICENSE"} author = "Aleksei Tarasov" @@ -109,7 +109,7 @@ requires = [ ".[engine-cuda,desktop]" ] formal_name = "FirstBreaksPicking-CUDASystem" description = "Desktop app for seismic first-breaks-picking (CUDA System)" sources = ["fbcudasystem"] -requires = [ ".[engine-cuda,desktop]" ] +requires = [ ".[engine-cuda-system,desktop]" ] # OpenVINO build [tool.briefcase.app.fbopenvino] From 0df77c98b08e7e263ba96c46dfb964f6d3989384 Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 8 Nov 2025 17:32:40 +0100 Subject: [PATCH 12/15] cuda supported engine without cuda libs + add windows path --- .github/workflows/release-workflow.yaml | 3 ++- first_breaks/VERSION | 2 +- first_breaks/__init__.py | 11 +++++++++++ pyproject.toml | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-workflow.yaml b/.github/workflows/release-workflow.yaml index d96fc40..a4a8106 100644 --- a/.github/workflows/release-workflow.yaml +++ b/.github/workflows/release-workflow.yaml @@ -92,7 +92,8 @@ jobs: runs-on: windows-latest strategy: matrix: - flavor: [ cpu, cuda, cudasystem, openvino ] +# flavor: [ cpu, cuda, cudasystem, openvino ] + flavor: [ cudasystem ] steps: - name: Checkout uses: actions/checkout@v4 diff --git a/first_breaks/VERSION b/first_breaks/VERSION index 8998ed3..0286018 100644 --- a/first_breaks/VERSION +++ b/first_breaks/VERSION @@ -1 +1 @@ -0.9.0a4 \ No newline at end of file +0.9.0a5 \ No newline at end of file diff --git a/first_breaks/__init__.py b/first_breaks/__init__.py index 135a8db..910cbf6 100644 --- a/first_breaks/__init__.py +++ b/first_breaks/__init__.py @@ -22,6 +22,17 @@ def is_macos() -> bool: return "darwin" in platform +if is_windows(): + extra_potential_paths = [] + extra_potential_paths.extend(list(Path(r"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA").glob("*"))) + extra_potential_paths.extend(list(Path(r"C:\Program Files\NVIDIA GPU Computing Toolkit").glob("*"))) + extra_potential_paths.extend(list(Path(r"C:\Program Files\NVIDIA\CUDNN").glob("*"))) + extra_potential_paths = [str(p) for p in extra_potential_paths] + separator = ";" + + os.environ["PATH"] = separator.join([os.environ["PATH"]] + extra_potential_paths) + + if is_windows(): base = os.path.dirname(sys.executable) app_pkgs = os.path.join(base, "app_packages") diff --git a/pyproject.toml b/pyproject.toml index bed959f..7994cdf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,7 @@ include = ["first_breaks*"] [tool.briefcase] project_name = "FirstBreaksPicking" bundle = "com.example" -version = "0.9.0a4" +version = "0.9.0a5" url = "https://github.com/DaloroAT/first_breaks_picking" license = {file = "LICENSE"} author = "Aleksei Tarasov" From 6e34e142b536deba5de7607175c5ac46686e644d Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 8 Nov 2025 17:52:13 +0100 Subject: [PATCH 13/15] prepare for pr --- .github/workflows/release-workflow.yaml | 6 ++---- first_breaks/__init__.py | 12 ------------ pyproject.toml | 14 +++----------- tests/test_common/test_readme_examples.py | 2 +- tests/test_desktop/test_main_gui.py | 2 +- 5 files changed, 7 insertions(+), 29 deletions(-) diff --git a/.github/workflows/release-workflow.yaml b/.github/workflows/release-workflow.yaml index a4a8106..361d7c1 100644 --- a/.github/workflows/release-workflow.yaml +++ b/.github/workflows/release-workflow.yaml @@ -2,7 +2,7 @@ name: Release on: push: -# branches: [main] + branches: [main] paths: ['first_breaks/VERSION'] @@ -92,8 +92,7 @@ jobs: runs-on: windows-latest strategy: matrix: -# flavor: [ cpu, cuda, cudasystem, openvino ] - flavor: [ cudasystem ] + flavor: [ cpu, cuda, openvino ] steps: - name: Checkout uses: actions/checkout@v4 @@ -118,7 +117,6 @@ jobs: $app = switch ("${{ matrix.flavor }}") { "cpu" { "fbcpu" } "cuda" { "fbcuda" } - "cudasystem" { "fbcudasystem" } "openvino" { "fbopenvino" } } echo "APP=$app" >> $env:GITHUB_OUTPUT diff --git a/first_breaks/__init__.py b/first_breaks/__init__.py index 910cbf6..274f1e4 100644 --- a/first_breaks/__init__.py +++ b/first_breaks/__init__.py @@ -1,6 +1,5 @@ import os import sys -from pathlib import Path from sys import platform try: @@ -22,17 +21,6 @@ def is_macos() -> bool: return "darwin" in platform -if is_windows(): - extra_potential_paths = [] - extra_potential_paths.extend(list(Path(r"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA").glob("*"))) - extra_potential_paths.extend(list(Path(r"C:\Program Files\NVIDIA GPU Computing Toolkit").glob("*"))) - extra_potential_paths.extend(list(Path(r"C:\Program Files\NVIDIA\CUDNN").glob("*"))) - extra_potential_paths = [str(p) for p in extra_potential_paths] - separator = ";" - - os.environ["PATH"] = separator.join([os.environ["PATH"]] + extra_potential_paths) - - if is_windows(): base = os.path.dirname(sys.executable) app_pkgs = os.path.join(base, "app_packages") diff --git a/pyproject.toml b/pyproject.toml index 7994cdf..0fab8d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,6 @@ dependencies = [ [project.optional-dependencies] engine-cpu = ["onnxruntime>=1.23"] engine-cuda = ["onnxruntime-gpu[cuda,cudnn]>=1.23"] -engine-cuda-system = ["onnxruntime-gpu>=1.23"] engine-openvino = ["onnxruntime-openvino>=1.23", "openvino>=2025"] desktop = [ @@ -92,28 +91,21 @@ long_description = "Project is devoted to pick waves that are the first to be de # CPU build [tool.briefcase.app.fbcpu] -formal_name = "FirstBreaksPicking-CPU" +formal_name = "FirstBreaksPicking (CPU)" description = "Desktop app for seismic first-breaks-picking (CPU)" sources = ["fbcpu"] requires = [ ".[engine-cpu,desktop]" ] # CUDA build [tool.briefcase.app.fbcuda] -formal_name = "FirstBreaksPicking-CUDA" +formal_name = "FirstBreaksPicking (CUDA)" description = "Desktop app for seismic first-breaks-picking (CUDA)" sources = ["fbcuda"] requires = [ ".[engine-cuda,desktop]" ] -# CUDA build without CUDA+CuDNN libs -[tool.briefcase.app.fbcudasystem] -formal_name = "FirstBreaksPicking-CUDASystem" -description = "Desktop app for seismic first-breaks-picking (CUDA System)" -sources = ["fbcudasystem"] -requires = [ ".[engine-cuda-system,desktop]" ] - # OpenVINO build [tool.briefcase.app.fbopenvino] -formal_name = "FirstBreaksPicking-OpenVINO" +formal_name = "FirstBreaksPicking (OpenVINO)" description = "Desktop app for seismic first-breaks-picking (OpenVINO)" sources = ["fbopenvino"] requires = [ ".[engine-openvino,desktop]" ] \ No newline at end of file diff --git a/tests/test_common/test_readme_examples.py b/tests/test_common/test_readme_examples.py index 140b3ed..31e664b 100644 --- a/tests/test_common/test_readme_examples.py +++ b/tests/test_common/test_readme_examples.py @@ -8,7 +8,7 @@ def find_code_block(file: Path, start_indicator: str, end_indicator: str) -> str: - with open(file) as f: + with open(file, encoding="utf-8") as f: text = f.readlines() i = text.index(start_indicator) + 2 diff --git a/tests/test_desktop/test_main_gui.py b/tests/test_desktop/test_main_gui.py index f864c97..871e53b 100644 --- a/tests/test_desktop/test_main_gui.py +++ b/tests/test_desktop/test_main_gui.py @@ -251,7 +251,7 @@ def __set_params(qtbot: QtBot, main_window: MainWindow, gain: float, maximum_tim assert device_widget is not None device_widget.setFocus() - device_widget.setCurrentIndex(device_widget.CPU_INEDX) + device_widget.setCurrentIndex(device_widget.CPU_INDEX) maximum_time_widget.setFocus() qtbot.keyClick(maximum_time_widget, "a", modifier=Qt.ControlModifier) From 4585f95db83d1d63f2d9ba5afe59317f69a26f95 Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 8 Nov 2025 18:00:15 +0100 Subject: [PATCH 14/15] prepare for pr --- .github/workflows/tests-workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests-workflow.yaml b/.github/workflows/tests-workflow.yaml index e8703ea..00c8375 100644 --- a/.github/workflows/tests-workflow.yaml +++ b/.github/workflows/tests-workflow.yaml @@ -33,7 +33,7 @@ jobs: - name: Install project run: | python -m pip install --upgrade pip - pip install .[standard] + pip install .[standard,dev] - name: Tests run: make run_tests From 1248903ef1985ba735680f56e003f8ce57fe7a0b Mon Sep 17 00:00:00 2001 From: DaloroAT Date: Sat, 8 Nov 2025 18:11:30 +0100 Subject: [PATCH 15/15] readme path --- tests/test_common/test_readme_examples.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/test_common/test_readme_examples.py b/tests/test_common/test_readme_examples.py index 31e664b..d40f611 100644 --- a/tests/test_common/test_readme_examples.py +++ b/tests/test_common/test_readme_examples.py @@ -4,8 +4,6 @@ import pytest -from first_breaks.const import PROJECT_ROOT - def find_code_block(file: Path, start_indicator: str, end_indicator: str) -> str: with open(file, encoding="utf-8") as f: @@ -19,6 +17,13 @@ def find_code_block(file: Path, start_indicator: str, end_indicator: str) -> str return code_block +@pytest.fixture(scope="session") +def readme_path(pytestconfig: pytest.Config) -> Path: + p = Path(pytestconfig.rootpath) / "README.md" + assert p.exists(), f"README.md not found at {p}" + return p + + @pytest.mark.parametrize( "block_name", [ @@ -39,14 +44,14 @@ def find_code_block(file: Path, start_indicator: str, end_indicator: str) -> str "plot-sgy-real-picks", ], ) -def test_code_blocks_in_readme(block_name: str, demo_sgy: Path, logs_dir_for_tests: Path) -> None: +def test_code_blocks_in_readme(block_name: str, demo_sgy: Path, logs_dir_for_tests: Path, readme_path: Path) -> None: assert logs_dir_for_tests.exists() os.chdir(str(logs_dir_for_tests)) shutil.copyfile(str(demo_sgy), str(logs_dir_for_tests / "data.sgy")) start_indicator = f"[code-block-start]:{block_name}\n" end_indicator = f"[code-block-end]:{block_name}\n" - code = find_code_block(PROJECT_ROOT / "README.md", start_indicator, end_indicator) + code = find_code_block(readme_path, start_indicator, end_indicator) assert code tmp_fname = f"{block_name}.py"