feat(studyPrefetcher): Study Prefetcher (#4206)

This commit is contained in:
Leonardo Campos authored and GitHub committed 2024-06-28 08:58:39 -04:00
1 parent 257cc477cd
commit 2048b19484
24 files changed
+992 -98

No files matched your search

+3
View File
@@ -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`;
}
@@ -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,