refactor: 💡 Move DICOMSR code to @ohif/core project (#1310)
* Move DICOMSR to @ohif/core * refactor: 💡 Move DICOMSR code to @ohif/core project We've just merged support for DICOM Structured Reports. Today, support for this feature lives in the @ohif/viewer project in it's lib folder. Ideally, it should be moved to @ohif/core and given a clear public API and unit tests. Closes: #1282 * Update imports * CR Update: Update imports
This commit is contained in:
parent
73a3f07e2b
commit
695ad732e1
@ -39,6 +39,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
"ajv": "^6.10.0",
|
"ajv": "^6.10.0",
|
||||||
|
"dcmjs": "^0.8.3",
|
||||||
"dicomweb-client": "^0.5.2",
|
"dicomweb-client": "^0.5.2",
|
||||||
"isomorphic-base64": "^1.0.2",
|
"isomorphic-base64": "^1.0.2",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
import { log, studies, utils } from '@ohif/core';
|
import log from '../log';
|
||||||
import { retrieveMeasurementFromSR, stowSRFromMeasurements } from './handleStructuredReport';
|
import studies from '../studies';
|
||||||
|
import utils from '../utils';
|
||||||
|
import {
|
||||||
|
retrieveMeasurementFromSR,
|
||||||
|
stowSRFromMeasurements,
|
||||||
|
} from './handleStructuredReport';
|
||||||
import findMostRecentStructuredReport from './utils/findMostRecentStructuredReport';
|
import findMostRecentStructuredReport from './utils/findMostRecentStructuredReport';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +70,9 @@ const storeMeasurements = async (measurementData, filter, server) => {
|
|||||||
message: 'Measurements were saved with success',
|
message: 'Measurements were saved with success',
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(`[DICOMSR] Error while saving the measurements: ${error.message}`);
|
log.error(
|
||||||
|
`[DICOMSR] Error while saving the measurements: ${error.message}`
|
||||||
|
);
|
||||||
throw new Error('Error while saving the measurements.');
|
throw new Error('Error while saving the measurements.');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import * as dcmjs from 'dcmjs';
|
import * as dcmjs from 'dcmjs';
|
||||||
import { DICOMWeb } from '@ohif/core';
|
import { api } from 'dicomweb-client';
|
||||||
|
|
||||||
|
import DICOMWeb from '../DICOMWeb';
|
||||||
import parseDicomStructuredReport from './parseDicomStructuredReport';
|
import parseDicomStructuredReport from './parseDicomStructuredReport';
|
||||||
import parseMeasurementsData from './parseMeasurementsData';
|
import parseMeasurementsData from './parseMeasurementsData';
|
||||||
import getAllDisplaySets from './utils/getAllDisplaySets';
|
import getAllDisplaySets from './utils/getAllDisplaySets';
|
||||||
|
|
||||||
import { api } from 'dicomweb-client';
|
|
||||||
|
|
||||||
const VERSION_NAME = 'dcmjs-0.0';
|
const VERSION_NAME = 'dcmjs-0.0';
|
||||||
const TRANSFER_SYNTAX_UID = '1.2.840.10008.1.2.1';
|
const TRANSFER_SYNTAX_UID = '1.2.840.10008.1.2.1';
|
||||||
|
|
||||||
@ -34,7 +34,10 @@ const retrieveMeasurementFromSR = async (series, studies, serverUrl) => {
|
|||||||
|
|
||||||
const part10SRArrayBuffer = await dicomWeb.retrieveInstance(options);
|
const part10SRArrayBuffer = await dicomWeb.retrieveInstance(options);
|
||||||
const displaySets = getAllDisplaySets(studies);
|
const displaySets = getAllDisplaySets(studies);
|
||||||
const measurementsData = parseDicomStructuredReport(part10SRArrayBuffer, displaySets);
|
const measurementsData = parseDicomStructuredReport(
|
||||||
|
part10SRArrayBuffer,
|
||||||
|
displaySets
|
||||||
|
);
|
||||||
|
|
||||||
return measurementsData;
|
return measurementsData;
|
||||||
};
|
};
|
||||||
@ -47,13 +50,10 @@ const retrieveMeasurementFromSR = async (series, studies, serverUrl) => {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
const stowSRFromMeasurements = async (measurements, serverUrl) => {
|
const stowSRFromMeasurements = async (measurements, serverUrl) => {
|
||||||
const { dataset } = parseMeasurementsData(
|
const { dataset } = parseMeasurementsData(measurements);
|
||||||
measurements
|
|
||||||
);
|
|
||||||
const { DicomMetaDictionary, DicomDict } = dcmjs.data;
|
const { DicomMetaDictionary, DicomDict } = dcmjs.data;
|
||||||
const meta = {
|
const meta = {
|
||||||
FileMetaInformationVersion:
|
FileMetaInformationVersion: dataset._meta.FileMetaInformationVersion.Value,
|
||||||
dataset._meta.FileMetaInformationVersion.Value,
|
|
||||||
MediaStorageSOPClassUID: dataset.SOPClassUID,
|
MediaStorageSOPClassUID: dataset.SOPClassUID,
|
||||||
MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
|
MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
|
||||||
TransferSyntaxUID: TRANSFER_SYNTAX_UID,
|
TransferSyntaxUID: TRANSFER_SYNTAX_UID,
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import * as dcmjs from 'dcmjs';
|
import * as dcmjs from 'dcmjs';
|
||||||
|
|
||||||
import findInstanceMetadataBySopInstanceUid from './utils/findInstanceMetadataBySopInstanceUid';
|
import findInstanceMetadataBySopInstanceUid from './utils/findInstanceMetadataBySopInstanceUid';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +38,12 @@ const parseDicomStructuredReport = (part10SRArrayBuffer, displaySets) => {
|
|||||||
const { studyInstanceUid, patientId } = study;
|
const { studyInstanceUid, patientId } = study;
|
||||||
const { seriesInstanceUid } = series;
|
const { seriesInstanceUid } = series;
|
||||||
const { sopInstanceUid, frameIndex } = measurement;
|
const { sopInstanceUid, frameIndex } = measurement;
|
||||||
const imagePath = getImagePath(studyInstanceUid, seriesInstanceUid, sopInstanceUid, frameIndex);
|
const imagePath = getImagePath(
|
||||||
|
studyInstanceUid,
|
||||||
|
seriesInstanceUid,
|
||||||
|
sopInstanceUid,
|
||||||
|
frameIndex
|
||||||
|
);
|
||||||
|
|
||||||
const imageId = instanceMetadata.getImageId();
|
const imageId = instanceMetadata.getImageId();
|
||||||
if (!imageId) {
|
if (!imageId) {
|
||||||
@ -75,8 +81,15 @@ const parseDicomStructuredReport = (part10SRArrayBuffer, displaySets) => {
|
|||||||
* @param {string} frameIndex
|
* @param {string} frameIndex
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getImagePath = (studyInstanceUid, seriesInstanceUid, sopInstanceUid, frameIndex) => {
|
const getImagePath = (
|
||||||
return [studyInstanceUid, seriesInstanceUid, sopInstanceUid, frameIndex].join('_');
|
studyInstanceUid,
|
||||||
}
|
seriesInstanceUid,
|
||||||
|
sopInstanceUid,
|
||||||
|
frameIndex
|
||||||
|
) => {
|
||||||
|
return [studyInstanceUid, seriesInstanceUid, sopInstanceUid, frameIndex].join(
|
||||||
|
'_'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default parseDicomStructuredReport;
|
export default parseDicomStructuredReport;
|
||||||
@ -1,6 +1,8 @@
|
|||||||
import * as dcmjs from 'dcmjs';
|
import * as dcmjs from 'dcmjs';
|
||||||
import { log, measurements } from '@ohif/core';
|
|
||||||
import cornerstone from 'cornerstone-core';
|
import cornerstone from 'cornerstone-core';
|
||||||
|
|
||||||
|
import log from '../log';
|
||||||
|
import measurements from '../measurements';
|
||||||
import isToolSupported from './utils/isToolSupported';
|
import isToolSupported from './utils/isToolSupported';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,7 +11,9 @@ const findInstanceMetadataBySopInstanceUid = (displaySets, sopInstanceUid) => {
|
|||||||
displaySets.find(displaySet => {
|
displaySets.find(displaySet => {
|
||||||
if (!displaySet.images) return false;
|
if (!displaySet.images) return false;
|
||||||
|
|
||||||
instanceFound = displaySet.images.find(instanceMetadata => instanceMetadata._sopInstanceUID === sopInstanceUid);
|
instanceFound = displaySet.images.find(
|
||||||
|
instanceMetadata => instanceMetadata._sopInstanceUID === sopInstanceUid
|
||||||
|
);
|
||||||
|
|
||||||
return !!instanceFound;
|
return !!instanceFound;
|
||||||
});
|
});
|
||||||
@ -4,15 +4,17 @@
|
|||||||
* @param {Array} studies
|
* @param {Array} studies
|
||||||
* @returns {Object} Series
|
* @returns {Object} Series
|
||||||
*/
|
*/
|
||||||
const findMostRecentStructuredReport = (studies) => {
|
const findMostRecentStructuredReport = studies => {
|
||||||
let mostRecentStructuredReport;
|
let mostRecentStructuredReport;
|
||||||
|
|
||||||
studies.forEach(study => {
|
studies.forEach(study => {
|
||||||
const allSeries = study.getSeries ? study.getSeries() : [];
|
const allSeries = study.getSeries ? study.getSeries() : [];
|
||||||
allSeries.forEach(series => {
|
allSeries.forEach(series => {
|
||||||
|
|
||||||
if (isStructuredReportSeries(series)) {
|
if (isStructuredReportSeries(series)) {
|
||||||
if (!mostRecentStructuredReport || compareSeriesDate(series, mostRecentStructuredReport)) {
|
if (
|
||||||
|
!mostRecentStructuredReport ||
|
||||||
|
compareSeriesDate(series, mostRecentStructuredReport)
|
||||||
|
) {
|
||||||
mostRecentStructuredReport = series;
|
mostRecentStructuredReport = series;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,7 +30,7 @@ const findMostRecentStructuredReport = (studies) => {
|
|||||||
* @param {Object} series - Series metadata
|
* @param {Object} series - Series metadata
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
const isStructuredReportSeries = (series) => {
|
const isStructuredReportSeries = series => {
|
||||||
const supportedSopClassUIDs = [
|
const supportedSopClassUIDs = [
|
||||||
'1.2.840.10008.5.1.4.1.1.88.22',
|
'1.2.840.10008.5.1.4.1.1.88.22',
|
||||||
'1.2.840.10008.5.1.4.1.1.11.1',
|
'1.2.840.10008.5.1.4.1.1.11.1',
|
||||||
@ -38,7 +40,7 @@ const isStructuredReportSeries = (series) => {
|
|||||||
const sopClassUid = firstInstance._instance.sopClassUid;
|
const sopClassUid = firstInstance._instance.sopClassUid;
|
||||||
|
|
||||||
return supportedSopClassUIDs.includes(sopClassUid);
|
return supportedSopClassUIDs.includes(sopClassUid);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checkes if series1 is newer than series2
|
* Checkes if series1 is newer than series2
|
||||||
@ -48,10 +50,11 @@ const isStructuredReportSeries = (series) => {
|
|||||||
* @returns {boolean} true/false if series1 is newer than series2
|
* @returns {boolean} true/false if series1 is newer than series2
|
||||||
*/
|
*/
|
||||||
const compareSeriesDate = (series1, series2) => {
|
const compareSeriesDate = (series1, series2) => {
|
||||||
return series1._data.seriesDate > series2._data.seriesDate ||
|
return (
|
||||||
|
series1._data.seriesDate > series2._data.seriesDate ||
|
||||||
(series1._data.seriesDate === series2._data.seriesDate &&
|
(series1._data.seriesDate === series2._data.seriesDate &&
|
||||||
series1._data.seriesTime > series2._data.seriesTime);
|
series1._data.seriesTime > series2._data.seriesTime)
|
||||||
}
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default findMostRecentStructuredReport;
|
export default findMostRecentStructuredReport;
|
||||||
@ -4,7 +4,7 @@
|
|||||||
* @param {Object} studies - List of studies loaded into the viewer
|
* @param {Object} studies - List of studies loaded into the viewer
|
||||||
* @returns {Object} List of DisplaySets
|
* @returns {Object} List of DisplaySets
|
||||||
*/
|
*/
|
||||||
const getAllDisplaySets = (studies) => {
|
const getAllDisplaySets = studies => {
|
||||||
let allDisplaySets = [];
|
let allDisplaySets = [];
|
||||||
|
|
||||||
studies.forEach(study => {
|
studies.forEach(study => {
|
||||||
@ -5,6 +5,7 @@ import { ServicesManager } from './services';
|
|||||||
import classes, { CommandsManager, HotkeysManager } from './classes/';
|
import classes, { CommandsManager, HotkeysManager } from './classes/';
|
||||||
|
|
||||||
import DICOMWeb from './DICOMWeb';
|
import DICOMWeb from './DICOMWeb';
|
||||||
|
import DICOMSR from './DICOMSR';
|
||||||
import cornerstone from './cornerstone.js';
|
import cornerstone from './cornerstone.js';
|
||||||
import hangingProtocols from './hanging-protocols';
|
import hangingProtocols from './hanging-protocols';
|
||||||
import header from './header.js';
|
import header from './header.js';
|
||||||
@ -46,6 +47,7 @@ const OHIF = {
|
|||||||
object,
|
object,
|
||||||
log,
|
log,
|
||||||
DICOMWeb,
|
DICOMWeb,
|
||||||
|
DICOMSR,
|
||||||
viewer: {},
|
viewer: {},
|
||||||
measurements,
|
measurements,
|
||||||
hangingProtocols,
|
hangingProtocols,
|
||||||
@ -76,6 +78,7 @@ export {
|
|||||||
object,
|
object,
|
||||||
log,
|
log,
|
||||||
DICOMWeb,
|
DICOMWeb,
|
||||||
|
DICOMSR,
|
||||||
measurements,
|
measurements,
|
||||||
hangingProtocols,
|
hangingProtocols,
|
||||||
//
|
//
|
||||||
|
|||||||
@ -28,6 +28,7 @@ describe('Top level exports', () => {
|
|||||||
'object',
|
'object',
|
||||||
'log',
|
'log',
|
||||||
'DICOMWeb',
|
'DICOMWeb',
|
||||||
|
'DICOMSR',
|
||||||
'OHIF', //
|
'OHIF', //
|
||||||
'measurements',
|
'measurements',
|
||||||
'hangingProtocols',
|
'hangingProtocols',
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { MeasurementTable } from '@ohif/ui';
|
import { MeasurementTable } from '@ohif/ui';
|
||||||
import OHIF from '@ohif/core';
|
import OHIF, { DICOMSR } from '@ohif/core';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import cornerstone from 'cornerstone-core';
|
import cornerstone from 'cornerstone-core';
|
||||||
import DICOMSR from './../../lib/DICOMSR';
|
|
||||||
|
|
||||||
import jumpToRowItem from './jumpToRowItem.js';
|
import jumpToRowItem from './jumpToRowItem.js';
|
||||||
|
|
||||||
@ -32,9 +31,7 @@ function groupBy(list, props) {
|
|||||||
*/
|
*/
|
||||||
function getAllTools(toolGroups = []) {
|
function getAllTools(toolGroups = []) {
|
||||||
let tools = [];
|
let tools = [];
|
||||||
toolGroups.forEach(
|
toolGroups.forEach(toolGroup => (tools = tools.concat(toolGroup.childTools)));
|
||||||
toolGroup => (tools = tools.concat(toolGroup.childTools))
|
|
||||||
);
|
|
||||||
|
|
||||||
return tools;
|
return tools;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { MODULE_TYPES } from '@ohif/core';
|
import { MODULE_TYPES } from '@ohif/core';
|
||||||
import OHIF from '@ohif/core';
|
import OHIF, { DICOMSR } from '@ohif/core';
|
||||||
import { withDialog } from '@ohif/ui';
|
import { withDialog } from '@ohif/ui';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import ConnectedHeader from './ConnectedHeader.js';
|
import ConnectedHeader from './ConnectedHeader.js';
|
||||||
@ -12,7 +12,6 @@ import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
|
|||||||
import ConnectedViewerMain from './ConnectedViewerMain.js';
|
import ConnectedViewerMain from './ConnectedViewerMain.js';
|
||||||
import SidePanel from './../components/SidePanel.js';
|
import SidePanel from './../components/SidePanel.js';
|
||||||
import { extensionManager } from './../App.js';
|
import { extensionManager } from './../App.js';
|
||||||
import DICOMSR from '../lib/DICOMSR';
|
|
||||||
|
|
||||||
// Contexts
|
// Contexts
|
||||||
import WhiteLabellingContext from '../context/WhiteLabellingContext.js';
|
import WhiteLabellingContext from '../context/WhiteLabellingContext.js';
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@ -6545,6 +6545,16 @@ dcmjs@^0.8.2:
|
|||||||
loglevelnext "^3.0.1"
|
loglevelnext "^3.0.1"
|
||||||
ndarray "^1.0.18"
|
ndarray "^1.0.18"
|
||||||
|
|
||||||
|
dcmjs@^0.8.3:
|
||||||
|
version "0.8.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.8.3.tgz#fff1b030b6cb2d6e2afb1aa99840bfa853724c31"
|
||||||
|
integrity sha512-eXQjqgtJf9+oseraKDNDm2A5F3Th4B2GJeZtjStj0IFXxjlbPOzdq3PfCyxdwfRaKOBIwr0q3YK/Vfs2CpQY8Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/polyfill" "^7.6.0"
|
||||||
|
"@babel/runtime" "^7.6.3"
|
||||||
|
loglevelnext "^3.0.1"
|
||||||
|
ndarray "^1.0.18"
|
||||||
|
|
||||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.1, debug@^2.6.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
|
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.1, debug@^2.6.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user