Skip to content

Commit 5f6b07e

Browse files
Ohifv3 fixes (#1573)
* Fix OHIF V3 issues related to proxy/build Signed-off-by: Sachidanand Alle <[email protected]> * Fix Run Script via NGINX Signed-off-by: Sachidanand Alle <[email protected]> * Use OHIF V3 as default Signed-off-by: Sachidanand Alle <[email protected]> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix screenshot Signed-off-by: Sachidanand Alle <[email protected]> * Fix Build Signed-off-by: Sachidanand Alle <[email protected]> * Fix Build Signed-off-by: Sachidanand Alle <[email protected]> * Fix Build Signed-off-by: Sachidanand Alle <[email protected]> --------- Signed-off-by: Sachidanand Alle <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 6ff3a60 commit 5f6b07e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+935
-547
lines changed

monailabel/endpoints/proxy.py

Lines changed: 63 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
# limitations under the License.
1111

1212
import logging
13+
import time
1314

1415
import google.auth
1516
import google.auth.transport.requests
16-
import httpx
17-
from fastapi import APIRouter, Depends
17+
import requests
18+
from fastapi import APIRouter, Depends, Request
1819
from fastapi.responses import Response
1920

2021
from monailabel.config import settings
@@ -29,103 +30,106 @@
2930
)
3031

3132

32-
class GoogleAuth(httpx.Auth):
33-
def __init__(self, token):
34-
self.token = token
35-
36-
def auth_flow(self, request):
37-
# Send the request, with a custom `Authorization` header.
38-
request.headers["Authorization"] = "Bearer %s" % self.token
39-
yield request
40-
41-
42-
async def proxy_dicom(op: str, path: str, response: Response):
33+
async def proxy_dicom(request: Request, op: str, path: str):
4334
auth = (
4435
(settings.MONAI_LABEL_DICOMWEB_USERNAME, settings.MONAI_LABEL_DICOMWEB_PASSWORD)
4536
if settings.MONAI_LABEL_DICOMWEB_USERNAME and settings.MONAI_LABEL_DICOMWEB_PASSWORD
4637
else None
4738
)
39+
40+
headers = {}
4841
if "googleapis.com" in settings.MONAI_LABEL_STUDIES:
4942
google_credentials, _ = google.auth.default(scopes=["https://www.googleapis.com/auth/cloud-platform"])
5043
auth_req = google.auth.transport.requests.Request()
5144
google_credentials.refresh(auth_req)
5245
token = google_credentials.token
53-
auth = GoogleAuth(token)
54-
55-
async with httpx.AsyncClient(auth=auth) as client:
56-
server = f"{settings.MONAI_LABEL_STUDIES.rstrip('/')}"
57-
prefix = (
58-
settings.MONAI_LABEL_WADO_PREFIX
59-
if op == "wado"
60-
else settings.MONAI_LABEL_QIDO_PREFIX
61-
if op == "qido"
62-
else settings.MONAI_LABEL_STOW_PREFIX
63-
if op == "stow"
64-
else ""
65-
)
46+
headers["Authorization"] = "Bearer %s" % token
47+
auth = None
48+
49+
server = f"{settings.MONAI_LABEL_STUDIES.rstrip('/')}"
50+
prefix = (
51+
settings.MONAI_LABEL_WADO_PREFIX
52+
if op == "wado"
53+
else settings.MONAI_LABEL_QIDO_PREFIX
54+
if op == "qido"
55+
else settings.MONAI_LABEL_STOW_PREFIX
56+
if op == "stow"
57+
else ""
58+
)
6659

