1 Introduction

The goal of single-cell transcriptomics is to measure the transcriptional states of large numbers of cells simultaneously. The input to a single-cell RNA sequencing (scRNAseq) method is a collection of cells. Formally, the desired output is a transcript or genes (\(M\)) x cells (\(N\)) matrix \(X^{N \times M}\) that describes, for each cell, the abundance of its constituent transcripts or genes. More generally, single-cell genomics methods seek to measure not just transcriptional state, but other modalities in cells, e.g., protein abundances, epigenetic states, cellular morphology, etc.

Ideally, we want a scRNASeq method that:

  • is universal in terms of cell size, type and state
  • have no minimum input requirements (works on cells with low amount of RNA)
  • assay every cell (100% capture rate)
  • detect every transcript or gene in every cell (100% sensitivity)
  • identify individual transcripts by their full-length sequence
  • assign transcripts correctly to cells (no cell doublets)

The development of single-cell RNA-seq technologies and their adoption by biologists has been remarkable. Svensson et al. 2019 describes a database of articles which present single-cell RNA-seq experiments, and the graph below, rendered from the current version of the database, makes clear the exponential growth in single-cell transcriptomics:

if (!require("tidyverse", quietly = TRUE))
    install.packages("tidyverse")
if (!require("lubridate", quietly = TRUE))
    install.packages("lubridate")
library(tidyverse)
library(lubridate)
df <- read_tsv('http://nxn.se/single-cell-studies/data.tsv',
               show_col_types = F) %>% 
  mutate(Date = ymd(Date)) %>% 
  filter(Measurement == "RNA-seq")
df %>% 
  arrange(desc(order(Date))) %>% 
  group_by(Date) %>% 
  summarise(number = n()) %>% 
  mutate(cumulative_number = cumsum(number)) %>% 
  ggplot() +
  geom_line(aes(x = Date, y = cumulative_number)) +
  labs(
    title = "Cumulative number of single-cell studies",
    y = "Cumulative number",
    x = "Date"
  ) +
  theme_classic()

2 scRNASeq technologies

There are many different scRNAseq technologies in use and under development, but broadly they fall into a few categories

  • well-based methods (e.g. Fluidigm SMARTer C1, Smart-seq2)
  • droplet-based methods (e.g. Drop-seq, InDrops, 10X Genomics Chromium)
  • spatial transcriptomics approaches (e.g. MERFISH, SEQFISH)

Improvement in these technologies has led to an increasing number of sequenced cells per experiments.

df %>% 
  arrange(desc(order(Date))) %>% 
  group_by(Date) %>% 
  mutate(cell_number = mean(`Reported cells total`)) %>% 
  ggplot() +
  geom_point(aes(x = Date, y = cell_number)) +
  labs(
    title = "Number of cells sequenced",
    y = "Cell number",
    x = "Date"
  ) +
  theme() +
  annotation_logticks() +
  scale_y_log10() +
  theme_classic()

Droplet-based approaches have become popular due to their relative low-cost, easy to use, and scalability. This is evident in a breakdown of articles by technology used:

df %>% 
  arrange(desc(order(Date))) %>% 
  dplyr::select(Date, Technique) %>% 
  separate_rows(Technique, sep = " & ") %>% 
  mutate(Date = floor_date(Date, "2month")) %>% 
  group_by(Date, Technique) %>% 
  summarize(number = n(), .groups = "rowwise") %>% 
  group_by(Technique) %>% 
  mutate(tot_number = n()) %>% 
  arrange(tot_number) %>% 
  ungroup() %>% 
  mutate(Technique = ifelse(tot_number < 20, "other", Technique),
         Technique = fct_reorder(Technique, tot_number, .desc = T)) %>% 
  drop_na() %>% 
  ggplot() +
  geom_col(aes(x = Date, y = number, fill = Technique)) +
  labs(
    title = "Technologie used in single-cell studies",
    y = "number of studies",
    x = "Date"
  ) +
  theme() +
  scale_y_log10() +
  annotation_logticks() +
  xlim(ymd("2013-01-01"), NA) +
  theme_classic()

3 Droplet-based methods

Droplet based single-cell RNA-seq methods were popularized by a pair of papers published in 2015:

Figure from the Drop-seq Macosko et al. 2015 paper

