Skip to content

Commit

Permalink
Merge branch 'master' into clean-up-pytest-warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
waltsims authored Dec 19, 2023
2 parents 5093b86 + 9954eb3 commit 9bcadc6
Show file tree
Hide file tree
Showing 37 changed files with 897 additions and 260 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: k-Wave-python
- name: checkout reference k-Wave repo
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ucl-bug/k-wave
path: k-wave
Expand Down Expand Up @@ -50,7 +50,7 @@ jobs:
python-version: [ "3.8", "3.9", "3.10" ]
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Download collectedValues
uses: actions/download-artifact@v3
with:
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 @@ -10,7 +10,7 @@ jobs:
python-version: [ "3.8", "3.9" ] #, "3.10" ]
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ RUN apt-get update
RUN apt-get install -y gfortran libopenblas-dev liblapack-dev libgl1-mesa-glx libglib2.0-0 libgl1-mesa-glx libglib2.0-0 git
RUN pip install --upgrade pip
COPY pyproject.toml .
COPY README.md .
#COPY README.md .
COPY docs/ docs
COPY LICENSE .
COPY kwave/ kwave
RUN pip install '.[test]'
10 changes: 5 additions & 5 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# k-Wave-python
[![Documentation Status](https://readthedocs.org/projects/k-wave-python/badge/?version=latest)](https://k-wave-python.readthedocs.io/en/latest/?badge=latest)

This project is a Python implementation of most of the [MATLAB toolbox k-Wave](http://www.k-wave.org/) as well as an
interface to the pre-compiled v1.3 of k-Wave simulation binaries which support NVIDIA sm 5.0 (Maxwell) to sm 9.0a (Hopper) GPUs.
This project is a Python implementation of v1.4.0 of the [MATLAB toolbox k-Wave](http://www.k-wave.org/) as well as an
interface to the pre-compiled v1.3 of k-Wave simulation binaries, which support NVIDIA sm 5.0 (Maxwell) to sm 9.0a (Hopper) GPUs.

## Mission

Expand Down Expand Up @@ -31,7 +31,7 @@ After installation, run the B-mode reconstruction example in the `examples` dire
```bash
git clone https://github.com/waltsims/k-wave-python
cd k-wave-python
git checkout v0.2.1
git checkout v0.3.0
pip install '.[example]'
python3 examples/bmode_reconstruction_example.py
```
Expand All @@ -46,7 +46,7 @@ This example file steps through the process of:
This example expects an NVIDIA GPU by default to simulate with k-Wave.

To test the reconstruction on a machine with a GPU,
set `RUN_SIMULATION` [on line 28 of `bmode_reconstruction_example.py`](https://github.com/waltsims/k-wave-python/blob/master/examples/bmode_reconstruction_example.py#L28)
set `RUN_SIMULATION` [on line 30 of `bmode_reconstruction_example.py`](https://github.com/waltsims/k-wave-python/blob/master/examples/bmode_reconstruction_example.py#L30)
to `True`, and the example will run without the pre-computed data.

## Development
Expand All @@ -68,4 +68,4 @@ The documentation for k-wave-python can be found [here](https://k-wave-python.re

## Contact

e-mail [[email protected]](mailto:[email protected]).
e-mail [[email protected]](mailto:[email protected]).
9 changes: 7 additions & 2 deletions examples/bmode_reconstruction_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
from kwave.utils.dotdictionary import dotdict
from kwave.utils.signals import tone_burst

if __name__ == '__main__':

def main():
# pathname for the input and output files
pathname = gettempdir()
phantom_data_path = 'phantom_data.mat'
Expand Down Expand Up @@ -110,7 +111,7 @@

# set the input settings
input_filename = f'example_input_{scan_line_index}.h5'
input_file_full_path = os.path.join(pathname, input_filename)
input_file_full_path = os.path.join(pathname, input_filename) # noqa: F841
# set the input settings
simulation_options = SimulationOptions(
pml_inside=False,
Expand Down Expand Up @@ -160,3 +161,7 @@

logging.log(logging.INFO, "Beamforming channel data and reconstructing the image...")
beamform(channel_data)


if __name__ == '__main__':
main()
149 changes: 149 additions & 0 deletions examples/example_array_as_a_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import matplotlib.pyplot as plt
import numpy as np

from kwave.data import Vector
from kwave.kgrid import kWaveGrid
from kwave.kmedium import kWaveMedium
from kwave.ksensor import kSensor
from kwave.ksource import kSource
from kwave.kspaceFirstOrder2D import kspace_first_order_2d_gpu
from kwave.options.simulation_execution_options import SimulationExecutionOptions
from kwave.options.simulation_options import SimulationOptions
from kwave.utils.conversion import cart2grid
from kwave.utils.kwave_array import kWaveArray
from kwave.utils.mapgen import make_cart_circle, make_disc
from kwave.utils.signals import reorder_binary_sensor_data


def main():
# create empty array
karray = kWaveArray()

# define arc properties
radius = 100e-3 # [m]
diameter = 8e-3 # [m]
ring_radius = 50e-3 # [m]
num_elements = 20

# orient all elements towards the center of the grid
focus_pos = Vector([0, 0]) # [m]

element_pos = make_cart_circle(ring_radius, num_elements, focus_pos)

for idx in range(num_elements):
karray.add_arc_element(element_pos[:, idx], radius, diameter, focus_pos)

# grid properties
N = Vector([256, 256])
d = Vector([0.5e-3, 0.5e-3])
kgrid = kWaveGrid(N, d)

# medium properties
medium = kWaveMedium(sound_speed=1500)

# time array
kgrid.makeTime(medium.sound_speed)

source = kSource()
x_offset = 20 # [pixels]
# make a small disc in the top left of the domain
source.p0 = make_disc(N, Vector([N.x / 4 + x_offset, N.y / 4]), 4)
source.p0[99:119, 59:199] = 1
logical_p0 = source.p0.astype(bool)
sensor = kSensor()
sensor.mask = element_pos
simulation_options = SimulationOptions(
save_to_disk=True,
data_cast='single',
)

execution_options = SimulationExecutionOptions(is_gpu_simulation=True)
output = kspace_first_order_2d_gpu(kgrid, source, sensor, medium, simulation_options, execution_options)
# TODO (walter): This should be done by kspaceFirstOrder
_, _, reorder_index = cart2grid(kgrid, element_pos)
sensor_data_point = reorder_binary_sensor_data(output['p'].T, reorder_index=reorder_index)

# assign binary mask from karray to the source mask
sensor.mask = karray.get_array_binary_mask(kgrid)

output = kspace_first_order_2d_gpu(kgrid, source, sensor, medium, simulation_options, execution_options)
sensor_data = output['p'].T
combined_sensor_data = karray.combine_sensor_data(kgrid, sensor_data)

# =========================================================================
# VISUALIZATION
# =========================================================================

# create pml mask (re-use default size of 20 grid points from simulation_options)
pml_size = simulation_options.pml_x_size # 20 [grid_points]
pml_mask = np.zeros((N.x, N.y), dtype=bool)
pml_mask[:pml_size, :] = 1
pml_mask[:, :pml_size] = 1
pml_mask[-pml_size:, :] = 1
pml_mask[:, -pml_size:] = 1

# Plot source, sensor, and pml masks

# Assign unique values to each mask
sensor_val = sensor.mask * 1
logical_p0_val = logical_p0 * 2
pml_mask_val = pml_mask * 3

# Combine masks
combined_mask = sensor_val + logical_p0_val + pml_mask_val
combined_mask = np.flipud(combined_mask)

# Define custom colormap
colors = [
(1, 1, 1), # White (Background)
(233/255, 131/255, 0/255), # Orange (Sensor)
(254/255, 221/255, 92/255), # Yellow (Sources)
(0.8, 0.8, 0.8), # Light Grey (PML Mask)
]
cmap = plt.matplotlib.colors.ListedColormap(colors)

fig, ax = plt.subplots()
c = ax.pcolormesh(combined_mask, cmap=cmap, shading='auto')
plt.axis('image')

# Define labels for the colorbar
labels = {
0: 'None',
1: 'Sensor',
2: 'Initial pressure p0',
3: 'PML Mask',
}

colorbar = plt.colorbar(c, ticks=list(labels.keys()), ax=ax)
colorbar.ax.set_yticklabels(list(labels.values()))

ax.set_xticks([])
ax.set_yticks([])

# Plot recorded sensor data
fig, (ax1, ax2)= plt.subplots(ncols=1, nrows=2)
ax1.imshow(sensor_data_point, aspect='auto')
ax1.set_xlabel(r'Time [$\mu$s]')
ax1.set_ylabel('Detector Number')
ax1.set_title('Cartesian point detectors')

ax2.imshow(combined_sensor_data, aspect='auto')
ax2.set_xlabel(r'Time [$\mu$s]')
ax2.set_ylabel('Detector Number')
ax2.set_title('Arc detectors')

fig.subplots_adjust(hspace=0.5)

# Plot a trace from the recorded sensor data
fig = plt.figure()
plt.plot(kgrid.t_array.squeeze() * 1e6, sensor_data_point[0, :], label='Cartesian point detectors')
plt.plot(kgrid.t_array.squeeze() * 1e6, combined_sensor_data[0, :], label='Arc detectors')
plt.xlabel(r'Time [$\mu$s]')
plt.ylabel('Pressure [pa]')
plt.legend()

plt.show()


if __name__ == '__main__':
main()
Loading

0 comments on commit 9bcadc6

Please sign in to comment.