Skip to contents

Introduction

This vignette describes the steps to generate supercells for cytometry data using SuperCellCyto R package.

Please note that we’re still actively updating this vignette (and in fact the package itself), and that we welcome any feedbacks on how to improve them. Please reach out by creating GitHub issues on our GitHub repository.

Installation

SuperCellCyto can be installed using the remotes package from CRAN:

# install remotes package first.
install.packages("remotes")
# then use it to install SuperCellCyto
remotes::install_github("phipsonlab/SuperCellCyto")

SuperCellCyto requires the SuperCell R package installed to run properly. If you use the remotes::install_github command above to install SuperCellCyto, it should be automatically installed. But in the case it doesn’t, you can manually install it by using:

remotes::install_github("GfellerLab/SuperCell")

Preparing your dataset

The function which creates supercells is called runSuperCellCyto, and it operates on a data.table object, an enhanced version of R native data.frame.

In addition to needing the data stored in a data.table object it also requires:

  1. The markers you will be using to create supercells to have been appropriately transformed, typically using either arcsinh transformation or linear binning (using FlowJo). runSuperCellCyto does not perform any data transformation or scaling.
  2. The object to have a column denoting the unique ID of each cell. You most likely have to create this column yourself, and it can simply just be a numerical value ranging from 1 to however many cells you have in your data.
  3. The object to have a column denoting the biological sample each cell comes from. This column is critical to ensure that cells from different samples will not be mixed in a supercell.

If you are not sure how to import CSV or FCS files into data.table object, and/or how to subsequently prepare the object ready for SuperCellCyto, please consult this vignette. In that vignette, we also provide an explanation behind why we need to have the cell ID and sample column.

For this vignette, we will simulate some toy data using the simCytoData function. Specifically, we will simulate 15 markers and 3 samples, with each sample containing 10,000 cells. Hence in total, we will have a toy dataset containing 15 markers and 30,000 cells.

n_markers <- 15
n_samples <- 3
dat <- simCytoData(nmarkers = n_markers, ncells = rep(10000, n_samples))
head(dat)
#>    Marker_1  Marker_2 Marker_3  Marker_4  Marker_5 Marker_6 Marker_7 Marker_8
#>       <num>     <num>    <num>     <num>     <num>    <num>    <num>    <num>
#> 1: 19.13900 11.047502 8.109901 11.153058  7.515309 6.566224 16.72313 9.525907
#> 2: 17.63241 10.904888 8.033231 11.422321 10.098410 7.490162 17.70240 7.581921
#> 3: 16.84859 12.476788 9.450227 10.796365  9.288795 7.595264 14.72862 9.674838
#> 4: 19.70900 13.188581 8.322482 11.068842  8.102258 5.972802 17.74900 8.280305
#> 5: 17.28251  9.716123 8.648233 12.109427  9.167410 6.051073 18.92843 8.332661
#> 6: 18.56965  9.985479 8.034869  9.563705 10.236974 9.388743 18.09571 8.357653
#>    Marker_9 Marker_10 Marker_11 Marker_12 Marker_13 Marker_14 Marker_15
#>       <num>     <num>     <num>     <num>     <num>     <num>     <num>
#> 1: 7.342792  19.90619  9.409914  9.795976  16.49780  19.45645  15.61254
#> 2: 7.546813  18.32504  8.103623 10.550122  15.59001  18.73096  16.50269
#> 3: 7.351313  19.34953  9.761501 11.109906  15.10613  19.45356  17.34555
#> 4: 7.077500  19.09530  9.099912 10.094702  16.77055  18.80640  14.90563
#> 5: 7.311363  20.07808  8.225553 13.047892  17.37030  18.57122  16.65049
#> 6: 7.944067  19.88923  9.425613 11.622521  17.23069  20.58829  16.26642
#>      Sample Cell_Id
#>      <char>  <char>
#> 1: Sample_1  Cell_1
#> 2: Sample_1  Cell_2
#> 3: Sample_1  Cell_3
#> 4: Sample_1  Cell_4
#> 5: Sample_1  Cell_5
#> 6: Sample_1  Cell_6

