feat(segmentation): segment statistics, labelmap interpolation and segment bidirectional (#4865)

This commit is contained in:
Alireza authored and GitHub committed 2025-03-17 22:34:34 -04:00
1 parent 694f3e9611
commit ec79b5523e
73 files changed
+3603 -1563

No files matched your search

@@ -1,20 +1,26 @@
import React, { ReactNode } from 'react';
import React, { ReactNode, useState, Children, isValidElement } from 'react';
import { useTranslation } from 'react-i18next';
import { PanelSection } from '../PanelSection';
import { SegmentationTableProvider, SegmentationTableContext } from './SegmentationTableContext';
import {
SegmentationTableProvider,
SegmentationTableContextType,
ViewportSegmentationInfo,
} from './contexts';
import { SegmentationSegments } from './SegmentationSegments';
import { SegmentStatistics } from './SegmentStatistics';
import { SegmentationTableConfig } from './SegmentationTableConfig';
import { AddSegmentRow } from './AddSegmentRow';
import { AddSegmentationRow } from './AddSegmentationRow';
import { SegmentationSelectorHeader } from './SegmentationSelectorHeader';
import { SegmentationHeader } from './SegmentationHeader';
import { SegmentationCollapsed } from './SegmentationCollapsed';
import { SegmentationExpanded } from './SegmentationExpanded';
import Icons from '../Icons';
interface SegmentationTableProps extends SegmentationTableContext {
disabled?: boolean;
// Only include props that aren't part of the context
interface SegmentationTableProps extends Omit<SegmentationTableContextType, 'setShowConfig'> {
title?: string;
children?: ReactNode;
setShowConfig?: (value: boolean) => void;
}
interface SegmentationTableComponent extends React.FC<SegmentationTableProps> {
@@ -22,55 +28,118 @@ interface SegmentationTableComponent extends React.FC<SegmentationTableProps> {
Config: typeof SegmentationTableConfig;
AddSegmentRow: typeof AddSegmentRow;
AddSegmentationRow: typeof AddSegmentationRow;
SelectorHeader: typeof SegmentationSelectorHeader;
Header: typeof SegmentationHeader;
Collapsed: typeof SegmentationCollapsed;
Expanded: typeof SegmentationExpanded;
SegmentStatistics: typeof SegmentStatistics;
}
export const SegmentationTable: SegmentationTableComponent = (props: SegmentationTableProps) => {
export const SegmentationTableRoot = (props: SegmentationTableProps) => {
const { t } = useTranslation('SegmentationTable');
const { data = [], mode, title, disableEditing, disabled, children, ...contextProps } = props;
const {
data = [],
mode,
title,
disableEditing = false,
disabled = false,
children,
showConfig: externalShowConfig,
...contextProps
} = props;
const [internalShowConfig, setInternalShowConfig] = useState(false);
const showConfig = externalShowConfig !== undefined ? externalShowConfig : internalShowConfig;
// Find the active segmentation info based on which representation is active
const activeSegmentationInfo = data.find(info => info.representation?.active);
const activeSegmentationId = activeSegmentationInfo?.segmentation?.segmentationId;
const activeRepresentation = activeSegmentationInfo?.representation;
const activeSegmentation = activeSegmentationInfo?.segmentation;
const { fillAlpha, fillAlphaInactive, outlineWidth, renderFill, renderOutline } =
activeRepresentation?.styles ?? {};
// Get the active segmentation ID
const activeSegmentationId =
props.activeSegmentationId || activeSegmentationInfo?.segmentation?.segmentationId;
const activeRepresentation = props.activeRepresentation || activeSegmentationInfo?.representation;
const activeSegmentation = props.activeSegmentation || activeSegmentationInfo?.segmentation;
// Extract style properties or use defaults
const {
fillAlpha = props.fillAlpha || 0.5,
fillAlphaInactive = props.fillAlphaInactive || 0.2,
outlineWidth = props.outlineWidth || 1,
renderFill = props.renderFill !== undefined ? props.renderFill : true,
renderOutline = props.renderOutline !== undefined ? props.renderOutline : true,
} = activeRepresentation?.styles ?? {};
// Check if SegmentationTableConfig is present in children
const hasConfigComponent = Children.toArray(children).some(
child => isValidElement(child) && child.type === SegmentationTableConfig
);
// Process children to conditionally render the config component based on showConfig
const processedChildren = Children.map(children, child => {
if (isValidElement(child) && child.type === SegmentationTableConfig) {
// Only render the Config component if showConfig is true
return showConfig ? child : null;
}
return child;
});
const toggleShowConfig = () => {
if (props.setShowConfig) {
props.setShowConfig(!showConfig);
} else {
setInternalShowConfig(!internalShowConfig);
}
};
return (
<SegmentationTableProvider
data={data}
mode={mode}
disabled={disabled}
disableEditing={disableEditing}
fillAlpha={fillAlpha}
fillAlphaInactive={fillAlphaInactive}
outlineWidth={outlineWidth}
renderFill={renderFill}
renderOutline={renderOutline}
activeSegmentationId={activeSegmentationId}
activeSegmentation={activeSegmentation}
activeRepresentation={activeRepresentation}
{...contextProps}
value={{
data,
mode,
showConfig,
disabled,
disableEditing,
fillAlpha,
fillAlphaInactive,
outlineWidth,
renderFill,
renderOutline,
activeSegmentationId,
activeSegmentation,
activeRepresentation,
...contextProps,
setShowConfig: toggleShowConfig,
}}
>
<PanelSection defaultOpen={true}>
<PanelSection.Header>
<PanelSection.Header className="flex items-center justify-between">
<span>{t(title)}</span>
{hasConfigComponent && (
<div className="ml-auto mr-2">
<Icons.Settings
className="text-primary-active h-4 w-4"
onClick={e => {
e.stopPropagation();
toggleShowConfig();
}}
/>
</div>
)}
</PanelSection.Header>
<PanelSection.Content>{children}</PanelSection.Content>
<PanelSection.Content>{processedChildren}</PanelSection.Content>
</PanelSection>
</SegmentationTableProvider>
);
};
SegmentationTable.Segments = SegmentationSegments;
SegmentationTable.Config = SegmentationTableConfig;
SegmentationTable.AddSegmentRow = AddSegmentRow;
SegmentationTable.AddSegmentationRow = AddSegmentationRow;
SegmentationTable.SelectorHeader = SegmentationSelectorHeader;
SegmentationTable.Header = SegmentationHeader;
SegmentationTable.Collapsed = SegmentationCollapsed;
SegmentationTable.Expanded = SegmentationExpanded;
const SegmentationTable = Object.assign(SegmentationTableRoot, {
Segments: SegmentationSegments,
Config: SegmentationTableConfig,
AddSegmentRow: AddSegmentRow,
AddSegmentationRow: AddSegmentationRow,
Collapsed: SegmentationCollapsed,
Expanded: SegmentationExpanded,
SegmentStatistics: SegmentStatistics,
Header: SegmentationHeader,
}) as SegmentationTableComponent;
export { SegmentationTable };