UNPKG

bakana-remotes

Version:

Fetch remote single-cell RNA-seq datasets for input into the bakana analysis pipeline.

170 lines (148 loc) 6.06 kB
import * as bakana from "bakana"; import * as utils from "./utils.js"; class GypsumNavigator { #download; #url; #prefix; #path; #manifest; constructor(prefix, path, url, download) { this.#prefix = prefix; this.#path = path; this.#url = url; this.#download = download; this.#manifest = null; } async get(path, asBuffer) { let full_path = this.#prefix; if (this.#path !== null) { full_path += "/" + this.#path; } full_path += "/" + path; return this.#download(this.#url + "/file/" + encodeURIComponent(full_path)); } async exists(path) { if (this.#manifest == null) { const manuri = this.#url + "/file/" + encodeURIComponent(this.#prefix + "/..manifest"); const raw_man = await this.#download(manuri); const dec = new TextDecoder; this.#manifest = JSON.parse(dec.decode(raw_man)); } let lookup = (this.#path === null ? "" : this.#path + "/") + path; return (lookup in this.#manifest); } clean(localPath) {} } /** * Dataset represented by a SummarizedExperiment in the [**gypsum**](https://github.com/ArtifactDB/gypsum-worker) store. * This extends the [AbstractDataset](https://kanaverse.github.io/bakana/AbstractAlabasterDataset.html) class. */ export class GypsumDataset extends bakana.AbstractAlabasterDataset { #id; static #downloadFun = utils.defaultDownload; /** * @param {function} fun - A (possibly `async`) function that accepts a URL and returns a Uint8Array of that URL's contents. * @return {function} Previous setting of the downloader function. */ static setDownloadFun(fun) { let previous = GypsumDataset.#downloadFun; GypsumDataset.#downloadFun = fun; return previous; } /** * @param {string} project - Name of the project. * @param {string} asset - Name of the asset. * @param {string} version - Name of the version. * @param {?string} path - Path to the SummarizedExperiment inside the version directory. * This can be `null` if the SummarizedExperiment exists at the root of the directory. * @param {string} [url=https://gypsum.artifactdb.com] - URL to the **gypsum** REST API. */ constructor(project, asset, version, path, url = "https://gypsum.artifactdb.com") { super(new GypsumNavigator(project + "/" + asset + "/" + version, path, url, GypsumDataset.#downloadFun)); this.#id = { project, asset, version, path, url }; } /** * @return {string} Format of this dataset class. * @static */ static format() { return "gypsum"; } /** * @return {object} Object containing the abbreviated details of this dataset. */ abbreviate() { return { id: { ...(this.#id) }, options: this.options() }; } /** * @return {object} Object describing this dataset, containing: * * - `files`: Array of objects representing the files used in this dataset. * Each object corresponds to a single file and contains: * - `type`: a string denoting the type. * - `file`: a {@linkplain SimpleFile} object representing the file contents. * - `options`: An object containing additional options to saved. */ serialize() { const enc = new TextEncoder; const buffer = enc.encode(JSON.stringify(this.#id)); // Storing it as a string in the buffer. let output = { type: "id", file: new bakana.SimpleFile(buffer, { name: "id" }) }; return { files: [ output ], options: this.options() } } /** * @param {Array} files - Array of objects like that produced by {@linkcode GypsumDataset#serialize serialize}. * @param {object} options - Object containing additional options to be passed to the constructor. * @return {GypsumDataset} A new instance of this class. * @static */ static async unserialize(files, options) { let args = {}; // This should contain 'id'. for (const x of files) { const dec = new TextDecoder; args[x.type] = dec.decode(x.file.buffer()); } if (!("id" in args)) { throw new Error("expected a file of type 'id' when unserializing a GypsumDataset"); } const id = JSON.parse(args.id); let output = new GypsumDataset(id.project, id.asset, id.version, id.path, id.url); output.setOptions(options); return output; } } /** * Result represented as a SummarizedExperiment in the [**gypsum**](https://github.com/ArtifactDB/gypsum-worker) store. * This extends the [AbstractResult](https://kanaverse.github.io/bakana/AbstractAlabasterResult.html) class. * @hideconstructor */ export class GypsumResult extends bakana.AbstractAlabasterResult { static #downloadFun = utils.defaultDownload; /** * @param {function} fun - A (possibly `async`) function that accepts a URL and returns a Uint8Array of that URL's contents. * @return {function} Previous setting of the downloader function. */ static setDownloadFun(fun) { let previous = GypsumResult.#downloadFun; GypsumResult.#downloadFun = fun; return previous; } /** * @param {string} project - Name of the project. * @param {string} asset - Name of the asset. * @param {string} version - Name of the version. * @param {?string} path - Path to the SummarizedExperiment inside the version directory. * This can be `null` if the SummarizedExperiment exists at the root of the directory. * @param {string} [url=https://gypsum.artifactdb.com] - URL to the **gypsum** REST API. */ constructor(project, asset, version, path, url = "https://gypsum.artifactdb.com") { super(new GypsumNavigator(project + "/" + asset + "/" + version, path, url, GypsumResult.#downloadFun)); } }