@fideus-labs/ngff-zarr 0.0.1 → 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 (176) hide show
  1. package/README.md +10 -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 +30 -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 +218 -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 +289 -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 +958 -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 +251 -0
  30. package/esm/schemas/coordinate_systems.d.ts.map +1 -0
  31. package/esm/schemas/coordinate_systems.js +139 -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 +617 -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 +334 -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 +70 -5
  49. package/esm/schemas/units.d.ts.map +1 -1
  50. package/esm/schemas/units.js +4 -12
  51. package/esm/schemas/zarr_metadata.d.ts +10 -4
  52. package/esm/schemas/zarr_metadata.d.ts.map +1 -1
  53. package/esm/schemas/zarr_metadata.js +22 -1
  54. package/esm/types/array_interface.d.ts +7 -0
  55. package/esm/types/array_interface.d.ts.map +1 -0
  56. package/esm/types/array_interface.js +1 -0
  57. package/esm/types/hcs.d.ts +70 -0
  58. package/esm/types/hcs.d.ts.map +1 -0
  59. package/esm/types/hcs.js +204 -0
  60. package/esm/types/methods.d.ts.map +1 -1
  61. package/esm/types/methods.js +2 -0
  62. package/esm/types/multiscales.d.ts.map +1 -1
  63. package/esm/types/ngff_image.d.ts +6 -3
  64. package/esm/types/ngff_image.d.ts.map +1 -1
  65. package/esm/types/ngff_image.js +13 -1
  66. package/esm/types/rfc4.d.ts +94 -0
  67. package/esm/types/rfc4.d.ts.map +1 -0
  68. package/esm/types/rfc4.js +135 -0
  69. package/esm/types/units.d.ts +1 -1
  70. package/esm/types/units.d.ts.map +1 -1
  71. package/esm/types/zarr_metadata.d.ts +14 -5
  72. package/esm/types/zarr_metadata.d.ts.map +1 -1
  73. package/esm/utils/create_queue.d.ts +6 -0
  74. package/esm/utils/create_queue.d.ts.map +1 -0
  75. package/esm/utils/create_queue.js +11 -0
  76. package/esm/utils/factory.d.ts +1 -1
  77. package/esm/utils/factory.d.ts.map +1 -1
  78. package/esm/utils/factory.js +16 -7
  79. package/esm/utils/method_metadata.d.ts +10 -0
  80. package/esm/utils/method_metadata.d.ts.map +1 -0
  81. package/esm/utils/method_metadata.js +37 -0
  82. package/esm/utils/validation.d.ts.map +1 -1
  83. package/package.json +7 -1
  84. package/script/io/from_ngff_zarr.d.ts +4 -1
  85. package/script/io/from_ngff_zarr.d.ts.map +1 -1
  86. package/script/io/from_ngff_zarr.js +94 -27
  87. package/script/io/hcs.d.ts +18 -0
  88. package/script/io/hcs.d.ts.map +1 -0
  89. package/script/io/hcs.js +55 -0
  90. package/script/io/itk_image_to_ngff_image.d.ts +30 -0
  91. package/script/io/itk_image_to_ngff_image.d.ts.map +1 -0
  92. package/script/io/itk_image_to_ngff_image.js +153 -0
  93. package/script/io/ngff_image_to_itk_image.d.ts +30 -0
  94. package/script/io/ngff_image_to_itk_image.d.ts.map +1 -0
  95. package/script/io/ngff_image_to_itk_image.js +244 -0
  96. package/script/io/to_multiscales.d.ts +18 -0
  97. package/script/io/to_multiscales.d.ts.map +1 -0
  98. package/script/io/to_multiscales.js +67 -0
  99. package/script/io/to_ngff_image.d.ts +17 -0
  100. package/script/io/to_ngff_image.d.ts.map +1 -0
  101. package/script/io/to_ngff_image.js +162 -0
  102. package/script/io/to_ngff_zarr.d.ts +3 -2
  103. package/script/io/to_ngff_zarr.d.ts.map +1 -1
  104. package/script/io/to_ngff_zarr.js +289 -26
  105. package/script/methods/itkwasm.d.ts +6 -0
  106. package/script/methods/itkwasm.d.ts.map +1 -0
  107. package/script/methods/itkwasm.js +984 -0
  108. package/script/mod.d.ts +9 -2
  109. package/script/mod.d.ts.map +1 -1
  110. package/script/mod.js +12 -3
  111. package/script/schemas/coordinate_systems.d.ts +251 -0
  112. package/script/schemas/coordinate_systems.d.ts.map +1 -0
  113. package/script/schemas/coordinate_systems.js +142 -0
  114. package/script/schemas/index.d.ts +9 -0
  115. package/script/schemas/index.d.ts.map +1 -0
  116. package/script/schemas/index.js +101 -0
  117. package/script/schemas/methods.d.ts.map +1 -1
  118. package/script/schemas/methods.js +2 -0
  119. package/script/schemas/multiscales.d.ts.map +1 -1
  120. package/script/schemas/multiscales.js +2 -0
  121. package/script/schemas/ngff_image.d.ts +9 -2
  122. package/script/schemas/ngff_image.d.ts.map +1 -1
  123. package/script/schemas/ngff_image.js +11 -2
  124. package/script/schemas/ome_zarr.d.ts +617 -0
  125. package/script/schemas/ome_zarr.d.ts.map +1 -0
  126. package/script/schemas/ome_zarr.js +211 -0
  127. package/script/schemas/rfc4.d.ts +334 -0
  128. package/script/schemas/rfc4.d.ts.map +1 -0
  129. package/script/schemas/rfc4.js +132 -0
  130. package/script/schemas/units.d.ts +70 -5
  131. package/script/schemas/units.d.ts.map +1 -1
  132. package/script/schemas/units.js +4 -12
  133. package/script/schemas/zarr_metadata.d.ts +10 -4
  134. package/script/schemas/zarr_metadata.d.ts.map +1 -1
  135. package/script/schemas/zarr_metadata.js +23 -2
  136. package/script/types/array_interface.d.ts +7 -0
  137. package/script/types/array_interface.d.ts.map +1 -0
  138. package/script/types/array_interface.js +2 -0
  139. package/script/types/hcs.d.ts +70 -0
  140. package/script/types/hcs.d.ts.map +1 -0
  141. package/script/types/hcs.js +233 -0
  142. package/script/types/methods.d.ts.map +1 -1
  143. package/script/types/methods.js +2 -0
  144. package/script/types/multiscales.d.ts.map +1 -1
  145. package/script/types/ngff_image.d.ts +6 -3
  146. package/script/types/ngff_image.d.ts.map +1 -1
  147. package/script/types/ngff_image.js +13 -1
  148. package/script/types/rfc4.d.ts +94 -0
  149. package/script/types/rfc4.d.ts.map +1 -0
  150. package/script/types/rfc4.js +143 -0
  151. package/script/types/units.d.ts +1 -1
  152. package/script/types/units.d.ts.map +1 -1
  153. package/script/types/zarr_metadata.d.ts +14 -5
  154. package/script/types/zarr_metadata.d.ts.map +1 -1
  155. package/script/utils/create_queue.d.ts +6 -0
  156. package/script/utils/create_queue.d.ts.map +1 -0
  157. package/script/utils/create_queue.js +17 -0
  158. package/script/utils/factory.d.ts +1 -1
  159. package/script/utils/factory.d.ts.map +1 -1
  160. package/script/utils/factory.js +39 -7
  161. package/script/utils/method_metadata.d.ts +10 -0
  162. package/script/utils/method_metadata.d.ts.map +1 -0
  163. package/script/utils/method_metadata.js +40 -0
  164. package/script/utils/validation.d.ts.map +1 -1
  165. package/esm/schemas/lazy_array.d.ts +0 -8
  166. package/esm/schemas/lazy_array.d.ts.map +0 -1
  167. package/esm/schemas/lazy_array.js +0 -7
  168. package/esm/types/lazy_array.d.ts +0 -18
  169. package/esm/types/lazy_array.d.ts.map +0 -1
  170. package/esm/types/lazy_array.js +0 -27
  171. package/script/schemas/lazy_array.d.ts +0 -8
  172. package/script/schemas/lazy_array.d.ts.map +0 -1
  173. package/script/schemas/lazy_array.js +0 -10
  174. package/script/types/lazy_array.d.ts +0 -18
  175. package/script/types/lazy_array.d.ts.map +0 -1
  176. package/script/types/lazy_array.js +0 -31
