Add DicomMicroscopy plugin
This commit is contained in:
parent
84c949f2e6
commit
03c7274812
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -10,3 +10,6 @@
|
||||
[submodule "Packages-react/plugins/VTKPlugin"]
|
||||
path = Packages-react/plugins/VTKPlugin
|
||||
url = git@github.com:OHIF/VTKPlugin.git
|
||||
[submodule "Packages-react/plugins/OpenLayersPlugin"]
|
||||
path = Packages-react/plugins/OpenLayersPlugin
|
||||
url = git@github.com:OHIF/OpenLayersPlugin.git
|
||||
|
||||
@ -97,16 +97,20 @@
|
||||
"cornerstone-math": "^0.1.8",
|
||||
"cornerstone-tools": "3.0.0-b.1512",
|
||||
"cornerstone-wado-image-loader": "^2.2.3",
|
||||
"dicom-microscopy-viewer": "^0.2.0",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"dicomweb-client": "^0.4.1",
|
||||
"hammerjs": "^2.0.8",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"ohif-core": "^0.1.7",
|
||||
"oidc-client": "^1.6.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.7.0",
|
||||
"react-bootstrap-modal": "^4.2.0",
|
||||
"react-cornerstone-viewport": "^0.1.8",
|
||||
"react-dnd": "^7.0.2",
|
||||
"react-dnd-html5-backend": "^7.0.2",
|
||||
"react-dom": "^16.7.0",
|
||||
"react-redux": "^6.0.0",
|
||||
"react-router": "^4.3.1",
|
||||
"react-router-dom": "^4.3.1",
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { createStore, combineReducers } from 'redux';
|
||||
@ -12,6 +11,8 @@ import OHIFCornerstoneViewportPlugin from './connectedComponents/OHIFCornerstone
|
||||
import WhiteLabellingContext from './WhiteLabellingContext';
|
||||
import OHIFDicomPDFViewportPlugin from './connectedComponents/OHIFDicomPDFViewportPlugin/OHIFDicomPDFViewportPlugin.js';
|
||||
import OHIFDicomPDFSopClassHandlerPlugin from './connectedComponents/OHIFDicomPDFViewportPlugin/OHIFDicomPDFSopClassHandlerPlugin.js';
|
||||
import DicomMicroscopySopClassHandlerPlugin from './connectedComponents/DicomMicroscopyPlugin/DicomMicroscopySopClassHandlerPlugin.js';
|
||||
import DicomMicroscopyViewport from './connectedComponents/DicomMicroscopyPlugin/DicomMicroscopyViewport.js';
|
||||
|
||||
import {
|
||||
loadUser,
|
||||
@ -103,7 +104,6 @@ const buttonsAction = OHIF.redux.actions.setAvailableButtons(defaultButtons);
|
||||
|
||||
store.dispatch(buttonsAction);
|
||||
|
||||
|
||||
const { plugins } = OHIF;
|
||||
const { PLUGIN_TYPES } = plugins;
|
||||
|
||||
@ -125,9 +125,25 @@ const pdfPluginActionSopClass = OHIF.redux.actions.addPlugin({
|
||||
component: OHIFDicomPDFSopClassHandlerPlugin
|
||||
});
|
||||
|
||||
const microscopyPluginAction = OHIF.redux.actions.addPlugin({
|
||||
id: 'microscopy',
|
||||
type: PLUGIN_TYPES.VIEWPORT,
|
||||
component: DicomMicroscopyViewport
|
||||
});
|
||||
|
||||
const microscopyPluginActionPluginActionSopClass = OHIF.redux.actions.addPlugin(
|
||||
{
|
||||
id: 'microscopy_sopClassHandler',
|
||||
type: PLUGIN_TYPES.SOP_CLASS_HANDLER,
|
||||
component: DicomMicroscopySopClassHandlerPlugin
|
||||
}
|
||||
);
|
||||
|
||||
store.dispatch(cornerstonePluginAction);
|
||||
store.dispatch(pdfPluginAction);
|
||||
store.dispatch(pdfPluginActionSopClass);
|
||||
store.dispatch(microscopyPluginAction);
|
||||
store.dispatch(microscopyPluginActionPluginActionSopClass);
|
||||
|
||||
// TODO[react] Use a provider when the whole tree is React
|
||||
window.store = store;
|
||||
@ -193,6 +209,10 @@ class App extends Component {
|
||||
routerBasename: PropTypes.string
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
whiteLabelling: {}
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import list from './HeaderMenuList.json';
|
||||
import OHIFLogo from '../OHIFLogo/OHIFLogo.js';
|
||||
//import Icons from "../../images/icons.svg";
|
||||
|
||||
const Icons = '/icons.svg';
|
||||
//const Icons = '/icons.svg';
|
||||
|
||||
function Header({ home, location, children }) {
|
||||
const { state } = location;
|
||||
@ -19,21 +19,25 @@ function Header({ home, location, children }) {
|
||||
return (
|
||||
<div className={`entry-header ${home ? 'header-big' : ''}`}>
|
||||
<div className="header-left-box">
|
||||
{
|
||||
state && state.studyLink &&
|
||||
{state && state.studyLink && (
|
||||
<Link to={state.studyLink} className="header-btn header-viewerLink">
|
||||
Back to Viewer
|
||||
</Link>
|
||||
}
|
||||
)}
|
||||
|
||||
{children}
|
||||
|
||||
{!home &&
|
||||
<Link className='header-btn header-studyListLinkSection' to={{
|
||||
pathname: "/",
|
||||
state: { studyLink: location.pathname }
|
||||
}}>Study list</Link>
|
||||
}
|
||||
{!home && (
|
||||
<Link
|
||||
className="header-btn header-studyListLinkSection"
|
||||
to={{
|
||||
pathname: '/',
|
||||
state: { studyLink: location.pathname }
|
||||
}}
|
||||
>
|
||||
Study list
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="header-menu">
|
||||
|
||||
@ -8,9 +8,9 @@ import version from './version.js';
|
||||
import { homepage } from '../package.json';
|
||||
|
||||
window.info = {
|
||||
sha,
|
||||
version,
|
||||
homepage
|
||||
sha,
|
||||
version,
|
||||
homepage
|
||||
};
|
||||
|
||||
// For debugging
|
||||
@ -25,7 +25,7 @@ OHIF.external.cornerstoneMath = cornerstoneMath;
|
||||
OHIF.external.cornerstoneWADOImageLoader = cornerstoneWADOImageLoader;
|
||||
|
||||
// TODO: Is there a better way to guess ROOT_URL?
|
||||
let ROOT_URL = homepage;
|
||||
//let ROOT_URL = homepage;
|
||||
|
||||
// If the page we are on is not a subset of the expected homepage
|
||||
// provided in the package.json file, we might be doing local development.
|
||||
@ -53,21 +53,21 @@ cornerstoneWADOImageLoader.webWorkerManager.initialize(config);
|
||||
*/
|
||||
|
||||
OHIF.user.getAccessToken = () => {
|
||||
// TODO: Get the Redux store from somewhere else
|
||||
const state = window.store.getState();
|
||||
if (!state.oidc || !state.oidc.user) {
|
||||
return;
|
||||
}
|
||||
// TODO: Get the Redux store from somewhere else
|
||||
const state = window.store.getState();
|
||||
if (!state.oidc || !state.oidc.user) {
|
||||
return;
|
||||
}
|
||||
|
||||
return state.oidc.user.access_token;
|
||||
}
|
||||
return state.oidc.user.access_token;
|
||||
};
|
||||
|
||||
cornerstoneWADOImageLoader.configure({
|
||||
beforeSend: function(xhr) {
|
||||
const headers = OHIF.DICOMWeb.getAuthorizationHeader();
|
||||
beforeSend: function(xhr) {
|
||||
const headers = OHIF.DICOMWeb.getAuthorizationHeader();
|
||||
|
||||
if (headers.Authorization) {
|
||||
xhr.setRequestHeader("Authorization", headers.Authorization);
|
||||
}
|
||||
if (headers.Authorization) {
|
||||
xhr.setRequestHeader('Authorization', headers.Authorization);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
import OHIF from 'ohif-core';
|
||||
import { api } from 'dicomweb-client';
|
||||
|
||||
const { plugins, utils } = OHIF;
|
||||
const { PLUGIN_TYPES } = plugins;
|
||||
|
||||
const SOP_CLASS_UIDS = {
|
||||
VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE: '1.2.840.10008.5.1.4.1.1.77.1.6'
|
||||
};
|
||||
|
||||
const dwc = api.DICOMwebClient;
|
||||
|
||||
const DicomMicrscopySopClassHandlerPlugin = {
|
||||
id: 'DicomMicroscopySopClassHandlerPlugin',
|
||||
type: PLUGIN_TYPES.SOP_CLASS_HANDLER,
|
||||
sopClassUids: [SOP_CLASS_UIDS.VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE],
|
||||
getDisplaySetFromSeries(series, study) {
|
||||
const instance = series.getFirstInstance();
|
||||
|
||||
const headers = OHIF.DICOMWeb.getAuthorizationHeader();
|
||||
console.warn(headers);
|
||||
|
||||
debugger;
|
||||
|
||||
const dicomWebClient = new dwc({
|
||||
url: study.getData().wadoRoot,
|
||||
headers
|
||||
});
|
||||
|
||||
// Note: We are passing the dicomweb client into each viewport!
|
||||
|
||||
return {
|
||||
plugin: 'microscopy',
|
||||
displaySetInstanceUid: utils.guid(),
|
||||
dicomWebClient,
|
||||
sopInstanceUid: instance.getSOPInstanceUID(),
|
||||
seriesInstanceUid: series.getSeriesInstanceUID(),
|
||||
studyInstanceUid: study.getStudyInstanceUID()
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export default DicomMicrscopySopClassHandlerPlugin;
|
||||
@ -0,0 +1,86 @@
|
||||
import React, { Component } from 'react';
|
||||
import { api } from 'dicom-microscopy-viewer';
|
||||
|
||||
const microscopyViewer = api.VLWholeSlideMicroscopyImageViewer;
|
||||
|
||||
class DicomMicroscopyViewport extends Component {
|
||||
state = {
|
||||
error: null
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.container = React.createRef();
|
||||
}
|
||||
|
||||
// install the microscopy renderer into the web page.
|
||||
// you should only do this once.
|
||||
installOpenLayersRenderer(container, displaySet) {
|
||||
const dicomWebClient = displaySet.dicomWebClient;
|
||||
|
||||
const searchInstanceOptions = {
|
||||
studyInstanceUID: displaySet.studyInstanceUid,
|
||||
seriesInstanceUID: displaySet.seriesInstanceUid
|
||||
};
|
||||
|
||||
dicomWebClient
|
||||
.searchForInstances(searchInstanceOptions)
|
||||
.then(instances => {
|
||||
const promises = [];
|
||||
for (let i = 0; i < instances.length; i++) {
|
||||
const sopInstanceUID = instances[i]['00080018']['Value'][0];
|
||||
const retrieveInstanceOptions = {
|
||||
studyInstanceUID: displaySet.studyInstanceUid,
|
||||
seriesInstanceUID: displaySet.seriesInstanceUid,
|
||||
sopInstanceUID
|
||||
};
|
||||
|
||||
const promise = dicomWebClient
|
||||
.retrieveInstanceMetadata(retrieveInstanceOptions)
|
||||
.then(metadata => {
|
||||
const imageType = metadata[0]['00080008']['Value'];
|
||||
if (imageType[2] === 'VOLUME') {
|
||||
return metadata[0];
|
||||
}
|
||||
});
|
||||
promises.push(promise);
|
||||
}
|
||||
return Promise.all(promises);
|
||||
})
|
||||
.then(metadata => {
|
||||
console.warn(metadata);
|
||||
metadata = metadata.filter(m => m);
|
||||
|
||||
const viewer = new microscopyViewer({
|
||||
client: dicomWebClient,
|
||||
metadata
|
||||
});
|
||||
|
||||
debugger;
|
||||
|
||||
viewer.render({ container });
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { studies, displaySet } = this.props.viewportData;
|
||||
|
||||
this.installOpenLayersRenderer(this.container.current, displaySet);
|
||||
}
|
||||
|
||||
render() {
|
||||
const style = { width: '100%', height: '100%' };
|
||||
return (
|
||||
<div className={'DicomMicroscopyViewer'} style={style}>
|
||||
{this.state.error ? (
|
||||
<h2>{JSON.stringify(this.state.error)}</h2>
|
||||
) : (
|
||||
<div ref={this.container} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DicomMicroscopyViewport;
|
||||
@ -1,8 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cornerstone from 'cornerstone-core';
|
||||
import cornerstoneTools from 'cornerstone-tools';
|
||||
import OHIF from 'ohif-core';
|
||||
//import OHIF from 'ohif-core';
|
||||
//import { CineDialog } from 'react-viewerbase';
|
||||
|
||||
import WhiteLabellingContext from '../WhiteLabellingContext.js';
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
* Entry point index.js for development
|
||||
*/
|
||||
|
||||
|
||||
import App from './App.js';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
@ -21,7 +20,7 @@ Example config with OIDC
|
||||
// Try going to:
|
||||
// http://localhost:5000/viewer/1.3.6.1.4.1.25403.345050719074.3824.20170126082328.1
|
||||
// http://ohif-viewer-react.s3-website-us-east-1.amazonaws.com/viewer/1.3.6.1.4.1.25403.345050719074.3824.20170126082328.1
|
||||
props.servers = {
|
||||
/*props.servers = {
|
||||
"dicomWeb": [{
|
||||
"name": "DCM4CHEE",
|
||||
"wadoUriRoot": "https://cancer.crowds-cure.org/dcm4chee-arc/aets/DCM4CHEE/wado",
|
||||
@ -49,7 +48,37 @@ props.oidc = [{
|
||||
"kc_idp_hint": "crowds-cure-cancer-auth0-oidc",
|
||||
"client_id": "crowds-cure-cancer"
|
||||
}
|
||||
}];
|
||||
}];*/
|
||||
|
||||
props.servers = {
|
||||
dicomWeb: [
|
||||
{
|
||||
name: 'DCM4CHEE',
|
||||
wadoUriRoot:
|
||||
'https://k8s-testing.ohif.org/dcm4chee-arc/aets/DCM4CHEE/wado',
|
||||
qidoRoot: 'https://k8s-testing.ohif.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
wadoRoot: 'https://k8s-testing.ohif.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
qidoSupportsIncludeField: true,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
requestOptions: {
|
||||
requestFromBrowser: true
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
props.oidc = [
|
||||
{
|
||||
authServerUrl: 'https://k8s-testing.ohif.org/auth/realms/dcm4che',
|
||||
authRedirectUri: routerBasename + '/callback',
|
||||
postLogoutRedirectUri: routerBasename + '/logout-redirect.html',
|
||||
clientId: 'ohif-viewer',
|
||||
responseType: 'id_token token',
|
||||
scope: 'email profile openid',
|
||||
revokeAccessTokenOnSignout: true
|
||||
}
|
||||
];
|
||||
|
||||
/* Example config without OIDC */
|
||||
// Try going to:
|
||||
@ -115,12 +144,10 @@ function RadicalImagingLogo() {
|
||||
);
|
||||
}
|
||||
|
||||
props.whiteLabelling = {
|
||||
/*props.whiteLabelling = {
|
||||
logoComponent: RadicalImagingLogo()
|
||||
};
|
||||
};*/
|
||||
|
||||
// TODO: Why do we need to do this? Something is wrong with our rollup settings
|
||||
//var Viewer = window.OHIFStandaloneViewer.App;
|
||||
var app = React.createElement(App, props, null);
|
||||
|
||||
ReactDOM.render(app, document.getElementById('root'));
|
||||
|
||||
@ -1 +1 @@
|
||||
export default '1242155351531';
|
||||
export default '84c949f2e68036ef488e09e05aed890a47e1a161';
|
||||
|
||||
@ -1 +1 @@
|
||||
export default '0.0.0';
|
||||
export default '0.0.6';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1
Packages-react/plugins/OpenLayersPlugin
Submodule
1
Packages-react/plugins/OpenLayersPlugin
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 2405290b1e5e80d13bae5358625463605eb83930
|
||||
@ -1 +1 @@
|
||||
Subproject commit 3af04fe6f45b5582d1d672696736d1668c9ea985
|
||||
Subproject commit 1a66caa34d5a841ef414437a53093f7d22be840c
|
||||
Loading…
Reference in New Issue
Block a user