feat(SR): Measurement adapter mappings and save to same series (#3140)
* feat: Add adapter mappings for RectangleROI and Angle and save same PR comments * fix: Rehydrate check on non core measurement adapters
This commit is contained in:
1 parent
926290f69e
commit
67fc3f733d
42 files changed
+1277
-218
No files matched your search
@@ -1,15 +1,15 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { utils, ServicesManager } from '@ohif/core';
|
||||
import { MeasurementTable, Dialog, Input, useViewportGrid } from '@ohif/ui';
|
||||
import ActionButtons from './ActionButtons';
|
||||
import debounce from 'lodash.debounce';
|
||||
|
||||
import { utils } from '@ohif/core';
|
||||
import createReportDialogPrompt, {
|
||||
CREATE_REPORT_DIALOG_RESPONSE,
|
||||
} from './createReportDialogPrompt';
|
||||
import createReportAsync from '../Actions/createReportAsync';
|
||||
import getNextSRSeriesNumber from '../utils/getNextSRSeriesNumber';
|
||||
import findSRWithSameSeriesDescription from '../utils/findSRWithSameSeriesDescription';
|
||||
|
||||
const { downloadCSVReport } = utils;
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function PanelMeasurementTable({
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
extensionManager,
|
||||
}) {
|
||||
}): React.FunctionComponent {
|
||||
const [viewportGrid, viewportGridService] = useViewportGrid();
|
||||
const { activeViewportIndex, viewports } = viewportGrid;
|
||||
const {
|
||||
@@ -25,7 +25,7 @@ export default function PanelMeasurementTable({
|
||||
uiDialogService,
|
||||
uiNotificationService,
|
||||
displaySetService,
|
||||
} = servicesManager.services;
|
||||
} = (servicesManager as ServicesManager).services;
|
||||
const [displayMeasurements, setDisplayMeasurements] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -72,7 +72,7 @@ export default function PanelMeasurementTable({
|
||||
measurementService.clearMeasurements();
|
||||
}
|
||||
|
||||
async function createReport() {
|
||||
async function createReport(): Promise<any> {
|
||||
// filter measurements that are added to the active study
|
||||
const activeViewport = viewports[activeViewportIndex];
|
||||
const measurements = measurementService.getMeasurements();
|
||||
@@ -109,17 +109,19 @@ export default function PanelMeasurementTable({
|
||||
? 'Research Derived Series' // default
|
||||
: promptResult.value; // provided value
|
||||
|
||||
const SeriesNumber = getNextSRSeriesNumber(displaySetService);
|
||||
// Re-use an existing series having the same series description to avoid
|
||||
// creating too many series instances.
|
||||
const options = findSRWithSameSeriesDescription(
|
||||
SeriesDescription,
|
||||
displaySetService
|
||||
);
|
||||
|
||||
const displaySetInstanceUIDs = await createReportAsync(
|
||||
return createReportAsync(
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
dataSource,
|
||||
trackedMeasurements,
|
||||
{
|
||||
SeriesDescription,
|
||||
SeriesNumber,
|
||||
}
|
||||
options
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -233,16 +235,7 @@ export default function PanelMeasurementTable({
|
||||
}
|
||||
|
||||
PanelMeasurementTable.propTypes = {
|
||||
servicesManager: PropTypes.shape({
|
||||
services: PropTypes.shape({
|
||||
measurementService: PropTypes.shape({
|
||||
getMeasurements: PropTypes.func.isRequired,
|
||||
subscribe: PropTypes.func.isRequired,
|
||||
EVENTS: PropTypes.object.isRequired,
|
||||
VALUE_TYPES: PropTypes.object.isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
servicesManager: PropTypes.instanceOf(ServicesManager).isRequired,
|
||||
};
|
||||
|
||||
function _getMappedMeasurements(measurementService) {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { DisplaySetService, Types } from '@ohif/core';
|
||||
|
||||
import getNextSRSeriesNumber from './getNextSRSeriesNumber';
|
||||
|
||||
/**
|
||||
* Find an SR having the same series description.
|
||||
* This is used by the store service in order to store DICOM SR's having the
|
||||
* same Series Description into a single series under consecutive instance numbers
|
||||
* That way, they are all organized as a set and could have tools to view
|
||||
* "prior" SR instances.
|
||||
*
|
||||
* @param SeriesDescription - is the description to look for
|
||||
* @param displaySetService - the display sets to search for DICOM SR in
|
||||
* @returns SeriesMetadata from a DICOM SR having the same series description
|
||||
*/
|
||||
export default function findSRWithSameSeriesDescription(
|
||||
SeriesDescription: string,
|
||||
displaySetService: DisplaySetService
|
||||
): Types.SeriesMetadata {
|
||||
const activeDisplaySets = displaySetService.getActiveDisplaySets();
|
||||
const srDisplaySets = activeDisplaySets.filter(ds => ds.Modality === 'SR');
|
||||
const sameSeries = srDisplaySets.find(
|
||||
ds => ds.SeriesDescription === SeriesDescription
|
||||
);
|
||||
if (sameSeries) {
|
||||
console.log('Storing to same series', sameSeries);
|
||||
const { instance } = sameSeries;
|
||||
const {
|
||||
SeriesInstanceUID,
|
||||
SeriesDescription,
|
||||
SeriesDate,
|
||||
SeriesTime,
|
||||
SeriesNumber,
|
||||
Modality,
|
||||
} = instance;
|
||||
return {
|
||||
SeriesInstanceUID,
|
||||
SeriesDescription,
|
||||
SeriesDate,
|
||||
SeriesTime,
|
||||
SeriesNumber,
|
||||
Modality,
|
||||
InstanceNumber: sameSeries.others.length + 1,
|
||||
};
|
||||
}
|
||||
|
||||
const SeriesNumber = getNextSRSeriesNumber(displaySetService);
|
||||
return { SeriesDescription, SeriesNumber };
|
||||
}
|
||||
Reference in new issue
Block a user