@@ -0,0 +1,218 @@
1
+ // SPDX-FileCopyrightText: Copyright (c) Fideus Labs LLC
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * Convert NgffImage to ITK-Wasm Image
5
+ */
6
+ import * as zarr from "zarrita";
7
+ import { NgffImage } from "../types/ngff_image.js";
8
+ /**
9
+ * Convert the data type from zarr DataType to ITK-Wasm component type
10
+ */
11
+ function dataTypeToComponentType(dataType) {
12
+ switch (dataType) {
13
+ case "uint8":
14
+ return "uint8";
15
+ case "int8":
16
+ return "int8";
17
+ case "uint16":
18
+ return "uint16";
19
+ case "int16":
20
+ return "int16";
21
+ case "uint32":
22
+ return "uint32";
23
+ case "int32":
24
+ return "int32";
25
+ case "uint64":
26
+ return "uint64";
27
+ case "int64":
28
+ return "int64";
29
+ case "float32":
30
+ return "float32";
31
+ case "float64":
32
+ return "float64";
33
+ default:
34
+ throw new Error(`Unsupported data type: ${dataType}`);
35
+ }
36
+ }
37
+ /**
38
+ * Move the channel dimension to the end (last position) if it exists
39
+ * This follows the ITK convention where vector/RGB components are the last dimension
40
+ */
41
+ function moveChannelDimToLast(ngffImage) {
42
+ const dims = ngffImage.dims;
43
+ const cIndex = dims.indexOf("c");
44
+ if (cIndex === -1 || cIndex === dims.length - 1) {
45
+ // No channel dimension or already at the end
46
+ return ngffImage;
47
+ }
48
+ // Reorder dimensions to move 'c' to the end
49
+ const newDims = [...dims];
50
+ const cDim = newDims.splice(cIndex, 1)[0];
51
+ newDims.push(cDim);
52
+ // Note: We would need to transpose the zarr array data here
53
+ // For now, we'll assume the data is already in the correct order
54
+ // In a full implementation, you'd transpose the zarr array
55
+ return new NgffImage({
56
+ data: ngffImage.data, // TODO: transpose if needed
57
+ dims: newDims,
58
+ scale: ngffImage.scale,
59
+ translation: ngffImage.translation,
60
+ name: ngffImage.name,
61
+ axesUnits: ngffImage.axesUnits,
62
+ axesOrientations: ngffImage.axesOrientations,
63
+ computedCallbacks: ngffImage.computedCallbacks,
64
+ });
65
+ }
66
+ /**
67
+ * Convert an NgffImage to an ITK-Wasm Image, preserving spatial metadata.
68
+ *
69
+ * This function converts NgffImage objects to ITK-Wasm Image format while
70
+ * preserving spatial information like spacing, origin, and direction matrix.
71
+ * Optionally extracts specific time or channel slices.
72
+ *
73
+ * @param ngffImage - The NgffImage to convert
74
+ * @param options - Conversion options
75
+ * @returns Promise resolving to ITK-Wasm Image
76
+ */
77
+ export async function ngffImageToItkImage(ngffImage, options = {}) {
78
+ const { tIndex, cIndex } = options;
79
+ let workingImage = ngffImage;
80
+ // Extract time slice if requested
81
+ if (tIndex !== undefined && workingImage.dims.includes("t")) {
82
+ const tDimIndex = workingImage.dims.indexOf("t");
83
+ const newDims = workingImage.dims.filter((dim) => dim !== "t");
84
+ const newScale = Object.fromEntries(Object.entries(workingImage.scale).filter(([dim]) => dim !== "t"));
85
+ const newTranslation = Object.fromEntries(Object.entries(workingImage.translation).filter(([dim]) => dim !== "t"));
86
+ // Extract the time slice from zarr array
87
+ const selection = new Array(workingImage.data.shape.length).fill(null);
88
+ selection[tDimIndex] = tIndex;
89
+ const sliceData = await zarr.get(workingImage.data, selection);
90
+ // Create new zarr array with reduced dimensions
91
+ const store = new Map();
92
+ const root = zarr.root(store);
93
+ const newShape = workingImage.data.shape.filter((_, i) => i !== tDimIndex);
94
+ const chunkShape = newShape.map((s) => Math.min(s, 256));
95
+ const newArray = await zarr.create(root.resolve("slice"), {
96
+ shape: newShape,
97
+ chunk_shape: chunkShape,
98
+ data_type: workingImage.data.dtype,
99
+ fill_value: 0,
100
+ });
101
+ // Write the slice data
102
+ const fullSelection = new Array(newShape.length).fill(null);
103
+ await zarr.set(newArray, fullSelection, sliceData);
104
+ workingImage = new NgffImage({
105
+ data: newArray,
106
+ dims: newDims,
107
+ scale: newScale,
108
+ translation: newTranslation,
109
+ name: workingImage.name,
110
+ axesUnits: workingImage.axesUnits
111
+ ? Object.fromEntries(Object.entries(workingImage.axesUnits).filter(([dim]) => dim !== "t"))
112
+ : undefined,
113
+ axesOrientations: workingImage.axesOrientations
114
+ ? Object.fromEntries(Object.entries(workingImage.axesOrientations).filter(([dim]) => dim !== "t"))
115
+ : undefined,
116
+ computedCallbacks: workingImage.computedCallbacks,
117
+ });
118
+ }
119
+ // Extract channel slice if requested
120
+ if (cIndex !== undefined && workingImage.dims.includes("c")) {
121
+ const cDimIndex = workingImage.dims.indexOf("c");
122
+ const newDims = workingImage.dims.filter((dim) => dim !== "c");
123
+ const newScale = Object.fromEntries(Object.entries(workingImage.scale).filter(([dim]) => dim !== "c"));
124
+ const newTranslation = Object.fromEntries(Object.entries(workingImage.translation).filter(([dim]) => dim !== "c"));
125
+ // Extract the channel slice from zarr array
126
+ const selection = new Array(workingImage.data.shape.length).fill(null);
127
+ selection[cDimIndex] = cIndex;
128
+ const sliceData = await zarr.get(workingImage.data, selection);
129
+ // Create new zarr array with reduced dimensions
130
+ const store = new Map();
131
+ const root = zarr.root(store);
132
+ const newShape = workingImage.data.shape.filter((_, i) => i !== cDimIndex);
133
+ const chunkShape = newShape.map((s) => Math.min(s, 256));
134
+ const newArray = await zarr.create(root.resolve("slice"), {
135
+ shape: newShape,
136
+ chunk_shape: chunkShape,
137
+ data_type: workingImage.data.dtype,
138
+ fill_value: 0,
139
+ });
140
+ // Write the slice data
141
+ const fullSelection = new Array(newShape.length).fill(null);
142
+ await zarr.set(newArray, fullSelection, sliceData);
143
+ workingImage = new NgffImage({
144
+ data: newArray,
145
+ dims: newDims,
146
+ scale: newScale,
147
+ translation: newTranslation,
148
+ name: workingImage.name,
149
+ axesUnits: workingImage.axesUnits
150
+ ? Object.fromEntries(Object.entries(workingImage.axesUnits).filter(([dim]) => dim !== "c"))
151
+ : undefined,
152
+ axesOrientations: workingImage.axesOrientations
153
+ ? Object.fromEntries(Object.entries(workingImage.axesOrientations).filter(([dim]) => dim !== "c"))
154
+ : undefined,
155
+ computedCallbacks: workingImage.computedCallbacks,
156
+ });
157
+ }
158
+ // Move channel dimension to last position (ITK convention)
159
+ workingImage = moveChannelDimToLast(workingImage);
160
+ const dims = workingImage.dims;
161
+ const data = workingImage.data;
162
+ // Identify ITK spatial dimensions
163
+ const itkDimensionNames = new Set(["x", "y", "z", "t"]);
164
+ const itkDims = dims.filter((dim) => itkDimensionNames.has(dim));
165
+ // Sort ITK dimensions: spatial first (x, y, z), then time
166
+ const sortedItkDims = itkDims.sort((a, b) => {
167
+ const order = ["x", "y", "z", "t"];
168
+ return order.indexOf(a) - order.indexOf(b);
169
+ });
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]
173
+ const spacing = sortedItkDims.map((dim) => workingImage.scale[dim] || 1.0);
174
+ const origin = sortedItkDims.map((dim) => workingImage.translation[dim] || 0.0);
175
+ const size = sortedItkDims.map((dim) => data.shape[dims.indexOf(dim)]);
176
+ const dimension = sortedItkDims.length;
177
+ // Determine component type and pixel type
178
+ const componentType = dataTypeToComponentType(data.dtype);
179
+ let components = 1;
180
+ let pixelType = "Scalar";
181
+ if (dims.includes("c")) {
182
+ components = data.shape[dims.indexOf("c")];
183
+ if (components === 3 && componentType === "uint8") {
184
+ pixelType = "RGB";
185
+ }
186
+ else {
187
+ pixelType =
188
+ "VariableLengthVector";
189
+ }
190
+ }
191
+ // Create ImageType
192
+ const imageType = {
193
+ dimension,
194
+ componentType,
195
+ pixelType,
196
+ components,
197
+ };
198
+ // Read all data from zarr array
199
+ const selection = new Array(data.shape.length).fill(null);
200
+ const dataChunk = await zarr.get(data, selection);
201
+ // Create direction matrix (identity for now)
202
+ const direction = new Float64Array(dimension * dimension);
203
+ for (let i = 0; i < dimension; i++) {
204
+ direction[i * dimension + i] = 1.0;
205
+ }
206
+ // Create ITK-Wasm Image
207
+ const itkImage = {
208
+ imageType,
209
+ name: workingImage.name || "image",
210
+ origin,
211
+ spacing,
212
+ direction,
213
+ size,
214
+ metadata: new Map(),
215
+ data: dataChunk.data, // Cast to handle zarrita's data type
216
+ };
217
+ return itkImage;
218
+ }
@@ -0,0 +1,18 @@
1
+ import { NgffImage } from "../types/ngff_image.js";
2
+ import { Multiscales } from "../types/multiscales.js";
3
+ import { Methods } from "../types/methods.js";
4
+ export { toNgffImage, type ToNgffImageOptions } from "./to_ngff_image.js";
5
+ export interface ToMultiscalesOptions {
6
+ scaleFactors?: (Record<string, number> | number)[];
7
+ method?: Methods;
8
+ chunks?: number | number[] | Record<string, number>;
9
+ }
10
+ /**
11
+ * Generate multiple resolution scales for an NgffImage (simplified version for testing)
12
+ *
13
+ * @param image - Input NgffImage
14
+ * @param options - Configuration options
15
+ * @returns Multiscales object
16
+ */
17
+ export declare function toMultiscales(image: NgffImage, options?: ToMultiscalesOptions): Promise<Multiscales>;
18
+ //# sourceMappingURL=to_multiscales.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to_multiscales.d.ts","sourceRoot":"","sources":["../../src/io/to_multiscales.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAW9C,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE1E,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrD;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,WAAW,CAAC,CAqEtB"}
@@ -0,0 +1,62 @@
1
+ import { Methods } from "../types/methods.js";
2
+ import { createAxis, createDataset, createMetadata, createMultiscales, } from "../utils/factory.js";
3
+ import { getMethodMetadata } from "../utils/method_metadata.js";
4
+ import { downsampleItkWasm } from "../methods/itkwasm.js";
5
+ // Re-export for convenience
6
+ export { toNgffImage } from "./to_ngff_image.js";
7
+ /**
8
+ * Generate multiple resolution scales for an NgffImage (simplified version for testing)
9
+ *
10
+ * @param image - Input NgffImage
11
+ * @param options - Configuration options
12
+ * @returns Multiscales object
13
+ */
14
+ export async function toMultiscales(image, options = {}) {
15
+ const { scaleFactors = [2, 4], method = Methods.ITKWASM_GAUSSIAN, chunks: _chunks, } = options;
16
+ let images;
17
+ // Check if we should perform actual downsampling
18
+ if (method === Methods.ITKWASM_GAUSSIAN ||
19
+ method === Methods.ITKWASM_BIN_SHRINK ||
20
+ method === Methods.ITKWASM_LABEL_IMAGE) {
21
+ // Perform actual downsampling using ITK-Wasm
22
+ const smoothing = method === Methods.ITKWASM_GAUSSIAN
23
+ ? "gaussian"
24
+ : method === Methods.ITKWASM_BIN_SHRINK
25
+ ? "bin_shrink"
26
+ : "label_image";
27
+ images = await downsampleItkWasm(image, scaleFactors, smoothing);
28
+ }
29
+ else {
30
+ // Fallback: create only the base image (no actual downsampling)
31
+ images = [image];
32
+ }
33
+ // Create axes from image dimensions
34
+ const axes = image.dims.map((dim) => {
35
+ if (dim === "x" || dim === "y" || dim === "z") {
36
+ return createAxis(dim, "space", image.axesUnits?.[dim]);
37
+ }
38
+ else if (dim === "c") {
39
+ return createAxis(dim, "channel");
40
+ }
41
+ else if (dim === "t") {
42
+ return createAxis(dim, "time");
43
+ }
44
+ else {
45
+ throw new Error(`Unsupported dimension: ${dim}`);
46
+ }
47
+ });
48
+ // Create datasets for all images
49
+ const datasets = images.map((img, index) => {
50
+ return createDataset(`scale${index}`, img.dims.map((dim) => img.scale[dim]), img.dims.map((dim) => img.translation[dim]));
51
+ });
52
+ // Create metadata with method information
53
+ const methodMetadata = getMethodMetadata(method);
54
+ const metadata = createMetadata(axes, datasets, image.name);
55
+ // The 'type' field, part of the OME-Zarr specification, in metadata is used here to
56
+ // record the downsampling method applied to generate multiscale images for provenance.
57
+ metadata.type = method;
58
+ if (methodMetadata) {
59
+ metadata.metadata = methodMetadata;
60
+ }
61
+ return createMultiscales(images, metadata, scaleFactors, method);
62
+ }
@@ -0,0 +1,17 @@
1
+ import { NgffImage } from "../types/ngff_image.js";
2
+ export interface ToNgffImageOptions {
3
+ dims?: string[];
4
+ scale?: Record<string, number>;
5
+ translation?: Record<string, number>;
6
+ name?: string;
7
+ shape?: number[];
8
+ }
9
+ /**
10
+ * Convert array data to NgffImage
11
+ *
12
+ * @param data - Input data as typed array or regular array
13
+ * @param options - Configuration options for NgffImage creation
14
+ * @returns NgffImage instance
15
+ */
16
+ export declare function toNgffImage(data: ArrayLike<number> | number[][] | number[][][], options?: ToNgffImageOptions): Promise<NgffImage>;
17
+ //# sourceMappingURL=to_ngff_image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to_ngff_image.d.ts","sourceRoot":"","sources":["../../src/io/to_ngff_image.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGnD,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE,EACnD,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,SAAS,CAAC,CAqIpB"}
@@ -0,0 +1,136 @@
1
+ import * as zarr from "zarrita";
2
+ import { NgffImage } from "../types/ngff_image.js";
3
+ /**
4
+ * Convert array data to NgffImage
5
+ *
6
+ * @param data - Input data as typed array or regular array
7
+ * @param options - Configuration options for NgffImage creation
8
+ * @returns NgffImage instance
9
+ */
10
+ export async function toNgffImage(data, options = {}) {
11
+ const { dims = ["y", "x"], scale = {}, translation = {}, name = "image", shape: explicitShape, } = options;
12
+ // Determine data shape and create typed array
13
+ let typedData;
14
+ let shape;
15
+ if (Array.isArray(data)) {
16
+ // Handle multi-dimensional arrays
17
+ if (Array.isArray(data[0])) {
18
+ if (Array.isArray(data[0][0])) {
19
+ // 3D array
20
+ const d3 = data;
21
+ shape = [d3.length, d3[0].length, d3[0][0].length];
22
+ typedData = new Float32Array(shape[0] * shape[1] * shape[2]);
23
+ let idx = 0;
24
+ for (let i = 0; i < shape[0]; i++) {
25
+ for (let j = 0; j < shape[1]; j++) {
26
+ for (let k = 0; k < shape[2]; k++) {
27
+ typedData[idx++] = d3[i][j][k];
28
+ }
29
+ }
30
+ }
31
+ }
32
+ else {
33
+ // 2D array
34
+ const d2 = data;
35
+ shape = [d2.length, d2[0].length];
36
+ typedData = new Float32Array(shape[0] * shape[1]);
37
+ let idx = 0;
38
+ for (let i = 0; i < shape[0]; i++) {
39
+ for (let j = 0; j < shape[1]; j++) {
40
+ typedData[idx++] = d2[i][j];
41
+ }
42
+ }
43
+ }
44
+ }
45
+ else {
46
+ // 1D array
47
+ const d1 = data;
48
+ shape = [d1.length];
49
+ typedData = new Float32Array(d1);
50
+ }
51
+ }
52
+ else {
53
+ // ArrayLike (already a typed array)
54
+ // Use explicit shape if provided, otherwise infer from data length and dims
55
+ if (explicitShape) {
56
+ shape = [...explicitShape];
57
+ }
58
+ else {
59
+ // Try to infer shape - this is a best guess
60
+ shape = [data.length];
61
+ }
62
+ // Preserve the original typed array type
63
+ if (data instanceof Uint8Array) {
64
+ typedData = data;
65
+ }
66
+ else if (data instanceof Uint16Array) {
67
+ typedData = data;
68
+ }
69
+ else {
70
+ typedData = new Float32Array(data);
71
+ }
72
+ }
73
+ // Adjust shape to match dims length if not explicitly provided
74
+ if (!explicitShape) {
75
+ while (shape.length < dims.length) {
76
+ shape.unshift(1);
77
+ }
78
+ }
79
+ if (shape.length !== dims.length) {
80
+ throw new Error(`Shape dimensionality (${shape.length}) must match dims length (${dims.length})`);
81
+ }
82
+ // Create in-memory zarr store and array
83
+ const store = new Map();
84
+ const root = zarr.root(store);
85
+ // Calculate appropriate chunk size
86
+ const chunkShape = shape.map((dim) => Math.min(dim, 256));
87
+ const zarrArray = await zarr.create(root.resolve("data"), {
88
+ shape,
89
+ chunk_shape: chunkShape,
90
+ data_type: "float32",
91
+ fill_value: 0,
92
+ });
93
+ // Write data to zarr array
94
+ await zarr.set(zarrArray, [], {
95
+ data: typedData,
96
+ shape,
97
+ stride: calculateStride(shape),
98
+ });
99
+ // Create scale and translation records with defaults
100
+ const fullScale = {};
101
+ const fullTranslation = {};
102
+ const spatialDims = new Set(["x", "y", "z"]);
103
+ for (const dim of dims) {
104
+ // Only set defaults for spatial dimensions
105
+ if (spatialDims.has(dim)) {
106
+ fullScale[dim] = scale[dim] ?? 1.0;
107
+ fullTranslation[dim] = translation[dim] ?? 0.0;
108
+ }
109
+ else {
110
+ // For non-spatial dimensions, only include if explicitly provided
111
+ if (scale[dim] !== undefined) {
112
+ fullScale[dim] = scale[dim];
113
+ }
114
+ if (translation[dim] !== undefined) {
115
+ fullTranslation[dim] = translation[dim];
116
+ }
117
+ }
118
+ }
119
+ return new NgffImage({
120
+ data: zarrArray,
121
+ dims,
122
+ scale: fullScale,
123
+ translation: fullTranslation,
124
+ name,
125
+ axesUnits: undefined,
126
+ computedCallbacks: undefined,
127
+ });
128
+ }
129
+ function calculateStride(shape) {
130
+ const stride = new Array(shape.length);
131
+ stride[shape.length - 1] = 1;
132
+ for (let i = shape.length - 2; i >= 0; i--) {
133
+ stride[i] = stride[i + 1] * shape[i + 1];
134
+ }
135
+ return stride;
136
+ }
@@ -1,9 +1,10 @@
1
+ import * as zarr from "zarrita";
1
2
  import type { Multiscales } from "../types/multiscales.js";
3
+ import type { MemoryStore } from "./from_ngff_zarr.js";
2
4
  export interface ToNgffZarrOptions {
3
5
  overwrite?: boolean;
4
6
  version?: "0.4" | "0.5";
5
- useTensorstore?: boolean;
6
7
  chunksPerShard?: number | number[] | Record<string, number>;
7
8
  }
8
- export declare function toNgffZarr(_storePath: string, _multiscales: Multiscales, options?: ToNgffZarrOptions): Promise<void>;
9
+ export declare function toNgffZarr(store: string | MemoryStore | zarr.FetchStore, multiscales: Multiscales, options?: ToNgffZarrOptions): Promise<void>;
9
10
  //# sourceMappingURL=to_ngff_zarr.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"to_ngff_zarr.d.ts","sourceRoot":"","sources":["../../src/io/to_ngff_zarr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7D;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,WAAW,EACzB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAuBf"}
1
+ {"version":3,"file":"to_ngff_zarr.d.ts","sourceRoot":"","sources":["../../src/io/to_ngff_zarr.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7D;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC,UAAU,EAC7C,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA0Ff"}