@fideus-labs/ngff-zarr 0.0.1 → 0.1.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 (174) hide show
  1. package/README.md +9 -2
  2. package/esm/io/from_ngff_zarr.d.ts +4 -1
  3. package/esm/io/from_ngff_zarr.d.ts.map +1 -1
  4. package/esm/io/from_ngff_zarr.js +94 -27
  5. package/esm/io/hcs.d.ts +18 -0
  6. package/esm/io/hcs.d.ts.map +1 -0
  7. package/esm/io/hcs.js +51 -0
  8. package/esm/io/itk_image_to_ngff_image.d.ts +25 -0
  9. package/esm/io/itk_image_to_ngff_image.d.ts.map +1 -0
  10. package/esm/io/itk_image_to_ngff_image.js +127 -0
  11. package/esm/io/ngff_image_to_itk_image.d.ts +30 -0
  12. package/esm/io/ngff_image_to_itk_image.d.ts.map +1 -0
  13. package/esm/io/ngff_image_to_itk_image.js +216 -0
  14. package/esm/io/to_multiscales.d.ts +18 -0
  15. package/esm/io/to_multiscales.d.ts.map +1 -0
  16. package/esm/io/to_multiscales.js +62 -0
  17. package/esm/io/to_ngff_image.d.ts +17 -0
  18. package/esm/io/to_ngff_image.d.ts.map +1 -0
  19. package/esm/io/to_ngff_image.js +136 -0
  20. package/esm/io/to_ngff_zarr.d.ts +3 -2
  21. package/esm/io/to_ngff_zarr.d.ts.map +1 -1
  22. package/esm/io/to_ngff_zarr.js +273 -26
  23. package/esm/methods/itkwasm.d.ts +6 -0
  24. package/esm/methods/itkwasm.d.ts.map +1 -0
  25. package/esm/methods/itkwasm.js +816 -0
  26. package/esm/mod.d.ts +9 -2
  27. package/esm/mod.d.ts.map +1 -1
  28. package/esm/mod.js +10 -2
  29. package/esm/schemas/coordinate_systems.d.ts +644 -0
  30. package/esm/schemas/coordinate_systems.d.ts.map +1 -0
  31. package/esm/schemas/coordinate_systems.js +140 -0
  32. package/esm/schemas/index.d.ts +9 -0
  33. package/esm/schemas/index.d.ts.map +1 -0
  34. package/esm/schemas/index.js +38 -0
  35. package/esm/schemas/methods.d.ts.map +1 -1
  36. package/esm/schemas/methods.js +2 -0
  37. package/esm/schemas/multiscales.d.ts.map +1 -1
  38. package/esm/schemas/multiscales.js +2 -0
  39. package/esm/schemas/ngff_image.d.ts +9 -2
  40. package/esm/schemas/ngff_image.d.ts.map +1 -1
  41. package/esm/schemas/ngff_image.js +11 -2
  42. package/esm/schemas/ome_zarr.d.ts +581 -0
  43. package/esm/schemas/ome_zarr.d.ts.map +1 -0
  44. package/esm/schemas/ome_zarr.js +208 -0
  45. package/esm/schemas/rfc4.d.ts +439 -0
  46. package/esm/schemas/rfc4.d.ts.map +1 -0
  47. package/esm/schemas/rfc4.js +129 -0
  48. package/esm/schemas/units.d.ts.map +1 -1
  49. package/esm/schemas/units.js +5 -0
  50. package/esm/schemas/zarr_metadata.d.ts +302 -9
  51. package/esm/schemas/zarr_metadata.d.ts.map +1 -1
  52. package/esm/schemas/zarr_metadata.js +22 -1
  53. package/esm/types/array_interface.d.ts +7 -0
  54. package/esm/types/array_interface.d.ts.map +1 -0
  55. package/esm/types/array_interface.js +1 -0
  56. package/esm/types/hcs.d.ts +70 -0
  57. package/esm/types/hcs.d.ts.map +1 -0
  58. package/esm/types/hcs.js +204 -0
  59. package/esm/types/methods.d.ts.map +1 -1
  60. package/esm/types/methods.js +2 -0
  61. package/esm/types/multiscales.d.ts.map +1 -1
  62. package/esm/types/ngff_image.d.ts +6 -3
  63. package/esm/types/ngff_image.d.ts.map +1 -1
  64. package/esm/types/ngff_image.js +13 -1
  65. package/esm/types/rfc4.d.ts +94 -0
  66. package/esm/types/rfc4.d.ts.map +1 -0
  67. package/esm/types/rfc4.js +135 -0
  68. package/esm/types/units.d.ts +1 -1
  69. package/esm/types/units.d.ts.map +1 -1
  70. package/esm/types/zarr_metadata.d.ts +14 -5
  71. package/esm/types/zarr_metadata.d.ts.map +1 -1
  72. package/esm/utils/create_queue.d.ts +6 -0
  73. package/esm/utils/create_queue.d.ts.map +1 -0
  74. package/esm/utils/create_queue.js +11 -0
  75. package/esm/utils/factory.d.ts +1 -1
  76. package/esm/utils/factory.d.ts.map +1 -1
  77. package/esm/utils/factory.js +16 -7
  78. package/esm/utils/method_metadata.d.ts +10 -0
  79. package/esm/utils/method_metadata.d.ts.map +1 -0
  80. package/esm/utils/method_metadata.js +37 -0
  81. package/esm/utils/validation.d.ts.map +1 -1
  82. package/package.json +7 -1
  83. package/script/io/from_ngff_zarr.d.ts +4 -1
  84. package/script/io/from_ngff_zarr.d.ts.map +1 -1
  85. package/script/io/from_ngff_zarr.js +94 -27
  86. package/script/io/hcs.d.ts +18 -0
  87. package/script/io/hcs.d.ts.map +1 -0
  88. package/script/io/hcs.js +55 -0
  89. package/script/io/itk_image_to_ngff_image.d.ts +25 -0
  90. package/script/io/itk_image_to_ngff_image.d.ts.map +1 -0
  91. package/script/io/itk_image_to_ngff_image.js +153 -0
  92. package/script/io/ngff_image_to_itk_image.d.ts +30 -0
  93. package/script/io/ngff_image_to_itk_image.d.ts.map +1 -0
  94. package/script/io/ngff_image_to_itk_image.js +242 -0
  95. package/script/io/to_multiscales.d.ts +18 -0
  96. package/script/io/to_multiscales.d.ts.map +1 -0
  97. package/script/io/to_multiscales.js +67 -0
  98. package/script/io/to_ngff_image.d.ts +17 -0
  99. package/script/io/to_ngff_image.d.ts.map +1 -0
  100. package/script/io/to_ngff_image.js +162 -0
  101. package/script/io/to_ngff_zarr.d.ts +3 -2
  102. package/script/io/to_ngff_zarr.d.ts.map +1 -1
  103. package/script/io/to_ngff_zarr.js +273 -26
  104. package/script/methods/itkwasm.d.ts +6 -0
  105. package/script/methods/itkwasm.d.ts.map +1 -0
  106. package/script/methods/itkwasm.js +842 -0
  107. package/script/mod.d.ts +9 -2
  108. package/script/mod.d.ts.map +1 -1
  109. package/script/mod.js +12 -3
  110. package/script/schemas/coordinate_systems.d.ts +644 -0
  111. package/script/schemas/coordinate_systems.d.ts.map +1 -0
  112. package/script/schemas/coordinate_systems.js +143 -0
  113. package/script/schemas/index.d.ts +9 -0
  114. package/script/schemas/index.d.ts.map +1 -0
  115. package/script/schemas/index.js +101 -0
  116. package/script/schemas/methods.d.ts.map +1 -1
  117. package/script/schemas/methods.js +2 -0
  118. package/script/schemas/multiscales.d.ts.map +1 -1
  119. package/script/schemas/multiscales.js +2 -0
  120. package/script/schemas/ngff_image.d.ts +9 -2
  121. package/script/schemas/ngff_image.d.ts.map +1 -1
  122. package/script/schemas/ngff_image.js +11 -2
  123. package/script/schemas/ome_zarr.d.ts +581 -0
  124. package/script/schemas/ome_zarr.d.ts.map +1 -0
  125. package/script/schemas/ome_zarr.js +211 -0
  126. package/script/schemas/rfc4.d.ts +439 -0
  127. package/script/schemas/rfc4.d.ts.map +1 -0
  128. package/script/schemas/rfc4.js +132 -0
  129. package/script/schemas/units.d.ts.map +1 -1
  130. package/script/schemas/units.js +5 -0
  131. package/script/schemas/zarr_metadata.d.ts +302 -9
  132. package/script/schemas/zarr_metadata.d.ts.map +1 -1
  133. package/script/schemas/zarr_metadata.js +23 -2
  134. package/script/types/array_interface.d.ts +7 -0
  135. package/script/types/array_interface.d.ts.map +1 -0
  136. package/script/types/array_interface.js +2 -0
  137. package/script/types/hcs.d.ts +70 -0
  138. package/script/types/hcs.d.ts.map +1 -0
  139. package/script/types/hcs.js +233 -0
  140. package/script/types/methods.d.ts.map +1 -1
  141. package/script/types/methods.js +2 -0
  142. package/script/types/multiscales.d.ts.map +1 -1
  143. package/script/types/ngff_image.d.ts +6 -3
  144. package/script/types/ngff_image.d.ts.map +1 -1
  145. package/script/types/ngff_image.js +13 -1
  146. package/script/types/rfc4.d.ts +94 -0
  147. package/script/types/rfc4.d.ts.map +1 -0
  148. package/script/types/rfc4.js +143 -0
  149. package/script/types/units.d.ts +1 -1
  150. package/script/types/units.d.ts.map +1 -1
  151. package/script/types/zarr_metadata.d.ts +14 -5
  152. package/script/types/zarr_metadata.d.ts.map +1 -1
  153. package/script/utils/create_queue.d.ts +6 -0
  154. package/script/utils/create_queue.d.ts.map +1 -0
  155. package/script/utils/create_queue.js +17 -0
  156. package/script/utils/factory.d.ts +1 -1
  157. package/script/utils/factory.d.ts.map +1 -1
  158. package/script/utils/factory.js +39 -7
  159. package/script/utils/method_metadata.d.ts +10 -0
  160. package/script/utils/method_metadata.d.ts.map +1 -0
  161. package/script/utils/method_metadata.js +40 -0
  162. package/script/utils/validation.d.ts.map +1 -1
  163. package/esm/schemas/lazy_array.d.ts +0 -8
  164. package/esm/schemas/lazy_array.d.ts.map +0 -1
  165. package/esm/schemas/lazy_array.js +0 -7
  166. package/esm/types/lazy_array.d.ts +0 -18
  167. package/esm/types/lazy_array.d.ts.map +0 -1
  168. package/esm/types/lazy_array.js +0 -27
  169. package/script/schemas/lazy_array.d.ts +0 -8
  170. package/script/schemas/lazy_array.d.ts.map +0 -1
  171. package/script/schemas/lazy_array.js +0 -10
  172. package/script/types/lazy_array.d.ts +0 -18
  173. package/script/types/lazy_array.d.ts.map +0 -1
  174. package/script/types/lazy_array.js +0 -31
