Skip to content

Commit

Permalink
Support for display of image analysis results (#87)
Browse files Browse the repository at this point in the history
* Expose new library features for display of analysis results
* Add menus for segments, mappings, and annotation groups
* Upgrade dependencies
* Unify handling of optical paths for color and grayscale images
* Add loading indicator
* Ensure roi annotations are re-rendered upon modification
* Support configuration of dark/light app mode
* Fix selection of volume images
* Improve styling of overview
* Enable dynamic selection of DICOMweb server via UI
* Improve handling of reference objects
* Render specimen metadata in compacter form
* Improve fetching of wasm code
* Fix recreation of viewers on page reload
* Improve styling of slide viewer sidebar
* Work around common standard compliance issues
* Update preview configuration
* Configure webpack and jest in craco config file
* Update docker-compose configuration
* Sort slides by series number
* Add github pages deployment workflow
* Update ignore files
* Update README

Co-authored-by: Chris Gorman <[email protected]>
  • Loading branch information
hackermd and cgorman authored Mar 15, 2022
1 parent ddbc7d2 commit 886cfb7
Show file tree
Hide file tree
Showing 65 changed files with 8,009 additions and 6,860 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
name: Deploy to Firebase Hosting on PR
'on': pull_request
name: Deploy to Firebase Hosting
on:
pull_request:
branches: [ master ]
push:
branches: [ master ]
jobs:
build_and_preview:
if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: sudo npm i -g yarn && yarn install && REACT_APP_CONFIG=preview yarn build
- uses: FirebaseExtended/action-hosting-deploy@v0
- run: sudo npm i -g yarn
- name: Install dependencies
run: yarn install
- name: Build
run: REACT_APP_CONFIG=preview PUBLIC_URL=/ yarn build
- name: Deploy
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_SLIM }}'
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/deploy_gh_pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Deploy to gh-pages

on:
push:
branches:
- master

jobs:
gh-pages-deploy:
name: Deploying to gh-pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: sudo npm install -g yarn
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build and deploy with gh-pages
run: |
git remote set-url origin https://git:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
yarn deploy -- -u "github-actions-bot <[email protected]>"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 changes: 0 additions & 17 deletions .github/workflows/firebase-hosting-merge.yml

This file was deleted.

30 changes: 30 additions & 0 deletions .github/workflows/run_unit_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: unit tests

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build_and_test:

runs-on: ubuntu-latest
strategy:
matrix:
node-version: ["14.x", "16.x"]

steps:
- uses: actions/checkout@v2
- name: Set up Node ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: yarn install
- name: Build with craco
run: yarn build
- name: Lint with standard
run: yarn lint
- name: Test with jest
run: yarn test
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
# production
/build

