@ohif/app 3.12.0-beta.114 → 3.12.0-beta.115

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/{2842.bundle.72b8e407027b26a34584.js → 2842.bundle.323078a1185dc9a58ac7.js} +80 -18
  2. package/dist/{5448.bundle.95f9ed97b8ab5ca9e6b0.js → 4410.bundle.09d2d3bfb23511a9a7d4.js} +202 -6
  3. package/dist/{5549.bundle.1a5e24f59873b7a30799.js → 5549.bundle.64c0f91bbed858352e1a.js} +93 -21
  4. package/dist/{7412.bundle.3256f92f3f2d6aa25008.js → 7412.bundle.3c1ced74bcd0c83da9fb.js} +13 -2
  5. package/dist/{7431.bundle.999b2b65d4973bc56218.js → 7431.bundle.d772d0b75ef6dc75acfc.js} +5 -3
  6. package/dist/{9195.bundle.0ebdd4b679ee7967a0e9.js → 9195.bundle.c4ecd0426003bf54fa27.js} +2 -2
  7. package/dist/{app.bundle.23afbbef42ad1c18e04f.js → app.bundle.cc8e10497cc52a5b4517.js} +270 -7
  8. package/dist/{compute.bundle.9d2a75c300c39d48be90.js → compute.bundle.85de00d380fec20ac4ac.js} +3 -3
  9. package/dist/index.html +1 -1
  10. package/dist/{polySeg.bundle.1cc6ecabd5fb8ab1d99c.js → polySeg.bundle.87769c9338f2425c7e65.js} +3 -3
  11. package/dist/sw.js +1 -1
  12. package/package.json +21 -21
  13. /package/dist/{1403.bundle.57cb00001011a891c721.js → 1403.bundle.c7510ca2f9816815d854.js} +0 -0
  14. /package/dist/{1459.bundle.b18c0c265cfdffc50ad4.js → 1459.bundle.349b9a5e41378937c2a0.js} +0 -0
  15. /package/dist/{147.bundle.ee7de13189cf1963aea9.js → 147.bundle.85a9ed9fd123f57f23a6.js} +0 -0
  16. /package/dist/{1730.bundle.fd7196fce95a907c02b2.js → 1730.bundle.23b516d3572a29f69191.js} +0 -0
  17. /package/dist/{1933.bundle.c0be85081628cbd5b634.js → 1933.bundle.ee2cbb7633385b57a124.js} +0 -0
  18. /package/dist/{2018.bundle.868c69572d25f819b8aa.js → 2018.bundle.0a9d421eef18675f2570.js} +0 -0
  19. /package/dist/{213.bundle.738f3f3bad9747d87251.js → 213.bundle.d9cf0851a89078267731.js} +0 -0
  20. /package/dist/{2424.bundle.608a0fedf823bc6d318d.js → 2424.bundle.b7786957ad05e682e872.js} +0 -0
  21. /package/dist/{3081.bundle.532a14bbf71da3f4f48c.js → 3081.bundle.277932a8223bd644f720.js} +0 -0
  22. /package/dist/{3353.bundle.7d5f628fe7eb8fe738ce.js → 3353.bundle.9d3e114b02d6fbbd927f.js} +0 -0
  23. /package/dist/{3461.bundle.f229ee13ccc18b7de681.js → 3461.bundle.64687760f02b384b93fc.js} +0 -0
  24. /package/dist/{3584.bundle.839a16d349815b3f7c97.js → 3584.bundle.318f292fda0d5e1f54df.js} +0 -0
  25. /package/dist/{4019.bundle.cdb81fb4777792f6175d.js → 4019.bundle.9f338ce1c5ae27f6eab5.js} +0 -0
  26. /package/dist/{4775.bundle.ce3cbcb52f3c118eb042.js → 4775.bundle.195c3d6c9d93cfd3c236.js} +0 -0
  27. /package/dist/{4819.bundle.6f0174dea6faae4b10ca.js → 4819.bundle.c9337e4eeb35e7750942.js} +0 -0
  28. /package/dist/{5028.bundle.25f0de3a61ba3a0efcf8.js → 5028.bundle.16d4386e6e1fbbc69138.js} +0 -0
  29. /package/dist/{5400.bundle.be4bdac337da734fdcd3.js → 5400.bundle.c1c101c5b66a1667bdfd.js} +0 -0
  30. /package/dist/{5457.bundle.8cbdf4da0e12f88f4010.js → 5457.bundle.a92e4cdcd0de91f7c076.js} +0 -0
  31. /package/dist/{5485.bundle.f96a631f8d341cb15cc3.js → 5485.bundle.9f2fd0dfd87210c63ca0.js} +0 -0
  32. /package/dist/{5802.bundle.aef18b250a1927d84108.js → 5802.bundle.aed34ddbad09f03edefe.js} +0 -0
  33. /package/dist/{6027.bundle.e4c090cb74a219798e83.js → 6027.bundle.3deea60831170d71b705.js} +0 -0
  34. /package/dist/{6163.bundle.ba7bd975bc702d2ea746.js → 6163.bundle.c3da0245099b42524e53.js} +0 -0
  35. /package/dist/{7639.bundle.7fdafc277c50936d40aa.js → 7639.bundle.ef13a3e705ab38a8c4a9.js} +0 -0
  36. /package/dist/{8305.bundle.abad864a52838a31af66.js → 8305.bundle.049b5a9184b32179af80.js} +0 -0
  37. /package/dist/{85.bundle.c05988a8c5ca1c644d91.js → 85.bundle.de4772507551aee94eb6.js} +0 -0
  38. /package/dist/{8558.bundle.b83784a541bed16b8b29.js → 8558.bundle.7232966d534bef02b1d6.js} +0 -0
  39. /package/dist/{8583.bundle.4d9bfa4b52e5fbf5cff4.js → 8583.bundle.31384271766bcea5e3a1.js} +0 -0
  40. /package/dist/{9862.bundle.2992313d0e19d394e6a5.js → 9862.bundle.2763343cffe86fcafa33.js} +0 -0
  41. /package/dist/{9927.bundle.2aad1abce48144437803.js → 9927.bundle.be81012ed537ef481ae3.js} +0 -0
