bakana-remotes
Version:
Fetch remote single-cell RNA-seq datasets for input into the bakana analysis pipeline.
170 lines (148 loc) • 6.06 kB
JavaScript
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));
}
}