chore(prettier): full repo linting and code reformatting once and for all (#3627)
This commit is contained in:
1 parent
01500a2d4c
commit
9045ddaedc
656 files changed
+21737
-20628
No files matched your search
@@ -24,12 +24,9 @@ const DEFAULT_MEATADATA = {
|
||||
*/
|
||||
export default function PanelPetSUV({ servicesManager, commandsManager }) {
|
||||
const { t } = useTranslation('PanelSUV');
|
||||
const {
|
||||
displaySetService,
|
||||
toolGroupService,
|
||||
toolbarService,
|
||||
hangingProtocolService,
|
||||
} = (servicesManager as ServicesManager).services;
|
||||
const { displaySetService, toolGroupService, toolbarService, hangingProtocolService } = (
|
||||
servicesManager as ServicesManager
|
||||
).services;
|
||||
const [metadata, setMetadata] = useState(DEFAULT_MEATADATA);
|
||||
const [ptDisplaySet, setPtDisplaySet] = useState(null);
|
||||
|
||||
@@ -127,9 +124,7 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) {
|
||||
});
|
||||
|
||||
toolbarService.state.toggles['Crosshairs'] = false;
|
||||
toolbarService._broadcastEvent(
|
||||
toolbarService.EVENTS.TOOL_BAR_STATE_MODIFIED
|
||||
);
|
||||
toolbarService._broadcastEvent(toolbarService.EVENTS.TOOL_BAR_STATE_MODIFIED);
|
||||
|
||||
// metadata should be dcmjs naturalized
|
||||
DicomMetadataStore.updateMetadataForSeries(
|
||||
@@ -139,15 +134,13 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) {
|
||||
);
|
||||
|
||||
// update the displaySets
|
||||
displaySetService.setDisplaySetMetadataInvalidated(
|
||||
ptDisplaySet.displaySetInstanceUID
|
||||
);
|
||||
displaySetService.setDisplaySetMetadataInvalidated(ptDisplaySet.displaySetInstanceUID);
|
||||
}
|
||||
return (
|
||||
<div className="overflow-x-hidden overflow-y-auto invisible-scrollbar">
|
||||
<div className="invisible-scrollbar overflow-y-auto overflow-x-hidden">
|
||||
{
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col p-4 space-y-4 bg-primary-dark">
|
||||
<div className="bg-primary-dark flex flex-col space-y-4 p-4">
|
||||
<Input
|
||||
label={t('Patient Sex')}
|
||||
labelClassName="text-white mb-2"
|
||||
@@ -174,10 +167,7 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) {
|
||||
label={t('Total Dose (bq)')}
|
||||
labelClassName="text-white mb-2"
|
||||
className="mt-1"
|
||||
value={
|
||||
metadata.RadiopharmaceuticalInformationSequence
|
||||
.RadionuclideTotalDose || ''
|
||||
}
|
||||
value={metadata.RadiopharmaceuticalInformationSequence.RadionuclideTotalDose || ''}
|
||||
onChange={e => {
|
||||
handleMetadataChange({
|
||||
RadiopharmaceuticalInformationSequence: {
|
||||
@@ -190,10 +180,7 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) {
|
||||
label={t('Half Life (s)')}
|
||||
labelClassName="text-white mb-2"
|
||||
className="mt-1"
|
||||
value={
|
||||
metadata.RadiopharmaceuticalInformationSequence
|
||||
.RadionuclideHalfLife || ''
|
||||
}
|
||||
value={metadata.RadiopharmaceuticalInformationSequence.RadionuclideHalfLife || ''}
|
||||
onChange={e => {
|
||||
handleMetadataChange({
|
||||
RadiopharmaceuticalInformationSequence: {
|
||||
@@ -207,8 +194,7 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) {
|
||||
labelClassName="text-white mb-2"
|
||||
className="mt-1"
|
||||
value={
|
||||
metadata.RadiopharmaceuticalInformationSequence
|
||||
.RadiopharmaceuticalStartTime || ''
|
||||
metadata.RadiopharmaceuticalInformationSequence.RadiopharmaceuticalStartTime || ''
|
||||
}
|
||||
onChange={e => {
|
||||
handleMetadataChange({
|
||||
|
||||
@@ -8,9 +8,12 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
|
||||
return (
|
||||
<>
|
||||
{segmentations?.length ? (
|
||||
<div className="flex justify-center mt-4 space-x-2">
|
||||
<div className="mt-4 flex justify-center space-x-2">
|
||||
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
|
||||
<ButtonGroup color="black" size="inherit">
|
||||
<ButtonGroup
|
||||
color="black"
|
||||
size="inherit"
|
||||
>
|
||||
<LegacyButton
|
||||
className="px-2 py-2 text-base"
|
||||
disabled={tmtvValue === null}
|
||||
@@ -25,7 +28,10 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
|
||||
{t('Export CSV')}
|
||||
</LegacyButton>
|
||||
</ButtonGroup>
|
||||
<ButtonGroup color="black" size="inherit">
|
||||
<ButtonGroup
|
||||
color="black"
|
||||
size="inherit"
|
||||
>
|
||||
<LegacyButton
|
||||
className="px-2 py-2 text-base"
|
||||
onClick={() => {
|
||||
|
||||
+12
-26
@@ -5,9 +5,7 @@ import { SegmentationTable, Button, Icon } from '@ohif/ui';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import segmentationEditHandler from './segmentationEditHandler';
|
||||
import ExportReports from './ExportReports';
|
||||
import ROIThresholdConfiguration, {
|
||||
ROI_STAT,
|
||||
} from './ROIThresholdConfiguration';
|
||||
import ROIThresholdConfiguration, { ROI_STAT } from './ROIThresholdConfiguration';
|
||||
|
||||
const LOWER_CT_THRESHOLD_DEFAULT = -1024;
|
||||
const UPPER_CT_THRESHOLD_DEFAULT = 1024;
|
||||
@@ -44,19 +42,14 @@ function reducer(state, action) {
|
||||
}
|
||||
}
|
||||
|
||||
export default function PanelRoiThresholdSegmentation({
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
}) {
|
||||
export default function PanelRoiThresholdSegmentation({ servicesManager, commandsManager }) {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
|
||||
const { t } = useTranslation('PanelSUV');
|
||||
const [showConfig, setShowConfig] = useState(false);
|
||||
const [labelmapLoading, setLabelmapLoading] = useState(false);
|
||||
const [selectedSegmentationId, setSelectedSegmentationId] = useState(null);
|
||||
const [segmentations, setSegmentations] = useState(() =>
|
||||
segmentationService.getSegmentations()
|
||||
);
|
||||
const [segmentations, setSegmentations] = useState(() => segmentationService.getSegmentations());
|
||||
|
||||
const [config, dispatch] = useReducer(reducer, {
|
||||
strategy: DEFAULT_STRATEGY,
|
||||
@@ -95,9 +88,7 @@ export default function PanelRoiThresholdSegmentation({
|
||||
const lesionGlyoclysisStats = lesionStats.volume * lesionStats.meanValue;
|
||||
|
||||
// update segDetails with the suv peak for the active segmentation
|
||||
const segmentation = segmentationService.getSegmentation(
|
||||
selectedSegmentationId
|
||||
);
|
||||
const segmentation = segmentationService.getSegmentation(selectedSegmentationId);
|
||||
|
||||
const cachedStats = {
|
||||
lesionStats,
|
||||
@@ -178,8 +169,8 @@ export default function PanelRoiThresholdSegmentation({
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col">
|
||||
<div className="overflow-x-hidden overflow-y-auto invisible-scrollbar">
|
||||
<div className="flex mx-4 my-4 mb-4 space-x-4">
|
||||
<div className="invisible-scrollbar overflow-y-auto overflow-x-hidden">
|
||||
<div className="mx-4 my-4 mb-4 flex space-x-4">
|
||||
<Button
|
||||
onClick={() => {
|
||||
setLabelmapLoading(true);
|
||||
@@ -196,14 +187,12 @@ export default function PanelRoiThresholdSegmentation({
|
||||
<Button onClick={handleROIThresholding}>Run</Button>
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center justify-around h-8 mb-2 border-t outline-none cursor-pointer select-none bg-secondary-dark first:border-0 border-secondary-light"
|
||||
className="bg-secondary-dark border-secondary-light mb-2 flex h-8 cursor-pointer select-none items-center justify-around border-t outline-none first:border-0"
|
||||
onClick={() => {
|
||||
setShowConfig(!showConfig);
|
||||
}}
|
||||
>
|
||||
<div className="px-4 text-base text-white">
|
||||
{t('ROI Threshold Configuration')}
|
||||
</div>
|
||||
<div className="px-4 text-base text-white">{t('ROI Threshold Configuration')}</div>
|
||||
</div>
|
||||
{showConfig && (
|
||||
<ROIThresholdConfiguration
|
||||
@@ -246,8 +235,8 @@ export default function PanelRoiThresholdSegmentation({
|
||||
) : null}
|
||||
</div>
|
||||
{tmtvValue !== null ? (
|
||||
<div className="flex items-baseline justify-between px-2 py-1 mt-4 bg-secondary-dark">
|
||||
<span className="text-base font-bold tracking-widest text-white uppercase">
|
||||
<div className="bg-secondary-dark mt-4 flex items-baseline justify-between px-2 py-1">
|
||||
<span className="text-base font-bold uppercase tracking-widest text-white">
|
||||
{'TMTV:'}
|
||||
</span>
|
||||
<div className="text-white">{`${tmtvValue} mL`}</div>
|
||||
@@ -262,13 +251,10 @@ export default function PanelRoiThresholdSegmentation({
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="opacity-50 hover:opacity-80 flex items-center justify-center text-blue-400 mt-auto cursor-pointer mb-4"
|
||||
className="mt-auto mb-4 flex cursor-pointer items-center justify-center text-blue-400 opacity-50 hover:opacity-80"
|
||||
onClick={() => {
|
||||
// navigate to a url in a new tab
|
||||
window.open(
|
||||
'https://github.com/OHIF/Viewers/blob/master/modes/tmtv/README.md',
|
||||
'_blank'
|
||||
);
|
||||
window.open('https://github.com/OHIF/Viewers/blob/master/modes/tmtv/README.md', '_blank');
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
|
||||
+24
-18
@@ -14,18 +14,15 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
const { t } = useTranslation('ROIThresholdConfiguration');
|
||||
|
||||
return (
|
||||
<div className="flex flex-col px-4 space-y-4 bg-primary-dark py-2">
|
||||
<div className="bg-primary-dark flex flex-col space-y-4 px-4 py-2">
|
||||
<div className="flex items-end space-x-2">
|
||||
<div className="flex flex-col w-1/2">
|
||||
<div className="flex w-1/2 flex-col">
|
||||
<Select
|
||||
label={t('Strategy')}
|
||||
closeMenuOnSelect={true}
|
||||
className="mr-2 bg-black border-primary-main text-white "
|
||||
className="border-primary-main mr-2 bg-black text-white "
|
||||
options={options}
|
||||
placeholder={
|
||||
options.find(option => option.value === config.strategy)
|
||||
.placeHolder
|
||||
}
|
||||
placeholder={options.find(option => option.value === config.strategy).placeHolder}
|
||||
value={config.strategy}
|
||||
onChange={({ value }) => {
|
||||
dispatch({
|
||||
@@ -66,7 +63,7 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
<Input
|
||||
label={t('Percentage of Max SUV')}
|
||||
labelClassName="text-white"
|
||||
className="mt-2 bg-black border-primary-main"
|
||||
className="border-primary-main mt-2 bg-black"
|
||||
type="text"
|
||||
containerClassName="mr-2"
|
||||
value={config.weight}
|
||||
@@ -81,11 +78,14 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
/>
|
||||
)}
|
||||
{config.strategy !== ROI_STAT && (
|
||||
<div className="text-sm mr-2">
|
||||
<div className="mr-2 text-sm">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr className="mt-2">
|
||||
<td className="pr-4 pt-2" colSpan="3">
|
||||
<td
|
||||
className="pr-4 pt-2"
|
||||
colSpan="3"
|
||||
>
|
||||
<Label
|
||||
className="text-white"
|
||||
text="Lower & Upper Ranges"
|
||||
@@ -93,15 +93,18 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
</td>
|
||||
</tr>
|
||||
<tr className="mt-2">
|
||||
<td className="text-center pr-4 pt-2">
|
||||
<Label className="text-white" text="CT"></Label>
|
||||
<td className="pr-4 pt-2 text-center">
|
||||
<Label
|
||||
className="text-white"
|
||||
text="CT"
|
||||
></Label>
|
||||
</td>
|
||||
<td>
|
||||
<div className="flex justify-between">
|
||||
<Input
|
||||
label={t('')}
|
||||
labelClassName="text-white"
|
||||
className="mt-2 bg-black border-primary-main"
|
||||
className="border-primary-main mt-2 bg-black"
|
||||
type="text"
|
||||
containerClassName="mr-2"
|
||||
value={config.ctLower}
|
||||
@@ -117,7 +120,7 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
<Input
|
||||
label={t('')}
|
||||
labelClassName="text-white"
|
||||
className="mt-2 bg-black border-primary-main"
|
||||
className="border-primary-main mt-2 bg-black"
|
||||
type="text"
|
||||
containerClassName="mr-2"
|
||||
value={config.ctUpper}
|
||||
@@ -134,15 +137,18 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-center pr-4 pt-2">
|
||||
<Label className="text-white" text="PT"></Label>
|
||||
<td className="pr-4 pt-2 text-center">
|
||||
<Label
|
||||
className="text-white"
|
||||
text="PT"
|
||||
></Label>
|
||||
</td>
|
||||
<td>
|
||||
<div className="flex justify-between">
|
||||
<Input
|
||||
label={t('')}
|
||||
labelClassName="text-white"
|
||||
className="mt-2 bg-black border-primary-main"
|
||||
className="border-primary-main mt-2 bg-black"
|
||||
type="text"
|
||||
containerClassName="mr-2"
|
||||
value={config.ptLower}
|
||||
@@ -158,7 +164,7 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
<Input
|
||||
label={t('')}
|
||||
labelClassName="text-white"
|
||||
className="mt-2 bg-black border-primary-main"
|
||||
className="border-primary-main mt-2 bg-black"
|
||||
type="text"
|
||||
containerClassName="mr-2"
|
||||
value={config.ptUpper}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ function segmentationItemEditHandler({ id, servicesManager }) {
|
||||
return (
|
||||
<Input
|
||||
autoFocus
|
||||
className="bg-black border-primary-main"
|
||||
className="border-primary-main bg-black"
|
||||
type="text"
|
||||
containerClassName="mr-2"
|
||||
value={value.label}
|
||||
|
||||
@@ -14,11 +14,7 @@ const metadataProvider = classes.MetadataProvider;
|
||||
const RECTANGLE_ROI_THRESHOLD_MANUAL = 'RectangleROIStartEndThreshold';
|
||||
const LABELMAP = csTools.Enums.SegmentationRepresentations.Labelmap;
|
||||
|
||||
const commandsModule = ({
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
extensionManager,
|
||||
}) => {
|
||||
const commandsModule = ({ servicesManager, commandsManager, extensionManager }) => {
|
||||
const {
|
||||
viewportGridService,
|
||||
uiNotificationService,
|
||||
@@ -74,9 +70,7 @@ const commandsModule = ({
|
||||
continue;
|
||||
}
|
||||
|
||||
ptDisplaySet = displaySets.find(
|
||||
displaySet => displaySet.Modality === 'PT'
|
||||
);
|
||||
ptDisplaySet = displaySets.find(displaySet => displaySet.Modality === 'PT');
|
||||
|
||||
if (ptDisplaySet) {
|
||||
break;
|
||||
@@ -102,17 +96,13 @@ const commandsModule = ({
|
||||
PatientWeight: instance.PatientWeight,
|
||||
RadiopharmaceuticalInformationSequence: {
|
||||
RadionuclideTotalDose:
|
||||
instance.RadiopharmaceuticalInformationSequence[0]
|
||||
.RadionuclideTotalDose,
|
||||
instance.RadiopharmaceuticalInformationSequence[0].RadionuclideTotalDose,
|
||||
RadionuclideHalfLife:
|
||||
instance.RadiopharmaceuticalInformationSequence[0]
|
||||
.RadionuclideHalfLife,
|
||||
instance.RadiopharmaceuticalInformationSequence[0].RadionuclideHalfLife,
|
||||
RadiopharmaceuticalStartTime:
|
||||
instance.RadiopharmaceuticalInformationSequence[0]
|
||||
.RadiopharmaceuticalStartTime,
|
||||
instance.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartTime,
|
||||
RadiopharmaceuticalStartDateTime:
|
||||
instance.RadiopharmaceuticalInformationSequence[0]
|
||||
.RadiopharmaceuticalStartDateTime,
|
||||
instance.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartDateTime,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -148,10 +138,7 @@ const commandsModule = ({
|
||||
representationType
|
||||
);
|
||||
|
||||
segmentationService.setActiveSegmentationForToolGroup(
|
||||
segmentationId,
|
||||
toolGroupId
|
||||
);
|
||||
segmentationService.setActiveSegmentationForToolGroup(segmentationId, toolGroupId);
|
||||
}
|
||||
|
||||
return segmentationId;
|
||||
@@ -160,21 +147,14 @@ const commandsModule = ({
|
||||
const toolGroupIds = _getMatchedViewportsToolGroupIds();
|
||||
|
||||
toolGroupIds.forEach(toolGroupId => {
|
||||
segmentationService.setActiveSegmentationForToolGroup(
|
||||
segmentationId,
|
||||
toolGroupId
|
||||
);
|
||||
segmentationService.setActiveSegmentationForToolGroup(segmentationId, toolGroupId);
|
||||
});
|
||||
},
|
||||
thresholdSegmentationByRectangleROITool: ({ segmentationId, config }) => {
|
||||
const segmentation = csTools.segmentation.state.getSegmentation(
|
||||
segmentationId
|
||||
);
|
||||
const segmentation = csTools.segmentation.state.getSegmentation(segmentationId);
|
||||
|
||||
const { representationData } = segmentation;
|
||||
const {
|
||||
displaySetMatchDetails: matchDetails,
|
||||
} = hangingProtocolService.getMatchDetails();
|
||||
const { displaySetMatchDetails: matchDetails } = hangingProtocolService.getMatchDetails();
|
||||
const volumeLoaderScheme = 'cornerstoneStreamingImageVolume'; // Loader id which defines which volume loader to use
|
||||
|
||||
const ctDisplaySet = matchDetails.get('ctDisplaySet');
|
||||
@@ -248,9 +228,7 @@ const commandsModule = ({
|
||||
getLesionStats: ({ labelmap, segmentIndex = 1 }) => {
|
||||
const { scalarData, spacing } = labelmap;
|
||||
|
||||
const { scalarData: referencedScalarData } = cs.cache.getVolume(
|
||||
labelmap.referencedVolumeId
|
||||
);
|
||||
const { scalarData: referencedScalarData } = cs.cache.getVolume(labelmap.referencedVolumeId);
|
||||
|
||||
let segmentationMax = -Infinity;
|
||||
let segmentationMin = Infinity;
|
||||
@@ -292,9 +270,7 @@ const commandsModule = ({
|
||||
};
|
||||
},
|
||||
calculateTMTV: ({ segmentations }) => {
|
||||
const labelmaps = segmentations.map(s =>
|
||||
segmentationService.getLabelmapVolume(s.id)
|
||||
);
|
||||
const labelmaps = segmentations.map(s => segmentationService.getLabelmapVolume(s.id));
|
||||
|
||||
if (!labelmaps.length) {
|
||||
return;
|
||||
@@ -317,17 +293,14 @@ const commandsModule = ({
|
||||
createAndDownloadTMTVReport(segReport, additionalReportRows);
|
||||
},
|
||||
getTotalLesionGlycolysis: ({ segmentations }) => {
|
||||
const labelmapVolumes = segmentations.map(s =>
|
||||
segmentationService.getLabelmapVolume(s.id)
|
||||
);
|
||||
const labelmapVolumes = segmentations.map(s => segmentationService.getLabelmapVolume(s.id));
|
||||
|
||||
let mergedLabelmap;
|
||||
// merge labelmap will through an error if labels maps are not the same size
|
||||
// or same direction or ....
|
||||
try {
|
||||
mergedLabelmap = csTools.utilities.segmentation.createMergedLabelmapForIndex(
|
||||
labelmapVolumes
|
||||
);
|
||||
mergedLabelmap =
|
||||
csTools.utilities.segmentation.createMergedLabelmapForIndex(labelmapVolumes);
|
||||
} catch (e) {
|
||||
console.error('commandsModule::getTotalLesionGlycolysis', e);
|
||||
return;
|
||||
@@ -337,9 +310,7 @@ const commandsModule = ({
|
||||
const { referencedVolumeId, spacing } = labelmapVolumes[0];
|
||||
|
||||
if (!referencedVolumeId) {
|
||||
console.error(
|
||||
'commandsModule::getTotalLesionGlycolysis:No referencedVolumeId found'
|
||||
);
|
||||
console.error('commandsModule::getTotalLesionGlycolysis:No referencedVolumeId found');
|
||||
}
|
||||
|
||||
const ptVolume = cs.cache.getVolume(referencedVolumeId);
|
||||
@@ -365,14 +336,7 @@ const commandsModule = ({
|
||||
const averageSuv = suv / totalLesionVoxelCount;
|
||||
|
||||
// total Lesion Glycolysis [suv * ml]
|
||||
return (
|
||||
averageSuv *
|
||||
totalLesionVoxelCount *
|
||||
spacing[0] *
|
||||
spacing[1] *
|
||||
spacing[2] *
|
||||
1e-3
|
||||
);
|
||||
return averageSuv * totalLesionVoxelCount * spacing[0] * spacing[1] * spacing[2] * 1e-3;
|
||||
},
|
||||
setStartSliceForROIThresholdTool: () => {
|
||||
const { viewport } = _getActiveViewportsEnabledElement();
|
||||
@@ -488,9 +452,7 @@ const commandsModule = ({
|
||||
const referencedVolumeId = labelmapVolume.referencedVolumeId;
|
||||
segReport.referencedVolumeId = referencedVolumeId;
|
||||
|
||||
const referencedVolume = segmentationService.getLabelmapVolume(
|
||||
referencedVolumeId
|
||||
);
|
||||
const referencedVolume = segmentationService.getLabelmapVolume(referencedVolumeId);
|
||||
|
||||
if (!referencedVolume) {
|
||||
report[id] = segReport;
|
||||
@@ -503,10 +465,7 @@ const commandsModule = ({
|
||||
}
|
||||
|
||||
const firstImageId = referencedVolume.imageIds[0];
|
||||
const instance = OHIF.classes.MetadataProvider.get(
|
||||
'instance',
|
||||
firstImageId
|
||||
);
|
||||
const instance = OHIF.classes.MetadataProvider.get('instance', firstImageId);
|
||||
|
||||
if (!instance) {
|
||||
report[id] = segReport;
|
||||
@@ -559,9 +518,7 @@ const commandsModule = ({
|
||||
},
|
||||
});
|
||||
|
||||
viewports.push(
|
||||
cornerstoneViewportService.getCornerstoneViewport(viewportId)
|
||||
);
|
||||
viewports.push(cornerstoneViewportService.getCornerstoneViewport(viewportId));
|
||||
});
|
||||
|
||||
viewports.forEach(viewport => {
|
||||
|
||||
@@ -6,11 +6,7 @@ import { PanelPetSUV, PanelROIThresholdSegmentation } from './Panels';
|
||||
// - cancel promises when component is destroyed
|
||||
// - show errors in UI for thumbnails if promise fails
|
||||
|
||||
function getPanelModule({
|
||||
commandsManager,
|
||||
extensionManager,
|
||||
servicesManager,
|
||||
}) {
|
||||
function getPanelModule({ commandsManager, extensionManager, servicesManager }) {
|
||||
const wrappedPanelPetSuv = () => {
|
||||
return (
|
||||
<PanelPetSUV
|
||||
|
||||
@@ -12,12 +12,7 @@ const tmtvExtension = {
|
||||
* Only required property. Should be a unique value across all extensions.
|
||||
*/
|
||||
id,
|
||||
preRegistration({
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
extensionManager,
|
||||
configuration = {},
|
||||
}) {
|
||||
preRegistration({ servicesManager, commandsManager, extensionManager, configuration = {} }) {
|
||||
init({ servicesManager, commandsManager, extensionManager, configuration });
|
||||
},
|
||||
getPanelModule,
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
addTool,
|
||||
RectangleROIStartEndThresholdTool,
|
||||
} from '@cornerstonejs/tools';
|
||||
import { addTool, RectangleROIStartEndThresholdTool } from '@cornerstonejs/tools';
|
||||
import { utilities } from '@cornerstonejs/core';
|
||||
|
||||
import measurementServiceMappingsFactory from './utils/measurementServiceMappings/measurementServiceMappingsFactory';
|
||||
@@ -18,11 +15,8 @@ const CORNERSTONE_3D_TOOLS_SOURCE_VERSION = '0.1';
|
||||
* @param {Object|Array} configuration.csToolsConfig
|
||||
*/
|
||||
export default function init({ servicesManager, extensionManager }) {
|
||||
const {
|
||||
measurementService,
|
||||
displaySetService,
|
||||
cornerstoneViewportService,
|
||||
} = servicesManager.services;
|
||||
const { measurementService, displaySetService, cornerstoneViewportService } =
|
||||
servicesManager.services;
|
||||
|
||||
addTool(RectangleROIStartEndThresholdTool);
|
||||
|
||||
|
||||
@@ -41,21 +41,12 @@ function calculateSuvPeak(
|
||||
}
|
||||
|
||||
if (labelmap.scalarData.length !== referenceVolume.scalarData.length) {
|
||||
throw new Error(
|
||||
'labelmap and referenceVolume must have the same number of pixels'
|
||||
);
|
||||
throw new Error('labelmap and referenceVolume must have the same number of pixels');
|
||||
}
|
||||
|
||||
const {
|
||||
scalarData: labelmapData,
|
||||
dimensions,
|
||||
imageData: labelmapImageData,
|
||||
} = labelmap;
|
||||
const { scalarData: labelmapData, dimensions, imageData: labelmapImageData } = labelmap;
|
||||
|
||||
const {
|
||||
scalarData: referenceVolumeData,
|
||||
imageData: referenceVolumeImageData,
|
||||
} = referenceVolume;
|
||||
const { scalarData: referenceVolumeData, imageData: referenceVolumeImageData } = referenceVolume;
|
||||
|
||||
let boundsIJK;
|
||||
// Todo: using the first annotation for now
|
||||
@@ -69,10 +60,7 @@ function calculateSuvPeak(
|
||||
return ijk as Types.Point3;
|
||||
});
|
||||
|
||||
boundsIJK = utilities.boundingBox.getBoundingBoxAroundShape(
|
||||
rectangleCornersIJK,
|
||||
dimensions
|
||||
);
|
||||
boundsIJK = utilities.boundingBox.getBoundingBoxAroundShape(rectangleCornersIJK, dimensions);
|
||||
}
|
||||
|
||||
let max = 0;
|
||||
@@ -96,16 +84,9 @@ function calculateSuvPeak(
|
||||
}
|
||||
};
|
||||
|
||||
utilities.pointInShapeCallback(
|
||||
labelmapImageData,
|
||||
() => true,
|
||||
callback,
|
||||
boundsIJK
|
||||
);
|
||||
utilities.pointInShapeCallback(labelmapImageData, () => true, callback, boundsIJK);
|
||||
|
||||
const direction = labelmapImageData
|
||||
.getDirection()
|
||||
.slice(0, 3) as Types.Point3;
|
||||
const direction = labelmapImageData.getDirection().slice(0, 3) as Types.Point3;
|
||||
|
||||
/**
|
||||
* 2. Find the bottom and top of the great circle for the second sphere (1cc sphere)
|
||||
@@ -120,10 +101,7 @@ function calculateSuvPeak(
|
||||
referenceVolumeImageData.indexToWorld(maxIJK as vec3, secondaryCircleWorld);
|
||||
vec3.scaleAndAdd(bottomWorld, secondaryCircleWorld, direction, -diameter / 2);
|
||||
vec3.scaleAndAdd(topWorld, secondaryCircleWorld, direction, diameter / 2);
|
||||
const suvPeakCirclePoints = [bottomWorld, topWorld] as [
|
||||
Types.Point3,
|
||||
Types.Point3
|
||||
];
|
||||
const suvPeakCirclePoints = [bottomWorld, topWorld] as [Types.Point3, Types.Point3];
|
||||
|
||||
/**
|
||||
* 3. Find the Mean and Max of the 1cc sphere centered on the suv Max of the previous
|
||||
|
||||
@@ -11,10 +11,7 @@ import { utilities } from '@cornerstonejs/tools';
|
||||
* @param {number} segmentIndex
|
||||
* @returns {number} TMTV in ml
|
||||
*/
|
||||
function calculateTMTV(
|
||||
labelmaps: Array<Types.IImageVolume>,
|
||||
segmentIndex = 1
|
||||
): number {
|
||||
function calculateTMTV(labelmaps: Array<Types.IImageVolume>, segmentIndex = 1): number {
|
||||
const volumeId = 'mergedLabelmap';
|
||||
|
||||
const mergedLabelmap = utilities.segmentation.createMergedLabelmapForIndex(
|
||||
@@ -24,10 +21,7 @@ function calculateTMTV(
|
||||
);
|
||||
|
||||
const { imageData, spacing } = mergedLabelmap;
|
||||
const values = imageData
|
||||
.getPointData()
|
||||
.getScalars()
|
||||
.getData();
|
||||
const values = imageData.getPointData().getScalars().getData();
|
||||
|
||||
// count non-zero values inside the outputData, this would
|
||||
// consider the overlapping regions to be only counted once
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,7 +1,4 @@
|
||||
export default function createAndDownloadTMTVReport(
|
||||
segReport,
|
||||
additionalReportRows
|
||||
) {
|
||||
export default function createAndDownloadTMTVReport(segReport, additionalReportRows) {
|
||||
const firstReport = segReport[Object.keys(segReport)[0]];
|
||||
const columns = Object.keys(firstReport);
|
||||
const csv = [columns.join(',')];
|
||||
@@ -11,9 +8,7 @@ export default function createAndDownloadTMTVReport(
|
||||
columns.forEach(column => {
|
||||
// if it is array then we need to replace , with space to avoid csv parsing error
|
||||
row.push(
|
||||
Array.isArray(segmentation[column])
|
||||
? segmentation[column].join(' ')
|
||||
: segmentation[column]
|
||||
Array.isArray(segmentation[column]) ? segmentation[column].join(' ') : segmentation[column]
|
||||
);
|
||||
});
|
||||
csv.push(row.join(','));
|
||||
|
||||
@@ -98,15 +98,9 @@ function initializeDataset(annotations, metadataProvider) {
|
||||
const rtSOPInstanceUID = DicomMetaDictionary.uid();
|
||||
|
||||
// get the first annotation data
|
||||
const {
|
||||
referencedImageId: imageId,
|
||||
FrameOfReferenceUID,
|
||||
} = annotations[0].metadata;
|
||||
const { referencedImageId: imageId, FrameOfReferenceUID } = annotations[0].metadata;
|
||||
|
||||
const { studyInstanceUID } = metadataProvider.get(
|
||||
'generalSeriesModule',
|
||||
imageId
|
||||
);
|
||||
const { studyInstanceUID } = metadataProvider.get('generalSeriesModule', imageId);
|
||||
|
||||
const patientModule = getPatientModule(imageId, metadataProvider);
|
||||
const rtSeriesModule = getRTSeriesModule(imageId, metadataProvider);
|
||||
@@ -136,23 +130,11 @@ function initializeDataset(annotations, metadataProvider) {
|
||||
}
|
||||
|
||||
function getPatientModule(imageId, metadataProvider) {
|
||||
const generalSeriesModule = metadataProvider.get(
|
||||
'generalSeriesModule',
|
||||
imageId
|
||||
);
|
||||
const generalStudyModule = metadataProvider.get(
|
||||
'generalStudyModule',
|
||||
imageId
|
||||
);
|
||||
const patientStudyModule = metadataProvider.get(
|
||||
'patientStudyModule',
|
||||
imageId
|
||||
);
|
||||
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
|
||||
);
|
||||
const patientDemographicModule = metadataProvider.get('patientDemographicModule', imageId);
|
||||
|
||||
return {
|
||||
Modality: generalSeriesModule.modality,
|
||||
@@ -169,11 +151,7 @@ function getPatientModule(imageId, metadataProvider) {
|
||||
};
|
||||
}
|
||||
|
||||
function getReferencedFrameOfReferenceSequence(
|
||||
toolData,
|
||||
metadataProvider,
|
||||
dataset
|
||||
) {
|
||||
function getReferencedFrameOfReferenceSequence(toolData, metadataProvider, dataset) {
|
||||
const { referencedImageId: imageId, FrameOfReferenceUID } = toolData.metadata;
|
||||
const instance = metadataProvider.get('instance', imageId);
|
||||
const { SeriesInstanceUID } = instance;
|
||||
@@ -190,9 +168,7 @@ function getReferencedFrameOfReferenceSequence(
|
||||
RTReferencedSeriesSequence: [
|
||||
{
|
||||
SeriesInstanceUID,
|
||||
ContourImageSequence: [
|
||||
...ReferencedSeriesSequence[0].ReferencedInstanceSequence,
|
||||
],
|
||||
ContourImageSequence: [...ReferencedSeriesSequence[0].ReferencedInstanceSequence],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -209,10 +185,7 @@ function getReferencedSeriesSequence(toolData, index, metadataProvider) {
|
||||
|
||||
const ReferencedSeriesSequence = [];
|
||||
if (SeriesInstanceUID) {
|
||||
const series = DicomMetadataStore.getSeries(
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID
|
||||
);
|
||||
const series = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);
|
||||
|
||||
const ReferencedSeries = {
|
||||
SeriesInstanceUID,
|
||||
|
||||
+2
-7
@@ -20,18 +20,13 @@ class AnnotationToPointData {
|
||||
const toolClass = AnnotationToPointData.TOOL_NAMES[toolName];
|
||||
|
||||
if (!toolClass) {
|
||||
throw new Error(
|
||||
`Unknown tool type: ${toolName}, cannot convert to RTSSReport`
|
||||
);
|
||||
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
|
||||
);
|
||||
const ContourSequence = toolClass.getContourSequence(annotation, metadataProvider);
|
||||
|
||||
// Todo: random rgb color for now, options should be passed in
|
||||
const color = [
|
||||
|
||||
+1
-6
@@ -29,12 +29,7 @@ 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 orderedPoints = [...points[0], ...points[1], ...points[3], ...points[2]];
|
||||
const pointsArray = orderedPoints.flat();
|
||||
|
||||
// reduce the precision of the points to 2 decimal places
|
||||
|
||||
@@ -3,10 +3,7 @@ import * as csTools from '@cornerstonejs/tools';
|
||||
function getRoiStats(referencedVolume, annotations) {
|
||||
// roiStats
|
||||
const { imageData } = referencedVolume;
|
||||
const values = imageData
|
||||
.getPointData()
|
||||
.getScalars()
|
||||
.getData();
|
||||
const values = imageData.getPointData().getScalars().getData();
|
||||
|
||||
// Todo: add support for other strategies
|
||||
const { fn, baseValue } = _getStrategyFn('max');
|
||||
@@ -59,9 +56,10 @@ function getThresholdValues(
|
||||
};
|
||||
}
|
||||
|
||||
function _getStrategyFn(
|
||||
statistic
|
||||
): { fn: (a: number, b: number) => number; baseValue: number } {
|
||||
function _getStrategyFn(statistic): {
|
||||
fn: (a: number, b: number) => number;
|
||||
baseValue: number;
|
||||
} {
|
||||
const baseValue = -Infinity;
|
||||
const fn = (number, maxValue) => {
|
||||
if (number > maxValue) {
|
||||
|
||||
+2
-10
@@ -10,11 +10,7 @@ const RectangleROIStartEndThreshold = {
|
||||
* @param {Object} cornerstone Cornerstone event data
|
||||
* @return {Measurement} Measurement instance
|
||||
*/
|
||||
toMeasurement: (
|
||||
csToolsEventDetail,
|
||||
displaySetService,
|
||||
cornerstoneViewportService
|
||||
) => {
|
||||
toMeasurement: (csToolsEventDetail, displaySetService, cornerstoneViewportService) => {
|
||||
const { annotation, viewportId } = csToolsEventDetail;
|
||||
const { metadata, data, annotationUID } = annotation;
|
||||
|
||||
@@ -30,11 +26,7 @@ const RectangleROIStartEndThreshold = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
cornerstoneViewportService,
|
||||
viewportId
|
||||
|
||||
Reference in new issue
Block a user