Purpose:

Why are TCGA and PBTA data so different and why is TCGA TMB not higher than PBTA as we expected from literature and the results from Grobner et al. 2019

Related issues: Original Issue 3 Issue 257 Draft PR 521

Main three exploratory questions asked in this notebook:

  1. Is the tumor read depth different between PBTA and TCGA? )
  2. Do TMB comparisons results change if we calculate TMB with each caller by itself?
  3. How much do the TCGA and PBTA overlap in their target WXS regions?

Conclusions from this notebook:

Although it may be partially a caller-specific thing, we also suspect a problem with Lancet’s TCGA calls which is likely because it is all WXS data. This issue is further investigated in the Lancet WXS-WGS analysis notebook and the Lancet padded-unpadded analysis notebook.

Post notes:
It was later determined that the BED files used for these TMB calculations were incorrect See Related Issues:
- 568
- 565
- 564

Usage

To run this from the command line, use:

Rscript -e "rmarkdown::render('analyses/snv-callers/lancet-wxs-tests/explore-tcga-pbta.Rmd', 
                              clean = TRUE)"

This assumes you are in the top directory of the repository.

Setup

# Magrittr pipe
`%>%` <- dplyr::`%>%`

# We will need the calculate_tmb function from this script
source(file.path("..", "..", "snv-callers", "util", "tmb_functions.R"))

Declare directory paths.

scratch_dir <- file.path("..", "..", "..", "scratch")
data_dir <- file.path("..", "..", "..", "data")
ref_dir <- file.path("..", "ref_files")
plots_dir <- file.path("plots", "tcga-vs-pbta-plots")

if (!dir.exists(plots_dir)) {
  dir.create(plots_dir, recursive = TRUE)
}

Special functions

Function for setting up PBTA data from the database. These databases were originally created by the run consensus bash script for pbta and run consensus bash script for tcga

set_up_data <- function(data_name, 
                        database_path, 
                        metadata, 
                        is_tcga, 
                        cols_to_keep) {
  
  # Given the name of dataset in the database set up the data with the metadata
  #
  # Args:
  #  data_name: A string that is the name of the table in the SQLite file you'd like to pull out.
  #  database_path: file path to an SQlite file made previously by a run_consensus script
  #  metadata: associated metadata with this database
  #  is_tcga: TRUE or FALSE for whether or not this is TCGA data. FALSE = PBTA data
  #  cols_to_keep: A vector of strings indicating the column names to keep
  
  # Start up connection
  con <- DBI::dbConnect(
    RSQLite::SQLite(),
    database_path
  )
  # Connect to SQL
  df <- dplyr::tbl(con, data_name) %>%
    # Only keep the columns we want
    dplyr::select(cols_to_keep) %>%
    # Turn into data.frame
    as.data.frame() 
  
  # This step is only needed for TCGA data
  if (is_tcga) {
    df <- df %>% 
      # Shorten the Tumor_Sample_Barcode so it matches
      dplyr::mutate(Tumor_Sample_Barcode = substr(Tumor_Sample_Barcode, 0, 12))
  } 
  
  # Tack on the metadata columns we want
  df  <- df %>% 
    dplyr::inner_join(
      metadata %>%
        dplyr::select(
          Tumor_Sample_Barcode,
          experimental_strategy, 
          short_histology
        )
    ) 
  # Disconnect this database
  DBI::dbDisconnect(con)
  
  # Return this data.frame
  return(df)
}

Function for making a combined CDF plot for TMB. This plotting function was adapted from the breaks_cdf_plot function in the chromosomal-instability

tmb_cdf_plot <- function(tmb_df, plot_title) {
  # Given a data.frame of TMB data, plot it as a CDF plot and save it as a png. 
  #
  # Args:
  #   tmb_df: a chromosomal breaks density file path where each sample is
  #                 a row with `samples` and `breaks_count` columns. 
  #   plot_title: to be used for the ggplot2::ggtitle and what it will be saved 
  #                as a png as.
  
  cdf_plot <- tmb_df %>%
    as.data.frame() %>%
    dplyr::mutate(short_histology = tools::toTitleCase(short_histology)) %>%
    # Only plot histologies groups with more than `min_samples` number of samples
    dplyr::group_by(short_histology, add = TRUE) %>%
    # Only keep groups with this amount of samples
    dplyr::filter(dplyr::n() > 5) %>%
    # Calculate histology group mean
    dplyr::mutate(
      hist_mean = mean(tmb),
      hist_rank = rank(tmb, ties.method = "first") / dplyr::n(),
      sample_size = paste0("n = ", dplyr::n())
    ) %>%
    dplyr::ungroup() %>%
    dplyr::mutate(short_histology = reorder(short_histology, hist_mean)) %>%
    # Now we will plot these as cummulative distribution plots
    ggplot2::ggplot(ggplot2::aes(
      x = hist_rank,
      y = tmb,
      color = datasets
    )) +
    ggplot2::geom_point() +
    # Add summary line for mean
    ggplot2::geom_segment(
      x = 0, xend = 1, color = "grey",
      ggplot2::aes(y = hist_mean, yend = hist_mean)
    ) +
    # Separate by histology
    ggplot2::facet_wrap(~ short_histology + sample_size, nrow = 1, strip.position = "bottom") +
    ggplot2::theme_classic() +
    ggplot2::xlab("") +
    ggplot2::ylab("TMB") +
    # Transform to log10 make non-log y-axis labels
    ggplot2::scale_y_continuous(trans = "log1p", breaks = c(0, 1, 3, 10, 30)) +
    ggplot2::scale_x_continuous(limits = c(-0.2, 1.2), breaks = c()) +
    # Making it pretty
    ggplot2::theme(legend.position = "none") +
    ggplot2::theme(
      axis.text.x = ggplot2::element_blank(),
      axis.ticks.x = ggplot2::element_blank(),
      strip.placement = "outside",
      strip.text = ggplot2::element_text(size = 10, angle = 90, hjust = 1),
      strip.background = ggplot2::element_rect(fill = NA, color = NA)
    ) +
    ggplot2::ggtitle(plot_title)

  # Save as a PNG
  ggplot2::ggsave(filename = file.path(plots_dir, paste0("tmb-cdf-", plot_title, ".png")), 
                  plot = cdf_plot, 
                  width = 10, 
                  height = 7.5)
}

Function for comparing the sequence overlap of two GenomicRanges objects.

bed_overlap <- function(bed_granges_1,
                        bed_granges_2,
                        name_1,
                        name_2,
                        plot_name) {
  # Given two GenomicRanges objects make a VennDiagram of their overlap
  
  # Find intersection
  overlaps <- GenomicRanges::intersect(bed_granges_1, bed_granges_2)

  # Reduce these ranges for good measure in case they have overlaps 
  overlaps <- GenomicRanges::reduce(overlaps)
  
  # Percent of TCGA Target region covered by overlap
  sum(overlaps@ranges@width) / sum(bed_granges_2@ranges@width)

  # Percent of PBTA Target region covered by overlap
  sum(bed_granges_1@ranges@width)

  # Make filename to save plot as
  plot.file <- file.path(plots_dir, paste0(plot_name, ".png"))

  # Make the Venn diagram
  grid::grid.newpage()
  venn.plot <- VennDiagram::draw.pairwise.venn(
    area1 = sum(bed_granges_1@ranges@width),
    area2 = sum(bed_granges_2@ranges@width),
    cross.area = sum(overlaps@ranges@width),
    category = c(name_1, name_2),
    fill = c("#F8766D", "#00BFC4"),
    cex = 2,
    cat.cex = 1.5,
    ext.pos = 0,
    ext.dist = -0.01,
    ext.length = .8,
    ext.line.lwd = 2,
    ext.line.lty = "dashed",
    margin = 0.1
  )
  grid::grid.draw(venn.plot)

  # Save as a PNG
  png(plot.file)
  grid::grid.draw(venn.plot)
  dev.off()

  # Print out a summary of the ratios
  cat(
    " Ratio of", name_1, "overlapped:",
    sum(overlaps@ranges@width) / sum(bed_granges_1@ranges@width), "\n",
    "Ratio of", name_2, "overlapped:",
    sum(overlaps@ranges@width) / sum(bed_granges_2@ranges@width), "\n"
  )
}

Read in the metadata

Do some minor formatting so it works with the set_up_data function.

pbta_metadata <- readr::read_tsv(file.path(data_dir, "pbta-histologies.tsv")) %>% 
  # MAF files generally call this Tumor_Sample_Barcode and we will need to join by this ID
  dplyr::rename(Tumor_Sample_Barcode = Kids_First_Biospecimen_ID)
Parsed with column specification:
cols(
  .default = col_character(),
  OS_days = col_double(),
  age_last_update_days = col_double(),
  normal_fraction = col_double(),
  tumor_fraction = col_double(),
  tumor_ploidy = col_double(),
  molecular_subtype = col_logical()
)
See spec(...) for full column specifications.
493 parsing failures.
 row               col           expected actual                                 file
2334 molecular_subtype 1/0/T/F/TRUE/FALSE Group3 '../../../data/pbta-histologies.tsv'
2335 molecular_subtype 1/0/T/F/TRUE/FALSE Group4 '../../../data/pbta-histologies.tsv'
2336 molecular_subtype 1/0/T/F/TRUE/FALSE Group3 '../../../data/pbta-histologies.tsv'
2337 molecular_subtype 1/0/T/F/TRUE/FALSE Group3 '../../../data/pbta-histologies.tsv'
2338 molecular_subtype 1/0/T/F/TRUE/FALSE Group3 '../../../data/pbta-histologies.tsv'
.... ................. .................. ...... ....................................
See problems(...) for more details.
tcga_metadata <- readr::read_tsv(file.path(data_dir, "pbta-tcga-manifest.tsv")) %>%
  dplyr::mutate(
    experimental_strategy = "WXS", # This field doesn't exist for this data, but all is WXS
    short_histology = Primary_diagnosis
  ) # This field is named differently in PBTA
Parsed with column specification:
cols(
  Normal_BAM = col_character(),
  Tumor_BAM = col_character(),
  Tumor_Sample_Barcode = col_character(),
  broad_histology = col_character(),
  Primary_diagnosis = col_character()
)

Set up the datasets from the databases

Declare the columns we’ll keep.

cols_to_keep <- c(
  "Chromosome",
  "Start_Position",
  "End_Position",
  "Reference_Allele",
  "Allele",
  "Tumor_Sample_Barcode",
  "Variant_Classification",
  "t_depth",
  "t_ref_count",
  "t_alt_count",
  "n_depth",
  "n_ref_count",
  "n_alt_count",
  "VAF"
)

Set up TCGA data.

tcga_db_file <- file.path(scratch_dir, "tcga_snv_db.sqlite")

