From db58cb5dde38734b076b8d0862d54f88344e7874 Mon Sep 17 00:00:00 2001 From: sedghi Date: Tue, 4 Mar 2025 11:40:13 -0500 Subject: [PATCH 1/4] fix examples --- .../examples/labelmapInterpolation/index.ts | 431 ++++++++++-------- .../examples/labelmapStatistics/index.ts | 39 +- 2 files changed, 250 insertions(+), 220 deletions(-) diff --git a/packages/labelmap-interpolation/examples/labelmapInterpolation/index.ts b/packages/labelmap-interpolation/examples/labelmapInterpolation/index.ts index 24307a33c..a660113cc 100644 --- a/packages/labelmap-interpolation/examples/labelmapInterpolation/index.ts +++ b/packages/labelmap-interpolation/examples/labelmapInterpolation/index.ts @@ -1,230 +1,250 @@ +import type { Types } from '@cornerstonejs/core'; import { RenderingEngine, Enums, - imageLoader, - eventTarget, + setVolumesForViewports, + volumeLoader, } from '@cornerstonejs/core'; -import * as cornerstoneTools from '@cornerstonejs/tools'; import { - createImageIdsAndCacheMetaData, initDemo, + createImageIdsAndCacheMetaData, setTitleAndDescription, - addBrushSizeSlider, + addDropdownToToolbar, + addSliderToToolbar, + setCtTransferFunctionForVolumeActor, + addButtonToToolbar, + addManipulationBindings, } from '../../../../utils/demo/helpers'; +import * as cornerstoneTools from '@cornerstonejs/tools'; +import * as labelmapInterpolation from '@cornerstonejs/labelmap-interpolation'; // This is for debugging purposes -console.debug( +console.warn( 'Click on index.ts to open source code for this example --------->' ); const { ToolGroupManager, - ZoomTool, - StackScrollTool, Enums: csToolsEnums, + segmentation, RectangleScissorsTool, + SphereScissorsTool, CircleScissorsTool, BrushTool, PaintFillTool, - PanTool, - segmentation, utilities: cstUtils, } = cornerstoneTools; -const { MouseBindings, KeyboardBindings, Events } = csToolsEnums; +const { MouseBindings } = csToolsEnums; const { ViewportType } = Enums; -const { segmentation: segmentationUtils, roundNumber } = cstUtils; +const { segmentation: segmentationUtils } = cstUtils; // Define a unique id for the volume -let renderingEngine; -const renderingEngineId = 'myRenderingEngine'; -const viewportId = 'STACK_VIEWPORT'; -const toolGroupId = 'TOOL_GROUP_ID'; +const volumeName = 'CT_VOLUME_ID'; // Id of the volume less loader prefix +const volumeLoaderScheme = 'cornerstoneStreamingImageVolume'; // Loader id which defines which volume loader to use +const volumeId = `${volumeLoaderScheme}:${volumeName}`; // VolumeId with loader id + volume id +const segmentationId = 'MY_SEGMENTATION_ID'; +const toolGroupId = 'MY_TOOLGROUP_ID'; // ======== Set up page ======== // setTitleAndDescription( - 'Stack Segmentation Statistics', - 'Here we demonstrate how to calculate statistics for a stack segmentation.' + 'Labelmap Interpolation', + 'Here we demonstrate interpolation between slices for labelmaps' ); const size = '500px'; const content = document.getElementById('content'); - -const statsGrid = document.createElement('div'); -statsGrid.style.display = 'flex'; -statsGrid.style.flexDirection = 'row'; -statsGrid.style.fontSize = 'smaller'; - -const statsIds = ['segment1', 'segment2', 'segmentCombined']; -const statsStyle = { - width: '20em', - height: '10em', -}; - -for (const statsId of statsIds) { - const statsDiv = document.createElement('div'); - statsDiv.id = statsId; - statsDiv.innerText = statsId; - Object.assign(statsDiv.style, statsStyle); - statsGrid.appendChild(statsDiv); -} - -content.appendChild(statsGrid); - const viewportGrid = document.createElement('div'); + +viewportGrid.style.display = 'flex'; viewportGrid.style.display = 'flex'; viewportGrid.style.flexDirection = 'row'; -const element = document.createElement('div'); -element.style.width = size; -element.style.height = size; -element.oncontextmenu = () => false; +const element1 = document.createElement('div'); +const element2 = document.createElement('div'); +const element3 = document.createElement('div'); +element1.style.width = size; +element1.style.height = size; +element2.style.width = size; +element2.style.height = size; +element3.style.width = size; +element3.style.height = size; + +// Disable right click context menu so we can have right click tools +element1.oncontextmenu = (e) => e.preventDefault(); +element2.oncontextmenu = (e) => e.preventDefault(); +element3.oncontextmenu = (e) => e.preventDefault(); + +viewportGrid.appendChild(element1); +viewportGrid.appendChild(element2); +viewportGrid.appendChild(element3); -viewportGrid.appendChild(element); content.appendChild(viewportGrid); const instructions = document.createElement('p'); instructions.innerText = ` - Left Click: Use selected Segmentation Tool. - Middle Click: Pan - Right Click: Zoom - Mouse wheel: Scroll Stack + Use the labelmap tools in the normal way. Note preview is turned off for those + tools to simplify initial segment creation. +
Segments are interpolated BETWEEN slices, so you need to create two or more + segments of the same segment index on slices in a viewport separated by at least + one empty segment. + Use "Extended Interpolation" button to interpolate segments which don't + overlap (assuming the segments were drawn on the same slice). + Use "Overlapping Interpolation" button to interpolate overlapping segments - that is, the segment must + overlap if drawn on the same slice to interpolate between them. This is a good choice + for multiple segments. + Accept the interpolation by hitting enter, or use the "Reject Preview/Interpolation" button. `; content.append(instructions); -// ============================= // +const interpolationTools = new Map(); -function displayStat(stat) { - if (!stat) { - return; - } - return `${stat.label || stat.name}: ${roundNumber(stat.value)} ${ - stat.unit ? stat.unit : '' - }`; -} +const configuration = {}; -async function calculateStatistics(id, indices) { - const viewport = renderingEngine.getViewport(viewportId); - const stats = await segmentationUtils.getStatistics({ - segmentationId: 'SEGMENTATION_ID', - segmentIndices: indices, - viewportId: viewport.id, - }); +interpolationTools.set('CircularBrush', { + baseTool: BrushTool.toolName, + configuration: { + ...configuration, + activeStrategy: 'FILL_INSIDE_CIRCLE', + }, +}); - if (!stats) { - return; - } - const items = [`Statistics on ${indices.join(', ')}`]; - stats.count.label = 'Voxels'; - - items.push( - displayStat(stats.volume), - displayStat(stats.count), - displayStat(stats.mean), - displayStat(stats.max), - displayStat(stats.min), - displayStat(stats.peakValue) - ); - const statsDiv = document.getElementById(id); - statsDiv.innerHTML = items.map((span) => `${span}
\n`).join('\n'); -} - -let timeoutId; +const optionsValues = [ + ...interpolationTools.keys(), + RectangleScissorsTool.toolName, + CircleScissorsTool.toolName, + SphereScissorsTool.toolName, + PaintFillTool.toolName, +]; -function segmentationModifiedCallback(evt) { - const { detail } = evt; - if (!detail || !detail.segmentIndex || detail.segmentIndex === 255) { - return; - } +// ============================= // +addDropdownToToolbar({ + options: { values: optionsValues, defaultValue: BrushTool.toolName }, + onSelectedValueChange: (nameAsStringOrNumber) => { + const name = String(nameAsStringOrNumber); + const toolGroup = ToolGroupManager.getToolGroup(toolGroupId); + + // Set the currently active tool disabled + const toolName = toolGroup.getActivePrimaryMouseButtonTool(); + + if (toolName) { + toolGroup.setToolDisabled(toolName); + } + + toolGroup.setToolActive(name, { + bindings: [{ mouseButton: MouseBindings.Primary }], + }); + }, +}); + +addSliderToToolbar({ + title: 'Brush Size', + range: [5, 100], + defaultValue: 25, + onSelectedValueChange: (valueAsStringOrNumber) => { + const value = Number(valueAsStringOrNumber); + segmentationUtils.setBrushSizeForToolGroup(toolGroupId, value); + }, +}); - const statsId = detail.segmentIndex === 1 ? statsIds[0] : statsIds[1]; +// ============================= // +addDropdownToToolbar({ + options: { values: ['1', '2', '3'], defaultValue: '1' }, + labelText: 'Segment', + onSelectedValueChange: (segmentIndex) => { + segmentation.segmentIndex.setActiveSegmentIndex( + segmentationId, + Number(segmentIndex) + ); + }, +}); + +addButtonToToolbar({ + title: 'Run Extended Interpolation', + onClick: () => { + const segmentIndex = + segmentation.segmentIndex.getActiveSegmentIndex(segmentationId); + labelmapInterpolation.interpolate({ + segmentationId, + segmentIndex: Number(segmentIndex), + }); + }, +}); - const debounced = () => { - calculateStatistics(statsId, [detail.segmentIndex]); - // Also update combined stats - calculateStatistics(statsIds[2], [1, 2]); - }; +// ============================= // - if (timeoutId) { - window.clearTimeout(timeoutId); - } +async function addSegmentationsToState() { + // Create a segmentation of the same resolution as the source data + await volumeLoader.createAndCacheDerivedLabelmapVolume(volumeId, { + volumeId: segmentationId, + }); - timeoutId = window.setTimeout(debounced, 1000); + // Add the segmentations to state + segmentation.addSegmentations([ + { + segmentationId, + representation: { + // The type of segmentation + type: csToolsEnums.SegmentationRepresentations.Labelmap, + // The actual segmentation data, in the case of labelmap this is a + // reference to the source volume of the segmentation. + data: { + volumeId: segmentationId, + }, + }, + }, + ]); } -// ============================= // +/** + * Runs the demo + */ +async function run() { + // Init Cornerstone and related libraries + await initDemo(); -function setupTools() { // Add tools to Cornerstone3D - cornerstoneTools.addTool(PanTool); - cornerstoneTools.addTool(ZoomTool); - cornerstoneTools.addTool(StackScrollTool); cornerstoneTools.addTool(RectangleScissorsTool); cornerstoneTools.addTool(CircleScissorsTool); + cornerstoneTools.addTool(SphereScissorsTool); cornerstoneTools.addTool(PaintFillTool); cornerstoneTools.addTool(BrushTool); - // Define a tool group + // Define tool groups to add the segmentation display tool to const toolGroup = ToolGroupManager.createToolGroup(toolGroupId); - // Add tools to the group - toolGroup.addTool(PanTool.toolName); - toolGroup.addTool(ZoomTool.toolName); - toolGroup.addTool(StackScrollTool.toolName); + // Manipulation Tools + addManipulationBindings(toolGroup); + + // Segmentation Tools toolGroup.addTool(RectangleScissorsTool.toolName); toolGroup.addTool(CircleScissorsTool.toolName); + toolGroup.addTool(SphereScissorsTool.toolName); toolGroup.addTool(PaintFillTool.toolName); toolGroup.addTool(BrushTool.toolName); - // Set tool modes - toolGroup.setToolActive(BrushTool.toolName, { - bindings: [{ mouseButton: MouseBindings.Primary }], - }); - - toolGroup.setToolActive(PanTool.toolName, { - bindings: [ - { - mouseButton: MouseBindings.Auxiliary, - }, - { - mouseButton: MouseBindings.Primary, - modifierKey: KeyboardBindings.Ctrl, - }, - ], - }); - - toolGroup.setToolActive(ZoomTool.toolName, { - bindings: [ - { - mouseButton: MouseBindings.Secondary, - }, - { - mouseButton: MouseBindings.Primary, - modifierKey: KeyboardBindings.Shift, - }, - ], - }); + for (const [toolName, config] of interpolationTools.entries()) { + if (config.baseTool) { + toolGroup.addToolInstance( + toolName, + config.baseTool, + config.configuration + ); + } else { + toolGroup.addTool(toolName, config.configuration); + } + if (config.passive) { + // This can be applied during add/remove contours + toolGroup.setToolPassive(toolName); + } + } - toolGroup.setToolActive(StackScrollTool.toolName, { - bindings: [{ mouseButton: MouseBindings.Wheel }], + toolGroup.setToolActive(interpolationTools.keys().next().value, { + bindings: [{ mouseButton: MouseBindings.Primary }], }); - return toolGroup; -} - -// ============================= // - -/** - * Runs the demo - */ -async function run() { - // Init Cornerstone and related libraries - await initDemo(); - - const toolGroup = setupTools(); - - // Get Cornerstone imageIds and fetch metadata into RAM + // Get Cornerstone imageIds for the source data and fetch metadata into RAM const imageIds = await createImageIdsAndCacheMetaData({ StudyInstanceUID: '1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463', @@ -233,66 +253,77 @@ async function run() { wadoRsRoot: 'https://d14fa38qiwhyfd.cloudfront.net/dicomweb', }); - // Create a stack of images - const imageIdsArray = imageIds.slice(0, 10); - // Create segmentation images for the stack - const segImages = await imageLoader.createAndCacheDerivedLabelmapImages( - imageIdsArray - ); - - // Instantiate a rendering engine - renderingEngine = new RenderingEngine(renderingEngineId); - - // Create the viewport - const viewportInput = { - viewportId, - type: ViewportType.STACK, - element, - }; + // Define a volume in memory + const volume = await volumeLoader.createAndCacheVolume(volumeId, { + imageIds, + }); - renderingEngine.setViewports([viewportInput]); + // Add some segmentations based on the source data volume + await addSegmentationsToState(); - // Set the stack of images - const viewport = renderingEngine.getViewport(viewportId); - await viewport.setStack(imageIdsArray, 0); + // Instantiate a rendering engine + const renderingEngineId = 'myRenderingEngine'; + const renderingEngine = new RenderingEngine(renderingEngineId); - // Add the viewport to the toolgroup - toolGroup.addViewport(viewportId, renderingEngineId); + // Create the viewports + const viewportId1 = 'CT_AXIAL'; + const viewportId2 = 'CT_SAGITTAL'; + const viewportId3 = 'CT_CORONAL'; - // Add segmentation - segmentation.addSegmentations([ + const viewportInputArray = [ { - segmentationId: 'SEGMENTATION_ID', - representation: { - type: csToolsEnums.SegmentationRepresentations.Labelmap, - data: { - imageIds: segImages.map((it) => it.imageId), - }, + viewportId: viewportId1, + type: ViewportType.ORTHOGRAPHIC, + element: element1, + defaultOptions: { + orientation: Enums.OrientationAxis.AXIAL, + background: [0, 0, 0], }, }, - ]); - - // Add the segmentation representation to the viewport - await segmentation.addSegmentationRepresentations(viewportId, [ { - segmentationId: 'SEGMENTATION_ID', - type: csToolsEnums.SegmentationRepresentations.Labelmap, + viewportId: viewportId2, + type: ViewportType.ORTHOGRAPHIC, + element: element2, + defaultOptions: { + orientation: Enums.OrientationAxis.SAGITTAL, + background: [0, 0, 0], + }, }, - ]); + { + viewportId: viewportId3, + type: ViewportType.ORTHOGRAPHIC, + element: element3, + defaultOptions: { + orientation: Enums.OrientationAxis.CORONAL, + background: [0, 0, 0], + }, + }, + ]; - // Add brush size slider - addBrushSizeSlider({ - toolGroupId, - }); + renderingEngine.setViewports(viewportInputArray); + + toolGroup.addViewport(viewportId1, renderingEngineId); + toolGroup.addViewport(viewportId2, renderingEngineId); + toolGroup.addViewport(viewportId3, renderingEngineId); - cornerstoneTools.utilities.stackContextPrefetch.enable(element); + // Set the volume to load + volume.load(); - // Add segmentation modified callback - eventTarget.addEventListener( - Events.SEGMENTATION_DATA_MODIFIED, - segmentationModifiedCallback + // Set volumes on the viewports + await setVolumesForViewports( + renderingEngine, + [{ volumeId, callback: setCtTransferFunctionForVolumeActor }], + [viewportId1, viewportId2, viewportId3] ); + // Add the segmentation representation to the toolgroup + const segMap = { + [viewportId1]: [{ segmentationId }], + [viewportId2]: [{ segmentationId }], + [viewportId3]: [{ segmentationId }], + }; + await segmentation.addLabelmapRepresentationToViewportMap(segMap); + // Render the image renderingEngine.render(); } diff --git a/packages/tools/examples/labelmapStatistics/index.ts b/packages/tools/examples/labelmapStatistics/index.ts index 5b8f9d9da..e0735788a 100644 --- a/packages/tools/examples/labelmapStatistics/index.ts +++ b/packages/tools/examples/labelmapStatistics/index.ts @@ -225,31 +225,31 @@ async function run() { const toolGroup = setupTools(); - // Get Cornerstone imageIds and fetch metadata into RAM - // const imageIds = await createImageIdsAndCacheMetaData({ - // StudyInstanceUID: - // '1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463', - // SeriesInstanceUID: - // '1.3.6.1.4.1.14519.5.2.1.7009.2403.226151125820845824875394858561', - // wadoRsRoot: 'https://d14fa38qiwhyfd.cloudfront.net/dicomweb', - // }); // Get Cornerstone imageIds and fetch metadata into RAM const imageIds = await createImageIdsAndCacheMetaData({ StudyInstanceUID: - '1.3.6.1.4.1.14519.5.2.1.1188.2803.137585363493444318569098508293', - SeriesInstanceUID: - '1.3.6.1.4.1.14519.5.2.1.1188.2803.699272945123913604672897602509', - SOPInstanceUID: - '1.3.6.1.4.1.14519.5.2.1.1188.2803.295285318555680716246271899544', - wadoRsRoot: 'https://d14fa38qiwhyfd.cloudfront.net/dicomweb', - }); - const imageIds2 = await createImageIdsAndCacheMetaData({ - StudyInstanceUID: '1.2.840.113663.1500.1.248223208.1.1.20110323.105903.687', + '1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463', SeriesInstanceUID: - '1.2.840.113663.1500.1.248223208.2.1.20110323.105903.687', - SOPInstanceUID: '1.2.840.113663.1500.1.248223208.3.10.20110323.110423.875', + '1.3.6.1.4.1.14519.5.2.1.7009.2403.226151125820845824875394858561', wadoRsRoot: 'https://d14fa38qiwhyfd.cloudfront.net/dicomweb', }); + // Get Cornerstone imageIds and fetch metadata into RAM + // const imageIds = await createImageIdsAndCacheMetaData({ + // StudyInstanceUID: + // '1.3.6.1.4.1.14519.5.2.1.1188.2803.137585363493444318569098508293', + // SeriesInstanceUID: + // '1.3.6.1.4.1.14519.5.2.1.1188.2803.699272945123913604672897602509', + // SOPInstanceUID: + // '1.3.6.1.4.1.14519.5.2.1.1188.2803.295285318555680716246271899544', + // wadoRsRoot: 'https://d14fa38qiwhyfd.cloudfront.net/dicomweb', + // }); + // const imageIds2 = await createImageIdsAndCacheMetaData({ + // StudyInstanceUID: '1.2.840.113663.1500.1.248223208.1.1.20110323.105903.687', + // SeriesInstanceUID: + // '1.2.840.113663.1500.1.248223208.2.1.20110323.105903.687', + // SOPInstanceUID: '1.2.840.113663.1500.1.248223208.3.10.20110323.110423.875', + // wadoRsRoot: 'https://d14fa38qiwhyfd.cloudfront.net/dicomweb', + // }); // Create a stack of images const imageIdsArray = imageIds.slice(0, 10); @@ -270,7 +270,6 @@ async function run() { renderingEngine.setViewports([viewportInput]); - // Set the stack of images const viewport = renderingEngine.getViewport(viewportId); await viewport.setStack(imageIdsArray, 0); From e2514ffc6b66c26149a1b766ea96d450c772effb Mon Sep 17 00:00:00 2001 From: sedghi Date: Tue, 4 Mar 2025 15:29:24 -0500 Subject: [PATCH 2/4] feat(segmentation): Add flexible segment statistics calculation with individual and collective modes This commit introduces a more flexible approach to calculating segmentation statistics by: - Adding a new SegmentStatsCalculator to manage segment-specific statistics - Supporting both 'individual' and 'collective' computation modes - Refactoring VolumetricCalculator and BasicStatsCalculator to support more dynamic statistical analysis - Updating segmentation statistics worker to use the new calculation method - Improving example code to demonstrate new statistics calculation features --- package.json | 4 +- .../examples/labelmapStatistics/index.ts | 91 +++-- .../math/basic/BasicStatsCalculator.ts | 368 +++++++++++------- .../src/utilities/math/basic/Calculator.ts | 18 +- .../segmentation/SegmentStatsCalculator.ts | 90 +++++ .../segmentation/VolumetricCalculator.ts | 227 ++++++++--- .../utilities/segmentation/getStatistics.ts | 81 +++- .../tools/src/utilities/segmentation/index.ts | 2 + packages/tools/src/workers/computeWorker.js | 33 +- utils/demo/helpers/initDemo.ts | 2 +- yarn.lock | 148 ++++--- 11 files changed, 716 insertions(+), 348 deletions(-) create mode 100644 packages/tools/src/utilities/segmentation/SegmentStatsCalculator.ts diff --git a/package.json b/package.json index c02a47d5f..97a08d860 100644 --- a/package.json +++ b/package.json @@ -71,8 +71,8 @@ "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^15.0.2", "@rollup/plugin-typescript": "^11.1.6", - "@rspack/cli": "^1.2.2", - "@rspack/core": "^1.2.2", + "@rspack/cli": "^1.2.7", + "@rspack/core": "^1.2.7", "@types/dom-webcodecs": "^0.1.11", "@types/emscripten": "^1.39.6", "@types/jasmine": "^4.3.1", diff --git a/packages/tools/examples/labelmapStatistics/index.ts b/packages/tools/examples/labelmapStatistics/index.ts index e0735788a..6027b907e 100644 --- a/packages/tools/examples/labelmapStatistics/index.ts +++ b/packages/tools/examples/labelmapStatistics/index.ts @@ -8,11 +8,11 @@ import * as cornerstoneTools from '@cornerstonejs/tools'; import { createImageIdsAndCacheMetaData, initDemo, - addDropdownToToolbar, setTitleAndDescription, - addButtonToToolbar, addBrushSizeSlider, + addSegmentIndexDropdown, } from '../../../../utils/demo/helpers'; +import addButtonToToolbar from '../../../../utils/demo/helpers/addButtonToToolbar'; // This is for debugging purposes console.debug( @@ -73,6 +73,16 @@ for (const statsId of statsIds) { content.appendChild(statsGrid); +// Add calculate button +addButtonToToolbar({ + title: 'Calculate Statistics', + onClick: () => { + // Get the selected mode from the dropdown + calculateStatistics([1, 2], 'individual'); + calculateStatistics([1, 2], 'collective'); + }, +}); + const viewportGrid = document.createElement('div'); viewportGrid.style.display = 'flex'; viewportGrid.style.flexDirection = 'row'; @@ -106,32 +116,59 @@ function displayStat(stat) { }`; } -async function calculateStatistics(id, indices) { - const viewport = renderingEngine.getViewport(viewportId); +async function calculateStatistics(indices, mode) { const stats = await segmentationUtils.getStatistics({ segmentationId: 'SEGMENTATION_ID', segmentIndices: indices, + mode, }); if (!stats) { return; } - const items = [`Statistics on ${indices.join(', ')}`]; - stats.count.label = 'Voxels'; - - items.push( - displayStat(stats.volume), - displayStat(stats.count), - displayStat(stats.mean), - displayStat(stats.max), - displayStat(stats.min), - displayStat(stats.peakValue) - ); - const statsDiv = document.getElementById(id); - statsDiv.innerHTML = items.map((span) => `${span}
\n`).join('\n'); -} -let timeoutId; + if (mode === 'individual') { + // Handle individual mode where stats is an object with segment indices as keys + const segmentStats = stats as { [segmentIndex: number]: any }; + + for (const segmentIndex of indices) { + if (segmentStats[segmentIndex]) { + const segmentStat = segmentStats[segmentIndex]; + segmentStat.count.label = 'Voxels'; + const items = [`Statistics on segment ${segmentIndex}`]; + + items.push( + displayStat(segmentStat.volume), + displayStat(segmentStat.count), + displayStat(segmentStat.mean), + displayStat(segmentStat.max), + displayStat(segmentStat.min), + displayStat(segmentStat.peakValue) + ); + + const statsDiv = document.getElementById(`segment${segmentIndex}`); + statsDiv.innerHTML = items.map((span) => `${span}
\n`).join('\n'); + } + } + } else { + const items = [`Statistics on ${indices.join(', ')}`]; + // Handle collective mode where stats is a NamedStatistics object + const namedStats = stats as any; + namedStats.count.label = 'Voxels'; + + items.push( + displayStat(namedStats.volume), + displayStat(namedStats.count), + displayStat(namedStats.mean), + displayStat(namedStats.max), + displayStat(namedStats.min), + displayStat(namedStats.peakValue) + ); + + const statsDiv = document.getElementById('segmentCombined'); + statsDiv.innerHTML = items.map((span) => `${span}
\n`).join('\n'); + } +} function segmentationModifiedCallback(evt) { const { detail } = evt; @@ -139,19 +176,7 @@ function segmentationModifiedCallback(evt) { return; } - const statsId = detail.segmentIndex === 1 ? statsIds[0] : statsIds[1]; - - const debounced = () => { - calculateStatistics(statsId, [detail.segmentIndex]); - // Also update combined stats - calculateStatistics(statsIds[2], [1, 2]); - }; - - if (timeoutId) { - window.clearTimeout(timeoutId); - } - - timeoutId = window.setTimeout(debounced, 1000); + // No longer using setTimeout - statistics will be calculated on button click } // ============================= // @@ -302,6 +327,8 @@ async function run() { toolGroupId, }); + addSegmentIndexDropdown('SEGMENTATION_ID', [1, 2]); + cornerstoneTools.utilities.stackContextPrefetch.enable(element); // Add segmentation modified callback diff --git a/packages/tools/src/utilities/math/basic/BasicStatsCalculator.ts b/packages/tools/src/utilities/math/basic/BasicStatsCalculator.ts index 460d405c3..6670766b4 100644 --- a/packages/tools/src/utilities/math/basic/BasicStatsCalculator.ts +++ b/packages/tools/src/utilities/math/basic/BasicStatsCalculator.ts @@ -1,168 +1,240 @@ import { utilities } from '@cornerstonejs/core'; import type { NamedStatistics } from '../../../types'; -import Calculator from './Calculator'; +import { Calculator, InstanceCalculator } from './Calculator'; +import type { Types } from '@cornerstonejs/core'; const { PointsManager } = utilities; -export default class BasicStatsCalculator extends Calculator { - private static max = [-Infinity]; - private static min = [Infinity]; - private static sum = [0]; - private static count = 0; - private static maxIJK = null; - private static maxLPS = null; - private static minIJK = null; - private static minLPS = null; - - // Values for Welford's algorithm - private static runMean = [0]; - private static m2 = [0]; - - // Collect the points to be returned - private static pointsInShape = PointsManager.create3(1024); - - public static statsInit(options: { storePointData: boolean }) { - if (!options.storePointData) { - BasicStatsCalculator.pointsInShape = null; +// Define an interface for the internal state used by the basic stats calculators +interface BasicStatsState { + max: number[]; + min: number[]; + sum: number[]; + count: number; + maxIJK: Types.Point3 | null; + maxLPS: Types.Point3 | null; + minIJK: Types.Point3 | null; + minLPS: Types.Point3 | null; + runMean: number[]; + m2: number[]; + pointsInShape: Types.IPointsManager | null; +} + +// Helper function to create a new state +function createBasicStatsState(storePointData: boolean): BasicStatsState { + return { + max: [-Infinity], + min: [Infinity], + sum: [0], + count: 0, + maxIJK: null, + maxLPS: null, + minIJK: null, + minLPS: null, + runMean: [0], + m2: [0], + pointsInShape: storePointData ? PointsManager.create3(1024) : null, + }; +} + +// Shared logic for updating stats from a callback +function basicStatsCallback( + state: BasicStatsState, + newValue: number | Types.RGB, + pointLPS: Types.Point3 | null = null, + pointIJK: Types.Point3 | null = null +): void { + if ( + Array.isArray(newValue) && + newValue.length > 1 && + state.max.length === 1 + ) { + state.max.push(state.max[0], state.max[0]); + state.min.push(state.min[0], state.min[0]); + state.sum.push(state.sum[0], state.sum[0]); + state.runMean.push(0, 0); + state.m2.push(state.m2[0], state.m2[0]); + } + + if (state.pointsInShape && pointLPS) { + state.pointsInShape.push(pointLPS); + } + const newArray = Array.isArray(newValue) ? newValue : [newValue]; + + state.count += 1; + state.max.forEach((it, idx) => { + const value = newArray[idx]; + const delta = value - state.runMean[idx]; + state.sum[idx] += value; + state.runMean[idx] += delta / state.count; + const delta2 = value - state.runMean[idx]; + state.m2[idx] += delta * delta2; + + state.min[idx] = Math.min(state.min[idx], value); + if (value < state.min[idx]) { + state.min[idx] = value; + if (idx === 0) { + state.minIJK = pointIJK; + state.minLPS = pointLPS; + } + } + + if (value > state.max[idx]) { + state.max[idx] = value; + if (idx === 0) { + state.maxIJK = pointIJK; + state.maxLPS = pointLPS; + } } + }); +} + +// Shared logic for computing the statistics +function basicGetStatistics( + state: BasicStatsState, + unit?: string +): NamedStatistics { + const mean = state.sum.map((sum) => sum / state.count); + const stdDev = state.m2.map((squaredDiffSum) => + Math.sqrt(squaredDiffSum / state.count) + ); + + const named: NamedStatistics = { + max: { + name: 'max', + label: 'Max Pixel', + value: state.max.length === 1 ? state.max[0] : state.max, + unit, + pointIJK: state.maxIJK, + pointLPS: state.maxLPS, + }, + min: { + name: 'min', + label: 'Min Pixel', + value: state.min.length === 1 ? state.min[0] : state.min, + unit, + pointIJK: state.minIJK, + pointLPS: state.minLPS, + }, + mean: { + name: 'mean', + label: 'Mean Pixel', + value: mean.length === 1 ? mean[0] : mean, + unit, + }, + stdDev: { + name: 'stdDev', + label: 'Standard Deviation', + value: stdDev.length === 1 ? stdDev[0] : stdDev, + unit, + }, + count: { + name: 'count', + label: 'Pixel Count', + value: state.count, + unit: null, + }, + pointsInShape: state.pointsInShape, + array: [], + }; + named.array.push( + named.max, + named.mean, + named.stdDev, + named.stdDev, + named.count + ); + + // Reset state for next computation + const store = state.pointsInShape !== null; + const freshState = createBasicStatsState(store); + // Copy fresh state into the provided state object + state.max = freshState.max; + state.min = freshState.min; + state.sum = freshState.sum; + state.count = freshState.count; + state.maxIJK = freshState.maxIJK; + state.maxLPS = freshState.maxLPS; + state.minIJK = freshState.minIJK; + state.minLPS = freshState.minLPS; + state.runMean = freshState.runMean; + state.m2 = freshState.m2; + state.pointsInShape = freshState.pointsInShape; + + return named; +} + +/** + * A static basic stats calculator that uses shared helper functions. + */ +export class BasicStatsCalculator extends Calculator { + private static state: BasicStatsState = createBasicStatsState(true); + + public static statsInit(options: { storePointData: boolean }): void { + this.state = createBasicStatsState(options.storePointData); } - /** - * This callback is used when we verify if the point is in the annotation drawn - * so we can get every point in the shape to calculate the statistics - */ - static statsCallback = ({ + public static statsCallback = ({ value: newValue, pointLPS = null, pointIJK = null, + }: { + value: number | Types.RGB; + pointLPS?: Types.Point3 | null; + pointIJK?: Types.Point3 | null; }): void => { - if ( - Array.isArray(newValue) && - newValue.length > 1 && - this.max.length === 1 - ) { - this.max.push(this.max[0], this.max[0]); - this.min.push(this.min[0], this.min[0]); - this.sum.push(this.sum[0], this.sum[0]); - this.runMean.push(0, 0); - this.m2.push(this.m2[0], this.m2[0]); - } - - if (this.pointsInShape && pointLPS) { - this.pointsInShape?.push(pointLPS); - } - const newArray = Array.isArray(newValue) ? newValue : [newValue]; - - this.count += 1; - this.max.map((it, idx) => { - const value = newArray[idx]; - - const delta = value - this.runMean[idx]; - this.sum[idx] += value; - this.runMean[idx] += delta / this.count; - const delta2 = value - this.runMean[idx]; - this.m2[idx] += delta * delta2; - - this.min[idx] = Math.min(this.min[idx], value); - if (value < this.min[idx]) { - this.min[idx] = value; - if (idx === 0) { - this.minIJK = pointIJK; - this.minLPS = pointLPS; - } - } + basicStatsCallback(this.state, newValue, pointLPS, pointIJK); + }; - if (value > this.max[idx]) { - this.max[idx] = value; - if (idx === 0) { - this.maxIJK = pointIJK; - this.maxLPS = pointLPS; - } - } - }); + public static getStatistics = (options?: { + unit: string; + }): NamedStatistics => { + return basicGetStatistics(this.state, options?.unit); }; +} + +/** + * An instantiable version of BasicStatsCalculator that shares common logic with the static version. + */ +export class InstanceBasicStatsCalculator extends InstanceCalculator { + private state: BasicStatsState; + + constructor(storePointData: boolean = true) { + super(storePointData); + this.state = createBasicStatsState(storePointData); + } /** - * Basic function that calculates statistics for a given array of points. - * @returns An object that contains : - * max : The maximum value of the array - * mean : mean of the array - * stdDev : standard deviation of the array - * array : An array of hte above values, in order. + * Resets the internal state. + * @param options Object with storePointData flag. */ + statsInit(options: { storePointData: boolean }): void { + this.state = createBasicStatsState(options.storePointData); + } - static getStatistics = (options?: { unit: string }): NamedStatistics => { - const mean = this.sum.map((sum) => sum / this.count); - const stdDev = this.m2.map((squaredDiffSum) => - Math.sqrt(squaredDiffSum / this.count) - ); - - const unit = options?.unit || null; - - const named: NamedStatistics = { - max: { - name: 'max', - label: 'Max Pixel', - value: singleArrayAsNumber(this.max), - unit, - pointIJK: this.maxIJK, - pointLPS: this.maxLPS, - }, - min: { - name: 'min', - label: 'Min Pixel', - value: singleArrayAsNumber(this.min), - unit, - pointIJK: this.minIJK, - pointLPS: this.minLPS, - }, - mean: { - name: 'mean', - label: 'Mean Pixel', - value: singleArrayAsNumber(mean), - unit, - }, - stdDev: { - name: 'stdDev', - label: 'Standard Deviation', - value: singleArrayAsNumber(stdDev), - unit, - }, - count: { - name: 'count', - label: 'Pixel Count', - value: this.count, - unit: null, - }, - pointsInShape: this.pointsInShape, - array: [], - }; - named.array.push( - named.max, - named.mean, - named.stdDev, - // Use the stdDev twice to preserve old ordering - this is updated to be - // correct value with Welford's algorithm now. - named.stdDev, - named.count - ); - - this.max = [-Infinity]; - this.min = [Infinity]; - this.sum = [0]; - this.m2 = [0]; - this.runMean = [0]; - this.count = 0; - this.maxIJK = null; - this.maxLPS = null; - this.minIJK = null; - this.minLPS = null; - this.pointsInShape = PointsManager.create3(1024); - - return named; - }; -} + /** + * Processes a new data point for statistics calculation. + * @param newValue The new value or values to process. + * @param pointLPS Optional LPS point. + * @param pointIJK Optional IJK point. + */ + statsCallback(data: { + value: number | Types.RGB; + pointLPS?: Types.Point3 | null; + pointIJK?: Types.Point3 | null; + }): void { + basicStatsCallback(this.state, data.value, data.pointLPS, data.pointIJK); + } -function singleArrayAsNumber(val: number[]) { - return val.length === 1 ? val[0] : val; + /** + * Computes and returns the statistics based on the accumulated data. + * @param options Optional parameters including unit. + * @returns The computed statistics. + */ + getStatistics(options?: { + unit: string; + spacing?: number[] | number; + }): NamedStatistics { + return basicGetStatistics(this.state, options?.unit); + } } diff --git a/packages/tools/src/utilities/math/basic/Calculator.ts b/packages/tools/src/utilities/math/basic/Calculator.ts index c723533fb..f7ab34dfc 100644 --- a/packages/tools/src/utilities/math/basic/Calculator.ts +++ b/packages/tools/src/utilities/math/basic/Calculator.ts @@ -1,11 +1,23 @@ import type { NamedStatistics } from '../../../types'; -abstract class Calculator { - static run: ({ value }) => void; +export abstract class Calculator { /** * Gets the statistics as both an array of values, as well as the named values. */ static getStatistics: () => NamedStatistics; } -export default Calculator; +/** + * An instantiable version of Calculator with instance methods. + */ +export class InstanceCalculator { + constructor(private storePointData: boolean) {} + /** + * Returns the calculated statistics. + * @returns The statistics result. + */ + getStatistics() { + // Implement instance-specific logic if needed + console.debug('InstanceCalculator getStatistics called'); + } +} diff --git a/packages/tools/src/utilities/segmentation/SegmentStatsCalculator.ts b/packages/tools/src/utilities/segmentation/SegmentStatsCalculator.ts new file mode 100644 index 000000000..efbd3cc49 --- /dev/null +++ b/packages/tools/src/utilities/segmentation/SegmentStatsCalculator.ts @@ -0,0 +1,90 @@ +import type { Types } from '@cornerstonejs/core'; +import type { NamedStatistics } from '../../types'; +import { InstanceVolumetricCalculator } from './VolumetricCalculator'; + +/** + * A calculator that manages statistics for multiple segments. + * This class acts as a container for multiple VolumetricCalculator instances, + * one for each segment index. + */ +export default class SegmentStatsCalculator { + private static calculators: Map< + number | number[], + InstanceVolumetricCalculator + > = new Map(); + + private static indices: number[] = []; + private static mode: 'collective' | 'individual' = 'collective'; + + public static statsInit(options: { + storePointData: boolean; + indices: number[]; + mode: 'collective' | 'individual'; + }) { + const { storePointData, indices, mode } = options; + this.mode = mode; + this.indices = indices; + + // Clear existing calculators + this.calculators.clear(); + + if (this.mode === 'individual') { + // Create individual calculator for each segment index + indices.forEach((index) => { + this.calculators.set( + index, + new InstanceVolumetricCalculator(storePointData) + ); + }); + } else { + // Create single calculator for all indices + this.calculators.set( + indices, + new InstanceVolumetricCalculator(storePointData) + ); + } + } + + public static statsCallback(data: { + value: number | Types.RGB; + pointLPS?: Types.Point3; + pointIJK?: Types.Point3; + segmentIndex?: number; + }) { + const { segmentIndex, ...statsData } = data; + + if (!segmentIndex) { + throw new Error('Segment index is required for stats calculation'); + } + + const calculator = + this.mode === 'individual' + ? this.calculators.get(segmentIndex) + : this.calculators.get(this.indices); + + if (!calculator) { + throw new Error(`No calculator found for segment ${segmentIndex}`); + } + + calculator.statsCallback(statsData); + } + + /** + * Get statistics for all segments or a specific segment + */ + public static getStatistics(options?: { + spacing?: number[] | number; + unit?: string; + }): NamedStatistics | { [segmentIndex: number]: NamedStatistics } { + if (this.mode === 'individual') { + const result: { [segmentIndex: number]: NamedStatistics } = {}; + this.calculators.forEach((calculator, segmentIndex) => { + result[segmentIndex as number] = calculator.getStatistics(options); + }); + return result; + } + + const calculator = this.calculators.get(this.indices); + return calculator.getStatistics(options); + } +} diff --git a/packages/tools/src/utilities/segmentation/VolumetricCalculator.ts b/packages/tools/src/utilities/segmentation/VolumetricCalculator.ts index e0573ab0a..2498ced49 100644 --- a/packages/tools/src/utilities/segmentation/VolumetricCalculator.ts +++ b/packages/tools/src/utilities/segmentation/VolumetricCalculator.ts @@ -1,79 +1,188 @@ import type { Types } from '@cornerstonejs/core'; import type { NamedStatistics } from '../../types'; -import { BasicStatsCalculator } from '../math/basic'; +import { + BasicStatsCalculator, + InstanceBasicStatsCalculator, +} from '../math/basic/BasicStatsCalculator'; const TEST_MAX_LOCATIONS = 10; +interface VolumetricState { + maxIJKs: Array<{ + value: number; + pointLPS?: Types.Point3; + pointIJK?: Types.Point3; + }>; +} + +function createVolumetricState(): VolumetricState { + return { + maxIJKs: [], + }; +} + +function volumetricStatsCallback( + state: VolumetricState, + data: { + value: number | Types.RGB; + pointLPS?: Types.Point3; + pointIJK?: Types.Point3; + } +): void { + const { value } = data; + const { maxIJKs } = state; + const length = maxIJKs.length; + + if ( + typeof value !== 'number' || + (length >= TEST_MAX_LOCATIONS && value < maxIJKs[0].value) + ) { + return; + } + + if (!length || value >= maxIJKs[length - 1].value) { + maxIJKs.push( + data as { + value: number; + pointLPS?: Types.Point3; + pointIJK?: Types.Point3; + } + ); + } else { + for (let i = 0; i < length; i++) { + if (value <= maxIJKs[i].value) { + maxIJKs.splice( + i, + 0, + data as { + value: number; + pointLPS?: Types.Point3; + pointIJK?: Types.Point3; + } + ); + break; + } + } + } + + if (maxIJKs.length >= TEST_MAX_LOCATIONS) { + maxIJKs.splice(0, 1); + } +} + +function volumetricGetStatistics( + state: VolumetricState, + stats: NamedStatistics, + options: { + spacing?: number[] | number; + unit?: string; + } +): NamedStatistics { + const { spacing } = options; + const volumeUnit = spacing ? 'mm³' : 'voxels³'; + const volumeScale = spacing + ? Array.isArray(spacing) + ? spacing[0] * spacing[1] * spacing[2] * 1000 + : spacing * spacing * spacing * 1000 + : 1; + + stats.volume = { + value: Array.isArray(stats.count.value) + ? stats.count.value.map((v: number) => v * volumeScale) + : stats.count.value * volumeScale, + unit: volumeUnit, + name: 'volume', + }; + + stats.maxIJKs = state.maxIJKs.filter( + (entry): entry is { value: number; pointIJK: Types.Point3 } => + entry.pointIJK !== undefined + ); + stats.array.push(stats.volume); + + // Reset state + state.maxIJKs = []; + + return stats; +} + /** - * A basic stats calculator for volumetric data, generally for use with - * segmentations. + * A basic stats calculator for volumetric data, generally for use with segmentations. */ -export default class VolumetricCalculator extends BasicStatsCalculator { - /** - * maxIJKs is a list of possible peak value locations based - * on the statsCallback calls with the largest TEST_MAX_LOCATIONS values. - */ - private static maxIJKs = []; +export class VolumetricCalculator extends BasicStatsCalculator { + private static volumetricState: VolumetricState = createVolumetricState(); + + public static statsInit(options: { storePointData: boolean }): void { + super.statsInit(options); + this.volumetricState = createVolumetricState(); + } + + public static statsCallback(data: { + value: number | Types.RGB; + pointLPS?: Types.Point3; + pointIJK?: Types.Point3; + }): void { + super.statsCallback(data); + volumetricStatsCallback(this.volumetricState, data); + } + public static getStatistics(options: { - spacing?: number; + spacing?: number[] | number; unit?: string; }): NamedStatistics { - const { spacing } = options; - // Get the basic units - const stats = BasicStatsCalculator.getStatistics(); - - // Add the volumetric units - const volumeUnit = spacing ? 'mm\xb3' : 'voxels\xb3'; - const volumeScale = spacing - ? spacing[0] * spacing[1] * spacing[2] * 1000 - : 1; - - stats.volume = { - value: Array.isArray(stats.count.value) - ? stats.count.value.map((v) => v * volumeScale) - : stats.count.value * volumeScale, - unit: volumeUnit, - name: 'volume', + const optionsWithUnit = { + ...options, + unit: options?.unit || 'none', }; - stats.maxIJKs = this.maxIJKs; + const stats = super.getStatistics(optionsWithUnit); + return volumetricGetStatistics( + this.volumetricState, + stats, + optionsWithUnit + ); + } +} - stats.array.push(stats.volume); - // Reset all the calculated values to agree with the BasicStatsCalculator API - this.maxIJKs = []; +/** + * An instantiable version of VolumetricCalculator that uses instance state. + */ +export class InstanceVolumetricCalculator extends InstanceBasicStatsCalculator { + private volumetricState: VolumetricState; - return stats; + constructor(storePointData: boolean = true) { + super(storePointData); + this.volumetricState = createVolumetricState(); } - /** - * Calculate the basic stats, and then start collecting locations of peak values. - */ - public static statsCallback(data: { + statsInit(options: { storePointData: boolean }): void { + super.statsInit(options); + this.volumetricState = createVolumetricState(); + } + + statsCallback(data: { value: number | Types.RGB; pointLPS?: Types.Point3; pointIJK?: Types.Point3; - }) { - BasicStatsCalculator.statsCallback(data); - const { value } = data; - const { maxIJKs } = this; - const { length } = maxIJKs; - if ( - typeof value !== 'number' || - (length >= TEST_MAX_LOCATIONS && value < maxIJKs[0].value) - ) { - return; - } - if (!length || value >= maxIJKs[length - 1].value) { - maxIJKs.push(data); - } else { - for (let i = 0; i < length; i++) { - if (value <= maxIJKs[i].value) { - maxIJKs.splice(i, 0, data); - break; - } - } - } - if (length >= TEST_MAX_LOCATIONS) { - maxIJKs.splice(0, 1); - } + }): void { + super.statsCallback(data); + volumetricStatsCallback(this.volumetricState, data); + } + + getStatistics(options?: { + spacing?: number[] | number; + unit?: string; + }): NamedStatistics { + const optionsWithUnit = { + ...options, + unit: options?.unit || 'none', + }; + const stats = super.getStatistics(optionsWithUnit); + return volumetricGetStatistics( + this.volumetricState, + stats, + optionsWithUnit + ); } } + +export default VolumetricCalculator; diff --git a/packages/tools/src/utilities/segmentation/getStatistics.ts b/packages/tools/src/utilities/segmentation/getStatistics.ts index f5c213b11..1efc01ed5 100644 --- a/packages/tools/src/utilities/segmentation/getStatistics.ts +++ b/packages/tools/src/utilities/segmentation/getStatistics.ts @@ -20,6 +20,8 @@ import type { LabelmapSegmentationDataStack, LabelmapSegmentationDataVolume, } from '../../types/LabelmapTypes'; +import type { NamedStatistics } from '../../types'; + // Radius for a volume of 10, eg 1 cm^3 = 1000 mm^3 const radiusForVol1 = Math.pow((3 * 1000) / (4 * Math.PI), 1 / 3); @@ -32,13 +34,31 @@ const triggerWorkerProgress = (eventTarget, progress) => { }); }; +/** + * Get statistics for a segmentation. + * + * @param segmentationId - The segmentation ID. + * @param segmentIndices - The segment indices to get statistics for. + * - If a single number is provided, it retrieves statistics for that specific segment. + * - If an array is provided: + * - In `collective` mode (default), it retrieves statistics for all voxels that belong to any of the specified segment indices (OR operation). + * - In `individual` mode, it retrieves statistics separately for each segment index. + * @param mode - The computation mode (optional, defaults to `'collective'`). + * - `'collective'` (default): Treats the segment indices as a group, computing combined statistics. + * - `'individual'`: Treats each segment index separately, computing statistics for each one independently. + * + * @returns The statistics, either as a single aggregated result (if `collective` mode) + * or an object with segment indices as keys and statistics as values (if `individual` mode). + */ async function getStatistics({ segmentationId, segmentIndices, + mode = 'collective', }: { segmentationId: string; segmentIndices: number[] | number; -}) { + mode?: 'collective' | 'individual'; +}): Promise { registerComputeWorker(); triggerWorkerProgress(eventTarget, 0); @@ -88,10 +108,19 @@ async function getStatistics({ ); const unit = getPixelValueUnitsImageId(refImageId, modalityUnitOptions); - const stats = reconstructableVolume - ? await calculateVolumeStatistics(operationData, indices, unit) - : await calculateStackStatistics(segImageIds, indices, unit); + ? await calculateVolumeStatistics({ + operationData, + indices, + unit, + mode, + }) + : await calculateStackStatistics({ + segImageIds, + indices, + unit, + mode, + }); return stats; } @@ -99,7 +128,12 @@ async function getStatistics({ /** * Calculate statistics for a reconstructable volume */ -async function calculateVolumeStatistics(operationData, indices, unit) { +async function calculateVolumeStatistics({ + operationData, + indices, + unit, + mode, +}) { // Get the strategy data const strategyData = getStrategyData({ operationData, @@ -151,12 +185,42 @@ async function calculateVolumeStatistics(operationData, indices, unit) { segmentationInfo, imageInfo, indices, + mode, } ); triggerWorkerProgress(eventTarget, 100); - // Update units + if (mode === 'collective') { + return processSegmentationStatistics({ + stats, + unit, + spacing, + segmentationImageData, + imageVoxelManager, + }); + } else { + const finalStats = {}; + Object.entries(stats).forEach(([segmentIndex, stat]) => { + finalStats[segmentIndex] = processSegmentationStatistics({ + stats: stat, + unit, + spacing, + segmentationImageData, + imageVoxelManager, + }); + }); + return finalStats; + } +} + +const processSegmentationStatistics = ({ + stats, + unit, + spacing, + segmentationImageData, + imageVoxelManager, +}) => { stats.mean.unit = unit; stats.max.unit = unit; stats.min.unit = unit; @@ -195,12 +259,12 @@ async function calculateVolumeStatistics(operationData, indices, unit) { } return stats; -} +}; /** * Calculate statistics for a stack of images */ -async function calculateStackStatistics(segImageIds, indices, unit) { +async function calculateStackStatistics({ segImageIds, indices, unit, mode }) { triggerWorkerProgress(eventTarget, 0); // we need to loop over each seg image separately and calculate the stats const segmentationInfo = []; @@ -237,6 +301,7 @@ async function calculateStackStatistics(segImageIds, indices, unit) { segmentationInfo, imageInfo, indices, + mode, } ); diff --git a/packages/tools/src/utilities/segmentation/index.ts b/packages/tools/src/utilities/segmentation/index.ts index 356d6c380..fd80c7e15 100644 --- a/packages/tools/src/utilities/segmentation/index.ts +++ b/packages/tools/src/utilities/segmentation/index.ts @@ -16,6 +16,7 @@ import { setBrushThresholdForToolGroup, } from './brushThresholdForToolGroup'; import VolumetricCalculator from './VolumetricCalculator'; +import SegmentStatsCalculator from './SegmentStatsCalculator'; import thresholdSegmentationByRange from './thresholdSegmentationByRange'; import contourAndFindLargestBidirectional from './contourAndFindLargestBidirectional'; import createBidirectionalToolData from './createBidirectionalToolData'; @@ -48,6 +49,7 @@ export { getBrushThresholdForToolGroup, setBrushThresholdForToolGroup, VolumetricCalculator, + SegmentStatsCalculator, thresholdSegmentationByRange, contourAndFindLargestBidirectional, createBidirectionalToolData, diff --git a/packages/tools/src/workers/computeWorker.js b/packages/tools/src/workers/computeWorker.js index 8664a9e19..bf8bc617b 100644 --- a/packages/tools/src/workers/computeWorker.js +++ b/packages/tools/src/workers/computeWorker.js @@ -1,12 +1,12 @@ import { expose } from 'comlink'; import { utilities } from '@cornerstonejs/core'; -import VolumetricCalculator from '../utilities/segmentation/VolumetricCalculator'; +import SegmentStatsCalculator from '../utilities/segmentation/SegmentStatsCalculator'; const { VoxelManager } = utilities; const computeWorker = { calculateSegmentsStatisticsVolume: (args) => { - const { segmentationInfo, imageInfo, indices } = args; + const { segmentationInfo, imageInfo, indices, mode } = args; const { scalarData: segmentationScalarData, @@ -38,6 +38,8 @@ const computeWorker = { scalarData: imageScalarData, }); + SegmentStatsCalculator.statsInit({ storePointData: false, indices, mode }); + // Use forEach to iterate over all voxels and call statsCallback for those in the segmentation segVoxelManager.forEach( ({ value, pointIJK, index }) => { @@ -48,9 +50,9 @@ const computeWorker = { // get the value from the image voxel manager const imageValue = imageVoxelManager.getAtIndex(index); - // Todo: later add the isInObject check based on lps for the different dimensions - // for now just assume the pointIJK is within the bounds - VolumetricCalculator.statsCallback({ + // Process the voxel for the specific segment index + SegmentStatsCalculator.statsCallback({ + segmentIndex: value, value: imageValue, pointIJK, }); @@ -60,16 +62,21 @@ const computeWorker = { } ); - const stats = VolumetricCalculator.getStatistics({ + // Get statistics based on the mode + const stats = SegmentStatsCalculator.getStatistics({ spacing: segmentationSpacing, unit: 'mm', + mode, }); return stats; }, calculateSegmentsStatisticsStack: (args) => { - const { segmentationInfo, imageInfo, indices } = args; + const { segmentationInfo, imageInfo, indices, mode } = args; + + // Initialize the SegmentStatsCalculator with the segment indices + SegmentStatsCalculator.init(indices, { storePointData: true }); // Create voxel managers for each pair of segmentation and image info for (let i = 0; i < segmentationInfo.length; i++) { @@ -95,9 +102,6 @@ const computeWorker = { // Use forEach to iterate and call statsCallback segVoxelManager.forEach( ({ value, pointIJK, index }) => { - // Todo: later add the isInObject check based on lps for the different dimensions - // for now just assume the pointIJK is within the bounds - if (indices.indexOf(value) === -1) { return; } @@ -105,8 +109,11 @@ const computeWorker = { // get the value from the image voxel manager const imageValue = imageVoxelManager.getAtIndex(index); - VolumetricCalculator.statsCallback({ + // Process the voxel for the specific segment index + SegmentStatsCalculator.processVoxel({ + segmentIndex: value, value: imageValue, + pointIJK, }); }, { @@ -118,8 +125,10 @@ const computeWorker = { // Pick first one for spacing const spacing = segmentationInfo[0].spacing; - const stats = VolumetricCalculator.getStatistics({ + // Get statistics based on the mode + const stats = SegmentStatsCalculator.getStatistics({ spacing, + mode, }); return stats; diff --git a/utils/demo/helpers/initDemo.ts b/utils/demo/helpers/initDemo.ts index de0677b09..55ee47480 100644 --- a/utils/demo/helpers/initDemo.ts +++ b/utils/demo/helpers/initDemo.ts @@ -20,7 +20,7 @@ import * as polySeg from '@cornerstonejs/polymorphic-segmentation'; window.cornerstone = cornerstone; window.cornerstoneTools = cornerstoneTools; -export default async function initDemo(config) { +export default async function initDemo(config = {}) { initProviders(); cornerstoneDICOMImageLoader.init(); initVolumeLoader(); diff --git a/yarn.lock b/yarn.lock index cbb9358d1..b98a73f96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5757,110 +5757,95 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz#f672f6508f090fc73f08ba40ff76c20b57424778" integrity sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA== -"@rspack/binding-darwin-arm64@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.2.2.tgz#e2444ef46b3ee689a6021ae757bb55a0dbe7b491" - integrity sha512-h23F8zEkXWhwMeScm0ZnN78Zh7hCDalxIWsm7bBS0eKadnlegUDwwCF8WE+8NjWr7bRzv0p3QBWlS5ufkcL4eA== - "@rspack/binding-darwin-arm64@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.2.6.tgz#5f1fad2c77608061e2607f181dbdf32b62d4d247" integrity sha512-31URF3tAgVR8Pt6Oc8MANV/gYNR6DlUhtIMmWM2EwdcWTyIEnN7gSDdjtB6cYvETHwdM7NDSCOgyIirG1+tNZw== -"@rspack/binding-darwin-x64@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.2.2.tgz#5a4b827692d3063a5d30577ba41f2d97ab452492" - integrity sha512-vG5s7FkEvwrGLfksyDRHwKAHUkhZt1zHZZXJQn4gZKjTBonje8ezdc7IFlDiWpC4S+oBYp73nDWkUzkGRbSdcQ== +"@rspack/binding-darwin-arm64@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.2.7.tgz#83b3a9659175c67c8b5e802e11efefda982693a8" + integrity sha512-dT5eSMTknZaI8Djmz8KnaWM68rjZuBZwsKyF144o+ZSJM55vgiNXyL0lQYB8mX9nR3Gck+jKuGUAT2W/EF/t5Q== "@rspack/binding-darwin-x64@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.2.6.tgz#e9e1f86adeb9717aad14721c920a6871801d3bfb" integrity sha512-0XJMOGEqERP9N8zgJxfdWzuZG9buEp6RL4PSVaXPvcKw75Ig3YW50A8sMqd4SNXAqJp2gC706d6l8OnMXpRo3w== -"@rspack/binding-linux-arm64-gnu@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.2.tgz#9c07f56fcac8ddc12bb818868fd5194c80d11fb5" - integrity sha512-VykY/kiYOzO8E1nYzfJ9+gQEHxb5B6lt5wa8M6xFi5B6jEGU+OsaGskmAZB9/GFImeFDHxDPvhUalI4R9p8O2Q== +"@rspack/binding-darwin-x64@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.2.7.tgz#79efabd938190a17e7fac220b0f8fd35e576d8d5" + integrity sha512-5n8IhKBxH71d4BUIvyzTwSOAOKNneLPJwLIphSPNIbCMGjLI59/EVpxSQ/AAUfyMkqOs635NNCn0eGQVuzpI/w== "@rspack/binding-linux-arm64-gnu@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.6.tgz#df0234b410ade125a7cf056fd32bd3288b1e1418" integrity sha512-Ld26wvy9NSTqhUb/ll5ZpIW08ZzUkTl5daW3xHJgcaoRDrnJkRV1pMx8cdV8S+xsavJIPf4c+BuKpU6Ml2kx9A== -"@rspack/binding-linux-arm64-musl@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.2.tgz#e3aff4cd36de780f95ded65264363b444f7f3c4e" - integrity sha512-Z5vAC4wGfXi8XXZ6hs8Q06TYjr3zHf819HB4DI5i4C1eQTeKdZSyoFD0NHFG23bP4NWJffp8KhmoObcy9jBT5Q== +"@rspack/binding-linux-arm64-gnu@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.7.tgz#51393cb6e00bd02b751448ad3db914e9ae30ffe8" + integrity sha512-DTtFBJmgQQrVWjbklpgJDr3kE9Uf1fHsPh+1GVslsBuyn+o4O7JslrnjuVsQCYKoiEg0Lg4ZPQmwnhJLHssZ5A== "@rspack/binding-linux-arm64-musl@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.6.tgz#4ac3b06784f3111d7cac24c55780e22a3dffd26b" integrity sha512-TrklgPKngiuzRovr7MdXDKXPfjJlT3g5LmCX/Y4pPfNrrOLjzL/fpEBRXBJEhrSuNWqpkZSNLs+Av02IY7manQ== -"@rspack/binding-linux-x64-gnu@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.2.tgz#5af03e8b21c4afecddd92d52f0994a7e4785aabd" - integrity sha512-o3pDaL+cH5EeRbDE9gZcdZpBgp5iXvYZBBhe8vZQllYgI4zN5MJEuleV7WplG3UwTXlgZg3Kht4RORSOPn96vg== +"@rspack/binding-linux-arm64-musl@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.7.tgz#604ca55e06e45654fbd0a8c696bec2452708da7a" + integrity sha512-01/OoQQF9eyDvRKkxj4DzCznfGZIvnzI8qOsrv+M7VBm8FLoKpb3hygXixaGQOXmNL42XTh61qjgm++fBu6aUA== "@rspack/binding-linux-x64-gnu@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.6.tgz#76389841c412952e18ff908d0b36bea5c8f86e3d" integrity sha512-aZ6mrZyuUg8hlBf7qEfXRAVPh2tM8E7kYZhI5eBOUoi6XhO5fTVcf/S2VUimFWLUmJdmSujG+nrYGQu1n74Xag== -"@rspack/binding-linux-x64-musl@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.2.tgz#e5be9d4d6d7e5369fa0708c3bc6281a8c52525ad" - integrity sha512-RE3e0xe4DdchHssttKzryDwjLkbrNk/4H59TkkWeGYJcLw41tmcOZVFQUOwKLUvXWVyif/vjvV/w1SMlqB4wQg== +"@rspack/binding-linux-x64-gnu@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.7.tgz#2a6b9b8074c7e0e8c5fe57819478012353553e32" + integrity sha512-lUOAUq0YSsofCXsP6XnlgfH0ZRDZ2X2XqXLXYjqf4xkSxCl5eBmE0EQYjAHF4zjUvU5rVx4a4bDLWv7+t3bOHg== "@rspack/binding-linux-x64-musl@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.6.tgz#510b72377cec1abca142b02cb5588391ca29831f" integrity sha512-Trg+s1b6sD4XNMOvwWwI+cebwGOBEXsND9Ofjc6L1RPtCeZQ5Rrycfh/HVymI50Y48g8YMibLZw8G2gAfK8SZw== -"@rspack/binding-win32-arm64-msvc@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.2.tgz#4b1e98a304f1ea10fefb1de2de8abc460a0a15a7" - integrity sha512-R+PKBYn6uzTaDdVqTHvjqiJPBr5ZHg1wg5UmFDLNH9OklzVFyQh1JInSdJRb7lzfzTRz6bEkkwUFBPQK/CGScw== +"@rspack/binding-linux-x64-musl@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.7.tgz#d851a554812f8f00be9ac472c8cb72ab40028063" + integrity sha512-ZrPXfgT30p4DlydYavaTHiluxHkWvZHt7K4q7qNyTfYYowG6jRGwWi/PATdugNICGv027Wsh5nzEO4o27Iuhwg== "@rspack/binding-win32-arm64-msvc@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.6.tgz#8a2a3eac5c6a6805a5c7fa9ce4e00acda6901c9f" integrity sha512-lEWMW8H5ERYX376NA2qGritCHmcMNW+Ob6WVWuEZNh0oWeBD/mWqWFxbCx5J3KtlVy4miwk65V8YDd92alUEyw== -"@rspack/binding-win32-ia32-msvc@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.2.2.tgz#3eff46acf9b1e11b33846edf0f7f916e8aeeb5e6" - integrity sha512-dBqz3sRAGZ2f31FgzKLDvIRfq2haRP3X3XVCT0PsiMcvt7QJng+26aYYMy2THatd/nM8IwExYeitHWeiMBoruw== +"@rspack/binding-win32-arm64-msvc@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.7.tgz#524795d99ea830c1c80fe6d7054df3df51e434f2" + integrity sha512-1OzzM+OUSWX39XYcDfxJ8bGX5vNNrRejCMGotBEdP+uQ3KMWCPz0G4KRc3QIjghaLIYk3ofd83hcfUxyk/2Xog== "@rspack/binding-win32-ia32-msvc@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.2.6.tgz#b8d15bb50439dd7ba40642ea8f7a618e2dd9e568" integrity sha512-ML3f7vDyv2c7d+ync6l3aRY4cIAKUPT5n+yz7sRcwIBrB4n1n4rH6wf5a56h4wHjiWpnV0gXBXI9SrYD5a4vRQ== -"@rspack/binding-win32-x64-msvc@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.2.tgz#6f4bf6a590ffbbda64316ef1dc0378c0c3d93f2e" - integrity sha512-eeAvaN831KG553cMSHkVldyk6YQn4ujgRHov6r1wtREq7CD3/ka9LMkJUepCN85K7XtwYT0N4KpFIQyf5GTGoA== +"@rspack/binding-win32-ia32-msvc@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.2.7.tgz#4656621e7e519e4e089c0100a783f175c6a38a8f" + integrity sha512-VWlDCV9kDtijk9GK6ZtBQmYoVzKGpnrJB0iI3d2gIEa/2NwikJ89bLMFE4dFx8UNH3p/sSyb5pmPOQnbudFK7Q== "@rspack/binding-win32-x64-msvc@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.6.tgz#81713cc4b4e27e1f38b5e2d08b5d970a5d640fbe" integrity sha512-0W0iComo7cdOg5fOuaZ2l1Mz7DG1A4SPDes557n9CH2Tf5rub3m2rBoMQ1B/XIkcUeGf+oB6bbBBroHPH0vQBA== -"@rspack/binding@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.2.2.tgz#0be057d1668cfc753bfbf039704fb0eb1c69a953" - integrity sha512-GCZwpGFYlLTdJ2soPLwjw9z4LSZ+GdpbHNfBt3Cm/f/bAF8n6mZc7dHUqN893RFh7MPU17HNEL3fMw7XR+6pHg== - optionalDependencies: - "@rspack/binding-darwin-arm64" "1.2.2" - "@rspack/binding-darwin-x64" "1.2.2" - "@rspack/binding-linux-arm64-gnu" "1.2.2" - "@rspack/binding-linux-arm64-musl" "1.2.2" - "@rspack/binding-linux-x64-gnu" "1.2.2" - "@rspack/binding-linux-x64-musl" "1.2.2" - "@rspack/binding-win32-arm64-msvc" "1.2.2" - "@rspack/binding-win32-ia32-msvc" "1.2.2" - "@rspack/binding-win32-x64-msvc" "1.2.2" +"@rspack/binding-win32-x64-msvc@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.7.tgz#65c05cb8386fed325e2fcda8f70d02e5c387d334" + integrity sha512-l/sTdeMsQF1a1aB79cWykDNRZG6nkUA0biJo2/sEARP3ijdr8TuwUdirp2JRDmZfQJkoJnQ2un9y9qyW+TIZzA== "@rspack/binding@1.2.6": version "1.2.6" @@ -5877,19 +5862,34 @@ "@rspack/binding-win32-ia32-msvc" "1.2.6" "@rspack/binding-win32-x64-msvc" "1.2.6" -"@rspack/cli@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/cli/-/cli-1.2.2.tgz#16fb207564e3f8f1ce13d85e392c8e540e7aee4f" - integrity sha512-d1wsIqmQHjqfo2KKx9TOOW7M4PnD2Viv9FbosXRW/lisvPFJUTwg87onv2x3z4KTCHqplH9T4MCeKmCj+ZNKOw== +"@rspack/binding@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.2.7.tgz#aa6794a92d5e10955155180db6a5c2d2c96cb10d" + integrity sha512-QH+kxkG0I9C6lmlwgBUDFsy24ihXMGG5lfiNtQilk4CyBN+AgSWFENcYrnkUaBioZAvMBznQLiccV3X0JeH9iQ== + optionalDependencies: + "@rspack/binding-darwin-arm64" "1.2.7" + "@rspack/binding-darwin-x64" "1.2.7" + "@rspack/binding-linux-arm64-gnu" "1.2.7" + "@rspack/binding-linux-arm64-musl" "1.2.7" + "@rspack/binding-linux-x64-gnu" "1.2.7" + "@rspack/binding-linux-x64-musl" "1.2.7" + "@rspack/binding-win32-arm64-msvc" "1.2.7" + "@rspack/binding-win32-ia32-msvc" "1.2.7" + "@rspack/binding-win32-x64-msvc" "1.2.7" + +"@rspack/cli@^1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/cli/-/cli-1.2.7.tgz#4140b8fd423499527b1a58e38651f03775d2f867" + integrity sha512-nUUZuwnSEORqPcknhP+gkQh9YZqeOlmFKJA1YRnZ5QQkzugCehV+xzVjO+Ezd8R1CSMpqdAQq7+pFZ8rpaRymA== dependencies: "@discoveryjs/json-ext" "^0.5.7" "@rspack/dev-server" "1.0.10" - colorette "2.0.19" + colorette "2.0.20" exit-hook "^4.0.0" interpret "^3.1.1" rechoir "^0.8.0" webpack-bundle-analyzer "4.6.1" - yargs "17.6.2" + yargs "17.7.2" "@rspack/core@^1.1.1": version "1.2.6" @@ -5901,15 +5901,15 @@ "@rspack/lite-tapable" "1.0.1" caniuse-lite "^1.0.30001700" -"@rspack/core@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.2.2.tgz#c91b7d36aa080ca99459826ad2db0e665215da2c" - integrity sha512-EeHAmY65Uj62hSbUKesbrcWGE7jfUI887RD03G++Gj8jS4WPHEu1TFODXNOXg6pa7zyIvs2BK0Bm16Kwz8AEaQ== +"@rspack/core@^1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.2.7.tgz#8ccf495f0b814ce3711b9aaf5a11afdffefa4167" + integrity sha512-Vg7ySflnqI1nNOBPd6VJkQozWADssxn3einbxa9OqDVAB+dGSj8qihTs6rlaTSewidoaYTGIAiTMHO2y+61qqQ== dependencies: "@module-federation/runtime-tools" "0.8.4" - "@rspack/binding" "1.2.2" + "@rspack/binding" "1.2.7" "@rspack/lite-tapable" "1.0.1" - caniuse-lite "^1.0.30001616" + caniuse-lite "^1.0.30001700" "@rspack/dev-server@1.0.10": version "1.0.10" @@ -8865,7 +8865,7 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001616, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001669: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001669: version "1.0.30001699" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz" integrity sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w== @@ -9315,12 +9315,7 @@ colord@^2.9.3: resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== -colorette@2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== - -colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.20: +colorette@2.0.20, colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.20: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== @@ -25455,19 +25450,6 @@ yargs-unparser@^2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@17.6.2: - version "17.6.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" - integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - yargs@17.7.2, yargs@^17.0.0, yargs@^17.3.1, yargs@^17.6.0, yargs@^17.6.2, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" From 1997c7fcddf653f494de564d3030a80568353c17 Mon Sep 17 00:00:00 2001 From: sedghi Date: Tue, 4 Mar 2025 15:29:57 -0500 Subject: [PATCH 3/4] s --- packages/tools/src/utilities/math/basic/index.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/tools/src/utilities/math/basic/index.ts b/packages/tools/src/utilities/math/basic/index.ts index 53ccb4a16..f0b643ff8 100644 --- a/packages/tools/src/utilities/math/basic/index.ts +++ b/packages/tools/src/utilities/math/basic/index.ts @@ -1,4 +1,12 @@ -import BasicStatsCalculator from './BasicStatsCalculator'; -import Calculator from './Calculator'; +import { + BasicStatsCalculator, + InstanceBasicStatsCalculator, +} from './BasicStatsCalculator'; +import { Calculator, InstanceCalculator } from './Calculator'; -export { BasicStatsCalculator, Calculator }; +export { + BasicStatsCalculator, + InstanceBasicStatsCalculator, + Calculator, + InstanceCalculator, +}; From 0e216331f52d70e070e4e1e1ae84085bb0dba1db Mon Sep 17 00:00:00 2001 From: sedghi Date: Thu, 6 Mar 2025 23:56:58 -0500 Subject: [PATCH 4/4] bun --- bun.lock | 138 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/bun.lock b/bun.lock index 0c0ff55ab..ac1707006 100644 --- a/bun.lock +++ b/bun.lock @@ -24,8 +24,8 @@ "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^15.0.2", "@rollup/plugin-typescript": "^11.1.6", - "@rspack/cli": "^1.2.2", - "@rspack/core": "^1.2.2", + "@rspack/cli": "^1.2.7", + "@rspack/core": "^1.2.7", "@types/dom-webcodecs": "^0.1.11", "@types/emscripten": "^1.39.6", "@types/jasmine": "^4.3.1", @@ -131,7 +131,7 @@ }, "packages/adapters": { "name": "@cornerstonejs/adapters", - "version": "3.0.4", + "version": "3.0.5", "dependencies": { "@babel/runtime-corejs2": "^7.17.8", "buffer": "^6.0.3", @@ -140,13 +140,13 @@ "ndarray": "^1.0.19", }, "peerDependencies": { - "@cornerstonejs/core": "^3.0.4", - "@cornerstonejs/tools": "^3.0.4", + "@cornerstonejs/core": "^3.0.5", + "@cornerstonejs/tools": "^3.0.5", }, }, "packages/ai": { "name": "@cornerstonejs/ai", - "version": "3.0.4", + "version": "3.0.5", "dependencies": { "@babel/runtime-corejs2": "^7.17.8", "buffer": "^6.0.3", @@ -164,7 +164,7 @@ }, "packages/core": { "name": "@cornerstonejs/core", - "version": "3.0.4", + "version": "3.0.5", "dependencies": { "@kitware/vtk.js": "32.9.0", "comlink": "^4.4.1", @@ -173,7 +173,7 @@ }, "packages/dicomImageLoader": { "name": "@cornerstonejs/dicom-image-loader", - "version": "3.0.4", + "version": "3.0.5", "dependencies": { "@cornerstonejs/codec-charls": "^1.2.3", "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", @@ -185,7 +185,7 @@ "uuid": "^9.0.0", }, "peerDependencies": { - "@cornerstonejs/core": "^3.0.4", + "@cornerstonejs/core": "^3.0.5", "dicom-parser": "^1.8.9", }, }, @@ -193,11 +193,11 @@ "name": "docs", "version": "3.0.0", "dependencies": { - "@cornerstonejs/adapters": "^3.0.4", - "@cornerstonejs/core": "^3.0.4", - "@cornerstonejs/dicom-image-loader": "^3.0.4", - "@cornerstonejs/nifti-volume-loader": "^3.0.4", - "@cornerstonejs/tools": "^3.0.4", + "@cornerstonejs/adapters": "^3.0.5", + "@cornerstonejs/core": "^3.0.5", + "@cornerstonejs/dicom-image-loader": "^3.0.5", + "@cornerstonejs/nifti-volume-loader": "^3.0.5", + "@cornerstonejs/tools": "^3.0.5", "@docusaurus/core": "3.6.3", "@docusaurus/faster": "3.6.3", "@docusaurus/module-type-aliases": "3.6.3", @@ -235,7 +235,7 @@ }, "packages/labelmap-interpolation": { "name": "@cornerstonejs/labelmap-interpolation", - "version": "3.0.4", + "version": "3.0.5", "dependencies": { "@itk-wasm/morphological-contour-interpolation": "1.1.0", "itk-wasm": "1.0.0-b.165", @@ -248,17 +248,17 @@ }, "packages/nifti-volume-loader": { "name": "@cornerstonejs/nifti-volume-loader", - "version": "3.0.4", + "version": "3.0.5", "dependencies": { "nifti-reader-js": "^0.6.8", }, "peerDependencies": { - "@cornerstonejs/core": "^3.0.4", + "@cornerstonejs/core": "^3.0.5", }, }, "packages/polymorphic-segmentation": { "name": "@cornerstonejs/polymorphic-segmentation", - "version": "3.0.4", + "version": "3.0.5", "dependencies": { "@icr/polyseg-wasm": "0.4.0", }, @@ -270,7 +270,7 @@ }, "packages/tools": { "name": "@cornerstonejs/tools", - "version": "3.0.4", + "version": "3.0.5", "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "^4.4.1", @@ -280,7 +280,7 @@ "canvas": "^2.11.2", }, "peerDependencies": { - "@cornerstonejs/core": "^3.0.4", + "@cornerstonejs/core": "^3.0.5", "@kitware/vtk.js": "32.9.0", "@types/d3-array": "^3.0.4", "@types/d3-interpolate": "^3.0.1", @@ -1233,29 +1233,29 @@ "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.13.0", "", { "os": "linux", "cpu": "x64" }, "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA=="], - "@rspack/binding": ["@rspack/binding@1.2.2", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.2.2", "@rspack/binding-darwin-x64": "1.2.2", "@rspack/binding-linux-arm64-gnu": "1.2.2", "@rspack/binding-linux-arm64-musl": "1.2.2", "@rspack/binding-linux-x64-gnu": "1.2.2", "@rspack/binding-linux-x64-musl": "1.2.2", "@rspack/binding-win32-arm64-msvc": "1.2.2", "@rspack/binding-win32-ia32-msvc": "1.2.2", "@rspack/binding-win32-x64-msvc": "1.2.2" } }, "sha512-GCZwpGFYlLTdJ2soPLwjw9z4LSZ+GdpbHNfBt3Cm/f/bAF8n6mZc7dHUqN893RFh7MPU17HNEL3fMw7XR+6pHg=="], + "@rspack/binding": ["@rspack/binding@1.2.7", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.2.7", "@rspack/binding-darwin-x64": "1.2.7", "@rspack/binding-linux-arm64-gnu": "1.2.7", "@rspack/binding-linux-arm64-musl": "1.2.7", "@rspack/binding-linux-x64-gnu": "1.2.7", "@rspack/binding-linux-x64-musl": "1.2.7", "@rspack/binding-win32-arm64-msvc": "1.2.7", "@rspack/binding-win32-ia32-msvc": "1.2.7", "@rspack/binding-win32-x64-msvc": "1.2.7" } }, "sha512-QH+kxkG0I9C6lmlwgBUDFsy24ihXMGG5lfiNtQilk4CyBN+AgSWFENcYrnkUaBioZAvMBznQLiccV3X0JeH9iQ=="], - "@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@1.2.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-h23F8zEkXWhwMeScm0ZnN78Zh7hCDalxIWsm7bBS0eKadnlegUDwwCF8WE+8NjWr7bRzv0p3QBWlS5ufkcL4eA=="], + "@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@1.2.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dT5eSMTknZaI8Djmz8KnaWM68rjZuBZwsKyF144o+ZSJM55vgiNXyL0lQYB8mX9nR3Gck+jKuGUAT2W/EF/t5Q=="], - "@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@1.2.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-vG5s7FkEvwrGLfksyDRHwKAHUkhZt1zHZZXJQn4gZKjTBonje8ezdc7IFlDiWpC4S+oBYp73nDWkUzkGRbSdcQ=="], + "@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@1.2.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-5n8IhKBxH71d4BUIvyzTwSOAOKNneLPJwLIphSPNIbCMGjLI59/EVpxSQ/AAUfyMkqOs635NNCn0eGQVuzpI/w=="], - "@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@1.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-VykY/kiYOzO8E1nYzfJ9+gQEHxb5B6lt5wa8M6xFi5B6jEGU+OsaGskmAZB9/GFImeFDHxDPvhUalI4R9p8O2Q=="], + "@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@1.2.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-DTtFBJmgQQrVWjbklpgJDr3kE9Uf1fHsPh+1GVslsBuyn+o4O7JslrnjuVsQCYKoiEg0Lg4ZPQmwnhJLHssZ5A=="], - "@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@1.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z5vAC4wGfXi8XXZ6hs8Q06TYjr3zHf819HB4DI5i4C1eQTeKdZSyoFD0NHFG23bP4NWJffp8KhmoObcy9jBT5Q=="], + "@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@1.2.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-01/OoQQF9eyDvRKkxj4DzCznfGZIvnzI8qOsrv+M7VBm8FLoKpb3hygXixaGQOXmNL42XTh61qjgm++fBu6aUA=="], - "@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@1.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-o3pDaL+cH5EeRbDE9gZcdZpBgp5iXvYZBBhe8vZQllYgI4zN5MJEuleV7WplG3UwTXlgZg3Kht4RORSOPn96vg=="], + "@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@1.2.7", "", { "os": "linux", "cpu": "x64" }, "sha512-lUOAUq0YSsofCXsP6XnlgfH0ZRDZ2X2XqXLXYjqf4xkSxCl5eBmE0EQYjAHF4zjUvU5rVx4a4bDLWv7+t3bOHg=="], - "@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@1.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-RE3e0xe4DdchHssttKzryDwjLkbrNk/4H59TkkWeGYJcLw41tmcOZVFQUOwKLUvXWVyif/vjvV/w1SMlqB4wQg=="], + "@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@1.2.7", "", { "os": "linux", "cpu": "x64" }, "sha512-ZrPXfgT30p4DlydYavaTHiluxHkWvZHt7K4q7qNyTfYYowG6jRGwWi/PATdugNICGv027Wsh5nzEO4o27Iuhwg=="], - "@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@1.2.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-R+PKBYn6uzTaDdVqTHvjqiJPBr5ZHg1wg5UmFDLNH9OklzVFyQh1JInSdJRb7lzfzTRz6bEkkwUFBPQK/CGScw=="], + "@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@1.2.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-1OzzM+OUSWX39XYcDfxJ8bGX5vNNrRejCMGotBEdP+uQ3KMWCPz0G4KRc3QIjghaLIYk3ofd83hcfUxyk/2Xog=="], - "@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@1.2.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-dBqz3sRAGZ2f31FgzKLDvIRfq2haRP3X3XVCT0PsiMcvt7QJng+26aYYMy2THatd/nM8IwExYeitHWeiMBoruw=="], + "@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@1.2.7", "", { "os": "win32", "cpu": "ia32" }, "sha512-VWlDCV9kDtijk9GK6ZtBQmYoVzKGpnrJB0iI3d2gIEa/2NwikJ89bLMFE4dFx8UNH3p/sSyb5pmPOQnbudFK7Q=="], - "@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@1.2.2", "", { "os": "win32", "cpu": "x64" }, "sha512-eeAvaN831KG553cMSHkVldyk6YQn4ujgRHov6r1wtREq7CD3/ka9LMkJUepCN85K7XtwYT0N4KpFIQyf5GTGoA=="], + "@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@1.2.7", "", { "os": "win32", "cpu": "x64" }, "sha512-l/sTdeMsQF1a1aB79cWykDNRZG6nkUA0biJo2/sEARP3ijdr8TuwUdirp2JRDmZfQJkoJnQ2un9y9qyW+TIZzA=="], - "@rspack/cli": ["@rspack/cli@1.2.2", "", { "dependencies": { "@discoveryjs/json-ext": "^0.5.7", "@rspack/dev-server": "1.0.10", "colorette": "2.0.19", "exit-hook": "^4.0.0", "interpret": "^3.1.1", "rechoir": "^0.8.0", "webpack-bundle-analyzer": "4.6.1", "yargs": "17.6.2" }, "peerDependencies": { "@rspack/core": "^1.0.0-alpha || ^1.x", "@rspack/tracing": "^1.x" }, "optionalPeers": ["@rspack/tracing"], "bin": { "rspack": "bin/rspack.js" } }, "sha512-d1wsIqmQHjqfo2KKx9TOOW7M4PnD2Viv9FbosXRW/lisvPFJUTwg87onv2x3z4KTCHqplH9T4MCeKmCj+ZNKOw=="], + "@rspack/cli": ["@rspack/cli@1.2.7", "", { "dependencies": { "@discoveryjs/json-ext": "^0.5.7", "@rspack/dev-server": "1.0.10", "colorette": "2.0.20", "exit-hook": "^4.0.0", "interpret": "^3.1.1", "rechoir": "^0.8.0", "webpack-bundle-analyzer": "4.6.1", "yargs": "17.7.2" }, "peerDependencies": { "@rspack/core": "^1.0.0-alpha || ^1.x", "@rspack/tracing": "^1.x" }, "optionalPeers": ["@rspack/tracing"], "bin": { "rspack": "bin/rspack.js" } }, "sha512-nUUZuwnSEORqPcknhP+gkQh9YZqeOlmFKJA1YRnZ5QQkzugCehV+xzVjO+Ezd8R1CSMpqdAQq7+pFZ8rpaRymA=="], - "@rspack/core": ["@rspack/core@1.2.2", "", { "dependencies": { "@module-federation/runtime-tools": "0.8.4", "@rspack/binding": "1.2.2", "@rspack/lite-tapable": "1.0.1", "caniuse-lite": "^1.0.30001616" }, "peerDependencies": { "@rspack/tracing": "^1.x", "@swc/helpers": ">=0.5.1" }, "optionalPeers": ["@rspack/tracing", "@swc/helpers"] }, "sha512-EeHAmY65Uj62hSbUKesbrcWGE7jfUI887RD03G++Gj8jS4WPHEu1TFODXNOXg6pa7zyIvs2BK0Bm16Kwz8AEaQ=="], + "@rspack/core": ["@rspack/core@1.2.7", "", { "dependencies": { "@module-federation/runtime-tools": "0.8.4", "@rspack/binding": "1.2.7", "@rspack/lite-tapable": "1.0.1", "caniuse-lite": "^1.0.30001700" }, "peerDependencies": { "@rspack/tracing": "^1.x", "@swc/helpers": ">=0.5.1" }, "optionalPeers": ["@rspack/tracing", "@swc/helpers"] }, "sha512-Vg7ySflnqI1nNOBPd6VJkQozWADssxn3einbxa9OqDVAB+dGSj8qihTs6rlaTSewidoaYTGIAiTMHO2y+61qqQ=="], "@rspack/dev-server": ["@rspack/dev-server@1.0.10", "", { "dependencies": { "chokidar": "^3.6.0", "connect-history-api-fallback": "^2.0.0", "express": "^4.19.2", "http-proxy-middleware": "^2.0.6", "mime-types": "^2.1.35", "p-retry": "4.6.2", "webpack-dev-middleware": "^7.4.2", "webpack-dev-server": "5.0.4", "ws": "^8.16.0" }, "peerDependencies": { "@rspack/core": "*" } }, "sha512-iDsEtP0jNHRm4LJxL00QFTlOuqkdxIFxnd69h0KrFadmtxAWiDLIe4vYdZXWF74w4MezsJFx6dB2nUM/Ok8utA=="], @@ -1973,7 +1973,7 @@ "caniuse-api": ["caniuse-api@3.0.0", "", { "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" } }, "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw=="], - "caniuse-lite": ["caniuse-lite@1.0.30001697", "", {}, "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001702", "", {}, "sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA=="], "canvas": ["canvas@2.11.2", "", { "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", "nan": "^2.17.0", "simple-get": "^3.0.3" } }, "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw=="], @@ -2073,7 +2073,7 @@ "colord": ["colord@2.9.3", "", {}, "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="], - "colorette": ["colorette@2.0.19", "", {}, "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="], + "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], "colormap": ["colormap@2.3.2", "", { "dependencies": { "lerp": "^1.0.3" } }, "sha512-jDOjaoEEmA9AgA11B/jCSAvYE95r3wRoAyTf3LEHGiUVlNHJaL1mRkf5AyLSpQBVGfTEPwGEqCIzL+kgr2WgNA=="], @@ -5323,7 +5323,7 @@ "yaml": ["yaml@2.3.1", "", {}, "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ=="], - "yargs": ["yargs@17.6.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw=="], + "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], @@ -5483,6 +5483,8 @@ "@docusaurus/core/webpack-merge": ["webpack-merge@6.0.1", "", { "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", "wildcard": "^2.0.1" } }, "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg=="], + "@docusaurus/faster/@rspack/core": ["@rspack/core@1.2.2", "", { "dependencies": { "@module-federation/runtime-tools": "0.8.4", "@rspack/binding": "1.2.2", "@rspack/lite-tapable": "1.0.1", "caniuse-lite": "^1.0.30001616" }, "peerDependencies": { "@rspack/tracing": "^1.x", "@swc/helpers": ">=0.5.1" }, "optionalPeers": ["@rspack/tracing", "@swc/helpers"] }, "sha512-EeHAmY65Uj62hSbUKesbrcWGE7jfUI887RD03G++Gj8jS4WPHEu1TFODXNOXg6pa7zyIvs2BK0Bm16Kwz8AEaQ=="], + "@docusaurus/faster/webpack": ["webpack@5.97.1", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.14.0", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.10", "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg=="], "@docusaurus/mdx-loader/fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="], @@ -5607,8 +5609,6 @@ "@lerna/create/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], - "@lerna/create/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "@mapbox/node-pre-gyp/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], "@mapbox/node-pre-gyp/make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="], @@ -5667,8 +5667,6 @@ "@netlify/build/typescript": ["typescript@5.7.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg=="], - "@netlify/build/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "@netlify/build-info/dot-prop": ["dot-prop@7.2.0", "", { "dependencies": { "type-fest": "^2.11.2" } }, "sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA=="], "@netlify/build-info/find-up": ["find-up@6.3.0", "", { "dependencies": { "locate-path": "^7.1.0", "path-exists": "^5.0.0" } }, "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw=="], @@ -5679,8 +5677,6 @@ "@netlify/build-info/yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="], - "@netlify/build-info/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "@netlify/cache-utils/path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="], "@netlify/config/chalk": ["chalk@5.3.0", "", {}, "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w=="], @@ -5701,8 +5697,6 @@ "@netlify/config/validate-npm-package-name": ["validate-npm-package-name@4.0.0", "", { "dependencies": { "builtins": "^5.0.0" } }, "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q=="], - "@netlify/config/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "@netlify/edge-bundler/esbuild": ["esbuild@0.21.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.2", "@esbuild/android-arm": "0.21.2", "@esbuild/android-arm64": "0.21.2", "@esbuild/android-x64": "0.21.2", "@esbuild/darwin-arm64": "0.21.2", "@esbuild/darwin-x64": "0.21.2", "@esbuild/freebsd-arm64": "0.21.2", "@esbuild/freebsd-x64": "0.21.2", "@esbuild/linux-arm": "0.21.2", "@esbuild/linux-arm64": "0.21.2", "@esbuild/linux-ia32": "0.21.2", "@esbuild/linux-loong64": "0.21.2", "@esbuild/linux-mips64el": "0.21.2", "@esbuild/linux-ppc64": "0.21.2", "@esbuild/linux-riscv64": "0.21.2", "@esbuild/linux-s390x": "0.21.2", "@esbuild/linux-x64": "0.21.2", "@esbuild/netbsd-x64": "0.21.2", "@esbuild/openbsd-x64": "0.21.2", "@esbuild/sunos-x64": "0.21.2", "@esbuild/win32-arm64": "0.21.2", "@esbuild/win32-ia32": "0.21.2", "@esbuild/win32-x64": "0.21.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-LmHPAa5h4tSxz+g/D8IHY6wCjtIiFx8I7/Q0Aq+NmvtoYvyMnJU0KQJcqB6QH30X9x/W4CemgUtPgQDZFca5SA=="], "@netlify/edge-bundler/execa": ["execa@6.1.0", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", "human-signals": "^3.0.1", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^3.0.7", "strip-final-newline": "^3.0.0" } }, "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA=="], @@ -5765,8 +5759,6 @@ "@netlify/zip-it-and-ship-it/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], - "@netlify/zip-it-and-ship-it/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "@nicolo-ribaudo/eslint-scope-5-internals/eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], "@npmcli/agent/http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], @@ -5885,6 +5877,8 @@ "are-we-there-yet/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + "autoprefixer/caniuse-lite": ["caniuse-lite@1.0.30001697", "", {}, "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ=="], + "axios/form-data": ["form-data@4.0.1", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw=="], "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -5911,6 +5905,8 @@ "brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "browserslist/caniuse-lite": ["caniuse-lite@1.0.30001697", "", {}, "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ=="], + "cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "cacheable-request/mimic-response": ["mimic-response@4.0.0", "", {}, "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg=="], @@ -5921,6 +5917,8 @@ "camelcase-keys/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], + "caniuse-api/caniuse-lite": ["caniuse-lite@1.0.30001697", "", {}, "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ=="], + "chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], @@ -6089,8 +6087,6 @@ "dpdm/typescript": ["typescript@5.7.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg=="], - "dpdm/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], "engine.io/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], @@ -6301,8 +6297,6 @@ "jest-circus/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - "jest-cli/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "jest-config/ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], "jest-config/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], @@ -6375,8 +6369,6 @@ "lerna/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], - "lerna/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "lightningcss/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], "lint-staged/chalk": ["chalk@5.3.0", "", {}, "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w=="], @@ -6389,8 +6381,6 @@ "listhen/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], - "listr2/colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - "listr2/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], "listr2/log-update": ["log-update@5.0.1", "", { "dependencies": { "ansi-escapes": "^5.0.0", "cli-cursor": "^4.0.0", "slice-ansi": "^5.0.0", "strip-ansi": "^7.0.1", "wrap-ansi": "^8.0.1" } }, "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw=="], @@ -6667,8 +6657,6 @@ "nx/yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="], - "nx/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], "p-event/p-timeout": ["p-timeout@5.1.0", "", {}, "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew=="], @@ -6985,7 +6973,9 @@ "webpack-bundle-analyzer/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], - "webpack-dev-middleware/colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], + "webpack-cli/colorette": ["colorette@2.0.19", "", {}, "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="], + + "webpack-dev-server/colorette": ["colorette@2.0.19", "", {}, "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="], "webpack-dev-server/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], @@ -7197,6 +7187,10 @@ "@docusaurus/core/webpack/schema-utils": ["schema-utils@3.3.0", "", { "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } }, "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg=="], + "@docusaurus/faster/@rspack/core/@rspack/binding": ["@rspack/binding@1.2.2", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.2.2", "@rspack/binding-darwin-x64": "1.2.2", "@rspack/binding-linux-arm64-gnu": "1.2.2", "@rspack/binding-linux-arm64-musl": "1.2.2", "@rspack/binding-linux-x64-gnu": "1.2.2", "@rspack/binding-linux-x64-musl": "1.2.2", "@rspack/binding-win32-arm64-msvc": "1.2.2", "@rspack/binding-win32-ia32-msvc": "1.2.2", "@rspack/binding-win32-x64-msvc": "1.2.2" } }, "sha512-GCZwpGFYlLTdJ2soPLwjw9z4LSZ+GdpbHNfBt3Cm/f/bAF8n6mZc7dHUqN893RFh7MPU17HNEL3fMw7XR+6pHg=="], + + "@docusaurus/faster/@rspack/core/caniuse-lite": ["caniuse-lite@1.0.30001697", "", {}, "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ=="], + "@docusaurus/faster/webpack/eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], "@docusaurus/faster/webpack/schema-utils": ["schema-utils@3.3.0", "", { "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } }, "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg=="], @@ -7315,8 +7309,6 @@ "@netlify/build/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - "@netlify/build/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "@netlify/config/dot-prop/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], "@netlify/config/execa/human-signals": ["human-signals@3.0.1", "", {}, "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ=="], @@ -7399,8 +7391,6 @@ "@netlify/functions-utils/@netlify/zip-it-and-ship-it/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], - "@netlify/functions-utils/@netlify/zip-it-and-ship-it/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "@netlify/git-utils/execa/human-signals": ["human-signals@3.0.1", "", {}, "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ=="], "@netlify/git-utils/micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -7479,10 +7469,10 @@ "@rspack/cli/webpack-bundle-analyzer/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], - "@rspack/dev-server/webpack-dev-middleware/colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - "@rspack/dev-server/webpack-dev-middleware/memfs": ["memfs@4.17.0", "", { "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", "@jsonjoy.com/util": "^1.3.0", "tree-dump": "^1.0.1", "tslib": "^2.0.0" } }, "sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg=="], + "@rspack/dev-server/webpack-dev-server/colorette": ["colorette@2.0.19", "", {}, "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="], + "@rspack/dev-server/webpack-dev-server/open": ["open@10.1.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw=="], "@rspack/dev-server/webpack-dev-server/p-retry": ["p-retry@6.2.1", "", { "dependencies": { "@types/retry": "0.12.2", "is-network-error": "^1.0.0", "retry": "^0.13.1" } }, "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ=="], @@ -7939,8 +7929,6 @@ "netlify-cli/listr2/cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="], - "netlify-cli/listr2/colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - "netlify-cli/listr2/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], "netlify-cli/listr2/wrap-ansi": ["wrap-ansi@9.0.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q=="], @@ -8385,6 +8373,24 @@ "@docusaurus/core/webpack/schema-utils/ajv-keywords": ["ajv-keywords@3.5.2", "", { "peerDependencies": { "ajv": "^6.9.1" } }, "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="], + "@docusaurus/faster/@rspack/core/@rspack/binding/@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@1.2.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-h23F8zEkXWhwMeScm0ZnN78Zh7hCDalxIWsm7bBS0eKadnlegUDwwCF8WE+8NjWr7bRzv0p3QBWlS5ufkcL4eA=="], + + "@docusaurus/faster/@rspack/core/@rspack/binding/@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@1.2.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-vG5s7FkEvwrGLfksyDRHwKAHUkhZt1zHZZXJQn4gZKjTBonje8ezdc7IFlDiWpC4S+oBYp73nDWkUzkGRbSdcQ=="], + + "@docusaurus/faster/@rspack/core/@rspack/binding/@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@1.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-VykY/kiYOzO8E1nYzfJ9+gQEHxb5B6lt5wa8M6xFi5B6jEGU+OsaGskmAZB9/GFImeFDHxDPvhUalI4R9p8O2Q=="], + + "@docusaurus/faster/@rspack/core/@rspack/binding/@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@1.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z5vAC4wGfXi8XXZ6hs8Q06TYjr3zHf819HB4DI5i4C1eQTeKdZSyoFD0NHFG23bP4NWJffp8KhmoObcy9jBT5Q=="], + + "@docusaurus/faster/@rspack/core/@rspack/binding/@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@1.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-o3pDaL+cH5EeRbDE9gZcdZpBgp5iXvYZBBhe8vZQllYgI4zN5MJEuleV7WplG3UwTXlgZg3Kht4RORSOPn96vg=="], + + "@docusaurus/faster/@rspack/core/@rspack/binding/@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@1.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-RE3e0xe4DdchHssttKzryDwjLkbrNk/4H59TkkWeGYJcLw41tmcOZVFQUOwKLUvXWVyif/vjvV/w1SMlqB4wQg=="], + + "@docusaurus/faster/@rspack/core/@rspack/binding/@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@1.2.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-R+PKBYn6uzTaDdVqTHvjqiJPBr5ZHg1wg5UmFDLNH9OklzVFyQh1JInSdJRb7lzfzTRz6bEkkwUFBPQK/CGScw=="], + + "@docusaurus/faster/@rspack/core/@rspack/binding/@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@1.2.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-dBqz3sRAGZ2f31FgzKLDvIRfq2haRP3X3XVCT0PsiMcvt7QJng+26aYYMy2THatd/nM8IwExYeitHWeiMBoruw=="], + + "@docusaurus/faster/@rspack/core/@rspack/binding/@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@1.2.2", "", { "os": "win32", "cpu": "x64" }, "sha512-eeAvaN831KG553cMSHkVldyk6YQn4ujgRHov6r1wtREq7CD3/ka9LMkJUepCN85K7XtwYT0N4KpFIQyf5GTGoA=="], + "@docusaurus/faster/webpack/eslint-scope/estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], "@docusaurus/faster/webpack/schema-utils/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], @@ -8449,10 +8455,6 @@ "@netlify/build/p-filter/p-map/aggregate-error": ["aggregate-error@4.0.1", "", { "dependencies": { "clean-stack": "^4.0.0", "indent-string": "^5.0.0" } }, "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w=="], - "@netlify/build/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@netlify/build/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "@netlify/functions-utils/@netlify/zip-it-and-ship-it/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g=="], "@netlify/functions-utils/@netlify/zip-it-and-ship-it/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.19.11", "", { "os": "android", "cpu": "arm" }, "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw=="],