package/README.md CHANGED
@@ -1,8 +1,12 @@
1
+ <!-- SPDX-FileCopyrightText: Copyright (c) Fideus Labs LLC -->
2
+ <!-- SPDX-License-Identifier: MIT -->
1
3
  # ngff-zarr
2
4
 
3
5
  [![PyPI - Version](https://img.shields.io/pypi/v/ngff-zarr.svg)](https://pypi.org/project/ngff-zarr)
4
6
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ngff-zarr.svg)](https://pypi.org/project/ngff-zarr)
5
- [![Test](https://github.com/thewtex/ngff-zarr/actions/workflows/pixi-test.yml/badge.svg)](https://github.com/thewtex/ngff-zarr/actions/workflows/pixi-test.yml)
7
+ [![Python CI Testing](https://github.com/thewtex/ngff-zarr/actions/workflows/python.yml/badge.svg)](https://github.com/thewtex/ngff-zarr/actions/workflows/python.yml)
8
+ [![Typescript CI Testing](https://github.com/thewtex/ngff-zarr/actions/workflows/typescript.yml/badge.svg)](https://github.com/thewtex/ngff-zarr/actions/workflows/typescript.yml)
9
+ [![MCP CI Testing](https://github.com/thewtex/ngff-zarr/actions/workflows/mcp-ci.yml/badge.svg)](https://github.com/thewtex/ngff-zarr/actions/workflows/mcp-ci.yml)
6
10
  [![DOI](https://zenodo.org/badge/541840158.svg)](https://zenodo.org/badge/latestdoi/541840158)
7
11
  [![Documentation Status](https://readthedocs.org/projects/ngff-zarr/badge/?version=latest)](https://ngff-zarr.readthedocs.io/en/latest/?badge=latest)
8
12
 
@@ -39,7 +43,9 @@ The main Python package provides:
39
43
  - Optional OME-Zarr data model validation during reading
40
44
  - Writes OME-Zarr v0.4 to v0.5
41
45
  - [Sharded Zarr] stores
42
- - Optional writing via [tensorstore]
46
+ - Optional writing via zarr-python 2, zarr-python 3, [tensorstore] or zarrita (TypeScript)
47
+ - [Anatomical orientation metadata](./docs/rfc4.md) (RFC-4)
48
+ - **High Content Screening (HCS) support** for plate and well data
43
49
  - **Model Context Protocol (MCP) server** for AI agent integration
44
50
 
45
51
  📖 **Documentation**
@@ -63,6 +69,7 @@ usage instructions.
63
69
  - [pydantic-ome-ngff](https://janeliascicomp.github.io/pydantic-ome-ngff/)
64
70
  - [aicsimageio](https://allencellmodeling.github.io/aicsimageio/)
65
71
  - [bfio](https://bfio.readthedocs.io/)
72
+ - [zod-ome-ngff](https://github.com/hms-dbmi/zod-ome-ngff)
66
73
 
67
74
  ## License
68
75
 
@@ -1,7 +1,10 @@
1
+ import * as zarr from "zarrita";
1
2
  import { Multiscales } from "../types/multiscales.js";
2
3
  export interface FromNgffZarrOptions {
3
4
  validate?: boolean;
5
+ version?: "0.4" | "0.5";
4
6
  }
5
- export declare function fromNgffZarr(storePath: string, options?: FromNgffZarrOptions): Promise<Multiscales>;
7
+ export type MemoryStore = Map<string, Uint8Array>;
8
+ export declare function fromNgffZarr(store: string | MemoryStore | zarr.FetchStore, options?: FromNgffZarrOptions): Promise<Multiscales>;
6
9
  export declare function readArrayData(storePath: string, arrayPath: string, selection?: (number | null)[]): Promise<unknown>;
7
10
  //# sourceMappingURL=from_ngff_zarr.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"from_ngff_zarr.d.ts","sourceRoot":"","sources":["../../src/io/from_ngff_zarr.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAOtD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,WAAW,CAAC,CAyItB;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,GAC5B,OAAO,CAAC,OAAO,CAAC,CAoBlB"}
1
+ {"version":3,"file":"from_ngff_zarr.d.ts","sourceRoot":"","sources":["../../src/io/from_ngff_zarr.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMtD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAElD,wBAAsB,YAAY,CAEhC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC,UAAU,EAC7C,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,WAAW,CAAC,CA6MtB;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,GAC5B,OAAO,CAAC,OAAO,CAAC,CAmClB"}
@@ -1,45 +1,62 @@
1
+ // SPDX-FileCopyrightText: Copyright (c) Fideus Labs LLC
2
+ // SPDX-License-Identifier: MIT
1
3
  import * as dntShim from "../_dnt.shims.js";
2
4
  import * as zarr from "zarrita";
3
5
  import { Multiscales } from "../types/multiscales.js";
4
6
  import { NgffImage } from "../types/ngff_image.js";
5
- import { LazyArray } from "../types/lazy_array.js";
6
7
  import { MetadataSchema } from "../schemas/zarr_metadata.js";
7
- export async function fromNgffZarr(storePath, options = {}) {
8
+ export async function fromNgffZarr(
9
+ // Also accepts FileSystemStore, ZipFileStore objects in Node.js/Deno
10
+ store, options = {}) {
8
11
  const validate = options.validate ?? false;
12
+ const version = options.version;
9
13
  try {
10
14
  // Determine the appropriate store type based on the path
11
- let store;
12
- if (storePath.startsWith("http://") || storePath.startsWith("https://")) {
15
+ let resolvedStore;
16
+ if (store instanceof Map || store instanceof zarr.FetchStore) {
17
+ resolvedStore = store;
18
+ }
19
+ else if (store.startsWith("http://") || store.startsWith("https://")) {
13
20
  // Use FetchStore for HTTP/HTTPS URLs
14
- store = new zarr.FetchStore(storePath);
21
+ resolvedStore = new zarr.FetchStore(store);
15
22
  }
16
23
  else {
17
24
  // For local paths, check if we're in a browser environment
18
25
  if (typeof dntShim.dntGlobalThis !== "undefined") {
19
26
  throw new Error("Local file paths are not supported in browser environments. Use HTTP/HTTPS URLs instead.");
20
27
  }
21
- // Use dynamic import for FileSystemStore in Node.js/Deno environments
28
+ // Use dynamic import for FileSystemStore, ZipFileStore in Node.js/Deno environments
22
29
  try {
23
- const { FileSystemStore } = await import("@zarrita/storage");
24
- store = new FileSystemStore(storePath);
30
+ const { FileSystemStore, ZipFileStore } = await import("@zarrita/storage");
31
+ // @ts-ignore: Node/Deno workaround
32
+ if (store instanceof FileSystemStore || store instanceof ZipFileStore) {
33
+ // @ts-ignore: Node/Deno workaround
34
+ resolvedStore = store;
35
+ }
36
+ else {
37
+ // Normalize the path for cross-platform compatibility
38
+ const normalizedPath = store.replace(/^\/([A-Za-z]:)/, "$1");
39
+ // @ts-ignore: Node/Deno workaround
40
+ resolvedStore = new FileSystemStore(normalizedPath);
41
+ }
25
42
  }
26
43
  catch (error) {
27
44
  throw new Error(`Failed to load FileSystemStore: ${error}. Use HTTP/HTTPS URLs for browser compatibility.`);
28
45
  }
29
46
  }
30
- const root = zarr.root(store);
31
47
  // Try to use consolidated metadata for better performance
32
- let consolidatedRoot;
48
+ let optimizedStore;
33
49
  try {
34
- consolidatedRoot = await zarr.tryWithConsolidated(store);
50
+ // @ts-ignore: tryWithConsolidated typing
51
+ optimizedStore = await zarr.tryWithConsolidated(resolvedStore);
35
52
  }
36
53
  catch {
37
- consolidatedRoot = store;
54
+ optimizedStore = resolvedStore;
38
55
  }
39
- const group = await zarr.open.v2(zarr.root(consolidatedRoot), {
56
+ const root = await zarr.open(optimizedStore, {
40
57
  kind: "group",
41
58
  });
42
- const attrs = group.attrs;
59
+ const attrs = root.attrs;
43
60
  if (!attrs || !attrs.multiscales) {
44
61
  throw new Error("No multiscales metadata found in Zarr store");
45
62
  }
@@ -54,24 +71,60 @@ export async function fromNgffZarr(storePath, options = {}) {
54
71
  if (!result.success) {
55
72
  throw new Error(`Invalid OME-Zarr metadata: ${result.error.message}`);
56
73
  }
74
+ // Check version compatibility if specified
75
+ if (version) {
76
+ const metadataWithVersion = multiscalesMetadata;
77
+ if (metadataWithVersion.version !== version) {
78
+ throw new Error(`Expected OME-Zarr version ${version}, but found ${metadataWithVersion.version || "unknown"}`);
79
+ }
80
+ }
57
81
  }
58
82
  const metadata = multiscalesMetadata;
59
83
  // Extract omero metadata from root attributes if present
60
84
  if (attrs.omero) {
61
- metadata.omero = attrs.omero;
85
+ const omeroData = attrs.omero;
86
+ // Handle backward compatibility for OMERO window metadata
87
+ if (omeroData.channels && Array.isArray(omeroData.channels)) {
88
+ for (const channel of omeroData.channels) {
89
+ if (channel.window && typeof channel.window === "object") {
90
+ const window = channel.window;
91
+ // Ensure both min/max and start/end are present for compatibility
92
+ if (window.min !== undefined && window.max !== undefined) {
93
+ // If only min/max present, use them for start/end
94
+ if (window.start === undefined) {
95
+ window.start = window.min;
96
+ }
97
+ if (window.end === undefined) {
98
+ window.end = window.max;
99
+ }
100
+ }
101
+ else if (window.start !== undefined && window.end !== undefined) {
102
+ // If only start/end present, use them for min/max
103
+ if (window.min === undefined) {
104
+ window.min = window.start;
105
+ }
106
+ if (window.max === undefined) {
107
+ window.max = window.end;
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ metadata.omero = omeroData;
62
114
  }
63
115
  const images = [];
64
116
  for (const dataset of metadata.datasets) {
65
117
  const arrayPath = dataset.path;
66
- const zarrArray = await zarr.open.v2(root.resolve(arrayPath), {
118
+ const zarrArray = (await zarr.open(root.resolve(arrayPath), {
67
119
  kind: "array",
68
- });
69
- const lazyArray = new LazyArray({
70
- shape: zarrArray.shape,
71
- dtype: zarrArray.dtype,
72
- chunks: [zarrArray.chunks],
73
- name: arrayPath,
74
- });
120
+ }));
121
+ // Verify we have an array with the expected properties
122
+ if (!zarrArray ||
123
+ !("shape" in zarrArray) ||
124
+ !("dtype" in zarrArray) ||
125
+ !("chunks" in zarrArray)) {
126
+ throw new Error(`Invalid zarr array at path ${arrayPath}: missing shape property`);
127
+ }
75
128
  const scale = {};
76
129
  const translation = {};
77
130
  for (const transform of dataset.coordinateTransformations) {
@@ -98,7 +151,7 @@ export async function fromNgffZarr(storePath, options = {}) {
98
151
  return acc;
99
152
  }, {});
100
153
  const ngffImage = new NgffImage({
101
- data: lazyArray,
154
+ data: zarrArray,
102
155
  dims,
103
156
  scale,
104
157
  translation,
@@ -124,9 +177,23 @@ export async function readArrayData(storePath, arrayPath, selection) {
124
177
  try {
125
178
  const store = new zarr.FetchStore(storePath);
126
179
  const root = zarr.root(store);
127
- const zarrArray = await zarr.open.v2(root.resolve(arrayPath), {
128
- kind: "array",
129
- });
180
+ // Try to open as zarr v2 first, then v3 if that fails
181
+ let zarrArray;
182
+ try {
183
+ zarrArray = await zarr.open.v2(root.resolve(arrayPath), {
184
+ kind: "array",
185
+ });
186
+ }
187
+ catch (v2Error) {
188
+ try {
189
+ zarrArray = await zarr.open.v3(root.resolve(arrayPath), {
190
+ kind: "array",
191
+ });
192
+ }
193
+ catch (v3Error) {
194
+ throw new Error(`Failed to open zarr array ${arrayPath} as either v2 or v3 format. v2 error: ${v2Error}. v3 error: ${v3Error}`);
195
+ }
196
+ }
130
197
  if (selection) {
131
198
  return await zarr.get(zarrArray, selection);
132
199
  }
@@ -0,0 +1,18 @@
1
+ import type { HCSPlate } from "../types/hcs.js";
2
+ export interface FromHcsZarrOptions {
3
+ validate?: boolean;
4
+ wellCacheSize?: number;
5
+ imageCacheSize?: number;
6
+ }
7
+ export interface ToHcsZarrOptions {
8
+ compressionLevel?: number;
9
+ }
10
+ /**
11
+ * Read an HCS plate from an OME-Zarr NGFF store.
12
+ */
13
+ export declare function fromHcsZarr(store: string | object, options?: FromHcsZarrOptions): HCSPlate;
14
+ /**
15
+ * Write an HCS plate to an OME-Zarr NGFF store.
16
+ */
17
+ export declare function toHcsZarr(plate: HCSPlate, store: string | object, _options?: ToHcsZarrOptions): void;
18
+ //# sourceMappingURL=hcs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hcs.d.ts","sourceRoot":"","sources":["../../src/io/hcs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,iBAAiB,CAAC;AAG/D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAE/B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,GAAE,kBAAuB,GAC/B,QAAQ,CAkCV;AAED;;GAEG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,GAAE,gBAAqB,GAC9B,IAAI,CAaN"}
package/esm/io/hcs.js ADDED
@@ -0,0 +1,51 @@
1
+ import { HCSPlate as HCSPlateClass } from "../types/hcs.js";
2
+ /**
3
+ * Read an HCS plate from an OME-Zarr NGFF store.
4
+ */
5
+ export function fromHcsZarr(store, options = {}) {
6
+ const { validate = false, wellCacheSize, imageCacheSize } = options;
7
+ if (validate) {
8
+ console.warn("HCS validation not yet implemented");
9
+ }
10
+ if (typeof store !== "string") {
11
+ throw new Error("Non-string store types not yet supported");
12
+ }
13
+ // For now, create a mock implementation
14
+ // This will be properly implemented when the zarrita API integration is complete
15
+ const plateMetadata = {
16
+ columns: [{ name: "1" }, { name: "2" }],
17
+ rows: [{ name: "A" }, { name: "B" }],
18
+ wells: [
19
+ { path: "A/1", rowIndex: 0, columnIndex: 0 },
20
+ { path: "A/2", rowIndex: 0, columnIndex: 1 },
21
+ { path: "B/1", rowIndex: 1, columnIndex: 0 },
22
+ { path: "B/2", rowIndex: 1, columnIndex: 1 },
23
+ ],
24
+ version: "0.4",
25
+ acquisitions: [{ id: 0, name: "Test Acquisition" }],
26
+ field_count: 2,
27
+ name: "Test Plate",
28
+ };
29
+ return new HCSPlateClass({
30
+ store,
31
+ metadata: plateMetadata,
32
+ wellCacheSize,
33
+ imageCacheSize,
34
+ });
35
+ }
36
+ /**
37
+ * Write an HCS plate to an OME-Zarr NGFF store.
38
+ */
39
+ export function toHcsZarr(plate, store, _options = {}) {
40
+ if (typeof store !== "string") {
41
+ throw new Error("Non-string store types not yet supported");
42
+ }
43
+ // Mock implementation for now
44
+ console.log(`HCS plate structure would be created at ${store}`);
45
+ console.log(`Plate: ${plate.name}`);
46
+ console.log(`Wells: ${plate.wells.length}`);
47
+ console.log(`Rows: ${plate.rows.length}, Columns: ${plate.columns.length}`);
48
+ if (plate.acquisitions) {
49
+ console.log(`Acquisitions: ${plate.acquisitions.length}`);
50
+ }
51
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Convert ITK-Wasm Image to NgffImage
3
+ */
4
+ import type { Image } from "itk-wasm";
5
+ import { NgffImage } from "../types/ngff_image.js";
6
+ export interface ItkImageToNgffImageOptions {
7
+ /**
8
+ * Whether to add anatomical orientation metadata based on ITK LPS coordinate system
9
+ * @default true
10
+ */
11
+ addAnatomicalOrientation?: boolean;
12
+ }
13
+ /**
14
+ * Convert an ITK-Wasm Image to an NgffImage, preserving spatial metadata.
15
+ *
16
+ * This function converts ITK-Wasm Image objects to NgffImage format while
17
+ * preserving spatial information like spacing, origin, and optionally
18
+ * anatomical orientation based on the ITK LPS coordinate system.
19
+ *
20
+ * @param itkImage - The ITK-Wasm Image to convert
21
+ * @param options - Conversion options
22
+ * @returns Promise resolving to NgffImage
23
+ */
24
+ export declare function itkImageToNgffImage(itkImage: Image, options?: ItkImageToNgffImageOptions): Promise<NgffImage>;
25
+ //# sourceMappingURL=itk_image_to_ngff_image.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,127 @@
1
+ // SPDX-FileCopyrightText: Copyright (c) Fideus Labs LLC
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * Convert ITK-Wasm Image to NgffImage
5
+ */
6
+ import * as zarr from "zarrita";
7
+ import { NgffImage } from "../types/ngff_image.js";
8
+ import { itkLpsToAnatomicalOrientation } from "../types/rfc4.js";
9
+ // Import the get_strides function from zarrita utilities
10
+ import { _zarrita_internal_get_strides as getStrides } from "zarrita";
11
+ /**
12
+ * Convert an ITK-Wasm Image to an NgffImage, preserving spatial metadata.
13
+ *
14
+ * This function converts ITK-Wasm Image objects to NgffImage format while
15
+ * preserving spatial information like spacing, origin, and optionally
16
+ * anatomical orientation based on the ITK LPS coordinate system.
17
+ *
18
+ * @param itkImage - The ITK-Wasm Image to convert
19
+ * @param options - Conversion options
20
+ * @returns Promise resolving to NgffImage
21
+ */
22
+ export async function itkImageToNgffImage(itkImage, options = {}) {
23
+ const { addAnatomicalOrientation = true } = options;
24
+ // Extract image properties from ITK-Wasm Image
25
+ const _data = itkImage.data;
26
+ const shape = itkImage.size;
27
+ const spacing = itkImage.spacing;
28
+ const origin = itkImage.origin;
29
+ const ndim = shape.length;
30
+ // Determine dimension names based on shape and image type
31
+ // This logic matches the Python implementation
32
+ let dims;
33
+ // Check if this is a vector image (multi-component)
34
+ const imageType = itkImage.imageType;
35
+ const isVector = imageType.components > 1;
36
+ if (ndim === 3 && isVector) {
37
+ // 2D RGB/vector image: 2D spatial + components
38
+ dims = ["y", "x", "c"];
39
+ }
40
+ else if (ndim < 4) {
41
+ // Scalar images up to 3D: take the last ndim spatial dimensions
42
+ dims = ["z", "y", "x"].slice(-ndim);
43
+ }
44
+ else if (ndim < 5) {
45
+ // 3D RGB/vector or 4D scalar
46
+ if (isVector) {
47
+ dims = ["z", "y", "x", "c"];
48
+ }
49
+ else {
50
+ dims = ["t", "z", "y", "x"];
51
+ }
52
+ }
53
+ else if (ndim < 6) {
54
+ // 4D RGB/vector
55
+ dims = ["t", "z", "y", "x", "c"];
56
+ }
57
+ else {
58
+ throw new Error(`Unsupported number of dimensions: ${ndim}`);
59
+ }
60
+ // Identify spatial dimensions
61
+ const allSpatialDims = new Set(["x", "y", "z"]);
62
+ 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)
64
+ 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];
73
+ });
74
+ // Create translation mapping from origin (ITK order: [z, y, x] for 3D, [y, x] for 2D)
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];
82
+ });
83
+ // Create Zarr array from ITK-Wasm data
84
+ const store = new Map();
85
+ const root = zarr.root(store);
86
+ // Determine appropriate chunk size
87
+ const chunkShape = shape.map((s) => Math.min(s, 256));
88
+ const zarrArray = await zarr.create(root.resolve("image"), {
89
+ shape: shape,
90
+ chunk_shape: chunkShape,
91
+ data_type: imageType.componentType,
92
+ fill_value: 0,
93
+ });
94
+ // Write the ITK-Wasm data to the zarr array
95
+ // We use zarrita's set function to write the entire data efficiently
96
+ // Create a selection that covers the entire array (null means "all" for each dimension)
97
+ const selection = new Array(ndim).fill(null);
98
+ // Create a chunk object with the ITK-Wasm data in zarrita format
99
+ const dataChunk = {
100
+ data: itkImage.data,
101
+ shape: shape,
102
+ stride: getStrides(shape, "C"), // C-order (row-major) strides for compatibility
103
+ };
104
+ // Write all data to the zarr array using zarrita's set function
105
+ // This handles chunking and encoding automatically
106
+ await zarr.set(zarrArray, selection, dataChunk); // Add anatomical orientation if requested
107
+ let axesOrientations;
108
+ if (addAnatomicalOrientation) {
109
+ axesOrientations = {};
110
+ for (const dim of spatialDims) {
111
+ const orientation = itkLpsToAnatomicalOrientation(dim);
112
+ if (orientation !== undefined) {
113
+ axesOrientations[dim] = orientation;
114
+ }
115
+ }
116
+ }
117
+ return new NgffImage({
118
+ data: zarrArray,
119
+ dims,
120
+ scale,
121
+ translation,
122
+ name: "image",
123
+ axesUnits: undefined,
124
+ axesOrientations,
125
+ computedCallbacks: undefined,
126
+ });
127
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Convert NgffImage to ITK-Wasm Image
3
+ */
4
+ import type { Image } from "itk-wasm";
5
+ import { NgffImage } from "../types/ngff_image.js";
6
+ export interface NgffImageToItkImageOptions {
7
+ /**
8
+ * Extract a specific time index from a time-series image
9
+ * If specified and 't' dimension exists, extracts the slice at this time index
10
+ */
11
+ tIndex?: number;
12
+ /**
13
+ * Extract a specific channel index from a multi-channel image
14
+ * If specified and 'c' dimension exists, extracts the slice at this channel index
15
+ */
16
+ cIndex?: number;
17
+ }
18
+ /**
19
+ * Convert an NgffImage to an ITK-Wasm Image, preserving spatial metadata.
20
+ *
21
+ * This function converts NgffImage objects to ITK-Wasm Image format while
22
+ * preserving spatial information like spacing, origin, and direction matrix.
23
+ * Optionally extracts specific time or channel slices.
24
+ *
25
+ * @param ngffImage - The NgffImage to convert
26
+ * @param options - Conversion options
27
+ * @returns Promise resolving to ITK-Wasm Image
28
+ */
29
+ export declare function ngffImageToItkImage(ngffImage: NgffImage, options?: NgffImageToItkImageOptions): Promise<Image>;
30
+ //# sourceMappingURL=ngff_image_to_itk_image.d.ts.map
@@ -0,0 +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"}