UNPKG

bakana

Version:

Backend for kana's single-cell analyses. This supports single or multiple samples, execution in Node.js or the browser, in-memory caching of results for iterative analyses, and serialization to/from file for redistribution.

126 lines (105 loc) 4.18 kB
import * as scran from "scran.js"; import * as utils from "./utils/general.js"; import * as filter_module from "./cell_filtering.js"; import * as norm_module from "./rna_normalization.js"; export const step_name = "feature_selection"; /** * Results of per-gene variance modelling, * see [here](https://kanaverse.github.io/scran.js/ModelGeneVarResults.html) for details. * * @external ModelGeneVarResults */ /** * Feature selection is performed by modelling the per-gene variance and finding highly variable genes. * This wraps the [`modelGeneVariances`](https://kanaverse.github.io/scran.js/global.html#modelGeneVariances) function * from [**scran.js**](https://github.com/kanaverse/scran.js). * * Methods not documented here are not part of the stable API and should not be used by applications. * @hideconstructor */ export class FeatureSelectionState { #filter; #norm; #cache; #parameters; constructor(filter, norm, parameters = null, cache = null) { if (!(filter instanceof filter_module.CellFilteringState)) { throw new Error("'filter' should be a CellFilteringState object"); } this.#filter = filter; if (!(norm instanceof norm_module.RnaNormalizationState)) { throw new Error("'norm' should be an RnaNormalizationState object"); } this.#norm = norm; this.#parameters = (parameters === null ? {} : parameters); this.#cache = (cache === null ? {} : cache); this.changed = false; } free() { utils.freeCache(this.#cache.matrix); } /*************************** ******** Getters ********** ***************************/ valid() { return this.#norm.valid(); } /** * @return {external:ModelGeneVarResults} Variance modelling results, * available after running {@linkcode FeatureSelectionState#compute compute}. */ fetchResults() { return this.#cache.results; } /** * @return {Float64Array} Array of length equal to the number of genes, * containing the sorted residuals after fitting a mean-dependent trend to the variances. * Available after running {@linkcode FeatureSelectionState#compute compute}. */ fetchSortedResiduals() { return this.#cache.sorted_residuals; } /** * @return {object} Object containing the parameters. */ fetchParameters() { return { ...this.#parameters }; // avoid pass-by-reference activity. } /*************************** ******** Compute ********** ***************************/ /** * @return {object} Object containing default parameters, * see the `parameters` argument in {@linkcode FeatureSelectionState#compute compute} for details. */ static defaults() { return { span: 0.3 }; } /** * This method should not be called directly by users, but is instead invoked by {@linkcode runAnalysis}. * * @param {object} parameters - Parameter object, equivalent to the `feature_selection` property of the `parameters` of {@linkcode runAnalysis}. * @param {number} parameters.span - Value between 0 and 1 specifying the span for the LOWESS smoother. * * @return The object is updated with the new results. */ compute(parameters) { parameters = utils.defaultizeParameters(parameters, FeatureSelectionState.defaults()); this.changed = false; if (this.#norm.changed || parameters.span != this.#parameters.span) { utils.freeCache(this.#cache.results); if (this.valid()) { let mat = this.#norm.fetchNormalizedMatrix(); let block = this.#filter.fetchFilteredBlock(); this.#cache.results = scran.modelGeneVariances(mat, { span: parameters.span, block: block }); this.#cache.sorted_residuals = this.#cache.results.residuals().slice(); // a separate copy. this.#cache.sorted_residuals.sort(); this.changed = true; } } this.#parameters = parameters; return; } }