Skip to content

Commit

Permalink
feat(customizationService): Enable saving and loading of private tags…
Browse files Browse the repository at this point in the history
… in SRs (#3842)
  • Loading branch information
pedrokohler authored Dec 13, 2023
1 parent d1c07d9 commit e1f55e6
Show file tree
Hide file tree
Showing 19 changed files with 110 additions and 38 deletions.
14 changes: 12 additions & 2 deletions extensions/cornerstone-dicom-sr/src/commandsModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ const _generateReport = (measurementData, additionalFindingTypes, options = {})
return dataset;
};

const commandsModule = ({}) => {
const commandsModule = props => {
const { servicesManager } = props;
const { customizationService } = servicesManager.services;
const actions = {
/**
*
Expand Down Expand Up @@ -95,7 +97,15 @@ const commandsModule = ({}) => {
throw new Error('Invalid report, no content');
}

await dataSource.store.dicom(naturalizedReport);
const onBeforeDicomStore =
customizationService.getModeCustomization('onBeforeDicomStore')?.value;

let dicomDict;
if (typeof onBeforeDicomStore === 'function') {
dicomDict = onBeforeDicomStore({ measurementData, naturalizedReport });
}

await dataSource.store.dicom(naturalizedReport, null, dicomDict);

if (StudyInstanceUID) {
dataSource.deleteStudyMetadataPromise(StudyInstanceUID);
Expand Down
37 changes: 33 additions & 4 deletions extensions/cornerstone-dicom-sr/src/getSopClassHandlerModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,12 @@ function _load(displaySet, servicesManager, extensionManager) {

// Check currently added displaySets and add measurements if the sources exist.
displaySetService.activeDisplaySets.forEach(activeDisplaySet => {
_checkIfCanAddMeasurementsToDisplaySet(displaySet, activeDisplaySet, dataSource);
_checkIfCanAddMeasurementsToDisplaySet(
displaySet,
activeDisplaySet,
dataSource,
servicesManager
);
});

// Subscribe to new displaySets as the source may come in after.
Expand All @@ -180,12 +185,23 @@ function _load(displaySet, servicesManager, extensionManager) {
// If there are still some measurements that have not yet been loaded into cornerstone,
// See if we can load them onto any of the new displaySets.
displaySetsAdded.forEach(newDisplaySet => {
_checkIfCanAddMeasurementsToDisplaySet(displaySet, newDisplaySet, dataSource);
_checkIfCanAddMeasurementsToDisplaySet(
displaySet,
newDisplaySet,
dataSource,
servicesManager
);
});
});
}

function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dataSource) {
function _checkIfCanAddMeasurementsToDisplaySet(
srDisplaySet,
newDisplaySet,
dataSource,
servicesManager
) {
const { customizationService } = servicesManager.services;
let unloadedMeasurements = srDisplaySet.measurements.filter(
measurement => measurement.loaded === false
);
Expand Down Expand Up @@ -244,7 +260,20 @@ function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dat

if (SOPInstanceUIDs.includes(SOPInstanceUID)) {
for (let j = unloadedMeasurements.length - 1; j >= 0; j--) {
const measurement = unloadedMeasurements[j];
let measurement = unloadedMeasurements[j];

const onBeforeSRAddMeasurement = customizationService.getModeCustomization(
'onBeforeSRAddMeasurement'
)?.value;

if (typeof onBeforeSRAddMeasurement === 'function') {
measurement = onBeforeSRAddMeasurement({
measurement,
StudyInstanceUID: srDisplaySet.StudyInstanceUID,
SeriesInstanceUID: srDisplaySet.SeriesInstanceUID,
});
}

if (_measurementReferencesSOPInstanceUID(measurement, SOPInstanceUID, frameNumber)) {
addMeasurement(measurement, imageId, newDisplaySet.displaySetInstanceUID);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,9 @@ export default class DICOMSRDisplayTool extends AnnotationTool {
const textLines = this._getTextBoxLinesFromLabels(label);
const canvasTextBoxCoords = utilities.drawing.getTextBoxCoordsCanvas(adaptedCanvasCoordinates);

annotation.data.handles.textBox.worldPosition = viewport.canvasToWorld(canvasTextBoxCoords);
if (!annotation.data?.handles?.textBox?.worldPosition) {
annotation.data.handles.textBox.worldPosition = viewport.canvasToWorld(canvasTextBoxCoords);
}

const textBoxPosition = viewport.worldToCanvas(annotation.data.handles.textBox.worldPosition);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default function addMeasurement(measurement, imageId, displaySetInstanceU
data: {
label: measurement.labels,
handles: {
textBox: {},
textBox: measurement.textBox ?? {},
},
cachedStats: {
TrackingUniqueIdentifier: measurementData.TrackingUniqueIdentifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export default function hydrateStructuredReport(
const datasetToUse = _mapLegacyDataSet(instance);

// Use dcmjs to generate toolState.
const storedMeasurementByAnnotationType = MeasurementReport.generateToolState(
let storedMeasurementByAnnotationType = MeasurementReport.generateToolState(
datasetToUse,
// NOTE: we need to pass in the imageIds to dcmjs since the we use them
// for the imageToWorld transformation. The following assumes that the order
Expand All @@ -101,6 +101,16 @@ export default function hydrateStructuredReport(
metaData
);

const onBeforeSRHydration =
customizationService.getModeCustomization('onBeforeSRHydration')?.value;

if (typeof onBeforeSRHydration === 'function') {
storedMeasurementByAnnotationType = onBeforeSRHydration({
storedMeasurementByAnnotationType,
displaySet,
});
}

// Filter what is found by DICOM SR to measurements we support.
const mappingDefinitions = mappings.map(m => m.annotationType);
const hydratableMeasurementsInSR = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const Angle = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}

const { points } = data.handles;
const { points, textBox } = data.handles;

const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);

Expand All @@ -62,6 +62,7 @@ const Angle = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const Length = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}

const { points } = data.handles;
const { points, textBox } = data.handles;

const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);

Expand All @@ -59,6 +59,7 @@ const Length = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const Bidirectional = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}

const { points } = data.handles;
const { points, textBox } = data.handles;

const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);

Expand All @@ -57,6 +57,7 @@ const Bidirectional = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const CircleROI = {
displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}

const { points } = data.handles;
const { points, textBox } = data.handles;

const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);

Expand All @@ -55,6 +55,7 @@ const CircleROI = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const CobbAngle = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}

const { points } = data.handles;
const { points, textBox } = data.handles;

const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);

Expand All @@ -62,6 +62,7 @@ const CobbAngle = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const EllipticalROI = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}

const { points } = data.handles;
const { points, textBox } = data.handles;

const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);

Expand All @@ -55,6 +55,7 @@ const EllipticalROI = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const Length = {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}

const { points } = data.handles;
const { points, textBox } = data.handles;

const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);

Expand All @@ -65,6 +65,7 @@ const Length = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const PlanarFreehandROI = {
displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}

const { points } = data.handles;
const { points, textBox } = data.handles;

const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);

Expand All @@ -60,6 +60,7 @@ const PlanarFreehandROI = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const RectangleROI = {
displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}

const { points } = data.handles;
const { points, textBox } = data.handles;

const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);

Expand All @@ -55,6 +55,7 @@ const RectangleROI = {
SOPInstanceUID,
FrameOfReferenceUID,
points,
textBox,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
Expand Down
42 changes: 27 additions & 15 deletions extensions/default/src/DicomWebDataSource/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ const metadataProvider = classes.MetadataProvider;
* @param {bool} lazyLoadStudy - "enableStudyLazyLoad"; Request series meta async instead of blocking
* @param {string|bool} singlepart - indicates of the retrieves can fetch singlepart. Options are bulkdata, video, image or boolean true
*/
function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
function createDicomWebApi(dicomWebConfig, servicesManager) {
const { userAuthenticationService, customizationService } = servicesManager.services;
let dicomWebConfigCopy,
qidoConfig,
wadoConfig,
Expand Down Expand Up @@ -140,7 +141,13 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
instances: {
search: (studyInstanceUid, queryParameters) => {
qidoDicomWebClient.headers = getAuthrorizationHeader();
return qidoSearch.call(undefined, qidoDicomWebClient, studyInstanceUid, null, queryParameters);
return qidoSearch.call(
undefined,
qidoDicomWebClient,
studyInstanceUid,
null,
queryParameters
);
},
},
},
Expand Down Expand Up @@ -211,7 +218,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
},

store: {
dicom: async (dataset, request) => {
dicom: async (dataset, request, dicomDict) => {
wadoDicomWebClient.headers = getAuthrorizationHeader();
if (dataset instanceof ArrayBuffer) {
const options = {
Expand All @@ -220,21 +227,26 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
};
await wadoDicomWebClient.storeInstances(options);
} else {
const meta = {
FileMetaInformationVersion: dataset._meta?.FileMetaInformationVersion?.Value,
MediaStorageSOPClassUID: dataset.SOPClassUID,
MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
TransferSyntaxUID: EXPLICIT_VR_LITTLE_ENDIAN,
ImplementationClassUID,
ImplementationVersionName,
};
let effectiveDicomDict = dicomDict;

if (!dicomDict) {
const meta = {
FileMetaInformationVersion: dataset._meta?.FileMetaInformationVersion?.Value,
MediaStorageSOPClassUID: dataset.SOPClassUID,
MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
TransferSyntaxUID: EXPLICIT_VR_LITTLE_ENDIAN,
ImplementationClassUID,
ImplementationVersionName,
};

const denaturalized = denaturalizeDataset(meta);
const dicomDict = new DicomDict(denaturalized);
const denaturalized = denaturalizeDataset(meta);
const defaultDicomDict = new DicomDict(denaturalized);
defaultDicomDict.dict = denaturalizeDataset(dataset);

dicomDict.dict = denaturalizeDataset(dataset);
effectiveDicomDict = defaultDicomDict;
}

const part10Buffer = dicomDict.write();
const part10Buffer = effectiveDicomDict.write();

const options = {
datasets: [part10Buffer],
Expand Down
4 changes: 2 additions & 2 deletions extensions/default/src/DicomWebProxyDataSource/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { createDicomWebApi } from '../DicomWebDataSource/index';
* dicomWeb configuration array
*
*/
function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService) {
function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
const { name } = dicomWebProxyConfig;
let dicomWebDelegate = undefined;

Expand All @@ -28,7 +28,7 @@ function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService)

dicomWebDelegate = createDicomWebApi(
data.servers.dicomWeb[0].configuration,
UserAuthenticationService
servicesManager
);
dicomWebDelegate.initialize({ params, query });
}
Expand Down
2 changes: 1 addition & 1 deletion extensions/default/src/MergeDataSource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const callByRetrieveAETitle = ({

function createMergeDataSourceApi(
mergeConfig: MergeConfig,
UserAuthenticationService: unknown,
servicesManager: unknown,
extensionManager
) {
const { seriesMerge } = mergeConfig;
Expand Down
Loading

0 comments on commit e1f55e6

Please sign in to comment.