UNPKG

scran.js

Version:

Single cell RNA-seq analysis in Javascript

108 lines (94 loc) 4.38 kB
import * as utils from "./utils.js"; import * as wasm from "./wasm.js"; /** * Perform a hypergeometric test, typically for over-enrichment of markers across gene sets. * This can be computed for multiple gene sets by providing arrays as some or all of the arguments. * If multiple arrays are supplied, they must be of the same length. * * @param {number|Array|TypedArray|WasmArray} markersInSet - Number of detected markers that are also in the gene set. * @param {number|Array|TypedArray|WasmArray} numberOfMarkers - Total number of detected markers. * @param {number|Array|TypedArray|WasmArray} geneSetSize - Size of the gene set. * @param {number|Array|TypedArray|WasmArray} numberOfGenes - Total number of genes. * @param {object} [options={}] - Optional parameters. * @param {boolean} [options.asTypedArray=true] - Whether to return a Float64Array. * If `false`, a Float64WasmArray is returned instead. * @param {?Float64WasmArray} [options.buffer=null] - Buffer in which to store the output. * If not `null`, this should have the same length as any of the array-like arguments. * @param {boolean} [options.log=false] - Whether to compute log-probabilities. * @param {?number} [options.numberOfThreads=null] - Number of threads to use. * If `null`, defaults to {@linkcode maximumThreads}. * * @return {Float64Array|Float64WasmArray} An array of length equal to that of the supplied arrays (or 1, if no arrays are supplied). * 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, options = {}) { let { asTypedArray = true, buffer = null, log = false, numberOfThreads = null, ...others } = options; utils.checkOtherOptions(others); let markersInSet_data; let numberOfMarkers_data; let geneSetSize_data; let numberOfGenes_data; let nthreads = utils.chooseNumberOfThreads(numberOfThreads); let ntests = null; let check_length = (candidate, name, sofar) => { if (sofar !== null && candidate.length !== sofar) { throw new Error("array inputs must have the same length (failing for '" + name + "')"); } return candidate.length; } if (typeof markersInSet == "number") { markersInSet = [markersInSet]; } else { ntests = check_length(markersInSet, "markersInSet", ntests); } if (typeof numberOfMarkers == "number") { numberOfMarkers = [numberOfMarkers]; } else { ntests = check_length(numberOfMarkers, "numberOfMarkers", ntests); } if (typeof geneSetSize == "number") { geneSetSize = [geneSetSize]; } else { ntests = check_length(geneSetSize, "geneSetSize", ntests); } if (typeof numberOfGenes == "number") { numberOfGenes = [numberOfGenes]; } else { ntests = check_length(numberOfGenes, "numberOfGenes", ntests); } if (ntests == null) { ntests = 1; } let tmp = null; try { markersInSet_data = utils.wasmifyArray(markersInSet, "Int32WasmArray"); numberOfMarkers_data = utils.wasmifyArray(numberOfMarkers, "Int32WasmArray"); geneSetSize_data = utils.wasmifyArray(geneSetSize, "Int32WasmArray"); numberOfGenes_data = utils.wasmifyArray(numberOfGenes, "Int32WasmArray"); if (buffer == null) { buffer = utils.createFloat64WasmArray(ntests); tmp = buffer; } wasm.call(module => module.hypergeometric_test( ntests, markersInSet_data.length != 1, markersInSet_data.offset, geneSetSize_data.length != 1, geneSetSize_data.offset, numberOfMarkers_data.length != 1, numberOfMarkers_data.offset, numberOfGenes_data.length != 1, numberOfGenes_data.offset, buffer.offset, log, nthreads )); } finally { utils.free(markersInSet_data); utils.free(numberOfMarkers_data); utils.free(geneSetSize_data); utils.free(numberOfGenes_data); } return utils.toTypedArray(buffer, tmp == null, asTypedArray); }