rsomics_limma_array_weights/
lib.rs1mod matrix;
9mod reml;
10
11use std::io::Write;
12use std::path::Path;
13
14use rsomics_common::{Result, RsomicsError};
15
16pub use matrix::{read_design, read_expr};
17
18pub struct Options<'a> {
19 pub expr: &'a Path,
20 pub design: &'a Path,
21 pub prior_n: f64,
22 pub maxiter: usize,
23 pub tol: f64,
24}
25
26pub struct Results {
27 pub samples: Vec<String>,
28 pub weights: Vec<f64>,
29 pub n_genes: usize,
30 pub iters: usize,
31 pub converged: bool,
32}
33
34pub fn run(opts: &Options) -> Result<Results> {
35 let expr = read_expr(opts.expr)?;
36 let design = read_design(opts.design)?;
37 if design.x.len() != expr.samples.len() {
38 return Err(RsomicsError::InvalidInput(format!(
39 "design has {} rows, expression has {} samples",
40 design.x.len(),
41 expr.samples.len()
42 )));
43 }
44
45 let fit = reml::array_weights(&expr.y, &design.x, opts.prior_n, opts.maxiter, opts.tol)?;
46
47 Ok(Results {
48 samples: expr.samples,
49 weights: fit.weights,
50 n_genes: expr.y.len(),
51 iters: fit.iters,
52 converged: fit.converged,
53 })
54}
55
56pub fn write_weights(res: &Results, out: &mut dyn Write) -> Result<()> {
57 let mut buf = ryu::Buffer::new();
58 writeln!(out, "sample\tweight").map_err(RsomicsError::Io)?;
59 for (s, w) in res.samples.iter().zip(&res.weights) {
60 writeln!(out, "{s}\t{}", buf.format(*w)).map_err(RsomicsError::Io)?;
61 }
62 Ok(())
63}