public/config/*
!public/config/demo.js
!public/config/local.js
!public/config/preview.js

# misc
.DS_Store
.env.local
Expand Down
4 changes: 4 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
tmp
public/config/*
!public/config/local.js
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ RUN NODE_OPTIONS=--max_old_space_size=8192 yarn run build && \
RUN mkdir -p /var/run/nginx && \
chown -R nginx:nginx /var/www/html /var/run/nginx /var/lib/nginx /var/log/nginx && \
chmod -R 0755 /var/www/html /var/run/nginx /var/lib/nginx /var/log/nginx && \
rm -r /etc/nginx/conf.d /etc/nginx/sites-available /etc/nginx/sites-enabled
rm -r /etc/nginx/conf.d /etc/nginx/sites-available /etc/nginx/sites-enabled && \
rm -r /var/www/html/*

COPY etc/nginx/conf.d /etc/nginx/conf.d
COPY etc/nginx/nginx.conf /etc/nginx/
Expand Down
146 changes: 110 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,67 @@
# Slim: Slide microscopy image display and annotation system for thin clients
# Slim: interoperable web viewer and annotation tool for computational pathology

A lightweight server-less single-page application for interactive visualization of digital slide microscopy (SM) images and associated image annotations in standard DICOM format.
The application is based on the [dicom-microscopy-viewer](https://github.com/MGHComputationalPathology/dicom-microscopy-viewer) library and can simply be placed in front of a [DICOMweb](https://www.dicomstandard.org/dicomweb/) compatible Image Management System (IMS), Picture Archiving and Communication (PACS), or Vendor Neutral Archive (VNA).
*Slim* is a single-page application for interactive visualization and annotation of digital whole slide microscopy images and derived image analysis results in standard DICOM format.
The application is based on the [dicom-microscopy-viewer](https://github.com/MGHComputationalPathology/dicom-microscopy-viewer) JavaScript library and runs fully client side without any custom server components.
It relies on [DICOMweb](https://www.dicomstandard.org/dicomweb/) RESTful services to search for, retrieve, and store imaging data and can thereby simply be placed in front of any DICOMweb-conformant Image Management System (IMS), Picture Archiving and Communication (PACS), or Vendor Neutral Archive (VNA).

## Image display
## Explore

The app will search the IMS for studies containing SM images and visualize image instances of the DICOM VL Whole Slide Microscopy Image SOP Storage Class.
### National Cancer Institute's Imaging Data Commons

## Image annotation
*Slim* serves as the slide microscopy viewer of the [National Cancer Institute's Imaging Data Commons (IDC)](https://datacommons.cancer.gov/repository/imaging-data-commons).

The app allows users to create graphical image region of interest (ROI) annotations and store them as DICOM Comprehensive 3D SR documents using SR template [TID 1500 "Measurement Report"](http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1500).
ROIs are stored as 3D spatial coordinates (SCOORD3D) according to SR template [TID 1410 "Planar ROI Measurements and Qualitative Evaluations"](http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1410) together with measurements and qualitative evaluations.
Specifically, [Image Region](http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#para_b68aa0a9-d0b1-475c-9630-fbbd48dc581d) is used to store the vector graphic data and [Finding](http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#para_c4ac1cac-ee86-4a86-865a-8137ebe1bd95) is used to describe what has been annotated using a standard medical terminology such as SNOMED CT.
<img src="docs/screenshots/IDC_CPTAC_C3L-00965-26.png" alt="IDC CPTAC C3L-00965-26" width="100%">

Use *Slim* to visually explore public IDC cancer imaging data collections by visiting the IDC web portal: [portal.imaging.datacommons.cancer.gov](https://portal.imaging.datacommons.cancer.gov/).

## Features

### Display of images

*Slim* enables interactive visualization of DICOM VL Whole Slide Microscopy Image instances in a vendor-neutral and device-independent manner.

Interoperability with various image acquisition and management systems was successfully demonstrated interoperability at the [DICOM WG-26 Connectathon at Path Visions 2020](https://digitalpathologyassociation.org/past-presentations#PV20) and the [DICOM WG-26 Hackathon at Path Visions 2021](https://digitalpathologyassociation.org/past-presentations#PV21).
Shown below are screenshots of examples images that are publicly available on the NEMA FTP server at [medical.nema.org](ftp://medical.nema.org).

| | Vendor | Illumination | Stain |
| :-: |:------ |:------------ | :--- |
| <img src="docs/screenshots/NEMA_Roche_TriChrome.png" alt="NEMA Roche Brightfield" width="350"> | Roche Tissue Diagnostics | Brightfield | Trichrome |
| <img src="docs/screenshots/NEMA_3DHISTECH_HE.png" alt="NEMA 3DHISTECH Brightfield" width="350"> | 3DHISTECH | Brightfield | H&E |
| <img src="docs/screenshots/NEMA_3DHISTECH_DAPI-FITC-Rhodamine.png" alt="NEMA 3DHISTECH Flourescence" width="350"> | 3DHISTECH | Fluorescence | DAPI, FITC, Rhodamine |
| <img src="docs/screenshots/NEMA_SamanTree_Histolog.png" alt="NEMA SamanTree Flourescence" width="350"> | SamanTree Medical | Fluorescence | Histolog |

### Display of image annotations and analysis results

Slime further allows for interative visualization of image annotations and analysis results.
The viewer currently supports the following types of DICOM instances:

Vector graphics:

- [DICOM Comprehensive 3D SR](https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_A.35.13.html) instances that are structured according to template [TID 1500 "Measurements Report"](https://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1500) and contain planar image region of interest (ROI) annotations structured according to template [TID 1410 "Planar ROI Measurements and Qualitative Evaluations"](http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1410)
- [DICOM Microscopy Bulk Simple Annotations](https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_A.87.html) instances that contain groups of many ROI annotations (e.g., single cells)

Raster graphics:

- [DICOM Segmentation](https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_A.51.html) instances that contain binary or fractional segmentation masks
- [DICOM Parametric Map](https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_A.75.html) instances that contain saliency maps, attention maps, class activation maps, etc.


| | DICOM IOD |
| :-: |:--------- |
| <img src="docs/screenshots/IDC_CPTAC_C3N-01016-22_segmentation.png" alt="IDC CPTAC Segmentation" width="350"> | Segmentation |
| <img src="docs/screenshots/IDC_CPTAC_C3N-01016-22_parametric_map.png" alt="IDC CPTAC Parametric Map" width="350"> | Parametric Map |
| <img src="docs/screenshots/IDC_CPTAC_C3N-01016-22_annotation.png" alt="IDC CPTAC Comprehensive 3D SR" width="350"> | Comprehensive 3D SR |
| <img src="docs/screenshots/IDC_TCGA_TCGA-05-4244-01Z-00-DX1_segmentation.png" alt="IDC TCGA Segmentation" width="350"> | Segmentation |
| <img src="docs/screenshots/IDC_TCGA_TCGA-05-4244-01Z-00-DX1_bulk_annotations.png" alt="IDC TCGA Segmentation" width="350"> | Microscopy Bulk Simple Annotations |


### Annotation of images

In addition to display, *Slim* provides annotation tools that allow users to create graphical image region of interest (ROI) annotations and store them as [DICOM Comprehensive 3D SR](https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_A.35.13.html) instances using SR template [TID 1500 "Measurement Report"](http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1500).
ROIs are stored as 3D spatial coordinates (SCOORD3D) in millimeter unit according to SR template [TID 1410 "Planar ROI Measurements and Qualitative Evaluations"](http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1410) together with measurements and qualitative evaluations (labels).
Specifically, [Image Region](http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#para_b68aa0a9-d0b1-475c-9630-fbbd48dc581d) is used to store the vector graphic data and [Finding](http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#para_c4ac1cac-ee86-4a86-865a-8137ebe1bd95) is used to describe what has been annotated using a standard medical terminology such as [SNOMED CT](https://www.snomed.org/).
The terms that can be chosen by a user can be configured (see [AppConfig.d.ts](src/AppConfig.d.ts)).

The app will also search the IMS for existing SR documents and display any ROI annotations contained in DICOM Comprehensive 3D SR documents that are structured according to TID 1500.

## Autentication and authorization

Expand All @@ -22,22 +70,40 @@ Users can authenticate and authorize the application to access data via [OpenID
## Configuration

The app can be configured via a `public/config/{name}.js` JavaScript configuration file.
Please refer to the `AppConfig.d.ts` file for configuration options.
Please refer to the [AppConfig.d.ts](src/AppConfig.d.ts) file for configuration options.

The configuration can be changed at build-time using the `REACT_APP_CONFIG` environment variable.

## Deployment

Download the latest release from [github.com/herrmannlab/slim/releases](https://github.com/herrmannlab/slim/releases) and then run the following commands to install build dependencies and build the app:

```none
yarn install
PUBLIC_URL=/ yarn build
```

Once the app has been built, the content of the `build` folder can be directly served by a static web server at `/`.


### Local

The repository provides a [Docker compose file](https://docs.docker.com/compose/compose-file/) to deploy a web server and a [dcm4chee-arc-light](https://github.com/dcm4che/dcm4chee-arc-light) DICOMweb server on localhost for local app development and testing:
The repository provides a [Docker compose file](https://docs.docker.com/compose/compose-file/) to deploy a static web server and a [dcm4chee-arc-light](https://github.com/dcm4che/dcm4chee-arc-light) DICOMweb server on localhost for local app development and testing:

$ docker-compose up -d
```none
docker-compose up -d
```

Serves the app via an NGINX web server at `http://localhost:8008` and exposes the DICOMweb RESTful services at `http://localhost:8008/dicomweb`.
The local deployment serves the app via an NGINX web server at `http://localhost:8008` and exposes the DICOMweb services at `http://localhost:8008/dicomweb`.
Once the serives are up, one can store DICOM objects in the archive using the [Store transaction of the DICOMweb Studies Service](http://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_10.5.html).

Local deployment uses the default configuration `public/config/local.js`.
The command line interface of the [dicomweb-client Python package](https://dicomweb-client.readthedocs.io/en/latest/usage.html#command-line-interface-cli) makes storing DICOM files in the archive straight forward:

```none
dicomweb_client -vv --url http://localhost:8008/dicomweb store instances -h
```

The local deployment uses the default configuration file `public/config/local.js`:

```js
window.config = {
Expand All @@ -49,15 +115,12 @@ window.config = {
write: true
}
],
renderer: {
retrieveRendered: true
},
annotations: [
{
finding: {
value: '108369006',
value: '85756007',
schemeDesignator: 'SCT',
meaning: 'Neoplasm'
meaning: 'Tissue'
},
style: {
stroke: {
Expand All @@ -73,17 +136,19 @@ window.config = {
};
```

Customize the configuration according to your needs at either build-time or run-time.

### Google Cloud Platform

Here is an example configuration `public/config/gcp.js` for running the app with the [Google Healthcare API](https://cloud.google.com/healthcare) and OIDC authentication/authorization:
*Slim* can be readily configured to connect to a secured DICOMweb endpoint of the [Google Cloud Healthcare API](https://cloud.google.com/healthcare) with OIDC authentication:

```js
const gcpProject = ""
const gcpLocation = ""
const gcpDataset = ""
const gcpStore = ""
const gcpClientID = ""

window.config = {
path: "/",
servers: [
Expand All @@ -99,9 +164,6 @@ window.config = {
scope: "email profile openid https://www.googleapis.com/auth/cloud-healthcare",
grantType: "implicit"
},
renderer: {
retrieveRendered: false
},
annotations: [
{
finding: {
Expand All @@ -118,6 +180,22 @@ window.config = {
color: [255, 255, 255, 0.2]
}
}
},
{
finding: {
value: '85756007',
schemeDesignator: 'SCT',
meaning: 'Tissue'
},
style: {
stroke: {
color: [255, 255, 0, 1],
width: 2
},
fill: {
color: [255, 255, 255, 0.2]
}
}
}
]
};
Expand All @@ -130,24 +208,20 @@ Create an [OIDC client ID for web application](https://developers.google.com/ide
Note that Google's OIDC implementation does currently not yet support the authorization code grant type with PKCE challenge.
For the time being, the legacy implicit grand type has to be used.

## Production

To install requirements and run the app for production deployment, run the following commands:

$ yarn install
$ yarn build

For further information about installation of system dependencies and configuration, see `Dockerfile`.

## Development

To install requirements and run the app for local development, run the following commands:

$ yarn install
$ yarn start
```none
yarn install
yarn start
```

This will serve the app via a development server at [http://localhost:3000](http://localhost:3000) using the `local` configuration.
This will serve the app via a development server at [http://localhost:3000](http://localhost:3000) using the default `local` configuration.

The configuration can be specified using the `REACT_APP_CONFIG` environment variable, which can be set either in the `.env` file or directly in the command line:

$ REACT_APP_CONFIG=local yarn start
```none
REACT_APP_CONFIG=local yarn start
```
6 changes: 3 additions & 3 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript'
]
}
Loading

0 comments on commit 886cfb7

Please sign in to comment.