fullwave25 1.2.2.dev0__tar.gz → 1.2.3.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/.bumpversion.toml +1 -1
  2. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/PKG-INFO +1 -1
  3. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/__init__.py +1 -1
  4. fullwave25-1.2.3.dev1/fullwave/solver/binary_manager.py +145 -0
  5. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/solver/solver.py +3 -1
  6. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/pyproject.toml +2 -2
  7. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/uv.lock +1 -1
  8. fullwave25-1.2.2.dev0/fullwave/solver/bins/exponential_attenuation/gpu/2d/fullwave2_2d_exponential_attenuation_multi_gpu_cuda118 +0 -0
  9. fullwave25-1.2.2.dev0/fullwave/solver/bins/exponential_attenuation/gpu/2d/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  10. fullwave25-1.2.2.dev0/fullwave/solver/bins/exponential_attenuation/gpu/2d/fullwave2_2d_exponential_attenuation_multi_gpu_cuda129 +0 -0
  11. fullwave25-1.2.2.dev0/fullwave/solver/bins/exponential_attenuation/gpu/2d/fullwave2_2d_exponential_attenuation_multi_gpu_cuda130 +0 -0
  12. fullwave25-1.2.2.dev0/fullwave/solver/bins/exponential_attenuation/gpu/3d/fullwave2_3d_exponential_attenuation_multi_gpu_cuda118 +0 -0
  13. fullwave25-1.2.2.dev0/fullwave/solver/bins/exponential_attenuation/gpu/3d/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  14. fullwave25-1.2.2.dev0/fullwave/solver/bins/exponential_attenuation/gpu/3d/fullwave2_3d_exponential_attenuation_multi_gpu_cuda129 +0 -0
  15. fullwave25-1.2.2.dev0/fullwave/solver/bins/exponential_attenuation/gpu/3d/fullwave2_3d_exponential_attenuation_multi_gpu_cuda130 +0 -0
  16. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/.gitignore +0 -0
  17. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/.pre-commit-config.yaml +0 -0
  18. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/.python-version +0 -0
  19. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/20260120_0844.log +0 -0
  20. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/CITATION.cff +0 -0
  21. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/CLAUDE.md +0 -0
  22. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/CONTRIBUTING.md +0 -0
  23. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/LICENSE +0 -0
  24. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/Makefile +0 -0
  25. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/README.md +0 -0
  26. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/beamformer.m +0 -0
  27. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/experiments/__init__.py +0 -0
  28. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/experiments/exp_scatterer_diameter.py +0 -0
  29. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/beamformer/__init__.py +0 -0
  30. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/beamformer/beamformer.py +0 -0
  31. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/constants/__init__.py +0 -0
  32. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/constants/material_properties.py +0 -0
  33. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/grid.py +0 -0
  34. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium.py +0 -0
  35. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/__init__.py +0 -0
  36. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/domain.py +0 -0
  37. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/medium_builder.py +0 -0
  38. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/presets/__init__.py +0 -0
  39. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/presets/data/.keep +0 -0
  40. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/presets/data/abdominal_wall/i2365f_etfw1.mat +0 -0
  41. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/presets/domain_abdominal_wall.py +0 -0
  42. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/presets/domain_background.py +0 -0
  43. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/presets/domain_scatterer.py +0 -0
  44. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/presets/domain_simple.py +0 -0
  45. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/medium_builder/presets/domain_water_gel.py +0 -0
  46. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/sensor.py +0 -0
  47. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/solver/__init__.py +0 -0
  48. {fullwave25-1.2.2.dev0/fullwave/solver/bins/gpu → fullwave25-1.2.3.dev1/fullwave/solver/bins/_gpu}/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda118 +0 -0
  49. {fullwave25-1.2.2.dev0/fullwave/solver/bins/gpu → fullwave25-1.2.3.dev1/fullwave/solver/bins/_gpu}/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
  50. {fullwave25-1.2.2.dev0/fullwave/solver/bins/gpu → fullwave25-1.2.3.dev1/fullwave/solver/bins/_gpu}/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda129 +0 -0
  51. {fullwave25-1.2.2.dev0/fullwave/solver/bins/gpu → fullwave25-1.2.3.dev1/fullwave/solver/bins/_gpu}/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda130 +0 -0
  52. {fullwave25-1.2.2.dev0/fullwave/solver/bins/gpu → fullwave25-1.2.3.dev1/fullwave/solver/bins/_gpu}/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda118 +0 -0
  53. {fullwave25-1.2.2.dev0/fullwave/solver/bins/gpu → fullwave25-1.2.3.dev1/fullwave/solver/bins/_gpu}/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda124 +0 -0
  54. {fullwave25-1.2.2.dev0/fullwave/solver/bins/gpu → fullwave25-1.2.3.dev1/fullwave/solver/bins/_gpu}/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda129 +0 -0
  55. {fullwave25-1.2.2.dev0/fullwave/solver/bins/gpu → fullwave25-1.2.3.dev1/fullwave/solver/bins/_gpu}/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda130 +0 -0
  56. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/solver/bins/database/relaxation_params_database_num_relax=2_20260113_0957.mat +0 -0
  57. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/solver/cuda_utils.py +0 -0
  58. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/solver/input_file_writer.py +0 -0
  59. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/solver/launcher.py +0 -0
  60. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/solver/pml_builder.py +0 -0
  61. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/solver/utils.py +0 -0
  62. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/source.py +0 -0
  63. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/transducer.py +0 -0
  64. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/__init__.py +0 -0
  65. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/check_functions.py +0 -0
  66. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/coordinates.py +0 -0
  67. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/memory_tempfile.py +0 -0
  68. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/numerical.py +0 -0
  69. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/plot_utils.py +0 -0
  70. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/pulse.py +0 -0
  71. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/relaxation_parameters.py +0 -0
  72. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/scatterer.py +0 -0
  73. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/fullwave/utils/signal_process.py +0 -0
  74. {fullwave25-1.2.2.dev0 → fullwave25-1.2.3.dev1}/ruff.toml +0 -0