For our toy dataset, we will transform our data using arcsinh transformation. We will use the base R asinh function to do this:

# Specify which columns are the markers to transform
marker_cols <- paste0("Marker_", seq_len(n_markers))
# The co-factor for arc-sinh
cofactor <- 5

# Do the transformation
dat_asinh <- asinh(dat[, marker_cols, with = FALSE] / cofactor)

# Rename the new columns
marker_cols_asinh <- paste0(marker_cols, "_asinh")
names(dat_asinh) <- marker_cols_asinh

# Add them our previously loaded data
dat <- cbind(dat, dat_asinh)

head(dat[, marker_cols_asinh, with = FALSE])
#>    Marker_1_asinh Marker_2_asinh Marker_3_asinh Marker_4_asinh Marker_5_asinh
#>             <num>          <num>          <num>          <num>          <num>
#> 1:       2.052079       1.533585       1.260576       1.542255       1.196460
#> 2:       1.972970       1.521761       1.252501       1.564066       1.452403
#> 3:       1.929299       1.645506       1.393353       1.512677       1.378152
#> 4:       2.080499       1.697198       1.282679       1.535343       1.259773
#> 5:       1.953701       1.417953       1.315755       1.617823       1.366586
#> 6:       2.022889       1.442336       1.252674       1.403917       1.464632
#>    Marker_6_asinh Marker_7_asinh Marker_8_asinh Marker_9_asinh Marker_10_asinh
#>             <num>          <num>          <num>          <num>           <num>
#> 1:       1.086501       1.922137       1.400409       1.177195        2.090152
#> 2:       1.193671       1.976782       1.203817       1.199945        2.010090
#> 3:       1.205286       1.801142       1.414168       1.178154        2.062667
#> 4:       1.012486       1.979312       1.278326       1.146958        2.049867
#> 5:       1.022496       2.041379       1.283726       1.173652        2.098493
#> 6:       1.387587       1.997946       1.286295       1.243040        2.089325
#>    Marker_11_asinh Marker_12_asinh Marker_13_asinh Marker_14_asinh
#>              <num>           <num>           <num>           <num>
#> 1:        1.389576        1.425237        1.909146        2.068003
#> 2:        1.259916        1.491784        1.855116        2.031243
#> 3:        1.422098        1.538719        1.825138        2.067860
#> 4:        1.360104        1.452074        1.924850        2.035127
#> 5:        1.272652        1.687176        1.958570        2.022971
#> 6:        1.391048        1.580005        1.950817        2.122861
#>    Marker_15_asinh
#>              <num>
#> 1:        1.856491
#> 2:        1.909430
#> 3:        1.957199
#> 4:        1.812461
#> 5:        1.917966
#> 6:        1.895638

We will also create a column Cell_id_dummy which uniquely identify each cell. It will have values such as Cell_1, Cell_2, all the way until Cell_x where x is the number of cells in the dataset.

dat$Cell_id_dummy <- paste0("Cell_", seq_len(nrow(dat)))
head(dat$Cell_id_dummy, n = 10)
#>  [1] "Cell_1"  "Cell_2"  "Cell_3"  "Cell_4"  "Cell_5"  "Cell_6"  "Cell_7" 
#>  [8] "Cell_8"  "Cell_9"  "Cell_10"

By default, the simCytoData function will generate cells for multiple samples, and that the resulting data.table object will already have a column called Sample that denotes the sample the cells come from.

unique(dat$Sample)
#> [1] "Sample_1" "Sample_2" "Sample_3"

Let’s take note of the sample and cell id column for later.

sample_col <- "Sample"
cell_id_col <- "Cell_id_dummy"

Creating supercells

Now that we have our data, let’s create some supercells. To do this, we will use runSuperCellCyto function and pass the markers, sample and cell ID columns as parameters.

