From ced47c765fc7264d9e2580dbf62c287a9be6a202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20Lelis?= Date: Tue, 31 Jul 2018 10:02:47 -0300 Subject: [PATCH] feat(export-CSV) Export measurements to CSV file (#209) --- .../client/lib/exportToCsv.js | 25 ++++++++ .../ohif-measurements/client/lib/index.js | 1 + .../client/reports/reportMeasurementData.js | 58 +++++++++++++++++++ .../reports/reportMeasurementDataToCSV.js | 51 ++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 Packages/ohif-measurements/client/lib/exportToCsv.js create mode 100644 Packages/ohif-measurements/client/reports/reportMeasurementData.js create mode 100644 Packages/ohif-measurements/client/reports/reportMeasurementDataToCSV.js diff --git a/Packages/ohif-measurements/client/lib/exportToCsv.js b/Packages/ohif-measurements/client/lib/exportToCsv.js new file mode 100644 index 000000000..0a6c5799c --- /dev/null +++ b/Packages/ohif-measurements/client/lib/exportToCsv.js @@ -0,0 +1,25 @@ +import { OHIF } from 'meteor/ohif:core'; +import { getCSVMeasurementData } from '../reports/reportMeasurementDataToCSV'; + +const downloadCSV = (csvData, args = {}) => { + let data, link; + + const filename = args.filename || 'export.csv'; + + if (csvData == null) return; + + if (!csvData.match(/^data:text\/csv/i)) { + csvData = 'data:text/csv;charset=utf-8,' + csvData; + } + + data = encodeURI(csvData); + link = document.createElement('a'); + link.setAttribute('href', data); + link.setAttribute('download', filename); + link.click(); +}; + +OHIF.measurements.exportCSV = async (measurementApi, timepointApi) => { + const csvData = await getCSVMeasurementData(measurementApi, timepointApi); + downloadCSV(csvData); +}; diff --git a/Packages/ohif-measurements/client/lib/index.js b/Packages/ohif-measurements/client/lib/index.js index 5b6f8386a..088d3eeef 100644 --- a/Packages/ohif-measurements/client/lib/index.js +++ b/Packages/ohif-measurements/client/lib/index.js @@ -3,6 +3,7 @@ import './activateMeasurements'; import './clearCornerstoneToolState'; import './deactivateAllToolData'; import './exportPdf'; +import './exportToCsv'; import './findAndRenderDisplaySet'; import './getActiveTimepoint'; import './getImageDataUrl'; diff --git a/Packages/ohif-measurements/client/reports/reportMeasurementData.js b/Packages/ohif-measurements/client/reports/reportMeasurementData.js new file mode 100644 index 000000000..2798abe2e --- /dev/null +++ b/Packages/ohif-measurements/client/reports/reportMeasurementData.js @@ -0,0 +1,58 @@ +import { moment } from 'meteor/momentjs:moment'; +import { OHIF } from 'meteor/ohif:core'; + +export const getExportMeasurementData = async (measurementApi, timepointApi) => { + const currentTimepoint = timepointApi.current(); + const { timepointId } = currentTimepoint; + const study = OHIF.viewer.Studies.findBy({ + studyInstanceUid: currentTimepoint.studyInstanceUids[0] + }); + const { studyDescription, patientId, studyDate } = study; + const patientName = OHIF.viewerbase.helpers.formatPN(study.patientName); + + // All headers + const measurementData = { + patientName, + mrn: patientId, + studyDate: moment(studyDate).format('MMM DD YYYY'), + studyDescription, + data: [] + }; + + const addNewMeasurement = async (measurement) => { + const imageId = OHIF.viewerbase.getImageIdForImagePath(measurement.imagePath); + const { seriesDescription, seriesDate, modality, seriesInstanceUid } = cornerstone.metaData.get('series', imageId); + const meanStdDev = measurement.meanStdDev || {}; + + measurementData.data.push({ + seriesModality: modality, + seriesDate: moment(seriesDate).format('MMM DD YYYY'), + seriesDescription, + seriesInstanceUid, + measurementTool: measurement.toolType, + measurementDescription: OHIF.measurements.getLocationLabel(measurement.location) || 'No description', + number: measurement.measurementNumber, + length: measurement.length || '-', + mean: meanStdDev.mean || '-', + stdDev: meanStdDev.stdDev || '-', + area: measurement.area || '-' + }); + }; + + let allMeasurements = []; + Object.keys(measurementApi.toolGroups).forEach( toolGroup => { + let measurements = measurementApi.fetch(toolGroup, { timepointId }); + allMeasurements = allMeasurements.concat(measurements); + }); + const iterator = allMeasurements[Symbol.iterator](); + + let measurement; + let current = iterator.next(); + while (!current.done) { + measurement = current.value; + await addNewMeasurement(measurement); + current = iterator.next(); + } + + return measurementData; +}; diff --git a/Packages/ohif-measurements/client/reports/reportMeasurementDataToCSV.js b/Packages/ohif-measurements/client/reports/reportMeasurementDataToCSV.js new file mode 100644 index 000000000..75e8f3747 --- /dev/null +++ b/Packages/ohif-measurements/client/reports/reportMeasurementDataToCSV.js @@ -0,0 +1,51 @@ +import { getExportMeasurementData } from "./reportMeasurementData"; + +const columnDelimiter = ','; +const lineDelimiter = '\n'; +const headers = { + patientName: 'Patient Name', + mrn: 'MRN', + studyDate: 'Study Date', + seriesModality: 'Series Modality', + seriesDate: 'Series Date', + seriesDescription: 'Series Description', + seriesInstanceUid: 'Series InstanceUid', + measurementTool: 'Measurement Tool', + measurementDescription: 'Measurement Description', + length: 'Length', + mean: 'Mean', + stdDev: 'stdDev', + area: 'area' +}; + +export const getCSVMeasurementData = async (measurementApi, timepointApi) => { + let lineData = []; + let csvData = ''; + const dataObject = await getExportMeasurementData(measurementApi, timepointApi); + + for(header in headers) { + lineData.push(headers[header]); + } + csvData += lineData.join(columnDelimiter) + lineDelimiter; + + for(measurementLine of dataObject.data) { + lineData = [ + dataObject.patientName, + dataObject.mrn, + dataObject.studyDate, + measurementLine.seriesModality, + measurementLine.seriesDate, + measurementLine.seriesDescription, + measurementLine.seriesInstanceUid, + measurementLine.measurementTool, + measurementLine.measurementDescription, + measurementLine.length, + measurementLine.mean, + measurementLine.stdDev, + measurementLine.area + ]; + csvData += lineData.join(columnDelimiter) + lineDelimiter; + } + + return csvData; +}; \ No newline at end of file