StudyBrowser almost works
This commit is contained in:
parent
ec2df02e83
commit
70b7158c9b
@ -34,8 +34,8 @@
|
||||
"cornerstone-core": "^2.3.0",
|
||||
"cornerstone-math": "^0.1.8",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dcmjs": "^0.12.3",
|
||||
"cornerstone-wado-image-loader": "^3.1.2",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
|
||||
@ -12,6 +12,9 @@ const { setViewportSpecificData } = OHIF.redux.actions;
|
||||
|
||||
const commandsModule = ({ servicesManager }) => {
|
||||
const actions = {
|
||||
getCornerstoneLibraries: () => {
|
||||
return { cornerstone, cornerstoneTools };
|
||||
},
|
||||
rotateViewport: ({ viewports, rotation }) => {
|
||||
const enabledElement = getEnabledElement(viewports.activeViewportIndex);
|
||||
|
||||
@ -262,23 +265,28 @@ const commandsModule = ({ servicesManager }) => {
|
||||
StudyInstanceUID,
|
||||
SOPInstanceUID,
|
||||
frameIndex,
|
||||
activeViewportIndex
|
||||
activeViewportIndex,
|
||||
}) => {
|
||||
const study = studyMetadataManager.get(StudyInstanceUID);
|
||||
|
||||
const displaySet = study.findDisplaySet(ds => {
|
||||
return ds.images && ds.images.find(i => i.getSOPInstanceUID() === SOPInstanceUID)
|
||||
return (
|
||||
ds.images &&
|
||||
ds.images.find(i => i.getSOPInstanceUID() === SOPInstanceUID)
|
||||
);
|
||||
});
|
||||
|
||||
displaySet.SOPInstanceUID = SOPInstanceUID;
|
||||
displaySet.frameIndex = frameIndex;
|
||||
|
||||
window.store.dispatch(setViewportSpecificData(activeViewportIndex, displaySet));
|
||||
window.store.dispatch(
|
||||
setViewportSpecificData(activeViewportIndex, displaySet)
|
||||
);
|
||||
|
||||
cornerstone.getEnabledElements().forEach(enabledElement => {
|
||||
cornerstone.updateImage(enabledElement.element);
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const definitions = {
|
||||
@ -287,6 +295,12 @@ const commandsModule = ({ servicesManager }) => {
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
},
|
||||
getCornerstoneLibraries: {
|
||||
commandFn: actions.getCornerstoneLibraries,
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
context: 'VIEWER',
|
||||
},
|
||||
getNearbyToolData: {
|
||||
commandFn: actions.getNearbyToolData,
|
||||
storeContexts: [],
|
||||
|
||||
@ -4,6 +4,7 @@ import cornerstone from 'cornerstone-core';
|
||||
import csTools from 'cornerstone-tools';
|
||||
import merge from 'lodash.merge';
|
||||
import initCornerstoneTools from './initCornerstoneTools.js';
|
||||
import initWADOImageLoader from './initWADOImageLoader.js';
|
||||
import measurementServiceMappingsFactory from './utils/measurementServiceMappings/measurementServiceMappingsFactory';
|
||||
|
||||
/**
|
||||
|
||||
18
extensions/cornerstone/src/initWADOImageLoader.js
Normal file
18
extensions/cornerstone/src/initWADOImageLoader.js
Normal file
@ -0,0 +1,18 @@
|
||||
import cornerstone from 'cornerstone-core';
|
||||
import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
|
||||
import dicomParser from 'dicom-parser';
|
||||
|
||||
//import { initWebWorkers } from './utils/index.js';
|
||||
|
||||
cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
|
||||
cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
|
||||
|
||||
cornerstoneWADOImageLoader.configure({
|
||||
beforeSend: function(xhr) {
|
||||
/*const headers = OHIF.DICOMWeb.getAuthorizationHeader();
|
||||
|
||||
if (headers.Authorization) {
|
||||
xhr.setRequestHeader('Authorization', headers.Authorization);
|
||||
}*/
|
||||
},
|
||||
});
|
||||
@ -31,7 +31,7 @@ function ViewerLayout({
|
||||
const getPanelData = id => {
|
||||
const entry = extensionManager.getModuleEntry(id);
|
||||
// TODO, not sure why sidepanel content has to be JSX, and not a children prop?
|
||||
const content = entry.component({ extensionManager });
|
||||
const content = entry.component;
|
||||
|
||||
return {
|
||||
iconName: entry.iconName,
|
||||
|
||||
@ -7,37 +7,86 @@ import {
|
||||
displaySetManager,
|
||||
} from '@ohif/core';
|
||||
|
||||
function StudyBrowserPanel({ extensionManager }) {
|
||||
// TODO: need to check how this is intended to be passed in
|
||||
const dataSource = extensionManager.dataSourceMap.dicomweb[0];
|
||||
// Create map in local state from displaySetInstanceUids to thumbnails
|
||||
// Get thumbnail imageId from displaySet
|
||||
// When displaySetInstanceUids change, initiate async render into canvas
|
||||
// Get image data-uri from canvas offscreen
|
||||
// Set image data-uri into state (NOTE: This will probably end up in the fucking browser cache, NEED to find a way to prevent that from happening)
|
||||
// state triggers rerender
|
||||
//
|
||||
// TODO:
|
||||
// - No loading UI exists yet
|
||||
// - cancel promises when component is destroyed
|
||||
// - show errors in UI for thumbnails if promise fails
|
||||
|
||||
function getImageSrc(imageId, { cornerstone }) {
|
||||
// TODO: Switch to async/await when it stops failing
|
||||
return new Promise((resolve, reject) => {
|
||||
cornerstone.loadAndCacheImage(imageId).then(image => {
|
||||
const canvas = document.createElement('canvas');
|
||||
cornerstone.renderToCanvas(canvas, image);
|
||||
|
||||
resolve(canvas.toDataURL());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function StudyBrowserPanel({ getDataSources, commandsManager }) {
|
||||
const viewModel = useViewModel();
|
||||
|
||||
const dataSource = getDataSources('dicomweb')[0];
|
||||
const [studyData, setStudyData] = useState([]);
|
||||
const [thumbnailImageSrcMap, setThumbnailImageSrcMap] = useState(new Map());
|
||||
const updateThumbnailMap = (k, v) => {
|
||||
setThumbnailImageSrcMap(thumbnailImageSrcMap.set(k, v));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const command = commandsManager.getCommand(
|
||||
'getCornerstoneLibraries',
|
||||
'VIEWER'
|
||||
);
|
||||
|
||||
if (!command) {
|
||||
throw new Error('Required command not found');
|
||||
}
|
||||
|
||||
const { cornerstone, cornerstoneTools } = command.commandFn();
|
||||
|
||||
if (!viewModel.displaySetInstanceUids.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
viewModel.displaySetInstanceUids.forEach(uid => {
|
||||
const imageIds = dataSource.getImageIdsForDisplaySet(uid);
|
||||
const imageId = imageIds[0];
|
||||
|
||||
getImageSrc(imageId, { cornerstone }).then(imageSrc => {
|
||||
updateThumbnailMap(uid, imageSrc);
|
||||
});
|
||||
});
|
||||
}, [viewModel.displaySetInstanceUids]);
|
||||
|
||||
// TODO
|
||||
const viewportData = []; //useViewportGrid();
|
||||
const seriesTracking = {}; //useSeriesTracking();
|
||||
|
||||
const [studyData, setStudyData] = useState([]);
|
||||
|
||||
console.log(viewModel);
|
||||
|
||||
const displaySets = viewModel.displaySetInstanceUids.map(
|
||||
displaySetManager.getDisplaySetByUID
|
||||
);
|
||||
|
||||
console.log(displaySets);
|
||||
|
||||
if (!displaySets.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// - Put this in something so it only runs once
|
||||
// - Have update the query update the dicom data store at the study level and then have this component use the data in the view model
|
||||
useEffect(() => {
|
||||
if (!viewModel.displaySetInstanceUids.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dSets = viewModel.displaySetInstanceUids.map(
|
||||
displaySetManager.getDisplaySetByUID
|
||||
);
|
||||
|
||||
const aDisplaySet = dSets[0];
|
||||
const firstStudy = dicomMetadataStore.getStudy(
|
||||
aDisplaySet.StudyInstanceUID
|
||||
@ -74,6 +123,7 @@ function StudyBrowserPanel({ extensionManager }) {
|
||||
modality: ds.Modality,
|
||||
date: ds.SeriesDate,
|
||||
numInstances: ds.numImageFrames,
|
||||
//imageSrc,
|
||||
};
|
||||
|
||||
const displaySetViewportData = viewportData.find(
|
||||
@ -203,21 +253,30 @@ function StudyBrowserPanel({ extensionManager }) {
|
||||
return <StudyBrowser tabs={tabs} onClickStudy={memoOnClickStudy} />;
|
||||
}
|
||||
|
||||
function getPanelModule() {
|
||||
function getPanelModule({ getDataSources, commandsManager }) {
|
||||
const wrappedStudyBrowserPanel = () => {
|
||||
return (
|
||||
<StudyBrowserPanel
|
||||
getDataSources={getDataSources}
|
||||
commandsManager={commandsManager}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return [
|
||||
{
|
||||
name: 'seriesList',
|
||||
iconName: 'group-layers',
|
||||
iconLabel: 'Studies',
|
||||
label: 'Studies',
|
||||
component: StudyBrowserPanel,
|
||||
component: wrappedStudyBrowserPanel,
|
||||
},
|
||||
{
|
||||
name: 'measure',
|
||||
iconName: 'list-bullets',
|
||||
iconLabel: 'Measure',
|
||||
label: 'Measurements',
|
||||
component: StudyBrowserPanel,
|
||||
component: wrappedStudyBrowserPanel,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@ -28,13 +28,12 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^0.50.0",
|
||||
"@ohif/i18n": "^0.50.0",
|
||||
"@ohif/ui": "^0.50.0",
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dcmjs": "^0.12.2",
|
||||
"@ohif/core": "^2.5.1",
|
||||
"@ohif/i18n": "^0.52.6",
|
||||
"@ohif/ui": "^2.0.0",
|
||||
"cornerstone-core": "^2.3.0",
|
||||
"cornerstone-wado-image-loader": "^3.1.2",
|
||||
"dcmjs": "0.12.2",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"i18next": "^17.0.3",
|
||||
"i18next-browser-languagedetector": "^3.0.1",
|
||||
@ -56,9 +55,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohif/core": "^2.9.6",
|
||||
"@ohif/ui": "^1.4.4",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"@ohif/ui": "^2.0.0",
|
||||
"cornerstone-core": "^2.3.0",
|
||||
"cornerstone-wado-image-loader": "^3.1.2",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"gh-pages": "^2.0.1",
|
||||
"i18next": "^17.0.3",
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
"peerDependencies": {
|
||||
"cornerstone-core": "^2.3.0",
|
||||
"cornerstone-tools": "^4.12.0",
|
||||
"cornerstone-wado-image-loader": "^3.0.0",
|
||||
"cornerstone-wado-image-loader": "^3.1.2",
|
||||
"dicom-parser": "^1.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@ -177,6 +177,7 @@ export default class ExtensionManager {
|
||||
|
||||
try {
|
||||
const extensionModule = getModuleFn({
|
||||
getDataSources: this.getDataSources,
|
||||
servicesManager: this._servicesManager,
|
||||
commandsManager: this._commandsManager,
|
||||
appConfig: this._appConfig,
|
||||
|
||||
@ -141,7 +141,7 @@ const SidePanel = ({
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
{childComponent.content}
|
||||
<childComponent.content/>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<React.Fragment>{getPanelButtons()}</React.Fragment>
|
||||
|
||||
@ -18,6 +18,8 @@ const ThumbnailList = ({ thumbnails }) => {
|
||||
viewportIdentificator,
|
||||
isTracked,
|
||||
isActive,
|
||||
imageSrc,
|
||||
imageAltText,
|
||||
}) => {
|
||||
switch (componentType) {
|
||||
case 'thumbnail':
|
||||
@ -27,6 +29,9 @@ const ThumbnailList = ({ thumbnails }) => {
|
||||
description={description}
|
||||
seriesNumber={seriesNumber}
|
||||
numInstances={numInstances}
|
||||
imageSrc={imageSrc}
|
||||
imageAltText={imageAltText}
|
||||
viewportIdentificator={viewportIdentificator}
|
||||
isActive={isActive}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
@ -48,6 +53,8 @@ const ThumbnailList = ({ thumbnails }) => {
|
||||
description={description}
|
||||
seriesNumber={seriesNumber}
|
||||
numInstances={numInstances}
|
||||
imageSrc={imageSrc}
|
||||
imageAltText={imageAltText}
|
||||
viewportIdentificator={viewportIdentificator}
|
||||
isTracked={isTracked}
|
||||
isActive={isActive}
|
||||
|
||||
@ -67,8 +67,8 @@
|
||||
"core-js": "^3.2.1",
|
||||
"cornerstone-math": "^0.1.8",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dcmjs": "^0.12.2",
|
||||
"cornerstone-wado-image-loader": "^3.1.2",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"dicomweb-client": "^0.4.4",
|
||||
"dotenv-webpack": "^1.7.0",
|
||||
|
||||
@ -5791,10 +5791,10 @@ cornerstone-tools@^4.12.0:
|
||||
"@babel/runtime" "7.1.2"
|
||||
cornerstone-math "0.1.7"
|
||||
|
||||
cornerstone-wado-image-loader@^3.0.0:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cornerstone-wado-image-loader/-/cornerstone-wado-image-loader-3.0.6.tgz#7b2be91f8f658de3a7474e029aa8314a35725132"
|
||||
integrity sha512-1luWOh1GzkboZ3uxfu4T8vh7K9nlDiiEbQ4dYIY9oobRZVZQbQiLT8wEZPbb4JTUe7UWJISHPCNgtAU8UE9DNw==
|
||||
cornerstone-wado-image-loader@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/cornerstone-wado-image-loader/-/cornerstone-wado-image-loader-3.1.2.tgz#5113c317938510670061d11d05deb70266e4a35e"
|
||||
integrity sha512-cnDHrsa2GREqdMb9pjsoHgue+suHkDyuS/W0R8ZVD1lr+LQdv56dVM8oK9n7yOeorA4/IXG8630IL7uHdCHAQA==
|
||||
dependencies:
|
||||
dicom-parser "^1.8.3"
|
||||
pako "^1.0.10"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user