feat(image capture): Enhance SEG and RTSS Support with Dependency Updates and Bug Fixes (#4924)
This commit is contained in:
1 parent
479e280fdf
commit
fc33bd0d59
57 files changed
+1247
-935
No files matched your search
@@ -2,7 +2,8 @@ import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { DicomMetadataStore } from '@ohif/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Input, Label, PanelSection, Separator } from '@ohif/ui-next';
|
||||
import { Button, Input, Label, PanelSection } from '@ohif/ui-next';
|
||||
import { useSystem } from '@ohif/core/src';
|
||||
|
||||
const DEFAULT_MEATADATA = {
|
||||
PatientWeight: null,
|
||||
@@ -37,7 +38,10 @@ const InputRow = ({ children, className, ...props }) => {
|
||||
|
||||
// InputRow sub-components
|
||||
InputRow.Label = ({ children, unit, className, ...props }) => (
|
||||
<Label className={`min-w-32 flex-shrink-0 ${className || ''}`} {...props}>
|
||||
<Label
|
||||
className={`min-w-32 flex-shrink-0 ${className || ''}`}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
{unit && <span className="text-muted-foreground"> {unit}</span>}
|
||||
</Label>
|
||||
@@ -54,7 +58,8 @@ InputRow.Input = ({ className, ...props }) => (
|
||||
InputRow.Label.displayName = 'InputRow.Label';
|
||||
InputRow.Input.displayName = 'InputRow.Input';
|
||||
|
||||
export default function PanelPetSUV({ servicesManager, commandsManager }: withAppTypes) {
|
||||
export default function PanelPetSUV({ servicesManager }: withAppTypes) {
|
||||
const { commandsManager } = useSystem();
|
||||
const { t } = useTranslation('PanelSUV');
|
||||
const { displaySetService, toolGroupService, toolbarService, hangingProtocolService } =
|
||||
servicesManager.services;
|
||||
@@ -192,7 +197,9 @@ export default function PanelPetSUV({ servicesManager, commandsManager }: withAp
|
||||
<InputRow>
|
||||
<InputRow.Label unit="bq">{t('Total Dose')}</InputRow.Label>
|
||||
<InputRow.Input
|
||||
value={metadata.RadiopharmaceuticalInformationSequence.RadionuclideTotalDose || ''}
|
||||
value={
|
||||
metadata.RadiopharmaceuticalInformationSequence.RadionuclideTotalDose || ''
|
||||
}
|
||||
onChange={e => {
|
||||
handleMetadataChange({
|
||||
RadiopharmaceuticalInformationSequence: {
|
||||
@@ -206,7 +213,9 @@ export default function PanelPetSUV({ servicesManager, commandsManager }: withAp
|
||||
<InputRow>
|
||||
<InputRow.Label unit="s">{t('Half Life')}</InputRow.Label>
|
||||
<InputRow.Input
|
||||
value={metadata.RadiopharmaceuticalInformationSequence.RadionuclideHalfLife || ''}
|
||||
value={
|
||||
metadata.RadiopharmaceuticalInformationSequence.RadionuclideHalfLife || ''
|
||||
}
|
||||
onChange={e => {
|
||||
handleMetadataChange({
|
||||
RadiopharmaceuticalInformationSequence: {
|
||||
@@ -221,7 +230,8 @@ export default function PanelPetSUV({ servicesManager, commandsManager }: withAp
|
||||
<InputRow.Label unit="s">{t('Injection Time')}</InputRow.Label>
|
||||
<InputRow.Input
|
||||
value={
|
||||
metadata.RadiopharmaceuticalInformationSequence.RadiopharmaceuticalStartTime || ''
|
||||
metadata.RadiopharmaceuticalInformationSequence
|
||||
.RadiopharmaceuticalStartTime || ''
|
||||
}
|
||||
onChange={e => {
|
||||
handleMetadataChange({
|
||||
@@ -269,4 +279,4 @@ PanelPetSUV.propTypes = {
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
};
|
||||
+3
-4
@@ -2,11 +2,10 @@ import React, { useEffect } from 'react';
|
||||
import { useActiveViewportSegmentationRepresentations } from '@ohif/extension-cornerstone';
|
||||
import { handleROIThresholding } from '../../utils/handleROIThresholding';
|
||||
import { debounce } from '@ohif/core/src/utils';
|
||||
import { useSystem } from '@ohif/core/src';
|
||||
|
||||
export default function PanelRoiThresholdSegmentation({
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
}: withAppTypes) {
|
||||
export default function PanelRoiThresholdSegmentation() {
|
||||
const { commandsManager, servicesManager } = useSystem();
|
||||
const { segmentationService } = servicesManager.services;
|
||||
const { segmentationsWithRepresentations: segmentationsInfo } =
|
||||
useActiveViewportSegmentationRepresentations({ servicesManager });
|
||||
|
||||
@@ -1,62 +1,13 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
PanelSegmentation,
|
||||
useActiveViewportSegmentationRepresentations,
|
||||
} from '@ohif/extension-cornerstone';
|
||||
import { Button, Icons } from '@ohif/ui-next';
|
||||
import { PanelSegmentation } from '@ohif/extension-cornerstone';
|
||||
import PanelROIThresholdExport from './PanelROIThresholdSegmentation/PanelROIThresholdExport';
|
||||
|
||||
export default function PanelTMTV({
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
extensionManager,
|
||||
configuration,
|
||||
}: withAppTypes) {
|
||||
export default function PanelTMTV({ configuration }: withAppTypes) {
|
||||
return (
|
||||
<>
|
||||
<PanelSegmentation
|
||||
servicesManager={servicesManager}
|
||||
commandsManager={commandsManager}
|
||||
extensionManager={extensionManager}
|
||||
configuration={configuration}
|
||||
>
|
||||
<ExportCSV
|
||||
servicesManager={servicesManager}
|
||||
commandsManager={commandsManager}
|
||||
/>
|
||||
<PanelSegmentation configuration={configuration}>
|
||||
<PanelROIThresholdExport />
|
||||
</PanelSegmentation>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const ExportCSV = ({ servicesManager, commandsManager }: withAppTypes) => {
|
||||
const { segmentationsWithRepresentations: representations } =
|
||||
useActiveViewportSegmentationRepresentations({ servicesManager });
|
||||
|
||||
const tmtv = representations[0]?.segmentation.cachedStats?.tmtv;
|
||||
|
||||
const segmentations = representations.map(representation => representation.segmentation);
|
||||
|
||||
if (!segmentations.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-8 w-full items-center rounded pr-0.5">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="pl-1.5"
|
||||
onClick={() => {
|
||||
commandsManager.runCommand('exportTMTVReportCSV', {
|
||||
segmentations,
|
||||
tmtv,
|
||||
config: {},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Icons.Download />
|
||||
<span className="pl-1">CSV</span>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -8,7 +8,6 @@ import createAndDownloadTMTVReport from './utils/createAndDownloadTMTVReport';
|
||||
|
||||
import dicomRTAnnotationExport from './utils/dicomRTAnnotationExport/RTStructureSet';
|
||||
|
||||
import { getWebWorkerManager } from '@cornerstonejs/core';
|
||||
import { Enums } from '@cornerstonejs/tools';
|
||||
import { utils } from '@ohif/core';
|
||||
|
||||
@@ -22,32 +21,6 @@ const ROI_THRESHOLD_MANUAL_TOOL_IDS = [
|
||||
'CircleROIStartEndThreshold',
|
||||
];
|
||||
|
||||
const workerManager = getWebWorkerManager();
|
||||
|
||||
// Register the task
|
||||
|
||||
function getVolumesFromSegmentation(segmentationId) {
|
||||
const csSegmentation = csTools.segmentation.state.getSegmentation(segmentationId);
|
||||
const labelmapData = csSegmentation.representationData[
|
||||
SegmentationRepresentations.Labelmap
|
||||
] as csTools.Types.LabelmapToolOperationDataVolume;
|
||||
|
||||
const { volumeId, referencedVolumeId } = labelmapData;
|
||||
const labelmapVolume = cs.cache.getVolume(volumeId);
|
||||
const referencedVolume = cs.cache.getVolume(referencedVolumeId);
|
||||
|
||||
return { labelmapVolume, referencedVolume };
|
||||
}
|
||||
|
||||
function getLabelmapVolumeFromSegmentation(segmentation) {
|
||||
const { representationData } = segmentation;
|
||||
const { volumeId } = representationData[
|
||||
SegmentationRepresentations.Labelmap
|
||||
] as csTools.Types.LabelmapToolOperationDataVolume;
|
||||
|
||||
return cs.cache.getVolume(volumeId);
|
||||
}
|
||||
|
||||
const commandsModule = ({ servicesManager, commandsManager, extensionManager }: withAppTypes) => {
|
||||
const {
|
||||
viewportGridService,
|
||||
@@ -265,8 +238,14 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }:
|
||||
segmentations,
|
||||
});
|
||||
|
||||
let total_tlg = 0;
|
||||
for (const segmentationId in segReport) {
|
||||
const report = segReport[segmentationId];
|
||||
const tlg = report['namedStats_lesionGlycolysis'];
|
||||
total_tlg += tlg.value;
|
||||
}
|
||||
const additionalReportRows = [
|
||||
{ key: 'Total Lesion Glycolysis', value: { tlg: tlg.toFixed(4) } },
|
||||
{ key: 'Total Lesion Glycolysis', value: { tlg: total_tlg.toFixed(4) } },
|
||||
{ key: 'Threshold Configuration', value: { ...config } },
|
||||
];
|
||||
|
||||
@@ -382,9 +361,8 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }:
|
||||
continue;
|
||||
}
|
||||
|
||||
const referencedVolumeId = labelmapVolume.referencedVolumeId;
|
||||
|
||||
const referencedVolume = cs.cache.getVolume(referencedVolumeId);
|
||||
const referencedVolume =
|
||||
csTools.utilities.segmentation.getReferenceVolumeForSegmentationVolume(segmentationId);
|
||||
|
||||
if (!referencedVolume) {
|
||||
report[id] = segReport;
|
||||
@@ -476,9 +454,6 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }:
|
||||
thresholdSegmentationByRectangleROITool: {
|
||||
commandFn: actions.thresholdSegmentationByRectangleROITool,
|
||||
},
|
||||
getTotalLesionGlycolysis: {
|
||||
commandFn: actions.getTotalLesionGlycolysis,
|
||||
},
|
||||
calculateTMTV: {
|
||||
commandFn: actions.calculateTMTV,
|
||||
},
|
||||
|
||||
@@ -5,13 +5,7 @@ import PanelTMTV from './Panels/PanelTMTV';
|
||||
|
||||
function getPanelModule({ commandsManager, extensionManager, servicesManager }) {
|
||||
const wrappedPanelPetSuv = () => {
|
||||
return (
|
||||
<PanelPetSUV
|
||||
commandsManager={commandsManager}
|
||||
servicesManager={servicesManager}
|
||||
extensionManager={extensionManager}
|
||||
/>
|
||||
);
|
||||
return <PanelPetSUV />;
|
||||
};
|
||||
|
||||
const wrappedROIThresholdToolbox = () => {
|
||||
@@ -24,12 +18,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager })
|
||||
};
|
||||
|
||||
const wrappedROIThresholdExport = () => {
|
||||
return (
|
||||
<PanelROIThresholdExport
|
||||
commandsManager={commandsManager}
|
||||
servicesManager={servicesManager}
|
||||
/>
|
||||
);
|
||||
return <PanelROIThresholdExport />;
|
||||
};
|
||||
|
||||
const wrappedPanelTMTV = () => {
|
||||
@@ -43,10 +32,6 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager })
|
||||
commandsManager={commandsManager}
|
||||
servicesManager={servicesManager}
|
||||
/>
|
||||
<PanelROIThresholdExport
|
||||
commandsManager={commandsManager}
|
||||
servicesManager={servicesManager}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user