A microfluidic device is used to generate an emulsion, which consists of aqueous droplets in oil. The droplets are used to encapsulate cells, beads and reagents. In other words, each droplet is a “mini laboratory” in which the RNA from a single-cell can be captured and prepared for identification.

The generation of single-cell RNA-seq data is just the first step in understanding the transcriptomes cells. To interpret the data reads must be aligned or pseudoaligned, Unique Molecular Identifiers (UMIs) counted, and large cell x gene matrices examined. The growth in single-cell RNA-seq analysis tools for these tasks has been breathtaking. The graph below, plotted from real-time data downloaded from the scRNA-seq tools database, shows the number of tools published since 2016.

read_tsv("https://raw.githubusercontent.com/Oshlack/scRNA-tools/master/database/tools.tsv",
         show_col_types = F) %>%
  mutate(Date = ymd(Updated)) %>% 
  arrange(desc(order(Date))) %>% 
  group_by(Date) %>% 
  summarise(number = n()) %>% 
  mutate(cumulative_number = cumsum(number)) %>% 
  ggplot() +
  geom_line(aes(x = Date, y = cumulative_number)) +
  labs(
    title = "Cumulative number of single-cell tools",
    y = "Cumulative number",
    x = "Date"
  ) +
  theme_classic()

We are not going to learn how to use all these tools, but instead, focus on commonly used ones, to perform every steps of a single-cell RNASeq workflow.

In the following all quoted block like this one will correspond to things that you will have to do. Click on the Next link