tcga_lancet <- set_up_data(data_name = "lancet", 
                           database_path = tcga_db_file, 
                           metadata = tcga_metadata, 
                           is_tcga = TRUE, 
                           cols_to_keep)
Joining, by = "Tumor_Sample_Barcode"
tcga_mutect <- set_up_data(data_name = "mutect",
                           database_path = tcga_db_file, 
                           metadata = tcga_metadata, 
                           is_tcga = TRUE, 
                           cols_to_keep)
Warning: call dbDisconnect() when finished working with a connection
Joining, by = "Tumor_Sample_Barcode"
tcga_strelka <- set_up_data(data_name ="strelka",
                            database_path = tcga_db_file, 
                            metadata = tcga_metadata, 
                            is_tcga = TRUE, 
                            cols_to_keep)
Joining, by = "Tumor_Sample_Barcode"
tcga_consensus <- set_up_data("consensus",
                              database_path = tcga_db_file, 
                              metadata = tcga_metadata, 
                              is_tcga = TRUE, 
                              cols_to_keep)
Joining, by = "Tumor_Sample_Barcode"

Set up PBTA data.

pbta_db_file <- file.path(scratch_dir, "snv_db.sqlite")

pbta_lancet <- set_up_data(data_name = "lancet",
                           database_path = pbta_db_file, 
                           metadata = pbta_metadata, 
                           is_tcga = FALSE, 
                           cols_to_keep)

How does the tumor sequencing depth compare for each TCGA and PBTA data?

Set up combined PBTA and TCGA data.frames.

lancet <- dplyr::bind_rows(list(
  tcga = tcga_lancet,
  pbta = pbta_lancet
), .id = "dataset") %>%
  dplyr::mutate(dataset = as.factor(dataset))

mutect <- dplyr::bind_rows(list(
  tcga = tcga_mutect,
  pbta = pbta_mutect
), .id = "dataset") %>%
  dplyr::mutate(dataset = as.factor(dataset))

strelka <- dplyr::bind_rows(list(
  tcga = tcga_strelka,
  pbta = pbta_strelka
), .id = "dataset") %>%
  dplyr::mutate(dataset = as.factor(dataset))

We’ll plot the tumor sequencing depth for each caller as a series of density plots.

lancet %>%
  ggplot2::ggplot(ggplot2::aes(x = log10(t_depth), y = ..scaled..,
                               color = dataset)) +
  ggplot2::geom_density(bw = 0.5)

mutect %>%
  ggplot2::ggplot(ggplot2::aes(x = log10(t_depth), y = ..scaled..,
                               color = dataset)) +
  ggplot2::geom_density(bw = 0.2)

strelka %>%
  ggplot2::ggplot(ggplot2::aes(x = log10(t_depth), y = ..scaled.., color = dataset)) +
  ggplot2::geom_density(bw = 0.2)

How does the TMB comparison look for each caller by itself?

Lancet only TMB:

lancet_tmb <- dplyr::bind_rows(list(
  pbta = calculate_tmb(pbta_lancet,
    bed_wgs = file.path(data_dir, "intersect_cds_lancet_strelka_mutect_WGS.bed"),
    bed_wxs = file.path(data_dir, "intersect_cds_lancet_WXS.bed")
  ),
  tcga = calculate_tmb(tcga_lancet,
    bed_wgs = file.path(data_dir, "intersect_cds_lancet_strelka_mutect_WGS.bed"), # There's no TCGA WGS samples, this is just a place holder and won't be used.
    bed_wxs = file.path(ref_dir, "intersect_cds_gencode_liftover_WXS.bed")
  )
), .id = "datasets")
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Ratio of variants in this BED: 1.739157 
 Ratio of variants being filtered out: -0.7391572 
Ratio of variants in this BED: 1.651031 
 Ratio of variants being filtered out: -0.6510313 
Unreplaced values treated as NA as .x is not compatible. Please specify replacements exhaustively or supply .defaultParsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Ratio of variants in this BED: 0.7421131 
 Ratio of variants being filtered out: 0.2578869 
Ratio of variants in this BED: NaN 
 Ratio of variants being filtered out: NaN 
tmb_cdf_plot(lancet_tmb, plot_title = "Lancet")

Lancet TMB

Mutect only TMB:

mutect_tmb <- dplyr::bind_rows(list(
  pbta = calculate_tmb(pbta_mutect,
    bed_wgs = file.path(data_dir, "intersect_cds_lancet_strelka_mutect_WGS.bed"),
    bed_wxs = file.path(data_dir, "intersect_cds_lancet_WXS.bed")
  ),
  tcga = calculate_tmb(tcga_mutect,
    bed_wgs = file.path(data_dir, "intersect_cds_lancet_strelka_mutect_WGS.bed"),
    bed_wxs = file.path(ref_dir, "intersect_cds_gencode_liftover_WXS.bed")
  )
), .id = "datasets")
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Ratio of variants in this BED: 1.98804 
 Ratio of variants being filtered out: -0.9880405 
Ratio of variants in this BED: 1.091582 
 Ratio of variants being filtered out: -0.09158185 
Unreplaced values treated as NA as .x is not compatible. Please specify replacements exhaustively or supply .defaultParsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Ratio of variants in this BED: 0.4940234 
 Ratio of variants being filtered out: 0.5059766 
Ratio of variants in this BED: NaN 
 Ratio of variants being filtered out: NaN 
# Make a CDF plot
tmb_cdf_plot(mutect_tmb, plot_title = "Mutect2")

Mutect2 TMB

Strelka only TMB:

strelka_tmb <- dplyr::bind_rows(list(
  pbta = calculate_tmb(pbta_strelka,
    bed_wgs = file.path(data_dir, "intersect_cds_lancet_strelka_mutect_WGS.bed"),
    bed_wxs = file.path(data_dir, "intersect_cds_lancet_WXS.bed")
  ),
  tcga = calculate_tmb(tcga_strelka,
    bed_wgs = file.path(data_dir, "intersect_cds_lancet_strelka_mutect_WGS.bed"),
    bed_wxs = file.path(ref_dir, "intersect_cds_gencode_liftover_WXS.bed")
  )
), .id = "datasets")
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Ratio of variants in this BED: 1.701877 
 Ratio of variants being filtered out: -0.7018769 
Ratio of variants in this BED: 1.110021 
 Ratio of variants being filtered out: -0.1100208 
Unreplaced values treated as NA as .x is not compatible. Please specify replacements exhaustively or supply .defaultParsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Ratio of variants in this BED: 0.4836536 
 Ratio of variants being filtered out: 0.5163464 
Ratio of variants in this BED: NaN 
 Ratio of variants being filtered out: NaN 
# Make a CDF plot
tmb_cdf_plot(strelka_tmb, plot_title = "Strelka2")

Strelka2 TMB

Consensus TMB:

consensus_tmb <- dplyr::bind_rows(list(
  pbta = calculate_tmb(pbta_consensus,
    bed_wgs = file.path(data_dir, "intersect_cds_lancet_strelka_mutect_WGS.bed"),
    bed_wxs = file.path(data_dir, "intersect_cds_lancet_WXS.bed")
  ),
  tcga = calculate_tmb(tcga_consensus,
    bed_wgs = file.path(data_dir, "intersect_cds_lancet_strelka_mutect_WGS.bed"),
    bed_wxs = file.path(ref_dir, "intersect_cds_gencode_liftover_WXS.bed")
  )
), .id = "datasets")
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Ratio of variants in this BED: 3.093321 
 Ratio of variants being filtered out: -2.093321 
Ratio of variants in this BED: 1.427508 
 Ratio of variants being filtered out: -0.4275085 
Unreplaced values treated as NA as .x is not compatible. Please specify replacements exhaustively or supply .defaultParsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Parsed with column specification:
cols(
  X1 = col_character(),
  X2 = col_double(),
  X3 = col_double()
)
Ratio of variants in this BED: 0.7455764 
 Ratio of variants being filtered out: 0.2544236 
Ratio of variants in this BED: NaN 
 Ratio of variants being filtered out: NaN 
# Make a CDF plot
tmb_cdf_plot(consensus_tmb, plot_title = "Consensus")

Consensus TMB

Overlap of the target regions of both datasets

Download a TCGA Target BED regions file from MC3, and format the chromosome data to be chr, save as a TSV file.

tcga_bed <- readr::read_tsv("https://api.gdc.cancer.gov/data/7f0d3ab9-8bef-4e3b-928a-6090caae885b", col_names = c("chr", "start", "end")) %>%
  dplyr::filter(!is.na(chr)) %>%
  dplyr::mutate(chr = paste0("chr", chr)) %>%
  readr::write_tsv(file.path(ref_dir, "gencode.v19.basic.exome.tsv"),
    col_names = FALSE
  )
Parsed with column specification:
cols(
  chr = col_double(),
  start = col_double(),
  end = col_double()
)
27285 parsing failures.
   row col expected actual                                                                   file
697048 chr a double     MT 'https://api.gdc.cancer.gov/data/7f0d3ab9-8bef-4e3b-928a-6090caae885b'
697049 chr a double     MT 'https://api.gdc.cancer.gov/data/7f0d3ab9-8bef-4e3b-928a-6090caae885b'
697050 chr a double     MT 'https://api.gdc.cancer.gov/data/7f0d3ab9-8bef-4e3b-928a-6090caae885b'
697051 chr a double     MT 'https://api.gdc.cancer.gov/data/7f0d3ab9-8bef-4e3b-928a-6090caae885b'
697052 chr a double     MT 'https://api.gdc.cancer.gov/data/7f0d3ab9-8bef-4e3b-928a-6090caae885b'
...... ... ........ ...... ......................................................................
See problems(...) for more details.

After using UCSC BED liftover to convert from the Target BED regions for TCGA data from hg19 to hg38 (What the PBTA data is using).

tcga_lift_bed <- readr::read_tsv(file.path(
  ref_dir,
  "hg38_liftover_genome_gencode.v19.basic.exome.bed"
),
col_names = c("chr", "start", "end")
) %>%
  dplyr::mutate(chr = stringr::word(chr, sep = "_", 1))
Parsed with column specification:
cols(
  chr = col_character(),
  start = col_double(),
  end = col_double()
)
# Make GRanges for CNV data
tcga_lift_granges <- GenomicRanges::GRanges(
  seqnames = tcga_lift_bed$chr,
  ranges = IRanges::IRanges(
    start = tcga_lift_bed$start,
    end = tcga_lift_bed$end
  )
)

# Reduce this to it's essential ranges
tcga_lift_granges <- GenomicRanges::reduce(tcga_lift_granges)

Make a TCGA BED GenomicRanges.

# Make GRanges for CNV data
tcga_granges <- GenomicRanges::GRanges(
  seqnames = tcga_bed$chr,
  ranges = IRanges::IRanges(
    start = tcga_bed$start,
    end = tcga_bed$end
  )
)