67-
# some version of ohif requests metadata using qido so change it to wado
68-
print(
69-
f"This is the server {server} - This is the op {op} - This is the prefix {prefix} - This is the path {path}"
60+
# some version of ohif requests metadata using qido so change it to wado
61+
# print(f"Server {server}; Op: {op}; Prefix: {prefix}; Path: {path}")
62+
if path.endswith("metadata") and op == "qido":
63+
prefix = settings.MONAI_LABEL_WADO_PREFIX
64+
65+
if prefix:
66+
proxy_path = f"{prefix}/{path}"
67+
else:
68+
proxy_path = f"{path}"
69+
70+
logger.debug(f"Proxy connecting to /dicom/{op}/{path} => {proxy_path}")
71+
start = time.time()
72+
if request.method == "POST":
73+
headers.update(request.headers)
74+
rp_resp = requests.post(
75+
f"{server}/{proxy_path}",
76+
auth=auth,
77+
stream=True,
78+
headers=headers,
79+
data=await request.body(),
7080
)
71-
if path.endswith("metadata") and op == "qido":
72-
prefix = settings.MONAI_LABEL_WADO_PREFIX
73-
74-
if prefix:
75-
proxy_path = f"{server}/{prefix}/{path}"
76-
else:
77-
proxy_path = f"{server}/{path}"
78-
79-
logger.debug(f"Proxy connecting to /dicom/{op}/{path} => {proxy_path}")
80-
timeout = httpx.Timeout(
81-
settings.MONAI_LABEL_DICOMWEB_PROXY_TIMEOUT,
82-
read=settings.MONAI_LABEL_DICOMWEB_READ_TIMEOUT,
81+
else:
82+
rp_resp = requests.get(
83+
f"{server}/{proxy_path}",
84+
auth=auth,
85+
stream=True,
86+
headers=headers,
8387
)
88+
logger.debug(f"Proxy Time: {time.time() - start:.4f} => Path: {proxy_path}")
8489

85-
print(f"This is the proxy path: {proxy_path}")
86-
proxy = await client.get(proxy_path, timeout=timeout)
87-
88-
response.body = proxy.content
89-
response.status_code = proxy.status_code
90-
# response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
91-
# response.headers["Cross-Origin-Embedder-Policy"] = "require-corp"
92-
# response.headers["Cross-Origin-Resource-Policy"] = "same-site"
93-
# response.headers["Cross-Origin-Resource-Policy"] = "cross-origin"
94-
return response
90+
return Response(
91+
content=rp_resp.raw.read(),
92+
status_code=rp_resp.status_code,
93+
headers=rp_resp.headers,
94+
)
9595

9696

9797
@router.get("/dicom/wado/{path:path}", include_in_schema=False)
98+
@router.post("/dicom/wado/{path:path}", include_in_schema=False)
9899
async def proxy_wado(
100+
request: Request,
99101
path: str,
100-
response: Response,
101102
user: User = Depends(RBAC(settings.MONAI_LABEL_AUTH_ROLE_USER)),
102103
):
103-
return await proxy_dicom("wado", path, response)
104+
return await proxy_dicom(request, "wado", path)
104105

105106

106107
@router.get("/dicom/qido/{path:path}", include_in_schema=False)
108+
@router.post("/dicom/qido/{path:path}", include_in_schema=False)
107109
async def proxy_qido(
110+
request: Request,
108111
path: str,
109-
response: Response,
110112
user: User = Depends(RBAC(settings.MONAI_LABEL_AUTH_ROLE_USER)),
111113
):
112-
return await proxy_dicom("qido", path, response)
114+
return await proxy_dicom(request, "qido", path)
113115

114116

115117
@router.get("/dicom/stow/{path:path}", include_in_schema=False)
118+
@router.post("/dicom/stow/{path:path}", include_in_schema=False)
116119
async def proxy_stow(
120+
request: Request,
117121
path: str,
118-
response: Response,
119122
user: User = Depends(RBAC(settings.MONAI_LABEL_AUTH_ROLE_USER)),
120123
):
121-
return await proxy_dicom("stow", path, response)
124+
return await proxy_dicom(request, "stow", path)
122125

123126

124127
# https://fastapi.tiangolo.com/tutorial/path-params/#order-matters
125128
@router.get("/dicom/{path:path}", include_in_schema=False)
129+
@router.post("/dicom/{path:path}", include_in_schema=False)
126130
async def proxy(
131+
request: Request,
127132
path: str,
128-
response: Response,
129133
user: User = Depends(RBAC(settings.MONAI_LABEL_AUTH_ROLE_USER)),
130134
):
131-
return await proxy_dicom("", path, response)
135+
return await proxy_dicom(request, "", path)

plugins/ohifv3/.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright (c) MONAI Consortium
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
# Unless required by applicable law or agreed to in writing, software
7+
# distributed under the License is distributed on an "AS IS" BASIS,
8+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
# See the License for the specific language governing permissions and
10+
# limitations under the License.
11+
12+
logs
13+
Viewers
14+
www

plugins/ohifv3/README.md

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ limitations under the License.
1414
## MONAI Label Plugin for OHIF Viewer
1515
The Open Health Imaging Foundation (OHIF) Viewer is an open-source, web-based platform for medical imaging. OHIF Viewer provides a framework for building complex imaging applications with user-friendly interfaces. MONAI Label supports the web-based OHIF viewer with connectivity to a remote DICOM server via DICOMweb.
1616

17-
<img src="./images/ohifv3.png" width=90% />
17+
<img src="./images/ohifv3.jpg" width=90% />
1818

1919
### Table of Contents
2020
- [Supported Applications](#supported-applications)
@@ -33,20 +33,16 @@ When installing MONAI Label with `pip install monailabel`, a version of OHIF tha
3333
#### Development setup
3434

3535
To build the OHIF plugin for development, follow these steps:
36-
```bash
37-
sudo sh requirements.sh # installs yarn
38-
sh build.sh
39-
```
40-
41-
To run Orthanc from the submodule and avoid building the OHIF package for every code change, use the following commands:
4236
```bash
43-
cd plugins/ohif/Viewers
44-
45-
yarn run dev:orthanc
37+
sudo sh requirements.sh # installs yarn/ngnix
38+
sh build.sh
39+
```
4640

47-
# OHIF will run at http://127.0.0.1:3000/
41+
To run the OHIF plugin, update DICOM and MONAI Server Endpoints in configs/nginx.conf
42+
```bash
43+
sh run.sh
4844
```
49-
You can then visit http://127.0.0.1:3000/ on your browser to see the running OHIF.
45+
You can then visit http://127.0.0.1:3000/ohif/ on your browser to see the running OHIF.
5046

5147
### Installing Orthanc (DICOMWeb)
5248

plugins/ohifv3/build.sh

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,51 +25,31 @@ echo "Installing OHIF at: ${install_dir}"
2525

2626
cd ${my_dir}
2727
rm -rf Viewers
28-
git clone https://github.com/OHIF/Viewers.git
28+
cp -r ~/Projects/Viewers .
29+
#git clone https://github.com/OHIF/Viewers.git
2930
cd Viewers
30-
git checkout feat/monai-label
31+
git checkout 33f125940863607f8dba82c71b27a43f35431dd5
3132

33+
#cp -r ../extensions/monai-label extensions/
34+
#cp -r ../modes/monai-label modes/monai-label
35+
cd extensions
36+
ln -s ../../extensions/monai-label monai-label
37+
cd ..
3238

33-
sed -i "s|routerBasename: '/'|routerBasename: '/ohif/'|g" ./platform/app/public/config/default.js
34-
sed -i "s|name: 'aws'|name: 'Orthanc'|g" ./platform/app/public/config/default.js
35-
sed -i "s|wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb'|wadoUriRoot: 'http://localhost/dicom-web'|g" ./platform/app/public/config/default.js
36-
sed -i "s|wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb'|wadoRoot: 'http://localhost/dicom-web'|g" ./platform/app/public/config/default.js
37-
sed -i "s|qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb'|qidoRoot: 'http://localhost/dicom-web'|g" ./platform/app/public/config/default.js
39+
cd modes
40+
ln -s ../../modes/monai-label monai-label
41+
cd ..
3842

39-
sed -i "s|PUBLIC_URL=/|PUBLIC_URL=/ohif/|g" ./platform/app/.env
43+
git apply ../extensions.patch
4044

45+
cp ../config/monai_label.js platform/app/public/config/monai_label.js
4146

47+
yarn config set workspaces-experimental true
4248
yarn install
43-
44-
# Link the mode and extension HERE
45-
echo "Linking extension and mode at: $(pwd)"
46-
yarn run cli link-extension ../extension-monai-label
47-
yarn run cli link-mode ../mode-monai-label
48-
49-
cd ../extension-monai-label
50-
51-
echo "Running install again at: $(pwd)"
52-
53-
yarn install
54-
55-
echo "Moving nrrd-js and itk node modules to Viewersnode_modules/"
56-
57-
cp -r ./node_modules/nrrd-js ../Viewers/node_modules/
58-
59-
cp -r ./node_modules/itk ../Viewers/node_modules/
60-
61-
echo "Moving to Viewers folder to build OHIF"
62-
63-
cd ../Viewers
64-
65-
echo "Viewers folder before building OHIF $(pwd)"
66-
67-
QUICK_BUILD=true yarn run build
49+
APP_CONFIG=config/monai_label.js PUBLIC_URL=/ohif/ QUICK_BUILD=true yarn run build
6850

6951
rm -rf ${install_dir}
70-
mv ./platform/app/dist/ ${install_dir}
52+
cp -r platform/app/dist/ ${install_dir}
7153
echo "Copied OHIF to ${install_dir}"
7254

73-
rm -rf ../Viewers
74-
7555
cd ${curr_dir}

plugins/ohifv3/config/mime.types

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
2+
types {
3+
text/html html htm shtml;
4+
text/css css;
5+
text/xml xml;
6+
image/gif gif;
7+
image/jpeg jpeg jpg;
8+
application/javascript js;
9+
application/atom+xml atom;
10+
application/rss+xml rss;
11+
12+
text/mathml mml;
13+
text/plain txt;
14+
text/vnd.sun.j2me.app-descriptor jad;
15+
text/vnd.wap.wml wml;
16+
text/x-component htc;
17+
18+
image/avif avif;
19+
image/png png;
20+
image/svg+xml svg svgz;
21+
image/tiff tif tiff;
22+
image/vnd.wap.wbmp wbmp;
23+
image/webp webp;
24+
image/x-icon ico;
25+
image/x-jng jng;
26+
image/x-ms-bmp bmp;
27+
28+
font/woff woff;
29+
font/woff2 woff2;
30+
31+
application/java-archive jar war ear;
32+
application/json json;
33+
application/mac-binhex40 hqx;
34+
application/msword doc;
35+
application/pdf pdf;
36+
application/postscript ps eps ai;
37+
application/rtf rtf;
38+
application/vnd.apple.mpegurl m3u8;
39+
application/vnd.google-earth.kml+xml kml;
40+
application/vnd.google-earth.kmz kmz;
41+
application/vnd.ms-excel xls;
42+
application/vnd.ms-fontobject eot;
43+
application/vnd.ms-powerpoint ppt;
44+
application/vnd.oasis.opendocument.graphics odg;
45+
application/vnd.oasis.opendocument.presentation odp;
46+
application/vnd.oasis.opendocument.spreadsheet ods;
47+
application/vnd.oasis.opendocument.text odt;
48+
application/vnd.openxmlformats-officedocument.presentationml.presentation
49+
pptx;
50+
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
51+
xlsx;
52+
application/vnd.openxmlformats-officedocument.wordprocessingml.document
53+
docx;
54+
application/vnd.wap.wmlc wmlc;
55+
application/wasm wasm;
56+
application/x-7z-compressed 7z;
57+
application/x-cocoa cco;
58+
application/x-java-archive-diff jardiff;
59+
application/x-java-jnlp-file jnlp;
60+
application/x-makeself run;
61+
application/x-perl pl pm;
62+
application/x-pilot prc pdb;
63+
application/x-rar-compressed rar;
64+
application/x-redhat-package-manager rpm;
65+
application/x-sea sea;
66+
application/x-shockwave-flash swf;
67+
application/x-stuffit sit;
68+
application/x-tcl tcl tk;
69+
application/x-x509-ca-cert der pem crt;
70+
application/x-xpinstall xpi;
71+
application/xhtml+xml xhtml;
72+
application/xspf+xml xspf;
73+
application/zip zip;
74+
75+
application/octet-stream bin exe dll;
76+
application/octet-stream deb;
77+
application/octet-stream dmg;
78+
application/octet-stream iso img;
79+
application/octet-stream msi msp msm;
80+
81+
audio/midi mid midi kar;
82+
audio/mpeg mp3;
83+
audio/ogg ogg;
84+
audio/x-m4a m4a;
85+
audio/x-realaudio ra;
86+
87+
video/3gpp 3gpp 3gp;
88+
video/mp2t ts;
89+
video/mp4 mp4;
90+
video/mpeg mpeg mpg;
91+
video/quicktime mov;
92+
video/webm webm;
93+
video/x-flv flv;
94+
video/x-m4v m4v;
95+
video/x-mng mng;
96+
video/x-ms-asf asx asf;
97+
video/x-ms-wmv wmv;
98+
video/x-msvideo avi;
99+
}

0 commit comments

Comments
 (0)