Skip to content

Commit

Permalink
Add support for presentation states and other useful things (#103)
Browse files Browse the repository at this point in the history
* Ensure optical path settings are updated

* Update version of dicom-microscopy-viewer

* Allow configuration of geometry type per finding

* Improve handling of display settings

* Add log statements for auth steps

* Implement user logout

* Add keyboard shortcuts for annotation tools

* Update package dependencies

* Implement presentation states

* Fix redirect path after authentication

* Improve default presentation state

* Update dcm4che ldap configuration and proxy path

* Install newer nodejs version in container

* Update DICOMweb URLs in configuration files

* Support configuration of frame preload

* Include link to live demo in README

* Enlarge display setting popups

* Add input fields for display settings

* Include ol css

* Update URL of container tests

* Autoselect a presentation state if available
  • Loading branch information
hackermd authored Jun 1, 2022
1 parent e62d8ad commit 33ccd12
Show file tree
Hide file tree
Showing 32 changed files with 1,516 additions and 381 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run_container_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
- name: Test DICOMweb service
run: |
sleep 20
curl -sI http://localhost:8008/dicomweb/studies | grep -o '204 No Content'
curl -sI http://localhost:8008/dcm4chee-arc/aets/DCM4CHEE/rs/studies | grep -o '204 No Content'
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ RUN apt-get update && \
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
curl -sS https://deb.nodesource.com/setup_16.x | bash - && \
apt-get update && \
apt-get install -y --no-install-suggests --no-install-recommends \
nodejs \
Expand Down
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,21 @@ Explore additional slide microscopy imaging data sets and advanced viewer featur
The demo viewer uses an instance of the open-source [DCM4CHEE Archive](https://github.com/dcm4che/dcm4chee-arc-light) as DICOMweb server.


The IDC viewer uses the [Google Cloud Healthcare API](https://cloud.google.com/healthcare-api/) as DICOMweb server.

### Demo

To check out additional viewer features (multiplexed immunofluorescence, segmentations, annotations, etc.) on a variety of imaging data sets visit the live demo at [herrmannlab.github.io/slim](https://herrmannlab.github.io/slim/).

The demo viewer uses an instance of the open-source [DCM4CHEE Archive](https://github.com/dcm4che/dcm4chee-arc-light) as DICOMweb server.

## Features

### Display of images

*Slim* enables interactive visualization of DICOM VL Whole Slide Microscopy Image instances in a vendor-neutral and device-independent manner.
*Slim* enables interactive visualization of [DICOM VL Whole Slide Microscopy Image](https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_A.32.8.html) 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).
Interoperability with various image acquisition and management systems was successfully demonstrated 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 |
Expand Down Expand Up @@ -78,7 +86,7 @@ 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.
The app can be configured via a `public/config/{name}.js` JavaScript configuration file (see for example the default `public/config/local.js`).
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.
Expand All @@ -92,7 +100,8 @@ 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 `/`.
Once the app has been built, the content of the `build` folder can be directly served by a static web server at the location specified by `PUBLIC_URL` (in this case at `/`).
The `PUBLIC_URL` must be either a full URL or a relative path to the location at which the viewer application will get deployed (e.g., `PUBLIC_URL=https://herrmannlab.github.io/slim` or `PUBLIC_URL='/slim'`).


### Local
Expand Down Expand Up @@ -171,7 +180,8 @@ window.config = {
authority: "https://accounts.google.com",
clientId: gcpClientID,
scope: "email profile openid https://www.googleapis.com/auth/cloud-healthcare",
grantType: "implicit"
grantType: "implicit",
endSessionEndpoint: "https://www.google.com/accounts/Logout"
},
annotations: [
{
Expand Down Expand Up @@ -214,7 +224,7 @@ window.config = {

Create an [OIDC client ID for web application](https://developers.google.com/identity/sign-in/web/sign-in).

Note that Google's OIDC implementation does currently not yet support the authorization code grant type with PKCE challenge.
Note that Google's OIDC implementation does currently not yet support the authorization code grant type with PKCE challenge for private clients.
For the time being, the legacy implicit grand type has to be used.


Expand Down
24 changes: 23 additions & 1 deletion craco.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const CracoLessPlugin = require('craco-less')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
plugins: [
Expand Down Expand Up @@ -29,8 +30,29 @@ module.exports = {
fs: false,
path: false
},
extensions: ['.tsx', '.ts', '.js', '.wasm', '.json']
extensions: ['.tsx', '.ts', '.js', '.wasm', '.json'],
/* We use this alias and the CopyPlugin below to support using the
* dynamic-import version of Dicom Microscopy Viewer, but only when
* building a PWA. When we build a package, we must use the bundled
* version of Dicom Microscopy Viewer so we can produce a single file
* for the viewer.
*/
alias: {
'dicom-microscopy-viewer':
'dicom-microscopy-viewer/dist/dynamic-import/dicomMicroscopyViewer.min.js'
}
}
config.plugins.push(
// TO DO: remove hard coded path
new CopyWebpackPlugin({
patterns: [
{
from: './node_modules/dicom-microscopy-viewer/dist/dynamic-import',
to: './static/js'
}
]
})
)
config.target = 'web'
config.experiments = {
asyncWebAssembly: true
Expand Down
1 change: 1 addition & 0 deletions docker-compose.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ STORAGE_DIR=/storage/fs1
POSTGRES_DB=pacsdb
POSTGRES_USER=pacs
POSTGRES_PASSWORD=pacs
LDAP_INIT_CONFIG="default-config.ldif modify-dcmRemapRetrieveURL.ldif modify-dcmWebServicePath.ldif"
10 changes: 5 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ services:
user: nginx
depends_on:
- arc
# volumes:
# - ./build/:/var/www/html/:ro

ldap:
image: dcm4che/slapd-dcm4chee:2.6.0-25.1
image: dcm4che/slapd-dcm4chee:2.6.0-26.0
logging:
driver: json-file
options:
Expand All @@ -32,9 +30,11 @@ services:
volumes:
- ldap_data:/var/lib/openldap/openldap-data
- ldap_config:/etc/openldap/slapd.d
- ./etc/openldap/data/modify-dcmRemapRetrieveURL.ldif:/etc/openldap/data/modify-dcmRemapRetrieveURL.ldif:ro
- ./etc/openldap/data/modify-dcmWebServicePath.ldif:/etc/openldap/data/modify-dcmWebServicePath.ldif:ro

db:
image: dcm4che/postgres-dcm4chee:14.1-25
image: dcm4che/postgres-dcm4chee:14.2-26
logging:
driver: json-file
options:
Expand All @@ -46,7 +46,7 @@ services:
- db_data:/var/lib/postgresql/data

arc:
image: dcm4che/dcm4chee-arc-psql:5.25.1
image: dcm4che/dcm4chee-arc-psql:5.26.0
logging:
driver: json-file
options:
Expand Down
4 changes: 2 additions & 2 deletions etc/nginx/conf.d/local.conf
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ server {
add_header Access-Control-Allow-Origin *;
}

location ~ /dicomweb/(studies|series|instances) {
rewrite ^/dicomweb/(.*) /dcm4chee-arc/aets/DCM4CHEE/rs/$1 break;
location ~ /dcm4chee-arc/aets/DCM4CHEE/rs/(studies|series|instances) {
rewrite ^/dcm4chee-arc/aets/DCM4CHEE/rs/(.*) /dcm4chee-arc/aets/DCM4CHEE/rs/$1 break;
proxy_pass http://arc:8080;
proxy_http_version 1.1;
proxy_request_buffering off;
Expand Down
4 changes: 4 additions & 0 deletions etc/openldap/data/modify-dcmRemapRetrieveURL.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dn: dicomDeviceName=dcm4chee-arc,cn=Devices,cn=DICOM Configuration,dc=dcm4che,dc=org
changeType: modify
replace: dcmRemapRetrieveURL
dcmRemapRetrieveURL: http://localhost:8008
4 changes: 4 additions & 0 deletions etc/openldap/data/modify-dcmWebServicePath.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dn: dicomDeviceName=dcm4chee-arc,cn=Devices,cn=DICOM Configuration,dc=dcm4che,dc=org
changeType: modify
replace: dcmWebServicePath
dcmWebServicePath: /
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "slim",
"version": "0.5.1",
"version": "0.6.0",
"homepage": "https://github.com/herrmannlab/slim",
"private": true,
"scripts": {
"start": "craco start",
"start": "rm -rf ./node_modules/.cache/default-development && craco start",
"build": "craco build",
"lint": "ts-standard --env jest 'src/**/*.{tsx,ts}'",
"fmt": "ts-standard --env jest 'src/**/*.{tsx,ts}' --fix",
Expand Down Expand Up @@ -42,15 +42,15 @@
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"@types/react-router-dom": "^5.3.3",
"@types/react-table": "^7.0.25",
"@types/retry": "^0.12.1",
"@types/uuid": "^8.3.0",
"antd": "^4.19.3",
"antd": "^4.20.5",
"classnames": "^2.2.6",
"copy-webpack-plugin": "^10.2.4",
"craco-less": "^2.0.0",
"dcmjs": "^0.19.1",
"detect-browser": "^5.2.1",
"dicom-microscopy-viewer": "^0.36.5",
"dicom-microscopy-viewer": "^0.38.0",
"dicomweb-client": "^0.8.4",
"gh-pages": "^3.2.3",
"oidc-client": "^1.11.5",
Expand Down
1 change: 1 addition & 0 deletions public/config/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ window.config = {
write: false
}
],
preload: true,
annotations: [
{
finding: { value: '85756007', schemeDesignator: 'SCT', meaning: 'Tissue' }
Expand Down
105 changes: 101 additions & 4 deletions public/config/local.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,52 @@ window.config = {
{
id: 'local',
// This must match the proxy location configured for the web server
url: 'http://localhost:8008/dicomweb',
url: 'http://localhost:8008/dcm4chee-arc/aets/DCM4CHEE/rs',
write: true
}
],
disableWorklist: false,
disableAnnotationTools: false,
mode: 'light',
preload: true,
annotations: [
{
finding: {
value: '85756007',
schemeDesignator: 'SCT',
meaning: 'Tissue'
},
findingCategory: {
value: '91723000',
schemeDesignator: 'SCT',
meaning: 'Anatomical structure'
},
geometryTypes: ['polygon', 'freehandpolygon'],
style: {
stroke: {
color: [255, 255, 0, 1],
width: 2
},
fill: {
color: [255, 255, 255, 0.2]
}
},
},
{
finding: {
value: '108369006',
schemeDesignator: 'SCT',
meaning: 'Tumor'
},
findingCategory: {
value: '49755003',
schemeDesignator: 'SCT',
meaning: 'Morphologically abnormal structure'
},
geometryTypes: ['polygon', 'freehandpolygon'],
style: {
stroke: {
color: [251, 134, 4, 1],
color: [255, 0, 255, 1],
width: 2
},
fill: {
Expand All @@ -30,10 +60,16 @@ window.config = {
},
{
finding: {
value: '85756007',
value: '34823008',
schemeDesignator: 'SCT',
meaning: 'Tissue'
meaning: 'Tumor necrosis'
},
findingCategory: {
value: '49755003',
schemeDesignator: 'SCT',
meaning: 'Morphologically abnormal structure'
},
geometryTypes: ['polygon', 'freehandpolygon'],
style: {
stroke: {
color: [51, 204, 51, 1],
Expand All @@ -43,6 +79,67 @@ window.config = {
color: [255, 255, 255, 0.2]
}
}
},
{
finding: {
value: '369705002',
schemeDesignator: 'SCT',
meaning: 'Invasive tumor border'
},
findingCategory: {
value: '395557000',
schemeDesignator: 'SCT',
meaning: 'Tumor finding'
},
geometryTypes: ['line', 'freehandline'],
style: {
stroke: {
color: [51, 102, 255, 1],
width: 2
},
fill: {
color: [255, 255, 255, 0.2]
}
}
},
{
finding: {
value: '399721002',
schemeDesignator: 'SCT',
meaning: 'Tumor infiltration by lymphocytes present'
},
findingCategory: {
value: '395557000',
schemeDesignator: 'SCT',
meaning: 'Tumor finding'
},
geometryTypes: ['polygon', 'freehandpolygon'],
style: {
stroke: {
color: [51, 204, 204, 1],
width: 2
},
fill: {
color: [255, 255, 255, 0.2]
}
}
},
{
finding: {
value: '47973001',
schemeDesignator: 'SCT',
meaning: 'Artifact'
},
geometryTypes: ['polygon', 'freehandpolygon'],
style: {
stroke: {
color: [255, 80, 80, 1],
width: 2
},
fill: {
color: [255, 255, 255, 0.2]
}
}
}
]
}
2 changes: 1 addition & 1 deletion public/config/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ window.config = {
servers: [
{
id: 'preview',
url: 'https://idc-external-006.uc.r.appspot.com',
url: 'https://idc-external-006.uc.r.appspot.com/dcm4chee-arc/aets/DCM4CHEE/rs',
write: false
}
],
Expand Down
4 changes: 4 additions & 0 deletions src/App.dark.less
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
@import 'antd/lib/style/themes/default.less';
@import 'antd/dist/antd.dark.less';
@import 'antd/dist/antd.compact.less';
@import 'ol/ol.css';

@card-background: transparent;

.ant-layout-header {
color: white
}
.ant-layout-header a {
color: white
}

.ant-layout-sider-children {
overflow-y: auto;
Expand Down
4 changes: 4 additions & 0 deletions src/App.light.less
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
@import 'antd/lib/style/themes/default.less';
@import 'antd/dist/antd.less';
@import 'antd/dist/antd.compact.less';
@import 'ol/ol.css';

@card-background: transparent;

.ant-layout-header {
color: white
}
.ant-layout-header a {
color: white
}

.ant-layout-sider-children {
overflow-y: auto;
Expand Down
Loading

0 comments on commit 33ccd12

Please sign in to comment.