feat(studyPrefetcher): Study Prefetcher (#4206)
This commit is contained in:
1 parent
257cc477cd
commit
2048b19484
24 files changed
+992
-98
No files matched your search
@@ -25,6 +25,7 @@ import initCornerstoneTools from './initCornerstoneTools';
|
||||
|
||||
import { connectToolsToMeasurementService } from './initMeasurementService';
|
||||
import initCineService from './initCineService';
|
||||
import initStudyPrefetcherService from './initStudyPrefetcherService';
|
||||
import interleaveCenterLoader from './utils/interleaveCenterLoader';
|
||||
import nthLoader from './utils/nthLoader';
|
||||
import interleaveTopToBottom from './utils/interleaveTopToBottom';
|
||||
@@ -98,6 +99,7 @@ export default async function init({
|
||||
hangingProtocolService,
|
||||
viewportGridService,
|
||||
stateSyncService,
|
||||
studyPrefetcherService
|
||||
} = servicesManager.services;
|
||||
|
||||
window.services = servicesManager.services;
|
||||
@@ -190,6 +192,7 @@ export default async function init({
|
||||
this.measurementServiceSource = connectToolsToMeasurementService(servicesManager);
|
||||
|
||||
initCineService(servicesManager);
|
||||
initStudyPrefetcherService(servicesManager);
|
||||
|
||||
// When a custom image load is performed, update the relevant viewports
|
||||
hangingProtocolService.subscribe(
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { cache, imageLoadPoolManager, imageLoader, Enums, eventTarget, EVENTS as csEvents } from '@cornerstonejs/core';
|
||||
|
||||
function initStudyPrefetcherService(servicesManager: AppTypes.ServicesManager) {
|
||||
const { studyPrefetcherService } = servicesManager.services;
|
||||
|
||||
studyPrefetcherService.requestType = Enums.RequestType.Prefetch;
|
||||
studyPrefetcherService.imageLoadPoolManager = imageLoadPoolManager;
|
||||
studyPrefetcherService.imageLoader = imageLoader;
|
||||
|
||||
studyPrefetcherService.cache = {
|
||||
isImageCached(imageId: string): boolean {
|
||||
return !!cache.getImageLoadObject(imageId);
|
||||
}
|
||||
}
|
||||
|
||||
studyPrefetcherService.imageLoadEventsManager = {
|
||||
addEventListeners(onImageLoaded, onImageLoadFailed) {
|
||||
eventTarget.addEventListener(csEvents.IMAGE_LOADED, onImageLoaded);
|
||||
eventTarget.addEventListener(csEvents.IMAGE_LOAD_FAILED, onImageLoadFailed);
|
||||
|
||||
return [
|
||||
{
|
||||
unsubscribe: () => eventTarget.removeEventListener(csEvents.IMAGE_LOADED, onImageLoaded)
|
||||
},
|
||||
{
|
||||
unsubscribe: () => eventTarget.removeEventListener(csEvents.IMAGE_LOAD_FAILED, onImageLoadFailed)
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default initStudyPrefetcherService;
|
||||
@@ -17,12 +17,13 @@ const createRenderedRetrieve = (config, params) => {
|
||||
const { wadoRoot } = config;
|
||||
const { instance, tag = 'PixelData' } = params;
|
||||
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;
|
||||
const value = instance[tag];
|
||||
const bulkDataURI = instance[tag]?.BulkDataURI ?? '';
|
||||
|
||||
if (value?.BulkDataURI?.indexOf('?') !== -1) {
|
||||
if (bulkDataURI?.indexOf('?') !== -1) {
|
||||
// The value instance has parameters, so it should not revert to the rendered
|
||||
return;
|
||||
}
|
||||
|
||||
if (tag === 'PixelData' || tag === 'EncapsulatedDocument') {
|
||||
return `${wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}/rendered`;
|
||||
}
|
||||
|
||||
+34
-1
@@ -25,6 +25,7 @@ function PanelStudyBrowserTracking({
|
||||
hangingProtocolService,
|
||||
uiNotificationService,
|
||||
measurementService,
|
||||
studyPrefetcherService,
|
||||
} = servicesManager.services;
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -43,6 +44,7 @@ function PanelStudyBrowserTracking({
|
||||
]);
|
||||
const [studyDisplayList, setStudyDisplayList] = useState([]);
|
||||
const [displaySets, setDisplaySets] = useState([]);
|
||||
const [displaySetsLoadingState, setDisplaySetsLoadingState] = useState({});
|
||||
const [thumbnailImageSrcMap, setThumbnailImageSrcMap] = useState({});
|
||||
const [jumpToDisplaySet, setJumpToDisplaySet] = useState(null);
|
||||
|
||||
@@ -162,6 +164,7 @@ function PanelStudyBrowserTracking({
|
||||
|
||||
const mappedDisplaySets = _mapDisplaySets(
|
||||
currentDisplaySets,
|
||||
displaySetsLoadingState,
|
||||
thumbnailImageSrcMap,
|
||||
trackedSeries,
|
||||
viewports,
|
||||
@@ -176,12 +179,30 @@ function PanelStudyBrowserTracking({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
displaySetService.activeDisplaySets,
|
||||
displaySetsLoadingState,
|
||||
trackedSeries,
|
||||
viewports,
|
||||
dataSource,
|
||||
thumbnailImageSrcMap,
|
||||
]);
|
||||
|
||||
// -- displaySetsLoadingState
|
||||
useEffect(() => {
|
||||
const { unsubscribe } = studyPrefetcherService.subscribe(
|
||||
studyPrefetcherService.EVENTS.DISPLAYSET_LOAD_PROGRESS,
|
||||
updatedDisplaySetLoadingState => {
|
||||
const { displaySetInstanceUID, loadingProgress } = updatedDisplaySetLoadingState;
|
||||
|
||||
setDisplaySetsLoadingState(prevState => ({
|
||||
...prevState,
|
||||
[displaySetInstanceUID]: loadingProgress,
|
||||
}));
|
||||
}
|
||||
);
|
||||
|
||||
return () => unsubscribe();
|
||||
}, [studyPrefetcherService]);
|
||||
|
||||
// ~~ subscriptions --> displaySets
|
||||
useEffect(() => {
|
||||
// DISPLAY_SETS_ADDED returns an array of DisplaySets that were added
|
||||
@@ -233,6 +254,7 @@ function PanelStudyBrowserTracking({
|
||||
changedDisplaySets => {
|
||||
const mappedDisplaySets = _mapDisplaySets(
|
||||
changedDisplaySets,
|
||||
displaySetsLoadingState,
|
||||
thumbnailImageSrcMap,
|
||||
trackedSeries,
|
||||
viewports,
|
||||
@@ -252,6 +274,7 @@ function PanelStudyBrowserTracking({
|
||||
() => {
|
||||
const mappedDisplaySets = _mapDisplaySets(
|
||||
displaySetService.getActiveDisplaySets(),
|
||||
displaySetsLoadingState,
|
||||
thumbnailImageSrcMap,
|
||||
trackedSeries,
|
||||
viewports,
|
||||
@@ -270,7 +293,14 @@ function PanelStudyBrowserTracking({
|
||||
SubscriptionDisplaySetsChanged.unsubscribe();
|
||||
SubscriptionDisplaySetMetaDataInvalidated.unsubscribe();
|
||||
};
|
||||
}, [thumbnailImageSrcMap, trackedSeries, viewports, dataSource, displaySetService]);
|
||||
}, [
|
||||
displaySetsLoadingState,
|
||||
thumbnailImageSrcMap,
|
||||
trackedSeries,
|
||||
viewports,
|
||||
dataSource,
|
||||
displaySetService,
|
||||
]);
|
||||
|
||||
const tabs = createStudyBrowserTabs(StudyInstanceUIDs, studyDisplayList, displaySets);
|
||||
|
||||
@@ -454,6 +484,7 @@ function _mapDataSourceStudies(studies) {
|
||||
|
||||
function _mapDisplaySets(
|
||||
displaySets,
|
||||
displaySetLoadingState,
|
||||
thumbnailImageSrcMap,
|
||||
trackedSeriesInstanceUIDs,
|
||||
viewports, // TODO: make array of `displaySetInstanceUIDs`?
|
||||
@@ -476,6 +507,7 @@ function _mapDisplaySets(
|
||||
componentType === 'thumbnailTracked' ? thumbnailDisplaySets : thumbnailNoImageDisplaySets;
|
||||
|
||||
const { displaySetInstanceUID } = ds;
|
||||
const loadingProgress = displaySetLoadingState?.[displaySetInstanceUID];
|
||||
|
||||
const thumbnailProps = {
|
||||
displaySetInstanceUID,
|
||||
@@ -484,6 +516,7 @@ function _mapDisplaySets(
|
||||
modality: ds.Modality,
|
||||
seriesDate: formatDate(ds.SeriesDate),
|
||||
numInstances: ds.numImageFrames,
|
||||
loadingProgress,
|
||||
countIcon: ds.countIcon,
|
||||
messages: ds.messages,
|
||||
StudyInstanceUID: ds.StudyInstanceUID,
|
||||
|
||||
Reference in new issue
Block a user