Skip to content

Commit

Permalink
[91] - Adding CT loading functionality to web interface (#161)
Browse files Browse the repository at this point in the history
* Adding CT loading functionality to web

* Fixing issues with ct loading

* Adding support to load zipped dicom CTs

* Spellcheck

* Adding absorption to shaped grid

* Exposing CT scan info to the FE, so that we can make FE validations

* Constraining the distance from origin based on the CT size

* Removing unused pynrrd lib

* Small refactoring

* Refactoring

* Using voxels spacing when creating the grid

* Adding dependency

* Reverting the X/Y swap

* Removing gunicorn and replacing the make tarket web with web-development

* Pin stride version in all the places we specify pip install (#163)

* Pin stride version in all the places we specify pip install
* Fix dead link

* Poetry version updated

* Add focal pressure, focal volume, and FWHM to results metrics (#152)

* Poetry version updated

---------

Co-authored-by: newton sander <[email protected]>
Co-authored-by: charles <[email protected]>
Co-authored-by: d-lucena <[email protected]>
  • Loading branch information
4 people authored Oct 16, 2023
1 parent de8ad2c commit b58d1c9
Show file tree
Hide file tree
Showing 17 changed files with 773 additions and 172 deletions.
9 changes: 3 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY:help lint lint-check test test-coverage test-unit test-integration docs web web-development
.PHONY:help lint lint-check test test-coverage test-unit test-integration docs web

help:
@echo "Available commands are: \n*lint, lint-check, spellcheck, test, test-unit, test-integration docs web web-development"
@echo "Available commands are: \n*lint, lint-check, spellcheck, test, test-unit, test-integration docs web"

lint:
poetry run isort src tests docs/examples
Expand Down Expand Up @@ -46,8 +46,5 @@ test-integration:
docs:
poetry run mkdocs build

web-development:
poetry run ndk-ui

web:
poetry run gunicorn -b 0.0.0.0 -w 1 --timeout 99999999 'src.web.app:app'
poetry run ndk-ui
2 changes: 1 addition & 1 deletion docs/user_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ There are multiple ways of running the web server, you can choose between:
1. Open a terminal in the project location and run the following command

```
make web-development
make web
```

### Docker
Expand Down
65 changes: 44 additions & 21 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ mkdocs-gallery = "0.7.6"
xarray = ">=2022.3.0"
flask = {extras = ["async"], version = "^2.3.3"}
pydantic = "<2"
gunicorn = "^21.2.0"
pyrevolve = ">=2.2.3"
pydicom = "^2.4.3"
nibabel = "^5.1.0"

[tool.poetry.group.dev.dependencies]
black = {extras = ["jupyter"], version = "^23.9.1"}
Expand Down
48 changes: 31 additions & 17 deletions src/neurotechdevkit/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,45 @@ class Grid(stride.Grid):

@staticmethod
def make_shaped_grid(
shape: Tuple[int, int],
spacing: float,
shape: Tuple[int, ...],
spacing: Union[float, Tuple[float, ...]],
extra: Union[int, Iterable[int]] = 50,
absorbing: Union[int, Iterable[int]] = 40,
) -> "Grid":
"""Create an NDK Grid with the given shape.
"""Create an NDK Grid with a given shape.
Note that the time component of the grid is not defined here. That is
created at simulation time because it depends on simulation parameters.
Args:
shape: a tuple of two integers representing the shape of the grid.
shape: a tuple of integers representing the shape of the grid.
spacing: a float representing the axis-wise spacing of the grid, in
meters.
extra: an integer or an iterable of integers representing the number
of gridpoints to add as boundary layers on each side of the grid.
Extras are added both before and after the grid on each axis.
Default is 50.
absorbing: an integer or an iterable of integers representing the
number of gridpoints within the boundary layers that are
absorbing. Default is 40.
Returns:
Grid: the Grid object.
"""
space = stride.Space(shape=shape, spacing=spacing)
n_dims = len(shape)

if isinstance(extra, int):
extra = (extra,) * n_dims
else:
extra = tuple(extra)
if isinstance(absorbing, int):
absorbing = (absorbing,) * n_dims
else:
absorbing = tuple(absorbing)

space = stride.Space(
shape=shape, extra=extra, absorbing=absorbing, spacing=spacing
)
return Grid(space=space, time=None)

@staticmethod
Expand Down Expand Up @@ -84,18 +109,7 @@ def make_grid(
Grid: the Grid object.
"""
_extent = np.array(extent, dtype=float)
n_dims = len(_extent)
dx = speed_water / center_frequency / ppw # m
shape = _compute_grid_shape(_extent, dx)

if isinstance(extra, int):
extra = (extra,) * n_dims
else:
extra = tuple(extra)
if isinstance(absorbing, int):
absorbing = (absorbing,) * n_dims
else:
absorbing = tuple(absorbing)

space = stride.Space(shape=shape, extra=extra, absorbing=absorbing, spacing=dx)
return Grid(space=space, time=None)
return Grid.make_shaped_grid(shape, dx, extra, absorbing)
2 changes: 1 addition & 1 deletion src/neurotechdevkit/scenarios/built_in/_scenario_2.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def _create_scenario_2_mask(
brain_mask = brain_mask[:, :, z_center_idx]

if skull_mask.shape != output_shape:
# resample the mask to match the grid
# re-sample the mask to match the grid
scale_factor = np.array(output_shape) / np.array(skull_mask.shape)
skull_mask = scipy.ndimage.zoom(skull_mask, scale_factor, order=0)
brain_mask = scipy.ndimage.zoom(brain_mask, scale_factor, order=0)
Expand Down
13 changes: 13 additions & 0 deletions src/web/app.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
"""Flask app factory."""
import os
import pathlib

import matplotlib
from flask import Flask
from matplotlib import rc
from web.simulation_runner import SimulationRunner

CT_FOLDER = pathlib.Path("./ct-scans/")


def create_app():
"""Create the Flask app."""
Expand All @@ -23,11 +28,19 @@ def create_app():
return app


def assign_CT_FOLDER(app):
"""Assign the CT_FOLDER to the app."""
if not os.path.exists(CT_FOLDER):
os.makedirs(CT_FOLDER)
app.config["CT_FOLDER"] = CT_FOLDER


app = create_app()


def run():
"""Run the web app."""
assign_CT_FOLDER(app)
app.run(host="0.0.0.0", port=5000, debug=True)


Expand Down
Loading

0 comments on commit b58d1c9

Please sign in to comment.