UNPKG

scran.js

Version:

Single cell RNA-seq analysis in Javascript

142 lines (126 loc) 4.03 kB
import * as utils from "./utils.js"; /** * Helper class for handling matrix data from multiple modalities. * In particular, it simplifies memory management of the assorted {@linkplain ScranMatrix} instances containing data for different features in the same set of cells. */ export class MultiMatrix { #store; #ncols; /** * @param {object} [options={}] - Optional parameters. * @param {object} [options.store={}] - Existing store of {@linkplain ScranMatrix} objects. * Each matrix should correspond to a different modality, named according to its key. * All matrices should have data for the same set of cells, i.e., same number of columns. */ constructor(options = {}) { const { store = {}, ...others } = options; utils.checkOtherOptions(others); this.#store = store; this.#ncols = null; let keys = Object.keys(store); for (var k = 0; k < keys.length; k++) { let current = store[keys[k]]; if (k == 0) { this.#ncols = current.numberOfColumns(); } else if (current.numberOfColumns() != this.#ncols) { throw new Error("all matrices should have the same number of columns"); } } } /** * @return {?number} Number of columns in the matrices. * If no matrices are available, `null` is returned. */ numberOfColumns() { return this.#ncols; } /** * @return {Array} Names of the available modalities. */ available() { return Object.keys(this.#store); } /** * @param {string} i - Name of a modality. * @return {boolean} Whether modality `i` is available. */ has(i) { return (i in this.#store); } /** * @param {string} i - Name of a modality. * @return {ScranMatrix} The matrix data for modality `i`. */ get(i) { return this.#store[i]; } /** * @param {string} i - Name of a modality. * @param {ScranMatrix} matrix - The matrix data for modality `i`. * * @return `matrix` is added to the MultiMatrix with name `i`. */ add(i, matrix) { if (this.#ncols === null) { this.#ncols = matrix.numberOfColumns(); } else if (matrix.numberOfColumns() != this.#ncols) { throw new Error("all matrices should have the same number of columns"); } if (i in this.#store) { let old = this.#store[i]; utils.free(old); } this.#store[i] = matrix; } /** * @param {string} i - Name of a modality. * @return Modality `i` is removed from the MultiMatrix. */ remove(i) { utils.free(this.#store[i]); delete this.#store[i]; if (Object.keys(this.#store).length == 0) { this.#ncols = null; } } /** * @param {string} i - Name of a modality. * @return {MultiMatrix} A deep copy of the current object. */ clone() { let new_matrix = new MultiMatrix; try { for (const [k, v] of Object.entries(this.#store)) { new_matrix.add(k, v.clone()); } } catch (e) { new_matrix.free(); throw e; } return new_matrix; } /** * @param {string} from - Old name of the modality. * @param {string} to - New name for the modality. * * @return The modality `from` is renamed to `to`, possibly replacing any existing modality at `to`. */ rename(from, to) { if (from !== to) { if (to in this.#store) { utils.free(this.#store[to]); } this.#store[to] = this.#store[from]; delete this.#store[from]; } } /** * @return Frees memory for all modalities in this MultiMatrix. */ free() { for (const [x, v] of Object.entries(this.#store)) { utils.free(v); } return; } }