@@ -351,7 +351,7 @@ __webpack_require__.d(__webpack_exports__, {
351
351
  volumeLoader: () => (/* reexport */ volumeLoader)
352
352
  });
353
353
 
354
- // UNUSED EXPORTS: BaseRenderingEngine, ContextPoolRenderingEngine, EPSILON, EVENTS, ImageVolume, ProgressiveRetrieveImages, RenderingEngine, Settings, StreamingDynamicImageVolume, StreamingImageVolume, Surface, TiledRenderingEngine, VideoViewport, Viewport, VolumeViewport3D, WSIViewport, canRenderFloatTextures, cornerstoneMeshLoader, cornerstoneStreamingDynamicImageVolumeLoader, cornerstoneStreamingImageVolumeLoader, createCanvas, createViewportElement, createVolumeMapper, geometryLoader, getConfiguration, getOrCreateCanvas, getShouldUseCPURendering, imageLoadPoolManager, imageLoader, imageRetrievalPoolManager, init, isCornerstoneInitialized, peerImport, registerImageLoader, requestPoolManager, resetInitialization, resetUseCPURendering, setCanvasCreator, setConfiguration, setPreferSizeOverAccuracy, setUseCPURendering, setVolumesForViewports, version
354
+ // UNUSED EXPORTS: BaseRenderingEngine, ContextPoolRenderingEngine, EPSILON, EVENTS, ImageVolume, ProgressiveRetrieveImages, RenderingEngine, Settings, StreamingDynamicImageVolume, StreamingImageVolume, Surface, TiledRenderingEngine, VideoViewport, Viewport, VolumeViewport3D, WSIViewport, canRenderFloatTextures, cornerstoneMeshLoader, cornerstoneStreamingDynamicImageVolumeLoader, cornerstoneStreamingImageVolumeLoader, createCanvas, createViewportElement, createVolumeMapper, decimatedVolumeLoader, geometryLoader, getConfiguration, getOrCreateCanvas, getShouldUseCPURendering, imageLoadPoolManager, imageLoader, imageRetrievalPoolManager, init, isCornerstoneInitialized, peerImport, registerImageLoader, requestPoolManager, resetInitialization, resetUseCPURendering, setCanvasCreator, setConfiguration, setPreferSizeOverAccuracy, setUseCPURendering, setVolumesForViewports, version
355
355
 
356
356
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/enums/index.js + 1 modules
357
357
  var enums = __webpack_require__(71851);
@@ -603,6 +603,8 @@ var imageLoader = __webpack_require__(80068);
603
603
  var geometryLoader = __webpack_require__(52269);
604
604
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/ProgressiveRetrieveImages.js + 4 modules
605
605
  var ProgressiveRetrieveImages = __webpack_require__(36822);
606
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/decimatedVolumeLoader.js + 3 modules
607
+ var decimatedVolumeLoader = __webpack_require__(18481);
606
608
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/index.js + 46 modules
607
609
  var utilities = __webpack_require__(33592);
608
610
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/triggerEvent.js
@@ -652,6 +654,8 @@ var helpers = __webpack_require__(40661);
652
654
 
653
655
 
654
656
 
657
+
658
+
655
659
 
656
660
 
657
661
 
@@ -2400,23 +2404,6 @@ function createSigmoidRGBTransferFunction(voiRange, approximationNodes = 1024) {
2400
2404
  }
2401
2405
 
2402
2406
 
2403
- /***/ }),
2404
-
2405
- /***/ 63470:
2406
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2407
-
2408
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2409
- /* harmony export */ A: () => (/* binding */ decimate)
2410
- /* harmony export */ });
2411
- function decimate(list, interleave, offset = 0) {
2412
- const interleaveIndices = [];
2413
- for (let i = offset; i < list.length; i += interleave) {
2414
- interleaveIndices.push(i);
2415
- }
2416
- return interleaveIndices;
2417
- }
2418
-
2419
-
2420
2407
  /***/ }),
2421
2408
 
2422
2409
  /***/ 99949:
