From 9166a4113e43e31e17e2e8db41efeb5769f710af Mon Sep 17 00:00:00 2001 From: dxlin Date: Tue, 3 Oct 2023 17:57:28 -0400 Subject: [PATCH 1/8] -sample usage of segmentation to RTSS conversion --- .../src/commandsModule.ts | 43 ++++++++++++++++++- .../src/panels/PanelSegmentation.tsx | 19 +++++++- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/extensions/cornerstone-dicom-seg/src/commandsModule.ts b/extensions/cornerstone-dicom-seg/src/commandsModule.ts index 7cffb83f764..5aa89c1c9cf 100644 --- a/extensions/cornerstone-dicom-seg/src/commandsModule.ts +++ b/extensions/cornerstone-dicom-seg/src/commandsModule.ts @@ -2,9 +2,12 @@ import dcmjs from 'dcmjs'; import { createReportDialogPrompt } from '@ohif/extension-default'; import { ServicesManager, Types } from '@ohif/core'; import { cache, metaData } from '@cornerstonejs/core'; -import { segmentation as cornerstoneToolsSegmentation } from '@cornerstonejs/tools'; +import { + segmentation as cornerstoneToolsSegmentation, + Enums as cornerstoneToolsEnums, +} from '@cornerstonejs/tools'; import { adaptersSEG, helpers } from '@cornerstonejs/adapters'; -import { DicomMetadataStore } from '@ohif/core'; +import { classes, DicomMetadataStore } from '@ohif/core'; import { updateViewportsForSegmentationRendering, @@ -12,6 +15,8 @@ import { getTargetViewport, } from './utils/hydrationUtils'; +const { datasetToBlob } = dcmjs.data; + const { Cornerstone3D: { Segmentation: { generateLabelMaps2DFrom3D, generateSegmentation }, @@ -348,6 +353,37 @@ const commandsModule = ({ return naturalizedReport; }, + /** + * Converts segmentations into RTSS for download. + * This sample function retrieves all segentations and passes to + * cornerstone tool adapter to convert to DICOM RTSS format. It then + * converts dataset to downloadable blob. + * + */ + downloadRTSS: ({}) => { + const segmentations = segmentationService.getSegmentations(); + + console.log(segmentations); + + adaptersSEG.Cornerstone3D.RTStruct.RTSS.generateRTSS( + segmentations, + classes.MetadataProvider, + DicomMetadataStore, + cache, + cornerstoneToolsEnums + ).then(RTSS => { + console.log(RTSS); + try { + const reportBlob = datasetToBlob(RTSS); + + //Create a URL for the binary. + const objectUrl = URL.createObjectURL(reportBlob); + window.location.assign(objectUrl); + } catch (e) { + console.warn(e); + } + }); + }, }; const definitions = { @@ -372,6 +408,9 @@ const commandsModule = ({ storeSegmentation: { commandFn: actions.storeSegmentation, }, + downloadRTSS: { + commandFn: actions.downloadRTSS, + }, }; return { diff --git a/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx b/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx index d17c0397b9f..ec7f808ec82 100644 --- a/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx +++ b/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx @@ -1,7 +1,7 @@ import { createReportAsync } from '@ohif/extension-default'; import React, { useEffect, useState, useCallback } from 'react'; import PropTypes from 'prop-types'; -import { SegmentationGroupTable } from '@ohif/ui'; +import { SegmentationGroupTable, LegacyButtonGroup, LegacyButton } from '@ohif/ui'; import callInputDialog from './callInputDialog'; import callColorPickerDialog from './colorPickerDialog'; @@ -215,6 +215,10 @@ export default function PanelSegmentation({ } }; + const onDownloadRTSSClick = async () => { + commandsManager.runCommand('downloadRTSS', {}); + }; + return ( <>
@@ -266,6 +270,19 @@ export default function PanelSegmentation({ } />
+
+ + + {t('Export RTSS')} + + +
); } From 1600331c622de2b8b99929136463d76d9de084a4 Mon Sep 17 00:00:00 2001 From: dxlin Date: Tue, 3 Oct 2023 18:06:43 -0400 Subject: [PATCH 2/8] -cleanup console log --- extensions/cornerstone-dicom-seg/src/commandsModule.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/extensions/cornerstone-dicom-seg/src/commandsModule.ts b/extensions/cornerstone-dicom-seg/src/commandsModule.ts index 5aa89c1c9cf..e9fe430c207 100644 --- a/extensions/cornerstone-dicom-seg/src/commandsModule.ts +++ b/extensions/cornerstone-dicom-seg/src/commandsModule.ts @@ -363,8 +363,6 @@ const commandsModule = ({ downloadRTSS: ({}) => { const segmentations = segmentationService.getSegmentations(); - console.log(segmentations); - adaptersSEG.Cornerstone3D.RTStruct.RTSS.generateRTSS( segmentations, classes.MetadataProvider, @@ -372,7 +370,6 @@ const commandsModule = ({ cache, cornerstoneToolsEnums ).then(RTSS => { - console.log(RTSS); try { const reportBlob = datasetToBlob(RTSS); From 21e8be50ff9715160ad6d50bd487382300bd2cb4 Mon Sep 17 00:00:00 2001 From: dxlin Date: Wed, 4 Oct 2023 22:45:10 -0400 Subject: [PATCH 3/8] -remove redundant annotation to RTSS logic for tmtv --- .../src/commandsModule.ts | 2 +- .../RTStructureSet/RTSSReport.js | 235 ------------------ .../RTStructureSet/dicomRTAnnotationExport.js | 10 +- .../measurements/AnnotationToPointData.js | 53 ---- .../RectangleROIStartEndThreshold.js | 51 ---- 5 files changed, 8 insertions(+), 343 deletions(-) delete mode 100644 extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/RTSSReport.js delete mode 100644 extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/measurements/AnnotationToPointData.js delete mode 100644 extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/measurements/RectangleROIStartEndThreshold.js diff --git a/extensions/cornerstone-dicom-seg/src/commandsModule.ts b/extensions/cornerstone-dicom-seg/src/commandsModule.ts index e9fe430c207..6f311e4f8c1 100644 --- a/extensions/cornerstone-dicom-seg/src/commandsModule.ts +++ b/extensions/cornerstone-dicom-seg/src/commandsModule.ts @@ -363,7 +363,7 @@ const commandsModule = ({ downloadRTSS: ({}) => { const segmentations = segmentationService.getSegmentations(); - adaptersSEG.Cornerstone3D.RTStruct.RTSS.generateRTSS( + adaptersSEG.Cornerstone3D.RTStruct.RTSS.generateRTSSFromSegmentations( segmentations, classes.MetadataProvider, DicomMetadataStore, diff --git a/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/RTSSReport.js b/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/RTSSReport.js deleted file mode 100644 index afcab5604a6..00000000000 --- a/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/RTSSReport.js +++ /dev/null @@ -1,235 +0,0 @@ -import AnnotationToPointData from './measurements/AnnotationToPointData'; -import dcmjs from 'dcmjs'; -import { DicomMetadataStore } from '@ohif/core'; - -const { DicomMetaDictionary } = dcmjs.data; - -export default class RTSSReport { - constructor() {} - - /** - * Convert handles to RTSSReport report object containing the dcmjs dicom dataset. - * - * Note: The tool data needs to be formatted in a specific way, and currently - * it is limited to the RectangleROIStartEndTool in the Cornerstone. - * - * @param annotations Array of Cornerstone tool annotation data - * @param metadataProvider Metadata provider - * @param options report generation options - * @returns Report object containing the dataset - */ - static generateReport(annotations, metadataProvider, options) { - let dataset = initializeDataset(annotations, metadataProvider); - - annotations.forEach((annotation, index) => { - const ContourSequence = AnnotationToPointData.convert( - annotation, - index, - metadataProvider, - options - ); - - dataset.StructureSetROISequence.push( - getStructureSetModule(annotation, index, metadataProvider) - ); - - dataset.ROIContourSequence.push(ContourSequence); - dataset.RTROIObservationsSequence.push( - getRTROIObservationsSequence(annotation, index, metadataProvider) - ); - - // ReferencedSeriesSequence - // Todo: handle more than one series - dataset.ReferencedSeriesSequence = getReferencedSeriesSequence( - annotation, - index, - metadataProvider - ); - - // ReferencedFrameOfReferenceSequence - dataset.ReferencedFrameOfReferenceSequence = getReferencedFrameOfReferenceSequence( - annotation, - metadataProvider, - dataset - ); - }); - - const fileMetaInformationVersionArray = new Uint8Array(2); - fileMetaInformationVersionArray[1] = 1; - - const _meta = { - FileMetaInformationVersion: { - Value: [fileMetaInformationVersionArray.buffer], - vr: 'OB', - }, - TransferSyntaxUID: { - Value: ['1.2.840.10008.1.2.1'], - vr: 'UI', - }, - ImplementationClassUID: { - Value: [DicomMetaDictionary.uid()], // TODO: could be git hash or other valid id - vr: 'UI', - }, - ImplementationVersionName: { - Value: ['dcmjs'], - vr: 'SH', - }, - }; - - dataset._meta = _meta; - - return dataset; - } - - /** - * Generate Cornerstone tool state from dataset - * @param {object} dataset dataset - * @param {object} hooks - * @param {function} hooks.getToolClass Function to map dataset to a tool class - * @returns - */ - static generateToolState(dataset, hooks = {}) { - // Todo - console.warn('RTSSReport.generateToolState not implemented'); - } -} - -function initializeDataset(annotations, metadataProvider) { - const rtSOPInstanceUID = DicomMetaDictionary.uid(); - - // get the first annotation data - const { referencedImageId: imageId, FrameOfReferenceUID } = annotations[0].metadata; - - const { studyInstanceUID } = metadataProvider.get('generalSeriesModule', imageId); - - const patientModule = getPatientModule(imageId, metadataProvider); - const rtSeriesModule = getRTSeriesModule(imageId, metadataProvider); - - return { - StructureSetROISequence: [], - ROIContourSequence: [], - RTROIObservationsSequence: [], - ReferencedSeriesSequence: [], - ReferencedFrameOfReferenceSequence: [], - ...patientModule, - ...rtSeriesModule, - StudyInstanceUID: studyInstanceUID, - SOPClassUID: '1.2.840.10008.5.1.4.1.1.481.3', // RT Structure Set Storage - SOPInstanceUID: rtSOPInstanceUID, - Manufacturer: 'dcmjs', - Modality: 'RTSTRUCT', - FrameOfReferenceUID, - PositionReferenceIndicator: '', - StructureSetLabel: '', - StructureSetName: '', - ReferringPhysicianName: '', - OperatorsName: '', - StructureSetDate: DicomMetaDictionary.date(), - StructureSetTime: DicomMetaDictionary.time(), - }; -} - -function getPatientModule(imageId, metadataProvider) { - const generalSeriesModule = metadataProvider.get('generalSeriesModule', imageId); - const generalStudyModule = metadataProvider.get('generalStudyModule', imageId); - const patientStudyModule = metadataProvider.get('patientStudyModule', imageId); - const patientModule = metadataProvider.get('patientModule', imageId); - const patientDemographicModule = metadataProvider.get('patientDemographicModule', imageId); - - return { - Modality: generalSeriesModule.modality, - PatientID: patientModule.patientId, - PatientName: patientModule.patientName, - PatientBirthDate: '', - PatientAge: patientStudyModule.patientAge, - PatientSex: patientDemographicModule.patientSex, - PatientWeight: patientStudyModule.patientWeight, - StudyDate: generalStudyModule.studyDate, - StudyTime: generalStudyModule.studyTime, - StudyID: 'ToDo', - AccessionNumber: generalStudyModule.accessionNumber, - }; -} - -function getReferencedFrameOfReferenceSequence(toolData, metadataProvider, dataset) { - const { referencedImageId: imageId, FrameOfReferenceUID } = toolData.metadata; - const instance = metadataProvider.get('instance', imageId); - const { SeriesInstanceUID } = instance; - - const { ReferencedSeriesSequence } = dataset; - - return [ - { - FrameOfReferenceUID, - RTReferencedStudySequence: [ - { - ReferencedSOPClassUID: dataset.SOPClassUID, - ReferencedSOPInstanceUID: dataset.SOPInstanceUID, - RTReferencedSeriesSequence: [ - { - SeriesInstanceUID, - ContourImageSequence: [...ReferencedSeriesSequence[0].ReferencedInstanceSequence], - }, - ], - }, - ], - }, - ]; -} - -function getReferencedSeriesSequence(toolData, index, metadataProvider) { - // grab imageId from toolData - const { referencedImageId: imageId } = toolData.metadata; - const instance = metadataProvider.get('instance', imageId); - const { SeriesInstanceUID, StudyInstanceUID } = instance; - - const ReferencedSeriesSequence = []; - if (SeriesInstanceUID) { - const series = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID); - - const ReferencedSeries = { - SeriesInstanceUID, - ReferencedInstanceSequence: [], - }; - - series.instances.forEach(instance => { - const { SOPInstanceUID, SOPClassUID } = instance; - ReferencedSeries.ReferencedInstanceSequence.push({ - ReferencedSOPClassUID: SOPClassUID, - ReferencedSOPInstanceUID: SOPInstanceUID, - }); - }); - - ReferencedSeriesSequence.push(ReferencedSeries); - } - - return ReferencedSeriesSequence; -} - -function getRTSeriesModule(imageId, metadataProvider) { - return { - SeriesInstanceUID: DicomMetaDictionary.uid(), // generate a new series instance uid - SeriesNumber: '99', // Todo:: what should be the series number? - }; -} - -function getStructureSetModule(toolData, index, metadataProvider) { - const { FrameOfReferenceUID } = toolData.metadata; - - return { - ROINumber: index + 1, - ROIName: `Todo: name ${index + 1}`, - ROIDescription: `Todo: description ${index + 1}`, - ROIGenerationAlgorithm: 'Todo: algorithm', - ReferencedFrameOfReferenceUID: FrameOfReferenceUID, - }; -} - -function getRTROIObservationsSequence(toolData, index, metadataProvider) { - return { - ObservationNumber: index + 1, - ReferencedROINumber: index + 1, - RTROIInterpretedType: 'Todo: type', - ROIInterpreter: 'Todo: interpreter', - }; -} diff --git a/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/dicomRTAnnotationExport.js b/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/dicomRTAnnotationExport.js index 999b37addaf..df4aa9c3cc1 100644 --- a/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/dicomRTAnnotationExport.js +++ b/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/dicomRTAnnotationExport.js @@ -1,12 +1,16 @@ -import RTSSReport from './RTSSReport'; import dcmjs from 'dcmjs'; -import { classes } from '@ohif/core'; +import { classes, DicomMetadataStore } from '@ohif/core'; +import { adaptersSEG } from '@cornerstonejs/adapters'; const { datasetToBlob } = dcmjs.data; const metadataProvider = classes.MetadataProvider; export default function dicomRTAnnotationExport(annotations) { - const dataset = RTSSReport.generateReport(annotations, metadataProvider); + const dataset = adaptersSEG.Cornerstone3D.RTStruct.RTSS.generateRTSSFromAnnotations( + annotations, + metadataProvider, + DicomMetadataStore + ); const reportBlob = datasetToBlob(dataset); //Create a URL for the binary. diff --git a/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/measurements/AnnotationToPointData.js b/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/measurements/AnnotationToPointData.js deleted file mode 100644 index d1d67cebf8c..00000000000 --- a/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/measurements/AnnotationToPointData.js +++ /dev/null @@ -1,53 +0,0 @@ -import RectangleROIStartEndThreshold from './RectangleROIStartEndThreshold'; - -function validateAnnotation(annotation) { - if (!annotation?.data) { - throw new Error('Tool data is empty'); - } - - if (!annotation.metadata || annotation.metadata.referenceImageId) { - throw new Error('Tool data is not associated with any imageId'); - } -} - -class AnnotationToPointData { - constructor() {} - - static convert(annotation, index, metadataProvider) { - validateAnnotation(annotation); - - const { toolName } = annotation.metadata; - const toolClass = AnnotationToPointData.TOOL_NAMES[toolName]; - - if (!toolClass) { - throw new Error(`Unknown tool type: ${toolName}, cannot convert to RTSSReport`); - } - - // Each toolData should become a list of contours, ContourSequence - // contains a list of contours with their pointData, their geometry - // type and their length. - const ContourSequence = toolClass.getContourSequence(annotation, metadataProvider); - - // Todo: random rgb color for now, options should be passed in - const color = [ - Math.floor(Math.random() * 255), - Math.floor(Math.random() * 255), - Math.floor(Math.random() * 255), - ]; - - return { - ReferencedROINumber: index + 1, - ROIDisplayColor: color, - ContourSequence, - }; - } - - static register(toolClass) { - AnnotationToPointData.TOOL_NAMES[toolClass.toolName] = toolClass; - } -} - -AnnotationToPointData.TOOL_NAMES = {}; -AnnotationToPointData.register(RectangleROIStartEndThreshold); - -export default AnnotationToPointData; diff --git a/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/measurements/RectangleROIStartEndThreshold.js b/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/measurements/RectangleROIStartEndThreshold.js deleted file mode 100644 index c3b86a627a2..00000000000 --- a/extensions/tmtv/src/utils/dicomRTAnnotationExport/RTStructureSet/measurements/RectangleROIStartEndThreshold.js +++ /dev/null @@ -1,51 +0,0 @@ -// comment -class RectangleROIStartEndThreshold { - constructor() {} - - static getContourSequence(toolData, metadataProvider) { - const { data } = toolData; - const { projectionPoints, projectionPointsImageIds } = data.cachedStats; - - return projectionPoints.map((point, index) => { - const ContourData = getPointData(point); - const ContourImageSequence = getContourImageSequence( - projectionPointsImageIds[index], - metadataProvider - ); - - return { - NumberOfContourPoints: ContourData.length / 3, - ContourImageSequence, - ContourGeometricType: 'CLOSED_PLANAR', - ContourData, - }; - }); - } -} - -RectangleROIStartEndThreshold.toolName = 'RectangleROIStartEndThreshold'; - -function getPointData(points) { - // Since this is a closed contour, the order of the points is important. - // re-order the points to be in the correct order clockwise - // Spread to make sure Float32Arrays are converted to arrays - const orderedPoints = [...points[0], ...points[1], ...points[3], ...points[2]]; - const pointsArray = orderedPoints.flat(); - - // reduce the precision of the points to 2 decimal places - const pointsArrayWithPrecision = pointsArray.map(point => { - return point.toFixed(2); - }); - - return pointsArrayWithPrecision; -} - -function getContourImageSequence(imageId, metadataProvider) { - const sopCommon = metadataProvider.get('sopCommonModule', imageId); - - return { - ReferencedSOPClassUID: sopCommon.sopClassUID, - ReferencedSOPInstanceUID: sopCommon.sopInstanceUID, - }; -} -export default RectangleROIStartEndThreshold; From bc458cac18ff11657d9610efca9171d48cf24d3f Mon Sep 17 00:00:00 2001 From: Alireza Date: Thu, 5 Oct 2023 17:10:37 -0400 Subject: [PATCH 4/8] inject vtk to adapters --- extensions/cornerstone-dicom-seg/package.json | 1 + .../cornerstone-dicom-seg/src/commandsModule.ts | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/extensions/cornerstone-dicom-seg/package.json b/extensions/cornerstone-dicom-seg/package.json index a3051ab2c8c..ca3af0a766b 100644 --- a/extensions/cornerstone-dicom-seg/package.json +++ b/extensions/cornerstone-dicom-seg/package.json @@ -45,6 +45,7 @@ "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/tools": "^1.19.4", + "@kitware/vtk.js": "27.3.1", "react-color": "^2.19.3" } } diff --git a/extensions/cornerstone-dicom-seg/src/commandsModule.ts b/extensions/cornerstone-dicom-seg/src/commandsModule.ts index 6f311e4f8c1..e953d4b9b8a 100644 --- a/extensions/cornerstone-dicom-seg/src/commandsModule.ts +++ b/extensions/cornerstone-dicom-seg/src/commandsModule.ts @@ -9,6 +9,10 @@ import { import { adaptersSEG, helpers } from '@cornerstonejs/adapters'; import { classes, DicomMetadataStore } from '@ohif/core'; +import vtkImageMarchingSquares from '@kitware/vtk.js/Filters/General/ImageMarchingSquares'; +import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray'; +import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData'; + import { updateViewportsForSegmentationRendering, getUpdatedViewportsForSegmentation, @@ -362,13 +366,19 @@ const commandsModule = ({ */ downloadRTSS: ({}) => { const segmentations = segmentationService.getSegmentations(); + const vtkUtils = { + vtkImageMarchingSquares, + vtkDataArray, + vtkImageData, + }; adaptersSEG.Cornerstone3D.RTStruct.RTSS.generateRTSSFromSegmentations( segmentations, classes.MetadataProvider, DicomMetadataStore, cache, - cornerstoneToolsEnums + cornerstoneToolsEnums, + vtkUtils ).then(RTSS => { try { const reportBlob = datasetToBlob(RTSS); From 128b70176b48794a6075019c5b981fd302788027 Mon Sep 17 00:00:00 2001 From: dxlin Date: Thu, 5 Oct 2023 21:17:55 -0400 Subject: [PATCH 5/8] -change for download RTSS to be per segmentation set -embed "Download RTSS" under segmentation dropdown --- .../src/commandsModule.ts | 4 ++-- .../src/panels/PanelSegmentation.tsx | 20 +++++-------------- .../SegmentationDropDownRow.tsx | 8 ++++++++ .../SegmentationGroupTable.tsx | 4 ++++ 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/extensions/cornerstone-dicom-seg/src/commandsModule.ts b/extensions/cornerstone-dicom-seg/src/commandsModule.ts index e953d4b9b8a..62423ad998a 100644 --- a/extensions/cornerstone-dicom-seg/src/commandsModule.ts +++ b/extensions/cornerstone-dicom-seg/src/commandsModule.ts @@ -364,8 +364,8 @@ const commandsModule = ({ * converts dataset to downloadable blob. * */ - downloadRTSS: ({}) => { - const segmentations = segmentationService.getSegmentations(); + downloadRTSS: ({ segmentationId }) => { + const segmentations = segmentationService.getSegmentation(segmentationId); const vtkUtils = { vtkImageMarchingSquares, vtkDataArray, diff --git a/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx b/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx index ec7f808ec82..90c5e9febbc 100644 --- a/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx +++ b/extensions/cornerstone-dicom-seg/src/panels/PanelSegmentation.tsx @@ -215,8 +215,10 @@ export default function PanelSegmentation({ } }; - const onDownloadRTSSClick = async () => { - commandsManager.runCommand('downloadRTSS', {}); + const onSegmentationDownloadRTSS = segmentationId => { + commandsManager.runCommand('downloadRTSS', { + segmentationId, + }); }; return ( @@ -231,6 +233,7 @@ export default function PanelSegmentation({ onSegmentationClick={onSegmentationClick} onSegmentationDelete={onSegmentationDelete} onSegmentationDownload={onSegmentationDownload} + onSegmentationDownloadRTSS={onSegmentationDownloadRTSS} storeSegmentation={storeSegmentation} onSegmentationEdit={onSegmentationEdit} onSegmentClick={onSegmentClick} @@ -270,19 +273,6 @@ export default function PanelSegmentation({ } /> -
- - - {t('Export RTSS')} - - -
); } diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx index d3fa818c2f9..53eff1014eb 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx @@ -10,6 +10,7 @@ function SegmentationDropDownRow({ onToggleSegmentationVisibility, onSegmentationEdit, onSegmentationDownload, + onSegmentationDownloadRTSS, storeSegmentation, onSegmentationDelete, onSegmentationAdd, @@ -81,6 +82,12 @@ function SegmentationDropDownRow({ onSegmentationDownload(activeSegmentation.id); }, }, + { + title: 'Download as RTSS', + onClick: () => { + onSegmentationDownloadRTSS(activeSegmentation.id); + }, + }, ] : []), ]} @@ -147,6 +154,7 @@ SegmentationDropDownRow.propTypes = { onToggleSegmentationVisibility: PropTypes.func, onSegmentationEdit: PropTypes.func, onSegmentationDownload: PropTypes.func, + onSegmentationDownloadRTSS: PropTypes.func, storeSegmentation: PropTypes.func, onSegmentationDelete: PropTypes.func, onSegmentationAdd: PropTypes.func, diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx index fce3fb4ed62..e64903edd63 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx @@ -22,6 +22,7 @@ const SegmentationGroupTable = ({ onSegmentationClick, onSegmentationDelete, onSegmentationDownload, + onSegmentationDownloadRTSS, storeSegmentation, // segment handlers onSegmentClick, @@ -113,6 +114,7 @@ const SegmentationGroupTable = ({ onSegmentationDelete={onSegmentationDelete} onSegmentationEdit={onSegmentationEdit} onSegmentationDownload={onSegmentationDownload} + onSegmentationDownloadRTSS={onSegmentationDownloadRTSS} storeSegmentation={storeSegmentation} onSegmentationAdd={onSegmentationAdd} onToggleSegmentationVisibility={onToggleSegmentationVisibility} @@ -190,6 +192,7 @@ SegmentationGroupTable.propTypes = { onSegmentationClick: PropTypes.func.isRequired, onSegmentationDelete: PropTypes.func.isRequired, onSegmentationDownload: PropTypes.func.isRequired, + onSegmentationDownloadRTSS: PropTypes.func.isRequired, storeSegmentation: PropTypes.func.isRequired, onSegmentClick: PropTypes.func.isRequired, onSegmentAdd: PropTypes.func.isRequired, @@ -219,6 +222,7 @@ SegmentationGroupTable.defaultProps = { onSegmentationClick: () => {}, onSegmentationDelete: () => {}, onSegmentationDownload: () => {}, + onSemgnetationDownloadRTSS: () => {}, storeSegmentation: () => {}, onSegmentClick: () => {}, onSegmentAdd: () => {}, From 42ae9ed92abfb0e0c585b1e6ada4e571e71775ff Mon Sep 17 00:00:00 2001 From: Alireza Date: Fri, 6 Oct 2023 08:51:17 -0400 Subject: [PATCH 6/8] fix export path --- extensions/cornerstone-dicom-seg/package.json | 1 + .../src/commandsModule.ts | 32 +++++++++++-------- package.json | 1 + platform/app/package.json | 1 + 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/extensions/cornerstone-dicom-seg/package.json b/extensions/cornerstone-dicom-seg/package.json index ca3af0a766b..aefaac8547d 100644 --- a/extensions/cornerstone-dicom-seg/package.json +++ b/extensions/cornerstone-dicom-seg/package.json @@ -45,6 +45,7 @@ "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/tools": "^1.19.4", + "@cornerstonejs/adapters": "^1.19.4", "@kitware/vtk.js": "27.3.1", "react-color": "^2.19.3" } diff --git a/extensions/cornerstone-dicom-seg/src/commandsModule.ts b/extensions/cornerstone-dicom-seg/src/commandsModule.ts index 62423ad998a..1926ee9f138 100644 --- a/extensions/cornerstone-dicom-seg/src/commandsModule.ts +++ b/extensions/cornerstone-dicom-seg/src/commandsModule.ts @@ -6,7 +6,7 @@ import { segmentation as cornerstoneToolsSegmentation, Enums as cornerstoneToolsEnums, } from '@cornerstonejs/tools'; -import { adaptersSEG, helpers } from '@cornerstonejs/adapters'; +import { adaptersRT, helpers, adaptersSEG } from '@cornerstonejs/adapters'; import { classes, DicomMetadataStore } from '@ohif/core'; import vtkImageMarchingSquares from '@kitware/vtk.js/Filters/General/ImageMarchingSquares'; @@ -27,6 +27,12 @@ const { }, } = adaptersSEG; +const { + Cornerstone3D: { + RTSS: { generateRTSSFromSegmentations }, + }, +} = adaptersRT; + const { downloadDICOMData } = helpers; const commandsModule = ({ @@ -372,24 +378,24 @@ const commandsModule = ({ vtkImageData, }; - adaptersSEG.Cornerstone3D.RTStruct.RTSS.generateRTSSFromSegmentations( + const RTSS = generateRTSSFromSegmentations( segmentations, classes.MetadataProvider, DicomMetadataStore, cache, cornerstoneToolsEnums, vtkUtils - ).then(RTSS => { - try { - const reportBlob = datasetToBlob(RTSS); - - //Create a URL for the binary. - const objectUrl = URL.createObjectURL(reportBlob); - window.location.assign(objectUrl); - } catch (e) { - console.warn(e); - } - }); + ); + + try { + const reportBlob = datasetToBlob(RTSS); + + //Create a URL for the binary. + const objectUrl = URL.createObjectURL(reportBlob); + window.location.assign(objectUrl); + } catch (e) { + console.warn(e); + } }, }; diff --git a/package.json b/package.json index 97fb2c48b49..dceeec8b347 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "build:package-all": "lerna run build:package --parallel --stream", "build:package-all-1": "lerna run build:package-1 --parallel --stream", "dev": "lerna run dev:viewer --stream", + "dev:no:cache": "lerna run dev:no:cache --stream", "dev:project": ".scripts/dev.sh", "dev:orthanc": "lerna run dev:orthanc --stream", "dev:dcm4chee": "lerna run dev:dcm4chee --stream", diff --git a/platform/app/package.json b/platform/app/package.json index 52d3067d6f7..5763d54666c 100644 --- a/platform/app/package.json +++ b/platform/app/package.json @@ -26,6 +26,7 @@ "build:viewer:demo": "cross-env NODE_ENV=production APP_CONFIG=config/demo.js HTML_TEMPLATE=rollbar.html QUICK_BUILD=false yarn run build", "build": "node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --progress --config .webpack/webpack.pwa.js", "dev": "cross-env NODE_ENV=development webpack serve --config .webpack/webpack.pwa.js", + "dev:no:cache": "cross-env NODE_ENV=development webpack serve --no-cache --config .webpack/webpack.pwa.js", "dev:orthanc": "cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker_nginx-orthanc.js webpack serve --config .webpack/webpack.pwa.js", "dev:dcm4chee": "cross-env NODE_ENV=development APP_CONFIG=config/local_dcm4chee.js webpack serve --config .webpack/webpack.pwa.js", "dev:static": "cross-env NODE_ENV=development APP_CONFIG=config/local_static.js webpack serve --config .webpack/webpack.pwa.js", From 84220a87b4c36bd5fd99502a93e0318ff7bbea78 Mon Sep 17 00:00:00 2001 From: Alireza Date: Fri, 6 Oct 2023 12:43:33 -0400 Subject: [PATCH 7/8] update packages --- extensions/cornerstone-dicom-seg/package.json | 4 +- extensions/cornerstone-dicom-sr/package.json | 6 +-- extensions/cornerstone/package.json | 10 ++-- extensions/measurement-tracking/package.json | 4 +- platform/app/package.json | 2 +- platform/core/package.json | 2 +- .../SegmentationDropDownRow.tsx | 5 +- yarn.lock | 46 +++++++++---------- 8 files changed, 40 insertions(+), 39 deletions(-) diff --git a/extensions/cornerstone-dicom-seg/package.json b/extensions/cornerstone-dicom-seg/package.json index aefaac8547d..51897fe24dc 100644 --- a/extensions/cornerstone-dicom-seg/package.json +++ b/extensions/cornerstone-dicom-seg/package.json @@ -44,8 +44,8 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/tools": "^1.19.4", - "@cornerstonejs/adapters": "^1.19.4", + "@cornerstonejs/tools": "^1.20.1", + "@cornerstonejs/adapters": "^1.20.1", "@kitware/vtk.js": "27.3.1", "react-color": "^2.19.3" } diff --git a/extensions/cornerstone-dicom-sr/package.json b/extensions/cornerstone-dicom-sr/package.json index 00315be9404..8b0a49fbd03 100644 --- a/extensions/cornerstone-dicom-sr/package.json +++ b/extensions/cornerstone-dicom-sr/package.json @@ -44,9 +44,9 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^1.19.4", - "@cornerstonejs/core": "^1.19.4", - "@cornerstonejs/tools": "^1.19.4", + "@cornerstonejs/adapters": "^1.20.1", + "@cornerstonejs/core": "^1.20.1", + "@cornerstonejs/tools": "^1.20.1", "classnames": "^2.3.2" } } diff --git a/extensions/cornerstone/package.json b/extensions/cornerstone/package.json index bbe688a8ea9..c128b712e66 100644 --- a/extensions/cornerstone/package.json +++ b/extensions/cornerstone/package.json @@ -36,7 +36,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.19.4", + "@cornerstonejs/dicom-image-loader": "^1.20.1", "@ohif/core": "3.7.0-beta.99", "@ohif/ui": "3.7.0-beta.99", "dcmjs": "^0.29.6", @@ -52,10 +52,10 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^1.19.4", - "@cornerstonejs/core": "^1.19.4", - "@cornerstonejs/streaming-image-volume-loader": "^1.19.4", - "@cornerstonejs/tools": "^1.19.4", + "@cornerstonejs/adapters": "^1.20.1", + "@cornerstonejs/core": "^1.20.1", + "@cornerstonejs/streaming-image-volume-loader": "^1.20.1", + "@cornerstonejs/tools": "^1.20.1", "@kitware/vtk.js": "27.3.1", "html2canvas": "^1.4.1", "lodash.debounce": "4.0.8", diff --git a/extensions/measurement-tracking/package.json b/extensions/measurement-tracking/package.json index 65cb09aade1..3fd2737ce03 100644 --- a/extensions/measurement-tracking/package.json +++ b/extensions/measurement-tracking/package.json @@ -30,8 +30,8 @@ "start": "yarn run dev" }, "peerDependencies": { - "@cornerstonejs/core": "^1.19.4", - "@cornerstonejs/tools": "^1.19.4", + "@cornerstonejs/core": "^1.20.1", + "@cornerstonejs/tools": "^1.20.1", "@ohif/core": "3.7.0-beta.99", "@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.99", "@ohif/ui": "3.7.0-beta.99", diff --git a/platform/app/package.json b/platform/app/package.json index 5763d54666c..1295c46763d 100644 --- a/platform/app/package.json +++ b/platform/app/package.json @@ -51,7 +51,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.19.4", + "@cornerstonejs/dicom-image-loader": "^1.20.1", "@ohif/core": "3.7.0-beta.99", "@ohif/extension-cornerstone": "3.7.0-beta.99", "@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.99", diff --git a/platform/core/package.json b/platform/core/package.json index 981f3ed4629..b75d8d72c1c 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -35,7 +35,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.19.4", + "@cornerstonejs/dicom-image-loader": "^1.20.1", "@ohif/ui": "3.7.0-beta.99", "cornerstone-math": "0.1.9", "dicom-parser": "^1.8.21" diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx index 53eff1014eb..4775d5cd17d 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationDropDownRow.tsx @@ -41,6 +41,7 @@ function SegmentationDropDownRow({ alignment="left" itemsClassName="text-primary-active" showBorders={false} + maxCharactersPerLine={30} list={[ ...(!disableEditing ? [ @@ -77,13 +78,13 @@ function SegmentationDropDownRow({ }, }, { - title: 'Download', + title: 'Download DICOM SEG', onClick: () => { onSegmentationDownload(activeSegmentation.id); }, }, { - title: 'Download as RTSS', + title: 'Download DICOM RTSTRUCT', onClick: () => { onSegmentationDownloadRTSS(activeSegmentation.id); }, diff --git a/yarn.lock b/yarn.lock index c5ea684ced7..4b89db15935 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1482,10 +1482,10 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@cornerstonejs/adapters@^1.19.4": - version "1.19.4" - resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.19.4.tgz#65b5f83f709faf2b62ba87effde7579a034fcfd6" - integrity sha512-ulirXb8Jx2zWRviXKbumU1K4J9q+nTRCAeG8SONZFFWlWTSwWWPNyQfOHDb3SE/KcupVk4gKzIjd+r0cC+cPdw== +"@cornerstonejs/adapters@^1.20.1": + version "1.20.1" + resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.20.1.tgz#3240a9af56f7508069c1e50fd1ceaa016d3df0e2" + integrity sha512-iEKhw8+/ll0I7bblbO82XNlW8DjdrtNO4M3lTnUj/lBTvt4pk0QK2KM+/ILcaSMizwgZ7ZANlOK06J4cTtINdw== dependencies: "@babel/runtime-corejs2" "^7.17.8" buffer "^6.0.3" @@ -1534,43 +1534,43 @@ resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.2.tgz#e96721d56f6ec96f7f95c16321d88cc8467d8d81" integrity sha512-lgdvBvvNezleY+4pIe2ceUsJzlZe/0PipdeubQ3vZZOz3xxtHHMR1XFCl4fgd8gosR8COHuD7h6q+MwgrwBsng== -"@cornerstonejs/core@^1.19.4": - version "1.19.4" - resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.19.4.tgz#7d527f151a1487955e7817b8113ab4c9ad2f7231" - integrity sha512-vVV3I6SzMbP4JqqRp49fBmVSr44l7qOXrO/gb6J3cY/EmwuUdFeSQdmN6ggouaQ45fhKPqPGcyHNO/iww9BR3Q== +"@cornerstonejs/core@^1.20.1": + version "1.20.1" + resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.20.1.tgz#0d8765b1f9e7a9314a29286d59e5cf7ece3bee2f" + integrity sha512-83Ebs35XSNMhbTXDP3V3tTDjM00Qh3o/eQGDu4cHUq0Cu2nVYXTQeIlaQkLHffoqUDKJh3PzbQCDRYtodJ/vhQ== dependencies: "@kitware/vtk.js" "27.3.1" detect-gpu "^5.0.22" gl-matrix "^3.4.3" lodash.clonedeep "4.5.0" -"@cornerstonejs/dicom-image-loader@^1.19.4": - version "1.19.4" - resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.19.4.tgz#778d933f8531233382080c3afea45854e7cf92b5" - integrity sha512-1+Dt+FR12pfbybPwOVJONx2KcoHbTyp8zCxrbmpRUxivwbq55SMExQa4ef8fFL97/+Hb9euczdA+PO9bbcD3Fw== +"@cornerstonejs/dicom-image-loader@^1.20.1": + version "1.20.1" + resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.20.1.tgz#01d112f626a6a3bf01c5fc44f2d32061e5c4b835" + integrity sha512-PpRykX3Y3D8LRyNg9vG8hh+CmvUKB8Q8cJ5R1XY0lSv7jsnB1hW2NGA8L9JfKalkUxAugC/nPEwRG6sf9c5z0A== dependencies: "@cornerstonejs/codec-charls" "^1.2.3" "@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2" "@cornerstonejs/codec-openjpeg" "^1.2.2" "@cornerstonejs/codec-openjph" "^2.4.2" - "@cornerstonejs/core" "^1.19.4" + "@cornerstonejs/core" "^1.20.1" dicom-parser "^1.8.9" pako "^2.0.4" uuid "^9.0.0" -"@cornerstonejs/streaming-image-volume-loader@^1.19.4": - version "1.19.4" - resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.19.4.tgz#d2a7afcd673ba112d851e95d2895109c3490cdce" - integrity sha512-Y+g6hdM3cTsdjKjsgy/H19/qEveRqSeT/Og/mCi7AjKe/UeS+EB3vqA7GfkkyGkM2x/U/+F+5RkyzFCXPA2nOw== +"@cornerstonejs/streaming-image-volume-loader@^1.20.1": + version "1.20.1" + resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.20.1.tgz#e5053a7bfe9967882115054b50142f36df8f468a" + integrity sha512-E36rlnLDE4EjCPf1f9tB5LQdxtwAHHJuTSdZoBvcEbKOG/EzlNr1bVfHoJoMkPX8aTGfO6Y7dNP57IyqqEY3Bw== dependencies: - "@cornerstonejs/core" "^1.19.4" + "@cornerstonejs/core" "^1.20.1" -"@cornerstonejs/tools@^1.19.4": - version "1.19.4" - resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.19.4.tgz#c0d97c40c3d3b0c13dd359eef703de394994c719" - integrity sha512-BVlmi1LuLH4Q5ZYGAPJT/p7t9p8NGLrux1eBGx7LmDe7G2ZOsOWU3kGkbGAzVtb/d0HB9eBV3cruA0+xRwmpMA== +"@cornerstonejs/tools@^1.20.1": + version "1.20.1" + resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.20.1.tgz#7242ce2cdc25fe8367c855f67f329be1f235ae64" + integrity sha512-0tPvnS7RNkVkZWmUOG/CnPfXRAdU0P9oBGtEC3t2h8uBAiCX/VUxBiXOKkbsnmzkEj1LDElCqLONSHqCvz35tg== dependencies: - "@cornerstonejs/core" "^1.19.4" + "@cornerstonejs/core" "^1.20.1" lodash.clonedeep "4.5.0" lodash.get "^4.4.2" From 39dec5713f0b0579b685f74c7fd598f3e65c7cf9 Mon Sep 17 00:00:00 2001 From: Alireza Date: Fri, 6 Oct 2023 14:21:07 -0400 Subject: [PATCH 8/8] remaining --- .../src/panels/SegmentationToolbox.tsx | 30 +++++++++---------- .../ui/src/assets/icons/icon-tool-brush.svg | 14 ++++----- .../ui/src/assets/icons/icon-tool-eraser.svg | 16 +++++----- .../ui/src/assets/icons/icon-tool-shape.svg | 13 ++++++++ .../src/assets/icons/icon-tool-threshold.svg | 24 +++++++-------- platform/ui/src/components/Icon/getIcon.js | 2 ++ 6 files changed, 53 insertions(+), 46 deletions(-) create mode 100644 platform/ui/src/assets/icons/icon-tool-shape.svg diff --git a/extensions/cornerstone-dicom-seg/src/panels/SegmentationToolbox.tsx b/extensions/cornerstone-dicom-seg/src/panels/SegmentationToolbox.tsx index 4be0ed1b3bc..f2d580cff46 100644 --- a/extensions/cornerstone-dicom-seg/src/panels/SegmentationToolbox.tsx +++ b/extensions/cornerstone-dicom-seg/src/panels/SegmentationToolbox.tsx @@ -10,9 +10,9 @@ const TOOL_TYPES = { SPHERE_BRUSH: 'SphereBrush', CIRCULAR_ERASER: 'CircularEraser', SPHERE_ERASER: 'SphereEraser', - CIRCLE_SCISSOR: 'CircleScissor', - RECTANGLE_SCISSOR: 'RectangleScissor', - SPHERE_SCISSOR: 'SphereScissor', + CIRCLE_SHAPE: 'CircleScissor', + RECTANGLE_SHAPE: 'RectangleScissor', + SPHERE_SHAPE: 'SphereScissor', THRESHOLD_CIRCULAR_BRUSH: 'ThresholdCircularBrush', THRESHOLD_SPHERE_BRUSH: 'ThresholdSphereBrush', }; @@ -31,7 +31,7 @@ const initialState = { brushSize: 15, mode: 'CircularEraser', // Can be 'CircularEraser' or 'SphereEraser' }, - Scissors: { + Shapes: { brushSize: 15, mode: 'CircleScissor', // E.g., 'CircleScissor', 'RectangleScissor', or 'SphereScissor' }, @@ -301,24 +301,24 @@ function SegmentationToolbox({ servicesManager, extensionManager }) { ], }, { - name: 'Scissor', - icon: 'icon-tool-scissor', + name: 'Shapes', + icon: 'icon-tool-shape', disabled: !toolsEnabled, active: - state.activeTool === TOOL_TYPES.CIRCLE_SCISSOR || - state.activeTool === TOOL_TYPES.RECTANGLE_SCISSOR || - state.activeTool === TOOL_TYPES.SPHERE_SCISSOR, - onClick: () => setToolActive(TOOL_TYPES.CIRCLE_SCISSOR), + state.activeTool === TOOL_TYPES.CIRCLE_SHAPE || + state.activeTool === TOOL_TYPES.RECTANGLE_SHAPE || + state.activeTool === TOOL_TYPES.SPHERE_SHAPE, + onClick: () => setToolActive(TOOL_TYPES.CIRCLE_SHAPE), options: [ { name: 'Mode', type: 'radio', - value: state.Scissors.mode, - id: 'scissor-mode', + value: state.Shapes.mode, + id: 'shape-mode', values: [ - { value: TOOL_TYPES.CIRCLE_SCISSOR, label: 'Circle' }, - { value: TOOL_TYPES.RECTANGLE_SCISSOR, label: 'Rectangle' }, - { value: TOOL_TYPES.SPHERE_SCISSOR, label: 'Sphere' }, + { value: TOOL_TYPES.CIRCLE_SHAPE, label: 'Circle' }, + { value: TOOL_TYPES.RECTANGLE_SHAPE, label: 'Rectangle' }, + { value: TOOL_TYPES.SPHERE_SHAPE, label: 'Sphere' }, ], onChange: value => setToolActive(value), }, diff --git a/platform/ui/src/assets/icons/icon-tool-brush.svg b/platform/ui/src/assets/icons/icon-tool-brush.svg index 0956137105a..7f78d720a96 100644 --- a/platform/ui/src/assets/icons/icon-tool-brush.svg +++ b/platform/ui/src/assets/icons/icon-tool-brush.svg @@ -1,15 +1,13 @@ - + icon-tool-brush - - - - - - + + + + - + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/icon-tool-eraser.svg b/platform/ui/src/assets/icons/icon-tool-eraser.svg index 35e29a5ddf3..5c72e4c3737 100644 --- a/platform/ui/src/assets/icons/icon-tool-eraser.svg +++ b/platform/ui/src/assets/icons/icon-tool-eraser.svg @@ -1,16 +1,14 @@ - + icon-tool-eraser - - - - - - - + + + + + - + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/icon-tool-shape.svg b/platform/ui/src/assets/icons/icon-tool-shape.svg new file mode 100644 index 00000000000..132f7b58a92 --- /dev/null +++ b/platform/ui/src/assets/icons/icon-tool-shape.svg @@ -0,0 +1,13 @@ + + + icon-tool-shape + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/icon-tool-threshold.svg b/platform/ui/src/assets/icons/icon-tool-threshold.svg index 9a518c5b358..d1bcaa76e2a 100644 --- a/platform/ui/src/assets/icons/icon-tool-threshold.svg +++ b/platform/ui/src/assets/icons/icon-tool-threshold.svg @@ -1,21 +1,17 @@ - + icon-tool-threshold - - - - - - - - - - - - + + + + + + + + - + \ No newline at end of file diff --git a/platform/ui/src/components/Icon/getIcon.js b/platform/ui/src/components/Icon/getIcon.js index 9604964a46d..d09de1e75fb 100644 --- a/platform/ui/src/components/Icon/getIcon.js +++ b/platform/ui/src/components/Icon/getIcon.js @@ -137,6 +137,7 @@ import iconMoreMenu from './../../assets/icons/icon-more-menu.svg'; import iconToolBrush from './../../assets/icons/icon-tool-brush.svg'; import iconToolEraser from './../../assets/icons/icon-tool-eraser.svg'; import iconToolScissor from './../../assets/icons/icon-tool-scissor.svg'; +import iconToolShape from './../../assets/icons/icon-tool-shape.svg'; import iconToolThreshold from './../../assets/icons/icon-tool-threshold.svg'; /** Old OHIF */ @@ -282,6 +283,7 @@ const ICONS = { 'icon-tool-brush': iconToolBrush, 'icon-tool-eraser': iconToolEraser, 'icon-tool-scissor': iconToolScissor, + 'icon-tool-shape': iconToolShape, 'icon-tool-threshold': iconToolThreshold, /** Old OHIF */