# Reduce this to it's essential ranges
tcga_granges <- GenomicRanges::reduce(tcga_granges)

Format the PBTA WXS data as a GRanges object.

# pbta_bed <- readr::read_tsv(file.path(scratch_dir, "intersect_cds_WXS.bed"),
pbta_bed <- readr::read_tsv(file.path(data_dir, "WXS.hg38.100bp_padded.bed"),
  col_names = c("chr", "start", "end")
) %>%
  dplyr::filter(!is.na(chr))
Parsed with column specification:
cols(
  chr = col_character(),
  start = col_double(),
  end = col_double()
)
# Make GRanges for CNV data
pbta_granges <- GenomicRanges::GRanges(
  seqnames = pbta_bed$chr,
  ranges = IRanges::IRanges(
    start = pbta_bed$start,
    end = pbta_bed$end
  )
)

# Reduce this to it's essential ranges
pbta_granges <- GenomicRanges::reduce(pbta_granges)

Read in the coding sequence regions file.

cds_bed <- readr::read_tsv(file.path(
  scratch_dir,
  "gencode.v27.primary_assembly.annotation.bed"
),
col_names = c("chr", "start", "end")
) %>%
  dplyr::filter(!is.na(chr))
Parsed with column specification:
cols(
  chr = col_character(),
  start = col_double(),
  end = col_double()
)
# Make GRanges
cds_granges <- GenomicRanges::GRanges(
  seqnames = cds_bed$chr,
  ranges = IRanges::IRanges(
    start = cds_bed$start,
    end = cds_bed$end
  )
)

# Reduce this to it's essential ranges
cds_granges <- GenomicRanges::reduce(cds_granges)

We also need to see how this translates to CDS regions:

# Find CDS intersection
pbta_cds_granges <- GenomicRanges::intersect(pbta_granges, cds_granges)
Each of the 2 combined objects has sequence levels not in the other:
  - in 'x': chr7_KI270803v1_alt, chr15_KI270850v1_alt, chr17_KI270909v1_alt, chr19_KI270938v1_alt, chr22_KI270879v1_alt, chrUn_GL000213v1
  - in 'y': chrM, GL000009.2, GL000194.1, GL000195.1, GL000205.2, GL000213.1, GL000218.1, GL000219.1, KI270711.1, KI270713.1, KI270721.1, KI270726.1, KI270727.1, KI270728.1, KI270731.1, KI270734.1
  Make sure to always combine/compare objects based on the same reference
  genome (use suppressWarnings() to suppress this warning).
tcga_cds_granges <- GenomicRanges::intersect(tcga_granges, cds_granges)
tcga_lift_cds_granges <- GenomicRanges::intersect(tcga_lift_granges, cds_granges)
Each of the 2 combined objects has sequence levels not in the other:
  - in 'x': chrUn
  - in 'y': chrM, chrX, chrY, GL000009.2, GL000194.1, GL000195.1, GL000205.2, GL000213.1, GL000218.1, GL000219.1, KI270711.1, KI270713.1, KI270721.1, KI270726.1, KI270727.1, KI270728.1, KI270731.1, KI270734.1
  Make sure to always combine/compare objects based on the same reference
  genome (use suppressWarnings() to suppress this warning).

Make Venn diagrams of these overlaps

Find overlap between the TCGA (non-liftover) and PBTA data.

bed_overlap(pbta_granges,
  tcga_granges,
  plot_name = "PBTA vs TCGA WXS target BED",
  name_1 = "PBTA",
  name_2 = "TCGA"
)
 Ratio of PBTA overlapped: 0.07363001 
 Ratio of TCGA overlapped: 0.1186468 

Find overlap between the liftover TCGA target BED region and PBTA data.

bed_overlap(pbta_granges,
  tcga_lift_granges,
  plot_name = "PBTA vs TCGA WXS liftover target BED",
  name_1 = "PBTA",
  name_2 = "TCGA liftover"
)
Each of the 2 combined objects has sequence levels not in the other:
  - in 'x': chr7_KI270803v1_alt, chr15_KI270850v1_alt, chr17_KI270909v1_alt, chr19_KI270938v1_alt, chr22_KI270879v1_alt, chrUn_GL000213v1, chrX, chrY
  - in 'y': chrUn
  Make sure to always combine/compare objects based on the same reference
  genome (use suppressWarnings() to suppress this warning).
 Ratio of PBTA overlapped: 0.487083 
 Ratio of TCGA liftover overlapped: 0.7862399 

Find overlap between coding sequences only of the liftover TCGA target BED region and PBTA data.

bed_overlap(pbta_cds_granges,
  tcga_lift_cds_granges,
  plot_name = "PBTA vs TCGA WXS liftover coding sequence target BED",
  name_1 = "PBTA CDS",
  name_2 = "TCGA lift CDS"
)
Each of the 2 combined objects has sequence levels not in the other:
  - in 'x': chr7_KI270803v1_alt, chr15_KI270850v1_alt, chr17_KI270909v1_alt, chr19_KI270938v1_alt, chr22_KI270879v1_alt, chrUn_GL000213v1
  - in 'y': chrUn
  Make sure to always combine/compare objects based on the same reference
  genome (use suppressWarnings() to suppress this warning).
 Ratio of PBTA CDS overlapped: 0.942882 
 Ratio of TCGA lift CDS overlapped: 0.9794732 

Find overlap between coding sequences only of the TCGA target BED region and PBTA data.

bed_overlap(pbta_cds_granges,
  tcga_cds_granges,
  plot_name = "PBTA vs TCGA WXS Coding sequence target BED",
  name_1 = "PBTA CDS",
  name_2 = "TCGA CDS"
)
 Ratio of PBTA CDS overlapped: 0.08945405 
 Ratio of TCGA CDS overlapped: 0.975733 

Session Info

sessionInfo()
R version 3.6.0 (2019-04-26)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Debian GNU/Linux 9 (stretch)

Matrix products: default
BLAS/LAPACK: /usr/lib/libopenblasp-r0.2.19.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8       
 [4] LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8    LC_MESSAGES=C             
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
[10] LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] parallel  stats4    stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] GenomicRanges_1.38.0 GenomeInfoDb_1.22.0  IRanges_2.20.1       S4Vectors_0.24.1    
[5] BiocGenerics_0.32.0 

loaded via a namespace (and not attached):
 [1] tidyselect_0.2.5       xfun_0.8               purrr_0.3.2            colorspace_1.4-1      
 [5] htmltools_0.3.6        base64enc_0.1-3        yaml_2.2.0             blob_1.1.1            
 [9] rlang_0.4.0            pillar_1.4.2           glue_1.3.1             DBI_1.0.0             