@@ -1,5 +1,5 @@
1
1
  [tool.bumpversion]
2
- current_version = "1.2.2-dev0"
2
+ current_version = "1.2.3-dev1"
3
3
  parse = """(?x)
4
4
  (?P<major>0|[1-9]\\d*)\\.
5
5
  (?P<minor>0|[1-9]\\d*)\\.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fullwave25
3
- Version: 1.2.2.dev0
3
+ Version: 1.2.3.dev1
4
4
  Summary: Fullwave 2.5: Ultrasound wave propagation simulation with heterogeneous power law attenuation modelling capabilities
5
5
  Author: Masashi Sode, Gianmarco Pinton
6
6
  Maintainer: Masashi Sode
@@ -60,7 +60,7 @@ try:
60
60
  __version__ = version("fullwave")
61
61
  except PackageNotFoundError:
62
62
  # Update via bump-my-version, not manually
63
- __version__ = "1.2.2-dev0"
63
+ __version__ = "1.2.3-dev1"
64
64
 
65
65
  VERSION = __version__ # for convenience
66
66
  logger.info("Fullwave version: %s", __version__)
@@ -0,0 +1,145 @@
1
+ """Binary manager for fullwave solver executables.
2
+
3
+ Handles locating, caching, and downloading solver binaries from GitHub releases.
4
+
5
+ Priority order when resolving a binary:
6
+ 1. Bundled binary (shipped with the package or dev install).
7
+ 2. Local cache at ``~/.cache/fullwave25/bins/``.
8
+ 3. Download from the GitHub release pinned by ``BINARY_RELEASE_TAG``.
9
+
10
+ Binaries are versioned independently from the Python package — update
11
+ ``BINARY_RELEASE_TAG`` only when new binaries are published.
12
+
13
+ The release tag can be overridden at runtime with the environment variable
14
+ ``FULLWAVE25_BINARY_TAG`` (e.g. ``export FULLWAVE25_BINARY_TAG=v1.2.2``).
15
+ """
16
+
17
+ import logging
18
+ import os
19
+ import stat
20
+ import urllib.error
21
+ import urllib.request
22
+ from pathlib import Path
23
+
24
+ logger = logging.getLogger("__main__." + __name__)
25
+
26
+ GITHUB_REPO = "pinton-lab/fullwave25"
27
+ CACHE_DIR = Path.home() / ".cache" / "fullwave25" / "bins"
28
+
29
+ # Pinned release tag for the solver binaries.
30
+ # Update this only when new binaries are uploaded to a GitHub release.
31
+ BINARY_RELEASE_TAG = "v1.2.2"
32
+
33
+
34
+ def _download_url(filename: str, tag: str) -> str:
35
+ return f"https://github.com/{GITHUB_REPO}/releases/download/{tag}/{filename}"
36
+
37
+
38
+ def _download_binary(url: str, dest: Path) -> None:
39
+ """Download *url* to *dest*, showing a tqdm progress bar when available."""
40
+ dest.parent.mkdir(parents=True, exist_ok=True)
41
+ tmp = dest.with_suffix(".download_tmp")
42
+ try:
43
+ try:
44
+ from tqdm import tqdm
45
+
46
+ class _Hook:
47
+ def __init__(self) -> None:
48
+ self._bar: tqdm | None = None
49
+
50
+ def __call__(self, block: int, block_size: int, total: int) -> None: # noqa: ARG002
51
+ if self._bar is None:
52
+ self._bar = tqdm(
53
+ total=total if total > 0 else None,
54
+ unit="B",
55
+ unit_scale=True,
56
+ desc=dest.name,
57
+ )
58
+ self._bar.update(block_size)
59
+
60
+ def close(self) -> None:
61
+ if self._bar is not None:
62
+ self._bar.close()
63
+
64
+ hook = _Hook()
65
+ try:
66
+ urllib.request.urlretrieve(url, tmp, reporthook=hook) # noqa: S310
67
+ finally:
68
+ hook.close()
69
+
70
+ except ImportError:
71
+ urllib.request.urlretrieve(url, tmp) # noqa: S310
72
+
73
+ tmp.rename(dest)
74
+ dest.chmod(dest.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
75
+ logger.info("Binary saved to %s", dest)
76
+
77
+ except Exception:
78
+ tmp.unlink(missing_ok=True)
79
+ raise
80
+
81
+
82
+ def ensure_binary(local_path: Path) -> Path:
83
+ """Return an executable path for the solver binary.
84
+
85
+ Parameters
86
+ ----------
87
+ local_path:
88
+ The expected bundled path (as computed by ``_retrieve_fullwave_simulation_path``).
89
+
90
+ Returns
91
+ -------
92
+ Path
93
+ Resolved path to an executable binary.
94
+
95
+ Raises
96
+ ------
97
+ RuntimeError
98
+ If the binary cannot be found locally and the download fails.
99
+
100
+ """
101
+ # 1. Bundled binary present (dev install or package that still ships binaries).
102
+ if local_path.exists():
103
+ logger.debug("Using bundled binary: %s", local_path)
104
+ return local_path
105
+
106
+ filename = local_path.name
107
+ cached = CACHE_DIR / filename
108
+
109
+ # 2. Previously downloaded and cached.
110
+ if cached.exists():
111
+ logger.debug("Using cached binary: %s", cached)
112
+ return cached
113
+
114
+ # 3. Download from GitHub releases.
115
+ tag = os.environ.get("FULLWAVE25_BINARY_TAG", BINARY_RELEASE_TAG)
116
+ url = _download_url(filename, tag)
117
+
118
+ logger.info(
119
+ "Binary '%s' not found locally. Downloading from GitHub release '%s' …",
120
+ filename,
121
+ tag,
122
+ )
123
+
124
+ try:
125
+ _download_binary(url, cached)
126
+ except urllib.error.HTTPError as e:
127
+ msg = (
128
+ f"Could not download binary '{filename}' from:\n {url}\n"
129
+ f"HTTP error: {e.code} {e.reason}\n\n"
130
+ "Possible fixes:\n"
131
+ f" • Check that release '{tag}' exists and contains '{filename}'.\n"
132
+ f" • Override the tag: export FULLWAVE25_BINARY_TAG=<tag>\n"
133
+ f" • Place the binary manually at: {cached}\n"
134
+ )
135
+ raise RuntimeError(msg) from e
136
+ except Exception as e:
137
+ msg = (
138
+ f"Failed to download binary '{filename}' from:\n {url}\n"
139
+ f"Error: {e}\n\n"
140
+ f" • Place the binary manually at: {cached}\n"
141
+ f" • Or override the tag: export FULLWAVE25_BINARY_TAG=<tag>\n"
142
+ )
143
+ raise RuntimeError(msg) from e
144
+
145
+ return cached
@@ -16,6 +16,7 @@ from fullwave.utils import (
16
16
  check_functions,
17
17
  )
18
18
 
19
+ from .binary_manager import ensure_binary
19
20
  from .cuda_utils import get_cuda_architecture, retrieve_cuda_version
20
21
 
21
22
  logger = logging.getLogger("__main__." + __name__)
@@ -461,13 +462,14 @@ class Solver:
461
462
  self.n_relax_mechanisms = medium.n_relaxation_mechanisms
462
463
 
463
464
  if path_fullwave_simulation_bin is None:
464
- path_fullwave_simulation_bin = _retrieve_fullwave_simulation_path(
465
+ local_path = _retrieve_fullwave_simulation_path(
465
466
  use_gpu=use_gpu,
466
467
  is_3d=self.is_3d,
467
468
  use_exponential_attenuation=self.use_exponential_attenuation,
468
469
  use_isotropic_relaxation=use_isotropic_relaxation,
469
470
  n_relax_mechanisms=self.n_relax_mechanisms,
470
471
  )
472
+ path_fullwave_simulation_bin = ensure_binary(local_path)
471
473
  else:
472
474
  check_functions.check_path_exists(path_fullwave_simulation_bin)
473
475
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fullwave25"
3
- version = "1.2.2-dev0" # Update via bump-my-version, not manually
3
+ version = "1.2.3-dev1" # Update via bump-my-version, not manually
4
4
  description = "Fullwave 2.5: Ultrasound wave propagation simulation with heterogeneous power law attenuation modelling capabilities"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -57,4 +57,4 @@ build-backend = "hatchling.build"
57
57
  packages = ["fullwave", "fullwave.utils"]
58
58
 
59
59
  [tool.hatch.build]
60
- exclude = ["tests", "figs", "examples", ".vscode", ".github"]
60
+ exclude = ["tests", "figs", "examples", ".vscode", ".github", "fullwave/solver/bins/gpu", "fullwave/solver/bins/exponential_attenuation", "fullwave/solver/bins/_exponential_attenuation"]
@@ -735,7 +735,7 @@ wheels = [
735
735
 
736
736
  [[package]]
737
737
  name = "fullwave25"
738
- version = "1.2.2.dev0"
738
+ version = "1.2.3.dev1"
739
739
  source = { editable = "." }
740
740
  dependencies = [
741
741
  { name = "joblib" },
File without changes