@@ -3153,6 +3140,7 @@ __webpack_require__.d(__webpack_exports__, {
3153
3140
  deepMerge: () => (/* reexport */ deepMerge/* default */.A),
3154
3141
  eventListener: () => (/* reexport */ eventListener_namespaceObject),
3155
3142
  fnv1aHash: () => (/* reexport */ fnv1aHash/* default */.A),
3143
+ generateFrameImageId: () => (/* reexport */ generateFrameImageId),
3156
3144
  generateVolumePropsFromImageIds: () => (/* reexport */ generateVolumePropsFromImageIds/* generateVolumePropsFromImageIds */.D),
3157
3145
  genericMetadataProvider: () => (/* reexport */ genericMetadataProvider/* default */.A),
3158
3146
  getBufferConfiguration: () => (/* reexport */ getBufferConfiguration/* getBufferConfiguration */.h),
@@ -3184,6 +3172,7 @@ __webpack_require__.d(__webpack_exports__, {
3184
3172
  getVolumeSliceRangeInfo: () => (/* reexport */ getVolumeSliceRangeInfo/* default */.A),
3185
3173
  getVolumeViewportScrollInfo: () => (/* reexport */ getVolumeViewportScrollInfo/* default */.A),
3186
3174
  getVolumeViewportsContainingSameVolumes: () => (/* reexport */ utilities_getVolumeViewportsContainingSameVolumes),
3175
+ handleMultiframe4D: () => (/* reexport */ handleMultiframe4D),
3187
3176
  hasFloatScalingParameters: () => (/* reexport */ hasFloatScalingParameters/* hasFloatScalingParameters */.a),
3188
3177
  hasNaNValues: () => (/* reexport */ hasNaNValues/* default */.A),
3189
3178
  imageIdToURI: () => (/* reexport */ imageIdToURI/* default */.A),
@@ -4678,6 +4667,74 @@ function _getViewportModality(viewport, volumeId, getVolume) {
4678
4667
 
4679
4668
  ;// ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/splitImageIdsBy4DTags.js
4680
4669
 
4670
+ function generateFrameImageId(baseImageId, frameNumber) {
4671
+ const framePattern = /\/frames\/\d+/;
4672
+ if (!framePattern.test(baseImageId)) {
4673
+ throw new Error(`generateFrameImageId: baseImageId must contain a "/frames/" pattern followed by a digit. ` +
4674
+ `Expected format: e.g., "wadouri:http://example.com/image/frames/1" or "wadors:/path/to/image.dcm/frames/1". ` +
4675
+ `Received: ${baseImageId}`);
4676
+ }
4677
+ return baseImageId.replace(framePattern, `/frames/${frameNumber}`);
4678
+ }
4679
+ function handleMultiframe4D(imageIds) {
4680
+ if (!imageIds || imageIds.length === 0) {
4681
+ return null;
4682
+ }
4683
+ const baseImageId = imageIds[0];
4684
+ const instance = metaData.get('instance', baseImageId);
4685
+ if (!instance) {
4686
+ return null;
4687
+ }
4688
+ const numberOfFrames = instance.NumberOfFrames;
4689
+ if (!numberOfFrames || numberOfFrames <= 1) {
4690
+ return null;
4691
+ }
4692
+ const timeSlotVector = instance.TimeSlotVector;
4693
+ if (!timeSlotVector || !Array.isArray(timeSlotVector)) {
4694
+ return null;
4695
+ }
4696
+ const sliceVector = instance.SliceVector;
4697
+ const numberOfSlices = instance.NumberOfSlices;
4698
+ if (timeSlotVector.length !== numberOfFrames) {
4699
+ console.warn('TimeSlotVector length does not match NumberOfFrames:', timeSlotVector.length, 'vs', numberOfFrames);
4700
+ return null;
4701
+ }
4702
+ if (sliceVector) {
4703
+ if (!Array.isArray(sliceVector)) {
4704
+ console.warn('SliceVector exists but is not an array. Expected length:', numberOfFrames);
4705
+ return null;
4706
+ }
4707
+ if (sliceVector.length !== numberOfFrames ||
4708
+ sliceVector.some((val) => val === undefined)) {
4709
+ console.warn('SliceVector exists but has invalid length or undefined entries. Expected length:', numberOfFrames, 'Actual length:', sliceVector.length);
4710
+ return null;
4711
+ }
4712
+ }
4713
+ const timeSlotGroups = new Map();
4714
+ for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
4715
+ const timeSlot = timeSlotVector[frameIndex];
4716
+ const sliceIndex = sliceVector?.[frameIndex] ?? frameIndex;
4717
+ if (!timeSlotGroups.has(timeSlot)) {
4718
+ timeSlotGroups.set(timeSlot, []);
4719
+ }
4720
+ timeSlotGroups.get(timeSlot).push({ frameIndex, sliceIndex });
4721
+ }
4722
+ const sortedTimeSlots = Array.from(timeSlotGroups.keys()).sort((a, b) => a - b);
4723
+ const imageIdGroups = sortedTimeSlots.map((timeSlot) => {
4724
+ const frames = timeSlotGroups.get(timeSlot);
4725
+ frames.sort((a, b) => a.sliceIndex - b.sliceIndex);
4726
+ return frames.map((frame) => generateFrameImageId(baseImageId, frame.frameIndex + 1));
4727
+ });
4728
+ const expectedSlicesPerTimeSlot = numberOfSlices || imageIdGroups[0]?.length;
4729
+ const allGroupsHaveSameLength = imageIdGroups.every((group) => group.length === expectedSlicesPerTimeSlot);
4730
+ if (!allGroupsHaveSameLength) {
4731
+ console.warn('Multiframe 4D split resulted in uneven time slot groups. Expected', expectedSlicesPerTimeSlot, 'slices per time slot.');
4732
+ }
4733
+ return {
4734
+ imageIdGroups,
4735
+ splittingTag: 'TimeSlotVector',
4736
+ };
4737
+ }
4681
4738
  const groupBy = (array, key) => {
4682
4739
  return array.reduce((rv, x) => {
4683
4740
  (rv[x[key]] = rv[x[key]] || []).push(x);
@@ -4799,6 +4856,10 @@ function getPetFrameReferenceTime(imageId) {
4799
4856
  return moduleInfo ? moduleInfo['frameReferenceTime'] : 0;
4800
4857
  }
4801
4858
  function splitImageIdsBy4DTags(imageIds) {
4859
+ const multiframeResult = handleMultiframe4D(imageIds);
4860
+ if (multiframeResult) {
4861
+ return multiframeResult;
4862
+ }
4802
4863
  const positionGroups = getIPPGroups(imageIds);
4803
4864
  if (!positionGroups) {
4804
4865
  return { imageIdGroups: [imageIds], splittingTag: null };
@@ -4839,6 +4900,7 @@ function splitImageIdsBy4DTags(imageIds) {
4839
4900
  }
4840
4901
  /* harmony default export */ const utilities_splitImageIdsBy4DTags = (splitImageIdsBy4DTags);
4841
4902
 
4903
+
4842
4904
  ;// ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/getDynamicVolumeInfo.js
4843
4905
 
4844
4906
  function getDynamicVolumeInfo(imageIds) {
@@ -1,4 +1,4 @@
1
- (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[5448],{
1
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[4410],{
2
2
 
3
3
  /***/ 86871:
4
4
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
@@ -1559,6 +1559,7 @@ class BaseVolumeViewport extends Viewport/* default */.A {
1559
1559
  colormap,
1560
1560
  preset,
1561
1561
  slabThickness,
1562
+ sampleDistanceMultiplier,
1562
1563
  });
1563
1564
  }
1564
1565
  if (invert !== undefined && this.viewportProperties.invert !== invert) {
@@ -19589,8 +19590,8 @@ class BaseStreamingImageVolume extends _ImageVolume__WEBPACK_IMPORTED_MODULE_9__
19589
19590
  }
19590
19591
  getLoaderImageOptions(imageId) {
19591
19592
  const { transferSyntaxUID: transferSyntaxUID } = _metaData__WEBPACK_IMPORTED_MODULE_0__.get('transferSyntax', imageId) || {};
19592
- const imagePlaneModule = _metaData__WEBPACK_IMPORTED_MODULE_0__.get('imagePlaneModule', imageId) || {};
19593
- const { rows, columns } = imagePlaneModule;
19593
+ const targetRows = this.dimensions[1];
19594
+ const targetCols = this.dimensions[0];
19594
19595
  const imageIdIndex = this.getImageIdIndex(imageId);
19595
19596
  const modalityLutModule = _metaData__WEBPACK_IMPORTED_MODULE_0__.get('modalityLutModule', imageId) || {};
19596
19597
  const generalSeriesModule = _metaData__WEBPACK_IMPORTED_MODULE_0__.get('generalSeriesModule', imageId) || {};
@@ -19623,8 +19624,8 @@ class BaseStreamingImageVolume extends _ImageVolume__WEBPACK_IMPORTED_MODULE_9__
19623
19624
  }
19624
19625
  const targetBuffer = {
19625
19626
  type: this.dataType,
19626
- rows,
19627
- columns,
19627
+ rows: targetRows,
19628
+ columns: targetCols,
19628
19629
  };
19629
19630
  return {
19630
19631
  targetBuffer,
@@ -25491,6 +25492,183 @@ function cornerstoneStreamingImageVolumeLoader(volumeId, options) {
25491
25492
 
25492
25493
 
25493
25494
 
25495
+ /***/ }),
25496
+
25497
+ /***/ 18481:
25498
+ /***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {
25499
+
25500
+ "use strict";
25501
+
25502
+ // UNUSED EXPORTS: decimatedVolumeLoader, default
25503
+
25504
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/cache/classes/StreamingImageVolume.js
25505
+ var classes_StreamingImageVolume = __webpack_require__(50180);
25506
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/generateVolumePropsFromImageIds.js
25507
+ var utilities_generateVolumePropsFromImageIds = __webpack_require__(9734);
25508
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/decimate.js
25509
+ var utilities_decimate = __webpack_require__(63470);
25510
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/VoxelManager.js
25511
+ var utilities_VoxelManager = __webpack_require__(24623);
25512
+ ;// ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/decimatedVolumeModifiers/applyDecimatedVolumeModifiers.js
25513
+ function applyDecimatedVolumeModifiers_applyDecimatedVolumeModifiers(baseProps, modifiers, context) {
25514
+ return modifiers.reduce((currentProps, modifier) => modifier.apply(currentProps, context), baseProps);
25515
+ }
25516
+
25517
+ ;// ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/decimatedVolumeModifiers/inPlaneDecimationModifier.js
25518
+ const inPlaneDecimationModifier_inPlaneDecimationModifier = {
25519
+ name: 'InPlaneDecimationModifier',
25520
+ apply(volumeProps, context) {
25521
+ const [iDecimation = 1, jDecimation = iDecimation] = context.options.ijkDecimation ?? [];
25522
+ const columnFactor = Math.max(1, Math.floor(iDecimation));
25523
+ const rowFactor = Math.max(1, Math.floor(jDecimation));
25524
+ if (columnFactor === 1 && rowFactor === 1) {
25525
+ return volumeProps;
25526
+ }
25527
+ const [columns, rows] = volumeProps.dimensions;
25528
+ const newColumns = Math.max(1, Math.floor(columns / columnFactor));
25529
+ const newRows = Math.max(1, Math.floor(rows / rowFactor));
25530
+ const newDimensions = [
25531
+ newColumns,
25532
+ newRows,
25533
+ volumeProps.dimensions[2],
25534
+ ];
25535
+ const newSpacing = [
25536
+ volumeProps.spacing[0] * columnFactor,
25537
+ volumeProps.spacing[1] * rowFactor,
25538
+ volumeProps.spacing[2],
25539
+ ];
25540
+ const metadata = {
25541
+ ...volumeProps.metadata,
25542
+ Columns: newColumns,
25543
+ Rows: newRows,
25544
+ PixelSpacing: [newSpacing[1], newSpacing[0]],
25545
+ };
25546
+ return {
25547
+ ...volumeProps,
25548
+ dimensions: newDimensions,
25549
+ spacing: newSpacing,
25550
+ metadata,
25551
+ };
25552
+ },
25553
+ };
25554
+
25555
+ ;// ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/decimatedVolumeModifiers/index.js
25556
+
25557
+
25558
+
25559
+ ;// ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/decimatedVolumeLoader.js
25560
+
25561
+
25562
+
25563
+
25564
+
25565
+ function decimatedVolumeLoader(volumeId, options) {
25566
+ if (!options || !options.imageIds || !options.imageIds.length) {
25567
+ throw new Error('ImageIds must be provided to create a streaming image volume ');
25568
+ }
25569
+ const [iDecimation = 1, jDecimation = iDecimation, kDecimation = 1] = options.ijkDecimation ?? [];
25570
+ const columnDecimation = Math.max(1, Math.floor(iDecimation));
25571
+ const rowDecimation = jDecimation > 1 ? Math.max(1, Math.floor(jDecimation)) : columnDecimation;
25572
+ const kAxisDecimation = Math.max(1, Math.floor(kDecimation));
25573
+ const hasInPlaneDecimation = columnDecimation > 1 || rowDecimation > 1;
25574
+ const modifierOptions = {
25575
+ ijkDecimation: [
25576
+ columnDecimation,
25577
+ rowDecimation,
25578
+ kAxisDecimation,
25579
+ ],
25580
+ };
25581
+ const modifiers = [inPlaneDecimationModifier];
25582
+ function addDecimationToImageId(imageId, factor) {
25583
+ if (factor === 1) {
25584
+ return imageId;
25585
+ }
25586
+ return `${imageId}#decimation=${factor}`;
25587
+ }
25588
+ const expectedDecimatedCount = Math.floor(options.imageIds.length / kAxisDecimation);
25589
+ const isAlreadyDecimated = kAxisDecimation > 1 &&
25590
+ options.imageIds.length <= expectedDecimatedCount + 1;
25591
+ if (kAxisDecimation > 1 && !isAlreadyDecimated) {
25592
+ const decimatedResult = decimate(options.imageIds, kAxisDecimation);
25593
+ const decimatedImageIds = Array.isArray(decimatedResult) &&
25594
+ decimatedResult.length &&
25595
+ typeof decimatedResult[0] === 'number'
25596
+ ? decimatedResult.map((idx) => options.imageIds[idx])
25597
+ : decimatedResult;
25598
+ options.imageIds = decimatedImageIds;
25599
+ }
25600
+ if (columnDecimation > 1) {
25601
+ options.imageIds = options.imageIds.map((imageId) => addDecimationToImageId(imageId, columnDecimation));
25602
+ }
25603
+ async function getStreamingImageVolume() {
25604
+ const baseVolumeProps = generateVolumePropsFromImageIds(options.imageIds, volumeId);
25605
+ const modifierContext = {
25606
+ volumeId,
25607
+ imageIds: options.imageIds,
25608
+ options: modifierOptions,
25609
+ };
25610
+ const volumeProps = applyDecimatedVolumeModifiers(baseVolumeProps, modifiers, modifierContext);
25611
+ const { dimensions, spacing, origin, direction, metadata, imageIds, dataType, numberOfComponents, } = volumeProps;
25612
+ const streamingImageVolume = new StreamingImageVolume({
25613
+ volumeId,
25614
+ metadata,
25615
+ dimensions,
25616
+ spacing,
25617
+ origin,
25618
+ direction,
25619
+ imageIds,
25620
+ dataType,
25621
+ numberOfComponents,
25622
+ }, {
25623
+ imageIds,
25624
+ loadStatus: {
25625
+ loaded: false,
25626
+ loading: false,
25627
+ cancelled: false,
25628
+ cachedFrames: [],
25629
+ callbacks: [],
25630
+ },
25631
+ });
25632
+ if (hasInPlaneDecimation) {
25633
+ const vtkImageData = streamingImageVolume.imageData;
25634
+ if (vtkImageData) {
25635
+ vtkImageData.setDimensions(streamingImageVolume.dimensions);
25636
+ vtkImageData.setSpacing(streamingImageVolume.spacing);
25637
+ vtkImageData.modified();
25638
+ }
25639
+ const newVoxelManager = VoxelManager.createImageVolumeVoxelManager({
25640
+ dimensions: streamingImageVolume.dimensions,
25641
+ imageIds: streamingImageVolume.imageIds,
25642
+ numberOfComponents: numberOfComponents,
25643
+ });
25644
+ streamingImageVolume.voxelManager = newVoxelManager;
25645
+ if (vtkImageData) {
25646
+ vtkImageData.set({
25647
+ voxelManager: newVoxelManager,
25648
+ });
25649
+ }
25650
+ }
25651
+ return streamingImageVolume;
25652
+ }
25653
+ const streamingImageVolumePromise = getStreamingImageVolume();
25654
+ return {
25655
+ promise: streamingImageVolumePromise,
25656
+ decache: () => {
25657
+ streamingImageVolumePromise.then((streamingImageVolume) => {
25658
+ streamingImageVolume.destroy();
25659
+ streamingImageVolume = null;
25660
+ });
25661
+ },
25662
+ cancel: () => {
25663
+ streamingImageVolumePromise.then((streamingImageVolume) => {
25664
+ streamingImageVolume.cancelLoading();
25665
+ });
25666
+ },
25667
+ };
25668
+ }
25669
+ /* harmony default export */ const loaders_decimatedVolumeLoader = ((/* unused pure expression or super */ null && (decimatedVolumeLoader)));
25670
+
25671
+
25494
25672
  /***/ }),
25495
25673
 
25496
25674
  /***/ 52269:
@@ -34963,6 +35141,24 @@ function createPositionCallback(imageData) {
34963
35141
  }
34964
35142
 
34965
35143
 
35144
+ /***/ }),
35145
+
35146
+ /***/ 63470:
35147
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
35148
+
35149
+ "use strict";
35150
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
35151
+ /* harmony export */ A: () => (/* binding */ decimate)
35152
+ /* harmony export */ });
35153
+ function decimate(list, interleave, offset = 0) {
35154
+ const interleaveIndices = [];
35155
+ for (let i = offset; i < list.length; i += interleave) {
35156
+ interleaveIndices.push(i);
35157
+ }
35158
+ return interleaveIndices;
35159
+ }
35160
+
35161
+
34966
35162
  /***/ }),
34967
35163
 
34968
35164
  /***/ 74268:
@@ -35293,7 +35489,7 @@ function uuidv4() {
35293
35489
 
35294
35490
  "use strict";
35295
35491
  /* unused harmony export version */
35296
- const version = '4.14.6';
35492
+ const version = '4.15.2';
35297
35493
 
35298
35494
 
35299
35495
  /***/ }),
@@ -366,7 +366,7 @@ __webpack_require__.d(__webpack_exports__, {
366
366
  volumeLoader: () => (/* reexport */ volumeLoader)
367
367
  });
368
368
 
369
- // UNUSED EXPORTS: BaseRenderingEngine, ContextPoolRenderingEngine, EVENTS, ProgressiveRetrieveImages, RenderingEngine, StreamingDynamicImageVolume, StreamingImageVolume, Surface, TiledRenderingEngine, VideoViewport, Viewport, VolumeViewport3D, WSIViewport, canRenderFloatTextures, cornerstoneMeshLoader, cornerstoneStreamingDynamicImageVolumeLoader, cornerstoneStreamingImageVolumeLoader, createCanvas, createViewportElement, createVolumeMapper, geometryLoader, getOrCreateCanvas, getShouldUseCPURendering, imageRetrievalPoolManager, init, isCornerstoneInitialized, peerImport, registerImageLoader, requestPoolManager, resetInitialization, resetUseCPURendering, setCanvasCreator, setConfiguration, setPreferSizeOverAccuracy, setUseCPURendering, setVolumesForViewports, version
369
+ // UNUSED EXPORTS: BaseRenderingEngine, ContextPoolRenderingEngine, EVENTS, ProgressiveRetrieveImages, RenderingEngine, StreamingDynamicImageVolume, StreamingImageVolume, Surface, TiledRenderingEngine, VideoViewport, Viewport, VolumeViewport3D, WSIViewport, canRenderFloatTextures, cornerstoneMeshLoader, cornerstoneStreamingDynamicImageVolumeLoader, cornerstoneStreamingImageVolumeLoader, createCanvas, createViewportElement, createVolumeMapper, decimatedVolumeLoader, geometryLoader, getOrCreateCanvas, getShouldUseCPURendering, imageRetrievalPoolManager, init, isCornerstoneInitialized, peerImport, registerImageLoader, requestPoolManager, resetInitialization, resetUseCPURendering, setCanvasCreator, setConfiguration, setPreferSizeOverAccuracy, setUseCPURendering, setVolumesForViewports, version
370
370
 
371
371
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/enums/index.js + 1 modules
372
372
  var enums = __webpack_require__(71851);
@@ -618,6 +618,8 @@ var imageLoader = __webpack_require__(80068);
618
618
  var geometryLoader = __webpack_require__(52269);
619
619
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/ProgressiveRetrieveImages.js + 4 modules
620
620
  var ProgressiveRetrieveImages = __webpack_require__(36822);
621
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/decimatedVolumeLoader.js + 3 modules
622
+ var decimatedVolumeLoader = __webpack_require__(18481);
621
623
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/index.js + 46 modules
622
624
  var utilities = __webpack_require__(33592);
623
625
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/triggerEvent.js
@@ -667,6 +669,8 @@ var helpers = __webpack_require__(40661);
667
669
 
668
670
 
669
671
 
672
+
673
+
670
674
 
671
675
 
672
676
 
@@ -2439,24 +2443,6 @@ function createSigmoidRGBTransferFunction(voiRange, approximationNodes = 1024) {
2439
2443
  }
2440
2444
 
2441
2445
 
2442
- /***/ }),
2443
-
2444
- /***/ 63470:
2445
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2446
-
2447
- "use strict";
2448
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2449
- /* harmony export */ A: () => (/* binding */ decimate)
2450
- /* harmony export */ });
2451
- function decimate(list, interleave, offset = 0) {
2452
- const interleaveIndices = [];
2453
- for (let i = offset; i < list.length; i += interleave) {
2454
- interleaveIndices.push(i);
2455
- }
2456
- return interleaveIndices;
2457
- }
2458
-
2459
-
2460
2446
  /***/ }),
