UNPKG

scran.js

Version:

Single cell RNA-seq analysis in Javascript

94 lines (81 loc) 3.26 kB
import * as utils from "./utils.js"; import * as gc from "./gc.js"; import { FindNearestNeighborsResults, findNearestNeighbors } from "./findNearestNeighbors.js"; /** * Wrapper around the SNN graph object on the Wasm heap, produced by {@linkcode buildSnnGraph}. * @hideconstructor */ export class BuildSnnGraphResults { #id; #graph; constructor(id, raw) { this.#id = id; this.#graph = raw; return; } /** * @return Frees the memory allocated on the Wasm heap for this object. * This invalidates this object and all references to it. */ free() { if (this.#graph !== null) { gc.release(this.#id); this.#graph = null; } return; } // Not documented, internal use only. get graph() { return this.#graph; } } /** * Build a shared nearest graph where each cell is a node. * Edges are formed between cells that share one or more nearest neighbors, weighted by the number or rank of those shared neighbors. * * @param {BuildNeighborSearchIndexResults|FindNearestNeighborsResults} x A pre-built neighbor search index from {@linkcode buildNeighborSearchIndex}. * * Alternatively, a pre-computed set of neighbor search results from {linkcode findNearestNeighbors}. * The number of neighbors should be equal to `neighbors`, otherwise a warning is raised. * @param {object} [options={}] - Optional parameters. * @param {number} [options.scheme="rank"] - Weighting scheme for the edges between cells. * This can be based on the top ranks of the shared neighbors (`"rank"`), * the number of shared neighbors (`"number"`) * or the Jaccard index of the neighbor sets between cells (`"jaccard"`). * @param {number} [options.neighbors=10] - Number of nearest neighbors to use to construct the graph. * Ignored if `x` is a {@linkplain FindNearestNeighborsResults} object. * @param {?number} [options.numberOfThreads=null] - Number of threads to use. * If `null`, defaults to {@linkcode maximumThreads}. * * @return {BuildSnnGraphResults} Object containing the graph. */ export function buildSnnGraph(x, options = {}) { const { scheme = "rank", neighbors = 10, numberOfThreads = null, ...others } = options; utils.checkOtherOptions(others); var output; var my_neighbors; let nthreads = utils.chooseNumberOfThreads(numberOfThreads); utils.matchOptions("scheme", scheme, [ "rank", "number", "jaccard" ]); try { let ref; if (x instanceof FindNearestNeighborsResults) { if (neighbors != x.numberOfNeighbors()) { console.warn("number of neighbors in 'x' does not match 'neighbors'"); } ref = x; } else { my_neighbors = findNearestNeighbors(x, neighbors, { numberOfThreads: nthreads }); ref = my_neighbors ; // separate assignment is necessary for only 'my_neighbors' but not 'x' to be freed. } output = gc.call( module => module.build_snn_graph(ref.results, scheme, nthreads), BuildSnnGraphResults ); } catch(e) { utils.free(output); throw e; } finally { utils.free(my_neighbors); } return output; }