Skip to content

Commit

Permalink
Merge branch 'master' into feature/run_all_examples
Browse files Browse the repository at this point in the history
  • Loading branch information
waltsims authored Nov 2, 2024
2 parents e2a4d60 + 702556e commit 2b43725
Show file tree
Hide file tree
Showing 17 changed files with 1,073 additions and 81 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

# Virtual environments
.venv/
venv/

# Compiled files
*.pyc
Expand Down
10 changes: 6 additions & 4 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Every example has a short readme.md file which briefly describes the purpose of
- [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))
- [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))
Expand All @@ -25,9 +26,10 @@ Every example has a short readme.md file which briefly describes the purpose of

- [Focused bowl transducer (axisymmetric)](at_focused_bowl_AS/) ([original example](http://www.k-wave.org/documentation/example_at_piston_and_bowl_transducers.php#heading6), [![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_focused_bowl_AS/at_focused_bowl_AS.ipynb))


- [Focused annular array](at_focused_annular_array_3D/) ([original example](http://www.k-wave.org/documentation/example_at_piston_and_bowl_transducers.php#heading7), [![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_focused_annular_array_3D/at_focused_annular_array_3D.ipynb))

- [Focussed Detector In 2D Example](at_focused_annular_array_3D/) ([original example](http://www.k-wave.org/documentation/example_sd_focussed_detector_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_focussed_detector_2D/sd_focussed_detector_2D.ipynb))


## Contributing new examples

Expand All @@ -38,10 +40,10 @@ When adding a new example notebook, follow these steps:
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.
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.
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\>".

Thanks for contributing to k-wave-python!
7 changes: 7 additions & 0 deletions examples/sd_focussed_detector_2D/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Focussed Detector 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_focussed_detector_2D/sd_focussed_detector_2D.ipynb)

This example shows how k-Wave-python can be used to model the output of a focussed semicircular detector where the directionality arises from spatially averaging across the detector surface.

To read more, visit the [original example page](http://www.k-wave.org/documentation/example_sd_focussed_detector_2D.php).
207 changes: 207 additions & 0 deletions examples/sd_focussed_detector_2D/sd_focussed_detector_2D.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
{
"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": [
"# Focussed Detector In 2D Example\n",
"This example shows how k-Wave-python can be used to model the output of a focused semicircular detector, where the directionality arises from spatially averaging across the detector surface. Unlike the original example in k-Wave, this example does not visualize the simulation, as this functionality is not intrinsically supported by the accelerated binaries."
]
},
{
"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.ksource import kSource\n",
"from kwave.kspaceFirstOrder2D import kspaceFirstOrder2DC\n",
"from kwave.ktransducer import kSensor\n",
"from kwave.options.simulation_execution_options import SimulationExecutionOptions\n",
"from kwave.options.simulation_options import SimulationOptions\n",
"from kwave.utils.mapgen import make_disc, make_circle\n",
"from kwave.utils.data import scale_SI\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# create the computational grid\n",
"grid_size = Vector([180, 180]) # [grid points]\n",
"grid_spacing = Vector([0.1e-3, 0.1e-3]) # [m]\n",
"kgrid = kWaveGrid(grid_size, grid_spacing)\n",
"\n",
"# define the properties of the propagation medium\n",
"medium = kWaveMedium(sound_speed=1500)\n",
"\n",
"# define a sensor as part of a circle centred on the grid\n",
"sensor_radius = 65 # [grid points]\n",
"arc_angle = np.pi # [rad]\n",
"sensor_mask = make_circle(grid_size, grid_size // 2 + 1, sensor_radius, arc_angle)\n",
"sensor = kSensor(sensor_mask)\n",
"\n",
"# define the array of temporal points\n",
"t_end = 11e-6 # [s]\n",
"_ = kgrid.makeTime(medium.sound_speed, t_end=t_end)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define simulation parameters"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"input_filename = \"example_sd_focused_2d_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)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Run simulation with first source"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# place a disc-shaped source near the focus of the detector\n",
"source = kSource()\n",
"source.p0 = 2 * make_disc(grid_size, grid_size / 2, 4)\n",
"\n",
"# run the simulation\n",
"sensor_data1 = kspaceFirstOrder2DC(\n",
" medium=medium,\n",
" kgrid=kgrid,\n",
" source=deepcopy(source),\n",
" sensor=sensor,\n",
" simulation_options=simulation_options,\n",
" execution_options=SimulationExecutionOptions(),\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sensor_data1['p'].shape\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Run simulation with second source"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# place a disc-shaped source horizontally shifted from the focus of the detector\n",
"source.p0 = 2 * make_disc(grid_size, grid_size / 2 + [0, 20], 4)\n",
"\n",
"sensor_data2 = kspaceFirstOrder2DC(\n",
" medium=medium,\n",
" kgrid=kgrid,\n",
" source=deepcopy(source),\n",
" sensor=sensor,\n",
" simulation_options=simulation_options,\n",
" execution_options=SimulationExecutionOptions(),\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Visualize recorded data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sensor_output1 = np.sum(sensor_data1['p'], axis=1) / np.sum(sensor.mask)\n",
"sensor_output2 = np.sum(sensor_data2['p'], axis=1) / np.sum(sensor.mask)\n",
"\n",
"t_sc, t_scale, t_prefix, _ = scale_SI(t_end)\n",
"t_array = kgrid.t_array.squeeze() * t_scale\n",
"\n",
"plt.plot(t_array, sensor_output1, 'k')\n",
"plt.plot(t_array, sensor_output2, 'r')\n",
"\n",
"plt.xlabel('Time [' + t_prefix + 's]')\n",
"plt.ylabel('Average Pressure Measured Over Detector [au]')\n",
"plt.legend([\n",
" f\"Source on focus, sum(output^2) = {round(np.sum(sensor_output1**2) * 100) / 100}\",\n",
" f\"Source off focus, sum(output^2) = {round(np.sum(sensor_output2**2) * 100) / 100}\"\n",
"])\n",
"\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
}
108 changes: 108 additions & 0 deletions examples/sd_focussed_detector_2D/sd_focussed_detector_2D.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# # Focussed Detector In 2D Example
# This example shows how k-Wave-python can be used to model the output of a focused semicircular detector, where the directionality arises from spatially averaging across the detector surface. Unlike the original example in k-Wave, this example does not visualize the simulation, as this functionality is not intrinsically supported by the accelerated binaries.

import os
from copy import deepcopy
from tempfile import gettempdir

import numpy as np
import matplotlib.pyplot as plt

from kwave.data import Vector
from kwave.kgrid import kWaveGrid
from kwave.kmedium import kWaveMedium
from kwave.ksource import kSource
from kwave.kspaceFirstOrder2D import kspaceFirstOrder2DC
from kwave.ktransducer import kSensor
from kwave.options.simulation_execution_options import SimulationExecutionOptions
from kwave.options.simulation_options import SimulationOptions
from kwave.utils.mapgen import make_disc, make_circle
from kwave.utils.data import scale_SI


# In[3]:


# create the computational grid
grid_size = Vector([180, 180]) # [grid points]
grid_spacing = Vector([0.1e-3, 0.1e-3]) # [m]
kgrid = kWaveGrid(grid_size, grid_spacing)

# define the properties of the propagation medium
medium = kWaveMedium(sound_speed=1500)

# define a sensor as part of a circle centred on the grid
sensor_radius = 65 # [grid points]
arc_angle = np.pi # [rad]
sensor_mask = make_circle(grid_size, grid_size // 2 + 1, sensor_radius, arc_angle)
sensor = kSensor(sensor_mask)

# define the array of temporal points
t_end = 11e-6 # [s]
_ = kgrid.makeTime(medium.sound_speed, t_end=t_end)


# ## Define simulation parameters
input_filename = "example_sd_focused_2d_input.h5"
pathname = gettempdir()
input_file_full_path = os.path.join(pathname, input_filename)
simulation_options = SimulationOptions(save_to_disk=True, input_filename=input_filename, data_path=pathname)


# ## Run simulation with first source
# place a disc-shaped source near the focus of the detector
source = kSource()
source.p0 = 2 * make_disc(grid_size, grid_size / 2, 4)

# run the simulation
sensor_data1 = kspaceFirstOrder2DC(
medium=medium,
kgrid=kgrid,
source=deepcopy(source),
sensor=sensor,
simulation_options=simulation_options,
execution_options=SimulationExecutionOptions(),
)


sensor_data1["p"].shape


# ## Run simulation with second source


# place a disc-shaped source horizontally shifted from the focus of the detector
source.p0 = 2 * make_disc(grid_size, grid_size / 2 + [0, 20], 4)

sensor_data2 = kspaceFirstOrder2DC(
medium=medium,
kgrid=kgrid,
source=deepcopy(source),
sensor=sensor,
simulation_options=simulation_options,
execution_options=SimulationExecutionOptions(),
)


# ## Visualize recorded data


sensor_output1 = np.sum(sensor_data1["p"], axis=1) / np.sum(sensor.mask)
sensor_output2 = np.sum(sensor_data2["p"], axis=1) / np.sum(sensor.mask)

t_sc, t_scale, t_prefix, _ = scale_SI(t_end)
t_array = kgrid.t_array.squeeze() * t_scale

plt.plot(t_array, sensor_output1, "k")
plt.plot(t_array, sensor_output2, "r")

plt.xlabel("Time [" + t_prefix + "s]")
plt.ylabel("Average Pressure Measured Over Detector [au]")
plt.legend(
[
f"Source on focus, sum(output^2) = {round(np.sum(sensor_output1**2) * 100) / 100}",
f"Source off focus, sum(output^2) = {round(np.sum(sensor_output2**2) * 100) / 100}",
]
)

plt.show()
7 changes: 7 additions & 0 deletions examples/us_beam_patterns/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Simulating Ultrasound Beam Patterns 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/us_beam_patterns/us_beam_patterns.ipynb)

This example shows how the nonlinear beam pattern from an ultrasound transducer can be modelled. It builds on the Defining An Ultrasound Transducer and Simulating Transducer Field Patterns examples.

To read more, visit the [original example page](http://www.k-wave.org/documentation/example_us_beam_patterns.php).
Loading

0 comments on commit 2b43725

Please sign in to comment.