{
  "version": 3,
  "sources": ["index.js", "lib/utils.js", "lib/zarr-pixel-source.js", "lib/load-zarr.js"],
  "sourcesContent": ["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nexport { loadZarr } from \"./lib/load-zarr.js\";\nexport { default as ZarrPixelSource } from \"./lib/zarr-pixel-source.js\";\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { openGroup, HTTPStore } from 'zarr';\nexport function normalizeStore(source) {\n    if (typeof source === 'string') {\n        return new HTTPStore(source);\n    }\n    return source;\n}\nexport async function loadMultiscales(store, path = '') {\n    const grp = await openGroup(store, path);\n    const rootAttrs = (await grp.attrs.asObject());\n    // Root of Zarr store must implement multiscales extension.\n    // https://github.com/zarr-developers/zarr-specs/issues/50\n    if (!Array.isArray(rootAttrs.multiscales)) {\n        throw new Error('Cannot find Zarr multiscales metadata.');\n    }\n    const { datasets } = rootAttrs.multiscales[0];\n    const promises = datasets.map((d) => grp.getItem(d.path));\n    return {\n        data: await Promise.all(promises),\n        rootAttrs\n    };\n}\n/*\n * Creates an ES6 map of 'label' -> index\n * > const labels = ['a', 'b', 'c', 'd'];\n * > const dims = getDims(labels);\n * > dims('a') === 0;\n * > dims('b') === 1;\n * > dims('c') === 2;\n * > dims('hi!'); // throws\n */\nexport function getDims(labels) {\n    const lookup = new Map(labels.map((name, i) => [name, i]));\n    if (lookup.size !== labels.length) {\n        throw Error('Labels must be unique, found duplicated label.');\n    }\n    return (name) => {\n        const index = lookup.get(name);\n        if (index === undefined) {\n            throw Error('Invalid dimension.');\n        }\n        return index;\n    };\n}\nfunction prevPowerOf2(x) {\n    return 2 ** Math.floor(Math.log2(x));\n}\n/*\n * Helper method to determine whether pixel data is interleaved or not.\n * > isInterleaved([1, 24, 24]) === false;\n * > isInterleaved([1, 24, 24, 3]) === true;\n */\nexport function isInterleaved(shape) {\n    const lastDimSize = shape[shape.length - 1];\n    return lastDimSize === 3 || lastDimSize === 4;\n}\nexport function guessTileSize(arr) {\n    const interleaved = isInterleaved(arr.shape);\n    const [yChunk, xChunk] = arr.chunks.slice(interleaved ? -3 : -2);\n    const size = Math.min(yChunk, xChunk);\n    // deck.gl requirement for power-of-two tile size.\n    return prevPowerOf2(size);\n}\nexport function guessLabels(rootAttrs) {\n    if ('omero' in rootAttrs) {\n        return ['t', 'c', 'z', 'y', 'x'];\n    }\n    throw new Error('Could not infer dimension labels for Zarr source. Must provide dimension labels.');\n}\n/*\n * The 'indexer' for a Zarr-based source translates\n * a 'selection' to an array of indices that align to\n * the labeled dimensions.\n *\n * > const labels = ['a', 'b', 'y', 'x'];\n * > const indexer = getIndexer(labels);\n * > console.log(indexer({ a: 10, b: 20 }));\n * > // [10, 20, 0, 0]\n */\nexport function getIndexer(labels) {\n    const size = labels.length;\n    const dims = getDims(labels);\n    return (sel) => {\n        if (Array.isArray(sel)) {\n            return [...sel];\n        }\n        const selection = Array(size).fill(0);\n        for (const [key, value] of Object.entries(sel)) {\n            selection[dims(key)] = value;\n        }\n        return selection;\n    };\n}\nexport function getImageSize(source) {\n    const interleaved = isInterleaved(source.shape);\n    // 2D image data in Zarr are represented as (..., rows, columns [, bands])\n    // If an image is interleaved (RGB/A), we need to ignore the last dimension (bands)\n    // to get the height and weight of the image.\n    const [height, width] = source.shape.slice(interleaved ? -3 : -2);\n    return { height, width };\n}\n/**\n * Preserves (double) slashes earlier in the path, so this works better\n * for URLs. From https://stackoverflow.com/a/46427607\n * @param args parts of a path or URL to join.\n */\nexport function joinUrlParts(...args) {\n    return args\n        .map((part, i) => {\n        if (i === 0)\n            return part.trim().replace(/[/]*$/g, '');\n        return part.trim().replace(/(^[/]*|[/]*$)/g, '');\n    })\n        .filter((x) => x.length)\n        .join('/');\n}\nexport function validLabels(labels, shape) {\n    if (labels.length !== shape.length) {\n        throw new Error('Labels do not match Zarr array shape.');\n    }\n    const n = shape.length;\n    if (isInterleaved(shape)) {\n        // last three dimensions are [row, column, bands]\n        return labels[n - 3] === 'y' && labels[n - 2] === 'x' && labels[n - 1] === '_c';\n    }\n    // last two dimensions are [row, column]\n    return labels[n - 2] === 'y' && labels[n - 1] === 'x';\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { BoundsCheckError, slice } from 'zarr';\nimport { getImageSize, isInterleaved, getIndexer } from \"./utils.js\";\nexport const DTYPE_LOOKUP = {\n    u1: 'Uint8',\n    u2: 'Uint16',\n    u4: 'Uint32',\n    f4: 'Float32',\n    f8: 'Float64',\n    i1: 'Int8',\n    i2: 'Int16',\n    i4: 'Int32'\n};\nclass ZarrPixelSource {\n    labels;\n    tileSize;\n    _data;\n    _indexer;\n    _readChunks;\n    constructor(data, labels, tileSize) {\n        this._indexer = getIndexer(labels);\n        this._data = data;\n        const xChunkSize = data.chunks[this._xIndex];\n        const yChunkSize = data.chunks[this._xIndex - 1];\n        this._readChunks = tileSize === xChunkSize && tileSize === yChunkSize;\n        this.labels = labels;\n        this.tileSize = tileSize;\n    }\n    get shape() {\n        return this._data.shape;\n    }\n    get dtype() {\n        const suffix = this._data.dtype.slice(1);\n        if (!(suffix in DTYPE_LOOKUP)) {\n            throw Error(`Zarr dtype not supported, got ${suffix}.`);\n        }\n        return DTYPE_LOOKUP[suffix];\n    }\n    get _xIndex() {\n        const interleave = isInterleaved(this._data.shape);\n        return this._data.shape.length - (interleave ? 2 : 1);\n    }\n    _chunkIndex(selection, x, y) {\n        const sel = this._indexer(selection);\n        sel[this._xIndex] = x;\n        sel[this._xIndex - 1] = y;\n        return sel;\n    }\n    /**\n     * Converts x, y tile indices to zarr dimension Slices within image bounds.\n     */\n    _getSlices(x, y) {\n        const { height, width } = getImageSize(this);\n        const [xStart, xStop] = [x * this.tileSize, Math.min((x + 1) * this.tileSize, width)];\n        const [yStart, yStop] = [y * this.tileSize, Math.min((y + 1) * this.tileSize, height)];\n        // Deck.gl can sometimes request edge tiles that don't exist. We throw\n        // a BoundsCheckError which is picked up in `ZarrPixelSource.onTileError`\n        // and ignored by deck.gl.\n        if (xStart === xStop || yStart === yStop) {\n            throw new BoundsCheckError('Tile slice is zero-sized.');\n        }\n        return [slice(xStart, xStop), slice(yStart, yStop)];\n    }\n    async getRaster({ selection }) {\n        const sel = this._chunkIndex(selection, null, null);\n        const { data, shape } = (await this._data.getRaw(sel));\n        const [height, width] = shape;\n        return { data, width, height };\n    }\n    async getTile(props) {\n        const { x, y, selection, signal } = props;\n        let res;\n        if (this._readChunks) {\n            // Can read chunks directly by key since tile size matches chunk shape\n            const sel = this._chunkIndex(selection, x, y);\n            res = await this._data.getRawChunk(sel, { storeOptions: { signal } });\n        }\n        else {\n            // Need to use zarr fancy indexing to get desired tile size.\n            const [xSlice, ySlice] = this._getSlices(x, y);\n            const sel = this._chunkIndex(selection, xSlice, ySlice);\n            res = await this._data.getRaw(sel);\n        }\n        const { data, shape: [height, width] } = res;\n        return { data, width, height };\n    }\n    onTileError(err) {\n        if (!(err instanceof BoundsCheckError)) {\n            // Rethrow error if something other than tile being requested is out of bounds.\n            throw err;\n        }\n    }\n}\nexport default ZarrPixelSource;\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { loadMultiscales, guessTileSize, guessLabels, normalizeStore, validLabels } from \"./utils.js\";\nimport ZarrPixelSource from \"./zarr-pixel-source.js\";\nexport async function loadZarr(root, options = {}) {\n    const store = normalizeStore(root);\n    const { data, rootAttrs } = await loadMultiscales(store);\n    const tileSize = guessTileSize(data[0]);\n    // If no labels are provided, inspect the root attributes for the store.\n    // For now, we only infer labels for OME-Zarr.\n    const labels = options.labels ?? guessLabels(rootAttrs);\n    if (!validLabels(labels, data[0].shape)) {\n        throw new Error('Invalid labels for Zarr array dimensions.');\n    }\n    const pyramid = data.map((arr) => new ZarrPixelSource(arr, labels, tileSize));\n    return {\n        data: pyramid,\n        metadata: rootAttrs\n    };\n}\n"],
  "mappings": "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",
  "names": ["import_zarr"]
}