The reason why we need to specify the markers is because the function will create supercells based on only the expression of those markers. We highly recommend creating supercells using all markers in your data, let that be cell type or cell state markers. However, if for any reason you only want to only use a subset of the markers in your data, then make sure you specify them in a vector that you later pass to runSuperCellCyto function.

For this tutorial, we will use all the arcsinh transformed markers in the toy data.

supercells <- runSuperCellCyto(
  dt = dat,
  markers = marker_cols_asinh,
  sample_colname = sample_col,
  cell_id_colname = cell_id_col
)

Let’s dig deeper into the object it created:

class(supercells)
#> [1] "list"

It is a list containing 3 elements:

names(supercells)
#> [1] "supercell_expression_matrix" "supercell_cell_map"         
#> [3] "supercell_object"

Supercell object

The supercell_object contains the metadata used to create the supercells. It is a list, and each element contains the metadata used to create the supercells for a sample. This will come in handy if we need to either regenerate the supercells using different gamma values (so we get more or less supercells) or do some debugging later down the line. More on regenerating supercells on Controlling supercells granularity section below.

Supercell expression matrix

The supercell_expression_matrix contains the marker expression of each supercell. These are calculated by taking the average of the marker expression of all the cells contained within a supercell.

head(supercells$supercell_expression_matrix)
#>    Marker_1_asinh Marker_2_asinh Marker_3_asinh Marker_4_asinh Marker_5_asinh
#>             <num>          <num>          <num>          <num>          <num>
#> 1:       1.995580       1.446792       1.380742       1.590234       1.286952
#> 2:       2.006955       1.537573       1.377923       1.529462       1.532882
#> 3:       1.991794       1.620351       1.217180       1.492824       1.453263
#> 4:       1.979074       1.559259       1.158529       1.418033       1.426586
#> 5:       1.992628       1.440836       1.290857       1.553629       1.452623
#> 6:       1.984302       1.488000       1.403710       1.428657       1.382673
#>    Marker_6_asinh Marker_7_asinh Marker_8_asinh Marker_9_asinh Marker_10_asinh
#>             <num>          <num>          <num>          <num>           <num>
#> 1:      0.9476701       1.969010       1.312378       1.243954        2.053272
#> 2:      1.2034991       1.995900       1.220712       1.304066        2.038490
#> 3:      1.1255163       1.952354       1.357215       1.148167        2.045036
#> 4:      1.0297022       1.952434       1.322155       1.247408        2.036208
#> 5:      1.1542854       1.963172       1.353693       1.174537        2.038789
#> 6:      1.1358438       1.956189       1.372573       1.250619        2.030734
#>    Marker_11_asinh Marker_12_asinh Marker_13_asinh Marker_14_asinh
#>              <num>           <num>           <num>           <num>
#> 1:        1.442502        1.521068        1.874416        2.066384
#> 2:        1.383154        1.496705        1.873889        2.096878
#> 3:        1.264188        1.565585        1.868772        2.072210
#> 4:        1.452667        1.631582        1.857569        2.066998
#> 5:        1.401937        1.442093        1.871227        2.078795
#> 6:        1.339337        1.581792        1.847169        2.063871
#>    Marker_15_asinh   Sample                 SuperCellId
#>              <num>   <char>                      <char>
#> 1:        1.908856 Sample_1 SuperCell_1_Sample_Sample_1
#> 2:        1.902518 Sample_1 SuperCell_2_Sample_Sample_1
#> 3:        1.914732 Sample_1 SuperCell_3_Sample_Sample_1
#> 4:        1.911618 Sample_1 SuperCell_4_Sample_Sample_1
#> 5:        1.918450 Sample_1 SuperCell_5_Sample_Sample_1
#> 6:        1.900979 Sample_1 SuperCell_6_Sample_Sample_1

