Files
ohif-viewer/extensions/default/src/init.ts
2025-05-27 10:51:12 +07:00

114 lines
3.4 KiB
TypeScript

import { DicomMetadataStore, classes } from '@ohif/core';
import { calculateSUVScalingFactors } from '@cornerstonejs/calculate-suv';
import getPTImageIdInstanceMetadata from './getPTImageIdInstanceMetadata';
import { registerHangingProtocolAttributes } from './hangingprotocols';
const metadataProvider = classes.MetadataProvider;
/**
*
* @param {Object} servicesManager
* @param {Object} configuration
*/
export default function init({
servicesManager,
configuration = {},
commandsManager,
}: withAppTypes): void {
const { toolbarService, cineService, viewportGridService } = servicesManager.services;
toolbarService.registerEventForToolbarUpdate(cineService, [
cineService.EVENTS.CINE_STATE_CHANGED,
]);
// Add
DicomMetadataStore.subscribe(DicomMetadataStore.EVENTS.INSTANCES_ADDED, handlePETImageMetadata);
// If the metadata for PET has changed by the user (e.g. manually changing the PatientWeight)
// we need to recalculate the SUV Scaling Factors
DicomMetadataStore.subscribe(DicomMetadataStore.EVENTS.SERIES_UPDATED, handlePETImageMetadata);
// Adds extra custom attributes for use by hanging protocols
registerHangingProtocolAttributes({ servicesManager });
// Function to process and subscribe to events for a given set of commands and listeners
const subscribeToEvents = listeners => {
Object.entries(listeners).forEach(([event, commands]) => {
const supportedEvents = [
viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,
viewportGridService.EVENTS.VIEWPORTS_READY,
];
if (supportedEvents.includes(event)) {
viewportGridService.subscribe(event, eventData => {
const viewportId = eventData?.viewportId ?? viewportGridService.getActiveViewportId();
commandsManager.run(commands, { viewportId });
});
}
});
};
toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_MODIFIED, state => {
const { buttons } = state;
for (const [id, button] of Object.entries(buttons)) {
const { groupId, items, listeners } = button.props || {};
// Handle group items' listeners
if (groupId && items) {
items.forEach(item => {
if (item.listeners) {
subscribeToEvents(item.listeners);
}
});
}
// Handle button listeners
if (listeners) {
subscribeToEvents(listeners);
}
}
});
}
const handlePETImageMetadata = ({ SeriesInstanceUID, StudyInstanceUID }) => {
const { instances } = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);
if (!instances?.length) {
return;
}
const modality = instances[0].Modality;
if (!modality || modality !== 'PT') {
return;
}
const imageIds = instances.map(instance => instance.imageId);
const instanceMetadataArray = [];
// try except block to prevent errors when the metadata is not correct
try {
imageIds.forEach(imageId => {
const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
if (instanceMetadata) {
instanceMetadataArray.push(instanceMetadata);
}
});
if (!instanceMetadataArray.length) {
return;
}
const suvScalingFactors = calculateSUVScalingFactors(instanceMetadataArray);
instanceMetadataArray.forEach((instanceMetadata, index) => {
metadataProvider.addCustomMetadata(
imageIds[index],
'scalingModule',
suvScalingFactors[index]
);
});
} catch (error) {
console.log(error);
}
};