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

@@ -0,0 +1,139 @@
export function generateSegmentationCSVReport(
segmentationData,
info: {
reference: {
SeriesNumber: string;
SeriesInstanceUID: string;
StudyInstanceUID: string;
SeriesDate: string;
SeriesTime: string;
SeriesDescription: string;
};
}
) {
// Initialize the rows for our CSV
const csvRows = [];
// Add segmentation-level information
csvRows.push(['Segmentation ID', segmentationData.segmentationId || '']);
csvRows.push(['Segmentation Label', segmentationData.label || '']);
csvRows.push([]);
const additionalInfo = info.reference;
// Add reference information
const referenceKeys = [
['Series Number', additionalInfo.SeriesNumber],
['Series Instance UID', additionalInfo.SeriesInstanceUID],
['Study Instance UID', additionalInfo.StudyInstanceUID],
['Series Date', additionalInfo.SeriesDate],
['Series Time', additionalInfo.SeriesTime],
['Series Description', additionalInfo.SeriesDescription],
];
referenceKeys.forEach(([key, value]) => {
if (value) {
csvRows.push([`reference ${key}`, value]);
}
});
// Add a blank row for separation
csvRows.push([]);
csvRows.push(['Segments Statistics']);
// Add segment information in columns
if (segmentationData.segments) {
// First row: Segment headers
const segmentHeaderRow = ['Label'];
for (const segmentId in segmentationData.segments) {
const segment = segmentationData.segments[segmentId];
segmentHeaderRow.push(`${segment.label || ''}`);
}
csvRows.push(segmentHeaderRow);
// Add segment properties
csvRows.push([
'Segment Index',
...Object.values(segmentationData.segments).map(s => s.segmentIndex || ''),
]);
csvRows.push([
'Locked',
...Object.values(segmentationData.segments).map(s => (s.locked ? 'Yes' : 'No')),
]);
csvRows.push([
'Active',
...Object.values(segmentationData.segments).map(s => (s.active ? 'Yes' : 'No')),
]);
// Add segment statistics
// First, collect all unique statistics across all segments
const allStats = new Set();
for (const segment of Object.values(segmentationData.segments)) {
if (segment.cachedStats && segment.cachedStats.namedStats) {
for (const statKey in segment.cachedStats.namedStats) {
const stat = segment.cachedStats.namedStats[statKey];
const statLabel = stat.label || stat.name;
const statUnit = stat.unit ? ` (${stat.unit})` : '';
allStats.add(`${statLabel}${statUnit}`);
}
}
}
// Then create a row for each statistic
for (const statName of allStats) {
const statRow = [statName];
for (const segment of Object.values(segmentationData.segments)) {
let statValue = '';
if (segment.cachedStats && segment.cachedStats.namedStats) {
for (const statKey in segment.cachedStats.namedStats) {
const stat = segment.cachedStats.namedStats[statKey];
const currentStatName = `${stat.label || stat.name}${stat.unit ? ` (${stat.unit})` : ''}`;
if (currentStatName === statName) {
statValue = stat.value !== undefined ? stat.value : '';
break;
}
}
}
statRow.push(statValue);
}
csvRows.push(statRow);
}
}
// Convert to CSV string
let csvString = '';
for (const row of csvRows) {
const formattedRow = row.map(cell => {
// Handle values that need to be quoted (contain commas, quotes, or newlines)
const cellValue = cell !== undefined && cell !== null ? cell.toString() : '';
if (cellValue.includes(',') || cellValue.includes('"') || cellValue.includes('\n')) {
// Escape quotes and wrap in quotes
return '"' + cellValue.replace(/"/g, '""') + '"';
}
return cellValue;
});
csvString += formattedRow.join(',') + '\n';
}
// Create a download link and trigger the download
const blob = new Blob([csvString], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute(
'download',
`${segmentationData.label || 'Segmentation'}_Report_${new Date().toISOString().split('T')[0]}.csv`
);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}