ohif-viewer/platform/core/src/DICOMSR/dataExchange.js

170 lines
4.8 KiB
JavaScript
Raw Normal View History

import log from '../log';
import studies from '../studies';
import utils from '../utils';
import {
retrieveMeasurementFromSR,
stowSRFromMeasurements,
} from './handleStructuredReport';
feat: 🎸 DICOM SR STOW on MeasurementAPI (#954) * feat: 🎸 DICOM SR STOW on MeasurementAPI Closes: #758 * feat: 🎸 Adding the dataExchance from DICOM SR * feat: 🎸 Fix some issues and get the retrieve measurements working * feat: 🎸 Preventing measurement tool helpers to broke because the data is not Number (it comes as string from dcmjs) * feat: 🎸 Adding a button to start testing SATE functionality * feat: 🎸Small fixes into the code * feat: 🎸 MAke sure we get latest SR in the study, even on lazyLoad mode * Revert "feat: 🎸 Preventing measurement tool helpers to broke because the data is not Number (it comes as string from dcmjs)" This reverts commit 4b3a1efb5810487d2319826fd59c03d779882b5e. * feat: 🎸 Make sure after sync we update the viewports and also that annotation tools are set to passive, so it can be drawn in the viewports * feat: 🎸 Remove console logs and start using OHIF.log * feat: 🎸 Refactor measurement table to use Snackbar service of messages and make sure we only show save button if server type is dicomWeb * feat: 🎸 Refactor to remove mocked wadoRoot and use server * Fix to expose error once we can't save the SR * Update DCMJS into latest dev version * Update dcmjs with latest fixes * Fix PR callouts * Logging error on MeasurementReport creation * Preventing from breaking on non supported tools and also warning that some toolType is not sopported * Small error message update * Expose better the errors and when we have unsopported tools into the measurements * Renaming variable * Expose dcmjs tool support check * Change the way we warn the unsupportedTools * Adding style to the button * Small change on button style * Fix git conflicts * Fix after merge with latest master * Fix after merge with master, btn was not clickable * Fixing callouts * Adding util functions into files and refactor with JSDocs * Refactoring code, adding some basic JSDocs * Bump dcmjs with latest version and fixes * JSDocs and small refactors * yarn lock file after dcmjs update * Remove unused parameters * Registering a plain copy of server into measurementAPI * Small refactor * Start changing from toolType to toolName * Rename a function to get instanceMetadata * Adding error if server is not DICOMWeb on retrieve * Move snackbar outside of UI component and use UINotificationService * Refactor and JSDocs * Small fixes on JSDocs (style) * Remove unused import * Improve JSDocs on MeasurementApi * Remove refactor leftover * Improve JSDocs and propTypes * JSDocs and small refactors
2019-12-11 17:14:01 +01:00
import findMostRecentStructuredReport from './utils/findMostRecentStructuredReport';
import cornerstoneTools from 'cornerstone-tools';
import dcmjs from 'dcmjs';
const { MeasurementReport } = dcmjs.adapters.Cornerstone;
feat: 🎸 DICOM SR STOW on MeasurementAPI (#954) * feat: 🎸 DICOM SR STOW on MeasurementAPI Closes: #758 * feat: 🎸 Adding the dataExchance from DICOM SR * feat: 🎸 Fix some issues and get the retrieve measurements working * feat: 🎸 Preventing measurement tool helpers to broke because the data is not Number (it comes as string from dcmjs) * feat: 🎸 Adding a button to start testing SATE functionality * feat: 🎸Small fixes into the code * feat: 🎸 MAke sure we get latest SR in the study, even on lazyLoad mode * Revert "feat: 🎸 Preventing measurement tool helpers to broke because the data is not Number (it comes as string from dcmjs)" This reverts commit 4b3a1efb5810487d2319826fd59c03d779882b5e. * feat: 🎸 Make sure after sync we update the viewports and also that annotation tools are set to passive, so it can be drawn in the viewports * feat: 🎸 Remove console logs and start using OHIF.log * feat: 🎸 Refactor measurement table to use Snackbar service of messages and make sure we only show save button if server type is dicomWeb * feat: 🎸 Refactor to remove mocked wadoRoot and use server * Fix to expose error once we can't save the SR * Update DCMJS into latest dev version * Update dcmjs with latest fixes * Fix PR callouts * Logging error on MeasurementReport creation * Preventing from breaking on non supported tools and also warning that some toolType is not sopported * Small error message update * Expose better the errors and when we have unsopported tools into the measurements * Renaming variable * Expose dcmjs tool support check * Change the way we warn the unsupportedTools * Adding style to the button * Small change on button style * Fix git conflicts * Fix after merge with latest master * Fix after merge with master, btn was not clickable * Fixing callouts * Adding util functions into files and refactor with JSDocs * Refactoring code, adding some basic JSDocs * Bump dcmjs with latest version and fixes * JSDocs and small refactors * yarn lock file after dcmjs update * Remove unused parameters * Registering a plain copy of server into measurementAPI * Small refactor * Start changing from toolType to toolName * Rename a function to get instanceMetadata * Adding error if server is not DICOMWeb on retrieve * Move snackbar outside of UI component and use UINotificationService * Refactor and JSDocs * Small fixes on JSDocs (style) * Remove unused import * Improve JSDocs on MeasurementApi * Remove refactor leftover * Improve JSDocs and propTypes * JSDocs and small refactors
2019-12-11 17:14:01 +01:00
/**
*
* @typedef serverType
* @property {string} type - type of the server
* @property {string} wadoRoot - server wado root url
*
*/
/**
* Function to be registered into MeasurementAPI to retrieve measurements from DICOM Structured Reports
*
* @param {serverType} server
* @returns {Promise} Should resolve with OHIF measurementData object
*/
const retrieveMeasurements = server => {
log.info('[DICOMSR] retrieveMeasurements');
if (!server || server.type !== 'dicomWeb') {
log.error('[DICOMSR] DicomWeb server is required!');
return Promise.reject({});
}
const serverUrl = server.wadoRoot;
const studies = utils.studyMetadataManager.all();
Instance metadata/metadata providers overhaul (#1481) * Instance metadata plus metadata provider overhaul. Fix consumption of wado-uri urls fallbacks + datatype agnosticism. WIP DICOMify things. fix various issues with naturalized variable naming migration. Remove metadata provider. Fix consumption of multiframe images and addition of CWIL metadata. Fix strange build issues. Fix CWIL style windowWidth to array from naturalized DICOM. Fix PT, CT, CR and DX issues for cornerstone + DX issues for vtkjs. Move color palette fetching down to the natuaralized JSON level. Remove unused StudyMetadataSummary Remove redundant dicom metadata dictionary. Working local + json routes. Fix SR read. Finished first round of testing + cleaned up debugging etc. * data => metadata for instance naturalizedJSON * Update dcmjs version * Correct github isssues. * Fix erroneously replaced files. * Danny's recommended changes. * Instance metadata plus metadata provider overhaul. Fix consumption of wado-uri urls fallbacks + datatype agnosticism. WIP DICOMify things. fix various issues with naturalized variable naming migration. Remove metadata provider. Fix consumption of multiframe images and addition of CWIL metadata. Fix strange build issues. Fix CWIL style windowWidth to array from naturalized DICOM. Fix PT, CT, CR and DX issues for cornerstone + DX issues for vtkjs. Move color palette fetching down to the natuaralized JSON level. Remove unused StudyMetadataSummary Remove redundant dicom metadata dictionary. Working local + json routes. Fix SR read. Finished first round of testing + cleaned up debugging etc. * data => metadata for instance naturalizedJSON * Update dcmjs version * Correct github isssues. * Fix erroneously replaced files. * Danny's recommended changes. * Update JSON CI * Update casing of import. * Fix jump for SR. * Fix unit tests for measurements service * Fix json CI test. * fix: update yarn lock * Fix local non-encapsulated pdf view * CI updated to new sucess message. Co-authored-by: Danny <danny.ri.brown@gmail.com>
2020-03-09 20:03:23 +01:00
feat: 🎸 DICOM SR STOW on MeasurementAPI (#954) * feat: 🎸 DICOM SR STOW on MeasurementAPI Closes: #758 * feat: 🎸 Adding the dataExchance from DICOM SR * feat: 🎸 Fix some issues and get the retrieve measurements working * feat: 🎸 Preventing measurement tool helpers to broke because the data is not Number (it comes as string from dcmjs) * feat: 🎸 Adding a button to start testing SATE functionality * feat: 🎸Small fixes into the code * feat: 🎸 MAke sure we get latest SR in the study, even on lazyLoad mode * Revert "feat: 🎸 Preventing measurement tool helpers to broke because the data is not Number (it comes as string from dcmjs)" This reverts commit 4b3a1efb5810487d2319826fd59c03d779882b5e. * feat: 🎸 Make sure after sync we update the viewports and also that annotation tools are set to passive, so it can be drawn in the viewports * feat: 🎸 Remove console logs and start using OHIF.log * feat: 🎸 Refactor measurement table to use Snackbar service of messages and make sure we only show save button if server type is dicomWeb * feat: 🎸 Refactor to remove mocked wadoRoot and use server * Fix to expose error once we can't save the SR * Update DCMJS into latest dev version * Update dcmjs with latest fixes * Fix PR callouts * Logging error on MeasurementReport creation * Preventing from breaking on non supported tools and also warning that some toolType is not sopported * Small error message update * Expose better the errors and when we have unsopported tools into the measurements * Renaming variable * Expose dcmjs tool support check * Change the way we warn the unsupportedTools * Adding style to the button * Small change on button style * Fix git conflicts * Fix after merge with latest master * Fix after merge with master, btn was not clickable * Fixing callouts * Adding util functions into files and refactor with JSDocs * Refactoring code, adding some basic JSDocs * Bump dcmjs with latest version and fixes * JSDocs and small refactors * yarn lock file after dcmjs update * Remove unused parameters * Registering a plain copy of server into measurementAPI * Small refactor * Start changing from toolType to toolName * Rename a function to get instanceMetadata * Adding error if server is not DICOMWeb on retrieve * Move snackbar outside of UI component and use UINotificationService * Refactor and JSDocs * Small fixes on JSDocs (style) * Remove unused import * Improve JSDocs on MeasurementApi * Remove refactor leftover * Improve JSDocs and propTypes * JSDocs and small refactors
2019-12-11 17:14:01 +01:00
const latestSeries = findMostRecentStructuredReport(studies);
if (!latestSeries) return Promise.resolve({});
return retrieveMeasurementFromSR(latestSeries, studies, serverUrl);
};
/**
*
* @param {object[]} measurementData An array of measurements from the measurements service
* that you wish to serialize.
*/
const downloadReport = measurementData => {
const srDataset = generateReport(measurementData);
const reportBlob = dcmjs.data.datasetToBlob(srDataset);
//Create a URL for the binary.
var objectUrl = URL.createObjectURL(reportBlob);
window.location.assign(objectUrl);
};
/**
*
* @param {object[]} measurementData An array of measurements from the measurements service
* that you wish to serialize.
*/
const generateReport = measurementData => {
const ids = measurementData.map(md => md.id);
const filteredToolState = _getFilteredCornerstoneToolState(ids);
const report = MeasurementReport.generateReport(
filteredToolState,
cornerstone.metaData
);
return report.dataset;
};
/**
*
* @param {object[]} measurementData An array of measurements from the measurements service
* that you wish to serialize.
* @param {object} dataSource The dataSource that you wish to use to persist the data.
2020-06-30 19:02:23 +02:00
* @return {object} The naturalized report
*/
2020-06-30 19:02:23 +02:00
const storeMeasurements = async (measurementData, dataSource) => {
// TODO -> Eventually use the measurements directly and not the dcmjs adapter,
// But it is good enough for now whilst we only have cornerstone as a datasource.
log.info('[DICOMSR] storeMeasurements');
if (!dataSource || !dataSource.store || !dataSource.store.dicom) {
log.error('[DICOMSR] datasource has no dataSource.store.dicom endpoint!');
return Promise.reject({});
}
try {
2020-06-30 19:02:23 +02:00
const naturalizedReport = generateReport(measurementData);
const { StudyInstanceUID } = naturalizedReport;
await dataSource.store.dicom(naturalizedReport);
if (StudyInstanceUID) {
dataSource.deleteStudyMetadataPromise(StudyInstanceUID);
}
2020-06-30 19:02:23 +02:00
return naturalizedReport;
} catch (error) {
log.error(
`[DICOMSR] Error while saving the measurements: ${error.message}`
);
2020-06-30 19:02:23 +02:00
throw new Error(error.message || 'Error while saving the measurements.');
}
};
function _getFilteredCornerstoneToolState(uidFilter) {
const globalToolState = cornerstoneTools.globalImageIdSpecificToolStateManager.saveToolState();
const filteredToolState = {};
function addToFilteredToolState(imageId, toolType, toolDataI) {
if (!filteredToolState[imageId]) {
filteredToolState[imageId] = {};
}
const imageIdSpecificToolState = filteredToolState[imageId];
if (!imageIdSpecificToolState[toolType]) {
imageIdSpecificToolState[toolType] = {
data: [],
};
}
const toolData = imageIdSpecificToolState[toolType].data;
toolData.push(toolDataI);
}
const uids = uidFilter.slice();
const imageIds = Object.keys(globalToolState);
for (let i = 0; i < imageIds.length; i++) {
const imageId = imageIds[i];
const imageIdSpecificToolState = globalToolState[imageId];
const toolTypes = Object.keys(imageIdSpecificToolState);
for (let j = 0; j < toolTypes.length; j++) {
const toolType = toolTypes[j];
const toolData = imageIdSpecificToolState[toolType].data;
if (toolData) {
for (let k = 0; k < toolData.length; k++) {
const toolDataK = toolData[k];
const uidIndex = uids.findIndex(uid => uid === toolDataK.id);
if (uidIndex !== -1) {
addToFilteredToolState(imageId, toolType, toolDataK);
uids.splice(uidIndex, 1);
if (!uids.length) {
return filteredToolState;
}
}
}
}
}
}
return filteredToolState;
}
export { retrieveMeasurements, storeMeasurements, downloadReport };