2461
2447
 
2462
2448
  /***/ 99949:
@@ -3213,6 +3199,7 @@ __webpack_require__.d(__webpack_exports__, {
3213
3199
  deepMerge: () => (/* reexport */ deepMerge/* default */.A),
3214
3200
  eventListener: () => (/* reexport */ eventListener_namespaceObject),
3215
3201
  fnv1aHash: () => (/* reexport */ fnv1aHash/* default */.A),
3202
+ generateFrameImageId: () => (/* reexport */ generateFrameImageId),
3216
3203
  generateVolumePropsFromImageIds: () => (/* reexport */ generateVolumePropsFromImageIds/* generateVolumePropsFromImageIds */.D),
3217
3204
  genericMetadataProvider: () => (/* reexport */ genericMetadataProvider/* default */.A),
3218
3205
  getBufferConfiguration: () => (/* reexport */ getBufferConfiguration/* getBufferConfiguration */.h),
@@ -3244,6 +3231,7 @@ __webpack_require__.d(__webpack_exports__, {
3244
3231
  getVolumeSliceRangeInfo: () => (/* reexport */ getVolumeSliceRangeInfo/* default */.A),
3245
3232
  getVolumeViewportScrollInfo: () => (/* reexport */ getVolumeViewportScrollInfo/* default */.A),
3246
3233
  getVolumeViewportsContainingSameVolumes: () => (/* reexport */ utilities_getVolumeViewportsContainingSameVolumes),
3234
+ handleMultiframe4D: () => (/* reexport */ handleMultiframe4D),
3247
3235
  hasFloatScalingParameters: () => (/* reexport */ hasFloatScalingParameters/* hasFloatScalingParameters */.a),
3248
3236
  hasNaNValues: () => (/* reexport */ hasNaNValues/* default */.A),
3249
3237
  imageIdToURI: () => (/* reexport */ imageIdToURI/* default */.A),
@@ -4738,6 +4726,74 @@ function _getViewportModality(viewport, volumeId, getVolume) {
4738
4726
 
4739
4727
  ;// ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/splitImageIdsBy4DTags.js
4740
4728
 
4729
+ function generateFrameImageId(baseImageId, frameNumber) {
4730
+ const framePattern = /\/frames\/\d+/;
4731
+ if (!framePattern.test(baseImageId)) {
4732
+ throw new Error(`generateFrameImageId: baseImageId must contain a "/frames/" pattern followed by a digit. ` +
4733
+ `Expected format: e.g., "wadouri:http://example.com/image/frames/1" or "wadors:/path/to/image.dcm/frames/1". ` +
4734
+ `Received: ${baseImageId}`);
4735
+ }
4736
+ return baseImageId.replace(framePattern, `/frames/${frameNumber}`);
4737
+ }
4738
+ function handleMultiframe4D(imageIds) {
4739
+ if (!imageIds || imageIds.length === 0) {
4740
+ return null;
4741
+ }
4742
+ const baseImageId = imageIds[0];
4743
+ const instance = metaData.get('instance', baseImageId);
4744
+ if (!instance) {
4745
+ return null;
4746
+ }
4747
+ const numberOfFrames = instance.NumberOfFrames;
4748
+ if (!numberOfFrames || numberOfFrames <= 1) {
4749
+ return null;
4750
+ }
4751
+ const timeSlotVector = instance.TimeSlotVector;
4752
+ if (!timeSlotVector || !Array.isArray(timeSlotVector)) {
4753
+ return null;
4754
+ }
4755
+ const sliceVector = instance.SliceVector;
4756
+ const numberOfSlices = instance.NumberOfSlices;
4757
+ if (timeSlotVector.length !== numberOfFrames) {
4758
+ console.warn('TimeSlotVector length does not match NumberOfFrames:', timeSlotVector.length, 'vs', numberOfFrames);
4759
+ return null;
4760
+ }
4761
+ if (sliceVector) {
4762
+ if (!Array.isArray(sliceVector)) {
4763
+ console.warn('SliceVector exists but is not an array. Expected length:', numberOfFrames);
4764
+ return null;
4765
+ }
4766
+ if (sliceVector.length !== numberOfFrames ||
4767
+ sliceVector.some((val) => val === undefined)) {
4768
+ console.warn('SliceVector exists but has invalid length or undefined entries. Expected length:', numberOfFrames, 'Actual length:', sliceVector.length);
4769
+ return null;
4770
+ }
4771
+ }
4772
+ const timeSlotGroups = new Map();
4773
+ for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
4774
+ const timeSlot = timeSlotVector[frameIndex];
4775
+ const sliceIndex = sliceVector?.[frameIndex] ?? frameIndex;
4776
+ if (!timeSlotGroups.has(timeSlot)) {
4777
+ timeSlotGroups.set(timeSlot, []);
4778
+ }
4779
+ timeSlotGroups.get(timeSlot).push({ frameIndex, sliceIndex });
4780
+ }
4781
+ const sortedTimeSlots = Array.from(timeSlotGroups.keys()).sort((a, b) => a - b);
4782
+ const imageIdGroups = sortedTimeSlots.map((timeSlot) => {
4783
+ const frames = timeSlotGroups.get(timeSlot);
4784
+ frames.sort((a, b) => a.sliceIndex - b.sliceIndex);
4785
+ return frames.map((frame) => generateFrameImageId(baseImageId, frame.frameIndex + 1));
4786
+ });
4787
+ const expectedSlicesPerTimeSlot = numberOfSlices || imageIdGroups[0]?.length;
4788
+ const allGroupsHaveSameLength = imageIdGroups.every((group) => group.length === expectedSlicesPerTimeSlot);
4789
+ if (!allGroupsHaveSameLength) {
4790
+ console.warn('Multiframe 4D split resulted in uneven time slot groups. Expected', expectedSlicesPerTimeSlot, 'slices per time slot.');
4791
+ }
4792
+ return {
4793
+ imageIdGroups,
4794
+ splittingTag: 'TimeSlotVector',
4795
+ };
4796
+ }
4741
4797
  const groupBy = (array, key) => {
4742
4798
  return array.reduce((rv, x) => {
4743
4799
  (rv[x[key]] = rv[x[key]] || []).push(x);
@@ -4859,6 +4915,10 @@ function getPetFrameReferenceTime(imageId) {
4859
4915
  return moduleInfo ? moduleInfo['frameReferenceTime'] : 0;
4860
4916
  }
4861
4917
  function splitImageIdsBy4DTags(imageIds) {
4918
+ const multiframeResult = handleMultiframe4D(imageIds);
4919
+ if (multiframeResult) {
4920
+ return multiframeResult;
4921
+ }
4862
4922
  const positionGroups = getIPPGroups(imageIds);
4863
4923
  if (!positionGroups) {
4864
4924
  return { imageIdGroups: [imageIds], splittingTag: null };
@@ -4899,6 +4959,7 @@ function splitImageIdsBy4DTags(imageIds) {
4899
4959
  }
4900
4960
  /* harmony default export */ const utilities_splitImageIdsBy4DTags = (splitImageIdsBy4DTags);
4901
4961
 
4962
+
4902
4963
  ;// ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/getDynamicVolumeInfo.js
4903
4964
 
4904
4965
  function getDynamicVolumeInfo(imageIds) {
@@ -6975,7 +7036,7 @@ var COLOR_LUT = __webpack_require__(93952);
6975
7036
 
6976
7037
 
6977
7038
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/version.js
6978
- const version = '4.14.6';
7039
+ const version = '4.15.2';
6979
7040
 
6980
7041
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/synchronizers/callbacks/cameraSyncCallback.js
6981
7042
 
@@ -26766,6 +26827,17 @@ class RegionSegmentTool extends GrowCutBaseTool/* default */.A {
26766
26827
  }
26767
26828
  async getGrowCutLabelmap(growCutData) {
26768
26829
  const { segmentation: { referencedVolumeId }, renderingEngineId, viewportId, circleCenterPoint, circleBorderPoint, options, } = growCutData;
26830
+ const { positiveSeedVariance, negativeSeedVariance, positiveStdDevMultiplier, } = this.configuration;
26831
+ const baseStdDevMultiplier = positiveStdDevMultiplier ?? 1;
26832
+ const currentStdDevMultiplier = options?.positiveStdDevMultiplier
26833
+ ? Math.max(options.positiveStdDevMultiplier, 0.01)
26834
+ : baseStdDevMultiplier;
26835
+ const varianceScale = currentStdDevMultiplier / baseStdDevMultiplier;
26836
+ const growCutOptions = {
26837
+ ...options,
26838
+ positiveSeedVariance: Math.max(0.01, (positiveSeedVariance ?? 1) * varianceScale),
26839
+ negativeSeedVariance: Math.max(0.01, (negativeSeedVariance ?? 1) * varianceScale),
26840
+ };
26769
26841
  const renderingEngine = (0,esm.getRenderingEngine)(renderingEngineId);
26770
26842
  const viewport = renderingEngine.getViewport(viewportId);
26771
26843
  const worldCircleRadius = gl_matrix_esm/* vec3.len */.eR.len(gl_matrix_esm/* vec3.sub */.eR.sub(gl_matrix_esm/* vec3.create */.eR.create(), circleCenterPoint, circleBorderPoint));
@@ -26773,7 +26845,7 @@ class RegionSegmentTool extends GrowCutBaseTool/* default */.A {
26773
26845
  center: circleCenterPoint,
26774
26846
  radius: worldCircleRadius,
26775
26847
  };
26776
- return segmentation.growCut.runGrowCutForSphere(referencedVolumeId, sphereInfo, viewport, options);
26848
+ return segmentation.growCut.runGrowCutForSphere(referencedVolumeId, sphereInfo, viewport, growCutOptions);
26777
26849
  }
26778
26850
  _activateDraw(element) {
26779
26851
  element.addEventListener(enums.Events.MOUSE_UP, this._endCallback);
@@ -25210,6 +25210,17 @@ class RegionSegmentTool extends _base_GrowCutBaseTool__WEBPACK_IMPORTED_MODULE_7
25210
25210
  }
25211
25211
  async getGrowCutLabelmap(growCutData) {
25212
25212
  const { segmentation: { referencedVolumeId }, renderingEngineId, viewportId, circleCenterPoint, circleBorderPoint, options, } = growCutData;
25213
+ const { positiveSeedVariance, negativeSeedVariance, positiveStdDevMultiplier, } = this.configuration;
25214
+ const baseStdDevMultiplier = positiveStdDevMultiplier ?? 1;
25215
+ const currentStdDevMultiplier = options?.positiveStdDevMultiplier
25216
+ ? Math.max(options.positiveStdDevMultiplier, 0.01)
25217
+ : baseStdDevMultiplier;
25218
+ const varianceScale = currentStdDevMultiplier / baseStdDevMultiplier;
25219
+ const growCutOptions = {
25220
+ ...options,
25221
+ positiveSeedVariance: Math.max(0.01, (positiveSeedVariance ?? 1) * varianceScale),
25222
+ negativeSeedVariance: Math.max(0.01, (negativeSeedVariance ?? 1) * varianceScale),
25223
+ };
25213
25224
  const renderingEngine = (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.getRenderingEngine)(renderingEngineId);
25214
25225
  const viewport = renderingEngine.getViewport(viewportId);
25215
25226
  const worldCircleRadius = gl_matrix__WEBPACK_IMPORTED_MODULE_0__/* .vec3.len */ .eR.len(gl_matrix__WEBPACK_IMPORTED_MODULE_0__/* .vec3.sub */ .eR.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__/* .vec3.create */ .eR.create(), circleCenterPoint, circleBorderPoint));
@@ -25217,7 +25228,7 @@ class RegionSegmentTool extends _base_GrowCutBaseTool__WEBPACK_IMPORTED_MODULE_7
25217
25228
  center: circleCenterPoint,
25218
25229
  radius: worldCircleRadius,
25219
25230
  };
25220
- return _utilities_segmentation__WEBPACK_IMPORTED_MODULE_6__.growCut.runGrowCutForSphere(referencedVolumeId, sphereInfo, viewport, options);
25231
+ return _utilities_segmentation__WEBPACK_IMPORTED_MODULE_6__.growCut.runGrowCutForSphere(referencedVolumeId, sphereInfo, viewport, growCutOptions);
25221
25232
  }
25222
25233
  _activateDraw(element) {
25223
25234
  element.addEventListener(_enums__WEBPACK_IMPORTED_MODULE_4__.Events.MOUSE_UP, this._endCallback);
@@ -44622,7 +44633,7 @@ __webpack_require__.r(__webpack_exports__);
44622
44633
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
44623
44634
  /* harmony export */ r: () => (/* binding */ version)
44624
44635
  /* harmony export */ });
44625
- const version = '4.14.6';
44636
+ const version = '4.15.2';
44626
44637
 
44627
44638
 
44628
44639
  /***/ }),
@@ -3548,9 +3548,11 @@ class MarkerLabelmapTool extends dist_esm.LabelmapBaseTool {
3548
3548
  /* harmony import */ var _cornerstoneStreamingImageVolumeLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55500);
3549
3549
  /* harmony import */ var _cornerstoneStreamingDynamicImageVolumeLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55509);
3550
3550
  /* harmony import */ var _cornerstoneMeshLoader__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(56074);
3551
- /* harmony import */ var _geometryLoader__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(52269);
3552
- /* harmony import */ var _imageLoader__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(80068);
3553
- /* harmony import */ var _volumeLoader__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(13466);
3551
+ /* harmony import */ var _decimatedVolumeLoader__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(18481);
3552
+ /* harmony import */ var _geometryLoader__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(52269);
3553
+ /* harmony import */ var _imageLoader__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(80068);
3554
+ /* harmony import */ var _volumeLoader__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(13466);
3555
+
3554
3556
 
3555
3557
 
3556
3558