import * as wasm from "./wasm.js";
import * as utils from "./utils.js";
import { ScranMatrix } from "./ScranMatrix.js";
import * as wa from "wasmarrays.js";
/**
* Compute median-based size factors to remove composition biases.
* This is similar to the DESeq2 normalization strategy,
* and the factors can be directly used in {@linkcode logNormCounts}.
*
* @param {ScranMatrix} x The count matrix, usually after filtering.
* @param {object} [options={}] - Optional parameters.
* @param {boolean} [options.center=true] - Whether to return centered size factors.
* If `false`, the size factors can be interpreted as the scaling to match `reference`.
* @param {?(Array|TypedArray|Float64WasmArray)} [options.reference=null] - Reference profile to normalize against.
* This should be an array of length equal to the number of rows in `x`.
* If `null`, this is automatically set to the row means of `x`.
* @param {?Float64WasmArray} [options.buffer=null] - Output buffer for the size factors.
* This should have length equal to the number of columns in `x`.
* @param {number} [options.priorCount=10] Prior count to use for shrinking size factors towards the relative library size.
* Larger values result in stronger shrinkage when the coverage is low.
* @param {?number} [options.numberOfThreads=null] - Number of threads to use.
* If `null`, defaults to {@linkcode maximumThreads}.
*
* @return {Float64WasmArray} Array of length equal to the number of columns in `x`, containing the size factors for all cells.
*
* If `buffer` was supplied, it is used as the return value.
*/
export function medianSizeFactors(x, { center = true, reference = null, buffer = null, priorCount = 10, numberOfThreads = null } = {}) {
var local_buffer;
var ref_arr;
let nthreads = utils.chooseNumberOfThreads(numberOfThreads);
try {
if (!(buffer instanceof wa.Float64WasmArray)) {
local_buffer = utils.createFloat64WasmArray(x.numberOfColumns());
buffer = local_buffer;
} else if (buffer.length !== x.numberOfColumns()) {
throw new Error("length of 'buffer' must be equal to the number of columns in 'x'");
}
let use_ref = (reference !== null)
let ref_ptr = 0;
if (use_ref) {
ref_arr = utils.wasmifyArray(reference, "Float64WasmArray");
if (ref_arr.length !== x.numberOfRows()) {
throw new Error("length of 'reference' must be equal to the number of rows in 'x'");
}
ref_ptr = ref_arr.offset;
}
wasm.call(module => module.median_size_factors(x.matrix, use_ref, ref_ptr, center, priorCount, buffer.offset, nthreads));
} catch (e) {
utils.free(local_buffer);
throw e;
} finally {
utils.free(ref_arr);
}
return buffer;
}