Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/pip/scipy-1.14.1
Browse files Browse the repository at this point in the history
  • Loading branch information
waltsims authored Nov 12, 2024
2 parents cf93463 + 405aea4 commit 01b693c
Show file tree
Hide file tree
Showing 14 changed files with 678 additions and 144 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
strategy:
matrix:
os: [ "windows-latest", "ubuntu-latest" , "macos-latest"]
python-version: [ "3.9", "3.10", "3.11", "3.12" ]
python-version: [ "3.10", "3.11", "3.12", "3.13" ]
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
strategy:
matrix:
os: [ "windows-latest", "ubuntu-latest" , "macos-latest"]
python-version: [ "3.9", "3.10", "3.11", "3.12"]
python-version: [ "3.10", "3.11", "3.12", "3.13" ]
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
fetch-depth: 0 # otherwise, you will fail to push refs to dest repo
- uses: actions/setup-python@v5
with:
python-version: '3.9'
python-version: '3.10'
cache: 'pip'
- name: Build and Commit
uses: waltsims/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 2
build:
os: ubuntu-22.04
tools:
python: "3.9"
python: "3.11"
sphinx:
configuration: docs/conf.py
python:
Expand Down
23 changes: 12 additions & 11 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ Every example has a short readme.md file which briefly describes the purpose of
- [Array as a sensor](at_array_as_sensor/) ([original example](http://www.k-wave.org/documentation/example_at_array_as_sensor.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/at_array_as_sensor/at_array_as_sensor.ipynb))
- [Array as a source](at_array_as_source/) ([original example](http://www.k-wave.org/documentation/example_at_array_as_source.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/at_array_as_source/at_array_as_source.ipynb))
- [Linear array transducer](at_linear_array_transducer/)
([original example](http://www.k-wave.org/documentation/example_at_linear_array_transducer.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/at_linear_array_transducer/at_linear_array_transducer.ipynb))
([original example](http://www.k-wave.org/documentation/example_at_linear_array_transducer.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/at_linear_array_transducer/at_linear_array_transducer.ipynb))
- [Photoacoustic Waveforms](ivp_photoacoustic_waveforms/) ([original example](http://www.k-wave.org/documentation/example_ivp_photoacoustic_waveforms.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/ivp_photoacoustic_waveforms/ivp_photoacoustic_waveforms.ipynb))
- [Controlling the PML](na_controlling_the_pml/)
([original example](http://www.k-wave.org/documentation/example_na_controlling_the_pml.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/na_controlling_the_pml/na_controlling_the_pml.ipynb))
([original example](http://www.k-wave.org/documentation/example_na_controlling_the_pml.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/na_controlling_the_pml/na_controlling_the_pml.ipynb))
- [Defining An Ultrasound Transducer Example](us_defining_transducer) ([original example](http://www.k-wave.org/documentation/example_us_defining_transducer.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/us_defining_transducer/us_defining_transducer.ipynb))
- [Simulating Ultrasound Beam Patterns](us_beam_patterns/)([original example](http://www.k-wave.org/documentation/example_us_beam_patterns), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/us_beam_patterns/us_beam_patterns.ipynb))
- [Linear transducer B-mode](us_bmode_linear_transducer/) ([original example](http://www.k-wave.org/documentation/example_us_bmode_linear_transducer.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/us_bmode_linear_transducer/us_bmode_linear_transducer.ipynb))
- [Phased array B-mode](us_bmode_phased_array/)
([original example](http://www.k-wave.org/documentation/example_us_bmode_phased_array.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/us_bmode_phased_array/us_bmode_phased_array.ipynb))
([original example](http://www.k-wave.org/documentation/example_us_bmode_phased_array.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/us_bmode_phased_array/us_bmode_phased_array.ipynb))
- [Circular piston transducer](at_circular_piston_3D/) ([original example](http://www.k-wave.org/documentation/example_at_piston_and_bowl_transducers.php#heading3), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/at_circular_piston_3D/at_circular_piston_3D.ipynb))

- [Circular piston transducer (axisymmetric)](at_circular_piston_AS/) ([original example](http://www.k-wave.org/documentation/example_at_piston_and_bowl_transducers.php#heading4), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/at_circular_piston_AS/at_circular_piston_AS.ipynb))
Expand All @@ -32,20 +32,21 @@ Every example has a short readme.md file which briefly describes the purpose of

- [Focussed Detector In 3D Example](sd_focussed_detector_3D/) ([original example](http://www.k-wave.org/documentation/example_sd_focussed_detector_3D.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/sd_focussed_detector_3D/sd_focussed_detector_3D.ipynb))

- [Modelling Sensor Directivity In 2D Example](sd_directivity_modelling_2D/) ([original example](http://www.k-wave.org/documentation/example_sd_directivity_modelling_2D.php), [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/sd_directivity_modelling_2D/sd_directivity_modelling_2D.ipynb))

## Contributing new examples

When adding a new example notebook, follow these steps:

1. Search the [list of examples](https://docs.google.com/spreadsheets/d/1-x13iIez84AEyjjHMOe2GoC8FSyzUFHoy9R7VKttTlo/edit?usp=sharing) to find an open example.
1. Claim your example by opening an "Example" issue on GitHub.
3. Fork and clone the repository and create a branch for your new example.
2. Create an example sub-directory using the name from the hyperlink of the original k-wave example if it exists (e.g. for http://www.k-wave.org/documentation/example_ivp_loading_external_image.php name the directory "ivp_loading_external_image).
3. Add your example notebook to your example directory.
4. Create a Python script that mirrors your example notebook in the same directory. Using `nbconvert` is an easy way to convert to a Python script using ` jupyter nbconvert --to python --RegexRemovePreprocessor.patterns="^%" <notebook_path>`
5. Add a README.md file to your example directory briefly describing the concept or principle the example is meant to display and linking to the origonal k-wave example page if it exists.
6. Include a link in the `README.md` in the examples directory to a colab notebook for your example.
7. Add a your example to the list on this `README.md` and add a colab badge [using html](https://openincolab.com/) OR copy the pure markdown version above.
8. Open a pull request that [closes the open issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) from your forked example branch and name pull request "[Example] \<name of your example\>".
1. Fork and clone the repository and create a branch for your new example.
1. Create an example sub-directory using the name from the hyperlink of the original k-wave example if it exists (e.g. for http://www.k-wave.org/documentation/example_ivp_loading_external_image.php name the directory "ivp_loading_external_image).
1. Add your example notebook to your example directory.
1. Create a Python script that mirrors your example notebook in the same directory. Using `nbconvert` is an easy way to convert to a Python script using ` jupyter nbconvert --to python --RegexRemovePreprocessor.patterns="^%" <notebook_path>`
1. Add a README.md file to your example directory briefly describing the concept or principle the example is meant to display and linking to the origonal k-wave example page if it exists.
1. Include a link in the `README.md` in the examples directory to a colab notebook for your example.
1. Add a your example to the list on this `README.md` and add a colab badge [using html](https://openincolab.com/) OR copy the pure markdown version above.
1. Open a pull request that [closes the open issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) from your forked example branch and name pull request "[Example] \<name of your example\>".

Thanks for contributing to k-wave-python!
7 changes: 7 additions & 0 deletions examples/sd_directivity_modelling_2D/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Modelling Sensor Directivity In 2D Example

[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/waltsims/k-wave-python/blob/master/examples/sd_directivity_modelling_2D/sd_directivity_modelling_2D.ipynb)

This example demonstrates how the sensitivity of a large single element detector varies with the angular position of a point-like source.

To read more, visit the [original example page](http://www.k-wave.org/documentation/example_sd_directivity_modelling_2D.php).
244 changes: 244 additions & 0 deletions examples/sd_directivity_modelling_2D/sd_directivity_modelling_2D.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install git+https://github.com/waltsims/k-wave-python "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Modelling Sensor Directivity In 2D Example\n",
"\n",
"This example demonstrates how the sensitivity of a large single element detector varies with the angular position of a point-like source."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"import os\n",
"from copy import deepcopy\n",
"from tempfile import gettempdir\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"from kwave.data import Vector\n",
"from kwave.kgrid import kWaveGrid\n",
"from kwave.kmedium import kWaveMedium\n",
"from kwave.ksensor import kSensor\n",
"from kwave.ksource import kSource\n",
"from kwave.kspaceFirstOrder2D import kspaceFirstOrder2DC\n",
"from kwave.options.simulation_execution_options import SimulationExecutionOptions\n",
"from kwave.options.simulation_options import SimulationOptions\n",
"from kwave.utils.conversion import cart2grid\n",
"from kwave.utils.filters import filter_time_series\n",
"from kwave.utils.mapgen import make_cart_circle\n",
"from kwave.utils.matlab import ind2sub, matlab_find, unflatten_matlab_mask\n",
"from kwave.utils.colormap import get_color_map\n",
"from kwave.utils.data import scale_SI"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Create the computational grid and medium"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"grid_size_points = Vector([128, 128]) # [grid points]\n",
"grid_size_meters = Vector([50e-3, 50e-3]) # [m]\n",
"grid_spacing_meters = grid_size_meters / grid_size_points # [m]\n",
"kgrid = kWaveGrid(grid_size_points, grid_spacing_meters)\n",
"\n",
"# define the properties of the propagation medium\n",
"medium = kWaveMedium(sound_speed=1500)\n",
"\n",
"# define the array of time points [s]\n",
"Nt = 350\n",
"dt = 7e-8 # [s]\n",
"kgrid.setTime(Nt, dt)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define a large area detector"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sz = 20 # [grid points]\n",
"sensor_mask = np.zeros(grid_size_points)\n",
"sensor_mask[grid_size_points.x // 2, (grid_size_points.y // 2 - sz // 2) : (grid_size_points.y // 2 + sz // 2) + 1] = 1\n",
"sensor = kSensor(sensor_mask)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define a time varying sinusoidal source"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# define equally spaced point sources lying on a circle centred at the\n",
"# centre of the detector face\n",
"radius = 30 # [grid points]\n",
"points = 11\n",
"circle = make_cart_circle(radius * grid_spacing_meters.x, points, Vector([0, 0]), np.pi)\n",
"\n",
"# find the binary sensor mask most closely corresponding to the Cartesian\n",
"# coordinates from makeCartCircle\n",
"circle, _, _ = cart2grid(kgrid, circle)\n",
"\n",
"# find the indices of the sources in the binary source mask\n",
"source_positions = matlab_find(circle, val=1, mode=\"eq\")\n",
"\n",
"source = kSource()\n",
"source_freq = 0.25e6 # [Hz]\n",
"source_mag = 1 # [Pa]\n",
"source.p = source_mag * np.sin(2 * np.pi * source_freq * kgrid.t_array)\n",
"\n",
"# filter the source to remove high frequencies not supported by the grid\n",
"source.p = filter_time_series(kgrid, medium, source.p)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define simulation parameters and run simulations"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# pre-allocate array for storing the output time series\n",
"single_element_data = np.zeros((Nt, points)) # noqa: F841\n",
"\n",
"# run a simulation for each of these sources to see the effect that the\n",
"# angle from the detector has on the measured signal\n",
"for source_loop in range(points):\n",
" # select a point source\n",
" source.p_mask = np.zeros(grid_size_points)\n",
" source.p_mask[unflatten_matlab_mask(source.p_mask, source_positions[source_loop] - 1)] = 1\n",
"\n",
" # run the simulation\n",
"\n",
" input_filename = f\"example_input_{source_loop + 1}_input.h5\"\n",
" pathname = gettempdir()\n",
" input_file_full_path = os.path.join(pathname, input_filename)\n",
" simulation_options = SimulationOptions(save_to_disk=True, input_filename=input_filename, data_path=pathname)\n",
" # run the simulation\n",
" sensor_data = kspaceFirstOrder2DC(\n",
" medium=medium,\n",
" kgrid=kgrid,\n",
" source=deepcopy(source),\n",
" sensor=deepcopy(sensor),\n",
" simulation_options=simulation_options,\n",
" execution_options=SimulationExecutionOptions(),\n",
" )\n",
" single_element_data[:, source_loop] = sensor_data['p'].sum(axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Visualize recorded data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure()\n",
"plt.imshow(circle + sensor.mask, \n",
" extent=[\n",
" kgrid.y_vec.min() * 1e3, kgrid.y_vec.max() * 1e3, \n",
" kgrid.x_vec.max() * 1e3, kgrid.x_vec.min() * 1e3], vmin=-1, vmax=1, cmap=get_color_map())\n",
"plt.ylabel('x-position [mm]')\n",
"plt.xlabel('y-position [mm]')\n",
"plt.axis('image')\n",
"\n",
"_, t_scale, t_prefix, _ = scale_SI(kgrid.t_array[-1])\n",
"\n",
"# Plot the time series recorded for each of the sources\n",
"plt.figure()\n",
"# Loop through each source and plot individually\n",
"for i in range(single_element_data.shape[1]):\n",
" plt.plot((kgrid.t_array * t_scale).squeeze(), single_element_data[:, i], label=f'Source {i+1}')\n",
"\n",
"plt.xlabel(f'Time [{t_prefix}s]')\n",
"plt.ylabel('Pressure [au]')\n",
"plt.title('Time Series For Each Source Direction')\n",
"\n",
"\n",
"# Calculate angle between source and center of detector face\n",
"angles = []\n",
"for source_position in source_positions:\n",
" x, y = ind2sub(kgrid.y.shape, source_position)\n",
" angles.append(np.arctan(kgrid.y[x, y] / kgrid.x[x, y]))\n",
"\n",
"# Plot the maximum amplitudes for each of the sources\n",
"plt.figure()\n",
"plt.plot(angles, np.max(single_element_data[200:350, :], axis=0), 'o', mfc='none')\n",
"plt.xlabel('Angle Between Source and Centre of Detector Face [rad]')\n",
"plt.ylabel('Maximum Detected Pressure [au]')\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "env_kwave",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading

0 comments on commit 01b693c

Please sign in to comment.