@fideus-labs/ngff-zarr 0.8.0 → 0.10.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 (41) hide show
  1. package/esm/browser-mod.d.ts +2 -2
  2. package/esm/browser-mod.d.ts.map +1 -1
  3. package/esm/browser-mod.js +2 -2
  4. package/esm/browser-mod.js.map +1 -1
  5. package/esm/io/from_ngff_zarr-browser.d.ts +3 -2
  6. package/esm/io/from_ngff_zarr-browser.d.ts.map +1 -1
  7. package/esm/io/from_ngff_zarr-browser.js +14 -4
  8. package/esm/io/from_ngff_zarr-browser.js.map +1 -1
  9. package/esm/io/from_ngff_zarr.d.ts +1 -1
  10. package/esm/io/from_ngff_zarr.d.ts.map +1 -1
  11. package/esm/io/from_ngff_zarr.js +16 -9
  12. package/esm/io/from_ngff_zarr.js.map +1 -1
  13. package/esm/mod.d.ts +1 -1
  14. package/esm/mod.d.ts.map +1 -1
  15. package/esm/mod.js +1 -1
  16. package/esm/mod.js.map +1 -1
  17. package/esm/utils/compute_omero-shared.d.ts +12 -0
  18. package/esm/utils/compute_omero-shared.d.ts.map +1 -1
  19. package/esm/utils/compute_omero-shared.js +28 -0
  20. package/esm/utils/compute_omero-shared.js.map +1 -1
  21. package/esm/utils/compute_omero.d.ts +10 -38
  22. package/esm/utils/compute_omero.d.ts.map +1 -1
  23. package/esm/utils/compute_omero.js +383 -79
  24. package/esm/utils/compute_omero.js.map +1 -1
  25. package/esm/utils/omero_worker_rpc.d.ts +37 -0
  26. package/esm/utils/omero_worker_rpc.d.ts.map +1 -0
  27. package/esm/utils/omero_worker_rpc.js +156 -0
  28. package/esm/utils/omero_worker_rpc.js.map +1 -0
  29. package/esm/workers/omero_codec_worker.d.ts +2 -0
  30. package/esm/workers/omero_codec_worker.d.ts.map +1 -0
  31. package/esm/workers/omero_codec_worker.js +215 -0
  32. package/esm/workers/omero_codec_worker.js.map +1 -0
  33. package/package.json +2 -3
  34. package/esm/utils/compute_omero-browser.d.ts +0 -45
  35. package/esm/utils/compute_omero-browser.d.ts.map +0 -1
  36. package/esm/utils/compute_omero-browser.js +0 -250
  37. package/esm/utils/compute_omero-browser.js.map +0 -1
  38. package/esm/workers/compute_omero_worker.d.ts +0 -47
  39. package/esm/workers/compute_omero_worker.d.ts.map +0 -1
  40. package/esm/workers/compute_omero_worker.js +0 -113
  41. package/esm/workers/compute_omero_worker.js.map +0 -1