Therein, we will have the following columns:

  1. All the markers we previously specified in the markers_col variable. In this example, they are the arcsinh transformed markers in our toy data.
  2. A column (Sample in this case) denoting which sample a supercell belongs to, (note the column name is the same as what is stored in sample_col variable).
  3. The SuperCellId column denoting the unique ID of the supercell.

SuperCellId

Let’s have a look at SuperCellId:

head(unique(supercells$supercell_expression_matrix$SuperCellId))
#> [1] "SuperCell_1_Sample_Sample_1" "SuperCell_2_Sample_Sample_1"
#> [3] "SuperCell_3_Sample_Sample_1" "SuperCell_4_Sample_Sample_1"
#> [5] "SuperCell_5_Sample_Sample_1" "SuperCell_6_Sample_Sample_1"

Let’s break down one of them, SuperCell_1_Sample_Sample_1. SuperCell_1 is a numbering (1 to however many supercells there are in a sample) used to uniquely identify each supercell in a sample. Notably, you may encounter this (SuperCell_1, SuperCell_2) being repeated across different samples, e.g.,

supercell_ids <- unique(supercells$supercell_expression_matrix$SuperCellId)
supercell_ids[grep("SuperCell_1_", supercell_ids)]
#> [1] "SuperCell_1_Sample_Sample_1" "SuperCell_1_Sample_Sample_2"
#> [3] "SuperCell_1_Sample_Sample_3"

While these 3 supercells’ id are pre-fixed with SuperCell_1, it does not make them equal to one another! SuperCell_1_Sample_Sample_1 will only contain cells from Sample_1 while SuperCell_1_Sample_Sample_2 will only contain cells from Sample_2.

By now, you may have noticed that we appended the sample name into each supercell id. This aids in differentiating the supercells in different samples.

Supercell cell map

supercell_cell_map maps each cell in our dataset to the supercell it belongs to.

head(supercells$supercell_cell_map)
#>                      SuperCellID CellId   Sample
#>                           <char> <char>   <char>
#> 1:  SuperCell_55_Sample_Sample_1 Cell_1 Sample_1
#> 2:  SuperCell_70_Sample_Sample_1 Cell_2 Sample_1
#> 3:  SuperCell_26_Sample_Sample_1 Cell_3 Sample_1
#> 4: SuperCell_461_Sample_Sample_1 Cell_4 Sample_1
#> 5: SuperCell_333_Sample_Sample_1 Cell_5 Sample_1
#> 6: SuperCell_394_Sample_Sample_1 Cell_6 Sample_1

This map is very useful if we later need to expand the supercells out. Additionally, this is also the reason why we need to have a column in the dataset which uniquely identify each cell.

Running runSuperCellCyto in parallel

By default, runSuperCellCyto will process each sample one after the other. As each sample is processed independent of one another, strictly speaking, we can process all of them in parallel.

To do this, we need to:

  1. Create a BiocParallelParam object from the BiocParallel package. This object can either be of type MulticoreParamor SnowParam. We highly recommend consulting their vignette for more information.
  2. Set the number of tasks for the BiocParallelParam object to the number of samples we have in the dataset.
  3. Set the load_balancing parameter for runSuperCellCyto function to TRUE. This is to ensure even distribution of the supercell creation jobs. As each sample will be processed by a parallel job, we don’t want a job that process large sample to also be assigned other smaller samples if possible. If you want to know more how this feature works, please refer to our manuscript.

NOTE: we should not set the value for workers param for BiocParallelParam object more than the total number of cores we have in the computer, as it will render the computer useless for anything else. Perhaps more importantly, it might blow out your RAM and kill the Rsession. To find out the total number of cores we have in the computer, we can use parallel’s detectCores function.

n_cores <- detectCores()

And supply that number minus one as the workers param for BiocParallelParam object.

supercell_par <- runSuperCellCyto(
  dt = dat,
  markers = marker_cols_asinh,
  sample_colname = sample_col,
  cell_id_colname = cell_id_col,
  BPPARAM = MulticoreParam(
    workers = n_cores - 1,
    tasks = n_samples
  ),
  load_balancing = TRUE
)

