use extendr_api::{List, Robj};
use std::collections::HashMap;
use crate::single_cell::sc_processing::knn::KnnParams;
use crate::{
prelude::VecConvert,
single_cell::{multi_modal::wnn::parse_sigma_method, sc_processing::snn::parse_snn_type},
};
use super::{adt::dsb::DsbParams, wnn::WnnParams};
impl WnnParams {
pub fn from_r_list(r_list: List) -> Result<Self, extendr_api::Error> {
let knn_params = KnnParams::from_r_list(r_list.clone())?;
let params: HashMap<&str, Robj> = r_list.try_into()?;
let defaults = Self::default();
let k_nn = params
.get("k_nn")
.and_then(|v| v.as_integer())
.map(|v| v as usize)
.unwrap_or(defaults.k_nn);
let knn_range = params
.get("knn_range")
.and_then(|v| v.as_integer())
.map(|v| v as usize)
.unwrap_or(defaults.knn_range);
let sigma_method = params
.get("sigma_method")
.and_then(|v| v.as_str())
.and_then(parse_sigma_method)
.unwrap_or(defaults.sigma_method);
let sigma_idx = params
.get("sigma_idx")
.and_then(|v| v.as_integer())
.map(|v| v as usize)
.unwrap_or(defaults.sigma_idx);
let snn_type = params
.get("snn_type")
.and_then(|v| v.as_str())
.and_then(parse_snn_type)
.unwrap_or(defaults.snn_type);
let s_nn = params
.get("s_nn")
.and_then(|v| v.as_integer())
.map(|v| v as usize)
.unwrap_or(defaults.s_nn);
let sd_scale = params
.get("sd_scale")
.and_then(|v| v.as_real())
.map(|v| v as f32)
.unwrap_or(defaults.sd_scale);
let kernel_power = params
.get("kernel_power")
.and_then(|v| v.as_real())
.map(|v| v as f32)
.unwrap_or(defaults.kernel_power);
let cross_const = params
.get("cross_const")
.and_then(|v| v.as_real())
.map(|v| v as f32)
.unwrap_or(defaults.cross_const);
let sigma_floor = params
.get("sigma_floor")
.and_then(|v| v.as_real())
.map(|v| v as f32)
.unwrap_or(defaults.sigma_floor);
Ok(Self {
k_nn,
knn_range,
sigma_method,
sigma_idx,
snn_type,
s_nn,
sd_scale,
kernel_power,
cross_const,
sigma_floor,
knn_params,
})
}
}
impl DsbParams {
pub fn from_r_list(
r_list: List,
isotype_indices: Vec<i32>,
) -> Result<Self, extendr_api::Error> {
let params: HashMap<&str, Robj> = r_list.try_into()?;
let defaults = Self::default();
let denoise_counts = params
.get("denoise_counts")
.and_then(|v| v.as_bool())
.unwrap_or(defaults.denoise_counts);
let use_isotype_controls = params
.get("use_isotype_controls")
.and_then(|v| v.as_bool())
.unwrap_or(defaults.use_isotype_controls);
let isotype_indices = isotype_indices.r_int_convert();
let pseudocount = params
.get("pseudocount")
.and_then(|v| v.as_real())
.unwrap_or(defaults.pseudocount);
let quantile_low = params.get("quantile_low").and_then(|v| v.as_real());
let quantile_high = params.get("quantile_high").and_then(|v| v.as_real());
let quantile_clip = match (quantile_low, quantile_high) {
(Some(lo), Some(hi)) => Some((lo, hi)),
_ => defaults.quantile_clip,
};
Ok(Self {
denoise_counts,
use_isotype_controls,
isotype_indices,
pseudocount,
quantile_clip,
..defaults
})
}
}