@fideus-labs/ngff-zarr 0.1.0 → 0.2.0

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 (44) hide show
  1. package/README.md +1 -0
  2. package/esm/io/itk_image_to_ngff_image.d.ts +5 -0
  3. package/esm/io/itk_image_to_ngff_image.d.ts.map +1 -1
  4. package/esm/io/itk_image_to_ngff_image.js +20 -20
  5. package/esm/io/ngff_image_to_itk_image.d.ts.map +1 -1
  6. package/esm/io/ngff_image_to_itk_image.js +2 -0
  7. package/esm/io/to_multiscales.js +1 -1
  8. package/esm/io/to_ngff_zarr.js +16 -0
  9. package/esm/methods/itkwasm.d.ts.map +1 -1
  10. package/esm/methods/itkwasm.js +568 -426
  11. package/esm/schemas/coordinate_systems.d.ts +159 -552
  12. package/esm/schemas/coordinate_systems.d.ts.map +1 -1
  13. package/esm/schemas/coordinate_systems.js +0 -1
  14. package/esm/schemas/ome_zarr.d.ts +105 -69
  15. package/esm/schemas/ome_zarr.d.ts.map +1 -1
  16. package/esm/schemas/rfc4.d.ts +26 -131
  17. package/esm/schemas/rfc4.d.ts.map +1 -1
  18. package/esm/schemas/units.d.ts +70 -5
  19. package/esm/schemas/units.d.ts.map +1 -1
  20. package/esm/schemas/units.js +2 -15
  21. package/esm/schemas/zarr_metadata.d.ts +13 -300
  22. package/esm/schemas/zarr_metadata.d.ts.map +1 -1
  23. package/package.json +1 -1
  24. package/script/io/itk_image_to_ngff_image.d.ts +5 -0
  25. package/script/io/itk_image_to_ngff_image.d.ts.map +1 -1
  26. package/script/io/itk_image_to_ngff_image.js +20 -20
  27. package/script/io/ngff_image_to_itk_image.d.ts.map +1 -1
  28. package/script/io/ngff_image_to_itk_image.js +2 -0
  29. package/script/io/to_multiscales.js +1 -1
  30. package/script/io/to_ngff_zarr.js +16 -0
  31. package/script/methods/itkwasm.d.ts.map +1 -1
  32. package/script/methods/itkwasm.js +567 -425
  33. package/script/schemas/coordinate_systems.d.ts +159 -552
  34. package/script/schemas/coordinate_systems.d.ts.map +1 -1
  35. package/script/schemas/coordinate_systems.js +0 -1
  36. package/script/schemas/ome_zarr.d.ts +105 -69
  37. package/script/schemas/ome_zarr.d.ts.map +1 -1
  38. package/script/schemas/rfc4.d.ts +26 -131
  39. package/script/schemas/rfc4.d.ts.map +1 -1
  40. package/script/schemas/units.d.ts +70 -5
  41. package/script/schemas/units.d.ts.map +1 -1
  42. package/script/schemas/units.js +2 -15
  43. package/script/schemas/zarr_metadata.d.ts +13 -300
  44. package/script/schemas/zarr_metadata.d.ts.map +1 -1
package/README.md CHANGED
@@ -45,6 +45,7 @@ The main Python package provides:
45
45
  - [Sharded Zarr] stores
46
46
  - Optional writing via zarr-python 2, zarr-python 3, [tensorstore] or zarrita (TypeScript)
47
47
  - [Anatomical orientation metadata](./docs/rfc4.md) (RFC-4)
48
+ - **OME-Zarr Zip (.ozx) file support** for single-file OME-Zarr datasets (RFC-9)
48
49
  - **High Content Screening (HCS) support** for plate and well data
49
50
  - **Model Context Protocol (MCP) server** for AI agent integration
50
51
 
@@ -9,6 +9,11 @@ export interface ItkImageToNgffImageOptions {
9
9
  * @default true
10
10
  */
11
11
  addAnatomicalOrientation?: boolean;
12
+ /**
13
+ * Path prefix for the zarr array (e.g., "scale0/", "scale1/")
14
+ * @default "image"
15
+ */
16
+ path?: string;
12
17
  }