@@ -1,250 +0,0 @@
1
- // SPDX-FileCopyrightText: Copyright (c) Fideus Labs LLC
2
- // SPDX-License-Identifier: MIT
3
- /**
4
- * Browser-specific OMERO metadata computation using WebWorker.
5
- * This module offloads CPU-intensive statistics computation to a WebWorker
6
- * to prevent blocking the main thread.
7
- *
8
- * Features:
9
- * - WebWorker-based computation via Comlink
10
- * - Chunked streaming for memory efficiency with large images
11
- * - Automatic fallback to main thread if WebWorker unavailable
12
- * - Inline worker code (bundled as Blob URL)
13
- */
14
- import * as Comlink from "comlink";
15
- import { buildOmeroFromAccumulators, createAccumulator, extractChannel, updateAccumulator, validateQuantiles, } from "./compute_omero-shared.js";
16
- import { zarrGet } from "./worker_pool.js";
17
- // Re-export shared utilities for convenience
18
- export { getDefaultColors, GLASBEY_COLORS, } from "./compute_omero-shared.js";
19
- // Worker state
20
- let worker = null;
21
- let workerProxy = null;
22
- let workerSupported = null;
23
- let workerBlobUrl = null;
24
- // Chunk size for streaming (256K elements = ~1MB for float32)
25
- const CHUNK_SIZE = 256 * 1024;
26
- /**
27
- * Check if WebWorkers are supported in this environment.
28
- */
29
- function isWorkerSupported() {
30
- if (workerSupported === null) {
31
- try {
32
- workerSupported = typeof Worker !== "undefined" &&
33
- typeof Blob !== "undefined" &&
34
- typeof URL !== "undefined" &&
35
- typeof URL.createObjectURL === "function";
36
- }
37
- catch {
38
- workerSupported = false;
39
- }
40
- }
41
- return workerSupported;
42
- }
43
- /**
44
- * Get or create the worker proxy.
45
- * Returns null if workers are not supported.
46
- */
47
- function getWorkerProxy() {
48
- if (!isWorkerSupported()) {
49
- return null;
50
- }
51
- if (!workerProxy) {
52
- try {
53
- // In bundled builds, the Worker constructor line below is replaced with
54
- // inline Blob URL code that assigns workerBlobUrl. In non-bundled mode,
55
- // we use a module URL and there's no Blob URL to clean up.
56
- workerBlobUrl = null; // Will be overwritten in bundled mode
57
- worker = (() => {
58
- const workerCode = `var L=Symbol("Comlink.proxy"),q=Symbol("Comlink.endpoint"),v=Symbol("Comlink.releaseProxy"),y=Symbol("Comlink.finalizer"),B=Symbol("Comlink.thrown"),P=t=>typeof t=="object"&&t!==null||typeof t=="function",H={canHandle:t=>P(t)&&t[L],serialize(t){let{port1:e,port2:n}=new MessageChannel;return w(t,e),[n,[n]]},deserialize(t){return t.start(),j(t)}},\$={canHandle:t=>P(t)&&B in t,serialize({value:t}){let e;return t instanceof Error?e={isError:!0,value:{message:t.message,name:t.name,stack:t.stack}}:e={isError:!1,value:t},[e,[]]},deserialize(t){throw t.isError?Object.assign(new Error(t.value.message),t.value):t.value}},I=new Map([["proxy",H],["throw",\$]]);function U(t,e){for(let n of t)if(e===n||n==="*"||n instanceof RegExp&&n.test(e))return!0;return!1}function w(t,e=globalThis,n=["*"]){e.addEventListener("message",function o(r){if(!r||!r.data)return;if(!U(n,r.origin)){console.warn(\`Invalid origin '\${r.origin}' for comlink proxy\`);return}let{id:a,type:c,path:u}=Object.assign({path:[]},r.data),l=(r.data.argumentList||[]).map(E),i;try{let s=u.slice(0,-1).reduce((f,A)=>f[A],t),F=u.reduce((f,A)=>f[A],t);switch(c){case"GET":i=F;break;case"SET":s[u.slice(-1)[0]]=E(r.data.value),i=!0;break;case"APPLY":i=F.apply(s,l);break;case"CONSTRUCT":{let f=new F(...l);i=Z(f)}break;case"ENDPOINT":{let{port1:f,port2:A}=new MessageChannel;w(t,A),i=V(f,[f])}break;case"RELEASE":i=void 0;break;default:return}}catch(s){i={value:s,[B]:0}}Promise.resolve(i).catch(s=>({value:s,[B]:0})).then(s=>{let[F,f]=p(s);e.postMessage(Object.assign(Object.assign({},F),{id:a}),f),c==="RELEASE"&&(e.removeEventListener("message",o),T(e),y in t&&typeof t[y]=="function"&&t[y]())}).catch(s=>{let[F,f]=p({value:new TypeError("Unserializable return value"),[B]:0});e.postMessage(Object.assign(Object.assign({},F),{id:a}),f)})}),e.start&&e.start()}function G(t){return t.constructor.name==="MessagePort"}function T(t){G(t)&&t.close()}function j(t,e){let n=new Map;return t.addEventListener("message",function(r){let{data:a}=r;if(!a||!a.id)return;let c=n.get(a.id);if(c)try{c(a)}finally{n.delete(a.id)}}),x(t,n,[],e)}function h(t){if(t)throw new Error("Proxy has been released and is not useable")}function k(t){return m(t,new Map,{type:"RELEASE"}).then(()=>{T(t)})}var g=new WeakMap,d="FinalizationRegistry"in globalThis&&new FinalizationRegistry(t=>{let e=(g.get(t)||0)-1;g.set(t,e),e===0&&k(t)});function Q(t,e){let n=(g.get(e)||0)+1;g.set(e,n),d&&d.register(t,e,t)}function W(t){d&&d.unregister(t)}function x(t,e,n=[],o=function(){}){let r=!1,a=new Proxy(o,{get(c,u){if(h(r),u===v)return()=>{W(a),k(t),e.clear(),r=!0};if(u==="then"){if(n.length===0)return{then:()=>a};let l=m(t,e,{type:"GET",path:n.map(i=>i.toString())}).then(E);return l.then.bind(l)}return x(t,e,[...n,u])},set(c,u,l){h(r);let[i,s]=p(l);return m(t,e,{type:"SET",path:[...n,u].map(F=>F.toString()),value:i},s).then(E)},apply(c,u,l){h(r);let i=n[n.length-1];if(i===q)return m(t,e,{type:"ENDPOINT"}).then(E);if(i==="bind")return x(t,e,n.slice(0,-1));let[s,F]=O(l);return m(t,e,{type:"APPLY",path:n.map(f=>f.toString()),argumentList:s},F).then(E)},construct(c,u){h(r);let[l,i]=O(u);return m(t,e,{type:"CONSTRUCT",path:n.map(s=>s.toString()),argumentList:l},i).then(E)}});return Q(a,t),a}function Y(t){return Array.prototype.concat.apply([],t)}function O(t){let e=t.map(p);return[e.map(n=>n[0]),Y(e.map(n=>n[1]))]}var z=new WeakMap;function V(t,e){return z.set(t,e),t}function Z(t){return Object.assign(t,{[L]:!0})}function p(t){for(let[e,n]of I)if(n.canHandle(t)){let[o,r]=n.serialize(t);return[{type:"HANDLER",name:e,value:o},r]}return[{type:"RAW",value:t},z.get(t)||[]]}function E(t){switch(t.type){case"HANDLER":return I.get(t.name).deserialize(t.value);case"RAW":return t.value}}function m(t,e,n,o){return new Promise(r=>{let a=X();e.set(a,r),t.start&&t.start(),t.postMessage(Object.assign({id:a},n),o)})}function X(){return new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-")}var _=["30A2DA","FC4F30","E5AE38","6D904F","8B8B8B","17BECF","9467BD","D62728","1F77B4","E377C2","8C564B","BCBD22","3A0183","004300","0FFFA9","5E0040","C6BDFF","425052","B80080","FFB7B3","7D0200","6126FF","FFFF9A","AEC9AB","00867C","553A00","94FCFF","00BF00","7D00A0","AB7200","91FF00","01BE8A","00457B","C8826F","FF1F83","DD00FF","057400","644461","888FFF","FFB6F4","536237","CE85FF","686A84","BEB4BE","A56089","95D3FF","0100F8","FF8002","8B2945","ADA06D","53458B","C8FFD9","AA4600","FF798F","83D371","909EBF","9400F5","EBD09B","AD8BB1","00634A","FFDC00","887751","7EABA3","000097","F500C6","653329","006678","04E3C8","A737AE","C5DBE1","4D6EFF","9B9301","CD586B","EFDEFE","795A00","5F889A","B4FF92","5E726B","520066","058751","84206F","3C9605","657300","F1A06C","5F5045","BD004A","D06827","D796AB","895DFF","826C76","2B55B9","6E7CBB","E7D5D3","5D0018","7C3B01","80B17D","C8D97D","00E83B","7CB2FF","FF55FF","A42721","1DE4FF","7DAF3B","7B4B91","E0FF48","6B00C4","CDA897","BE63C4","89CDCE","4603C8","5E9279","414A01","05A79D","CF8C37","FFF8D0","435471","B544FF","CF4993","CFA4DF","94D400","A794DA","2DA558","8DE3B6","A4A99D","6C5CB7","FF7E5E","A7838A","AFBED8","2AC4FF","A6683D","F691FE","874B64","FF0C4B","215E23","4292FF","87839D","672D45","B14F41","004E53","5F1B00","AD4167","503267","D6FFFD","7FB5D1","A9B969","FF96CB","C87495","365039","FFD063","5E5862","879476","A978FF","03C863","E7BED4","D4E3D0","876790","897C27","CDDCFF","AA676B","323474","FF5EA9","009BB0","71FFDD","785C38","50659B","CC00B3","577B55","516E7B","015F92","AABDBE","017F99","04DD97","873A2C","F0968E","75C6AA","70695D","CCDC09","AF8557","D80075","9D3F81","D94500","DD6754","5FFF79","D5B173","62265E","BAA23D","D9F2B3","57028F","A19BAA","4D4A27","A4A9FF","ACE8DB","995901","AC00E2","47822F","CBC3AD","00C5B6","615378","336D68","A59280","8499A2","FD5764","7096D2","728D07","7F004C","1530A0","D1C1E2","C985D0","6C454B","7F0024","00A279","B2A9CF","F90000","B0E9FF","939E50","727A82","D92E55","476101","0059FF","7740B5","ACE460","674525","525D51","957368","A9E49A","A30058","D962F6","8E7DCF","FFBD93","A30092","9AFFB9","A7C2FF","F46200","E5F0FF","B89CA4","609694","FF9F35","8C2900","726B32","DF824E","AF7BD5","BC2D00","7B6FA3","484362","C7A3FF","004D28","C4C68E","E048D7","E7E965","E5C10B","00F4F1","9F5BA2","4C41B7","65338E","767E6C","A98A36"];function K(t){return t===1?["FFFFFF"]:Array.from({length:t},(e,n)=>_[n%_.length])}function b(t){let[e,n]=t;if(!(e>=0&&e<=1))throw new Error(\`Low quantile must be between 0 and 1, got \${e}\`);if(!(n>=0&&n<=1))throw new Error(\`High quantile must be between 0 and 1, got \${n}\`);if(e>=n)throw new Error(\`Low quantile must be less than high quantile, got (\${e}, \${n})\`)}function tt(t){if(!/^[0-9A-Fa-f]{6}\$/.test(t))throw new Error(\`Color must be a 6-digit hexadecimal string without # prefix, got '\${t}'\`)}function R(t,e){if(t.length===0)return NaN;if(t.length===1)return t[0];let n=e*(t.length-1),o=Math.floor(n),r=Math.ceil(n),a=n-o;return o===r?t[o]:t[o]*(1-a)+t[r]*a}function N(){return{min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY,sample:[],count:0}}function D(t,e){for(let n=0;n<e.length;n++){let o=e[n];if(!Number.isNaN(o)){if(o<t.min&&(t.min=o),o>t.max&&(t.max=o),t.sample.length<1e4)t.sample.push(o);else{let r=Math.floor(Math.random()*(t.count+1));r<1e4&&(t.sample[r]=o)}t.count++}}}function et(t,e){if(t.count===0)return{min:NaN,max:NaN,qLow:NaN,qHigh:NaN};t.sample.sort((r,a)=>r-a);let n=R(t.sample,e[0]),o=R(t.sample,e[1]);return{min:t.min,max:t.max,qLow:n,qHigh:o}}function S(t,e,n,o){let r=e[o],a=1;for(let s=o+1;s<e.length;s++)a*=e[s];let c=1;for(let s=0;s<o;s++)c*=e[s];let u=c*a,l=new Array(u),i=0;for(let s=0;s<c;s++){let f=s*r*a+n*a;for(let A=0;A<a;A++)l[i++]=t[f+A]}return l}function M(t,e,n,o){let r=t.length,a;if(n!==void 0){if(n.length<r)throw new Error(\`Not enough colors provided. Got \${n.length}, need \${r}.\`);for(let l of n.slice(0,r))tt(l);a=n.slice(0,r)}else a=K(r);let c;if(o!==void 0){if(o.length<r)throw new Error(\`Not enough labels provided. Got \${o.length}, need \${r}.\`);c=o.slice(0,r)}else c=Array(r).fill("");return{channels:t.map((l,i)=>{let s=et(l,e),F={min:s.min,max:s.max,start:s.qLow,end:s.qHigh};return{color:a[i],window:F,label:c[i]}})}}var C=null,nt={initializeComputation(t){b(t.quantiles);let e=t.dims.indexOf("c"),n=e!==-1?t.shape[e]:1;C={accumulators:Array.from({length:n},()=>N()),input:t}},processChunk(t){if(!C)throw new Error("Computation not initialized. Call initializeComputation first.");let{accumulators:e,input:n}=C,{shape:o,dims:r}=n,{chunkData:a}=t,c=r.indexOf("c");if(c!==-1)for(let l=0;l<e.length;l++){let i=S(a,o,l,c);D(e[l],i)}else D(e[0],a)},finalizeComputation(){if(!C)throw new Error("Computation not initialized. Call initializeComputation first.");let{accumulators:t,input:e}=C,n=M(t,e.quantiles,e.colors,e.labels);return C=null,n},computeOmero(t,e){b(e.quantiles);let{shape:n,dims:o,quantiles:r,colors:a,labels:c}=e,u=o.indexOf("c"),l=u!==-1,i=l?n[u]:1,s=Array.from({length:i},()=>N());if(l)for(let F=0;F<i;F++){let f=S(t,n,F,u);D(s[F],f)}else D(s[0],t);return M(s,r,a,c)},ping(){return"pong"}};w(nt);
59
- /*! Bundled license information:
60
-
61
- comlink/dist/esm/comlink.mjs:
62
- (**
63
- * @license
64
- * Copyright 2019 Google LLC
65
- * SPDX-License-Identifier: Apache-2.0
66
- *)
67
- */
68
- `;
69
- const blob = new Blob([workerCode], { type: "application/javascript" });
70
- const url = URL.createObjectURL(blob);
71
- workerBlobUrl = url;
72
- return new Worker(url, { type: "module" });
73
- })();
74
- workerProxy = Comlink.wrap(worker);
75
- }
76
- catch (e) {
77
- // Worker creation failed, fall back to main thread
78
- console.warn("Failed to create OMERO computation worker:", e);
79
- workerSupported = false;
80
- return null;
81
- }
82
- }
83
- return workerProxy;
84
- }
85
- /**
86
- * Compute OMERO metadata on the main thread (fallback implementation).
87
- * Used when WebWorker is not available.
88
- */
89
- async function computeOmeroMainThread(image, options = {}) {
90
- const quantiles = options.quantiles ?? [0.02, 0.98];
91
- validateQuantiles(quantiles);
92
- const dims = image.dims;
93
- const shape = image.data.shape;
94
- // Check if there's a channel dimension
95
- const cIndex = dims.indexOf("c");
96
- const hasChannelDim = cIndex !== -1;
97
- const nChannels = hasChannelDim ? shape[cIndex] : 1;
98
- // Read all data from the zarr array
99
- const result = await zarrGet(image.data);
100
- const fullData = result.data;
101
- // Create accumulators for each channel
102
- const accumulators = Array.from({ length: nChannels }, () => createAccumulator());
103
- if (hasChannelDim) {
104
- // Multi-channel: extract each channel and compute statistics
105
- for (let chIdx = 0; chIdx < nChannels; chIdx++) {
106
- const channelData = extractChannel(fullData, shape, chIdx, cIndex);
107
- updateAccumulator(accumulators[chIdx], channelData);
108
- }
109
- }
110
- else {
111
- // Single channel: compute directly
112
- updateAccumulator(accumulators[0], fullData);
113
- }
114
- return buildOmeroFromAccumulators(accumulators, quantiles, options.colors, options.labels);
115
- }
116
- /**
117
- * Compute OMERO metadata from an NgffImage using WebWorker.
118
- *
119
- * This function computes visualization parameters (OMERO metadata) from image data:
120
- * - min/max: The actual data range
121
- * - start/end: Display window based on quantiles (default 2% and 98%)
122
- *
123
- * For multi-channel images (with 'c' dimension), statistics are computed
124
- * separately for each channel, resulting in per-channel OMERO windows.
125
- *
126
- * The computation is performed in a WebWorker to avoid blocking the main thread.
127
- * If WebWorkers are not available, falls back to main thread computation.
128
- *
129
- * @param image - The NgffImage to compute metadata for
130
- * @param options - Optional configuration for quantiles, colors, and labels
131
- * @returns Promise resolving to Omero metadata with computed window parameters
132
- */
133
- export async function computeOmeroFromNgffImage(image, options = {}) {
134
- const api = getWorkerProxy();
135
- // Fallback to main thread if worker unavailable
136
- if (!api) {
137
- return computeOmeroMainThread(image, options);
138
- }
139
- try {
140
- const quantiles = options.quantiles ?? [0.02, 0.98];
141
- const shape = image.data.shape;
142
- const dims = image.dims;
143
- // Read data from zarr array
144
- const result = await zarrGet(image.data);
145
- const fullData = result.data;
146
- const totalSize = fullData.length;
147
- // For small datasets, use single-call API
148
- if (totalSize <= CHUNK_SIZE * 2) {
149
- // Transfer the data buffer to the worker
150
- const typedArray = fullData;
151
- // Create a copy of the buffer that we can transfer
152
- const buffer = new ArrayBuffer(typedArray.byteLength);
153
- const view = new Uint8Array(buffer);
154
- view.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength));
155
- const TypedArrayConstructor = typedArray.constructor;
156
- return await api.computeOmero(Comlink.transfer(new TypedArrayConstructor(buffer), [buffer]), {
157
- shape,
158
- dims,
159
- quantiles: quantiles,
160
- colors: options.colors,
161
- labels: options.labels,
162
- });
163
- }
164
- // For large datasets, use streaming API
165
- await api.initializeComputation({
166
- shape,
167
- dims,
168
- quantiles: quantiles,
169
- colors: options.colors,
170
- labels: options.labels,
171
- });
172
- // Stream data in chunks
173
- const typedArray = fullData;
174
- for (let offset = 0; offset < totalSize; offset += CHUNK_SIZE) {
175
- const end = Math.min(offset + CHUNK_SIZE, totalSize);
176
- const chunk = typedArray.slice(offset, end);
177
- // Create a copy of the chunk buffer that we can transfer
178
- const chunkBuffer = new ArrayBuffer(chunk.byteLength);
179
- const chunkView = new Uint8Array(chunkBuffer);
180
- chunkView.set(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength));
181
- const ChunkConstructor = chunk.constructor;
182
- await api.processChunk({
183
- chunkData: Comlink.transfer(new ChunkConstructor(chunkBuffer), [
184
- chunkBuffer,
185
- ]),
186
- });
187
- }
188
- // Finalize and return result
189
- return await api.finalizeComputation();
190
- }
191
- catch (error) {
192
- // Fallback to main thread on any error
193
- console.warn("WebWorker OMERO computation failed, falling back to main thread:", error);
194
- return computeOmeroMainThread(image, options);
195
- }
196
- }
197
- /**
198
- * Compute OMERO metadata from a Multiscales object using WebWorker.
199
- *
200
- * This is a convenience function that computes OMERO metadata from the
201
- * highest resolution image in a multiscales pyramid for accurate statistics.
202
- *
203
- * @param multiscales - The Multiscales object to compute metadata for
204
- * @param options - Optional configuration for quantiles, colors, and labels
205
- * @returns Promise resolving to Omero metadata with computed window parameters
206
- */
207
- export async function computeOmeroFromMultiscales(multiscales, options = {}) {
208
- if (!multiscales.images || multiscales.images.length === 0) {
209
- throw new Error("Multiscales has no images");
210
- }
211
- // Always use the highest resolution (first) image for accurate statistics
212
- const image = multiscales.images[0];
213
- const computeOptions = {};
214
- if (options.quantiles !== undefined) {
215
- computeOptions.quantiles = options.quantiles;
216
- }
217
- if (options.colors !== undefined) {
218
- computeOptions.colors = options.colors;
219
- }
220
- if (options.labels !== undefined) {
221
- computeOptions.labels = options.labels;
222
- }
223
- return await computeOmeroFromNgffImage(image, computeOptions);
224
- }
225
- /**
226
- * Terminate the OMERO computation worker and release resources.
227
- * Call this when you're done with OMERO computations to free memory.
228
- */
229
- export function terminateOmeroWorker() {
230
- if (workerProxy) {
231
- workerProxy[Comlink.releaseProxy]();
232
- workerProxy = null;
233
- }
234
- if (worker) {
235
- worker.terminate();
236
- worker = null;
237
- }
238
- if (workerBlobUrl) {
239
- URL.revokeObjectURL(workerBlobUrl);
240
- workerBlobUrl = null;
241
- }
242
- }
243
- /**
244
- * Check if the OMERO computation will use a WebWorker.
245
- * Useful for testing or conditional logic.
246
- */
247
- export function isUsingWorker() {
248
- return isWorkerSupported() && getWorkerProxy() !== null;
249
- }
250
- //# sourceMappingURL=compute_omero-browser.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compute_omero-browser.js","sourceRoot":"","sources":["../../src/utils/compute_omero-browser.ts"],"names":[],"mappings":"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"}
@@ -1,47 +0,0 @@
1
- import { type ComputeOmeroChunkInput, type ComputeOmeroWorkerInput } from "../utils/compute_omero-shared.js";
2
- import type { Omero } from "../types/zarr_metadata.js";
3
- /**
4
- * Worker API exposed via Comlink.
5
- *
6
- * IMPORTANT: This worker maintains global state and does not support
7
- * concurrent computations. Only one computation can be active at a time.
8
- * If initializeComputation is called while another computation is in
9
- * progress, the previous computation state will be lost.
10
- *
11
- * The typical workflow is:
12
- * 1. initializeComputation() - Start a new computation
13
- * 2. processChunk() - Call multiple times to stream data
14
- * 3. finalizeComputation() - Get results and reset state
15
- */
16
- declare const workerApi: {
17
- /**
18
- * Initialize a new OMERO computation.
19
- * Must be called before processChunk.
20
- *
21
- * WARNING: This will overwrite any existing computation state.
22
- * Do not call this if another computation is in progress.
23
- */
24
- initializeComputation(input: ComputeOmeroWorkerInput): void;
25
- /**
26
- * Process a chunk of data.
27
- * Call this multiple times for streaming large datasets.
28
- */
29
- processChunk(chunkInput: ComputeOmeroChunkInput): void;
30
- /**
31
- * Finalize computation and return OMERO metadata.
32
- * Resets state after returning.
33
- */
34
- finalizeComputation(): Omero;
35
- /**
36
- * Compute OMERO metadata in a single call (non-streaming).
37
- * Useful for smaller datasets where streaming overhead isn't needed.
38
- */
39
- computeOmero(data: ArrayLike<number>, input: ComputeOmeroWorkerInput): Omero;
40
- /**
41
- * Check if worker is ready.
42
- */
43
- ping(): string;
44
- };
45
- export type ComputeOmeroWorkerApi = typeof workerApi;
46
- export {};
47
- //# sourceMappingURL=compute_omero_worker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compute_omero_worker.d.ts","sourceRoot":"","sources":["../../src/workers/compute_omero_worker.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAK7B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAYvD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,SAAS;IACb;;;;;;OAMG;iCAC0B,uBAAuB,GAAG,IAAI;IAe3D;;;OAGG;6BACsB,sBAAsB,GAAG,IAAI;IA0BtD;;;OAGG;2BACoB,KAAK;IAqB5B;;;OAGG;uBAEK,SAAS,CAAC,MAAM,CAAC,SAChB,uBAAuB,GAC7B,KAAK;IA4BR;;OAEG;YACK,MAAM;CAGf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,OAAO,SAAS,CAAC"}
@@ -1,113 +0,0 @@
1
- // SPDX-FileCopyrightText: Copyright (c) Fideus Labs LLC
2
- // SPDX-License-Identifier: MIT
3
- /**
4
- * WebWorker for computing OMERO metadata.
5
- * This worker performs CPU-intensive statistics computation off the main thread.
6
- */
7
- import * as Comlink from "comlink";
8
- import { buildOmeroFromAccumulators, createAccumulator, extractChannel, updateAccumulator, validateQuantiles, } from "../utils/compute_omero-shared.js";
9
- let currentState = null;
10
- /**
11
- * Worker API exposed via Comlink.
12
- *
13
- * IMPORTANT: This worker maintains global state and does not support
14
- * concurrent computations. Only one computation can be active at a time.
15
- * If initializeComputation is called while another computation is in
16
- * progress, the previous computation state will be lost.
17
- *
18
- * The typical workflow is:
19
- * 1. initializeComputation() - Start a new computation
20
- * 2. processChunk() - Call multiple times to stream data
21
- * 3. finalizeComputation() - Get results and reset state
22
- */
23
- const workerApi = {
24
- /**
25
- * Initialize a new OMERO computation.
26
- * Must be called before processChunk.
27
- *
28
- * WARNING: This will overwrite any existing computation state.
29
- * Do not call this if another computation is in progress.
30
- */
31
- initializeComputation(input) {
32
- validateQuantiles(input.quantiles);
33
- const cIndex = input.dims.indexOf("c");
34
- const nChannels = cIndex !== -1 ? input.shape[cIndex] : 1;
35
- currentState = {
36
- accumulators: Array.from({ length: nChannels }, () => createAccumulator()),
37
- input,
38
- };
39
- },
40
- /**
41
- * Process a chunk of data.
42
- * Call this multiple times for streaming large datasets.
43
- */
44
- processChunk(chunkInput) {
45
- if (!currentState) {
46
- throw new Error("Computation not initialized. Call initializeComputation first.");
47
- }
48
- const { accumulators, input } = currentState;
49
- const { shape, dims } = input;
50
- const { chunkData } = chunkInput;
51
- const cIndex = dims.indexOf("c");
52
- const hasChannelDim = cIndex !== -1;
53
- if (hasChannelDim) {
54
- // Multi-channel: extract each channel and update its accumulator
55
- for (let chIdx = 0; chIdx < accumulators.length; chIdx++) {
56
- const channelData = extractChannel(chunkData, shape, chIdx, cIndex);
57
- updateAccumulator(accumulators[chIdx], channelData);
58
- }
59
- }
60
- else {
61
- // Single channel: update directly
62
- updateAccumulator(accumulators[0], chunkData);
63
- }
64
- },
65
- /**
66
- * Finalize computation and return OMERO metadata.
67
- * Resets state after returning.
68
- */
69
- finalizeComputation() {
70
- if (!currentState) {
71
- throw new Error("Computation not initialized. Call initializeComputation first.");
72
- }
73
- const { accumulators, input } = currentState;
74
- const result = buildOmeroFromAccumulators(accumulators, input.quantiles, input.colors, input.labels);
75
- // Reset state
76
- currentState = null;
77
- return result;
78
- },
79
- /**
80
- * Compute OMERO metadata in a single call (non-streaming).
81
- * Useful for smaller datasets where streaming overhead isn't needed.
82
- */
83
- computeOmero(data, input) {
84
- validateQuantiles(input.quantiles);
85
- const { shape, dims, quantiles, colors, labels } = input;
86
- const cIndex = dims.indexOf("c");
87
- const hasChannelDim = cIndex !== -1;
88
- const nChannels = hasChannelDim ? shape[cIndex] : 1;
89
- // Create accumulators for each channel
90
- const accumulators = Array.from({ length: nChannels }, () => createAccumulator());
91
- if (hasChannelDim) {
92
- // Multi-channel: extract each channel and compute statistics
93
- for (let chIdx = 0; chIdx < nChannels; chIdx++) {
94
- const channelData = extractChannel(data, shape, chIdx, cIndex);
95
- updateAccumulator(accumulators[chIdx], channelData);
96
- }
97
- }
98
- else {
99
- // Single channel: compute directly
100
- updateAccumulator(accumulators[0], data);
101
- }
102
- return buildOmeroFromAccumulators(accumulators, quantiles, colors, labels);
103
- },
104
- /**
105
- * Check if worker is ready.
106
- */
107
- ping() {
108
- return "pong";
109
- },
110
- };
111
- // Expose the API via Comlink
112
- Comlink.expose(workerApi);
113
- //# sourceMappingURL=compute_omero_worker.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compute_omero_worker.js","sourceRoot":"","sources":["../../src/workers/compute_omero_worker.ts"],"names":[],"mappings":"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"}