@aics/vole-core 4.4.0 → 4.5.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.
- package/es/Channel.js +2 -2
- package/es/Histogram.js +11 -15
- package/es/MeshVolume.js +2 -1
- package/es/VectorArrows3d.js +2 -3
- package/es/loaders/JsonImageInfoLoader.js +3 -2
- package/es/loaders/OmeZarrLoader.js +5 -15
- package/es/loaders/TiffLoader.js +9 -6
- package/es/types/BaseDrawableMeshObject.d.ts +1 -1
- package/es/types/Histogram.d.ts +1 -1
- package/es/types/ImageInfo.d.ts +1 -1
- package/es/types/MeshVolume.d.ts +1 -1
- package/es/types/VectorArrows3d.d.ts +2 -2
- package/es/types/Volume.d.ts +1 -1
- package/es/types/loaders/TiffLoader.d.ts +2 -1
- package/es/types/utils/url_utils.d.ts +5 -0
- package/es/utils/num_utils.js +6 -2
- package/es/utils/url_utils.js +25 -0
- package/es/workers/FetchTiffWorker.js +2 -11
- package/package.json +1 -1
package/es/Channel.js
CHANGED
|
@@ -157,7 +157,7 @@ export default class Channel {
|
|
|
157
157
|
};
|
|
158
158
|
this.rebuildDataTexture(this.imgData.data, w, h);
|
|
159
159
|
this.loaded = true;
|
|
160
|
-
this.histogram = new Histogram(bitsArray);
|
|
160
|
+
this.histogram = new Histogram(bitsArray, rawMin, rawMax);
|
|
161
161
|
this.frame = frame;
|
|
162
162
|
|
|
163
163
|
// reuse old lut but auto-remap it to new data range
|
|
@@ -205,7 +205,7 @@ export default class Channel {
|
|
|
205
205
|
this.loaded = true;
|
|
206
206
|
// update from current histogram?
|
|
207
207
|
this.setRawDataRange(rawMin, rawMax);
|
|
208
|
-
this.histogram = new Histogram(this.volumeData);
|
|
208
|
+
this.histogram = new Histogram(this.volumeData, rawMin, rawMax);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
// given this.volumeData, let's unpack it into a flat textureatlas and fill up this.imgData.
|
package/es/Histogram.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isFloatTypeArray } from "./types.js";
|
|
2
|
+
import { getDataRange } from "./utils/num_utils.js";
|
|
2
3
|
const NBINS = 256;
|
|
3
4
|
/**
|
|
4
5
|
* Builds a histogram with 256 bins from a data array. Assume data is 8 bit single channel grayscale.
|
|
@@ -18,7 +19,7 @@ export default class Histogram {
|
|
|
18
19
|
|
|
19
20
|
/** Index of the last bin (other than 0) with at least 1 value. */
|
|
20
21
|
|
|
21
|
-
constructor(data) {
|
|
22
|
+
constructor(data, dataMin = undefined, dataMax = undefined) {
|
|
22
23
|
this.dataMinBin = 0;
|
|
23
24
|
this.dataMaxBin = 0;
|
|
24
25
|
this.maxBin = 0;
|
|
@@ -28,7 +29,7 @@ export default class Histogram {
|
|
|
28
29
|
this.binSize = 0;
|
|
29
30
|
|
|
30
31
|
// build up the histogram
|
|
31
|
-
const hinfo = Histogram.calculateHistogram(data, NBINS);
|
|
32
|
+
const hinfo = Histogram.calculateHistogram(data, NBINS, dataMin, dataMax);
|
|
32
33
|
this.bins = hinfo.bins;
|
|
33
34
|
this.min = hinfo.min;
|
|
34
35
|
this.max = hinfo.max;
|
|
@@ -233,24 +234,19 @@ export default class Histogram {
|
|
|
233
234
|
}
|
|
234
235
|
return [b, e];
|
|
235
236
|
}
|
|
236
|
-
static calculateHistogram(arr, numBins = 1) {
|
|
237
|
+
static calculateHistogram(arr, numBins = 1, dataMin = undefined, dataMax = undefined) {
|
|
237
238
|
if (numBins < 1) {
|
|
238
239
|
numBins = 1;
|
|
239
240
|
}
|
|
240
241
|
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
// need to be careful about computing over chunks or whole ready-to-display volume
|
|
242
|
+
// ASSUMPTION: we will trust the min and max if provided.
|
|
243
|
+
let min = dataMin !== undefined ? dataMin : arr[0];
|
|
244
|
+
let max = dataMax !== undefined ? dataMax : arr[0];
|
|
245
245
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
min = arr[i];
|
|
251
|
-
} else if (arr[i] > max) {
|
|
252
|
-
max = arr[i];
|
|
253
|
-
}
|
|
246
|
+
// Find min and max in the array if the user did not provide them.
|
|
247
|
+
// Note that this is a completely separate walk through the data array which could be expensive.
|
|
248
|
+
if (dataMin === undefined || dataMax === undefined) {
|
|
249
|
+
[min, max] = getDataRange(arr);
|
|
254
250
|
}
|
|
255
251
|
const bins = new Uint32Array(numBins).fill(0);
|
|
256
252
|
|
package/es/MeshVolume.js
CHANGED
|
@@ -250,11 +250,12 @@ export default class MeshVolume {
|
|
|
250
250
|
this.meshrep[channel] = null;
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
|
-
saveChannelIsosurface(channelIndex, type,
|
|
253
|
+
saveChannelIsosurface(channelIndex, type, name) {
|
|
254
254
|
const meshrep = this.meshrep[channelIndex];
|
|
255
255
|
if (!meshrep) {
|
|
256
256
|
return;
|
|
257
257
|
}
|
|
258
|
+
const namePrefix = name !== undefined ? `${name}_` : "";
|
|
258
259
|
if (type === "STL") {
|
|
259
260
|
this.exportSTL(meshrep, namePrefix + "_" + this.volume.channelNames[channelIndex]);
|
|
260
261
|
} else if (type === "GLTF") {
|
package/es/VectorArrows3d.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
+
import BaseDrawableMeshObject from "./BaseDrawableMeshObject.js";
|
|
2
|
+
import { MESH_NO_PICK_OCCLUSION_LAYER } from "./ThreeJsPanel.js";
|
|
1
3
|
import { InstancedMesh, CylinderGeometry, ConeGeometry, Object3D, Vector3, MeshBasicMaterial, Color, DynamicDrawUsage, Matrix4 } from "three";
|
|
2
|
-
import BaseDrawableMeshObject from "./BaseDrawableMeshObject";
|
|
3
|
-
import { MESH_NO_PICK_OCCLUSION_LAYER } from "./ThreeJsPanel";
|
|
4
|
-
|
|
5
4
|
// Unscaled arrowhead dimensions.
|
|
6
5
|
const SHAFT_BASE_RADIUS = 0.5;
|
|
7
6
|
const HEAD_BASE_RADIUS = 1.5;
|
|
@@ -3,6 +3,7 @@ import { ThreadableVolumeLoader } from "./IVolumeLoader.js";
|
|
|
3
3
|
import { computeAtlasSize } from "../ImageInfo.js";
|
|
4
4
|
import { isChunk } from "../VolumeCache.js";
|
|
5
5
|
import { getDataRange } from "../utils/num_utils.js";
|
|
6
|
+
import { remapUri } from "../utils/url_utils.js";
|
|
6
7
|
|
|
7
8
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
8
9
|
|
|
@@ -70,7 +71,7 @@ class JsonImageInfoLoader extends ThreadableVolumeLoader {
|
|
|
70
71
|
if (cachedInfo) {
|
|
71
72
|
return cachedInfo;
|
|
72
73
|
}
|
|
73
|
-
const response = await fetch(this.urls[time]);
|
|
74
|
+
const response = await fetch(remapUri(this.urls[time]));
|
|
74
75
|
const imageInfo = await response.json();
|
|
75
76
|
imageInfo.pixel_size_unit = imageInfo.pixel_size_unit || "μm";
|
|
76
77
|
imageInfo.times = imageInfo.times || this.urls.length;
|
|
@@ -194,7 +195,7 @@ class JsonImageInfoLoader extends ThreadableVolumeLoader {
|
|
|
194
195
|
if (cacheHit) {
|
|
195
196
|
return;
|
|
196
197
|
}
|
|
197
|
-
const response = await fetch(image.name, {
|
|
198
|
+
const response = await fetch(remapUri(image.name), {
|
|
198
199
|
mode: "cors"
|
|
199
200
|
});
|
|
200
201
|
const blob = await response.blob();
|
|
@@ -3,6 +3,7 @@ import * as zarr from "zarrita";
|
|
|
3
3
|
const {
|
|
4
4
|
slice
|
|
5
5
|
} = zarr;
|
|
6
|
+
import { getDataRange } from "../utils/num_utils.js";
|
|
6
7
|
import SubscribableRequestQueue from "../utils/SubscribableRequestQueue.js";
|
|
7
8
|
import { ThreadableVolumeLoader } from "./IVolumeLoader.js";
|
|
8
9
|
import { composeSubregion, computePackedAtlasDims, convertSubregionToPixels, pickLevelToLoad, unitNameToSymbol } from "./VolumeLoaderUtils.js";
|
|
@@ -11,23 +12,13 @@ import { getScale, getSourceChannelMeta, matchSourceScaleLevels, orderByDimensio
|
|
|
11
12
|
import { VolumeLoadError, VolumeLoadErrorType, wrapVolumeLoadError } from "./VolumeLoadError.js";
|
|
12
13
|
import wrapArray, { RelaxedFetchStore } from "./zarr_utils/wrappers.js";
|
|
13
14
|
import { assertMetadataHasMultiscales, toOMEZarrMetaV4, validateOMEZarrMetadata } from "./zarr_utils/validation.js";
|
|
15
|
+
import { remapUri } from "../utils/url_utils.js";
|
|
14
16
|
const CHUNK_REQUEST_CANCEL_REASON = "chunk request cancelled";
|
|
15
17
|
|
|
16
18
|
// returns the converted data and the original min and max values
|
|
17
19
|
function convertChannel(channelData, dtype) {
|
|
18
20
|
// get min and max
|
|
19
|
-
|
|
20
|
-
let min = channelData[0];
|
|
21
|
-
let max = channelData[0];
|
|
22
|
-
for (let i = 0; i < channelData.length; i++) {
|
|
23
|
-
const val = channelData[i];
|
|
24
|
-
if (val < min) {
|
|
25
|
-
min = val;
|
|
26
|
-
}
|
|
27
|
-
if (val > max) {
|
|
28
|
-
max = val;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
21
|
+
const [min, max] = getDataRange(channelData);
|
|
31
22
|
if (dtype === "float64") {
|
|
32
23
|
// convert to float32
|
|
33
24
|
const f32 = new Float32Array(channelData.length);
|
|
@@ -91,7 +82,7 @@ class OMEZarrLoader extends ThreadableVolumeLoader {
|
|
|
91
82
|
if (!queue) {
|
|
92
83
|
queue = new SubscribableRequestQueue(fetchOptions?.concurrencyLimit, fetchOptions?.prefetchConcurrencyLimit);
|
|
93
84
|
}
|
|
94
|
-
const urlsArr = Array.isArray(urls) ? urls : [urls];
|
|
85
|
+
const urlsArr = (Array.isArray(urls) ? urls : [urls]).map(remapUri);
|
|
95
86
|
const scenesArr = Array.isArray(scenes) ? scenes : [scenes];
|
|
96
87
|
|
|
97
88
|
// Create one `ZarrSource` per URL
|
|
@@ -315,7 +306,7 @@ class OMEZarrLoader extends ThreadableVolumeLoader {
|
|
|
315
306
|
return dims;
|
|
316
307
|
});
|
|
317
308
|
const imgdata = {
|
|
318
|
-
name: source0.omeroMetadata?.name
|
|
309
|
+
name: source0.omeroMetadata?.name,
|
|
319
310
|
atlasTileDims: [atlasTileDims.x, atlasTileDims.y],
|
|
320
311
|
subregionSize: [pxSizeLv.x, pxSizeLv.y, pxSizeLv.z],
|
|
321
312
|
subregionOffset: [0, 0, 0],
|
|
@@ -468,7 +459,6 @@ class OMEZarrLoader extends ThreadableVolumeLoader {
|
|
|
468
459
|
const level = this.sources[sourceIdx].scaleLevels[multiscaleLevel];
|
|
469
460
|
const sliceSpec = this.orderByDimension(unorderedSpec, sourceIdx);
|
|
470
461
|
const reportChunk = (coords, sub) => reportChunkBase(sourceIdx, coords, sub);
|
|
471
|
-
console.log(level);
|
|
472
462
|
const result = await zarr.get(level, sliceSpec, {
|
|
473
463
|
opts: {
|
|
474
464
|
subscriber,
|
package/es/loaders/TiffLoader.js
CHANGED
|
@@ -4,6 +4,7 @@ import { ThreadableVolumeLoader, LoadSpec } from "./IVolumeLoader.js";
|
|
|
4
4
|
import { computePackedAtlasDims, MAX_ATLAS_EDGE } from "./VolumeLoaderUtils.js";
|
|
5
5
|
import { VolumeLoadError, VolumeLoadErrorType, wrapVolumeLoadError } from "./VolumeLoadError.js";
|
|
6
6
|
import { CImageInfo } from "../ImageInfo.js";
|
|
7
|
+
import { remapUri } from "../utils/url_utils.js";
|
|
7
8
|
function trimNull(xml) {
|
|
8
9
|
// trim trailing unicode zeros?
|
|
9
10
|
return xml && xml.trim().replace(/\0/g, "").trim();
|
|
@@ -21,6 +22,7 @@ function getOME(xml) {
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
class OMEDims {
|
|
25
|
+
name = undefined;
|
|
24
26
|
sizex = 0;
|
|
25
27
|
sizey = 0;
|
|
26
28
|
sizez = 1;
|
|
@@ -63,14 +65,15 @@ function getAttributeOrError(el, attr) {
|
|
|
63
65
|
function getOMEDims(imageEl) {
|
|
64
66
|
const dims = new OMEDims();
|
|
65
67
|
const pixelsEl = imageEl.getElementsByTagName("Pixels")[0];
|
|
68
|
+
dims.name = imageEl.getAttribute("Name") ?? "";
|
|
66
69
|
dims.sizex = Number(getAttributeOrError(pixelsEl, "SizeX"));
|
|
67
70
|
dims.sizey = Number(getAttributeOrError(pixelsEl, "SizeY"));
|
|
68
71
|
dims.sizez = Number(pixelsEl.getAttribute("SizeZ"));
|
|
69
72
|
dims.sizec = Number(pixelsEl.getAttribute("SizeC"));
|
|
70
73
|
dims.sizet = Number(pixelsEl.getAttribute("SizeT"));
|
|
71
|
-
dims.unit = pixelsEl.getAttribute("PhysicalSizeXUnit")
|
|
72
|
-
dims.pixeltype = pixelsEl.getAttribute("Type")
|
|
73
|
-
dims.dimensionorder = pixelsEl.getAttribute("DimensionOrder")
|
|
74
|
+
dims.unit = pixelsEl.getAttribute("PhysicalSizeXUnit") ?? "";
|
|
75
|
+
dims.pixeltype = pixelsEl.getAttribute("Type") ?? "";
|
|
76
|
+
dims.dimensionorder = pixelsEl.getAttribute("DimensionOrder") ?? "XYZCT";
|
|
74
77
|
dims.pixelsizex = Number(pixelsEl.getAttribute("PhysicalSizeX"));
|
|
75
78
|
dims.pixelsizey = Number(pixelsEl.getAttribute("PhysicalSizeY"));
|
|
76
79
|
dims.pixelsizez = Number(pixelsEl.getAttribute("PhysicalSizeZ"));
|
|
@@ -90,7 +93,7 @@ const getPixelType = pxSize => pxSize === 1 ? "uint8" : pxSize === 2 ? "uint16"
|
|
|
90
93
|
class TiffLoader extends ThreadableVolumeLoader {
|
|
91
94
|
constructor(url) {
|
|
92
95
|
super();
|
|
93
|
-
this.url = url;
|
|
96
|
+
this.url = url.map(remapUri);
|
|
94
97
|
}
|
|
95
98
|
async loadOmeDims() {
|
|
96
99
|
if (!this.dims) {
|
|
@@ -178,7 +181,7 @@ class TiffLoader extends ThreadableVolumeLoader {
|
|
|
178
181
|
// load tiff and check metadata
|
|
179
182
|
const numChannelsPerSource = this.url.length > 1 ? Array(this.url.length).fill(1) : [dims.sizec];
|
|
180
183
|
const imgdata = {
|
|
181
|
-
name:
|
|
184
|
+
name: dims.name,
|
|
182
185
|
atlasTileDims: [atlasDims.x, atlasDims.y],
|
|
183
186
|
subregionSize: [tilesizex, tilesizey, dims.sizez],
|
|
184
187
|
subregionOffset: [0, 0, 0],
|
|
@@ -188,7 +191,7 @@ class TiffLoader extends ThreadableVolumeLoader {
|
|
|
188
191
|
multiscaleLevelDims: [{
|
|
189
192
|
shape: [dims.sizet, dims.sizec, dims.sizez, tilesizey, tilesizex],
|
|
190
193
|
spacing: [1, 1, dims.pixelsizez, dims.pixelsizey * dims.sizey / tilesizey, dims.pixelsizex * dims.sizex / tilesizex],
|
|
191
|
-
spaceUnit: dims.unit
|
|
194
|
+
spaceUnit: dims.unit ?? "",
|
|
192
195
|
timeUnit: "",
|
|
193
196
|
dataType: getDtype(dims.pixeltype)
|
|
194
197
|
}],
|
package/es/types/Histogram.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export default class Histogram {
|
|
|
18
18
|
private dataMaxBin;
|
|
19
19
|
private pixelCount;
|
|
20
20
|
maxBin: number;
|
|
21
|
-
constructor(data: TypedArray<NumberType
|
|
21
|
+
constructor(data: TypedArray<NumberType>, dataMin?: number | undefined, dataMax?: number | undefined);
|
|
22
22
|
private static findBin;
|
|
23
23
|
/**
|
|
24
24
|
* Returns the integer bin index for the given value. If a value is outside
|
package/es/types/ImageInfo.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type VolumeDims } from "./VolumeDims.js";
|
|
2
2
|
import { Vector3, Vector2 } from "three";
|
|
3
3
|
export type ImageInfo = Readonly<{
|
|
4
|
-
name: string;
|
|
4
|
+
name: string | undefined;
|
|
5
5
|
/**
|
|
6
6
|
* XY dimensions of the texture atlas used by `RayMarchedAtlasVolume` and
|
|
7
7
|
* `Atlas2DSlice`, in number of z-slice tiles (not pixels). Chosen by the
|
package/es/types/MeshVolume.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export default class MeshVolume implements IDrawableObject {
|
|
|
34
34
|
hasIsosurface(channel: number): boolean;
|
|
35
35
|
createIsosurface(channel: number, color: [number, number, number], value?: number, alpha?: number, transp?: boolean): void;
|
|
36
36
|
destroyIsosurface(channel: number): void;
|
|
37
|
-
saveChannelIsosurface(channelIndex: number, type: string,
|
|
37
|
+
saveChannelIsosurface(channelIndex: number, type: string, name?: string): void;
|
|
38
38
|
exportSTL(input: Object3D, fname: string): void;
|
|
39
39
|
exportGLTF(input: Object3D, fname: string): void;
|
|
40
40
|
generateIsosurfaceGeometry(channelIndex: number, isovalue: number): BufferGeometry[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import BaseDrawableMeshObject from "./BaseDrawableMeshObject.js";
|
|
1
2
|
import { Vector3, Color } from "three";
|
|
2
|
-
import { IDrawableObject } from "./types";
|
|
3
|
-
import BaseDrawableMeshObject from "./BaseDrawableMeshObject";
|
|
3
|
+
import { IDrawableObject } from "./types.js";
|
|
4
4
|
/**
|
|
5
5
|
* A drawable vector arrow field, which uses instanced meshes for performance.
|
|
6
6
|
*/
|
package/es/types/Volume.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export default class Volume {
|
|
|
25
25
|
loadSpecRequired: Required<LoadSpec>;
|
|
26
26
|
channelLoadCallback?: PerChannelCallback;
|
|
27
27
|
imageMetadata: Record<string, unknown>;
|
|
28
|
-
name: string;
|
|
28
|
+
name: string | undefined;
|
|
29
29
|
channels: Channel[];
|
|
30
30
|
numChannels: number;
|
|
31
31
|
channelNames: string[];
|
|
@@ -3,6 +3,7 @@ import { type ImageInfo } from "../ImageInfo.js";
|
|
|
3
3
|
import type { VolumeDims } from "../VolumeDims.js";
|
|
4
4
|
import { TypedArray, NumberType } from "../types.js";
|
|
5
5
|
declare class OMEDims {
|
|
6
|
+
name: string | undefined;
|
|
6
7
|
sizex: number;
|
|
7
8
|
sizey: number;
|
|
8
9
|
sizez: number;
|
|
@@ -34,7 +35,7 @@ export type TiffLoadResult = {
|
|
|
34
35
|
range: [number, number];
|
|
35
36
|
};
|
|
36
37
|
declare class TiffLoader extends ThreadableVolumeLoader {
|
|
37
|
-
url
|
|
38
|
+
private url;
|
|
38
39
|
dims?: OMEDims;
|
|
39
40
|
constructor(url: string[]);
|
|
40
41
|
private loadOmeDims;
|
package/es/utils/num_utils.js
CHANGED
|
@@ -224,8 +224,12 @@ export function getDataRange(data) {
|
|
|
224
224
|
let min = data[0];
|
|
225
225
|
let max = data[0];
|
|
226
226
|
for (let i = 1; i < data.length; i++) {
|
|
227
|
-
|
|
228
|
-
|
|
227
|
+
const value = data[i];
|
|
228
|
+
if (value < min) {
|
|
229
|
+
min = value;
|
|
230
|
+
} else if (value > max) {
|
|
231
|
+
max = value;
|
|
232
|
+
}
|
|
229
233
|
}
|
|
230
234
|
return [min, max];
|
|
231
235
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const S3_URL_PREFIX = "s3://";
|
|
2
|
+
const GCS_URL_PREFIX = "gs://";
|
|
3
|
+
const VAST_FILES_PREFIX = "/allen/aics/";
|
|
4
|
+
const VAST_FILES_URL = "https://vast-files.int.allencell.org/";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Remaps non-standard URIs (e.g. S3 (`s3://`), Google Cloud Storage (`gs://`), or
|
|
8
|
+
* VAST files (`/allen/aics/`)) to a standard HTTPS URL.
|
|
9
|
+
*/
|
|
10
|
+
export function remapUri(url) {
|
|
11
|
+
let newUrl = url.trim();
|
|
12
|
+
if (newUrl.startsWith(S3_URL_PREFIX)) {
|
|
13
|
+
// remap s3://bucket/key to https://bucket.s3.amazonaws.com/key
|
|
14
|
+
const s3Path = newUrl.slice(S3_URL_PREFIX.length);
|
|
15
|
+
const pathSegments = s3Path.split("/");
|
|
16
|
+
newUrl = `https://${pathSegments[0]}.s3.amazonaws.com/${pathSegments.slice(1).join("/")}`;
|
|
17
|
+
} else if (newUrl.startsWith(GCS_URL_PREFIX)) {
|
|
18
|
+
// remap gs://bucket/key to https://storage.googleapis.com/bucket/key
|
|
19
|
+
newUrl = newUrl.replace(GCS_URL_PREFIX, "https://storage.googleapis.com/");
|
|
20
|
+
} else if (newUrl.startsWith(VAST_FILES_PREFIX)) {
|
|
21
|
+
// remap /allen/aics/... to https://vast-files.int.allencell.org/...
|
|
22
|
+
newUrl = newUrl.replace(VAST_FILES_PREFIX, VAST_FILES_URL);
|
|
23
|
+
}
|
|
24
|
+
return newUrl;
|
|
25
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { fromUrl } from "geotiff";
|
|
2
2
|
import { serializeError } from "serialize-error";
|
|
3
3
|
import { VolumeLoadError, VolumeLoadErrorType } from "../loaders/VolumeLoadError.js";
|
|
4
|
+
import { getDataRange } from "../utils/num_utils.js";
|
|
4
5
|
// from TIFF
|
|
5
6
|
const SAMPLEFORMAT_UINT = 1;
|
|
6
7
|
const SAMPLEFORMAT_INT = 2;
|
|
@@ -121,17 +122,7 @@ async function loadTiffChannel(e) {
|
|
|
121
122
|
// all slices collected, now resample to 8 bits full data range
|
|
122
123
|
const src = castToArray(buffer, bytesPerPixel, sampleFormat);
|
|
123
124
|
const dtype = getDtype(sampleFormat, bytesPerPixel);
|
|
124
|
-
|
|
125
|
-
let chmax = src[0];
|
|
126
|
-
for (let j = 0; j < src.length; ++j) {
|
|
127
|
-
const val = src[j];
|
|
128
|
-
if (val < chmin) {
|
|
129
|
-
chmin = val;
|
|
130
|
-
}
|
|
131
|
-
if (val > chmax) {
|
|
132
|
-
chmax = val;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
125
|
+
const [chmin, chmax] = getDataRange(src);
|
|
135
126
|
return {
|
|
136
127
|
data: src,
|
|
137
128
|
channel: channelIndex,
|