Skip to content

Commit

Permalink
Merge pull request #143 from GSTT-CSC/hazen-3.9-miniforge
Browse files Browse the repository at this point in the history
Ported hazen to python versions 3.9 and 3.10.
Updated various python packages.
Updated hazen tests.
  • Loading branch information
tomaroberts authored Dec 7, 2021
2 parents 9dad487 + 1de9e1a commit 87837d4
Show file tree
Hide file tree
Showing 15 changed files with 251 additions and 72 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/cli-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ on:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest ]
python-version: [ '3.9', '3.10' ]
steps:
- uses: actions/checkout@v2

- name: Set up Python 3.6
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.6
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
Expand Down
20 changes: 15 additions & 5 deletions .github/workflows/tests_development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ on:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest ]
python-version: [ '3.9', '3.10' ]
defaults:
run:
shell: bash -l {0}
# Service containers to run with `container-job`
services:
# Label used to access the service container
Expand All @@ -30,21 +37,24 @@ jobs:
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v2

- name: Set up Python 3.6
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.6
python-version: ${{ matrix.python-version }}

- name: Install dependencies
- name: Install Python packages
run: |
python -m pip install --upgrade pip
pip install flake8 pytest pytest-cov
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Display installed pip packages
run: |
pip list
- name: Setup flake8 annotations
uses: rbialon/flake8-annotations@v1

Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/tests_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ on:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest ]
python-version: [ '3.9', '3.10' ]
# Service containers to run with `container-job`
services:
# Label used to access the service container
Expand All @@ -35,10 +39,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: Set up Python 3.6
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.6
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
Expand Down
165 changes: 128 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,78 @@
<!-- PROJECT HEADING -->
<br />
<p align="center">
<a href="https://github.com/github_username/repo_name">
<img src="https://raw.githubusercontent.com/GSTT-CSC/gstt-csc.github.io/main/assets/transparent-CSC-logo-cropped.png" alt="Logo" width="40%">
</a>
<h1 align="center">Hazen</h1>
<img src="https://raw.githubusercontent.com/GSTT-CSC/hazen/readme-dev/docs/assets/ibn-al-haytham.jpeg" alt="Ibn Al-Haytham">
</p>
<h1 align="center">hazen</h1>
<p align="center">
Quality assurance framework for Magnetic Resonance Imaging
<br />
<a href="https://github.com/github_username/repo_name"><strong>Explore the docs »</strong></a>
<br />
<br />
<a href="https://github.com/GSTT-CSC/hazen">View repo</a>
·
<a href="https://github.com/GSTT-CSC/hazen/issues">Report Bug</a>
·
<a href="https://github.com/GSTT-CSC/hazen/issues">Request Feature</a>
Quality assurance framework for Magnetic Resonance Imaging
<br />
<a href="https://github.com/github_username/repo_name"><strong>Explore the docs »</strong></a>
<br />
<br />
<a href="https://github.com/GSTT-CSC/hazen">View repo</a>
·
<a href="https://github.com/GSTT-CSC/hazen/issues">Report Bug</a>
·
<a href="https://github.com/GSTT-CSC/hazen/issues">Request Feature</a>
</p>
<p align="center">
<img src="https://github.com/GSTT-CSC/hazen/actions/workflows/tests_release.yml/badge.svg?branch=master">
<img src="https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/laurencejackson/ba102d5f3e592fcd50451c2eff8a803d/raw/hazen_pytest-coverage-comment.json">
</p>
<p align="center">Please <b>STAR</b> this repo to receive updates about new versions of hazen!</p>

## Overview
---

Please 'star' this repository to receive release updates!
## Overview

hazen is a software framework for performing automated analysis of magnetic resonance imaging (MRI) Quality Assurance data.

It provides automatic quantitative analysis for the following measurements of MRI phantom data:
- Signal-to-noise ratio (SNR)
- Spatial resolution
- Slice position and width
- Uniformity
- Ghosting
- MR Relaxometry

Some example outputs from hazen:

## Usage
| hazen snr | hazen ghosting |
| ------------------ | ------------------------------- |
| ![](docs/assets/snr-example.png) | ![](docs/assets/ghosting-example.png) |

