feat(Segmentation): download RTSS from Labelmap(#3692)
Co-authored-by: Alireza <ar.sedghi@gmail.com>
@ -44,7 +44,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/tools": "^1.19.4",
|
||||
"@cornerstonejs/tools": "^1.20.1",
|
||||
"@cornerstonejs/adapters": "^1.20.1",
|
||||
"@kitware/vtk.js": "27.3.1",
|
||||
"react-color": "^2.19.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,16 @@ 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 { adaptersSEG, helpers } from '@cornerstonejs/adapters';
|
||||
import { DicomMetadataStore } from '@ohif/core';
|
||||
import {
|
||||
segmentation as cornerstoneToolsSegmentation,
|
||||
Enums as cornerstoneToolsEnums,
|
||||
} from '@cornerstonejs/tools';
|
||||
import { adaptersRT, helpers, adaptersSEG } 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,
|
||||
@ -12,12 +19,20 @@ import {
|
||||
getTargetViewport,
|
||||
} from './utils/hydrationUtils';
|
||||
|
||||
const { datasetToBlob } = dcmjs.data;
|
||||
|
||||
const {
|
||||
Cornerstone3D: {
|
||||
Segmentation: { generateLabelMaps2DFrom3D, generateSegmentation },
|
||||
},
|
||||
} = adaptersSEG;
|
||||
|
||||
const {
|
||||
Cornerstone3D: {
|
||||
RTSS: { generateRTSSFromSegmentations },
|
||||
},
|
||||
} = adaptersRT;
|
||||
|
||||
const { downloadDICOMData } = helpers;
|
||||
|
||||
const commandsModule = ({
|
||||
@ -348,6 +363,40 @@ 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: ({ segmentationId }) => {
|
||||
const segmentations = segmentationService.getSegmentation(segmentationId);
|
||||
const vtkUtils = {
|
||||
vtkImageMarchingSquares,
|
||||
vtkDataArray,
|
||||
vtkImageData,
|
||||
};
|
||||
|
||||
const RTSS = generateRTSSFromSegmentations(
|
||||
segmentations,
|
||||
classes.MetadataProvider,
|
||||
DicomMetadataStore,
|
||||
cache,
|
||||
cornerstoneToolsEnums,
|
||||
vtkUtils
|
||||
);
|
||||
|
||||
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 +421,9 @@ const commandsModule = ({
|
||||
storeSegmentation: {
|
||||
commandFn: actions.storeSegmentation,
|
||||
},
|
||||
downloadRTSS: {
|
||||
commandFn: actions.downloadRTSS,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@ -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,12 @@ export default function PanelSegmentation({
|
||||
}
|
||||
};
|
||||
|
||||
const onSegmentationDownloadRTSS = segmentationId => {
|
||||
commandsManager.runCommand('downloadRTSS', {
|
||||
segmentationId,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="ohif-scrollbar flex min-h-0 flex-auto select-none flex-col justify-between overflow-auto">
|
||||
@ -227,6 +233,7 @@ export default function PanelSegmentation({
|
||||
onSegmentationClick={onSegmentationClick}
|
||||
onSegmentationDelete={onSegmentationDelete}
|
||||
onSegmentationDownload={onSegmentationDownload}
|
||||
onSegmentationDownloadRTSS={onSegmentationDownloadRTSS}
|
||||
storeSegmentation={storeSegmentation}
|
||||
onSegmentationEdit={onSegmentationEdit}
|
||||
onSegmentClick={onSegmentClick}
|
||||
|
||||
@ -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),
|
||||
},
|
||||
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.101",
|
||||
"@ohif/ui": "3.7.0-beta.101",
|
||||
"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",
|
||||
|
||||
@ -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.101",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.101",
|
||||
"@ohif/ui": "3.7.0-beta.101",
|
||||
|
||||
@ -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',
|
||||
};
|
||||
}
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
@ -50,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.101",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.101",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.101",
|
||||
|
||||
@ -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.101",
|
||||
"cornerstone-math": "0.1.9",
|
||||
"dicom-parser": "^1.8.21"
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="23.7493737px" height="24.7494038px" viewBox="0 0 23.7493737 24.7494038" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>icon-tool-brush</title>
|
||||
<g id="Artboards" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Segmentation---assets" transform="translate(-40.625, -105.125)">
|
||||
<g id="icon-tool-brush" transform="translate(40, 105)">
|
||||
<g id="brush" transform="translate(1.5, 1)" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75">
|
||||
<path d="M0.285314129,22.3807117 C0.106218646,22.2955642 -0.00563032043,22.1126205 0.000218787638,21.9144007 C0.0060678957,21.716181 0.128509536,21.5401507 0.312314129,21.4657117 C2.69331413,20.5017117 1.92631413,17.7877117 2.63331413,16.3367117 C3.49915231,14.5926292 5.60557215,13.8677677 7.36131413,14.7097117 C12.6773141,17.3017117 6.34931413,25.2667117 0.285314129,22.3807117 Z" id="Path"></path>
|
||||
<path d="M21.5333141,0.349711738 C20.9877208,-0.135928959 20.1584241,-0.113148488 19.6403141,0.401711738 L7.74931413,12.2607117 C9.32532634,12.7428889 10.6345655,13.8504286 11.3713141,15.3247117 L21.7003141,2.24271174 C22.156142,1.66747397 22.0828125,0.836259875 21.5333141,0.349711738 Z" id="Path"></path>
|
||||
</g>
|
||||
<g id="Segmentation---assets" transform="translate(-40, -145)">
|
||||
<g id="icon-tool-brush" transform="translate(40, 145)">
|
||||
<path d="M3.24640621,22.3286833 C3.09173375,22.2551472 2.99513748,22.0971513 3.00018895,21.9259625 C3.00524042,21.7547737 3.11098486,21.6027485 3.26972426,21.5384606 C5.3260304,20.7059201 4.66362518,18.3620247 5.27421252,17.1088957 C6.02197747,15.6026514 7.84114758,14.9766383 9.35746132,15.7037675 C13.9485253,17.9422999 8.48346644,24.8211232 3.24640621,22.3286833 Z" id="Path" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||
<path d="M21.5968442,3.302022 C21.1256527,2.8826075 20.4094461,2.90228142 19.9619901,3.34693083 L9.69255027,13.5887345 C11.0536437,14.0051578 12.1843437,14.9616637 12.8206229,16.2349008 L21.7410706,4.93687606 C22.1347378,4.44008272 22.0714081,3.72222021 21.5968442,3.302022 Z" id="Path" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||
<rect id="Rectangle" x="0" y="0" width="25" height="25"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
@ -1,16 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24.25px" height="22.418445px" viewBox="0 0 24.25 22.418445" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>icon-tool-eraser</title>
|
||||
<g id="Artboards" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Segmentation---assets" transform="translate(-83.375, -106.3752)">
|
||||
<g id="icon-tool-eraser" transform="translate(83, 105)">
|
||||
<g id="eraser-1" transform="translate(1, 2)" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.25">
|
||||
<path d="M7,19.1705986 C5.7337971,19.1021794 4.52894862,18.6033051 3.585,17.7565986 L1.414,15.5835986 C0.635868537,14.8011205 0.635868537,13.5370767 1.414,12.7545986 L13.585,0.583598597 C14.3674781,-0.194532866 15.6315219,-0.194532866 16.414,0.583598597 L21.585,5.7545986 C22.3631315,6.53707671 22.3631315,7.80112049 21.585,8.5835986 L12.414,17.7545986 C11.4705925,18.601822 10.2661029,19.1013994 9,19.1705986 L7,19.1705986 Z" id="Path"></path>
|
||||
<line x1="9" y1="5.1685986" x2="17" y2="13.1685986" id="Path"></line>
|
||||
<line x1="0" y1="21.1685986" x2="23" y2="21.1685986" id="Path"></line>
|
||||
</g>
|
||||
<g id="Segmentation---assets" transform="translate(-83, -145)">
|
||||
<g id="icon-tool-eraser" transform="translate(83, 145)">
|
||||
<path d="M8.39130435,20.50359 C7.23520605,20.4411204 6.135127,19.9856264 5.27326087,19.2125465 L3.29104348,17.2285031 C2.58057562,16.5140665 2.58057562,15.3599396 3.29104348,14.6455031 L14.4036957,3.53285089 C15.1181322,2.82238304 16.2722591,2.82238304 16.9866957,3.53285089 L21.7080435,8.25419872 C22.4185113,8.96863525 22.4185113,10.1227622 21.7080435,10.8371987 L13.3345217,19.2107205 C12.4731497,19.9842722 11.3733983,20.4404081 10.2173913,20.50359 L8.39130435,20.50359 Z" id="Path" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||
<line x1="10.2173913" y1="7.71915524" x2="17.5217391" y2="15.0235031" id="Path" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"></line>
|
||||
<line x1="2" y1="22.3278509" x2="23" y2="22.3278509" id="Path" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"></line>
|
||||
<rect id="Rectangle" x="0" y="0" width="25" height="25"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
13
platform/ui/src/assets/icons/icon-tool-shape.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>icon-tool-shape</title>
|
||||
<g id="Artboards" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Segmentation---assets" transform="translate(-170, -193)">
|
||||
<g id="icon-tool-shape" transform="translate(170, 193)">
|
||||
<rect id="Rectangle" x="0" y="0" width="25" height="25"></rect>
|
||||
<rect id="Rectangle" stroke="currentColor" stroke-width="1.5" x="3" y="3" width="13" height="13" rx="1"></rect>
|
||||
<circle id="Oval" stroke="currentColor" stroke-width="1.5" cx="16.5" cy="16.5" r="6.5"></circle>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 813 B |
@ -1,21 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24.5px" height="16.5px" viewBox="0 0 24.5 16.5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>icon-tool-threshold</title>
|
||||
<g id="Artboards" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Segmentation---assets" transform="translate(-169.25, -109.25)">
|
||||
<g id="icon-tool-threshold" transform="translate(169, 105)">
|
||||
<g id="Group-16" transform="translate(1, 5)" stroke-width="1.5">
|
||||
<g id="Group-13">
|
||||
<line x1="19.5" y1="12.5" x2="23" y2="12.5" id="Line-2" stroke="currentColor" stroke-linecap="round"></line>
|
||||
<line x1="7.63278329e-17" y1="12.5" x2="14" y2="12.5" id="Line-2" stroke="currentColor" stroke-linecap="round"></line>
|
||||
<circle id="Oval" stroke="currentColor" cx="16.5" cy="12.5" r="2.5"></circle>
|
||||
<line x1="10.5" y1="2.5" x2="22.5" y2="2.5" id="Line-2" stroke="currentColor" stroke-linecap="round"></line>
|
||||
<line x1="2.27456942e-13" y1="2.5" x2="5.5" y2="2.5" id="Line-2" stroke="currentColor" stroke-linecap="round"></line>
|
||||
<circle id="Oval" stroke="currentColor" cx="8" cy="2.5" r="2.5"></circle>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Segmentation---assets" transform="translate(-127, -145)">
|
||||
<g id="icon-tool-threshold" transform="translate(127, 145)">
|
||||
<line x1="19.4565217" y1="16.8695652" x2="22.5" y2="16.8695652" id="Line-2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round"></line>
|
||||
<line x1="2.5" y1="16.8695652" x2="14.673913" y2="16.8695652" id="Line-2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round"></line>
|
||||
<circle id="Oval" stroke="currentColor" stroke-width="1.25" cx="16.8478261" cy="16.8695652" r="2.17391304"></circle>
|
||||
<line x1="11.6304348" y1="8.17391304" x2="22.0652174" y2="8.17391304" id="Line-2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round"></line>
|
||||
<line x1="2.5" y1="8.17391304" x2="7.2826087" y2="8.17391304" id="Line-2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round"></line>
|
||||
<circle id="Oval" stroke="currentColor" stroke-width="1.25" cx="9.45652174" cy="8.17391304" r="2.17391304"></circle>
|
||||
<rect id="Rectangle" x="0" y="0" width="25" height="25"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@ -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 */
|
||||
|
||||
@ -10,6 +10,7 @@ function SegmentationDropDownRow({
|
||||
onToggleSegmentationVisibility,
|
||||
onSegmentationEdit,
|
||||
onSegmentationDownload,
|
||||
onSegmentationDownloadRTSS,
|
||||
storeSegmentation,
|
||||
onSegmentationDelete,
|
||||
onSegmentationAdd,
|
||||
@ -40,6 +41,7 @@ function SegmentationDropDownRow({
|
||||
alignment="left"
|
||||
itemsClassName="text-primary-active"
|
||||
showBorders={false}
|
||||
maxCharactersPerLine={30}
|
||||
list={[
|
||||
...(!disableEditing
|
||||
? [
|
||||
@ -79,11 +81,17 @@ function SegmentationDropDownRow({
|
||||
: []),
|
||||
...[
|
||||
{
|
||||
title: 'Download',
|
||||
title: 'Download DICOM SEG',
|
||||
onClick: () => {
|
||||
onSegmentationDownload(activeSegmentation.id);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Download DICOM RTSTRUCT',
|
||||
onClick: () => {
|
||||
onSegmentationDownloadRTSS(activeSegmentation.id);
|
||||
},
|
||||
},
|
||||
],
|
||||
]}
|
||||
>
|
||||
@ -149,6 +157,7 @@ SegmentationDropDownRow.propTypes = {
|
||||
onToggleSegmentationVisibility: PropTypes.func,
|
||||
onSegmentationEdit: PropTypes.func,
|
||||
onSegmentationDownload: PropTypes.func,
|
||||
onSegmentationDownloadRTSS: PropTypes.func,
|
||||
storeSegmentation: PropTypes.func,
|
||||
onSegmentationDelete: PropTypes.func,
|
||||
onSegmentationAdd: PropTypes.func,
|
||||
|
||||
@ -22,6 +22,7 @@ const SegmentationGroupTable = ({
|
||||
onSegmentationClick,
|
||||
onSegmentationDelete,
|
||||
onSegmentationDownload,
|
||||
onSegmentationDownloadRTSS,
|
||||
storeSegmentation,
|
||||
// segment handlers
|
||||
onSegmentClick,
|
||||
@ -112,6 +113,7 @@ const SegmentationGroupTable = ({
|
||||
onSegmentationDelete={onSegmentationDelete}
|
||||
onSegmentationEdit={onSegmentationEdit}
|
||||
onSegmentationDownload={onSegmentationDownload}
|
||||
onSegmentationDownloadRTSS={onSegmentationDownloadRTSS}
|
||||
storeSegmentation={storeSegmentation}
|
||||
onSegmentationAdd={onSegmentationAdd}
|
||||
onToggleSegmentationVisibility={onToggleSegmentationVisibility}
|
||||
@ -188,6 +190,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,
|
||||
@ -217,6 +220,7 @@ SegmentationGroupTable.defaultProps = {
|
||||
onSegmentationClick: () => {},
|
||||
onSegmentationDelete: () => {},
|
||||
onSegmentationDownload: () => {},
|
||||
onSemgnetationDownloadRTSS: () => {},
|
||||
storeSegmentation: () => {},
|
||||
onSegmentClick: () => {},
|
||||
onSegmentAdd: () => {},
|
||||
|
||||
46
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"
|
||||
|
||||
|
||||