Controlling supercells granularity

This is described in the runSuperCellCyto function’s documentation, but let’s briefly go through it here.

The runSuperCellCyto function is equipped with various parameters which can be customised to alter the composition of the supercells. The one that is very likely to be used the most is the gamma parameter, denoted as gam in the function. By default, the value for gam is set to 20, which we found work well for most cases.

The gamma parameter controls how many supercells to generate, and indirectly, how many cells are captured within each supercell. This parameter is resolved into the following formula gamma=n_cells/n_supercells where n_cell denotes the number of cells and n_supercells denotes the number of supercells.

In general, the larger gamma parameter is set to, the less supercells we will get. Say for instance we have 10,000 cells. If gamma is set to 10, we will end up with about 1,000 supercells, whereas if gamma is set to 50, we will end up with about 200 supercells.

You may have noticed, after reading the sections above, runSuperCellCyto is ran on each sample independent of each other, and that we can only set 1 value as the gamma parameter. Indeed, for now, the same gamma value will be used across all samples, and that depending on how many cells we have in each sample, we will end up with different number of supercells for each sample. For instance, say we have 10,000 cells for sample 1, and 100,000 cells for sample 2. If gamma is set to 10, for sample 1, we will get 1,000 supercells (10,000/10) while for sample 2, we will get 10,000 supercells (100,000/10).

Do note: whatever gamma value you chose, you should not expect each supercell to contain exactly the same number of cells. This behaviour is intentional to ensure rare cell types are not intermixed with non-rare cell types in a supercell.

Adjusting gamma value after one run of runSuperCellCyto

If you have run runSuperCellCyto once and have not discarded the SuperCell object it generated (no serious, please don’t!), you can use the object to quickly regenerate supercells using different gamma values.

As an example, using the SuperCell object we have generated for our toy dataset, we will regenerate the supercells using gamma of 10 and 50. The function to do this is recomputeSupercells. We will store the output in a list, one element per gamma value.

addt_gamma_vals <- c(10, 50)
supercells_addt_gamma <- lapply(addt_gamma_vals, function(gam) {
  recomputeSupercells(
    dt = dat,
    sc_objects = supercells$supercell_object,
    markers = marker_cols_asinh,
    sample_colname = sample_col,
    cell_id_colname = cell_id_col,
    gam = gam
  )
})

We should end up with a list containing 2 elements. The 1st element contains supercells generated using gamma = 10, and the 2nd contains supercells generated using gamma = 50.

