diff --git a/js/MultiMatrix.js b/js/MultiMatrix.js index c52d9986..f6ccaa10 100644 --- a/js/MultiMatrix.js +++ b/js/MultiMatrix.js @@ -14,7 +14,10 @@ export class MultiMatrix { * 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({ store = {} } = {}) { + constructor(options = {}) { + const { store = {}, ...others } = options; + utils.checkOtherOptions(others); + this.#store = store; this.#ncols = null; diff --git a/js/ScranMatrix.js b/js/ScranMatrix.js index 6ce0e161..a6f9327d 100644 --- a/js/ScranMatrix.js +++ b/js/ScranMatrix.js @@ -82,7 +82,10 @@ export class ScranMatrix { * If `buffer` was supplied, the returned array is a view into it. * Note that this may be invalidated on the next allocation on the Wasm heap. */ - row(i, { buffer = null } = {}) { + row(i, options = {}) { + let { buffer = null, ...others } = options; + utils.checkOtherOptions(others); + if (buffer != null) { this.#matrix.row(i, buffer.offset); return buffer.array(); @@ -111,7 +114,10 @@ export class ScranMatrix { * If `buffer` was supplied, the returned array is a view into it. * Note that this may be invalidated on the next allocation on the Wasm heap. */ - column(i, { buffer = null } = {}) { + column(i, options = {}) { + let { buffer = null, ...others } = options; + utils.checkOtherOptions(others); + if (buffer != null) { this.#matrix.column(i, buffer.offset); return buffer.array(); diff --git a/js/aggregateAcrossCells.js b/js/aggregateAcrossCells.js index 681efc0b..1da4bd4f 100644 --- a/js/aggregateAcrossCells.js +++ b/js/aggregateAcrossCells.js @@ -39,7 +39,9 @@ export class AggregateAcrossCellsResults { * @return {Float64Array|Float64WasmArray} Array of length equal to the number of genes, containing the per-gene sum of values across across all cells in the specified `group`. * If `average = true` in {@linkcode aggregateAcrossCells}, each element is the mean value instead. */ - groupSums(group, { copy = true } = {}) { + groupSums(group, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.group_sums(group), copy); } @@ -57,7 +59,9 @@ export class AggregateAcrossCellsResults { * If `average = true` in {@linkcode aggregateAcrossCells}, each element is the mean value instead. * If `buffer` is supplied, the function returns `buffer` if `asTypedArray = false`, or a view on `buffer` if `asTypedArray = true`. */ - allSums({ asTypedArray = true, buffer = null } = {}) { + allSums(options = {}) { + let { asTypedArray = true, buffer = null, ...others } = options; + utils.checkOtherOptions(others); let tmp = null; try { @@ -83,7 +87,9 @@ export class AggregateAcrossCellsResults { * @return {Float64Array|Float64WasmArray} Array of length equal to the number of genes, containing the number of cells with detected expression for each gene in the specified `group`. * If `average = true` in {@linkcode aggregateAcrossCells}, each element is the proportion of detected cells instead. */ - groupDetected(group, { copy = true } = {}) { + groupDetected(group, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.group_detected(group), copy); } @@ -100,7 +106,9 @@ export class AggregateAcrossCellsResults { * If `average = true` in {@linkcode aggregateAcrossCells}, each element is the proportion of detected cells instead. * If `buffer` is supplied, the function returns `buffer` if `asTypedArray = false`, or a view on `buffer` if `asTypedArray = true`. */ - allDetected({ asTypedArray = true, buffer = null } = {}) { + allDetected(options = {}) { + let { asTypedArray = true, buffer = null, ...others } = options; + utils.checkOtherOptions(others); let tmp = null; try { @@ -144,7 +152,9 @@ export class AggregateAcrossCellsResults { * * @return {AggregateAcrossCellsResults} Object containing the aggregation results. */ -export function aggregateAcrossCells(x, groups, { average = false, numberOfThreads = null } = {}) { +export function aggregateAcrossCells(x, groups, options = {}) { + const { average = false, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); var group_data; var output; let nthreads = utils.chooseNumberOfThreads(numberOfThreads); diff --git a/js/block.js b/js/block.js index 59dc234c..f98dc84b 100644 --- a/js/block.js +++ b/js/block.js @@ -20,7 +20,9 @@ import * as fac from "./factorize.js"; * * If `buffer` was supplied, it is used as the return value. */ -export function createBlock(ncells, { buffer = null } = {}) { +export function createBlock(ncells, options = {}) { + let { buffer = null, ...other } = options; + utils.checkOtherOptions(other); let total = 0; ncells.forEach(x => { total += x; }); @@ -62,7 +64,9 @@ export function subsetBlock(x, subset, { filter = null, buffer = null } = {}) { } // Soft-deprecated, just use subsetFactor(). -export function filterBlock(x, filter, { buffer = null } = {}) { +export function filterBlock(x, filter, options = {}) { + let { buffer = null, ...other } = options; + utils.checkOtherOptions(other); return subsetBlock(x, filter, { buffer: buffer, filter: true }); } diff --git a/js/buildSnnGraph.js b/js/buildSnnGraph.js index c54cc81c..95416377 100644 --- a/js/buildSnnGraph.js +++ b/js/buildSnnGraph.js @@ -52,7 +52,9 @@ export class BuildSnnGraphResults { * * @return {BuildSnnGraphResults} Object containing the graph. */ -export function buildSnnGraph(x, { scheme = "rank", neighbors = 10, numberOfThreads = null } = {}) { +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); diff --git a/js/chooseHvgs.js b/js/chooseHvgs.js index b28e2804..eae19879 100644 --- a/js/chooseHvgs.js +++ b/js/chooseHvgs.js @@ -16,9 +16,12 @@ import { ModelGeneVariancesResults } from "./modelGeneVariances.js"; * @return {Uint8WasmArray} Array of length equal to the number of genes. * Highly variable genes are marked with a value of 1 and all other genes have values of zero. */ -export function chooseHvgs(x, { number = 4000, minimum = 0 } = {}) { +export function chooseHvgs(x, options = {}) { + const { number = 4000, minimum = 0, ...others } = options; + utils.checkOtherOptions(others); let stat; let chosen; + try { if (x instanceof ModelGeneVariancesResults) { stat = x.residuals({ copy: "view" }); @@ -27,11 +30,13 @@ export function chooseHvgs(x, { number = 4000, minimum = 0 } = {}) { } chosen = utils.createUint8WasmArray(stat.length); wasm.call(module => module.choose_highly_variable_genes(stat.length, stat.offset, chosen.offset, number, minimum)); + } catch (e) { chosen.free(); throw e; } finally { stat.free(); } + return chosen; } diff --git a/js/clusterGraph.js b/js/clusterGraph.js index 340c5368..6b4e2fec 100644 --- a/js/clusterGraph.js +++ b/js/clusterGraph.js @@ -10,7 +10,7 @@ export class ClusterMultilevelResults { #id; #results; - constructor(id, raw, filled = true) { + constructor(id, raw) { this.#id = id; this.#results = raw; } @@ -36,7 +36,9 @@ export class ClusterMultilevelResults { * * @return {number} The modularity at the specified level. */ - modularity({ level = null } = {}) { + modularity(options = {}) { + let { level = null, ...others } = options; + utils.checkOtherOptions(others); if (level == null) { level = this.bestLevel(); } @@ -51,7 +53,9 @@ export class ClusterMultilevelResults { * * @return {Int32Array|Int32WasmArray} Array containing the cluster membership for each cell. */ - membership({ level = null, copy = true } = {}) { + membership(options = {}) { + let { level = null, copy = true, ...others } = options; + utils.checkOtherOptions(others); if (level == null) { level = -1; } @@ -79,7 +83,7 @@ export class ClusterWalktrapResults { #id; #results; - constructor(id, raw, filled = true) { + constructor(id, raw) { this.#id = id; this.#results = raw; } @@ -98,7 +102,9 @@ export class ClusterWalktrapResults { * 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({ at = null } = {}) { + modularity(options = {}) { + let { at = null, ...others } = options; + utils.checkOtherOptions(others); if (at === null) { at = -1; } @@ -110,7 +116,9 @@ export class ClusterWalktrapResults { * @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({ copy = true } = {}) { + membership(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.membership(), copy); } @@ -157,7 +165,9 @@ export class ClusterLeidenResults { * * @return {(Int32Array|Int32WasmArray)} Array containing the cluster membership for each cell. */ - membership({ copy = true } = {}) { + membership(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.membership(), copy); } @@ -193,15 +203,18 @@ export class ClusterLeidenResults { * @return {ClusterMultiLevelResults|ClusterWalktrapResults|ClusterLeidenResults} Object containing the clustering results. * The class of this object depends on the choice of `method`. */ -export function clusterGraph(x, { - method = "multilevel", - multiLevelResolution = 1, - leidenResolution = 1, - leidenModularityObjective = false, - walktrapSteps = 4 -} = {}) { - var output; +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( diff --git a/js/clusterKmeans.js b/js/clusterKmeans.js index 2eafad66..cc7055a0 100644 --- a/js/clusterKmeans.js +++ b/js/clusterKmeans.js @@ -10,7 +10,7 @@ export class ClusterKmeansResults { #id; #results; - constructor(id, raw, filled = true) { + constructor(id, raw) { this.#results = raw; this.#id = id; } @@ -34,7 +34,9 @@ export class ClusterKmeansResults { * @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 assignment for each cell. */ - clusters({ copy = true } = {}) { + clusters(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.clusters(), copy); } @@ -43,7 +45,9 @@ export class ClusterKmeansResults { * @param {boolean|string} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Int32Array|Int32WasmArray} Array containing the number of cells in each cluster. */ - sizes({ copy = true } = {}) { + sizes(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.cluster_sizes(), copy); } @@ -53,7 +57,9 @@ export class ClusterKmeansResults { * @return {Float64Array|Float64WasmArray} Array containing the cluster centers in column-major format, * where rows are dimensions and columns are the clusters. */ - centers({ copy = true } = {}) { + centers(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.centers(), copy); } @@ -88,7 +94,7 @@ export class ClusterKmeansResults { * Cluster cells using k-means. * A variety of initialization and refinement algorithms can be used here, see the [**kmeans** documentation](https://github.com/LTLA/CppKmeans) for more details. * -* @param {(RunPcaResults|Float64WasmArray|Array|TypedArray)} x - Numeric coordinates of each cell in the dataset. + * @param {(RunPcaResults|Float64WasmArray|Array|TypedArray)} x - Numeric coordinates of each cell in the dataset. * For array inputs, this is expected to be in column-major format where the rows are the variables and the columns are the cells. * For a {@linkplain RunPcaResults} input, we extract the principal components. * @param {number} clusters Number of clusters to create. @@ -115,18 +121,22 @@ export class ClusterKmeansResults { * * @return {ClusterKmeansResults} Object containing the clustering results. */ -export function clusterKmeans(x, clusters, { - numberOfDims = null, - numberOfCells = null, - initMethod = "var-part", - initSeed = 5768, - initVarPartSizeAdjust = 1, - initVarPartOptimize = true, - refineMethod = "hartigan-wong", - refineLloydIterations = 100, - refineHartiganWongIterations = 10, - numberOfThreads = null -} = {}) { +export function clusterKmeans(x, clusters, options = {}) { + let { + numberOfDims = null, + numberOfCells = null, + initMethod = "var-part", + initSeed = 5768, + initVarPartSizeAdjust = 1, + initVarPartOptimize = true, + refineMethod = "hartigan-wong", + refineLloydIterations = 100, + refineHartiganWongIterations = 10, + numberOfThreads = null, + ...others + } = options; + utils.checkOtherOptions(others); + var buffer; var output; let nthreads = utils.chooseNumberOfThreads(numberOfThreads); diff --git a/js/computeClrm1Factors.js b/js/computeClrm1Factors.js index 131547dd..e4f054b6 100644 --- a/js/computeClrm1Factors.js +++ b/js/computeClrm1Factors.js @@ -18,7 +18,9 @@ import * as wa from "wasmarrays.js"; * Note that the factors are not centered and should be passed to {@linkcode centerSizeFactors} before calling {@linkcode normalizeCounts}. * If `buffer` is supplied, the function returns `buffer` if `asTypedArray = false`, or a view on `buffer` if `asTypedArray = true`. */ -export function computeClrm1Factors(x, { asTypedArray = true, buffer = null, priorCount = 10, numberOfThreads = null } = {}) { +export function computeClrm1Factors(x, options = {}) { + let { asTypedArray = true, buffer = null, priorCount = 10, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); var local_buffer = null; let nthreads = utils.chooseNumberOfThreads(numberOfThreads); diff --git a/js/delayed.js b/js/delayed.js index 29830c61..b8216ca6 100644 --- a/js/delayed.js +++ b/js/delayed.js @@ -21,7 +21,9 @@ import * as wasm from "./wasm.js"; * @return {ScranMatrix} A ScranMatrix containing the delayed arithmetic operation on `x`. * If `inPlace = true`, this is a reference to `x`, otherwise it is a new ScranMatrix. */ -export function delayedArithmetic(x, operation, value, { right = true, along = "row", inPlace = false } = {}) { +export function delayedArithmetic(x, operation, value, options = {}) { + const { right = true, along = "row", inPlace = false, ...others } = options; + utils.checkOtherOptions(others); let xcopy; let vbuffer; let target; @@ -68,7 +70,9 @@ export function delayedArithmetic(x, operation, value, { right = true, along = " * @return {ScranMatrix} A ScranMatrix containing the delayed math operation on `x`. * If `inPlace = true`, this is a reference to `x`, otherwise it is a new ScranMatrix. */ -export function delayedMath(x, operation, { logBase = null, inPlace = false } = {}) { +export function delayedMath(x, operation, options = {}) { + let { logBase = null, inPlace = false, ...others } = options; + utils.checkOtherOptions(others); let xcopy; let target; @@ -104,7 +108,9 @@ export function delayedMath(x, operation, { logBase = null, inPlace = false } = * @return {ScranMatrix} A ScranMatrix containing the transposition of `x`. * If `inPlace = true`, this is a reference to `x`, otherwise it is a new ScranMatrix. */ -export function transpose(x, { inPlace = false } = {}) { +export function transpose(x, options = {}) { + const { inPlace = false, ...others } = options; + utils.checkOtherOptions(others); let xcopy; let target; diff --git a/js/factorize.js b/js/factorize.js index d1597625..7bed65fd 100644 --- a/js/factorize.js +++ b/js/factorize.js @@ -34,7 +34,9 @@ import * as utils from "./utils.js"; * * If `buffer` was supplied, it is used as the value of the `ids` property. */ -export function convertToFactor(x, { asWasmArray = true, buffer = null, levels = null, action = "error", placeholder = -1 } = {}) { +export function convertToFactor(x, options = {}) { + let { asWasmArray = true, buffer = null, levels = null, action = "error", placeholder = -1, ...others } = options; + utils.checkOtherOptions(others); let local_buffer; let failure; @@ -184,7 +186,10 @@ export function dropUnusedLevels(x) { * @return `x` is modified by reference such that `x.levels` is set to `newLevels`. * `x.ids` is updated so that the indices now refer to the appropriate value in `newLevels`. */ -export function resetLevels(x, newLevels, { action = "error", placeholder = -1 } = {}) { +export function resetLevels(x, newLevels, options = {}) { + const { action = "error", placeholder = -1, ...others } = options; + utils.checkOtherOptions(others); + let mapping = new Map; for (var i = 0; i < newLevels.length; i++) { mapping.set(newLevels[i], i); @@ -275,7 +280,10 @@ export function resetLevels(x, newLevels, { action = "error", placeholder = -1 } * * If `buffer` is supplied, the returned `ids` will be set to `buffer`. */ -export function subsetFactor(x, subset, { drop = true, filter = null, buffer = null } = {}) { +export function subsetFactor(x, subset, options = {}) { + let { drop = true, filter = null, buffer = null, ...others } = options; + utils.checkOtherOptions(others); + let output = { ids: null, levels: x.levels }; if (x.ids instanceof wa.WasmArray) { diff --git a/js/findNearestNeighbors.js b/js/findNearestNeighbors.js index 1ff71373..b1eac503 100644 --- a/js/findNearestNeighbors.js +++ b/js/findNearestNeighbors.js @@ -63,7 +63,9 @@ export class BuildNeighborSearchIndexResults { * * @return {BuildNeighborSearchIndexResults} Index object to use for neighbor searches. */ -export function buildNeighborSearchIndex(x, { numberOfDims = null, numberOfCells = null, approximate = true } = {}) { +export function buildNeighborSearchIndex(x, options = {}) { + let { numberOfDims = null, numberOfCells = null, approximate = true, ...others } = options; + utils.checkOtherOptions(others); var buffer; var output; @@ -156,7 +158,10 @@ export class FindNearestNeighborsResults { * * If only some of the arguments are non-`null`, an error is raised. */ - serialize({ runs = null, indices = null, distances = null } = {}) { + serialize(options = {}) { + const { runs = null, indices = null, distances = null, ...others } = options; + utils.checkOtherOptions(others); + var copy = (runs === null) + (indices === null) + (distances === null); if (copy != 3 && copy != 0) { throw new Error("either all or none of 'runs', 'indices' and 'distances' can be 'null'"); @@ -261,7 +266,9 @@ export class FindNearestNeighborsResults { * * @return {FindNearestNeighborsResults} Object containing the search results. */ -export function findNearestNeighbors(x, k, { numberOfThreads = null } = {}) { +export function findNearestNeighbors(x, k, options = {}) { + const { numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); let nthreads = utils.chooseNumberOfThreads(numberOfThreads); return gc.call( module => module.find_nearest_neighbors(x.index, k, nthreads), diff --git a/js/guessFeatures.js b/js/guessFeatures.js index d1aa823c..beb32d48 100644 --- a/js/guessFeatures.js +++ b/js/guessFeatures.js @@ -1,3 +1,5 @@ +import * as utils from "./utils.js"; + /** * Guess the identity of the features from their names. * @@ -16,7 +18,10 @@ * This can either be `"ensembl"` or `"symbol"`. * - `confidence`: the percentage of entries in `x` that are consistent with the inferred identity. */ -export function guessFeatures(features, { forceTaxonomy = false } = {}) { +export function guessFeatures(features, options = {}) { + const { forceTaxonomy = false, ...others } = options; + utils.checkOtherOptions(others); + let ntotal = features.length; let early_threshold = Math.ceil(ntotal / 2); let format = payload => { diff --git a/js/hdf5.js b/js/hdf5.js index 5ee72aeb..e3bd7135 100644 --- a/js/hdf5.js +++ b/js/hdf5.js @@ -157,7 +157,10 @@ export class H5Base { return output; } - #create_attribute(attr, type, shape, { maxStringLength = null, levels = null } = {}) { // internal use only. + #create_attribute(attr, type, shape, options = {}) { // internal use only. + const { maxStringLength = null, levels = null, ...others } = options; + utils.checkOtherOptions(others); + let shape_arr = utils.wasmifyArray(shape, "Int32WasmArray"); try { if (type == "String") { @@ -200,7 +203,10 @@ export class H5Base { * If supplied, `x` should be an array of integers that index into `levels`. * Alternatively, `levels` may be `null`, in which case `x` should be an array of strings that is used to infer `levels`. */ - writeAttribute(attr, type, shape, x, { maxStringLength = null, levels = null } = {}) { + writeAttribute(attr, type, shape, x, options = {}) { + let { maxStringLength = null, levels = null, ...others } = options; + utils.checkOtherOptions(others); + if (x === null) { throw new Error("cannot write 'null' to HDF5"); } @@ -259,8 +265,11 @@ export class H5Group extends H5Base { /** * @param {string} file - Path to the HDF5 file. * @param {string} name - Name of the group inside the file. + * @param {object} [options={}] - Optional parameters, for internal use only. */ - constructor(file, name, { newlyCreated = false } = {}) { + constructor(file, name, options = {}) { + const { newlyCreated = false, ...others } = options; + utils.checkOtherOptions(others); super(file, name); if (newlyCreated) { @@ -369,9 +378,11 @@ export class H5Group extends H5Base { * @return {H5DataSet} A dataset of the specified type and shape is created as an immediate child of the current group. * A {@linkplain H5DataSet} object is returned representing this new dataset. */ - createDataSet(name, type, shape, { maxStringLength = 10, levels = null, compression = 6, chunks = null } = {}) { - let new_name = this.#child_name(name); + createDataSet(name, type, shape, options = {}) { + const { maxStringLength = 10, levels = null, compression = 6, chunks = null, ...others } = options; + utils.checkOtherOptions(others); + let new_name = this.#child_name(name); let shape_arr; let chunk_arr; try { @@ -433,7 +444,10 @@ export class H5Group extends H5Base { * The same dataset is then filled with the contents of `x`. * A {@linkplain H5DataSet} object is returned representing this new dataset. */ - writeDataSet(name, type, shape, x, { levels = null, compression = 6, chunks = null, cache = false } = {}) { + writeDataSet(name, type, shape, x, options = {}) { + const { levels = null, compression = 6, chunks = null, cache = false, ...others } = options; + utils.checkOtherOptions(others); + if (x === null) { throw new Error("cannot write 'null' to HDF5"); } @@ -477,6 +491,7 @@ export class H5Group extends H5Base { export class H5File extends H5Group { /** * @param {string} file - Path to the HDF5 file. + * @param {object} [options={}] - Further options to pass to the {@linkplain H5Group} constructor. */ constructor(file, options = {}) { super(file, "/", options); @@ -553,7 +568,9 @@ export class H5DataSet extends H5Base { * @param {boolean} [options.load=false] - Whether or not to load the contents of the dataset in the constructor. * If `false`, the contents can be loaded later with {@linkcode H5DataSet#load load}. */ - constructor(file, name, { load = false, newlyCreated = false, shape = null, type = null, values = null } = {}) { + constructor(file, name, options = {}) { + const { load = false, newlyCreated = false, shape = null, type = null, values = null, ...others } = options; + utils.checkOtherOptions(others); super(file, name); if (newlyCreated) { @@ -659,7 +676,7 @@ export class H5DataSet extends H5Base { } /** - * @param {(Array|TypedArray|number|string)} x - Values to write to the dataset. + * @param {Array|TypedArray|number|string} x - Values to write to the dataset. * This should be of length equal to the product of {@linkcode H5DataSet#shape shape}; * unless `shape` is empty, in which case it should either be of length 1, or a single number or string. * @param {object} [options={}] - Optional parameters. @@ -668,11 +685,13 @@ export class H5DataSet extends H5Base { * @return `x` is written to the dataset on file. * No return value is provided. */ - write(x, { cache = false } = {}) { + write(x, options = {}) { + const { cache = false, ...others } = options; + utils.checkOtherOptions(others); + if (x === null) { throw new Error("cannot write 'null' to HDF5"); } - x = check_shape(x, this.shape); if (this.type == "String") { @@ -747,13 +766,17 @@ function extract_names(host, output, recursive = true) { * these nested objects are empty if `recursive = false`. * HDF5 datasets are represented by strings specifying the data type - i.e., `"integer"`, `"float"`, `"string"` or `"other"`. */ -export function extractHdf5ObjectNames (path, { group = "", recursive = true } = {}) { +export function extractHdf5ObjectNames(path, options = {}) { + const { group = "", recursive = true, ...others } = options; + utils.checkOtherOptions(others); + var src; if (group == "") { src = new H5File(path); } else { src = new H5Group(path, group); } + var output = {}; extract_names(src, output, recursive); return output; diff --git a/js/hypergeometricTest.js b/js/hypergeometricTest.js index b9674870..4d660e35 100644 --- a/js/hypergeometricTest.js +++ b/js/hypergeometricTest.js @@ -23,7 +23,10 @@ import * as wasm from "./wasm.js"; * The i-th entry contains the p-value for enrichment computed using the i-th entry of each supplied array. * If `buffer` is supplied, the function returns `buffer` if `asTypedArray = false`, or a view on `buffer` if `asTypedArray = true`. */ -export function hypergeometricTest(markersInSet, numberOfMarkers, geneSetSize, numberOfGenes, { asTypedArray = true, buffer = null, log = false, numberOfThreads = null } = {}) { +export function hypergeometricTest(markersInSet, numberOfMarkers, geneSetSize, numberOfGenes, options = {}) { + let { asTypedArray = true, buffer = null, log = false, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + let markersInSet_data; let numberOfMarkers_data; let geneSetSize_data; diff --git a/js/initializeSparseMatrixFromArrays.js b/js/initializeSparseMatrixFromArrays.js index 99a40b5b..aae1c893 100644 --- a/js/initializeSparseMatrixFromArrays.js +++ b/js/initializeSparseMatrixFromArrays.js @@ -14,7 +14,10 @@ import { ScranMatrix } from "./ScranMatrix.js"; * * @return {ScranMatrix} Matrix containing dense data. */ -export function initializeDenseMatrixFromDenseArray(numberOfRows, numberOfColumns, values, { forceInteger = false } = {}) { +export function initializeDenseMatrixFromDenseArray(numberOfRows, numberOfColumns, values, options = {}) { + const { forceInteger = false, ...others } = options; + utils.checkOtherOptions(others); + var val_data; var output; @@ -61,7 +64,10 @@ export function initializeDenseMatrixFromDenseArray(numberOfRows, numberOfColumn * * @return {ScranMatrix} Matrix containing sparse data. */ -export function initializeSparseMatrixFromDenseArray(numberOfRows, numberOfColumns, values, { forceInteger = true, layered = true } = {}) { +export function initializeSparseMatrixFromDenseArray(numberOfRows, numberOfColumns, values, options = {}) { + const { forceInteger = true, layered = true, ...others } = options; + utils.checkOtherOptions(others); + var val_data; var output; @@ -115,7 +121,10 @@ export function initializeSparseMatrixFromDenseArray(numberOfRows, numberOfColum * * @return {ScranMatrix} Matrix containing sparse data. */ -export function initializeSparseMatrixFromSparseArrays(numberOfRows, numberOfColumns, values, indices, pointers, { byRow = true, forceInteger = true, layered = true } = {}) { +export function initializeSparseMatrixFromSparseArrays(numberOfRows, numberOfColumns, values, indices, pointers, options = {}) { + const { byRow = true, forceInteger = true, layered = true, ...others } = options; + utils.checkOtherOptions(others); + var val_data; var ind_data; var indp_data; diff --git a/js/initializeSparseMatrixFromHdf5.js b/js/initializeSparseMatrixFromHdf5.js index 11e1c21b..326145f4 100644 --- a/js/initializeSparseMatrixFromHdf5.js +++ b/js/initializeSparseMatrixFromHdf5.js @@ -25,7 +25,10 @@ import { ScranMatrix } from "./ScranMatrix.js"; * * @return {ScranMatrix} Matrix containing sparse data. */ -export function initializeSparseMatrixFromHdf5(file, name, { forceInteger = true, layered = true, subsetRow = null, subsetColumn = null } = {}) { +export function initializeSparseMatrixFromHdf5(file, name, options = {}) { + const { forceInteger = true, layered = true, subsetRow = null, subsetColumn = null, ...others } = options; + utils.checkOtherOptions(others); + const details = extractHdf5MatrixDetails(file, name); if (details.format == "dense") { return initializeSparseMatrixFromHdf5Dataset(file, name, { forceInteger, layered, subsetRow, subsetColumn }); @@ -103,7 +106,10 @@ function processSubsets(subsetRow, subsetColumn, FUN) { * * @return {ScranMatrix} Matrix containing sparse data. */ -export function initializeSparseMatrixFromHdf5Dataset(file, name, { transposed = true, forceInteger = true, layered = true, subsetRow = null, subsetColumn = null } = {}) { +export function initializeSparseMatrixFromHdf5Dataset(file, name, options = {}) { + const { transposed = true, forceInteger = true, layered = true, subsetRow = null, subsetColumn = null, ...others } = options; + utils.checkOtherOptions(others); + return processSubsets( subsetRow, subsetColumn, @@ -147,7 +153,10 @@ export function initializeSparseMatrixFromHdf5Dataset(file, name, { transposed = * * @return {ScranMatrix} Matrix containing sparse data. */ -export function initializeSparseMatrixFromHdf5Group(file, name, numberOfRows, numberOfColumns, byRow, { forceInteger = true, layered = true, subsetRow = null, subsetColumn = null } = {}) { +export function initializeSparseMatrixFromHdf5Group(file, name, numberOfRows, numberOfColumns, byRow, options = {}) { + const { forceInteger = true, layered = true, subsetRow = null, subsetColumn = null, ...others } = options; + utils.checkOtherOptions(others); + return processSubsets( subsetRow, subsetColumn, diff --git a/js/initializeSparseMatrixFromMatrixMarket.js b/js/initializeSparseMatrixFromMatrixMarket.js index efd03e68..fa84f08d 100644 --- a/js/initializeSparseMatrixFromMatrixMarket.js +++ b/js/initializeSparseMatrixFromMatrixMarket.js @@ -18,7 +18,10 @@ import { ScranMatrix } from "./ScranMatrix.js"; * * @return {ScranMatrix} Matrix containing sparse data. */ -export function initializeSparseMatrixFromMatrixMarket(x, { compression = "unknown", layered = true } = {}) { +export function initializeSparseMatrixFromMatrixMarket(x, options = {}) { + const { compression = "unknown", layered = true, ...others } = options; + utils.checkOtherOptions(others); + var buf_data; var output; @@ -61,7 +64,10 @@ export function initializeSparseMatrixFromMatrixMarket(x, { compression = "unkno * * @return {object} An object containing the number of `rows`, `columns` and `lines` in the matrix. */ -export function extractMatrixMarketDimensions(x, { compression = "unknown" } = {}) { +export function extractMatrixMarketDimensions(x, options = {}) { + const { compression = "unknown", ...others } = options; + utils.checkOtherOptions(others); + var buf_data; var stats = utils.createFloat64WasmArray(3); let output = {}; diff --git a/js/initializeSparseMatrixFromRds.js b/js/initializeSparseMatrixFromRds.js index 5fb6c87a..9c51dda6 100644 --- a/js/initializeSparseMatrixFromRds.js +++ b/js/initializeSparseMatrixFromRds.js @@ -16,7 +16,10 @@ import { ScranMatrix } from "./ScranMatrix.js"; * * @return {ScranMatrix} Matrix containing sparse data. */ -export function initializeSparseMatrixFromRds(x, { forceInteger = true, layered = true } = {}) { +export function initializeSparseMatrixFromRds(x, options = {}) { + const { forceInteger = true, layered = true, ...others } = options; + utils.checkOtherOptions(others); + var ids = null; var output; diff --git a/js/labelCells.js b/js/labelCells.js index 4ad5d785..6508d0e6 100644 --- a/js/labelCells.js +++ b/js/labelCells.js @@ -225,7 +225,10 @@ export function intersectFeatures(testFeatures, referenceFeatures) { // exported * * @return {TrainedLabelCellsReference} Object containing the built reference dataset. */ -export function trainLabelCellsReference(testFeatures, loadedReference, referenceFeatures, { top = 20, numberOfThreads = null } = {}) { +export function trainLabelCellsReference(testFeatures, loadedReference, referenceFeatures, options = {}) { + const { top = 20, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + var test_id_buffer; var ref_id_buffer; var output; @@ -301,7 +304,9 @@ class LabelCellsResults { * @return {Int32Array|Int32WasmArray} Array of length equal to the number of cells, * containing the index of the best label for each cell. */ - predicted({ copy = true } = {}) { + predicted(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.best(), copy); } @@ -316,9 +321,11 @@ class LabelCellsResults { * @return {Float64Array|Float64WasmArray} Array containing the scores for this cell across all labels. * If `buffer` is supplied, the function returns `buffer` if `asTypedArray = false`, or a view on `buffer` if `asTypedArray = true`. */ - scoreForCell(i, { asTypedArray = true, buffer = null } = {}) { - let tmp = null; + scoreForCell(i, options = {}) { + let { asTypedArray = true, buffer = null, ...others } = options; + utils.checkOtherOptions(others); + let tmp = null; try { if (buffer == null) { tmp = utils.createFloat64WasmArray(this.#results.num_labels()); @@ -340,7 +347,9 @@ class LabelCellsResults { * Only used if `buffer` is not supplied. * @return {Float64Array|Float64WasmArray} Array containing the scores across all cells for this label. */ - scoreForLabel(i, { copy = true, buffer = null } = {}) { + scoreForLabel(i, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.score_for_label(i), copy); } @@ -350,7 +359,9 @@ class LabelCellsResults { * @return {Float64Array|Float64WasmArray} Array of length equal to the number of cells, * containing the difference in scores between the best and second-best labels. */ - delta({ copy = true } = {}) { + delta(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.delta(), copy); } @@ -382,7 +393,10 @@ class LabelCellsResults { * * @return {LabelCellsResults} Labelling results for each cell in `x`. */ -export function labelCells(x, reference, { numberOfFeatures = null, numberOfCells = null, quantile = 0.8, numberOfThreads = null } = {}) { +export function labelCells(x, reference, options = {}) { + const { numberOfFeatures = null, numberOfCells = null, quantile = 0.8, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + var output = null; var matbuf; var tempmat; @@ -461,7 +475,7 @@ class IntegratedLabelCellsReferences { * Prepare a classifier that integrates multiple reference datasets. * This allows users to choose the best label for a test cell based on its classifications in multiple references. * - * @param {Array} features - An array of feature identifiers (usually strings) of length equal to the number of rows in the test matrix. + * @param {Array} testFeatures - An array of feature identifiers (usually strings) of length equal to the number of rows in the test matrix. * Each entry should contain a single identifier for the corresponding row of the test matrix. * Any `null` entries are considered to be incomparable. * If any entries are duplicated, only the first occurrence is used and the rest are ignored. @@ -471,17 +485,20 @@ class IntegratedLabelCellsReferences { * Each entry may also be an array of synonymous identifiers, in which case the first identifier that matches to an entry of `testFeatures` is used. * Contents of `referenceFeatures` are expected to exhibit some overlap with identifiers in `testFeatures`. * Any `null` entries are considered to be incomparable. - * If multiple entries of `referenceFeatures` match to the same feature in `features`, only the first matching entry is used and the rest are ignored. + * If multiple entries of `referenceFeatures` match to the same feature in `testFeatures`, only the first matching entry is used and the rest are ignored. * @param {Array} trainedReferences - Array of {@linkplain TrainedLabelCellsReference} objects, typically generated by calling {@linkcode trainLabelCellsReference} * on the same `testFeatures` and the corresponding entries of `loadedReferences` and `referenceFeatures`. - * This should have length equal to that of `loaded`. + * This should have length equal to that of `loadedReferences`. * @param {object} [options={}] - Optional parameters. * @param {?number} [options.numberOfThreads=null] - Number of threads to use. * If `null`, defaults to {@linkcode maximumThreads}. * * @return {IntegratedLabelCellsReference} Object containing the integrated references. */ -export function integrateLabelCellsReferences(testFeatures, loadedReferences, referenceFeatures, trainedReferences, { numberOfThreads = null } = {}) { +export function integrateLabelCellsReferences(testFeatures, loadedReferences, referenceFeatures, trainedReferences, options = {}) { + const { numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + let interlen_arr; let test_id_arr = []; let test_id_ptr_arr; @@ -605,7 +622,9 @@ class IntegrateLabelCellsResults { * @return {Int32Array|Int32WasmArray} Array of length equal to the number of cells, * containing the index of the best reference for each cell. */ - predicted({ copy = true } = {}) { + predicted(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.best(), copy); } @@ -620,7 +639,10 @@ class IntegrateLabelCellsResults { * @return {Float64Array|Float64WasmArray} Array containing the scores for this cell across all labels. * If `buffer` is supplied, the function returns `buffer` if `asTypedArray = false`, or a view on `buffer` if `asTypedArray = true`. */ - scoreForCell(i, { asTypedArray = true, buffer = null } = {}) { + scoreForCell(i, options = {}) { + let { asTypedArray = true, buffer = null, ...others } = options; + utils.checkOtherOptions(others); + let tmp; try { if (buffer == null) { @@ -642,7 +664,9 @@ class IntegrateLabelCellsResults { * * @return {Float64Array|Float64WasmArray} Array containing the scores across all cells for this label. */ - scoreForReference(i, { copy = true } = {}) { + scoreForReference(i, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.score_for_reference(i), copy); } @@ -653,7 +677,9 @@ class IntegrateLabelCellsResults { * @return {Float64Array|Float64WasmArray} Array of length equal to the number of cells, * containing the difference in scores between the best and second-best references. */ - delta({ copy = true } = {}) { + delta(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.delta(), copy); } @@ -672,12 +698,12 @@ class IntegrateLabelCellsResults { /** * Integrate cell labels across multiple reference datasets. * - * @param {(ScranMatrix|Float64WasmArray)} x - The count matrix, or log-normalized matrix, containing features in the rows and cells in the columns. + * @param {ScranMatrix|Float64WasmArray} x - The count matrix, or log-normalized matrix, containing features in the rows and cells in the columns. * If a Float64WasmArray is supplied, it is assumed to contain a column-major dense matrix. * @param {IntegratedLabelCellsReferences} integrated - An integrated set of reference datasets, typically generated by {@linkcode integrateLabelCellsReferences}. * @param {Array} assigned - An array of length equal to the number of references in `integrated`. * This should contain the result of classification of `x` with each individual reference via {@linkcode labelCells}. - * Each element should be a {@linkplain LabelCells} object; or an Array, TypedArray or Int32WasmArray of length equal to the number of cells in `x`. + * Each element should be a {@linkplain LabelCellsResults} object; or an Array, TypedArray or Int32WasmArray of length equal to the number of cells in `x`. * @param {object} [options={}] - Optional parameters. * @param {?number} [options.numberOfFeatures=null] - Number of features, used when `x` is a Float64WasmArray. * @param {?number} [options.numberOfCells=null] - Number of cells, used when `x` is a Float64WasmArray. @@ -687,7 +713,10 @@ class IntegrateLabelCellsResults { * * @return {IntegrateLabelCellsResults} Integrated labelling results for each cell in `x`. */ -export function integrateLabelCells(x, assigned, integrated, { numberOfFeatures = null, numberOfCells = null, quantile = 0.8, numberOfThreads = null } = {}) { +export function integrateLabelCells(x, assigned, integrated, options = {}) { + const { numberOfFeatures = null, numberOfCells = null, quantile = 0.8, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + let nrefs = integrated.numberOfReferences(); if (assigned.length != nrefs) { throw new Error("length of 'assigned' should be equal to the number of references in 'integrated'"); diff --git a/js/logNormCounts.js b/js/logNormCounts.js index 21cbf217..1d377a59 100644 --- a/js/logNormCounts.js +++ b/js/logNormCounts.js @@ -21,7 +21,10 @@ import * as wasm from "./wasm.js"; * * @return {ScranMatrix} A matrix of the same type as `x` containing log-transformed normalized expression values. */ -export function logNormCounts(x, { sizeFactors = null, allowZeros = false, allowNonFinite = false } = {}) { +export function logNormCounts(x, options = {}) { + const { sizeFactors = null, allowZeros = false, allowNonFinite = false, ...others } = options; + utils.checkOtherOptions(others); + var sf_data; var output; @@ -69,7 +72,10 @@ export function logNormCounts(x, { sizeFactors = null, allowZeros = false, allow * @return {Float64Array|Float64WasmArray} Array containing the centered size factors. * If `buffer` is supplied, the function returns `buffer` if `asTypedArray = false`, or a view on `buffer` if `asTypedArray = true`. */ -export function centerSizeFactors(sizeFactors, { block = null, asTypedArray = true, buffer = null, toLowestBlock = true } = {}) { +export function centerSizeFactors(sizeFactors, options = {}) { + let { block = null, asTypedArray = true, buffer = null, toLowestBlock = true, ...others } = options; + utils.checkOtherOptions(others); + let local_buffer = null; let block_data; diff --git a/js/mnnCorrect.js b/js/mnnCorrect.js index d3ea425e..57b3bd9c 100644 --- a/js/mnnCorrect.js +++ b/js/mnnCorrect.js @@ -40,19 +40,22 @@ import * as wasm from "./wasm.js"; * Corrected values are organized using the column-major layout, where rows are dimensions and columns are cells. * If `buffer` is supplied, the function returns `buffer` if `asTypedArray = false`, or a view on `buffer` if `asTypedArray = true`. */ -export function mnnCorrect(x, block, { - asTypedArray = true, - buffer = null, - numberOfDims = null, - numberOfCells = null, - k = 15, - numberOfMADs = 3, - robustIterations = 2, - robustTrim = 0.25, - referencePolicy = "max-rss", - approximate = true, - numberOfThreads = null -} = {}) { +export function mnnCorrect(x, block, options = {}) { + let { + asTypedArray = true, + buffer = null, + numberOfDims = null, + numberOfCells = null, + k = 15, + numberOfMADs = 3, + robustIterations = 2, + robustTrim = 0.25, + referencePolicy = "max-rss", + approximate = true, + numberOfThreads = null, + ...others + } = options; + utils.checkOtherOptions(others); let local_buffer = null; let x_data; diff --git a/js/modelGeneVariances.js b/js/modelGeneVariances.js index 2e0ed706..0522f6a0 100644 --- a/js/modelGeneVariances.js +++ b/js/modelGeneVariances.js @@ -26,7 +26,9 @@ export class ModelGeneVariancesResults { * containing the mean log-expression across all cells in the specified `block` * (or the average across all blocks, if `block = null`). */ - means({ block = null, copy = true } = {}) { + means(options = {}) { + const { block = null, copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.means(block == null ? -1 : block), copy); } @@ -42,7 +44,9 @@ export class ModelGeneVariancesResults { * containing the variance of log-expression across all cells in the specified `block` * (or the average across all blocks, if `block = null`). */ - variances({ block = null, copy = true } = {}) { + variances(options = {}) { + const { block = null, copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.variances(block == null ? -1 : block), copy); } @@ -59,7 +63,9 @@ export class ModelGeneVariancesResults { * (or the average across all blocks, if `block = null`). * Alternatively `null`, if `fillable = false` and the array was not already filled. */ - fitted({ block = null, copy = true } = {}) { + fitted(options = {}) { + const { block = null, copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.fitted(block == null ? -1 : block), copy); } @@ -75,7 +81,9 @@ export class ModelGeneVariancesResults { * containing the residuals from the mean-variance trend for the specified `block` * (or the average across all blocks, if `block = null`). */ - residuals({ block = null, copy = true } = {}) { + residuals(options = {}) { + const { block = null, copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.residuals(block == null ? -1 : block), copy); } @@ -129,7 +137,10 @@ export class ModelGeneVariancesResults { * * @return {ModelGeneVariancesResults} Object containing the variance modelling results. */ -export function modelGeneVariances(x, { block = null, span = 0.3, blockWeightPolicy = "variable", numberOfThreads = null } = {}) { +export function modelGeneVariances(x, options = {}) { + const { block = null, span = 0.3, blockWeightPolicy = "variable", numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + var block_data; var output; let nthreads = utils.chooseNumberOfThreads(numberOfThreads); diff --git a/js/perCellAdtQcMetrics.js b/js/perCellAdtQcMetrics.js index 104e08e5..913fb276 100644 --- a/js/perCellAdtQcMetrics.js +++ b/js/perCellAdtQcMetrics.js @@ -10,7 +10,7 @@ export class PerCellAdtQcMetricsResults { #id; #results; - constructor(id, raw, filled = true) { + constructor(id, raw) { this.#id = id; this.#results = raw; return; @@ -26,7 +26,9 @@ export class PerCellAdtQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Float64Array|Float64WasmArray} Array containing the total ADT count for each cell. */ - sum({ copy = true } = {}) { + sum(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.sum(), copy); } @@ -35,7 +37,9 @@ export class PerCellAdtQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Int32Array|Int32WasmArray} Array containing the total number of detected ADT features for each cell. */ - detected({ copy = true } = {}) { + detected(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.detected(), copy); } @@ -45,7 +49,9 @@ export class PerCellAdtQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Float64Array|Float64WasmArray} Array containing the total count in the ADT subset `i` for each cell. */ - subsetSum(i, { copy = true } = {}) { + subsetSum(i, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.subset_sum(i), copy); } @@ -95,7 +101,9 @@ export class PerCellAdtQcMetricsResults { * * @return {PerCellAdtQcMetricsResults} Object containing the ADT-based QC metrics. */ -export function perCellAdtQcMetrics(x, subsets, { numberOfThreads = null } = {}) { +export function perCellAdtQcMetrics(x, subsets, options = {}) { + const { numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); let nthreads = utils.chooseNumberOfThreads(numberOfThreads); return internal.computePerCellQcMetrics( x, diff --git a/js/perCellCrisprQcMetrics.js b/js/perCellCrisprQcMetrics.js index f243fd7f..abf341bc 100644 --- a/js/perCellCrisprQcMetrics.js +++ b/js/perCellCrisprQcMetrics.js @@ -25,7 +25,9 @@ export class PerCellCrisprQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Float64Array|Float64WasmArray} Array containing the total count across guides for each cell. */ - sum({ copy = true } = {}) { + sum(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.sum(), copy); } @@ -34,7 +36,9 @@ export class PerCellCrisprQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Int32Array|Int32WasmArray} Array containing the total number of detected guides for each cell. */ - detected({ copy = true } = {}) { + detected(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.detected(), copy); } @@ -43,7 +47,9 @@ export class PerCellCrisprQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Float64Array|Float64WasmArray} Array containing the count of the most abundant guide for each cell. */ - maxValue({ copy = true } = {}) { + maxValue(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.max_value(), copy); } @@ -62,7 +68,9 @@ export class PerCellCrisprQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Int32Array|Int32WasmArray} Array containing the index of the most abundant guide for each cell. */ - maxIndex({ copy = true } = {}) { + maxIndex(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.max_index(), copy); } @@ -96,7 +104,9 @@ export class PerCellCrisprQcMetricsResults { * * @return {PerCellCrisprQcMetricsResults} Object containing the QC metrics. */ -export function perCellCrisprQcMetrics(x, { numberOfThreads = null } = {}) { +export function perCellCrisprQcMetrics(x, options = {}) { + const { numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); let nthreads = utils.chooseNumberOfThreads(numberOfThreads); return gc.call( module => module.per_cell_crispr_qc_metrics(x.matrix, nthreads), diff --git a/js/perCellRnaQcMetrics.js b/js/perCellRnaQcMetrics.js index 28bb3842..a7eecb63 100644 --- a/js/perCellRnaQcMetrics.js +++ b/js/perCellRnaQcMetrics.js @@ -26,7 +26,9 @@ export class PerCellRnaQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Float64Array|Float64WasmArray} Array containing the total count across genes for each cell. */ - sum({ copy = true } = {}) { + sum(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.sum(), copy); } @@ -35,7 +37,9 @@ export class PerCellRnaQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Int32Array|Int32WasmArray} Array containing the total number of detected genes for each cell. */ - detected({ copy = true } = {}) { + detected(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.detected(), copy); } @@ -45,7 +49,9 @@ export class PerCellRnaQcMetricsResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Float64Array|Float64WasmArray} Array containing the proportion of counts in the subset `i` for each cell. */ - subsetProportion(i, { copy = true, fillable = false } = {}) { + subsetProportion(i, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.subset_proportion(i), copy); } @@ -95,9 +101,11 @@ export class PerCellRnaQcMetricsResults { * * @return {PerCellRnaQcMetricsResults} Object containing the QC metrics. */ -export function perCellRnaQcMetrics(x, subsets, { numberOfThreads = null } = {}) { +export function perCellRnaQcMetrics(x, subsets, options = {}) { + const { numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); let nthreads = utils.chooseNumberOfThreads(numberOfThreads); - return internal.computePerCellQcMetrics( + return internal.computePerCellQcMetrics( x, subsets, (matrix, nsubsets, subset_offset) => gc.call( diff --git a/js/rds.js b/js/rds.js index e48296ed..851c4612 100644 --- a/js/rds.js +++ b/js/rds.js @@ -101,7 +101,9 @@ export class RdsIntegerVector extends RdsVector { * * @return {Int32Array|Int32WasmArray} Values of the integer vector. */ - values({ copy = true } = {}) { + values(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.object.numeric_vector(), copy); } } @@ -124,7 +126,9 @@ export class RdsBooleanVector extends RdsVector { * @return {Int32Array|Int32WasmArray} Values of the logical vector. * Zero values are falsey and values of 1 are truthy. */ - values({ copy = true } = {}) { + values(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.object.numeric_vector(), copy); } } @@ -146,7 +150,9 @@ export class RdsDoubleVector extends RdsVector { * * @return {Float64Array|Float64WasmArray} Values of the double vector. */ - values({ copy = true } = {}) { + values(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.object.numeric_vector(), copy); } } diff --git a/js/realizeFile.js b/js/realizeFile.js index 1b9b157e..d2465b8d 100644 --- a/js/realizeFile.js +++ b/js/realizeFile.js @@ -1,4 +1,5 @@ import * as methods from "./file.js"; +import * as utils from "./utils.js"; import * as areal from "./abstract/realize.js"; /** @@ -10,7 +11,9 @@ import * as areal from "./abstract/realize.js"; * * @return {string} Temporary file path. */ -export function chooseTemporaryPath({ extension = "" } = {}) { +export function chooseTemporaryPath(options = {}) { + const { extension = "", ...others } = options; + utils.checkOtherOptions(others); return areal.temp("temp_", extension); } @@ -30,7 +33,10 @@ export function chooseTemporaryPath({ extension = "" } = {}) { * - `flush`: a function to be called to remove any temporary file created by this function. * For Node.js, this will be a no-op if `file` is already a path. */ -export function realizeFile(file, { extension = "" } = {}) { +export function realizeFile(file, options = {}) { + const { extension = "", ...others } = options; + utils.checkOtherOptions(others); + if (typeof file == "string") { return areal.handleString(file); } diff --git a/js/runPca.js b/js/runPca.js index 9f6bdd81..206d8b4d 100644 --- a/js/runPca.js +++ b/js/runPca.js @@ -21,7 +21,9 @@ export class RunPcaResults { * @return {Float64Array|Float64Wasmarray} Array containing the principal components for all cells. * This should be treated as a column-major array where the rows are the PCs and columns are the cells. */ - principalComponents({ copy = true } = {}) { + principalComponents(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.components(), copy); } @@ -31,7 +33,9 @@ export class RunPcaResults { * @return {Float64Array|Float64Wasmarray} Array containing the rotation matrix for all cells. * This should be treated as a column-major array where the rows are the genes and the columns are the PCs. */ - rotation({ copy = true } = {}) { + rotation(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.pcs(), copy); } @@ -40,7 +44,9 @@ export class RunPcaResults { * @param {boolean} [options.copy=true] - Whether to copy the results from the Wasm heap, see {@linkcode possibleCopy}. * @return {Float64Array|Float64WasmArray} Array containing the variance explained for each requested PC. */ - varianceExplained({ copy = true } = {}) { + varianceExplained(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.variance_explained(), copy); } @@ -120,16 +126,19 @@ export class RunPcaResults { * * @return {RunPcaResults} Object containing the computed PCs. */ -export function runPca(x, { - features = null, - numberOfPCs = 25, - scale = false, - block = null, - blockMethod = "regress", - blockWeightPolicy = "variable", - realizeMatrix = null, - numberOfThreads = null -} = {}) { +export function runPca(x, options = {}) { + let { + features = null, + numberOfPCs = 25, + scale = false, + block = null, + blockMethod = "regress", + blockWeightPolicy = "variable", + realizeMatrix = null, + numberOfThreads = null, + ...others + } = options; + utils.checkOtherOptions(others); var feat_data; var block_data; diff --git a/js/runTsne.js b/js/runTsne.js index 92c5b35e..6275bc70 100644 --- a/js/runTsne.js +++ b/js/runTsne.js @@ -68,7 +68,9 @@ export class TsneStatus { * @return The algorithm status in `x` is advanced up to the requested number of iterations, * or until the requested run time is exceeded, whichever comes first. */ - run({ maxIterations = 1000, runTime = null } = {}) { + run(options = {}) { + let { maxIterations = 1000, runTime = null, ...others } = options; + utils.checkOtherOptions(others); if (runTime === null) { runTime = -1; } @@ -113,7 +115,10 @@ export function perplexityToNeighbors(perplexity) { * * @return {TsneStatus} Object containing the initial status of the t-SNE algorithm. */ -export function initializeTsne(x, { perplexity = 30, checkMismatch = true, numberOfThreads = null } = {}) { +export function initializeTsne(x, options = {}) { + const { perplexity = 30, checkMismatch = true, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + var my_neighbors; var raw_coords; var output; @@ -174,7 +179,9 @@ export function initializeTsne(x, { perplexity = 30, checkMismatch = true, numbe * * @return {object} Object containing coordinates of the t-SNE embedding, see {@linkcode TsneStatus#extractCoordinates TsneStatus.extractCoordinates} for more details. */ -export function runTsne(x, { perplexity = 30, checkMismatch = true, numberOfThreads = null, maxIterations = 1000 } = {}) { +export function runTsne(x, options = {}) { + const { perplexity = 30, checkMismatch = true, numberOfThreads = null, maxIterations = 1000, ...others } = options; + utils.checkOtherOptions(others); let tstat = initializeTsne(x, { perplexity, checkMismatch, numberOfThreads }); tstat.run({ maxIterations }); return tstat.extractCoordinates(); diff --git a/js/runUmap.js b/js/runUmap.js index d18a03f2..87b4e26c 100644 --- a/js/runUmap.js +++ b/js/runUmap.js @@ -64,7 +64,9 @@ export class UmapStatus { * @return The algorithm status in `x` is advanced up to the total number of epochs used to initialize `x`, * or until the requested run time is exceeded, whichever comes first. */ - run({ runTime = null } = {}) { + run(options = {}) { + let { runTime = null, ...others } = options; + utils.checkOtherOptions(others); if (runTime === null) { runTime = -1; } @@ -111,7 +113,10 @@ export class UmapStatus { * * @return {UmapStatus} Object containing the initial status of the UMAP algorithm. */ -export function initializeUmap(x, { neighbors = 15, epochs = 500, minDist = 0.01, numberOfThreads = null } = {}) { +export function initializeUmap(x, options = {}) { + const { neighbors = 15, epochs = 500, minDist = 0.01, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + var my_neighbors; var raw_coords; var output; @@ -163,7 +168,9 @@ export function initializeUmap(x, { neighbors = 15, epochs = 500, minDist = 0.01 * * @return {object} Object containing coordinates of the UMAP embedding, see {@linkcode UmapStatus#extractCoordinates UmapStatus.extractCoordinates} for more details. */ -export function runUmap(x, { neighbors = 15, epochs = 500, minDist = 0.01, numberOfThreads = null } = {}) { +export function runUmap(x, options = {}){ + const { neighbors = 15, epochs = 500, minDist = 0.01, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); let ustat = initializeUmap(x, { neighbors, epochs, minDist, numberOfThreads }); ustat.run(); return ustat.extractCoordinates(); diff --git a/js/scaleByNeighbors.js b/js/scaleByNeighbors.js index 773b9f6a..4f5f2a43 100644 --- a/js/scaleByNeighbors.js +++ b/js/scaleByNeighbors.js @@ -31,7 +31,10 @@ import { buildNeighborSearchIndex, BuildNeighborSearchIndexResults } from "./fin * @return {Float64Array|Float64WasmArray} Array containing the combined embeddings in column-major format, i.e., dimensions in rows and cells in columns. * If `buffer` is supplied, the function returns `buffer` if `asTypedArray = false`, or a view on `buffer` if `asTypedArray = true`. */ -export function scaleByNeighbors(embeddings, numberOfCells, { neighbors = 20, indices = null, asTypedArray = true, buffer = null, approximate = true, weights = null, numberOfThreads = null } = {}) { +export function scaleByNeighbors(embeddings, numberOfCells, options = {}) { + let { neighbors = 20, indices = null, asTypedArray = true, buffer = null, approximate = true, weights = null, numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + let embed_ptrs; let index_ptrs; let holding_weights; diff --git a/js/scoreGsdecon.js b/js/scoreGsdecon.js index f4b38ae5..0015ad65 100644 --- a/js/scoreGsdecon.js +++ b/js/scoreGsdecon.js @@ -31,7 +31,10 @@ import * as wa from "wasmarrays.js"; * - `weights`, a Float64Array containing per-gene weights for each feature in the set. * - `scores`, a Float64Array containing the per-cell scores for each column of `x`. */ -export function scoreGsdecon(x, features, { block = null, scale = false, blockWeightPolicy = "variable", numberOfThreads = null } = {}) { +export function scoreGsdecon(x, features, options = {}) { + const { block = null, scale = false, blockWeightPolicy = "variable", numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + let temp; let output = {}; let feature_data, block_data; diff --git a/js/scoreMarkers.js b/js/scoreMarkers.js index fa9bd4de..f3f63659 100644 --- a/js/scoreMarkers.js +++ b/js/scoreMarkers.js @@ -35,7 +35,9 @@ export class ScoreMarkersResults { * @return {?(Float64Array|Float64WasmArray)} Array of length equal to the number of genes, * containing the mean expression for the requested group in the requested block. */ - mean(group, { copy = true } = {}) { + mean(group, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.mean(group), copy); } @@ -48,7 +50,9 @@ export class ScoreMarkersResults { * @return {Float64Array|Float64WasmArray} Array of length equal to the number of genes, * containing the proportion of cells with detectable expression for the requested group in the requested block. */ - detected(group, { copy = true } = {}) { + detected(group, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.detected(group), copy); } @@ -70,7 +74,9 @@ export class ScoreMarkersResults { * @return {Float64Array|Float64WasmArray} Array of length equal to the number of genes, * containing the summarized Cohen's d for the comparisons between `group` and all other groups. */ - cohensD(group, { summary = "mean", copy = true } = {}) { + cohensD(group, options = {}) { + const { summary = "mean", copy = true, ...others } = options; + utils.checkOtherOptions(others); this.#check_forbidden(summary); return utils.possibleCopy(wasm.call(_ => this.#results.cohens_d(group, summary)), copy); } @@ -90,7 +96,9 @@ export class ScoreMarkersResults { * @return {Float64Array|Float64WasmArray} Array of length equal to the number of genes, * containing the summarized AUC for the comparisons between `group` and all other groups. */ - auc(group, { summary = "mean", copy = true } = {}) { + auc(group, options = {}) { + const { summary = "mean", copy = true, ...others } = options; + utils.checkOtherOptions(others); this.#check_forbidden(summary); return utils.possibleCopy(wasm.call(_ => this.#results.auc(group, summary)), copy); } @@ -108,7 +116,9 @@ export class ScoreMarkersResults { * containing the summarized delta-mean for the comparisons between `group` and all other groups. * This can be interpreted as the log-fold change if log-expression values are used in {@linkcode scoreMarkers}. */ - deltaMean(group, { summary = "mean", copy = true } = {}) { + deltaMean(group, options = {}) { + const { summary = "mean", copy = true, ...others } = options; + utils.checkOtherOptions(others); this.#check_forbidden(summary); return utils.possibleCopy(wasm.call(_ => this.#results.delta_mean(group, summary)), copy); } @@ -125,7 +135,9 @@ export class ScoreMarkersResults { * @return {Float64Array|Float64WasmArray} Array of length equal to the number of genes, * containing the summarized delta-detected for the comparisons between `group` and all other groups. */ - deltaDetected(group, { summary = "mean", copy = true } = {}) { + deltaDetected(group, options = {}) { + const { summary = "mean", copy = true, ...others } = options; + utils.checkOtherOptions(others); this.#check_forbidden(summary); return utils.possibleCopy(wasm.call(_ => this.#results.delta_detected(group, summary)), copy); } @@ -168,7 +180,10 @@ export class ScoreMarkersResults { * * @return {ScoreMarkersResults} Object containing the marker scoring results. */ -export function scoreMarkers(x, groups, { block = null, threshold = 0, computeAuc = true, computeMedian = false, computeMaximum = false , numberOfThreads = null} = {}) { +export function scoreMarkers(x, groups, options = {}) { + const { block = null, threshold = 0, computeAuc = true, computeMedian = false, computeMaximum = false , numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + var output; var block_data; var group_data; diff --git a/js/subset.js b/js/subset.js index 6655cf12..d8fb9f5c 100644 --- a/js/subset.js +++ b/js/subset.js @@ -16,7 +16,10 @@ import { MultiMatrix } from "./MultiMatrix.js"; * A ScranMatrix containing the subset of rows from `mat` specified by `indices`. * If `inPlace = true`, this is a reference to `x`, otherwise it is a new ScranMatrix. */ -export function subsetRows(x, indices, { inPlace = false } = {}) { +export function subsetRows(x, indices, options = {}) { + const { inPlace = false, ...others } = options; + utils.checkOtherOptions(others); + let xcopy; let target; let wasm_indices; @@ -57,7 +60,10 @@ export function subsetRows(x, indices, { inPlace = false } = {}) { * A new ScranMatrix containing the subset of columns from `mat` specified by `indices`. * If `inPlace = true`, this is a reference to `x`, otherwise it is a new ScranMatrix. */ -export function subsetColumns(x, indices, { inPlace = false } = {}) { +export function subsetColumns(x, indices, options = {}) { + const { inPlace = false, ...others } = options; + utils.checkOtherOptions(others); + let xcopy; let target; let wasm_indices; @@ -98,7 +104,10 @@ export function subsetColumns(x, indices, { inPlace = false } = {}) { * @return {object|MultiMatrix} Object with the same keys as `split` where each value is a ScranMatrix for the corresponding subset of rows. * Alternatively, this is wrapped in a MultiMatrix if `createMultiMatrix = true`. */ -export function splitRows(matrix, split, { singleNull = false, createMultiMatrix = false } = {}) { +export function splitRows(matrix, split, options = {}) { + const { singleNull = false, createMultiMatrix = false, ...others } = options; + utils.checkOtherOptions(others); + let output = {}; let tkeys = Object.keys(split); diff --git a/js/suggestAdtQcFilters.js b/js/suggestAdtQcFilters.js index 8842f5f0..652c333c 100644 --- a/js/suggestAdtQcFilters.js +++ b/js/suggestAdtQcFilters.js @@ -23,7 +23,9 @@ export class SuggestAdtQcFiltersResults { * * @return {?(Float64Array|Float64WasmArray)} Array containing the filtering threshold on the number of detected ADTs for each batch. */ - detected({ copy = true } = {}) { + detected(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.detected(), copy); } @@ -35,7 +37,9 @@ export class SuggestAdtQcFiltersResults { * * @return {?(Float64Array|Float64WasmArray)} Array containing the filtering threshold on the total counts for subset `i` in each batch. */ - subsetSum(i, { copy = true } = {}) { + subsetSum(i, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.subset_sum(i), copy); } @@ -74,7 +78,9 @@ export class SuggestAdtQcFiltersResults { * Each entry is truthy if the corresponding cell is deemed to be of high-quality based on its values in `metrics`. * If `buffer` is supplied, the returned array is a view on `buffer`. */ - filter(metrics, { block = null, buffer = null } = {}) { + filter(metrics, options = {}) { + const { block = null, buffer = null, ...others } = options; + utils.checkOtherOptions(others); if (!(metrics instanceof PerCellAdtQcMetricsResults)) { throw new Error("'metrics' should be a PerCellAdtQcMetricsResults object"); } @@ -109,10 +115,14 @@ export class SuggestAdtQcFiltersResults { * * @return {SuggestAdtQcFiltersResults} Object containing the filtering results. */ -export function suggestAdtQcFilters(metrics, { numberOfMADs = 3, minDetectedDrop = 0.1, block = null } = {}) { +export function suggestAdtQcFilters(metrics, options = {}) { + const { numberOfMADs = 3, minDetectedDrop = 0.1, block = null, ...others } = options; + utils.checkOtherOptions(others); + if (!(metrics instanceof PerCellAdtQcMetricsResults)) { throw new Error("'metrics' should be a PerCellAdtQcMetricsResults object"); } + return internal.computePerCellQcFilters( metrics, block, diff --git a/js/suggestCrisprQcFilters.js b/js/suggestCrisprQcFilters.js index 857b3947..eec13f5f 100644 --- a/js/suggestCrisprQcFilters.js +++ b/js/suggestCrisprQcFilters.js @@ -23,17 +23,12 @@ export class SuggestCrisprQcFiltersResults { * * @return {?(Float64Array|Float64WasmArray)} Array containing the filtering threshold on the maximum count in each batch. */ - maxValue({ copy = true } = {}) { + maxValue(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.max_value(), copy); } - /** - * @ignore - */ - thresholdsMaxCount({ copy = true } = {}) { - return this.thresholdsMaxValue({ copy }); - } - /** * @return {number} Number of blocks in this object. */ @@ -55,7 +50,9 @@ export class SuggestCrisprQcFiltersResults { * Each entry is truthy if the corresponding cell is deemed to be of high-quality based on its values in `metrics`. * If `buffer` is supplied, the returned array is a view on `buffer`. */ - filter(metrics, { block = null, buffer = null } = {}) { + filter(metrics, options = {}) { + const { block = null, buffer = null, ...others } = options; + utils.checkOtherOptions(others); if (!(metrics instanceof PerCellCrisprQcMetricsResults)) { throw new Error("'metrics' should be a PerCellCrisprQcMetricsResults object"); } @@ -88,10 +85,14 @@ export class SuggestCrisprQcFiltersResults { * * @return {SuggestCrisprQcFiltersResults} Object containing the filtering results. */ -export function suggestCrisprQcFilters(metrics, { numberOfMADs = 3, block = null } = {}) { +export function suggestCrisprQcFilters(metrics, options = {}) { + const { numberOfMADs = 3, block = null, ...others } = options; + utils.checkOtherOptions(others); + if (!(metrics instanceof PerCellCrisprQcMetricsResults)) { throw new Error("'metrics' should be a PerCellCrisprQcMetricsResults object"); } + return internal.computePerCellQcFilters( metrics, block, diff --git a/js/suggestRnaQcFilters.js b/js/suggestRnaQcFilters.js index 12d71d87..b824e92b 100644 --- a/js/suggestRnaQcFilters.js +++ b/js/suggestRnaQcFilters.js @@ -23,7 +23,9 @@ export class SuggestRnaQcFiltersResults { * * @return {Float64Array|Float64WasmArray} Array containing the filtering threshold on the sums for each batch. */ - sum({ copy = true } = {}) { + sum(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.sum(), copy); } @@ -34,7 +36,9 @@ export class SuggestRnaQcFiltersResults { * * @return {Float64Array|Float64WasmArray} Array containing the filtering threshold on the number of detected genes for each batch. */ - detected({ copy = true } = {}) { + detected(options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.detected(), copy); } @@ -46,7 +50,9 @@ export class SuggestRnaQcFiltersResults { * * @return {Float64Array|Float64WasmArray} Array containing the filtering threshold on the proportions for subset `i` in each batch. */ - subsetProportion(i, { copy = true } = {}) { + subsetProportion(i, options = {}) { + const { copy = true, ...others } = options; + utils.checkOtherOptions(others); return utils.possibleCopy(this.#results.subset_proportion(i), copy); } @@ -83,7 +89,9 @@ export class SuggestRnaQcFiltersResults { * Each entry is truthy if the corresponding cell is deemed to be of high-quality based on its values in `metrics`. * If `buffer` is supplied, the returned array is a view on `buffer`. */ - filter(metrics, { block = null, buffer = null } = {}) { + filter(metrics, options = {}) { + const { block = null, buffer = null, ...others } = options; + utils.checkOtherOptions(others); if (!(metrics instanceof PerCellRnaQcMetricsResults)) { throw new Error("'metrics' should be a PerCellRnaQcMetricsResults object"); } @@ -116,10 +124,14 @@ export class SuggestRnaQcFiltersResults { * * @return {SuggestRnaQcFiltersResults} Object containing the filtering results. */ -export function suggestRnaQcFilters(metrics, { numberOfMADs = 3, block = null } = {}) { +export function suggestRnaQcFilters(metrics, options = {}) { + const { numberOfMADs = 3, block = null, ...others } = options; + utils.checkOtherOptions(others); + if (!(metrics instanceof PerCellRnaQcMetricsResults)) { throw new Error("'metrics' should be a PerCellRnaQcMetricsResults object"); } + return internal.computePerCellQcFilters( metrics, block, diff --git a/js/testGeneSetEnrichment.js b/js/testGeneSetEnrichment.js index 52daba3f..184ad88a 100644 --- a/js/testGeneSetEnrichment.js +++ b/js/testGeneSetEnrichment.js @@ -26,7 +26,10 @@ import * as utils from "./utils.js"; * - `size`: Int32Array containing the size of each set. * - `pvalue`: Float64Array containing the p-value for enrichment in each set. */ -export function testGeneSetEnrichment(markers, geneSets, totalGenes, { numberOfThreads = null } = {}) { +export function testGeneSetEnrichment(markers, geneSets, totalGenes, options = {}) { + const { numberOfThreads = null, ...others } = options; + utils.checkOtherOptions(others); + for (const j of markers) { if (j >= totalGenes) { throw new Error("'markers' contains out-of-range indices (" + String(j) + ")"); diff --git a/js/utils.js b/js/utils.js index 2f9f7856..1ce26425 100644 --- a/js/utils.js +++ b/js/utils.js @@ -153,12 +153,6 @@ export function matchOptions(name, value, choices) { } } -export function spawnArray(n, fill) { - let output = new Array(n); - output.fill(fill); - return output; -} - export function toTypedArray(buffer, wasSupplied, asTypedArray) { if (asTypedArray) { if (!wasSupplied) { @@ -172,3 +166,9 @@ export function toTypedArray(buffer, wasSupplied, asTypedArray) { return buffer; } } + +export function checkOtherOptions(options) { + for (const key of Object.keys(options)) { + throw new Error("unknown option '" + key + "'"); + } +} diff --git a/js/writeSparseMatrixToHdf5.js b/js/writeSparseMatrixToHdf5.js index 6eff9c22..48873bf3 100644 --- a/js/writeSparseMatrixToHdf5.js +++ b/js/writeSparseMatrixToHdf5.js @@ -1,5 +1,6 @@ import * as h5 from "./hdf5.js"; import * as wasm from "./wasm.js"; +import * as utils from "./utils.js"; /** * Write a sparse {@linkplain ScranMatrix} into HDF5 file, in the form of its compressed sparse components. @@ -23,7 +24,9 @@ import * as wasm from "./wasm.js"; * * @return `x` is written to `path` at `name`. */ -export function writeSparseMatrixToHdf5(x, path, name, { format = "tenx_matrix", forceInteger = false } = {}) { +export function writeSparseMatrixToHdf5(x, path, name, options = {}) { + const { format = "tenx_matrix", forceInteger = false, ...others } = options; + utils.checkOtherOptions(others); wasm.call(module => module.write_sparse_matrix_to_hdf5(x.matrix, path, name, format, forceInteger)); let handle = new h5.H5Group(path, name); diff --git a/tests/initializeScranMatrixFromHdf5.test.js b/tests/initializeScranMatrixFromHdf5.test.js index 927c0f36..c7918f8d 100644 --- a/tests/initializeScranMatrixFromHdf5.test.js +++ b/tests/initializeScranMatrixFromHdf5.test.js @@ -275,7 +275,7 @@ test("initialization from HDF5 works correctly with forced integers", () => { } // Using raw access. - var mat3 = scran.initializeSparseMatrixFromHdf5(path, "foobar", { numberOfRows: nr, numberOfColumns: nc, sparseByRow: false, forceInteger: true, layered: true }); + var mat3 = scran.initializeSparseMatrixFromHdf5Group(path, "foobar", nr, nc, false, { forceInteger: true, layered: true }); expect(mat3.numberOfRows()).toBe(nr); expect(mat3.numberOfColumns()).toBe(nc); expect(compare.equalArrays(mat3.row(0), mat1.row(0))).toBe(true); diff --git a/tests/initializeSparseMatrixFromMatrixMarket.test.js b/tests/initializeSparseMatrixFromMatrixMarket.test.js index 91365615..0708b709 100644 --- a/tests/initializeSparseMatrixFromMatrixMarket.test.js +++ b/tests/initializeSparseMatrixFromMatrixMarket.test.js @@ -94,7 +94,7 @@ test("initialization from Gzipped MatrixMarket works correctly with Gzip", () => expect(compare.equalArrays(mat.column(2), [0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0])).toBe(true); // Just checking that the it's actually compressed. - var mat2 = scran.initializeSparseMatrixFromMatrixMarket(buffer, { compressed: true }); + var mat2 = scran.initializeSparseMatrixFromMatrixMarket(buffer, { compression: "gzip" }); expect(mat2.numberOfRows()).toBe(11); expect(mat2.numberOfColumns()).toBe(5); expect(compare.equalArrays(mat2.row(4), mat.row(4))).toBe(true); diff --git a/tests/labelCells.test.js b/tests/labelCells.test.js index d420be02..4a50ede6 100644 --- a/tests/labelCells.test.js +++ b/tests/labelCells.test.js @@ -276,12 +276,15 @@ test("labelCells ignores nulls correctly", () => { for (var i = 0; i < until; i++) { copy[i] = null; } + let built = scran.trainLabelCellsReference(copy, refinfo, mockids); expect(built.numberOfFeatures() > 0).toBe(true); + let results = scran.labelCells(mat, built); let labels = results.predicted(); - expect(compare.equalArrays(labels, refresults.predicted({ copy: false }))).toBe(false); - let firstscore = results.scoreForCell(0, { copy: false }); + expect(compare.equalArrays(labels, refresults.predicted({ copy: false }))).toBe(false); // should have some diff! + let firstscore = results.scoreForCell(0); + expect(compare.equalFloatArrays(firstscore, refresults.scoreForCell(0))).toBe(false); // Manually removing the first gene from the test matrix. { diff --git a/tests/rds/init.test.js b/tests/rds/init.test.js index 333d6d1c..4cfd03fe 100644 --- a/tests/rds/init.test.js +++ b/tests/rds/init.test.js @@ -92,21 +92,6 @@ maybe("works for dgCMatrix", () => { expect_all(x, y => y%1 == 0); // forced integers. test_okayish(x, 70, 30, layered); - // Same results in consumption mode. - { - let stuff2 = scran.readRds(rpath); - let vals2 = stuff2.value(); - let x2 = scran.initializeSparseMatrixFromRds(vals2, { layered: layered, consume: true }); - - for (var c = 0; c < x.numberOfColumns(); c++) { - expect(compare.equalArrays(x.column(c), x2.column(c))).toBe(true); - } - - x2.free(); - vals2.free(); - stuff2.free(); - } - x.free(); } @@ -131,21 +116,6 @@ maybe("works for dgTMatrix", () => { test_okayish(x, 30, 70, layered); expect_all(x, y => y%1 == 0); // forced integers. - // Same results in consumption mode. - { - let stuff2 = scran.readRds(rpath); - let vals2 = stuff2.value(); - let x2 = scran.initializeSparseMatrixFromRds(vals2, { layered: layered, consume: true }); - - for (var c = 0; c < x.numberOfColumns(); c++) { - expect(compare.equalArrays(x.column(c), x2.column(c))).toBe(true); - } - - x2.free(); - vals2.free(); - stuff2.free(); - } - x.free(); }