test_that("downsample_immundata downsamples single-cell repertoires and is deterministic with seed", {
v_call = c("IGHV1", "IGHV2", "IGHV3", "IGHV4", "IGHV1", "IGHV2", "IGHV3", "IGHV4"),
j_call = c("IGHJ1", "IGHJ2", "IGHJ3", "IGHJ4", "IGHJ1", "IGHJ2", "IGHJ3", "IGHJ4"),
junction_aa = c("CARA", "CARB", "CARC", "CARD", "CARE", "CARF", "CARG", "CARH"),
features = c("v_call", "j_call", "junction_aa"),
context = "downsample single-cell deterministic"
ds1 <- downsample_immundata(idata, n = 2, seed = 100)
ds2 <- downsample_immundata(idata, n = 2, seed = 100)
test_that("downsample_immundata downsampled bulk repertoires by count", {
v_call = c("TRBV1", "TRBV2", "TRBV3", "TRBV4"),
j_call = c("TRBJ1", "TRBJ2", "TRBJ1", "TRBJ2"),
junction_aa = c("AAAA", "BBBB", "CCCC", "DDDD"),
schema = c("v_call", "j_call", "junction_aa"),
ds <- downsample_immundata(idata, n = 5, seed = 42)
test_that("downsample_immundata keeps paired chains intact", {
v_call = c("IGHV1", "IGLV1", "IGHV2", "IGLV2", "IGHV3", "IGLV3", "IGHV1", "IGLV1", "IGHV2", "IGLV2", "IGHV3", "IGLV3"),
j_call = c("IGHJ1", "IGLJ1", "IGHJ2", "IGLJ2", "IGHJ3", "IGLJ3", "IGHJ1", "IGLJ1", "IGHJ2", "IGLJ2", "IGHJ3", "IGLJ3"),
locus = c("IGH", "IGL", "IGH", "IGL", "IGH", "IGL", "IGH", "IGL", "IGH", "IGL", "IGH", "IGL"),
context = "downsample paired-chain integrity"
ds <- downsample_immundata(idata, n = 2, seed = 7)
test_that("downsample_immundata works on IG test data with proportion n", {
n_before <- idata$repertoires |> collect() |> pull(n_barcodes)
ds <- downsample_immundata(idata, n = 0.5, seed = 123)
n_after <- ds$repertoires |> collect() |> pull(n_barcodes)
test_that("downsample_immundata with n = 1 keeps one receptor per repertoire", {
v_call = c("IGHV1", "IGHV1", "IGHV2", "IGHV3", "IGHV4", "IGHV5", "IGHV5", "IGHV6"),
j_call = c("IGHJ1", "IGHJ1", "IGHJ2", "IGHJ3", "IGHJ4", "IGHJ5", "IGHJ5", "IGHJ6"),
context = "downsample n=1 receptor mode"
ds1 <- downsample_immundata(idata, n = 1, seed = 321)
ds2 <- downsample_immundata(idata, n = 1, seed = 321)
test_that("downsample_immundata validates n and handles no-repertoire fallback", {
ds <- downsample_immundata(idata, n = 0.1, seed = 1)
test_that("downsample_immundata warns and keeps repertoire unchanged when n exceeds available units", {
v_call = c("IGHV1", "IGHV2", "IGHV3", "IGHV1", "IGHV2", "IGHV3"),
j_call = c("IGHJ1", "IGHJ2", "IGHJ3", "IGHJ1", "IGHJ2", "IGHJ3"),
schema = make_receptor_schema(features = c("v_call", "j_call", "junction_aa"), chains = "IGH"),
ds <- downsample_immundata(idata, n = 10, seed = 42),
test_that("downsample_immundata supports count-mode proportion downsampling", {
ds <- downsample_immundata(idata, n = 0.5, seed = 101)
test_that("downsample_immundata is deterministic in count mode with seed", {
context = "downsample count deterministic"
ds1 <- downsample_immundata(idata, n = 5, seed = 222)
ds2 <- downsample_immundata(idata, n = 5, seed = 222)
test_that("downsample_immundata errors when proportion results in zero target", {
downsample_immundata(idata, n = 0.0001, seed = 1),
test_that("downsample_immundata produces consistent imd_count and imd_proportion invariants", {
v_call = c("IGHV1", "IGHV1", "IGHV2", "IGHV1", "IGHV2", "IGHV2"),
j_call = c("IGHJ1", "IGHJ1", "IGHJ2", "IGHJ1", "IGHJ2", "IGHJ2"),
context = "downsample count/proportion invariants"
ds <- downsample_immundata(idata, n = 2, seed = 33)
select(imd_repertoire_id, imd_receptor_id, imd_count, imd_proportion) |>
reps <- reps |> arrange(imd_repertoire_id)
expect_true(all(abs(receptor_stats$sum_prop - 1) < 1e-8))