13
18
  /**
14
19
  * Convert an ITK-Wasm Image to an NgffImage, preserving spatial metadata.
@@ -1 +1 @@
1
- {"version":3,"file":"itk_image_to_ngff_image.d.ts","sourceRoot":"","sources":["../../src/io/itk_image_to_ngff_image.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAOnD,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,KAAK,EACf,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,SAAS,CAAC,CAmHpB"}
1
+ {"version":3,"file":"itk_image_to_ngff_image.d.ts","sourceRoot":"","sources":["../../src/io/itk_image_to_ngff_image.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAOnD,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAEnC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,KAAK,EACf,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,SAAS,CAAC,CAmHpB"}
@@ -20,10 +20,12 @@ import { _zarrita_internal_get_strides as getStrides } from "zarrita";
20
20
  * @returns Promise resolving to NgffImage
21
21
  */
22
22
  export async function itkImageToNgffImage(itkImage, options = {}) {
23
- const { addAnatomicalOrientation = true } = options;
23
+ const { addAnatomicalOrientation = true, path = "image" } = options;
24
24
  // Extract image properties from ITK-Wasm Image
25
25
  const _data = itkImage.data;
26
- const shape = itkImage.size;
26
+ // ITK stores size in physical space order [x, y, z], but the data buffer is in
27
+ // C-order (row-major) which means [z, y, x] indexing. Reverse to match data layout.
28
+ const shape = [...itkImage.size].reverse();
27
29
  const spacing = itkImage.spacing;
28
30
  const origin = itkImage.origin;
29
31
  const ndim = shape.length;
@@ -60,32 +62,27 @@ export async function itkImageToNgffImage(itkImage, options = {}) {
60
62
  // Identify spatial dimensions
61
63
  const allSpatialDims = new Set(["x", "y", "z"]);
62
64
  const spatialDims = dims.filter((dim) => allSpatialDims.has(dim));
63
- // Create scale mapping from spacing (ITK order: [z, y, x] for 3D, [y, x] for 2D)
65
+ // Create scale mapping from spacing
66
+ // ITK stores spacing/origin in physical space order (x, y, z),
67
+ // but we need to map them to array order (z, y, x).
68
+ // Reverse the arrays to convert from physical to array order, matching Python implementation.
64
69
  const scale = {};
65
- // Define canonical ITK spatial order for up to 3D
66
- const itkSpatialOrder = ["z", "y", "x"].slice(-spatialDims.length);
67
- spatialDims.forEach((dim) => {
68
- const spatialIndex = itkSpatialOrder.indexOf(dim);
69
- if (spatialIndex === -1) {
70
- throw new Error(`Unknown spatial dimension: ${dim}`);
71
- }
72
- scale[dim] = spacing[spatialIndex];
70
+ const reversedSpacing = spacing.slice().reverse();
71
+ spatialDims.forEach((dim, idx) => {
72
+ scale[dim] = reversedSpacing[idx];
73
73
  });
74
- // Create translation mapping from origin (ITK order: [z, y, x] for 3D, [y, x] for 2D)
74
+ // Create translation mapping from origin
75
75
  const translation = {};
76
- spatialDims.forEach((dim) => {
77
- const spatialIndex = itkSpatialOrder.indexOf(dim);
78
- if (spatialIndex === -1) {
79
- throw new Error(`Unknown spatial dimension: ${dim}`);
80
- }
81
- translation[dim] = origin[spatialIndex];
76
+ const reversedOrigin = origin.slice().reverse();
77
+ spatialDims.forEach((dim, idx) => {
78
+ translation[dim] = reversedOrigin[idx];
82
79
  });
83
80
  // Create Zarr array from ITK-Wasm data
84
81
  const store = new Map();
85
82
  const root = zarr.root(store);
86
83
  // Determine appropriate chunk size
87
84
  const chunkShape = shape.map((s) => Math.min(s, 256));
88
- const zarrArray = await zarr.create(root.resolve("image"), {
85
+ const zarrArray = await zarr.create(root.resolve(path), {
89
86
  shape: shape,
90
87
  chunk_shape: chunkShape,
91
88
  data_type: imageType.componentType,
@@ -96,10 +93,13 @@ export async function itkImageToNgffImage(itkImage, options = {}) {
96
93
  // Create a selection that covers the entire array (null means "all" for each dimension)
97
94
  const selection = new Array(ndim).fill(null);
98
95
  // Create a chunk object with the ITK-Wasm data in zarrita format
96
+ // ITK-Wasm stores data in column-major order with size [x, y, z],
97
+ // which has the same memory layout as C-order (row-major) with shape [z, y, x].
98
+ // We reversed the shape above, and now use C-order strides for that reversed shape.
99
99
  const dataChunk = {
100
100
  data: itkImage.data,
101
101
  shape: shape,
102
- stride: getStrides(shape, "C"), // C-order (row-major) strides for compatibility
102
+ stride: getStrides(shape, "C"), // C-order strides for the reversed shape
103
103
  };
104
104
  // Write all data to the zarr array using zarrita's set function
105
105
  // This handles chunking and encoding automatically
@@ -1 +1 @@
1
- {"version":3,"file":"ngff_image_to_itk_image.d.ts","sourceRoot":"","sources":["../../src/io/ngff_image_to_itk_image.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,OAAO,KAAK,EAEV,KAAK,EAKN,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAsED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,SAAS,EACpB,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,KAAK,CAAC,CAiMhB"}
1
+ {"version":3,"file":"ngff_image_to_itk_image.d.ts","sourceRoot":"","sources":["../../src/io/ngff_image_to_itk_image.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,OAAO,KAAK,EAEV,KAAK,EAKN,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAsED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,SAAS,EACpB,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,KAAK,CAAC,CAmMhB"}
@@ -168,6 +168,8 @@ export async function ngffImageToItkImage(ngffImage, options = {}) {
168
168
  return order.indexOf(a) - order.indexOf(b);
169
169
  });
170
170
  // Create ITK spacing, origin, and size arrays
171
+ // sortedItkDims is already in physical space order [x, y, z]
172
+ // Mapping from dims extracts the correct values from NGFF's array order [z, y, x]
171
173
  const spacing = sortedItkDims.map((dim) => workingImage.scale[dim] || 1.0);
172
174
  const origin = sortedItkDims.map((dim) => workingImage.translation[dim] || 0.0);
173
175
  const size = sortedItkDims.map((dim) => data.shape[dims.indexOf(dim)]);
@@ -47,7 +47,7 @@ export async function toMultiscales(image, options = {}) {
47
47
  });
48
48
  // Create datasets for all images
49
49
  const datasets = images.map((img, index) => {
50
- return createDataset(`${index}`, img.dims.map((dim) => img.scale[dim]), img.dims.map((dim) => img.translation[dim]));
50
+ return createDataset(`scale${index}`, img.dims.map((dim) => img.scale[dim]), img.dims.map((dim) => img.translation[dim]));
51
51
  });
52
52
  // Create metadata with method information
53
53
  const methodMetadata = getMethodMetadata(method);
@@ -194,6 +194,22 @@ async function writeChunkWithGet(zarrArray, image, chunkIndex) {
194
194
  // Convert chunk data to target type
195
195
  const targetTypedArrayConstructor = getTypedArrayConstructor(zarrArray.dtype);
196
196
  const chunkTargetData = convertChunkToTargetType(chunkSourceData, zarrArray.dtype, targetTypedArrayConstructor);
197
+ // Validate chunk data size
198
+ const expectedSize = chunkShape.reduce((a, b) => a * b, 1);
199
+ const actualSize = chunkTargetData.byteLength /
200
+ (chunkTargetData
201
+ .BYTES_PER_ELEMENT || 1);
202
+ if (actualSize !== expectedSize) {
203
+ console.error(`[writeChunkWithGet] Chunk data size mismatch!`);
204
+ console.error(` Image shape:`, shape);
205
+ console.error(` Chunk index:`, chunkIndex);
206
+ console.error(` Chunk start:`, chunkStart);
207
+ console.error(` Chunk end:`, chunkEnd);
208
+ console.error(` Chunk shape:`, chunkShape);
209
+ console.error(` Expected size:`, expectedSize);
210
+ console.error(` Actual size:`, actualSize);
211
+ throw new Error(`Chunk data size mismatch: expected ${expectedSize} elements, got ${actualSize}`);
212
+ }
197
213
  // Create the selection for writing to the target zarr array
198
214
  const targetSelection = chunkStart.map((start, dim) => zarr.slice(start, chunkEnd[dim]));
199
215
  // Write the chunk using zarrita's set function
@@ -1 +1 @@
1
- {"version":3,"file":"itkwasm.d.ts","sourceRoot":"","sources":["../../src/methods/itkwasm.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAohCnD;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,EACjD,SAAS,EAAE,UAAU,GAAG,YAAY,GAAG,aAAa,GACnD,OAAO,CAAC,SAAS,EAAE,CAAC,CA+CtB"}
1
+ {"version":3,"file":"itkwasm.d.ts","sourceRoot":"","sources":["../../src/methods/itkwasm.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAknCnD;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,EACjD,SAAS,EAAE,UAAU,GAAG,YAAY,GAAG,aAAa,GACnD,OAAO,CAAC,SAAS,EAAE,CAAC,CA8HtB"}