---
### Docker
To use the docker version of hazen simply run the `hazen-app` script in a terminal. Docker must be installed on the host
system for this method to work, see [docker installation instructions](https://docs.docker.com/engine/install).
For ease of use it is recommended to copy the hazen-app script to location accessible on the path such as `/usr/local/bin`
so you can run it from any location.

e.g.
## Installation

### Prerequisites

- Python v3.9
- Git
- Docker

### Install

First, clone this repo, then follow the instructions for your operating system. To clone:
```bash
git clone [email protected]:GSTT-CSC/hazen.git
```

#### Docker

We recommend using the Docker version of hazen as it is easy to get up-and-running and is linked to the most stable release. Refer to the [Docker installation instructions](https://docs.docker.com/engine/install) to install Docker on your host computer.

For ease of use, it is recommended to copy the `hazen-app` script to a location accessible on the path such as `/usr/local/bin`. This will allow you to run hazen from any location on your computer. Then, to use Docker hazen, simply run the `hazen-app` script appended with the function you want to use (e.g.: `snr`).

In Terminal:

```bash
cd hazen
cp ./hazen-app /usr/local/bin

./hazen-app snr tests/data/snr/Siemens/
# run hazen
hazen-app snr tests/data/snr/Siemens/

latest: Pulling from gsttmriphysics/hazen
Digest: sha256:18603e40b45f3af4bf45f07559a08a7833af92a6efe21cb7306f758e8eeab24a
Expand All @@ -56,22 +86,64 @@ docker.io/gsttmriphysics/hazen:latest
'snr_subtraction_normalised_seFoV250_2meas_slice5mm_tra_repeat_PSN_noDC_2_1': 2154.69}
```
## Releasing
The Release Manager should ensure:
- All outstanding issues for that release have been closed or transferred to future release
- All tests are passing on Github Actions
- All documentation has been updated included version numbers
- Update version number in `hazenlib/__init__.py`
- Merge the release branch into master
- Create release on Github with new version tag (tag = version number)
- RMs of other branches should update their release from the new master release as soon as possible and deal with any merge conflicts.
#### Linux & MacOS
For developers, hazen can be installed using `pip`. We highly recommend using a virtual environment.
![image](https://user-images.githubusercontent.com/19840489/143266366-06e33949-12c7-44b4-9ed7-c0a795b5d492.png)
```bash
# Install OpenSSL
brew update
brew upgrade
brew install openssl
export LDFLAGS="-L`brew --prefix openssl`/lib"
export CPPFLAGS="-I`brew --prefix openssl`/include"

- RMs: Tom Roberts, Lucrezia Cester
# Go to local hazen repo directory
cd hazen

# Create and activate a virtual environment
python3 -m venv ./hazen-venv
source hazen-venv/bin/activate

# Install requirements
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt

# Install hazen
python setup.py install

# Run tests to ensure everything is working
pytest tests/
```
---
## Usage
### Command Line
The CLI version of hazen is designed to be pointed at single folders containing DICOM file(s). Example datasets are provided in the `tests/data/` directory. If you are not using the Docker version of hazen, replace `hazen-app` with `hazen` in the following commands.
To perform an SNR measurement on the provided example Philips DICOMs:
`hazen-app snr tests/data/snr/Philips`
To perform a spatial resolution measurement on example data provided by the East Kent Trust:
`hazen-app spatial_resolution tests/data/resolution/philips`
To see the full list of available tools, enter:
`hazen-app -h`
The `--report` option provides additional information for some of the functions. For example, the user can gain additional insight into the performance of the snr function by entering:
`hazen-app snr tests/data/snr/Philips --report`
### Web Interface
WIP: we are developing a web interface for hazen.
---
Expand All @@ -81,12 +153,31 @@ The Release Manager should ensure:
- The RM should ensure their release branch is kept up-to-date with master
- PRs should be merged into the appropriate release branch for the issue(s) it is addressing
Read CONTRIBUTING.md
If you want to contribute to the development of hazen, please take a look at: `CONTRIBUTING.md`.
---
## Users
Nothing to see here. Maybe see hazen/docs.
Please [raise an Issue](https://github.com/GSTT-CSC/hazen/issues) if you have any problems installing or running hazen.
We have used hazen with MRI data from a handful of different MRI scanners, including multiple different vendors. If your MRI data doesn't work with hazen, or the results are unexpected, please submit an Issue and we will investigate.
---
## Releasing
The Release Manager should ensure:
- All outstanding issues for the current release have been closed, or, transferred to future release.
- All tests are passing on Github Actions.
- All documentation has been updated with correct version numbers.
- The version number in `hazenlib/__init__.py` has been updated.
- The `release` branch has been merged into `main` branch
- A new release has been created with a new version tag (tag = version number)
- RMs of other branches should update their release from the latest release as soon as possible and deal with any merge conflicts.
![image](https://user-images.githubusercontent.com/19840489/143266366-06e33949-12c7-44b4-9ed7-c0a795b5d492.png)
- RMs: Tom Roberts, Lucrezia Cester
2 changes: 2 additions & 0 deletions contributors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ Dika Vilic
Elizabeth Gabriel
Jane Ansell
Neil Heraghty
Tom Roberts
Lucrezia Cester
Haris Shuaib
Binary file added docs/assets/ghosting-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/ibn-al-haytham.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/snr-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: hazen-3.9-miniforge

dependencies:
- pip #=21.3.1
- scikit-image
- pip:
- SQLAlchemy_Utils==0.33.11
- alembic==1.0.10
- celery==4.3.1
- numpy==1.21.0
- Werkzeug==0.15.6
- opencv-python==4.5.4.58
- Flask_Migrate==2.5.1
- pytest>=6.2
- coverage>=6.0.2
- Flask_Moment==0.7.0
- flask_heroku==0.1.9
- Flask==1.0.3
- pydicom==1.4.1
- WTForms==2.2.1
- Flask_Dropzone==1.5.3
- Flask_Mail==0.9.1
- Flask_Login==0.4.1
- Flask_Bootstrap4==4.0.2
- imutils==0.5.3
- matplotlib==3.4.3
- Flask_SQLAlchemy==2.4.0
- scipy==1.7.2
- docopt==0.6.2
- SQLAlchemy==1.3.3
- Flask_WTF==0.14.2
- flask_bootstrap==3.3.7.1
- PyJWT==1.7.1
- gunicorn==19.9.0
- psycopg2-binary==2.8.4
- arrow==0.13.2
- amqp==2.4.2
- sphinxcontrib-needs==0.4.3
- sphinxcontrib-napoleon
- sphinx_rtd_theme
- m2r
- python-dateutil
- email_validator
- colorlog

2 changes: 1 addition & 1 deletion hazenlib/slice_width.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def get_initial_trapezoid_fit_and_coefficients(profile, slice_thickness):
n_ramp = 47
n_plateau = 55

trapezoid_centre = round(np.median(np.argwhere(profile < np.mean(profile)))).astype(int)
trapezoid_centre = int(round(np.median(np.argwhere(profile < np.mean(profile)))))

n_total = len(profile)
n_left_baseline = int(trapezoid_centre - round(n_plateau / 2) - n_ramp - 1)
Expand Down
14 changes: 12 additions & 2 deletions hazenlib/spatial_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,25 @@ def thresh_image(img, bound=150):


def find_square(img):
cnts = cv.findContours(img.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
cnts = cv.findContours(img.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)[0]

for c in cnts[1]:
for c in cnts:
perimeter = cv.arcLength(c, True)
approx = cv.approxPolyDP(c, 0.1 * perimeter, True)
if len(approx) == 4:
# compute the bounding box of the contour and use the
# bounding box to compute the aspect ratio
rect = cv.minAreaRect(approx)

# OpenCV 4.5 adjustment
# - cv.minAreaRect() output tuple order changed since v3.4
# - swap rect[1] order & rotate rect[2] by -90
# – convert tuple>list>tuple to do this
rectAsList = list(rect)
rectAsList[1] = (rectAsList[1][1], rectAsList[1][0])
rectAsList[2] = rectAsList[2] - 90
rect = tuple(rectAsList)

box = cv.boxPoints(rect)
box = np.int0(box)
w, h = rect[1]
Expand Down
Loading

0 comments on commit 87837d4

Please sign in to comment.