
Simulate pseudo-bulk or spatial transcriptomics profiles from single-cell data
Source:R/quasar_sim_bulk.R
quasar_sim_bulk.RdGenerates pseudo-bulk expression profiles by sampling cells from a
single-cell reference according to Dirichlet-drawn cell-type fractions.
With mode = "spatial" the same machinery produces spot-level profiles
instead, pooling only a handful of cells per spot and restricting each spot to
a small number of cell types.
Optionally returns per-cell-type signature profiles and a global signature matrix.
Usage
quasar_sim_bulk(
...,
n_bulk_samples = NULL,
cells_per_bulk = 500,
mode = c("bulk", "spatial"),
cells_per_spot_range = c(5L, 11L),
celltypes_per_spot_range = c(1L, 5L),
spatial_background = 1e-06,
cell_type_column = "cell_type",
patient_id_column = NULL,
select_ct = NULL,
dirich_alpha = 1,
seet = 1,
sparse = FALSE,
sparse_prob = 0.5,
rare = FALSE,
rare_percentage = 0.4,
return_used_samples = FALSE,
return_patient_metadata = FALSE,
return_signature_matrix = FALSE,
verbose = TRUE
)Arguments
- ...
The single-cell reference, supplied in one of two forms:
A single object: a
Seuratobject (counts taken from the"RNA"assay) or aSingleCellExperiment(counts taken fromcounts()).Two objects: a genes \(\times\) cells count matrix followed by a cell-metadata
data.framewhose row names match the column names of the count matrix.
- n_bulk_samples
Integer number of pseudo-bulk samples to generate. If
NULL(default),1000 * (number of cell types)samples are generated.- cells_per_bulk
Integer number of cells pooled into each pseudo-bulk sample. Default
500. Ignored whenmode = "spatial", where the pool size is drawn per spot fromcells_per_spot_range.- mode
Character scalar selecting the simulation type.
"bulk"(default) poolscells_per_bulkcells per sample from a symmetric Dirichlet over all cell types."spatial"emulates spot-level transcriptomics: each spot keeps only a few cell types and pools a small, randomly drawn number of cells.- cells_per_spot_range
Integer vector of length two giving the inclusive range from which the number of cells per spot is drawn uniformly when
mode = "spatial". Defaultc(5, 11).- celltypes_per_spot_range
Integer vector of length two giving the inclusive range from which the number of cell types present in a spot is drawn uniformly when
mode = "spatial". Defaultc(1, 5), capped at the number of available cell types.- spatial_background
Numeric scalar giving the Dirichlet concentration assigned to cell types that are not selected for a spot when
mode = "spatial". A small positive value leaves trace amounts rather than exact zeros, which is what the reference implementation does. Default1e-6.- cell_type_column
Name of the metadata column holding cell-type labels. Default
"cell_type".- patient_id_column
Optional name of a metadata column holding patient/donor IDs. When supplied, each pseudo-bulk is drawn from a single donor where that donor has cells of the required type (falling back to the full cell-type pool otherwise). Default
NULL(no patient structure).- select_ct
Optional character vector restricting which cell types are used (and fixing their order in the output). Default
NULL(all cell types).- dirich_alpha
Concentration parameter of the symmetric Dirichlet used to draw cell-type fractions. Smaller values give more skewed mixtures. Default
1(uniform over the simplex).- seet
Integer random seed (passed to
set.seed) for reproducibility. Default1.- sparse
Logical; if
TRUE, randomly zero out a fraction of cell-type entries before renormalisation, producing samples in which some cell types are absent. DefaultFALSE.- sparse_prob
Probability that a given cell-type fraction is dropped when
sparse = TRUE. Default0.5.- rare
Logical; if
TRUE, force a random subset of cell-type fractions to small values in[0, 0.03]before renormalisation, to emulate rare populations. DefaultFALSE.- rare_percentage
Probability that a given cell-type fraction is made rare when
rare = TRUE. Default0.4.- return_used_samples
Logical; if
TRUE, include the per-sample, per-cell-type cell indices that were drawn. DefaultFALSE.- return_patient_metadata
Logical; if
TRUEandpatient_id_columnis set, include a data frame mapping each pseudo-bulk to its source donor. DefaultFALSE.- return_signature_matrix
Logical; if
TRUE, also compute per-cell-type signature profiles (one genes \(\times\) bulk matrix per cell type) and a global genes \(\times\) cell-types signature matrix. DefaultFALSE.- verbose
Logical; if
TRUE(default), print the header, progress bars, and timing summary. IfFALSE, nothing is printed.
Value
A named list containing:
bulk_expression_profilesGenes \(\times\)
n_bulk_samplesmatrix of summed pseudo-bulk counts.ground_truth_proportionsn_bulk_samples\(\times\) cell-types matrix of realized proportions (rows sum to 1).cells_per_sampleInteger vector giving the realized number of cells pooled into each sample. Constant in bulk mode, variable in spatial mode.
used_samples_by_ct(if
return_used_samples) list of lengthn_bulk_samples, each a per-cell-type list of drawn cell indices.bulk_patient_metadata(if
return_patient_metadataand patient mode) data frame mappingsample_idtopatient_id.bulk_signature_profiles(if
return_signature_matrix) list of per-cell-type genes \(\times\) bulk mean-expression matrices.global_signature_matrix(if
return_signature_matrix) genes \(\times\) cell-types matrix of mean signatures.timinglist with
pseudobulk_seconds,signature_seconds, andtotal_seconds.
Details
In mode = "bulk", cell-type fractions are drawn from a symmetric
Dirichlet, optionally modified by the sparse/rare masks,
renormalised per sample, and turned into integer cell counts by
floor(fraction * cells_per_bulk) (each bulk is guaranteed at least one
cell).
In mode = "spatial", each spot first draws how many cell types it
contains, then a Dirichlet whose concentration is dirich_alpha for the
selected types and spatial_background for the rest. The number of
cells in the spot is drawn uniformly from cells_per_spot_range and
allocated by round(fraction * n_cells) rather than floor,
because flooring a handful of cells would empty most spots. The
sparse and rare arguments are ignored in this mode, since
sparsity is already imposed by the per-spot cell-type selection.
In both modes cells are then sampled with replacement from the reference and
summed, so the returned ground_truth_proportions reflect the
*realized* allocations rather than the raw Dirichlet draws.
Examples
## Tiny synthetic reference: 1000 genes, 3 cell types, 100 cells each
set.seed(1)
n_genes <- 1000
cell_types <- c("Tcell", "Bcell", "Mono")
cells_per_type <- 100
n_cells <- length(cell_types) * cells_per_type
counts <- matrix(
rpois(n_genes * n_cells, lambda = 5),
nrow = n_genes, ncol = n_cells
)
rownames(counts) <- paste0("gene_", seq_len(n_genes))
colnames(counts) <- paste0("cell_", seq_len(n_cells))
meta <- data.frame(
cell_type = rep(cell_types, each = cells_per_type),
row.names = colnames(counts)
)
## Generate 50 pseudo-bulks of 100 cells each, with signatures
res <- quasar_sim_bulk(
counts, meta,
n_bulk_samples = 50,
cells_per_bulk = 100,
return_signature_matrix = TRUE,
verbose = TRUE
)
#> -------------------------------
#> Generating pseudo-bulks
#> -------------------------------
#> Creating pseudo-bulks
#> [ ] 0.00%
#> Samples : 0 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█ ] 2.00%
#> Samples : 1 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█ ] 4.00%
#> Samples : 2 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██ ] 6.00%
#> Samples : 3 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██ ] 8.00%
#> Samples : 4 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███ ] 10.00%
#> Samples : 5 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████ ] 12.00%
#> Samples : 6 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████ ] 14.00%
#> Samples : 7 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████ ] 16.00%
#> Samples : 8 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████ ] 18.00%
#> Samples : 9 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████ ] 20.00%
#> Samples : 10 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████ ] 22.00%
#> Samples : 11 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████ ] 24.00%
#> Samples : 12 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████ ] 26.00%
#> Samples : 13 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████ ] 28.00%
#> Samples : 14 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████ ] 30.00%
#> Samples : 15 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████ ] 32.00%
#> Samples : 16 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████ ] 34.00%
#> Samples : 17 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████████ ] 36.00%
#> Samples : 18 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████████ ] 38.00%
#> Samples : 19 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████████ ] 40.00%
#> Samples : 20 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████████ ] 42.00%
#> Samples : 21 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████████ ] 44.00%
#> Samples : 22 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████████ ] 46.00%
#> Samples : 23 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████████ ] 48.00%
#> Samples : 24 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████████████ ] 50.00%
#> Samples : 25 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████████████ ] 52.00%
#> Samples : 26 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████████████ ] 54.00%
#> Samples : 27 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████████████ ] 56.00%
#> Samples : 28 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████████████ ] 58.00%
#> Samples : 29 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████████████ ] 60.00%
#> Samples : 30 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████████████████ ] 62.00%
#> Samples : 31 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████████████████ ] 64.00%
#> Samples : 32 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████████████████ ] 66.00%
#> Samples : 33 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████████████████ ] 68.00%
#> Samples : 34 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████████████████ ] 70.00%
#> Samples : 35 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████████████████ ] 72.00%
#> Samples : 36 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████████████████ ] 74.00%
#> Samples : 37 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████████████████████ ] 76.00%
#> Samples : 38 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████████████████████ ] 78.00%
#> Samples : 39 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████████████████████ ] 80.00%
#> Samples : 40 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████████████████████ ] 82.00%
#> Samples : 41 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████████████████████ ] 84.00%
#> Samples : 42 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████████████████████ ] 86.00%
#> Samples : 43 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████████████████████ ] 88.00%
#> Samples : 44 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [███████████████████████████ ] 90.00%
#> Samples : 45 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████████████████████████ ] 92.00%
#> Samples : 46 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [████████████████████████████ ] 94.00%
#> Samples : 47 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████████████████████████ ] 96.00%
#> Samples : 48 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [█████████████████████████████ ] 98.00%
#> Samples : 49 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating pseudo-bulks
#> [██████████████████████████████] 100.00%
#> Samples : 50 / 50
#> Elapsed : 00:00
#> ETA : 00:00
#> Building signature matrices
#> [ ] 0.00%
#> Steps : 0 / 6
#> Elapsed : 00:00
#> ETA : 00:00
#>
Building signature matrices
#> [█████ ] 16.67%
#> Steps : 1 / 6
#> Elapsed : 00:00
#> ETA : 00:00
#>
Building signature matrices
#> [██████████ ] 33.33%
#> Steps : 2 / 6
#> Elapsed : 00:00
#> ETA : 00:00
#>
Building signature matrices
#> [███████████████ ] 50.00%
#> Steps : 3 / 6
#> Elapsed : 00:00
#> ETA : 00:00
#>
Building signature matrices
#> [████████████████████ ] 66.67%
#> Steps : 4 / 6
#> Elapsed : 00:00
#> ETA : 00:00
#>
Building signature matrices
#> [█████████████████████████ ] 83.33%
#> Steps : 5 / 6
#> Elapsed : 00:00
#> ETA : 00:00
#>
Building signature matrices
#> [██████████████████████████████] 100.00%
#> Steps : 6 / 6
#> Elapsed : 00:00
#> ETA : 00:00
#> Generated 50 pseudobulks (100 cells each) from 1000 genes
#> Pseudobulk creation time: 0.13 secs
#> Computed bulk_signature_profiles (list of genes×bulk matrices per cell type)
#> Signature matrix time: 0.01 secs
#> Returned global_signature_matrix (genes × celltypes)
#> Total quasar_sim_bulk time: 0.14 secs
#>
dim(res$bulk_expression_profiles) # 1000 x 50
#> [1] 1000 50
head(res$ground_truth_proportions) # rows sum to 1
#> Tcell Bcell Mono
#> sample_1 0.04081633 0.4897959 0.46938776
#> sample_2 0.25252525 0.3838384 0.36363636
#> sample_3 0.71717172 0.2222222 0.06060606
#> sample_4 0.16161616 0.3333333 0.50505051
#> sample_5 0.02040816 0.5408163 0.43877551
#> sample_6 0.43877551 0.3877551 0.17346939
dim(res$global_signature_matrix) # 1000 x 3
#> [1] 1000 3
## Spatial spots: few cells and few cell types per spot
spots <- quasar_sim_bulk(
counts, meta,
n_bulk_samples = 200,
mode = "spatial",
verbose = TRUE
)
#> -------------------------------
#> Generating spatial spots
#> -------------------------------
#> Creating spatial spots
#> [ ] 0.00%
#> Spots : 0 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [ ] 1.00%
#> Spots : 2 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█ ] 2.00%
#> Spots : 4 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█ ] 3.00%
#> Spots : 6 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█ ] 4.00%
#> Spots : 8 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██ ] 5.00%
#> Spots : 10 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██ ] 6.00%
#> Spots : 12 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██ ] 7.00%
#> Spots : 14 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██ ] 8.00%
#> Spots : 16 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███ ] 9.00%
#> Spots : 18 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███ ] 10.00%
#> Spots : 20 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███ ] 11.00%
#> Spots : 22 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████ ] 12.00%
#> Spots : 24 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████ ] 13.00%
#> Spots : 26 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████ ] 14.00%
#> Spots : 28 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████ ] 15.00%
#> Spots : 30 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████ ] 16.00%
#> Spots : 32 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████ ] 17.00%
#> Spots : 34 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████ ] 18.00%
#> Spots : 36 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████ ] 19.00%
#> Spots : 38 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████ ] 20.00%
#> Spots : 40 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████ ] 21.00%
#> Spots : 42 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████ ] 22.00%
#> Spots : 44 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████ ] 23.00%
#> Spots : 46 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████ ] 24.00%
#> Spots : 48 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████ ] 25.00%
#> Spots : 50 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████ ] 26.00%
#> Spots : 52 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████ ] 27.00%
#> Spots : 54 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████ ] 28.00%
#> Spots : 56 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████ ] 29.00%
#> Spots : 58 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████ ] 30.00%
#> Spots : 60 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████ ] 31.00%
#> Spots : 62 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████ ] 32.00%
#> Spots : 64 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████ ] 33.00%
#> Spots : 66 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████ ] 34.00%
#> Spots : 68 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████ ] 35.00%
#> Spots : 70 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████ ] 36.00%
#> Spots : 72 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████ ] 37.00%
#> Spots : 74 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████ ] 38.00%
#> Spots : 76 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████ ] 39.00%
#> Spots : 78 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████ ] 40.00%
#> Spots : 80 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████ ] 41.00%
#> Spots : 82 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████ ] 42.00%
#> Spots : 84 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████ ] 43.00%
#> Spots : 86 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████ ] 44.00%
#> Spots : 88 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████ ] 45.00%
#> Spots : 90 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████ ] 46.00%
#> Spots : 92 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████ ] 47.00%
#> Spots : 94 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████ ] 48.00%
#> Spots : 96 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████ ] 49.00%
#> Spots : 98 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████ ] 50.00%
#> Spots : 100 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████ ] 51.00%
#> Spots : 102 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████ ] 52.00%
#> Spots : 104 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████ ] 53.00%
#> Spots : 106 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████ ] 54.00%
#> Spots : 108 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████ ] 55.00%
#> Spots : 110 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████ ] 56.00%
#> Spots : 112 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████ ] 57.00%
#> Spots : 114 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████ ] 58.00%
#> Spots : 116 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████ ] 59.00%
#> Spots : 118 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████ ] 60.00%
#> Spots : 120 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████ ] 61.00%
#> Spots : 122 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████████ ] 62.00%
#> Spots : 124 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████████ ] 63.00%
#> Spots : 126 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████████ ] 64.00%
#> Spots : 128 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████ ] 65.00%
#> Spots : 130 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████ ] 66.00%
#> Spots : 132 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████ ] 67.00%
#> Spots : 134 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████ ] 68.00%
#> Spots : 136 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████████ ] 69.00%
#> Spots : 138 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████████ ] 70.00%
#> Spots : 140 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████████ ] 71.00%
#> Spots : 142 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████ ] 72.00%
#> Spots : 144 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████ ] 73.00%
#> Spots : 146 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████ ] 74.00%
#> Spots : 148 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████ ] 75.00%
#> Spots : 150 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████████████ ] 76.00%
#> Spots : 152 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████████████ ] 77.00%
#> Spots : 154 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████████████ ] 78.00%
#> Spots : 156 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████████ ] 79.00%
#> Spots : 158 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████████ ] 80.00%
#> Spots : 160 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████████ ] 81.00%
#> Spots : 162 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████████████ ] 82.00%
#> Spots : 164 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████████████ ] 83.00%
#> Spots : 166 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████████████ ] 84.00%
#> Spots : 168 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████████ ] 85.00%
#> Spots : 170 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████████ ] 86.00%
#> Spots : 172 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████████ ] 87.00%
#> Spots : 174 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████████ ] 88.00%
#> Spots : 176 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████████████████ ] 89.00%
#> Spots : 178 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████████████████ ] 90.00%
#> Spots : 180 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [███████████████████████████ ] 91.00%
#> Spots : 182 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████████████ ] 92.00%
#> Spots : 184 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████████████ ] 93.00%
#> Spots : 186 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████████████ ] 94.00%
#> Spots : 188 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [████████████████████████████ ] 95.00%
#> Spots : 190 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████████████████ ] 96.00%
#> Spots : 192 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████████████████ ] 97.00%
#> Spots : 194 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [█████████████████████████████ ] 98.00%
#> Spots : 196 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████████████] 99.00%
#> Spots : 198 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#>
Creating spatial spots
#> [██████████████████████████████] 100.00%
#> Spots : 200 / 200
#> Elapsed : 00:00
#> ETA : 00:00
#> Generated 200 spatial spots (4-12 cells each, median 8) from 1000 genes
#> Median cell types per spot: 2
#> Spot creation time: 0.25 secs
#> Total quasar_sim_bulk time: 0.25 secs
#>
dim(spots$bulk_expression_profiles) # 1000 x 200
#> [1] 1000 200
range(spots$cells_per_sample) # within cells_per_spot_range
#> [1] 4 12
table(rowSums(spots$ground_truth_proportions > 0))
#>
#> 1 2 3
#> 74 85 41