LS0tCnRpdGxlOiAic2luZ2xlLWNlbGwgUk5BIHNlcXVlbmNpbmcgYW5hbHlzaXMiCmF1dGhvcjogTGF1cmVudCBNb2RvbG8KZGF0ZTogMjAyMS0yMDIyCm91dHB1dDoKICAgIGh0bWxfbm90ZWJvb2s6CiAgICAgIHRvYzogdHJ1ZQogICAgICB0b2NfZmxvYXQ6CiAgICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgICB0aGVtZTogc2FuZHN0b25lCiAgICAgIGhpZ2hsaWdodDogcHlnbWVudHMKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFQsCiAgd2FybmluZyA9IEYsCiAgbWVzc2FnZSA9IEYsCiAgY2FjaGUgPSBULAogIHJvb3QuZGlyID0gIi4uIiwKICBmaXQud2lkdGggPSAxMCwKICBmaWcuaGVpZ2h0ID0gNSwKICBmaWcucGF0aCA9ICcuL2ltZy8nLAogIGRwaSA9IDEwMCwKICBwcm9ncmVzcyA9IFRSVUUKKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpUaGUgZ29hbCBvZiBzaW5nbGUtY2VsbCB0cmFuc2NyaXB0b21pY3MgaXMgdG8gbWVhc3VyZSB0aGUgdHJhbnNjcmlwdGlvbmFsIHN0YXRlcyBvZiBsYXJnZSBudW1iZXJzIG9mIGNlbGxzIHNpbXVsdGFuZW91c2x5LiBUaGUgaW5wdXQgdG8gYSBzaW5nbGUtY2VsbCBSTkEgc2VxdWVuY2luZyAoc2NSTkFzZXEpIG1ldGhvZCBpcyBhIGNvbGxlY3Rpb24gb2YgY2VsbHMuIEZvcm1hbGx5LCB0aGUgZGVzaXJlZCBvdXRwdXQgaXMgYSB0cmFuc2NyaXB0IG9yIGdlbmVzICgkTSQpIHggY2VsbHMgKCROJCkgbWF0cml4ICRYXntOIFx0aW1lcyBNfSQgdGhhdCBkZXNjcmliZXMsIGZvciBlYWNoIGNlbGwsIHRoZSBhYnVuZGFuY2Ugb2YgaXRzIGNvbnN0aXR1ZW50IHRyYW5zY3JpcHRzIG9yIGdlbmVzLiBNb3JlIGdlbmVyYWxseSwgc2luZ2xlLWNlbGwgZ2Vub21pY3MgbWV0aG9kcyBzZWVrIHRvIG1lYXN1cmUgbm90IGp1c3QgdHJhbnNjcmlwdGlvbmFsIHN0YXRlLCBidXQgb3RoZXIgbW9kYWxpdGllcyBpbiBjZWxscywgZS5nLiwgcHJvdGVpbiBhYnVuZGFuY2VzLCBlcGlnZW5ldGljIHN0YXRlcywgY2VsbHVsYXIgbW9ycGhvbG9neSwgZXRjLgoKSWRlYWxseSwgd2Ugd2FudCBhIHNjUk5BU2VxIG1ldGhvZCB0aGF0OgoKLSBpcyB1bml2ZXJzYWwgaW4gdGVybXMgb2YgY2VsbCBzaXplLCB0eXBlIGFuZCBzdGF0ZQotIGhhdmUgbm8gbWluaW11bSBpbnB1dCByZXF1aXJlbWVudHMgKHdvcmtzIG9uIGNlbGxzIHdpdGggbG93IGFtb3VudCBvZiBSTkEpCi0gYXNzYXkgZXZlcnkgY2VsbCAoMTAwJSBjYXB0dXJlIHJhdGUpCi0gZGV0ZWN0IGV2ZXJ5IHRyYW5zY3JpcHQgb3IgZ2VuZSBpbiBldmVyeSBjZWxsICgxMDAlIHNlbnNpdGl2aXR5KQotIGlkZW50aWZ5IGluZGl2aWR1YWwgdHJhbnNjcmlwdHMgYnkgdGhlaXIgZnVsbC1sZW5ndGggc2VxdWVuY2UKLSBhc3NpZ24gdHJhbnNjcmlwdHMgY29ycmVjdGx5IHRvIGNlbGxzIChubyBjZWxsIGRvdWJsZXRzKQoKIFRoZSBkZXZlbG9wbWVudCBvZiBzaW5nbGUtY2VsbCBSTkEtc2VxIHRlY2hub2xvZ2llcyBhbmQgdGhlaXIgYWRvcHRpb24gYnkgYmlvbG9naXN0cyBoYXMgYmVlbiByZW1hcmthYmxlLiBbU3ZlbnNzb24gZXQgYWwuIDIwMTldKGh0dHBzOi8vd3d3LmJpb3J4aXYub3JnL2NvbnRlbnQvMTAuMTEwMS83NDIzMDR2MikgZGVzY3JpYmVzIGEgZGF0YWJhc2Ugb2YgYXJ0aWNsZXMgd2hpY2ggcHJlc2VudCBzaW5nbGUtY2VsbCBSTkEtc2VxIGV4cGVyaW1lbnRzLCBhbmQgdGhlIGdyYXBoIGJlbG93LCByZW5kZXJlZCBmcm9tIHRoZSBjdXJyZW50IHZlcnNpb24gb2YgdGhlIGRhdGFiYXNlLCBtYWtlcyBjbGVhciB0aGUgZXhwb25lbnRpYWwgZ3Jvd3RoIGluIHNpbmdsZS1jZWxsIHRyYW5zY3JpcHRvbWljczoKCmBgYHtyIHNjcm5hX3N0dWRpZGVzLCBkZXBlbmRzb249ImxpYnJhcnkiLCBjYWNoZT1ULCBlY2hvPVQsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpCmlmICghcmVxdWlyZSgibHVicmlkYXRlIiwgcXVpZXRseSA9IFRSVUUpKQogICAgaW5zdGFsbC5wYWNrYWdlcygibHVicmlkYXRlIikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobHVicmlkYXRlKQpkZiA8LSByZWFkX3RzdignaHR0cDovL254bi5zZS9zaW5nbGUtY2VsbC1zdHVkaWVzL2RhdGEudHN2JywKICAgICAgICAgICAgICAgc2hvd19jb2xfdHlwZXMgPSBGKSAlPiUgCiAgbXV0YXRlKERhdGUgPSB5bWQoRGF0ZSkpICU+JSAKICBmaWx0ZXIoTWVhc3VyZW1lbnQgPT0gIlJOQS1zZXEiKQpgYGAKCmBgYHtyIHNjcm5hX3N0dWRpZXNfY3Vtc3VtLCBkZXBlbmRzb249InNjcm5hX3N0dWRpZXMiLCBjYWNoZT1UfQpkZiAlPiUgCiAgYXJyYW5nZShkZXNjKG9yZGVyKERhdGUpKSkgJT4lIAogIGdyb3VwX2J5KERhdGUpICU+JSAKICBzdW1tYXJpc2UobnVtYmVyID0gbigpKSAlPiUgCiAgbXV0YXRlKGN1bXVsYXRpdmVfbnVtYmVyID0gY3Vtc3VtKG51bWJlcikpICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gRGF0ZSwgeSA9IGN1bXVsYXRpdmVfbnVtYmVyKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDdW11bGF0aXZlIG51bWJlciBvZiBzaW5nbGUtY2VsbCBzdHVkaWVzIiwKICAgIHkgPSAiQ3VtdWxhdGl2ZSBudW1iZXIiLAogICAgeCA9ICJEYXRlIgogICkgKwogIHRoZW1lX2NsYXNzaWMoKQpgYGAKCiMgc2NSTkFTZXEgdGVjaG5vbG9naWVzCgpUaGVyZSBhcmUgbWFueSBkaWZmZXJlbnQgc2NSTkFzZXEgdGVjaG5vbG9naWVzIGluIHVzZSBhbmQgdW5kZXIgZGV2ZWxvcG1lbnQsIGJ1dCBicm9hZGx5IHRoZXkgZmFsbCBpbnRvIGEgZmV3IGNhdGVnb3JpZXMKCi0gd2VsbC1iYXNlZCBtZXRob2RzIChlLmcuIEZsdWlkaWdtIFNNQVJUZXIgQzEsIFNtYXJ0LXNlcTIpCi0gZHJvcGxldC1iYXNlZCBtZXRob2RzIChlLmcuIERyb3Atc2VxLCBJbkRyb3BzLCAxMFggR2Vub21pY3MgQ2hyb21pdW0pCi0gc3BhdGlhbCB0cmFuc2NyaXB0b21pY3MgYXBwcm9hY2hlcyAoZS5nLiBNRVJGSVNILCBTRVFGSVNIKQoKSW1wcm92ZW1lbnQgaW4gdGhlc2UgdGVjaG5vbG9naWVzIGhhcyBsZWQgdG8gYW4gaW5jcmVhc2luZyBudW1iZXIgb2Ygc2VxdWVuY2VkIGNlbGxzIHBlciBleHBlcmltZW50cy4KCmBgYHtyIHNjcm5hX3N0dWRpZXNfY2VsbG51bSwgZGVwZW5kc29uPSJzY3JuYV9zdHVkaWVzIiwgY2FjaGU9VH0KZGYgJT4lIAogIGFycmFuZ2UoZGVzYyhvcmRlcihEYXRlKSkpICU+JSAKICBncm91cF9ieShEYXRlKSAlPiUgCiAgbXV0YXRlKGNlbGxfbnVtYmVyID0gbWVhbihgUmVwb3J0ZWQgY2VsbHMgdG90YWxgKSkgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gRGF0ZSwgeSA9IGNlbGxfbnVtYmVyKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJOdW1iZXIgb2YgY2VsbHMgc2VxdWVuY2VkIiwKICAgIHkgPSAiQ2VsbCBudW1iZXIiLAogICAgeCA9ICJEYXRlIgogICkgKwogIHRoZW1lKCkgKwogIGFubm90YXRpb25fbG9ndGlja3MoKSArCiAgc2NhbGVfeV9sb2cxMCgpICsKICB0aGVtZV9jbGFzc2ljKCkKYGBgCgpEcm9wbGV0LWJhc2VkIGFwcHJvYWNoZXMgaGF2ZSBiZWNvbWUgcG9wdWxhciBkdWUgdG8gdGhlaXIgcmVsYXRpdmUgbG93LWNvc3QsIGVhc3kgdG8gdXNlLCBhbmQgc2NhbGFiaWxpdHkuIFRoaXMgaXMgZXZpZGVudCBpbiBhIGJyZWFrZG93biBvZiBhcnRpY2xlcyBieSB0ZWNobm9sb2d5IHVzZWQ6CgpgYGB7ciBzY3JuYV9zdHVkaWVzX3RlY2huaXF1ZSwgZGVwZW5kc29uPSJzY3JuYV9zdHVkaWVzIiwgY2FjaGU9VH0KZGYgJT4lIAogIGFycmFuZ2UoZGVzYyhvcmRlcihEYXRlKSkpICU+JSAKICBkcGx5cjo6c2VsZWN0KERhdGUsIFRlY2huaXF1ZSkgJT4lIAogIHNlcGFyYXRlX3Jvd3MoVGVjaG5pcXVlLCBzZXAgPSAiICYgIikgJT4lIAogIG11dGF0ZShEYXRlID0gZmxvb3JfZGF0ZShEYXRlLCAiMm1vbnRoIikpICU+JSAKICBncm91cF9ieShEYXRlLCBUZWNobmlxdWUpICU+JSAKICBzdW1tYXJpemUobnVtYmVyID0gbigpLCAuZ3JvdXBzID0gInJvd3dpc2UiKSAlPiUgCiAgZ3JvdXBfYnkoVGVjaG5pcXVlKSAlPiUgCiAgbXV0YXRlKHRvdF9udW1iZXIgPSBuKCkpICU+JSAKICBhcnJhbmdlKHRvdF9udW1iZXIpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZShUZWNobmlxdWUgPSBpZmVsc2UodG90X251bWJlciA8IDIwLCAib3RoZXIiLCBUZWNobmlxdWUpLAogICAgICAgICBUZWNobmlxdWUgPSBmY3RfcmVvcmRlcihUZWNobmlxdWUsIHRvdF9udW1iZXIsIC5kZXNjID0gVCkpICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX2NvbChhZXMoeCA9IERhdGUsIHkgPSBudW1iZXIsIGZpbGwgPSBUZWNobmlxdWUpKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRlY2hub2xvZ2llIHVzZWQgaW4gc2luZ2xlLWNlbGwgc3R1ZGllcyIsCiAgICB5ID0gIm51bWJlciBvZiBzdHVkaWVzIiwKICAgIHggPSAiRGF0ZSIKICApICsKICB0aGVtZSgpICsKICBzY2FsZV95X2xvZzEwKCkgKwogIGFubm90YXRpb25fbG9ndGlja3MoKSArCiAgeGxpbSh5bWQoIjIwMTMtMDEtMDEiKSwgTkEpICsKICB0aGVtZV9jbGFzc2ljKCkKYGBgCgojIERyb3BsZXQtYmFzZWQgbWV0aG9kcwoKRHJvcGxldCBiYXNlZCBzaW5nbGUtY2VsbCBSTkEtc2VxIG1ldGhvZHMgd2VyZSBwb3B1bGFyaXplZCBieSBhIHBhaXIgb2YgcGFwZXJzIHB1Ymxpc2hlZCBpbiAyMDE1OgoKLSBbTWFjb3NrbyBldCBhbC4sIEhpZ2hseSBwYXJhbGxlbCBnZW5vbWUtd2lkZSBleHByZXNzaW9uIHByb2ZpbGluZyBvZiBpbmRpdmlkdWFsIGNlbGxzIHVzaW5nIG5hbm9saXRlciBkcm9wbGV0cywgMjAxNS4gRE9JOjEwLjEwMTYvai5jZWxsLjIwMTUuMDUuMDAyIC0gZGVzY3JpYmVzIERyb3Atc2VxLl0oaHR0cHM6Ly93d3cuY2VsbC5jb20vY2VsbC9mdWxsdGV4dC9TMDA5Mi04Njc0XCgxNVwpMDA1NDktOCkKLSBbS2xlaW4gZXQgYWwuLCBEcm9wbGV0IGJhcmNvZGluZyBmb3Igc2luZ2xlLWNlbGwgdHJhbnNjcmlwdG9taWNzIGFwcGxpZWQgdG8gZW1icnlvbmljIHN0ZW0gY2VsbHMsIDIwMTUuIERPSToxMC4xMDE2L2ouY2VsbC4yMDE1LjA0LjA0NCAtIGRlc2NyaWJlcyBpbkRyb3BzLl0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMjYwMDA0ODcpCgohW0ZpZ3VyZSBmcm9tIHRoZSBEcm9wLXNlcSBNYWNvc2tvIGV0IGFsLiAyMDE1IHBhcGVyXSguL2ltZy9kcm9wbGV0LmpwZykKCkEgbWljcm9mbHVpZGljIGRldmljZSBpcyB1c2VkIHRvIGdlbmVyYXRlIGFuIGVtdWxzaW9uLCB3aGljaCBjb25zaXN0cyBvZiBhcXVlb3VzIGRyb3BsZXRzIGluIG9pbC4gVGhlIGRyb3BsZXRzIGFyZSB1c2VkIHRvIGVuY2Fwc3VsYXRlIGNlbGxzLCBiZWFkcyBhbmQgcmVhZ2VudHMuIEluIG90aGVyIHdvcmRzLCBlYWNoIGRyb3BsZXQgaXMgYSAibWluaSBsYWJvcmF0b3J5IiBpbiB3aGljaCB0aGUgUk5BIGZyb20gYSBzaW5nbGUtY2VsbCBjYW4gYmUgY2FwdHVyZWQgYW5kIHByZXBhcmVkIGZvciBpZGVudGlmaWNhdGlvbi4KCgpUaGUgZ2VuZXJhdGlvbiBvZiBzaW5nbGUtY2VsbCBSTkEtc2VxIGRhdGEgaXMganVzdCB0aGUgZmlyc3Qgc3RlcCBpbiB1bmRlcnN0YW5kaW5nIHRoZSB0cmFuc2NyaXB0b21lcyBjZWxscy4gVG8gaW50ZXJwcmV0IHRoZSBkYXRhIHJlYWRzIG11c3QgYmUgYWxpZ25lZCBvciBwc2V1ZG9hbGlnbmVkLCBVbmlxdWUgTW9sZWN1bGFyIElkZW50aWZpZXJzIChVTUlzKSBjb3VudGVkLCBhbmQgbGFyZ2UgY2VsbCB4IGdlbmUgbWF0cmljZXMgZXhhbWluZWQuIFRoZSBncm93dGggaW4gc2luZ2xlLWNlbGwgUk5BLXNlcSBhbmFseXNpcyB0b29scyBmb3IgdGhlc2UgdGFza3MgaGFzIGJlZW4gYnJlYXRodGFraW5nLiBUaGUgZ3JhcGggYmVsb3csIHBsb3R0ZWQgZnJvbSByZWFsLXRpbWUgZGF0YSBkb3dubG9hZGVkIGZyb20gdGhlIFtzY1JOQS1zZXEgdG9vbHMgZGF0YWJhc2VdKGh0dHBzOi8vd3d3LnNjcm5hLXRvb2xzLm9yZy90b29scyksIHNob3dzIHRoZSBudW1iZXIgb2YgdG9vbHMgcHVibGlzaGVkIHNpbmNlIDIwMTYuCgpgYGB7ciBzY3JuYV90b29sc251bWJlciwgZGVwZW5kc29uPSJsaWJyYXJ5IiwgY2FjaGU9VH0KcmVhZF90c3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9Pc2hsYWNrL3NjUk5BLXRvb2xzL21hc3Rlci9kYXRhYmFzZS90b29scy50c3YiLAogICAgICAgICBzaG93X2NvbF90eXBlcyA9IEYpICU+JQogIG11dGF0ZShEYXRlID0geW1kKFVwZGF0ZWQpKSAlPiUgCiAgYXJyYW5nZShkZXNjKG9yZGVyKERhdGUpKSkgJT4lIAogIGdyb3VwX2J5KERhdGUpICU+JSAKICBzdW1tYXJpc2UobnVtYmVyID0gbigpKSAlPiUgCiAgbXV0YXRlKGN1bXVsYXRpdmVfbnVtYmVyID0gY3Vtc3VtKG51bWJlcikpICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gRGF0ZSwgeSA9IGN1bXVsYXRpdmVfbnVtYmVyKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDdW11bGF0aXZlIG51bWJlciBvZiBzaW5nbGUtY2VsbCB0b29scyIsCiAgICB5ID0gIkN1bXVsYXRpdmUgbnVtYmVyIiwKICAgIHggPSAiRGF0ZSIKICApICsKICB0aGVtZV9jbGFzc2ljKCkKYGBgCldlIGFyZSBub3QgZ29pbmcgdG8gbGVhcm4gaG93IHRvIHVzZSBhbGwgdGhlc2UgdG9vbHMsIGJ1dCBpbnN0ZWFkLCBmb2N1cyBvbiBjb21tb25seSB1c2VkIG9uZXMsIHRvIHBlcmZvcm0gZXZlcnkgc3RlcHMgb2YgYSBzaW5nbGUtY2VsbCBSTkFTZXEgd29ya2Zsb3cuCgo+IEluIHRoZSBmb2xsb3dpbmcgYWxsIHF1b3RlZCBibG9jayBsaWtlIHRoaXMgb25lIHdpbGwgY29ycmVzcG9uZCB0byB0aGluZ3MgdGhhdCB5b3Ugd2lsbCBoYXZlIHRvIGRvLgo+IENsaWNrIG9uIHRoZSBbTmV4dF0oLi9uYXR1cmVfb2ZfdGhlX2RhdGEubmIuaHRtbCkgbGluaw==