supercells_addt_gamma[[1]]
#> $supercell_expression_matrix
#>       Marker_1_asinh Marker_2_asinh Marker_3_asinh Marker_4_asinh
#>                <num>          <num>          <num>          <num>
#>    1:       1.958112       1.477273       1.297276       1.582879
#>    2:       2.008231       1.488350       1.338411       1.602096
#>    3:       1.954654       1.452796       1.355253       1.497807
#>    4:       1.995565       1.441787       1.276807       1.403566
#>    5:       1.996515       1.495359       1.395112       1.457134
#>   ---                                                            
#> 2996:       1.938159       2.064955       1.535426       1.459380
#> 2997:       1.841834       2.044869       1.409913       1.546795
#> 2998:       1.895279       2.036483       1.400521       1.573768
#> 2999:       1.836585       2.063497       1.410812       1.576254
#> 3000:       1.832374       2.009185       1.477971       1.308368
#>       Marker_5_asinh Marker_6_asinh Marker_7_asinh Marker_8_asinh
#>                <num>          <num>          <num>          <num>
#>    1:       1.348905       1.109222       1.948428       1.212506
#>    2:       1.334919       1.126663       1.989638       1.420950
#>    3:       1.484985       1.089729       1.955906       1.298183
#>    4:       1.309531       1.025688       1.982881       1.396544
#>    5:       1.453476       1.155280       1.964886       1.371970
#>   ---                                                            
#> 2996:       1.810249       1.968773       1.196484       1.944173
#> 2997:       1.744334       1.902767       1.232638       1.884777
#> 2998:       1.662860       1.961998       1.245643       1.922657
#> 2999:       1.856069       1.878786       1.158055       1.862382
#> 3000:       1.738504       1.916038       1.000549       1.917864
#>       Marker_9_asinh Marker_10_asinh Marker_11_asinh Marker_12_asinh
#>                <num>           <num>           <num>           <num>
#>    1:       1.250576        2.033670        1.470982        1.616641
#>    2:       1.161198        2.029708        1.546475        1.542272
#>    3:       1.200253        2.055154        1.225996        1.620548
#>    4:       1.369452        2.046426        1.455330        1.545621
#>    5:       1.209573        2.054810        1.275787        1.544609
#>   ---                                                               
#> 2996:       2.081667        1.772929        1.476120        1.413936
#> 2997:       2.045146        1.634307        1.438281        1.608858
#> 2998:       2.058678        1.671930        1.350550        1.294358
#> 2999:       2.049559        1.646453        1.521212        1.317214
#> 3000:       2.062408        1.820415        1.508987        1.343004
#>       Marker_13_asinh Marker_14_asinh Marker_15_asinh   Sample
#>                 <num>           <num>           <num>   <char>
#>    1:        1.834889        2.043665        1.882948 Sample_1
#>    2:        1.868541        2.057596        1.943500 Sample_1
#>    3:        1.863654        2.037806        1.873391 Sample_1
#>    4:        1.881848        2.073825        1.904210 Sample_1
#>    5:        1.865784        2.069718        1.945993 Sample_1
#>   ---                                                         
#> 2996:        1.787596        1.949946        1.348721 Sample_3
#> 2997:        1.782119        1.912794        1.411217 Sample_3
#> 2998:        1.805910        1.952616        1.338124 Sample_3
#> 2999:        1.846411        1.873828        1.451726 Sample_3
#> 3000:        1.790610        1.882655        1.392312 Sample_3
#>                          SuperCellId
#>                               <char>
#>    1:    SuperCell_1_Sample_Sample_1
#>    2:    SuperCell_2_Sample_Sample_1
#>    3:    SuperCell_3_Sample_Sample_1
#>    4:    SuperCell_4_Sample_Sample_1
#>    5:    SuperCell_5_Sample_Sample_1
#>   ---                               
#> 2996:  SuperCell_996_Sample_Sample_3
#> 2997:  SuperCell_997_Sample_Sample_3
#> 2998:  SuperCell_998_Sample_Sample_3
#> 2999:  SuperCell_999_Sample_Sample_3
#> 3000: SuperCell_1000_Sample_Sample_3
#> 
#> $supercell_cell_map
#>                          SuperCellID     CellId   Sample
#>                               <char>     <char>   <char>
#>     1: SuperCell_153_Sample_Sample_1     Cell_1 Sample_1
#>     2: SuperCell_290_Sample_Sample_1     Cell_2 Sample_1
#>     3:  SuperCell_48_Sample_Sample_1     Cell_3 Sample_1
#>     4: SuperCell_830_Sample_Sample_1     Cell_4 Sample_1
#>     5: SuperCell_187_Sample_Sample_1     Cell_5 Sample_1
#>    ---                                                  
#> 29996: SuperCell_626_Sample_Sample_3 Cell_29996 Sample_3
#> 29997:  SuperCell_17_Sample_Sample_3 Cell_29997 Sample_3
#> 29998: SuperCell_119_Sample_Sample_3 Cell_29998 Sample_3
#> 29999:  SuperCell_41_Sample_Sample_3 Cell_29999 Sample_3
#> 30000: SuperCell_733_Sample_Sample_3 Cell_30000 Sample_3

The output generated by recomputeSupercells is essentially a list:

  1. supercell_expression_matrix: A data.table object that contains the marker expression for each supercell.
  2. supercell_cell_map: A data.table that maps each cell to its corresponding supercell.

As mentioned before, gamma dictates the granularity of supercells. Compared to the previous run where gamma was set to 20, we should get more supercells for gamma = 10, and less for gamma = 50. Let’s see if that’s the case.

n_supercells_gamma20 <- nrow(supercells$supercell_expression_matrix)
n_supercells_gamma10 <- nrow(supercells_addt_gamma[[1]]$supercell_expression_matrix)
n_supercells_gamma50 <- nrow(supercells_addt_gamma[[2]]$supercell_expression_matrix)
n_supercells_gamma10 > n_supercells_gamma20
#> [1] TRUE
n_supercells_gamma50 < n_supercells_gamma20
#> [1] TRUE

Specifying different gamma value for different samples

In the future, we may add the ability to specify different gam value for different samples. For now, if we want to do this, we will need to break down our data into multiple data.table objects, each containing data from 1 sample, and run runSuperCellCyto function on each of them with different gam parameter value. Something like the following:

n_markers <- 10
dat <- simCytoData(nmarkers = n_markers)
markers_col <- paste0("Marker_", seq_len(n_markers))
sample_col <- "Sample"
cell_id_col <- "Cell_Id"

samples <- unique(dat[[sample_col]])
gam_values <- c(10, 20, 10)

supercells_diff_gam <- lapply(seq_len(length(samples)), function(i) {
  sample <- samples[i]
  gam <- gam_values[i]
  dat_samp <- dat[dat$Sample == sample, ]
  supercell_samp <- runSuperCellCyto(
    dt = dat_samp,
    markers = markers_col,
    sample_colname = sample_col,
    cell_id_colname = cell_id_col,
    gam = gam
  )
  return(supercell_samp)
})

Subsequently, to extract and combine the supercell_expression_matrix and supercell_cell_map, we will need to use rbind:

supercell_expression_matrix <- do.call(
  "rbind", lapply(supercells_diff_gam, function(x) x[["supercell_expression_matrix"]])
)

supercell_cell_map <- do.call(
  "rbind", lapply(supercells_diff_gam, function(x) x[["supercell_cell_map"]])
)
rbind(head(supercell_expression_matrix, n = 3), tail(supercell_expression_matrix, n = 3))
#>    Marker_1  Marker_2  Marker_3 Marker_4 Marker_5  Marker_6  Marker_7  Marker_8
#>       <num>     <num>     <num>    <num>    <num>     <num>     <num>     <num>
#> 1:  9.51318 12.252145 19.105503 7.926682 15.33604  9.818517  5.484070  6.576358
#> 2:  9.04860 11.730022 19.006534 8.462920 17.20797 10.419792  7.338242  7.599751
#> 3:  8.77909 11.275179 19.918548 9.551486 16.35073 10.181823  7.044308  6.612135
#> 4: 16.56364  9.450688 11.754240 7.899247 16.82852 10.801556 18.600204 13.093094
#> 5: 12.50071  8.944497  9.637807 7.893013 16.91533 10.637318 19.670438 12.579984
#> 6: 12.52757 10.614893 12.388143 8.357340 17.81311 10.136396 16.493129 13.589231
#>    Marker_9 Marker_10   Sample                   SuperCellId
#>       <num>     <num>   <char>                        <char>
#> 1: 13.05270  7.510377 Sample_1   SuperCell_1_Sample_Sample_1
#> 2: 12.80418  6.351818 Sample_1   SuperCell_2_Sample_Sample_1
#> 3: 11.79897  6.531425 Sample_1   SuperCell_3_Sample_Sample_1
#> 4: 14.21919  8.947948 Sample_2 SuperCell_498_Sample_Sample_2
#> 5: 15.79227 10.261859 Sample_2 SuperCell_499_Sample_Sample_2
#> 6: 14.77029 10.253662 Sample_2 SuperCell_500_Sample_Sample_2
rbind(head(supercell_cell_map, n = 3), tail(supercell_cell_map, n = 3))
#>                      SuperCellID     CellId   Sample
#>                           <char>     <char>   <char>
#> 1: SuperCell_355_Sample_Sample_1     Cell_1 Sample_1
#> 2: SuperCell_174_Sample_Sample_1     Cell_2 Sample_1
#> 3: SuperCell_767_Sample_Sample_1     Cell_3 Sample_1
#> 4:  SuperCell_98_Sample_Sample_2 Cell_19998 Sample_2
#> 5: SuperCell_323_Sample_Sample_2 Cell_19999 Sample_2
#> 6: SuperCell_177_Sample_Sample_2 Cell_20000 Sample_2

