display viewport.
This commit is contained in:
parent
7c0d93f011
commit
4fc3169fed
@ -1,6 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import ConnectedCornerstoneViewport from './ConnectedCornerstoneViewport';
|
||||
import CornerstoneViewport from 'react-cornerstone-viewport';
|
||||
//import ConnectedCornerstoneViewport from './ConnectedCornerstoneViewport';
|
||||
import OHIF from '@ohif/core';
|
||||
import PropTypes from 'prop-types';
|
||||
import cornerstone from 'cornerstone-core';
|
||||
@ -18,9 +18,9 @@ class OHIFCornerstoneViewport extends Component {
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
studies: PropTypes.object,
|
||||
displaySet: PropTypes.object,
|
||||
viewportIndex: PropTypes.number,
|
||||
dataSource: PropTypes.object,
|
||||
children: PropTypes.node,
|
||||
customProps: PropTypes.object,
|
||||
};
|
||||
@ -39,98 +39,57 @@ class OHIFCornerstoneViewport extends Component {
|
||||
/**
|
||||
* Obtain the CornerstoneTools Stack for the specified display set.
|
||||
*
|
||||
* @param {Object[]} studies
|
||||
* @param {String} StudyInstanceUID
|
||||
* @param {String} displaySetInstanceUID
|
||||
* @param {String} [SOPInstanceUID]
|
||||
* @param {Number} [frameIndex=1]
|
||||
* @param {Object} displaySet
|
||||
* @param {Object} dataSource
|
||||
* @return {Object} CornerstoneTools Stack
|
||||
*/
|
||||
static getCornerstoneStack(
|
||||
studies,
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
SOPInstanceUID,
|
||||
frameIndex = 0
|
||||
) {
|
||||
if (!studies || !studies.length) {
|
||||
throw new Error('Studies not provided.');
|
||||
}
|
||||
|
||||
if (!StudyInstanceUID) {
|
||||
throw new Error('StudyInstanceUID not provided.');
|
||||
}
|
||||
|
||||
if (!displaySetInstanceUID) {
|
||||
throw new Error('StudyInstanceUID not provided.');
|
||||
}
|
||||
|
||||
// Create shortcut to displaySet
|
||||
const study = studies.find(
|
||||
study => study.StudyInstanceUID === StudyInstanceUID
|
||||
);
|
||||
|
||||
if (!study) {
|
||||
throw new Error('Study not found.');
|
||||
}
|
||||
|
||||
const displaySet = study.displaySets.find(set => {
|
||||
return set.displaySetInstanceUID === displaySetInstanceUID;
|
||||
});
|
||||
|
||||
if (!displaySet) {
|
||||
throw new Error('Display Set not found.');
|
||||
}
|
||||
static getCornerstoneStack(displaySet, dataSource) {
|
||||
const { frameIndex } = displaySet;
|
||||
|
||||
// Get stack from Stack Manager
|
||||
const storedStack = StackManager.findOrCreateStack(study, displaySet);
|
||||
const storedStack = StackManager.findOrCreateStack(displaySet, dataSource);
|
||||
|
||||
// Clone the stack here so we don't mutate it
|
||||
const stack = Object.assign({}, storedStack);
|
||||
|
||||
stack.currentImageIdIndex = frameIndex;
|
||||
|
||||
if (SOPInstanceUID) {
|
||||
const index = stack.imageIds.findIndex(imageId => {
|
||||
const imageIdSOPInstanceUID = cornerstone.metaData.get(
|
||||
'SOPInstanceUID',
|
||||
imageId
|
||||
);
|
||||
// TODO -> Do we ever use this like this?
|
||||
// if (SOPInstanceUID) {
|
||||
// const index = stack.imageIds.findIndex(imageId => {
|
||||
// const imageIdSOPInstanceUID = cornerstone.metaData.get(
|
||||
// 'SOPInstanceUID',
|
||||
// imageId
|
||||
// );
|
||||
|
||||
return imageIdSOPInstanceUID === SOPInstanceUID;
|
||||
});
|
||||
// return imageIdSOPInstanceUID === SOPInstanceUID;
|
||||
// });
|
||||
|
||||
if (index > -1) {
|
||||
stack.currentImageIdIndex = index;
|
||||
} else {
|
||||
console.warn(
|
||||
'SOPInstanceUID provided was not found in specified DisplaySet'
|
||||
);
|
||||
}
|
||||
}
|
||||
// if (index > -1) {
|
||||
// stack.currentImageIdIndex = index;
|
||||
// } else {
|
||||
// console.warn(
|
||||
// 'SOPInstanceUID provided was not found in specified DisplaySet'
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
getViewportData = async (
|
||||
studies,
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
SOPInstanceUID,
|
||||
frameIndex
|
||||
) => {
|
||||
getViewportData = async displaySet => {
|
||||
let viewportData;
|
||||
|
||||
const { dataSource } = this.props;
|
||||
|
||||
const stack = OHIFCornerstoneViewport.getCornerstoneStack(
|
||||
studies,
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
SOPInstanceUID,
|
||||
frameIndex
|
||||
displaySet,
|
||||
dataSource
|
||||
);
|
||||
|
||||
viewportData = {
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
StudyInstanceUID: displaySet.StudyInstanceUID,
|
||||
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
||||
stack,
|
||||
};
|
||||
|
||||
@ -138,32 +97,24 @@ class OHIFCornerstoneViewport extends Component {
|
||||
};
|
||||
|
||||
setStateFromProps() {
|
||||
const { studies, displaySet } = this.props.viewportData;
|
||||
const { displaySet } = this.props;
|
||||
const {
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
sopClassUIDs,
|
||||
SOPInstanceUID,
|
||||
frameIndex,
|
||||
sopClassUids,
|
||||
} = displaySet;
|
||||
|
||||
if (!StudyInstanceUID || !displaySetInstanceUID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sopClassUIDs && sopClassUIDs.length > 1) {
|
||||
if (sopClassUids && sopClassUids.length > 1) {
|
||||
console.warn(
|
||||
'More than one SOPClassUID in the same series is not yet supported.'
|
||||
);
|
||||
}
|
||||
|
||||
this.getViewportData(
|
||||
studies,
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
SOPInstanceUID,
|
||||
frameIndex
|
||||
).then(viewportData => {
|
||||
this.getViewportData(displaySet).then(viewportData => {
|
||||
this.setState({
|
||||
viewportData,
|
||||
});
|
||||
@ -175,8 +126,8 @@ class OHIFCornerstoneViewport extends Component {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { displaySet } = this.props.viewportData;
|
||||
const prevDisplaySet = prevProps.viewportData.displaySet;
|
||||
const { displaySet } = this.props;
|
||||
const prevDisplaySet = prevProps.displaySet;
|
||||
|
||||
if (
|
||||
displaySet.displaySetInstanceUID !==
|
||||
@ -232,9 +183,11 @@ class OHIFCornerstoneViewport extends Component {
|
||||
700
|
||||
);
|
||||
|
||||
// TODO -> We may still want a wrapped component to define all the measurement api stuff.
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConnectedCornerstoneViewport
|
||||
{/* <ConnectedCornerstoneViewport
|
||||
viewportIndex={viewportIndex}
|
||||
imageIds={imageIds}
|
||||
imageIdIndex={currentImageIdIndex}
|
||||
@ -246,6 +199,16 @@ class OHIFCornerstoneViewport extends Component {
|
||||
// onElementEnabled={() => {}}
|
||||
// setViewportActive{() => {}}
|
||||
{...this.props.customProps}
|
||||
/> */}
|
||||
<CornerstoneViewport
|
||||
viewportIndex={viewportIndex}
|
||||
imageIds={imageIds}
|
||||
imageIdIndex={currentImageIdIndex}
|
||||
onNewImage={debouncedNewImageHandler}
|
||||
isActive={true} // todo
|
||||
isStackPrefetchEnabled={true} // todo
|
||||
isPlaying={false}
|
||||
frameRate={24}
|
||||
/>
|
||||
{childrenWithProps}
|
||||
</>
|
||||
|
||||
@ -130,9 +130,9 @@ function createDicomWebApi(dicomWebConfig) {
|
||||
},
|
||||
},
|
||||
},
|
||||
getImageIdsForDisplaySet(displaySetInstanceUid) {
|
||||
getImageIdsForDisplaySet(displaySetInstanceUID) {
|
||||
const displaySet = displaySetManager.getDisplaySetByUID(
|
||||
displaySetInstanceUid
|
||||
displaySetInstanceUID
|
||||
);
|
||||
|
||||
const images = displaySet.images;
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { SidePanel, Toolbar } from '@ohif/ui';
|
||||
//
|
||||
import Header from './Header.jsx';
|
||||
import { displaySetManager } from '@ohif/core';
|
||||
|
||||
function ViewerLayout({
|
||||
// From Extension Module Params
|
||||
@ -11,7 +12,8 @@ function ViewerLayout({
|
||||
leftPanels,
|
||||
rightPanels,
|
||||
toolBarLayout,
|
||||
displaySetInstanceUids,
|
||||
viewports,
|
||||
displaySetInstanceUIDs,
|
||||
ViewportGrid,
|
||||
}) {
|
||||
/**
|
||||
@ -28,6 +30,17 @@ function ViewerLayout({
|
||||
};
|
||||
}, []);
|
||||
|
||||
// TODO -> Need some way of selecting which displaySets hit the viewports.
|
||||
const [viewportData, setViewportData] = useState([]);
|
||||
|
||||
console.log(displaySetInstanceUIDs);
|
||||
|
||||
useEffect(() => {
|
||||
setViewportData([
|
||||
displaySetManager.getDisplaySetByUID(displaySetInstanceUIDs[0]),
|
||||
]);
|
||||
}, [displaySetInstanceUIDs]);
|
||||
|
||||
const getPanelData = id => {
|
||||
const entry = extensionManager.getModuleEntry(id);
|
||||
// TODO, not sure why sidepanel content has to be JSX, and not a children prop?
|
||||
@ -42,11 +55,22 @@ function ViewerLayout({
|
||||
};
|
||||
};
|
||||
|
||||
const getViewportComponentData = viewportComponent => {
|
||||
const entry = extensionManager.getModuleEntry(viewportComponent.namespace);
|
||||
|
||||
return {
|
||||
component: entry.component,
|
||||
displaySetsToDisplay: viewportComponent.displaySetsToDisplay,
|
||||
};
|
||||
};
|
||||
|
||||
const leftPanelComponents = leftPanels.map(getPanelData);
|
||||
const rightPanelComponents = rightPanels.map(getPanelData);
|
||||
|
||||
console.warn(displaySetInstanceUids);
|
||||
console.warn(toolBarLayout);
|
||||
const viewportComponents = viewports.map(getViewportComponentData);
|
||||
|
||||
console.log(displaySetInstanceUIDs);
|
||||
console.log(toolBarLayout);
|
||||
|
||||
const [primaryToolBarLayout, secondaryToolBarLayout] = toolBarLayout;
|
||||
|
||||
@ -72,7 +96,10 @@ function ViewerLayout({
|
||||
<Toolbar type="secondary" tools={secondaryToolBarLayout.tools} />
|
||||
</div>
|
||||
<div className="flex flex-1 h-full overflow-hidden bg-black items-center justify-center pb-2 pt-1">
|
||||
<ViewportGrid />
|
||||
<ViewportGrid
|
||||
viewportData={viewportData}
|
||||
viewportComponents={viewportComponents}
|
||||
/>
|
||||
{/*
|
||||
viewportContents={[
|
||||
<Viewport
|
||||
@ -152,7 +179,7 @@ ViewerLayout.propTypes = {
|
||||
moreTools: PropTypes.array,
|
||||
})
|
||||
).isRequired,
|
||||
displaySetInstanceUids: PropTypes.any.isRequired,
|
||||
displaySetInstanceUIDs: PropTypes.any.isRequired,
|
||||
leftPanels: PropTypes.array,
|
||||
rightPanels: PropTypes.array,
|
||||
/** Responsible for rendering our grid of viewports; provided by consuming application */
|
||||
|
||||
@ -40,7 +40,7 @@ function StudyBrowserPanel({ getDataSources, commandsManager }) {
|
||||
const seriesTracking = {}; //useSeriesTracking();
|
||||
|
||||
useEffect(() => {
|
||||
if (!viewModel.displaySetInstanceUids.length) {
|
||||
if (!viewModel.displaySetInstanceUIDs.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ function StudyBrowserPanel({ getDataSources, commandsManager }) {
|
||||
|
||||
const { cornerstone, cornerstoneTools } = command.commandFn();
|
||||
|
||||
viewModel.displaySetInstanceUids.forEach(uid => {
|
||||
viewModel.displaySetInstanceUIDs.forEach(uid => {
|
||||
const imageIds = dataSource.getImageIdsForDisplaySet(uid);
|
||||
const imageId = imageIds[Math.floor(imageIds.length / 2)];
|
||||
|
||||
@ -68,7 +68,7 @@ function StudyBrowserPanel({ getDataSources, commandsManager }) {
|
||||
});
|
||||
});
|
||||
|
||||
const displaySets = viewModel.displaySetInstanceUids.map(
|
||||
const displaySets = viewModel.displaySetInstanceUIDs.map(
|
||||
displaySetManager.getDisplaySetByUID
|
||||
);
|
||||
|
||||
@ -98,7 +98,7 @@ function StudyBrowserPanel({ getDataSources, commandsManager }) {
|
||||
const studiesFromInstanceData = {};
|
||||
displaySets.forEach(ds => {
|
||||
const displaySet = {
|
||||
displaySetInstanceUid: ds.displaySetInstanceUid,
|
||||
displaySetInstanceUID: ds.displaySetInstanceUID,
|
||||
description: ds.SeriesDescription,
|
||||
seriesNumber: ds.SeriesNumber,
|
||||
modality: ds.Modality,
|
||||
@ -107,7 +107,7 @@ function StudyBrowserPanel({ getDataSources, commandsManager }) {
|
||||
};
|
||||
|
||||
const displaySetViewportData = viewportData.find(
|
||||
a => a.displaySetInstanceUid === ds.displaySetInstanceUid
|
||||
a => a.displaySetInstanceUID === ds.displaySetInstanceUID
|
||||
);
|
||||
|
||||
if (displaySetViewportData) {
|
||||
@ -192,11 +192,11 @@ function StudyBrowserPanel({ getDataSources, commandsManager }) {
|
||||
});
|
||||
|
||||
return () => (isSubscribed = false);
|
||||
}, [viewModel.displaySetInstanceUids]);
|
||||
}, [viewModel.displaySetInstanceUIDs]);
|
||||
|
||||
studyData.forEach(study => {
|
||||
study.displaySets.forEach(ds => {
|
||||
ds.imageSrc = thumbnailImageSrcMap.get(ds.displaySetInstanceUid);
|
||||
ds.imageSrc = thumbnailImageSrcMap.get(ds.displaySetInstanceUID);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ const makeDisplaySet = instances => {
|
||||
|
||||
// set appropriate attributes to image set...
|
||||
imageSet.setAttributes({
|
||||
displaySetInstanceUid: imageSet.uid, // create a local alias for the imageSet UID
|
||||
displaySetInstanceUID: imageSet.uid, // create a local alias for the imageSet UID
|
||||
SeriesDate: instance.SeriesDate,
|
||||
SeriesTime: instance.SeriesTime,
|
||||
SeriesInstanceUID: instance.SeriesInstanceUID,
|
||||
|
||||
@ -74,8 +74,7 @@ export default function mode({ modeConfiguration }) {
|
||||
rightPanels: ['org.ohif.default.panelModule.measure'],
|
||||
viewports: [
|
||||
{
|
||||
namespace:
|
||||
'org.ohif.cornerstone.viewportModule.OHIFCornerstoneViewport',
|
||||
namespace: 'org.ohif.cornerstone.viewportModule.cornerstone',
|
||||
displaySetsToDisplay: [
|
||||
'org.ohif.default.sopClassHandlerModule.stack',
|
||||
],
|
||||
|
||||
@ -3,7 +3,7 @@ import React, { Component, useContext } from 'react';
|
||||
/// TODO MAKE THIS PRETTY DANNY
|
||||
|
||||
const ViewModelContext = React.createContext({
|
||||
displaySetInstanceUids: [],
|
||||
displaySetInstanceUIDs: [],
|
||||
setDisplaySetInstanceUids: () => {},
|
||||
toolBarLayout: [],
|
||||
setToolBarLayout: () => {},
|
||||
@ -13,12 +13,12 @@ ViewModelContext.displayName = 'ViewModelContext';
|
||||
|
||||
class ViewModelProvider extends Component {
|
||||
state = {
|
||||
displaySetInstanceUids: [],
|
||||
displaySetInstanceUIDs: [],
|
||||
};
|
||||
|
||||
render() {
|
||||
const setDisplaySetInstanceUids = displaySetInstanceUids => {
|
||||
this.setState({ displaySetInstanceUids });
|
||||
const setDisplaySetInstanceUids = displaySetInstanceUIDs => {
|
||||
this.setState({ displaySetInstanceUIDs });
|
||||
};
|
||||
|
||||
const setToolBarLayout = toolBarLayout => {
|
||||
@ -28,7 +28,7 @@ class ViewModelProvider extends Component {
|
||||
return (
|
||||
<ViewModelContext.Provider
|
||||
value={{
|
||||
displaySetInstanceUids: this.state.displaySetInstanceUids,
|
||||
displaySetInstanceUIDs: this.state.displaySetInstanceUIDs,
|
||||
setDisplaySetInstanceUids,
|
||||
toolBarLayout: this.state.toolBarLayout,
|
||||
setToolBarLayout,
|
||||
|
||||
@ -8,26 +8,26 @@ class DisplaySetManager {
|
||||
this.SOPClassHandlerIds = SOPClassHandlerIds;
|
||||
|
||||
const {
|
||||
displaySetInstanceUids,
|
||||
displaySetInstanceUIDs,
|
||||
setDisplaySetInstanceUids,
|
||||
} = viewModelContext;
|
||||
|
||||
this.displaySetInstanceUids = displaySetInstanceUids;
|
||||
this.displaySetInstanceUIDs = displaySetInstanceUIDs;
|
||||
this.setDisplaySetInstanceUids = setDisplaySetInstanceUids;
|
||||
|
||||
// Reset displaySetInstanceUids
|
||||
// Reset displaySetInstanceUIDs
|
||||
this.setDisplaySetInstanceUids([]);
|
||||
}
|
||||
|
||||
_addDisplaySets(displaySets) {
|
||||
//const displayInstanceUids = [...this.displaySetInstanceUids];
|
||||
//const displayInstanceUids = [...this.displaySetInstanceUIDs];
|
||||
|
||||
const addedDisplaySetUids = [];
|
||||
|
||||
displaySets.forEach(displaySet => {
|
||||
this.displaySets.push(displaySet);
|
||||
|
||||
addedDisplaySetUids.push(displaySet.displaySetInstanceUid);
|
||||
addedDisplaySetUids.push(displaySet.displaySetInstanceUID);
|
||||
});
|
||||
|
||||
return addedDisplaySetUids;
|
||||
@ -39,9 +39,9 @@ class DisplaySetManager {
|
||||
);
|
||||
};
|
||||
|
||||
getDisplaySetByUID = displaySetInstanceUid => {
|
||||
getDisplaySetByUID = displaySetInstanceUID => {
|
||||
return this.displaySets.find(
|
||||
displaySet => displaySet.displaySetInstanceUid === displaySetInstanceUid
|
||||
displaySet => displaySet.displaySetInstanceUID === displaySetInstanceUID
|
||||
);
|
||||
};
|
||||
|
||||
@ -71,7 +71,7 @@ class DisplaySetManager {
|
||||
|
||||
if (cachedDisplaySets.length) {
|
||||
addedDisplaySetUids = cachedDisplaySets.map(
|
||||
displaySet => displaySet.displaySetInstanceUid
|
||||
displaySet => displaySet.displaySetInstanceUID
|
||||
);
|
||||
} else {
|
||||
const displaySets = handler.getDisplaySetsFromSeries(instances);
|
||||
@ -79,12 +79,12 @@ class DisplaySetManager {
|
||||
addedDisplaySetUids = this._addDisplaySets(displaySets);
|
||||
}
|
||||
|
||||
this.displaySetInstanceUids = [
|
||||
this.displaySetInstanceUIDs = [
|
||||
...addedDisplaySetUids,
|
||||
...this.displaySetInstanceUids,
|
||||
...this.displaySetInstanceUIDs,
|
||||
];
|
||||
|
||||
this.setDisplaySetInstanceUids(this.displaySetInstanceUids);
|
||||
this.setDisplaySetInstanceUids(this.displaySetInstanceUIDs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -105,9 +105,9 @@ export default class ExtensionManager {
|
||||
this._initToolBarModule(extensionModule, extensionId);
|
||||
break;
|
||||
|
||||
case MODULE_TYPES.VIEWPORT:
|
||||
case MODULE_TYPES.PANEL:
|
||||
case MODULE_TYPES.SOP_CLASS_HANDLER:
|
||||
case MODULE_TYPES.VIEWPORT:
|
||||
case MODULE_TYPES.CONTEXT:
|
||||
case MODULE_TYPES.LAYOUT_TEMPLATE:
|
||||
// Default for most extension points,
|
||||
@ -118,6 +118,7 @@ export default class ExtensionManager {
|
||||
`${extensionId}.${moduleType}.${element.name}`
|
||||
] = element;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
this.modules[moduleType].push({
|
||||
|
||||
@ -11,79 +11,37 @@ const stackUpdatedCallbacks = [];
|
||||
* Cornerstone meta data provider. This will be used to fill information
|
||||
* into the viewport overlays, and to calculate reference lines and orientation markers
|
||||
* @param {Object} stackMap stackMap object
|
||||
* @param {Object} study Study object
|
||||
* @param {Object} displaySet The set of images to make the stack from
|
||||
* @return {Array} Array with image IDs
|
||||
*/
|
||||
function createAndAddStack(stackMap, study, displaySet, stackUpdatedCallbacks) {
|
||||
const images = displaySet.images;
|
||||
function createAndAddStack(
|
||||
stackMap,
|
||||
displaySet,
|
||||
dataSource,
|
||||
stackUpdatedCallbacks
|
||||
) {
|
||||
const {
|
||||
images,
|
||||
displaySetInstanceUID,
|
||||
StudyInstanceUID,
|
||||
frameRate,
|
||||
isClip,
|
||||
} = displaySet;
|
||||
if (!images) {
|
||||
return;
|
||||
}
|
||||
|
||||
const numImages = images.length;
|
||||
const imageIds = [];
|
||||
let imageId;
|
||||
|
||||
displaySet.images.forEach((instance, imageIndex) => {
|
||||
const image = instance.getData();
|
||||
const metaData = {
|
||||
instance: image, // in this context, instance will be the data of the InstanceMetadata object...
|
||||
series: displaySet, // TODO: Check this
|
||||
study,
|
||||
numImages,
|
||||
imageIndex: imageIndex + 1,
|
||||
};
|
||||
|
||||
const naturalizedInstance = instance.getData().metadata;
|
||||
const NumberOfFrames = naturalizedInstance.NumberOfFrames;
|
||||
|
||||
if (NumberOfFrames > 1) {
|
||||
for (let i = 0; i < NumberOfFrames; i++) {
|
||||
metaData.frameNumber = i;
|
||||
imageId = getImageId(image, i);
|
||||
imageIds.push(imageId);
|
||||
|
||||
const {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
SOPInstanceUID,
|
||||
} = instance.getData().metadata;
|
||||
|
||||
metadataProvider.addImageIdToUIDs(imageId, {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
SOPInstanceUID,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
metaData.frameNumber = 1;
|
||||
imageId = getImageId(image);
|
||||
imageIds.push(imageId);
|
||||
|
||||
const {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
SOPInstanceUID,
|
||||
} = naturalizedInstance;
|
||||
|
||||
metadataProvider.addImageIdToUIDs(imageId, {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
SOPInstanceUID,
|
||||
});
|
||||
}
|
||||
});
|
||||
const imageIds = dataSource.getImageIdsForDisplaySet(displaySetInstanceUID);
|
||||
|
||||
const stack = {
|
||||
StudyInstanceUID: study.StudyInstanceUID,
|
||||
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
imageIds,
|
||||
frameRate: displaySet.frameRate,
|
||||
isClip: displaySet.isClip,
|
||||
frameRate,
|
||||
isClip,
|
||||
};
|
||||
|
||||
stackMap[displaySet.displaySetInstanceUID] = stack;
|
||||
stackMap[displaySetInstanceUID] = stack;
|
||||
|
||||
return stack;
|
||||
}
|
||||
@ -106,15 +64,14 @@ const StackManager = {
|
||||
},
|
||||
/**
|
||||
* Create a stack from an image set, as well as add in the metadata on a per image bases.
|
||||
* @param study The study who's metadata will be added
|
||||
* @param displaySet The set of images to make the stack from
|
||||
* @return {Array} Array with image IDs
|
||||
*/
|
||||
makeAndAddStack(study, displaySet) {
|
||||
makeAndAddStack(displaySet, dataSource) {
|
||||
return configuration.createAndAddStack(
|
||||
stackMap,
|
||||
study,
|
||||
displaySet,
|
||||
dataSource,
|
||||
stackUpdatedCallbacks
|
||||
);
|
||||
},
|
||||
@ -128,15 +85,14 @@ const StackManager = {
|
||||
},
|
||||
/**
|
||||
* Find a stack or reate one if it has not been created yet
|
||||
* @param study The study who's metadata will be added
|
||||
* @param displaySet The set of images to make the stack from
|
||||
* @return {Array} Array with image IDs
|
||||
*/
|
||||
findOrCreateStack(study, displaySet) {
|
||||
findOrCreateStack(displaySet, dataSource) {
|
||||
let stack = this.findStack(displaySet.displaySetInstanceUID);
|
||||
|
||||
if (!stack || !stack.imageIds) {
|
||||
stack = this.makeAndAddStack(study, displaySet);
|
||||
stack = this.makeAndAddStack(displaySet, dataSource);
|
||||
}
|
||||
|
||||
return stack;
|
||||
|
||||
@ -30,7 +30,7 @@ import studyMetadataManager from './studyMetadataManager';
|
||||
* Factory function to load and cache derived display sets.
|
||||
*
|
||||
* @param {object} referencedDisplaySet Display set
|
||||
* @param {string} referencedDisplaySet.displaySetInstanceUid Display set instance uid
|
||||
* @param {string} referencedDisplaySet.displaySetInstanceUID Display set instance uid
|
||||
* @param {string} referencedDisplaySet.seriesDate
|
||||
* @param {string} referencedDisplaySet.seriesTime
|
||||
* @param {string} referencedDisplaySet.seriesInstanceUid
|
||||
|
||||
@ -7,13 +7,13 @@ import { ButtonGroup, Button, StudyItem, ThumbnailList } from '@ohif/ui';
|
||||
const buttonClasses = 'text-white text-base border-none bg-black p-2 min-w-18';
|
||||
const activeButtonClasses = 'bg-primary-main';
|
||||
|
||||
const getInitialActiveTab = (tabs) => {
|
||||
const getInitialActiveTab = tabs => {
|
||||
return tabs && tabs[0] && tabs[0].name;
|
||||
};
|
||||
|
||||
const getTrackedSeries = (displaySets) => {
|
||||
const getTrackedSeries = displaySets => {
|
||||
let trackedSeries = 0;
|
||||
displaySets.forEach((displaySet) => {
|
||||
displaySets.forEach(displaySet => {
|
||||
if (displaySet.isTracked) {
|
||||
trackedSeries++;
|
||||
}
|
||||
@ -28,7 +28,7 @@ const StudyBrowser = ({ tabs, onClickStudy, onClickThumbnail }) => {
|
||||
const [thumbnailActive, setThumbnailActive] = useState(null);
|
||||
|
||||
const getTabContent = () => {
|
||||
const tabData = tabs.find((tab) => tab.name === tabActive);
|
||||
const tabData = tabs.find(tab => tab.name === tabActive);
|
||||
|
||||
if (!tabData || !tabData.studies || !Array.isArray(tabData.studies)) {
|
||||
return;
|
||||
@ -65,17 +65,16 @@ const StudyBrowser = ({ tabs, onClickStudy, onClickThumbnail }) => {
|
||||
<ThumbnailList
|
||||
thumbnails={displaySets}
|
||||
thumbnailActive={thumbnailActive}
|
||||
onThumbnailClick={(thumbnailId) => {
|
||||
setThumbnailActive(
|
||||
thumbnailId === thumbnailActive ? null : thumbnailId
|
||||
)
|
||||
onThumbnailClick={thumbnailId => {
|
||||
setThumbnailActive(
|
||||
thumbnailId === thumbnailActive ? null : thumbnailId
|
||||
);
|
||||
|
||||
if (onClickThumbnail) {
|
||||
// TODO: what is thumbnailId? Should pass display set instead
|
||||
onClickThumbnail(thumbnailId);
|
||||
}
|
||||
if (onClickThumbnail) {
|
||||
// TODO: what is thumbnailId? Should pass display set instead
|
||||
onClickThumbnail(thumbnailId);
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
@ -92,7 +91,7 @@ const StudyBrowser = ({ tabs, onClickStudy, onClickThumbnail }) => {
|
||||
color="inherit"
|
||||
className="border border-secondary-light rounded-md"
|
||||
>
|
||||
{tabs.map((tab) => {
|
||||
{tabs.map(tab => {
|
||||
const { name, label } = tab;
|
||||
const isActive = tabActive === name;
|
||||
return (
|
||||
@ -137,7 +136,7 @@ StudyBrowser.propTypes = {
|
||||
description: PropTypes.string,
|
||||
displaySets: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
displaySetInstanceUid: PropTypes.string.isRequired,
|
||||
displaySetInstanceUID: PropTypes.string.isRequired,
|
||||
imageSrc: PropTypes.string,
|
||||
imageAltText: PropTypes.string,
|
||||
seriesDate: PropTypes.string,
|
||||
|
||||
@ -27,7 +27,7 @@ import { StudyBrowser } from '@ohif/ui';
|
||||
modalities: 'CT,SR',
|
||||
displaySets: [
|
||||
{
|
||||
displaySetInstanceUid: 'f69f6asdasd48c-223e-db7f-c4af-b8906641a66e',
|
||||
displaySetInstanceUID: 'f69f6asdasd48c-223e-db7f-c4af-b8906641a66e',
|
||||
description: 'Multiple line image series description lorem sit',
|
||||
seriesNumber: 1,
|
||||
numInstances: 68,
|
||||
@ -36,7 +36,7 @@ import { StudyBrowser } from '@ohif/ui';
|
||||
isTracked: true,
|
||||
},
|
||||
{
|
||||
displaySetInstanceUid: 'f69f648c-223e-db7f-c4asdasdaf-b8906641a66e',
|
||||
displaySetInstanceUID: 'f69f648c-223e-db7f-c4asdasdaf-b8906641a66e',
|
||||
description: 'Multiple line image series description lorem sit',
|
||||
seriesNumber: 1,
|
||||
numInstances: 68,
|
||||
@ -44,14 +44,14 @@ import { StudyBrowser } from '@ohif/ui';
|
||||
viewportIdentificator: 'B',
|
||||
},
|
||||
{
|
||||
displaySetInstanceUid: 'f69f648c-223e-dasdasdb7f-c4af-b8906641a66e',
|
||||
displaySetInstanceUID: 'f69f648c-223e-dasdasdb7f-c4af-b8906641a66e',
|
||||
description: 'Multiple line image series description lorem sit',
|
||||
seriesNumber: 1,
|
||||
numInstances: 68,
|
||||
componentType: 'thumbnailTracked',
|
||||
},
|
||||
{
|
||||
displaySetInstanceUid: 'f69f648c-223e-db7f-c4afas-b8906asd641a66e',
|
||||
displaySetInstanceUID: 'f69f648c-223e-db7f-c4afas-b8906asd641a66e',
|
||||
description: 'Multiple line description lorem ipsum dolor sit amet',
|
||||
modality: 'SR',
|
||||
componentType: 'thumbnailNoImage',
|
||||
@ -67,7 +67,7 @@ import { StudyBrowser } from '@ohif/ui';
|
||||
modalities: 'CT',
|
||||
displaySets: [
|
||||
{
|
||||
displaySetInstanceUid: 'f69f648c-223e-db7f-c4af-b8906641a66e',
|
||||
displaySetInstanceUID: 'f69f648c-223e-db7f-c4af-b8906641a66e',
|
||||
description: 'Multiple line image series description lorem sit',
|
||||
seriesNumber: 1,
|
||||
numInstances: 68,
|
||||
|
||||
@ -8,7 +8,7 @@ const ThumbnailList = ({ thumbnails, thumbnailActive, onThumbnailClick }) => {
|
||||
<div className="bg-black py-3">
|
||||
{thumbnails.map(
|
||||
({
|
||||
displaySetInstanceUid,
|
||||
displaySetInstanceUID,
|
||||
description,
|
||||
seriesNumber,
|
||||
numInstances,
|
||||
@ -20,13 +20,13 @@ const ThumbnailList = ({ thumbnails, thumbnailActive, onThumbnailClick }) => {
|
||||
imageSrc,
|
||||
imageAltText,
|
||||
}) => {
|
||||
const isActive = thumbnailActive === displaySetInstanceUid;
|
||||
const isActive = thumbnailActive === displaySetInstanceUID;
|
||||
|
||||
switch (componentType) {
|
||||
case 'thumbnail':
|
||||
return (
|
||||
<Thumbnail
|
||||
key={displaySetInstanceUid}
|
||||
key={displaySetInstanceUID}
|
||||
description={description}
|
||||
seriesNumber={seriesNumber}
|
||||
numInstances={numInstances}
|
||||
@ -34,23 +34,23 @@ const ThumbnailList = ({ thumbnails, thumbnailActive, onThumbnailClick }) => {
|
||||
imageAltText={imageAltText}
|
||||
viewportIdentificator={viewportIdentificator}
|
||||
isActive={isActive}
|
||||
onClick={() => onThumbnailClick(displaySetInstanceUid)}
|
||||
onClick={() => onThumbnailClick(displaySetInstanceUID)}
|
||||
/>
|
||||
);
|
||||
case 'thumbnailNoImage':
|
||||
return (
|
||||
<ThumbnailNoImage
|
||||
key={displaySetInstanceUid}
|
||||
key={displaySetInstanceUID}
|
||||
modality={modality}
|
||||
seriesDate={seriesDate}
|
||||
description={description}
|
||||
onClick={() => onThumbnailClick(displaySetInstanceUid)}
|
||||
onClick={() => onThumbnailClick(displaySetInstanceUID)}
|
||||
/>
|
||||
);
|
||||
case 'thumbnailTracked':
|
||||
return (
|
||||
<ThumbnailTracked
|
||||
key={displaySetInstanceUid}
|
||||
key={displaySetInstanceUID}
|
||||
description={description}
|
||||
seriesNumber={seriesNumber}
|
||||
numInstances={numInstances}
|
||||
@ -59,7 +59,7 @@ const ThumbnailList = ({ thumbnails, thumbnailActive, onThumbnailClick }) => {
|
||||
viewportIdentificator={viewportIdentificator}
|
||||
isTracked={isTracked}
|
||||
isActive={isActive}
|
||||
onClick={() => onThumbnailClick(displaySetInstanceUid)}
|
||||
onClick={() => onThumbnailClick(displaySetInstanceUID)}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
@ -74,7 +74,7 @@ const ThumbnailList = ({ thumbnails, thumbnailActive, onThumbnailClick }) => {
|
||||
ThumbnailList.propTypes = {
|
||||
thumbnails: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
displaySetInstanceUid: PropTypes.string.isRequired,
|
||||
displaySetInstanceUID: PropTypes.string.isRequired,
|
||||
imageSrc: PropTypes.string,
|
||||
imageAltText: PropTypes.string,
|
||||
seriesDate: PropTypes.string,
|
||||
|
||||
@ -6,7 +6,7 @@ const studyWithSR = {
|
||||
modalities: 'CT,SR',
|
||||
displaySets: [
|
||||
{
|
||||
displaySetInstanceUid: 'f69f6asdasd48c-223e-db7f-c4af-b8906641a66e',
|
||||
displaySetInstanceUID: 'f69f6asdasd48c-223e-db7f-c4af-b8906641a66e',
|
||||
description: 'Multiple line image series description lorem sit',
|
||||
seriesNumber: 1,
|
||||
numInstances: 68,
|
||||
@ -15,7 +15,7 @@ const studyWithSR = {
|
||||
isTracked: true,
|
||||
},
|
||||
{
|
||||
displaySetInstanceUid: 'f69f648c-223e-db7f-c4asdasdaf-b8906641a66e',
|
||||
displaySetInstanceUID: 'f69f648c-223e-db7f-c4asdasdaf-b8906641a66e',
|
||||
description: 'Multiple line image series description lorem sit',
|
||||
seriesNumber: 1,
|
||||
numInstances: 68,
|
||||
@ -23,14 +23,14 @@ const studyWithSR = {
|
||||
viewportIdentificator: 'B',
|
||||
},
|
||||
{
|
||||
displaySetInstanceUid: 'f69f648c-223e-dasdasdb7f-c4af-b8906641a66e',
|
||||
displaySetInstanceUID: 'f69f648c-223e-dasdasdb7f-c4af-b8906641a66e',
|
||||
description: 'Multiple line image series description lorem sit',
|
||||
seriesNumber: 1,
|
||||
numInstances: 68,
|
||||
componentType: 'thumbnailTracked',
|
||||
},
|
||||
{
|
||||
displaySetInstanceUid: 'f69f648c-223e-db7f-c4afas-b8906asd641a66e',
|
||||
displaySetInstanceUID: 'f69f648c-223e-db7f-c4afas-b8906asd641a66e',
|
||||
description: 'Multiple line description lorem ipsum dolor sit amet',
|
||||
modality: 'SR',
|
||||
componentType: 'thumbnailNoImage',
|
||||
@ -47,7 +47,7 @@ const studySimple = {
|
||||
modalities: 'CT',
|
||||
displaySets: [
|
||||
{
|
||||
displaySetInstanceUid: 'f69f648c-223e-db7f-c4af-b8906641a66e',
|
||||
displaySetInstanceUID: 'f69f648c-223e-db7f-c4af-b8906641a66e',
|
||||
description: 'Multiple line image series description lorem sit',
|
||||
seriesNumber: 1,
|
||||
numInstances: 68,
|
||||
|
||||
@ -8,7 +8,12 @@ import { ViewportGrid, ViewportPane } from '@ohif/ui';
|
||||
// import EmptyViewport from './EmptyViewport.js';
|
||||
|
||||
function ViewerViewportGrid(props) {
|
||||
const { activeViewportIndex, displaySets, children } = props;
|
||||
const {
|
||||
activeViewportIndex,
|
||||
viewportData,
|
||||
viewportComponents,
|
||||
dataSource,
|
||||
} = props;
|
||||
|
||||
// From ViewportGridService and/or ContextProvider
|
||||
const [viewportGrid, setViewportGrid] = useState({
|
||||
@ -35,8 +40,20 @@ function ViewerViewportGrid(props) {
|
||||
|
||||
const getViewportPanes = () =>
|
||||
viewportGrid.viewports.map((viewport, viewportIndex) => {
|
||||
const someId = viewport.displaySetId;
|
||||
// const displaySet = displaySets[someId];
|
||||
const displaySet = viewportData[viewportIndex];
|
||||
|
||||
if (!displaySet) {
|
||||
return (
|
||||
<ViewportPane
|
||||
key={viewportIndex}
|
||||
className="m-1"
|
||||
onDrop={() => {
|
||||
/* setDisplaySet for Viewport */
|
||||
}}
|
||||
isActive={activeViewportIndex === viewportIndex}
|
||||
></ViewportPane>
|
||||
);
|
||||
}
|
||||
|
||||
// if (!displaySet) {
|
||||
// // TODO: Empty Viewport
|
||||
@ -48,14 +65,12 @@ function ViewerViewportGrid(props) {
|
||||
// ? displaySet.plugin
|
||||
// : layout.plugin;
|
||||
|
||||
// const ViewportComponent = _getViewportComponent(
|
||||
// data, // Why do we pass this as `ViewportData`, when that's not really what it is?
|
||||
// viewportIndex,
|
||||
// children,
|
||||
// TODO -> Need way for other viewport e.g. vtk to be used.
|
||||
|
||||
// pluginName,
|
||||
// defaultPluginName
|
||||
// );
|
||||
const ViewportComponent = _getViewportComponent(
|
||||
displaySet,
|
||||
viewportComponents
|
||||
);
|
||||
|
||||
return (
|
||||
<ViewportPane
|
||||
@ -66,13 +81,17 @@ function ViewerViewportGrid(props) {
|
||||
}}
|
||||
isActive={activeViewportIndex === viewportIndex}
|
||||
>
|
||||
{/* {ViewportComponent} */}
|
||||
<ViewportComponent
|
||||
displaySet={displaySet}
|
||||
viewportIndex={viewportIndex}
|
||||
dataSource={dataSource}
|
||||
/>
|
||||
</ViewportPane>
|
||||
);
|
||||
});
|
||||
|
||||
const ViewportPanes = React.useMemo(getViewportPanes, [
|
||||
children,
|
||||
viewportComponents,
|
||||
activeViewportIndex,
|
||||
]);
|
||||
|
||||
@ -86,16 +105,30 @@ function ViewerViewportGrid(props) {
|
||||
ViewerViewportGrid.propTypes = {
|
||||
// viewports: PropTypes.array.isRequired,
|
||||
activeViewportIndex: PropTypes.number.isRequired,
|
||||
children: PropTypes.node,
|
||||
viewportComponents: PropTypes.array.isRequired,
|
||||
// numRows: PropTypes.number.isRequired,
|
||||
// numColumns: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
ViewerViewportGrid.defaultProps = {
|
||||
// viewports: [],
|
||||
// numRows: 1,
|
||||
// numColumns: 1,
|
||||
viewportData: [],
|
||||
viewportComponents: [],
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
function _getViewportComponent(displaySet, viewportComponents) {
|
||||
const { SOPClassHandlerId } = displaySet;
|
||||
|
||||
for (let i = 0; i < viewportComponents.length; i++) {
|
||||
if (
|
||||
viewportComponents[i].displaySetsToDisplay.includes(SOPClassHandlerId)
|
||||
) {
|
||||
const { component } = viewportComponents[i];
|
||||
return component;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ViewerViewportGrid;
|
||||
|
||||
@ -17,7 +17,7 @@ export default function ModeRoute({
|
||||
const {
|
||||
toolBarLayout,
|
||||
setToolBarLayout,
|
||||
displaySetInstanceUids,
|
||||
displaySetInstanceUIDs,
|
||||
setDisplaySetInstanceUids,
|
||||
} = useViewModel();
|
||||
|
||||
@ -38,7 +38,7 @@ export default function ModeRoute({
|
||||
const createDisplaySets = useCallback(() => {
|
||||
// Add SOPClassHandlers to a new SOPClassManager.
|
||||
displaySetManager.init(extensionManager, sopClassHandlers, {
|
||||
displaySetInstanceUids,
|
||||
displaySetInstanceUIDs,
|
||||
setDisplaySetInstanceUids,
|
||||
});
|
||||
|
||||
@ -49,7 +49,7 @@ export default function ModeRoute({
|
||||
queryParams,
|
||||
displaySetManager.makeDisplaySets
|
||||
);
|
||||
}, [displaySetInstanceUids, location]);
|
||||
}, [displaySetInstanceUIDs, location]);
|
||||
|
||||
useEffect(() => {
|
||||
createDisplaySets();
|
||||
@ -84,6 +84,10 @@ export default function ModeRoute({
|
||||
const CombinedContextProvider = ({ children }) =>
|
||||
Compose({ components: contextModuleProviders, children });
|
||||
|
||||
function ViewportGridWithDataSource(props) {
|
||||
return ViewportGrid({ ...props, dataSource });
|
||||
}
|
||||
|
||||
return (
|
||||
<CombinedContextProvider>
|
||||
{/* TODO: extensionManager is already provided to the extension module.
|
||||
@ -92,9 +96,9 @@ export default function ModeRoute({
|
||||
<DragAndDropProvider>
|
||||
<LayoutComponent
|
||||
extensionManager={extensionManager}
|
||||
displaySetInstanceUids={displaySetInstanceUids}
|
||||
displaySetInstanceUIDs={displaySetInstanceUIDs}
|
||||
toolBarLayout={toolBarLayout}
|
||||
ViewportGrid={ViewportGrid}
|
||||
ViewportGrid={ViewportGridWithDataSource}
|
||||
{...layoutTemplateData.props}
|
||||
/>
|
||||
</DragAndDropProvider>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user