UNPKG

scran.js

Version:

Single cell RNA-seq analysis in Javascript

244 lines (222 loc) 8.39 kB
import * as utils from "./utils.js"; import * as gc from "./gc.js"; import { BuildSnnGraphResults } from "./buildSnnGraph.js"; /** * Wrapper around multi-level clustering results on the Wasm heap, produced by {@linkcode clusterGraph}. * @hideconstructor */ export class ClusterMultilevelResults { #id; #results; constructor(id, raw) { this.#id = id; this.#results = raw; } /** * @return {number} Number of levels in the results. */ numberOfLevels() { return this.#results.num_levels(); } /** * @return {number} Level with the lowest modularity. */ bestLevel() { return this.#results.best_level(); } /** * @param {object} [options={}] - Optional parameters. * @param {?number} [options.level=null] - The clustering level for which to obtain the modularity. * Defaults to the best clustering level from {@linkcode ClusterMultilevelResults#bestLevel bestLevel}. * * @return {number} The modularity at the specified level. */ modularity(options = {}) { let { level = null, ...others } = options; utils.checkOtherOptions(others); if (level == null) { level = this.bestLevel(); } return this.#results.modularity(level); } /** * @param {object} [options={}] - Optional parameters. * @param {?number} [options.level=null] - The clustering level for which to obtain the cluster membership. * Defaults to the best clustering level from {@linkcode ClusterMultilevelResults#bestLevel bestLevel}. * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * * @return {Int32Array|Int32WasmArray} Array containing the cluster membership for each cell. */ membership(options = {}) { let { level = null, copy = true, ...others } = options; utils.checkOtherOptions(others); if (level == null) { level = -1; } return utils.possibleCopy(this.#results.membership(level), copy); } /** * @return Frees the memory allocated on the Wasm heap for this object. * This invalidates this object and all references to it. */ free() { if (this.#results !== null) { gc.release(this.#id); this.#results = null; } return; } } /** * Wrapper around the walktrap clustering results on the Wasm heap, produced by {@linkcode clusterGraph}. * @hideconstructor */ export class ClusterWalktrapResults { #id; #results; constructor(id, raw) { this.#id = id; this.#results = raw; } /** * @return {number} Number of merge steps used by the Walktrap algorithm. */ numberOfMergeSteps() { return this.#results.num_merge_steps(); } /** * @param {object} [options={}] - Optional parameters. * @param {?number} [options.at=null] - Index at which to extract the modularity. * This can be any value from 0 to {@linkcode ClusterWalktrapResults#numberOfMergeSteps numberOfMergeSteps} plus 1. * Set to `null` to obtain the largest modularity across all merge steps. * @return {number} The modularity at the specified merge step, or the maximum modularity across all merge steps. */ modularity(options = {}) { let { at = null, ...others } = options; utils.checkOtherOptions(others); if (at === null) { at = -1; } return this.#results.modularity(at); } /** * @param {object} [options={}] - Optional parameters. * @param {boolean|string} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Int32Array|Int32WasmArray} Array containing the cluster membership for each cell. */ membership(options = {}) { const { copy = true, ...others } = options; utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.membership(), copy); } /** * @return Frees the memory allocated on the Wasm heap for this object. * This invalidates this object and all references to it. */ free() { if (this.#results !== null) { gc.release(this.#id); this.#results = null; } return; } } /** * Wrapper around the Leiden clustering results on the Wasm heap, produced by {@linkcode clusterGraph}. * @hideconstructor */ export class ClusterLeidenResults { #id; #results; constructor(id, raw, filled = true) { this.#id = id; this.#results = raw; return; } /** * @return {number} The quality of the Leiden clustering. * * Note that Leiden's quality score is technically a different measure from modularity. * Nonetheless, we use `modularity` for consistency with the other SNN clustering result classes. */ modularity() { return this.#results.modularity(); } /** * @param {object} [options={}] - Optional parameters. * @param {boolean|string} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * * @return {(Int32Array|Int32WasmArray)} Array containing the cluster membership for each cell. */ membership(options = {}) { const { copy = true, ...others } = options; utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.membership(), copy); } /** * @return Frees the memory allocated on the Wasm heap for this object. * This invalidates this object and all references to it. */ free() { if (this.#results !== null) { gc.release(this.#id); this.#results = null; } return; } } /** * Cluster cells using community detection on the SNN graph. * * @param {BuildSnnGraphResults} x - The shared nearest neighbor graph constructed by {@linkcode buildSnnGraph}. * @param {object} [options={}] - Optional parameters. * @param {string} [options.method="multilevel"] - Community detection method to use. * This should be one of `"multilevel"`, `"walktrap"` or `"leiden"`. * @param {number} [options.multiLevelResolution=1] - The resolution of the multi-level clustering, when `method = "multilevel"`. * Larger values result in more fine-grained clusters. * @param {number} [options.leidenResolution=1] - The resolution of the Leiden clustering, when `method = "leiden"`. * Larger values result in more fine-grained clusters. * @param {boolean} [options.leidenModularityObjective=false] - Whether to use the modularity as the objective function when `method = "leiden"`. * By default, the Constant-Potts Model is used instead. * Set to `true` to get an interpretation of the resolution on par with that of `method = "multilevel"`. * @param {number} [options.walktrapSteps=4] - Number of steps for the Walktrap algorithm, when `method = "walktrap"`. * * @return {ClusterMultiLevelResults|ClusterWalktrapResults|ClusterLeidenResults} Object containing the clustering results. * The class of this object depends on the choice of `method`. */ export function clusterGraph(x, options = {}) { const { method = "multilevel", multiLevelResolution = 1, leidenResolution = 1, leidenModularityObjective = false, walktrapSteps = 4, ...others } = options; utils.checkOtherOptions(others); var output; try { if (method == "multilevel") { output = gc.call( module => module.cluster_multilevel(x.graph, multiLevelResolution), ClusterMultilevelResults ); } else if (method == "walktrap") { output = gc.call( module => module.cluster_walktrap(x.graph, walktrapSteps), ClusterWalktrapResults ); } else if (method == "leiden") { output = gc.call( module => module.cluster_leiden(x.graph, leidenResolution, leidenModularityObjective), ClusterLeidenResults ); } else { throw new Error("unknown method '" + method + "'") } } catch (e) { utils.free(output); throw e; } return output; }