Mixing cells from different samples in a supercell

If for whatever reason you don’t mind (or perhaps more to the point want) each supercell to contain cells from different biological samples, you still need to have the sample column in your data.table. However, what you need to do is essentially set the value in the column to exactly one unique value. That way, SuperCellCyto will treat all cells as coming from one sample.

Just note, the parallel processing feature in SuperCellCyto won’t work for this as you will essentially only have 1 sample and nothing for SuperCellCyto to parallelise.

I have more cells than RAM in my computer

Is your dataset so huge that you are constantly running out of RAM when generating supercells? This thing happens and we have a solution for it.

Since supercells are generated for each sample independent of others you can easily break up the process. For example:

  1. Load up a subset of the samples (say 1-10).
  2. Generate supercells for those samples.
  3. Save the output using the qs package.
  4. Extract the supercell_expression_matrix and supercell_cell_map, and export them out as a csv file using data.table’s fwrite function.
  5. Load another sets of samples (say 11-20), rinse and repeat step 2-4.

Once you have processed all the samples, you can then load all supercell_expression_matrix and supercell_cell_map csv files and analyse them.

If you want to regenerate the supercells using different gamma values, load the relevant output saved using the qs package and the relevant data (remember to note which output belongs to which sets of samples!), and run recomputeSupercells function.

Session information

sessionInfo()
#> R version 4.3.3 (2024-02-29)
#> Platform: x86_64-pc-linux-gnu (64-bit)
#> Running under: Ubuntu 22.04.4 LTS
#> 
#> Matrix products: default
#> BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so;  LAPACK version 3.10.0
#> 
#> locale:
#>  [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
#>  [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
#>  [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
#> [10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   
#> 
#> time zone: UTC
#> tzcode source: system (glibc)
#> 
#> attached base packages:
#> [1] parallel  stats     graphics  grDevices utils     datasets  methods  
#> [8] base     
#> 
#> other attached packages:
#> [1] BiocParallel_1.36.0 SuperCellCyto_0.1.0
#> 
#> loaded via a namespace (and not attached):
#>  [1] Matrix_1.6-5      jsonlite_1.8.8    compiler_4.3.3    Rcpp_1.0.12      
#>  [5] SuperCell_1.0     jquerylib_0.1.4   systemfonts_1.0.6 textshaping_0.3.7
#>  [9] yaml_2.3.8        fastmap_1.1.1     lattice_0.22-5    R6_2.5.1         
#> [13] plyr_1.8.9        igraph_2.0.3      knitr_1.46        desc_1.4.3       
#> [17] bslib_0.7.0       rlang_1.1.3       cachem_1.0.8      RANN_2.6.1       
#> [21] xfun_0.43         fs_1.6.3          sass_0.4.9        memoise_2.0.1    
#> [25] cli_3.6.2         pkgdown_2.0.7     magrittr_2.0.3    digest_0.6.35    
#> [29] grid_4.3.3        lifecycle_1.0.4   vctrs_0.6.5       evaluate_0.23    
#> [33] glue_1.7.0        data.table_1.15.4 codetools_0.2-19  ragg_1.3.0       
#> [37] rmarkdown_2.26    purrr_1.0.2       tools_4.3.3       pkgconfig_2.0.3  
#> [41] htmltools_0.5.8.1