[13] bit64_0.9-7            dbplyr_1.4.2           lambda.r_1.2.3         GenomeInfoDbData_1.2.2
[17] stringr_1.4.0          zlibbioc_1.32.0        munsell_0.5.0          gtable_0.3.0          
[21] futile.logger_1.4.3    memoise_1.1.0          evaluate_0.14          labeling_0.3          
[25] knitr_1.23             curl_3.3               Rcpp_1.0.1             readr_1.3.1           
[29] scales_1.0.0           formatR_1.7            jsonlite_1.6           XVector_0.26.0        
[33] bit_1.1-14             ggplot2_3.2.0          hms_0.4.2              digest_0.6.20         
[37] stringi_1.4.3          dplyr_0.8.3            grid_3.6.0             tools_3.6.0           
[41] bitops_1.0-6           magrittr_1.5           RCurl_1.95-4.12        lazyeval_0.2.2        
[45] tibble_2.1.3           RSQLite_2.1.1          futile.options_1.0.1   crayon_1.3.4          
[49] pkgconfig_2.0.2        data.table_1.12.2      assertthat_0.2.1       rmarkdown_1.13        
[53] rstudioapi_0.10        R6_2.4.0               VennDiagram_1.6.20     compiler_3.6.0        
LS0tCnRpdGxlOiAiVENHQSBQQlRBIGNvbXBhcmlzb24gZXhwbG9yYXRpb24iCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCmF1dGhvcjogQy4gU2F2b25lbiBmb3IgQUxTRiBDQ0RMCmRhdGU6IDIwMjAKLS0tCgojIyMjIFB1cnBvc2U6IApXaHkgYXJlIFRDR0EgYW5kIFBCVEEgZGF0YSBzbyBkaWZmZXJlbnQgYW5kIHdoeSBpcyBUQ0dBIFRNQiBub3QgaGlnaGVyIHRoYW4gClBCVEEgYXMgd2UgZXhwZWN0ZWQgZnJvbSBsaXRlcmF0dXJlIGFuZCB0aGUgcmVzdWx0cyBmcm9tIEdyb2JuZXIgZXQgYWwuIDIwMTkKClJlbGF0ZWQgaXNzdWVzOgpbT3JpZ2luYWwgSXNzdWUgM10oaHR0cHM6Ly9naXRodWIuY29tL0FsZXhzTGVtb25hZGUvT3BlblBCVEEtYW5hbHlzaXMvaXNzdWVzLzMpCltJc3N1ZSAyNTddKGh0dHBzOi8vZ2l0aHViLmNvbS9BbGV4c0xlbW9uYWRlL09wZW5QQlRBLWFuYWx5c2lzL2lzc3Vlcy8yNTcpCltEcmFmdCBQUiA1MjFdKGh0dHBzOi8vZ2l0aHViLmNvbS9BbGV4c0xlbW9uYWRlL09wZW5QQlRBLWFuYWx5c2lzL3B1bGwvNTIxKQoKKk1haW4gdGhyZWUgZXhwbG9yYXRvcnkgcXVlc3Rpb25zIGFza2VkIGluIHRoaXMgbm90ZWJvb2s6KgoKMSkgW0lzIHRoZSB0dW1vciByZWFkIGRlcHRoIGRpZmZlcmVudCBiZXR3ZWVuIFBCVEEgYW5kIFRDR0E/XSgjaG93LWRvZXMtdGhlLXR1bW9yLXNlcXVlbmNpbmctZGVwdGgtY29tcGFyZS1mb3ItZWFjaC10Y2dhLWFuZC1wYnRhLWRhdGEpCikgCjIpIFtEbyBUTUIgY29tcGFyaXNvbnMgcmVzdWx0cyBjaGFuZ2UgaWYgd2UgY2FsY3VsYXRlIFRNQiB3aXRoIGVhY2ggY2FsbGVyIGJ5IGl0c2VsZj9dKCNob3ctZG9lcy10aGUtdG1iLWNvbXBhcmlzb24tbG9vay1mb3ItZWFjaC1jYWxsZXItYnktaXRzZWxmKQozKSBbSG93IG11Y2ggZG8gdGhlIFRDR0EgYW5kIFBCVEEgb3ZlcmxhcCBpbiB0aGVpciB0YXJnZXQgV1hTIHJlZ2lvbnM/XSgjb3ZlcmxhcC1vZi10aGUtdGFyZ2V0LXJlZ2lvbnMtb2YtYm90aC1kYXRhc2V0cykKCiMjIyMgQ29uY2x1c2lvbnMgZnJvbSB0aGlzIG5vdGVib29rOiAKQWx0aG91Z2ggaXQgbWF5IGJlIHBhcnRpYWxseSBhIGNhbGxlci1zcGVjaWZpYyB0aGluZywgd2UgYWxzbyBzdXNwZWN0IGEgcHJvYmxlbSB3aXRoIApMYW5jZXQncyBUQ0dBIGNhbGxzIHdoaWNoIGlzIGxpa2VseSBiZWNhdXNlIGl0IGlzIGFsbCBXWFMgZGF0YS4gClRoaXMgaXNzdWUgaXMgZnVydGhlciBpbnZlc3RpZ2F0ZWQgaW4gdGhlIFtMYW5jZXQgV1hTLVdHUyBhbmFseXNpcyBub3RlYm9va10oaHR0cHM6Ly9naXRodWIuY29tL0FsZXhzTGVtb25hZGUvT3BlblBCVEEtYW5hbHlzaXMvYmxvYi9tYXN0ZXIvYW5hbHlzZXMvc252LWNhbGxlcnMvbGFuY2V0LXd4cy10ZXN0cy9sYW5jZXQtcGFpcmVkLVdYUy1XR1MuUm1kKSBhbmQgdGhlIFtMYW5jZXQgcGFkZGVkLXVucGFkZGVkIGFuYWx5c2lzIG5vdGVib29rXShodHRwczovL2dpdGh1Yi5jb20vQWxleHNMZW1vbmFkZS9PcGVuUEJUQS1hbmFseXNpcy9ibG9iL21hc3Rlci9hbmFseXNlcy9zbnYtY2FsbGVycy9sYW5jZXQtd3hzLXRlc3RzL2xhbmNldC1wYWRkZWQtdnMtdW5wYWRkZWQuUm1kKS4gCgoqKlBvc3Qgbm90ZXM6KiogICAKSXQgd2FzIGxhdGVyIGRldGVybWluZWQgdGhhdCB0aGUgQkVEIGZpbGVzIHVzZWQgZm9yIHRoZXNlIFRNQiBjYWxjdWxhdGlvbnMgd2VyZSBpbmNvcnJlY3QgU2VlIFJlbGF0ZWQgSXNzdWVzOiAgCi0gWzU2OF0oaHR0cHM6Ly9naXRodWIuY29tL0FsZXhzTGVtb25hZGUvT3BlblBCVEEtYW5hbHlzaXMvaXNzdWVzLzU2OCkgIAotIFs1NjVdKGh0dHBzOi8vZ2l0aHViLmNvbS9BbGV4c0xlbW9uYWRlL09wZW5QQlRBLWFuYWx5c2lzL2lzc3Vlcy81NjUpICAKLSBbNTY0XShodHRwczovL2dpdGh1Yi5jb20vQWxleHNMZW1vbmFkZS9PcGVuUEJUQS1hbmFseXNpcy9pc3N1ZXMvNTY0KSAgCgojIyMjIFVzYWdlCgpUbyBydW4gdGhpcyBmcm9tIHRoZSBjb21tYW5kIGxpbmUsIHVzZToKYGBgClJzY3JpcHQgLWUgInJtYXJrZG93bjo6cmVuZGVyKCdhbmFseXNlcy9zbnYtY2FsbGVycy9sYW5jZXQtd3hzLXRlc3RzL2V4cGxvcmUtdGNnYS1wYnRhLlJtZCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGVhbiA9IFRSVUUpIgpgYGAKCl9UaGlzIGFzc3VtZXMgeW91IGFyZSBpbiB0aGUgdG9wIGRpcmVjdG9yeSBvZiB0aGUgcmVwb3NpdG9yeS5fCgojIyBTZXR1cAoKYGBge3J9CiMgTWFncml0dHIgcGlwZQpgJT4lYCA8LSBkcGx5cjo6YCU+JWAKCiMgV2Ugd2lsbCBuZWVkIHRoZSBjYWxjdWxhdGVfdG1iIGZ1bmN0aW9uIGZyb20gdGhpcyBzY3JpcHQKc291cmNlKGZpbGUucGF0aCgiLi4iLCAiLi4iLCAic252LWNhbGxlcnMiLCAidXRpbCIsICJ0bWJfZnVuY3Rpb25zLlIiKSkKYGBgCgpEZWNsYXJlIGRpcmVjdG9yeSBwYXRocy4gCgpgYGB7cn0Kc2NyYXRjaF9kaXIgPC0gZmlsZS5wYXRoKCIuLiIsICIuLiIsICIuLiIsICJzY3JhdGNoIikKZGF0YV9kaXIgPC0gZmlsZS5wYXRoKCIuLiIsICIuLiIsICIuLiIsICJkYXRhIikKcmVmX2RpciA8LSBmaWxlLnBhdGgoIi4uIiwgInJlZl9maWxlcyIpCnBsb3RzX2RpciA8LSBmaWxlLnBhdGgoInBsb3RzIiwgInRjZ2EtdnMtcGJ0YS1wbG90cyIpCgppZiAoIWRpci5leGlzdHMocGxvdHNfZGlyKSkgewogIGRpci5jcmVhdGUocGxvdHNfZGlyLCByZWN1cnNpdmUgPSBUUlVFKQp9CmBgYAoKIyMjIFNwZWNpYWwgZnVuY3Rpb25zIAoKRnVuY3Rpb24gZm9yIHNldHRpbmcgdXAgUEJUQSBkYXRhIGZyb20gdGhlIGRhdGFiYXNlLiAKVGhlc2UgZGF0YWJhc2VzIHdlcmUgb3JpZ2luYWxseSBjcmVhdGVkIGJ5IHRoZSBbcnVuIGNvbnNlbnN1cyBiYXNoIHNjcmlwdCBmb3IgcGJ0YV0oaHR0cHM6Ly9naXRodWIuY29tL0FsZXhzTGVtb25hZGUvT3BlblBCVEEtYW5hbHlzaXMvYmxvYi9tYXN0ZXIvYW5hbHlzZXMvc252LWNhbGxlcnMvcnVuX2NhbGxlcl9jb25zZW5zdXNfYW5hbHlzaXMtcGJ0YS5zaCkgYW5kICBbcnVuIGNvbnNlbnN1cyBiYXNoIHNjcmlwdCBmb3IgdGNnYV0oaHR0cHM6Ly9naXRodWIuY29tL0FsZXhzTGVtb25hZGUvT3BlblBCVEEtYW5hbHlzaXMvYmxvYi9tYXN0ZXIvYW5hbHlzZXMvc252LWNhbGxlcnMvcnVuX2NhbGxlcl9jb25zZW5zdXNfYW5hbHlzaXMtdGNnYS5zaCkKCmBgYHtyfQpzZXRfdXBfZGF0YSA8LSBmdW5jdGlvbihkYXRhX25hbWUsIAogICAgICAgICAgICAgICAgICAgICAgICBkYXRhYmFzZV9wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEsIAogICAgICAgICAgICAgICAgICAgICAgICBpc190Y2dhLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29sc190b19rZWVwKSB7CiAgCiAgIyBHaXZlbiB0aGUgbmFtZSBvZiBkYXRhc2V0IGluIHRoZSBkYXRhYmFzZSBzZXQgdXAgdGhlIGRhdGEgd2l0aCB0aGUgbWV0YWRhdGEKICAjCiAgIyBBcmdzOgogICMgIGRhdGFfbmFtZTogQSBzdHJpbmcgdGhhdCBpcyB0aGUgbmFtZSBvZiB0aGUgdGFibGUgaW4gdGhlIFNRTGl0ZSBmaWxlIHlvdSdkIGxpa2UgdG8gcHVsbCBvdXQuCiAgIyAgZGF0YWJhc2VfcGF0aDogZmlsZSBwYXRoIHRvIGFuIFNRbGl0ZSBmaWxlIG1hZGUgcHJldmlvdXNseSBieSBhIHJ1bl9jb25zZW5zdXMgc2NyaXB0CiAgIyAgbWV0YWRhdGE6IGFzc29jaWF0ZWQgbWV0YWRhdGEgd2l0aCB0aGlzIGRhdGFiYXNlCiAgIyAgaXNfdGNnYTogVFJVRSBvciBGQUxTRSBmb3Igd2hldGhlciBvciBub3QgdGhpcyBpcyBUQ0dBIGRhdGEuIEZBTFNFID0gUEJUQSBkYXRhCiAgIyAgY29sc190b19rZWVwOiBBIHZlY3RvciBvZiBzdHJpbmdzIGluZGljYXRpbmcgdGhlIGNvbHVtbiBuYW1lcyB0byBrZWVwCiAgCiAgIyBTdGFydCB1cCBjb25uZWN0aW9uCiAgY29uIDwtIERCSTo6ZGJDb25uZWN0KAogICAgUlNRTGl0ZTo6U1FMaXRlKCksCiAgICBkYXRhYmFzZV9wYXRoCiAgKQogICMgQ29ubmVjdCB0byBTUUwKICBkZiA8LSBkcGx5cjo6dGJsKGNvbiwgZGF0YV9uYW1lKSAlPiUKICAgICMgT25seSBrZWVwIHRoZSBjb2x1bW5zIHdlIHdhbnQKICAgIGRwbHlyOjpzZWxlY3QoY29sc190b19rZWVwKSAlPiUKICAgICMgVHVybiBpbnRvIGRhdGEuZnJhbWUKICAgIGFzLmRhdGEuZnJhbWUoKSAKICAKICAjIFRoaXMgc3RlcCBpcyBvbmx5IG5lZWRlZCBmb3IgVENHQSBkYXRhCiAgaWYgKGlzX3RjZ2EpIHsKICAgIGRmIDwtIGRmICU+JSAKICAgICAgIyBTaG9ydGVuIHRoZSBUdW1vcl9TYW1wbGVfQmFyY29kZSBzbyBpdCBtYXRjaGVzCiAgICAgIGRwbHlyOjptdXRhdGUoVHVtb3JfU2FtcGxlX0JhcmNvZGUgPSBzdWJzdHIoVHVtb3JfU2FtcGxlX0JhcmNvZGUsIDAsIDEyKSkKICB9IAogIAogICMgVGFjayBvbiB0aGUgbWV0YWRhdGEgY29sdW1ucyB3ZSB3YW50CiAgZGYgIDwtIGRmICU+JSAKICAgIGRwbHlyOjppbm5lcl9qb2luKAogICAgICBtZXRhZGF0YSAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KAogICAgICAgICAgVHVtb3JfU2FtcGxlX0JhcmNvZGUsCiAgICAgICAgICBleHBlcmltZW50YWxfc3RyYXRlZ3ksIAogICAgICAgICAgc2hvcnRfaGlzdG9sb2d5CiAgICAgICAgKQogICAgKSAKICAjIERpc2Nvbm5lY3QgdGhpcyBkYXRhYmFzZQogIERCSTo6ZGJEaXNjb25uZWN0KGNvbikKICAKICAjIFJldHVybiB0aGlzIGRhdGEuZnJhbWUKICByZXR1cm4oZGYpCn0KYGBgCgpGdW5jdGlvbiBmb3IgbWFraW5nIGEgY29tYmluZWQgQ0RGIHBsb3QgZm9yIFRNQi4gClRoaXMgcGxvdHRpbmcgZnVuY3Rpb24gd2FzIGFkYXB0ZWQgZnJvbSB0aGUgW2BicmVha3NfY2RmX3Bsb3RgIGZ1bmN0aW9uIGluIHRoZSAKYGNocm9tb3NvbWFsLWluc3RhYmlsaXR5YF0oaHR0cHM6Ly9naXRodWIuY29tL0FsZXhzTGVtb25hZGUvT3BlblBCVEEtYW5hbHlzaXMvYmxvYi9iMWI3M2ZlMzIxYTk3ZmE4MmQ4NWM4NmQyMGJkODU2MzVhYWJiYTI1L2FuYWx5c2VzL2Nocm9tb3NvbWFsLWluc3RhYmlsaXR5L3V0aWwvY2hyLWJyZWFrLXBsb3QuUiNMMTIwKQoKYGBge3J9CnRtYl9jZGZfcGxvdCA8LSBmdW5jdGlvbih0bWJfZGYsIHBsb3RfdGl0bGUpIHsKICAjIEdpdmVuIGEgZGF0YS5mcmFtZSBvZiBUTUIgZGF0YSwgcGxvdCBpdCBhcyBhIENERiBwbG90IGFuZCBzYXZlIGl0IGFzIGEgcG5nLiAKICAjCiAgIyBBcmdzOgogICMgICB0bWJfZGY6IGEgY2hyb21vc29tYWwgYnJlYWtzIGRlbnNpdHkgZmlsZSBwYXRoIHdoZXJlIGVhY2ggc2FtcGxlIGlzCiAgIyAgICAgICAgICAgICAgICAgYSByb3cgd2l0aCBgc2FtcGxlc2AgYW5kIGBicmVha3NfY291bnRgIGNvbHVtbnMuIAogICMgICBwbG90X3RpdGxlOiB0byBiZSB1c2VkIGZvciB0aGUgZ2dwbG90Mjo6Z2d0aXRsZSBhbmQgd2hhdCBpdCB3aWxsIGJlIHNhdmVkIAogICMgICAgICAgICAgICAgICAgYXMgYSBwbmcgYXMuCiAgCiAgY2RmX3Bsb3QgPC0gdG1iX2RmICU+JQogICAgYXMuZGF0YS5mcmFtZSgpICU+JQogICAgZHBseXI6Om11dGF0ZShzaG9ydF9oaXN0b2xvZ3kgPSB0b29sczo6dG9UaXRsZUNhc2Uoc2hvcnRfaGlzdG9sb2d5KSkgJT4lCiAgICAjIE9ubHkgcGxvdCBoaXN0b2xvZ2llcyBncm91cHMgd2l0aCBtb3JlIHRoYW4gYG1pbl9zYW1wbGVzYCBudW1iZXIgb2Ygc2FtcGxlcwogICAgZHBseXI6Omdyb3VwX2J5KHNob3J0X2hpc3RvbG9neSwgYWRkID0gVFJVRSkgJT4lCiAgICAjIE9ubHkga2VlcCBncm91cHMgd2l0aCB0aGlzIGFtb3VudCBvZiBzYW1wbGVzCiAgICBkcGx5cjo6ZmlsdGVyKGRwbHlyOjpuKCkgPiA1KSAlPiUKICAgICMgQ2FsY3VsYXRlIGhpc3RvbG9neSBncm91cCBtZWFuCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBoaXN0X21lYW4gPSBtZWFuKHRtYiksCiAgICAgIGhpc3RfcmFuayA9IHJhbmsodG1iLCB0aWVzLm1ldGhvZCA9ICJmaXJzdCIpIC8gZHBseXI6Om4oKSwKICAgICAgc2FtcGxlX3NpemUgPSBwYXN0ZTAoIm4gPSAiLCBkcGx5cjo6bigpKQogICAgKSAlPiUKICAgIGRwbHlyOjp1bmdyb3VwKCkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKHNob3J0X2hpc3RvbG9neSA9IHJlb3JkZXIoc2hvcnRfaGlzdG9sb2d5LCBoaXN0X21lYW4pKSAlPiUKICAgICMgTm93IHdlIHdpbGwgcGxvdCB0aGVzZSBhcyBjdW1tdWxhdGl2ZSBkaXN0cmlidXRpb24gcGxvdHMKICAgIGdncGxvdDI6OmdncGxvdChnZ3Bsb3QyOjphZXMoCiAgICAgIHggPSBoaXN0X3JhbmssCiAgICAgIHkgPSB0bWIsCiAgICAgIGNvbG9yID0gZGF0YXNldHMKICAgICkpICsKICAgIGdncGxvdDI6Omdlb21fcG9pbnQoKSArCiAgICAjIEFkZCBzdW1tYXJ5IGxpbmUgZm9yIG1lYW4KICAgIGdncGxvdDI6Omdlb21fc2VnbWVudCgKICAgICAgeCA9IDAsIHhlbmQgPSAxLCBjb2xvciA9ICJncmV5IiwKICAgICAgZ2dwbG90Mjo6YWVzKHkgPSBoaXN0X21lYW4sIHllbmQgPSBoaXN0X21lYW4pCiAgICApICsKICAgICMgU2VwYXJhdGUgYnkgaGlzdG9sb2d5CiAgICBnZ3Bsb3QyOjpmYWNldF93cmFwKH4gc2hvcnRfaGlzdG9sb2d5ICsgc2FtcGxlX3NpemUsIG5yb3cgPSAxLCBzdHJpcC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgICBnZ3Bsb3QyOjp0aGVtZV9jbGFzc2ljKCkgKwogICAgZ2dwbG90Mjo6eGxhYigiIikgKwogICAgZ2dwbG90Mjo6eWxhYigiVE1CIikgKwogICAgIyBUcmFuc2Zvcm0gdG8gbG9nMTAgbWFrZSBub24tbG9nIHktYXhpcyBsYWJlbHMKICAgIGdncGxvdDI6OnNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxcCIsIGJyZWFrcyA9IGMoMCwgMSwgMywgMTAsIDMwKSkgKwogICAgZ2dwbG90Mjo6c2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTAuMiwgMS4yKSwgYnJlYWtzID0gYygpKSArCiAgICAjIE1ha2luZyBpdCBwcmV0dHkKICAgIGdncGxvdDI6OnRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2dwbG90Mjo6dGhlbWUoCiAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRpY2tzLnggPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksCiAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwKICAgICAgc3RyaXAudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTAsIGFuZ2xlID0gOTAsIGhqdXN0ID0gMSksCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBnZ3Bsb3QyOjplbGVtZW50X3JlY3QoZmlsbCA9IE5BLCBjb2xvciA9IE5BKQogICAgKSArCiAgICBnZ3Bsb3QyOjpnZ3RpdGxlKHBsb3RfdGl0bGUpCgogICMgU2F2ZSBhcyBhIFBORwogIGdncGxvdDI6Omdnc2F2ZShmaWxlbmFtZSA9IGZpbGUucGF0aChwbG90c19kaXIsIHBhc3RlMCgidG1iLWNkZi0iLCBwbG90X3RpdGxlLCAiLnBuZyIpKSwgCiAgICAgICAgICAgICAgICAgIHBsb3QgPSBjZGZfcGxvdCwgCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMTAsIAogICAgICAgICAgICAgICAgICBoZWlnaHQgPSA3LjUpCn0KYGBgCgpGdW5jdGlvbiBmb3IgY29tcGFyaW5nIHRoZSBzZXF1ZW5jZSBvdmVybGFwIG9mIHR3byBHZW5vbWljUmFuZ2VzIG9iamVjdHMuIAoKYGBge3J9CmJlZF9vdmVybGFwIDwtIGZ1bmN0aW9uKGJlZF9ncmFuZ2VzXzEsCiAgICAgICAgICAgICAgICAgICAgICAgIGJlZF9ncmFuZ2VzXzIsCiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVfMSwKICAgICAgICAgICAgICAgICAgICAgICAgbmFtZV8yLAogICAgICAgICAgICAgICAgICAgICAgICBwbG90X25hbWUpIHsKICAjIEdpdmVuIHR3byBHZW5vbWljUmFuZ2VzIG9iamVjdHMgbWFrZSBhIFZlbm5EaWFncmFtIG9mIHRoZWlyIG92ZXJsYXAKICAKICAjIEZpbmQgaW50ZXJzZWN0aW9uCiAgb3ZlcmxhcHMgPC0gR2Vub21pY1Jhbmdlczo6aW50ZXJzZWN0KGJlZF9ncmFuZ2VzXzEsIGJlZF9ncmFuZ2VzXzIpCgogICMgUmVkdWNlIHRoZXNlIHJhbmdlcyBmb3IgZ29vZCBtZWFzdXJlIGluIGNhc2UgdGhleSBoYXZlIG92ZXJsYXBzIAogIG92ZXJsYXBzIDwtIEdlbm9taWNSYW5nZXM6OnJlZHVjZShvdmVybGFwcykKICAKICAjIFBlcmNlbnQgb2YgVENHQSBUYXJnZXQgcmVnaW9uIGNvdmVyZWQgYnkgb3ZlcmxhcAogIHN1bShvdmVybGFwc0ByYW5nZXNAd2lkdGgpIC8gc3VtKGJlZF9ncmFuZ2VzXzJAcmFuZ2VzQHdpZHRoKQoKICAjIFBlcmNlbnQgb2YgUEJUQSBUYXJnZXQgcmVnaW9uIGNvdmVyZWQgYnkgb3ZlcmxhcAogIHN1bShiZWRfZ3Jhbmdlc18xQHJhbmdlc0B3aWR0aCkKCiAgIyBNYWtlIGZpbGVuYW1lIHRvIHNhdmUgcGxvdCBhcwogIHBsb3QuZmlsZSA8LSBmaWxlLnBhdGgocGxvdHNfZGlyLCBwYXN0ZTAocGxvdF9uYW1lLCAiLnBuZyIpKQoKICAjIE1ha2UgdGhlIFZlbm4gZGlhZ3JhbQogIGdyaWQ6OmdyaWQubmV3cGFnZSgpCiAgdmVubi5wbG90IDwtIFZlbm5EaWFncmFtOjpkcmF3LnBhaXJ3aXNlLnZlbm4oCiAgICBhcmVhMSA9IHN1bShiZWRfZ3Jhbmdlc18xQHJhbmdlc0B3aWR0aCksCiAgICBhcmVhMiA9IHN1bShiZWRfZ3Jhbmdlc18yQHJhbmdlc0B3aWR0aCksCiAgICBjcm9zcy5hcmVhID0gc3VtKG92ZXJsYXBzQHJhbmdlc0B3aWR0aCksCiAgICBjYXRlZ29yeSA9IGMobmFtZV8xLCBuYW1lXzIpLAogICAgZmlsbCA9IGMoIiNGODc2NkQiLCAiIzAwQkZDNCIpLAogICAgY2V4ID0gMiwKICAgIGNhdC5jZXggPSAxLjUsCiAgICBleHQucG9zID0gMCwKICAgIGV4dC5kaXN0ID0gLTAuMDEsCiAgICBleHQubGVuZ3RoID0gLjgsCiAgICBleHQubGluZS5sd2QgPSAyLAogICAgZXh0LmxpbmUubHR5ID0gImRhc2hlZCIsCiAgICBtYXJnaW4gPSAwLjEKICApCiAgZ3JpZDo6Z3JpZC5kcmF3KHZlbm4ucGxvdCkKCiAgIyBTYXZlIGFzIGEgUE5HCiAgcG5nKHBsb3QuZmlsZSkKICBncmlkOjpncmlkLmRyYXcodmVubi5wbG90KQogIGRldi5vZmYoKQoKICAjIFByaW50IG91dCBhIHN1bW1hcnkgb2YgdGhlIHJhdGlvcwogIGNhdCgKICAgICIgUmF0aW8gb2YiLCBuYW1lXzEsICJvdmVybGFwcGVkOiIsCiAgICBzdW0ob3ZlcmxhcHNAcmFuZ2VzQHdpZHRoKSAvIHN1bShiZWRfZ3Jhbmdlc18xQHJhbmdlc0B3aWR0aCksICJcbiIsCiAgICAiUmF0aW8gb2YiLCBuYW1lXzIsICJvdmVybGFwcGVkOiIsCiAgICBzdW0ob3ZlcmxhcHNAcmFuZ2VzQHdpZHRoKSAvIHN1bShiZWRfZ3Jhbmdlc18yQHJhbmdlc0B3aWR0aCksICJcbiIKICApCn0KYGBgCgojIyBSZWFkIGluIHRoZSBtZXRhZGF0YSAKRG8gc29tZSBtaW5vciBmb3JtYXR0aW5nIHNvIGl0IHdvcmtzIHdpdGggdGhlIGBzZXRfdXBfZGF0YWAgZnVuY3Rpb24uIAoKYGBge3J9CnBidGFfbWV0YWRhdGEgPC0gcmVhZHI6OnJlYWRfdHN2KGZpbGUucGF0aChkYXRhX2RpciwgInBidGEtaGlzdG9sb2dpZXMudHN2IikpICU+JSAKICAjIE1BRiBmaWxlcyBnZW5lcmFsbHkgY2FsbCB0aGlzIFR1bW9yX1NhbXBsZV9CYXJjb2RlIGFuZCB3ZSB3aWxsIG5lZWQgdG8gam9pbiBieSB0aGlzIElECiAgZHBseXI6OnJlbmFtZShUdW1vcl9TYW1wbGVfQmFyY29kZSA9IEtpZHNfRmlyc3RfQmlvc3BlY2ltZW5fSUQpCgp0Y2dhX21ldGFkYXRhIDwtIHJlYWRyOjpyZWFkX3RzdihmaWxlLnBhdGgoZGF0YV9kaXIsICJwYnRhLXRjZ2EtbWFuaWZlc3QudHN2IikpICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICBleHBlcmltZW50YWxfc3RyYXRlZ3kgPSAiV1hTIiwgIyBUaGlzIGZpZWxkIGRvZXNuJ3QgZXhpc3QgZm9yIHRoaXMgZGF0YSwgYnV0IGFsbCBpcyBXWFMKICAgIHNob3J0X2hpc3RvbG9neSA9IFByaW1hcnlfZGlhZ25vc2lzCiAgKSAjIFRoaXMgZmllbGQgaXMgbmFtZWQgZGlmZmVyZW50bHkgaW4gUEJUQQpgYGAKCiMjIFNldCB1cCB0aGUgZGF0YXNldHMgZnJvbSB0aGUgZGF0YWJhc2VzCgpEZWNsYXJlIHRoZSBjb2x1bW5zIHdlJ2xsIGtlZXAuIAoKYGBge3J9CmNvbHNfdG9fa2VlcCA8LSBjKAogICJDaHJvbW9zb21lIiwKICAiU3RhcnRfUG9zaXRpb24iLAogICJFbmRfUG9zaXRpb24iLAogICJSZWZlcmVuY2VfQWxsZWxlIiwKICAiQWxsZWxlIiwKICAiVHVtb3JfU2FtcGxlX0JhcmNvZGUiLAogICJWYXJpYW50X0NsYXNzaWZpY2F0aW9uIiwKICAidF9kZXB0aCIsCiAgInRfcmVmX2NvdW50IiwKICAidF9hbHRfY291bnQiLAogICJuX2RlcHRoIiwKICAibl9yZWZfY291bnQiLAogICJuX2FsdF9jb3VudCIsCiAgIlZBRiIKKQpgYGAKClNldCB1cCBUQ0dBIGRhdGEuIAoKYGBge3J9CnRjZ2FfZGJfZmlsZSA8LSBmaWxlLnBhdGgoc2NyYXRjaF9kaXIsICJ0Y2dhX3Nudl9kYi5zcWxpdGUiKQoKdGNnYV9sYW5jZXQgPC0gc2V0X3VwX2RhdGEoZGF0YV9uYW1lID0gImxhbmNldCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhYmFzZV9wYXRoID0gdGNnYV9kYl9maWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEgPSB0Y2dhX21ldGFkYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNfdGNnYSA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xzX3RvX2tlZXApCgp0Y2dhX211dGVjdCA8LSBzZXRfdXBfZGF0YShkYXRhX25hbWUgPSAibXV0ZWN0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YWJhc2VfcGF0aCA9IHRjZ2FfZGJfZmlsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhID0gdGNnYV9tZXRhZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzX3RjZ2EgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sc190b19rZWVwKQoKdGNnYV9zdHJlbGthIDwtIHNldF91cF9kYXRhKGRhdGFfbmFtZSA9InN0cmVsa2EiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YWJhc2VfcGF0aCA9IHRjZ2FfZGJfZmlsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YSA9IHRjZ2FfbWV0YWRhdGEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNfdGNnYSA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sc190b19rZWVwKQoKdGNnYV9jb25zZW5zdXMgPC0gc2V0X3VwX2RhdGEoImNvbnNlbnN1cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFiYXNlX3BhdGggPSB0Y2dhX2RiX2ZpbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YSA9IHRjZ2FfbWV0YWRhdGEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc190Y2dhID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHNfdG9fa2VlcCkKYGBgCgpTZXQgdXAgUEJUQSBkYXRhLiAKCmBgYHtyfQpwYnRhX2RiX2ZpbGUgPC0gZmlsZS5wYXRoKHNjcmF0Y2hfZGlyLCAic252X2RiLnNxbGl0ZSIpCgpwYnRhX2xhbmNldCA8LSBzZXRfdXBfZGF0YShkYXRhX25hbWUgPSAibGFuY2V0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YWJhc2VfcGF0aCA9IHBidGFfZGJfZmlsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhID0gcGJ0YV9tZXRhZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzX3RjZ2EgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHNfdG9fa2VlcCkKCnBidGFfbXV0ZWN0IDwtIHNldF91cF9kYXRhKCJtdXRlY3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhYmFzZV9wYXRoID0gcGJ0YV9kYl9maWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEgPSBwYnRhX21ldGFkYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNfdGNnYSA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sc190b19rZWVwKQoKcGJ0YV9zdHJlbGthIDwtIHNldF91cF9kYXRhKCJzdHJlbGthIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFiYXNlX3BhdGggPSBwYnRhX2RiX2ZpbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEgPSBwYnRhX21ldGFkYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzX3RjZ2EgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xzX3RvX2tlZXApCgpwYnRhX2NvbnNlbnN1cyA8LSBzZXRfdXBfZGF0YSgiY29uc2Vuc3VzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YWJhc2VfcGF0aCA9IHBidGFfZGJfZmlsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhID0gcGJ0YV9tZXRhZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzX3RjZ2EgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHNfdG9fa2VlcCkKYGBgCgojIyBIb3cgZG9lcyB0aGUgdHVtb3Igc2VxdWVuY2luZyBkZXB0aCBjb21wYXJlIGZvciBlYWNoIFRDR0EgYW5kIFBCVEEgZGF0YT8KClNldCB1cCBjb21iaW5lZCBQQlRBIGFuZCBUQ0dBIGRhdGEuZnJhbWVzLiAKCmBgYHtyfQpsYW5jZXQgPC0gZHBseXI6OmJpbmRfcm93cyhsaXN0KAogIHRjZ2EgPSB0Y2dhX2xhbmNldCwKICBwYnRhID0gcGJ0YV9sYW5jZXQKKSwgLmlkID0gImRhdGFzZXQiKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRhdGFzZXQgPSBhcy5mYWN0b3IoZGF0YXNldCkpCgptdXRlY3QgPC0gZHBseXI6OmJpbmRfcm93cyhsaXN0KAogIHRjZ2EgPSB0Y2dhX211dGVjdCwKICBwYnRhID0gcGJ0YV9tdXRlY3QKKSwgLmlkID0gImRhdGFzZXQiKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRhdGFzZXQgPSBhcy5mYWN0b3IoZGF0YXNldCkpCgpzdHJlbGthIDwtIGRwbHlyOjpiaW5kX3Jvd3MobGlzdCgKICB0Y2dhID0gdGNnYV9zdHJlbGthLAogIHBidGEgPSBwYnRhX3N0cmVsa2EKKSwgLmlkID0gImRhdGFzZXQiKSAlPiUKICBkcGx5cjo6bXV0YXRlKGRhdGFzZXQgPSBhcy5mYWN0b3IoZGF0YXNldCkpCmBgYAoKV2UnbGwgcGxvdCB0aGUgdHVtb3Igc2VxdWVuY2luZyBkZXB0aCBmb3IgZWFjaCBjYWxsZXIgYXMgYSBzZXJpZXMgb2YgZGVuc2l0eSBwbG90cy4gCgpgYGB7cn0KbGFuY2V0ICU+JQogIGdncGxvdDI6OmdncGxvdChnZ3Bsb3QyOjphZXMoeCA9IGxvZzEwKHRfZGVwdGgpLCB5ID0gLi5zY2FsZWQuLiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gZGF0YXNldCkpICsKICBnZ3Bsb3QyOjpnZW9tX2RlbnNpdHkoYncgPSAwLjUpCmBgYAoKYGBge3J9Cm11dGVjdCAlPiUKICBnZ3Bsb3QyOjpnZ3Bsb3QoZ2dwbG90Mjo6YWVzKHggPSBsb2cxMCh0X2RlcHRoKSwgeSA9IC4uc2NhbGVkLi4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGRhdGFzZXQpKSArCiAgZ2dwbG90Mjo6Z2VvbV9kZW5zaXR5KGJ3ID0gMC4yKQpgYGAKCmBgYHtyfQpzdHJlbGthICU+JQogIGdncGxvdDI6OmdncGxvdChnZ3Bsb3QyOjphZXMoeCA9IGxvZzEwKHRfZGVwdGgpLCB5ID0gLi5zY2FsZWQuLiwgY29sb3IgPSBkYXRhc2V0KSkgKwogIGdncGxvdDI6Omdlb21fZGVuc2l0eShidyA9IDAuMikKYGBgCgojIyBIb3cgZG9lcyB0aGUgVE1CIGNvbXBhcmlzb24gbG9vayBmb3IgZWFjaCBjYWxsZXIgYnkgaXRzZWxmPyAKCkxhbmNldCBvbmx5IFRNQjoKCmBgYHtyfQpsYW5jZXRfdG1iIDwtIGRwbHlyOjpiaW5kX3Jvd3MobGlzdCgKICBwYnRhID0gY2FsY3VsYXRlX3RtYihwYnRhX2xhbmNldCwKICAgIGJlZF93Z3MgPSBmaWxlLnBhdGgoZGF0YV9kaXIsICJpbnRlcnNlY3RfY2RzX2xhbmNldF9zdHJlbGthX211dGVjdF9XR1MuYmVkIiksCiAgICBiZWRfd3hzID0gZmlsZS5wYXRoKGRhdGFfZGlyLCAiaW50ZXJzZWN0X2Nkc19sYW5jZXRfV1hTLmJlZCIpCiAgKSwKICB0Y2dhID0gY2FsY3VsYXRlX3RtYih0Y2dhX2xhbmNldCwKICAgIGJlZF93Z3MgPSBmaWxlLnBhdGgoZGF0YV9kaXIsICJpbnRlcnNlY3RfY2RzX2xhbmNldF9zdHJlbGthX211dGVjdF9XR1MuYmVkIiksICMgVGhlcmUncyBubyBUQ0dBIFdHUyBzYW1wbGVzLCB0aGlzIGlzIGp1c3QgYSBwbGFjZSBob2xkZXIgYW5kIHdvbid0IGJlIHVzZWQuCiAgICBiZWRfd3hzID0gZmlsZS5wYXRoKHJlZl9kaXIsICJpbnRlcnNlY3RfY2RzX2dlbmNvZGVfbGlmdG92ZXJfV1hTLmJlZCIpCiAgKQopLCAuaWQgPSAiZGF0YXNldHMiKQoKdG1iX2NkZl9wbG90KGxhbmNldF90bWIsIHBsb3RfdGl0bGUgPSAiTGFuY2V0IikKYGBgCgpbTGFuY2V0IFRNQl0ocGxvdHMvdGNnYS12cy1wYnRhLXBsb3RzL3RtYi1jZGYtTGFuY2V0LnBuZykKCk11dGVjdCBvbmx5IFRNQjoKCmBgYHtyfQptdXRlY3RfdG1iIDwtIGRwbHlyOjpiaW5kX3Jvd3MobGlzdCgKICBwYnRhID0gY2FsY3VsYXRlX3RtYihwYnRhX211dGVjdCwKICAgIGJlZF93Z3MgPSBmaWxlLnBhdGgoZGF0YV9kaXIsICJpbnRlcnNlY3RfY2RzX2xhbmNldF9zdHJlbGthX211dGVjdF9XR1MuYmVkIiksCiAgICBiZWRfd3hzID0gZmlsZS5wYXRoKGRhdGFfZGlyLCAiaW50ZXJzZWN0X2Nkc19sYW5jZXRfV1hTLmJlZCIpCiAgKSwKICB0Y2dhID0gY2FsY3VsYXRlX3RtYih0Y2dhX211dGVjdCwKICAgIGJlZF93Z3MgPSBmaWxlLnBhdGgoZGF0YV9kaXIsICJpbnRlcnNlY3RfY2RzX2xhbmNldF9zdHJlbGthX211dGVjdF9XR1MuYmVkIiksCiAgICBiZWRfd3hzID0gZmlsZS5wYXRoKHJlZl9kaXIsICJpbnRlcnNlY3RfY2RzX2dlbmNvZGVfbGlmdG92ZXJfV1hTLmJlZCIpCiAgKQopLCAuaWQgPSAiZGF0YXNldHMiKQoKIyBNYWtlIGEgQ0RGIHBsb3QKdG1iX2NkZl9wbG90KG11dGVjdF90bWIsIHBsb3RfdGl0bGUgPSAiTXV0ZWN0MiIpCmBgYAoKW011dGVjdDIgVE1CXShwbG90cy90Y2dhLXZzLXBidGEtcGxvdHMvdG1iLWNkZi1NdXRlY3QyLnBuZykKClN0cmVsa2Egb25seSBUTUI6CgpgYGB7cn0Kc3RyZWxrYV90bWIgPC0gZHBseXI6OmJpbmRfcm93cyhsaXN0KAogIHBidGEgPSBjYWxjdWxhdGVfdG1iKHBidGFfc3RyZWxrYSwKICAgIGJlZF93Z3MgPSBmaWxlLnBhdGgoZGF0YV9kaXIsICJpbnRlcnNlY3RfY2RzX2xhbmNldF9zdHJlbGthX211dGVjdF9XR1MuYmVkIiksCiAgICBiZWRfd3hzID0gZmlsZS5wYXRoKGRhdGFfZGlyLCAiaW50ZXJzZWN0X2Nkc19sYW5jZXRfV1hTLmJlZCIpCiAgKSwKICB0Y2dhID0gY2FsY3VsYXRlX3RtYih0Y2dhX3N0cmVsa2EsCiAgICBiZWRfd2dzID0gZmlsZS5wYXRoKGRhdGFfZGlyLCAiaW50ZXJzZWN0X2Nkc19sYW5jZXRfc3RyZWxrYV9tdXRlY3RfV0dTLmJlZCIpLAogICAgYmVkX3d4cyA9IGZpbGUucGF0aChyZWZfZGlyLCAiaW50ZXJzZWN0X2Nkc19nZW5jb2RlX2xpZnRvdmVyX1dYUy5iZWQiKQogICkKKSwgLmlkID0gImRhdGFzZXRzIikKCiMgTWFrZSBhIENERiBwbG90CnRtYl9jZGZfcGxvdChzdHJlbGthX3RtYiwgcGxvdF90aXRsZSA9ICJTdHJlbGthMiIpCmBgYAoKW1N0cmVsa2EyIFRNQl0ocGxvdHMvdGNnYS12cy1wYnRhLXBsb3RzL3RtYi1jZGYtU3RyZWxrYTIucG5nKQoKQ29uc2Vuc3VzIFRNQjoKCmBgYHtyfQpjb25zZW5zdXNfdG1iIDwtIGRwbHlyOjpiaW5kX3Jvd3MobGlzdCgKICBwYnRhID0gY2FsY3VsYXRlX3RtYihwYnRhX2NvbnNlbnN1cywKICAgIGJlZF93Z3MgPSBmaWxlLnBhdGgoZGF0YV9kaXIsICJpbnRlcnNlY3RfY2RzX2xhbmNldF9zdHJlbGthX211dGVjdF9XR1MuYmVkIiksCiAgICBiZWRfd3hzID0gZmlsZS5wYXRoKGRhdGFfZGlyLCAiaW50ZXJzZWN0X2Nkc19sYW5jZXRfV1hTLmJlZCIpCiAgKSwKICB0Y2dhID0gY2FsY3VsYXRlX3RtYih0Y2dhX2NvbnNlbnN1cywKICAgIGJlZF93Z3MgPSBmaWxlLnBhdGgoZGF0YV9kaXIsICJpbnRlcnNlY3RfY2RzX2xhbmNldF9zdHJlbGthX211dGVjdF9XR1MuYmVkIiksCiAgICBiZWRfd3hzID0gZmlsZS5wYXRoKHJlZl9kaXIsICJpbnRlcnNlY3RfY2RzX2dlbmNvZGVfbGlmdG92ZXJfV1hTLmJlZCIpCiAgKQopLCAuaWQgPSAiZGF0YXNldHMiKQoKIyBNYWtlIGEgQ0RGIHBsb3QKdG1iX2NkZl9wbG90KGNvbnNlbnN1c190bWIsIHBsb3RfdGl0bGUgPSAiQ29uc2Vuc3VzIikKYGBgCgpbQ29uc2Vuc3VzIFRNQl0ocGxvdHMvdGNnYS12cy1wYnRhLXBsb3RzL3RtYi1jZGYtQ29uc2Vuc3VzLnBuZykKCiMjIE92ZXJsYXAgb2YgdGhlIHRhcmdldCByZWdpb25zIG9mIGJvdGggZGF0YXNldHMKCkRvd25sb2FkIGEgVENHQSBUYXJnZXQgQkVEIHJlZ2lvbnMgZmlsZSBmcm9tIE1DMywgYW5kIGZvcm1hdCB0aGUgY2hyb21vc29tZSBkYXRhIHRvIApiZSBgY2hyYCwgc2F2ZSBhcyBhIFRTViBmaWxlLiAKCmBgYHtyfQp0Y2dhX2JlZCA8LSByZWFkcjo6cmVhZF90c3YoImh0dHBzOi8vYXBpLmdkYy5jYW5jZXIuZ292L2RhdGEvN2YwZDNhYjktOGJlZi00ZTNiLTkyOGEtNjA5MGNhYWU4ODViIiwgY29sX25hbWVzID0gYygiY2hyIiwgInN0YXJ0IiwgImVuZCIpKSAlPiUKICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShjaHIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKGNociA9IHBhc3RlMCgiY2hyIiwgY2hyKSkgJT4lCiAgcmVhZHI6OndyaXRlX3RzdihmaWxlLnBhdGgocmVmX2RpciwgImdlbmNvZGUudjE5LmJhc2ljLmV4b21lLnRzdiIpLAogICAgY29sX25hbWVzID0gRkFMU0UKICApCmBgYAoKQWZ0ZXIgdXNpbmcgW1VDU0MgQkVEIGxpZnRvdmVyXShodHRwczovL2dlbm9tZS51Y3NjLmVkdS9jZ2ktYmluL2hnTGlmdE92ZXIpIHRvIGNvbnZlcnQgCmZyb20gdGhlIFRhcmdldCBCRUQgcmVnaW9ucyBmb3IgVENHQSBkYXRhIGZyb20gaGcxOSB0byBoZzM4IChXaGF0IHRoZSBQQlRBIGRhdGEgaXMgdXNpbmcpLgoKYGBge3J9CnRjZ2FfbGlmdF9iZWQgPC0gcmVhZHI6OnJlYWRfdHN2KGZpbGUucGF0aCgKICByZWZfZGlyLAogICJoZzM4X2xpZnRvdmVyX2dlbm9tZV9nZW5jb2RlLnYxOS5iYXNpYy5leG9tZS5iZWQiCiksCmNvbF9uYW1lcyA9IGMoImNociIsICJzdGFydCIsICJlbmQiKQopICU+JQogIGRwbHlyOjptdXRhdGUoY2hyID0gc3RyaW5ncjo6d29yZChjaHIsIHNlcCA9ICJfIiwgMSkpCgojIE1ha2UgR1JhbmdlcyBmb3IgQ05WIGRhdGEKdGNnYV9saWZ0X2dyYW5nZXMgPC0gR2Vub21pY1Jhbmdlczo6R1JhbmdlcygKICBzZXFuYW1lcyA9IHRjZ2FfbGlmdF9iZWQkY2hyLAogIHJhbmdlcyA9IElSYW5nZXM6OklSYW5nZXMoCiAgICBzdGFydCA9IHRjZ2FfbGlmdF9iZWQkc3RhcnQsCiAgICBlbmQgPSB0Y2dhX2xpZnRfYmVkJGVuZAogICkKKQoKIyBSZWR1Y2UgdGhpcyB0byBpdCdzIGVzc2VudGlhbCByYW5nZXMKdGNnYV9saWZ0X2dyYW5nZXMgPC0gR2Vub21pY1Jhbmdlczo6cmVkdWNlKHRjZ2FfbGlmdF9ncmFuZ2VzKQpgYGAKCk1ha2UgYSBUQ0dBIEJFRCBHZW5vbWljUmFuZ2VzLiAKCmBgYHtyfQojIE1ha2UgR1JhbmdlcyBmb3IgQ05WIGRhdGEKdGNnYV9ncmFuZ2VzIDwtIEdlbm9taWNSYW5nZXM6OkdSYW5nZXMoCiAgc2VxbmFtZXMgPSB0Y2dhX2JlZCRjaHIsCiAgcmFuZ2VzID0gSVJhbmdlczo6SVJhbmdlcygKICAgIHN0YXJ0ID0gdGNnYV9iZWQkc3RhcnQsCiAgICBlbmQgPSB0Y2dhX2JlZCRlbmQKICApCikKCiMgUmVkdWNlIHRoaXMgdG8gaXQncyBlc3NlbnRpYWwgcmFuZ2VzCnRjZ2FfZ3JhbmdlcyA8LSBHZW5vbWljUmFuZ2VzOjpyZWR1Y2UodGNnYV9ncmFuZ2VzKQpgYGAKCkZvcm1hdCB0aGUgUEJUQSBXWFMgZGF0YSBhcyBhIEdSYW5nZXMgb2JqZWN0LiAKCmBgYHtyfQojIHBidGFfYmVkIDwtIHJlYWRyOjpyZWFkX3RzdihmaWxlLnBhdGgoc2NyYXRjaF9kaXIsICJpbnRlcnNlY3RfY2RzX1dYUy5iZWQiKSwKcGJ0YV9iZWQgPC0gcmVhZHI6OnJlYWRfdHN2KGZpbGUucGF0aChkYXRhX2RpciwgIldYUy5oZzM4LjEwMGJwX3BhZGRlZC5iZWQiKSwKICBjb2xfbmFtZXMgPSBjKCJjaHIiLCAic3RhcnQiLCAiZW5kIikKKSAlPiUKICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShjaHIpKQoKIyBNYWtlIEdSYW5nZXMgZm9yIENOViBkYXRhCnBidGFfZ3JhbmdlcyA8LSBHZW5vbWljUmFuZ2VzOjpHUmFuZ2VzKAogIHNlcW5hbWVzID0gcGJ0YV9iZWQkY2hyLAogIHJhbmdlcyA9IElSYW5nZXM6OklSYW5nZXMoCiAgICBzdGFydCA9IHBidGFfYmVkJHN0YXJ0LAogICAgZW5kID0gcGJ0YV9iZWQkZW5kCiAgKQopCgojIFJlZHVjZSB0aGlzIHRvIGl0J3MgZXNzZW50aWFsIHJhbmdlcwpwYnRhX2dyYW5nZXMgPC0gR2Vub21pY1Jhbmdlczo6cmVkdWNlKHBidGFfZ3JhbmdlcykKYGBgCgpSZWFkIGluIHRoZSBjb2Rpbmcgc2VxdWVuY2UgcmVnaW9ucyBmaWxlLiAKCmBgYHtyfQpjZHNfYmVkIDwtIHJlYWRyOjpyZWFkX3RzdihmaWxlLnBhdGgoCiAgc2NyYXRjaF9kaXIsCiAgImdlbmNvZGUudjI3LnByaW1hcnlfYXNzZW1ibHkuYW5ub3RhdGlvbi5iZWQiCiksCmNvbF9uYW1lcyA9IGMoImNociIsICJzdGFydCIsICJlbmQiKQopICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGNocikpCgojIE1ha2UgR1JhbmdlcwpjZHNfZ3JhbmdlcyA8LSBHZW5vbWljUmFuZ2VzOjpHUmFuZ2VzKAogIHNlcW5hbWVzID0gY2RzX2JlZCRjaHIsCiAgcmFuZ2VzID0gSVJhbmdlczo6SVJhbmdlcygKICAgIHN0YXJ0ID0gY2RzX2JlZCRzdGFydCwKICAgIGVuZCA9IGNkc19iZWQkZW5kCiAgKQopCgojIFJlZHVjZSB0aGlzIHRvIGl0J3MgZXNzZW50aWFsIHJhbmdlcwpjZHNfZ3JhbmdlcyA8LSBHZW5vbWljUmFuZ2VzOjpyZWR1Y2UoY2RzX2dyYW5nZXMpCmBgYAoKV2UgYWxzbyBuZWVkIHRvIHNlZSBob3cgdGhpcyB0cmFuc2xhdGVzIHRvIENEUyByZWdpb25zOgoKYGBge3J9CiMgRmluZCBDRFMgaW50ZXJzZWN0aW9uCnBidGFfY2RzX2dyYW5nZXMgPC0gR2Vub21pY1Jhbmdlczo6aW50ZXJzZWN0KHBidGFfZ3JhbmdlcywgY2RzX2dyYW5nZXMpCnRjZ2FfY2RzX2dyYW5nZXMgPC0gR2Vub21pY1Jhbmdlczo6aW50ZXJzZWN0KHRjZ2FfZ3JhbmdlcywgY2RzX2dyYW5nZXMpCnRjZ2FfbGlmdF9jZHNfZ3JhbmdlcyA8LSBHZW5vbWljUmFuZ2VzOjppbnRlcnNlY3QodGNnYV9saWZ0X2dyYW5nZXMsIGNkc19ncmFuZ2VzKQpgYGAKCiMjIE1ha2UgVmVubiBkaWFncmFtcyBvZiB0aGVzZSBvdmVybGFwcwoKRmluZCBvdmVybGFwIGJldHdlZW4gdGhlIFRDR0EgKG5vbi1saWZ0b3ZlcikgYW5kIFBCVEEgZGF0YS4gCgpgYGB7cn0KYmVkX292ZXJsYXAocGJ0YV9ncmFuZ2VzLAogIHRjZ2FfZ3JhbmdlcywKICBwbG90X25hbWUgPSAiUEJUQSB2cyBUQ0dBIFdYUyB0YXJnZXQgQkVEIiwKICBuYW1lXzEgPSAiUEJUQSIsCiAgbmFtZV8yID0gIlRDR0EiCikKYGBgCgpGaW5kIG92ZXJsYXAgYmV0d2VlbiB0aGUgbGlmdG92ZXIgVENHQSB0YXJnZXQgQkVEIHJlZ2lvbiBhbmQgUEJUQSBkYXRhLiAKCmBgYHtyfQpiZWRfb3ZlcmxhcChwYnRhX2dyYW5nZXMsCiAgdGNnYV9saWZ0X2dyYW5nZXMsCiAgcGxvdF9uYW1lID0gIlBCVEEgdnMgVENHQSBXWFMgbGlmdG92ZXIgdGFyZ2V0IEJFRCIsCiAgbmFtZV8xID0gIlBCVEEiLAogIG5hbWVfMiA9ICJUQ0dBIGxpZnRvdmVyIgopCmBgYAoKRmluZCBvdmVybGFwIGJldHdlZW4gY29kaW5nIHNlcXVlbmNlcyBvbmx5IG9mIHRoZSBsaWZ0b3ZlciBUQ0dBIHRhcmdldCBCRUQgcmVnaW9uIGFuZCBQQlRBIGRhdGEuIAoKYGBge3J9CmJlZF9vdmVybGFwKHBidGFfY2RzX2dyYW5nZXMsCiAgdGNnYV9saWZ0X2Nkc19ncmFuZ2VzLAogIHBsb3RfbmFtZSA9ICJQQlRBIHZzIFRDR0EgV1hTIGxpZnRvdmVyIGNvZGluZyBzZXF1ZW5jZSB0YXJnZXQgQkVEIiwKICBuYW1lXzEgPSAiUEJUQSBDRFMiLAogIG5hbWVfMiA9ICJUQ0dBIGxpZnQgQ0RTIgopCmBgYAoKRmluZCBvdmVybGFwIGJldHdlZW4gY29kaW5nIHNlcXVlbmNlcyBvbmx5IG9mIHRoZSBUQ0dBIHRhcmdldCBCRUQgcmVnaW9uIGFuZCBQQlRBIGRhdGEuIAoKYGBge3J9CmJlZF9vdmVybGFwKHBidGFfY2RzX2dyYW5nZXMsCiAgdGNnYV9jZHNfZ3JhbmdlcywKICBwbG90X25hbWUgPSAiUEJUQSB2cyBUQ0dBIFdYUyBDb2Rpbmcgc2VxdWVuY2UgdGFyZ2V0IEJFRCIsCiAgbmFtZV8xID0gIlBCVEEgQ0RTIiwKICBuYW1lXzIgPSAiVENHQSBDRFMiCikKYGBgCgojIyBTZXNzaW9uIEluZm8KCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAo=