1 A fresh running of all proteomics tasks

I think I finally worked out all(most?) of the kinks in the processing of DIA data. Thus I want to have a fresh run of all the tasks required to interpret the results.

2 Annotation version: 20190801

2.1 Genome annotation input

2.1.2 Download from microbesonline

Apparently I queried the microbesonline too often and now I get an error whenever I try to use them, this disappoints me.

## The species being downloaded is: Mycobacterium tuberculosis H37Rv
## Downloading: http://www.microbesonline.org/cgi-bin/genomeInfo.cgi?tId=83332;export=tab

2.2 Getting ontology data

## The species being downloaded is: Mycobacterium tuberculosis H37Rv and is being downloaded as 83332.tab.

2.3 Some pattern matching

This little block is intended to seek out peptide sequences with the highly degenerate pattern: Y(E|D) with a varying number of amino acids between the Y and (E or D).

get_hits <- function(patterns, peptide_file, pct_limit=0.25) {
  pep_seq <- Biostrings::readAAStringSet(peptide_file)
  pep_lst <- as.data.frame(pep_seq)[["x"]]
  pos_df <- data.frame(stringsAsFactors=FALSE)
  pep_names <- names(pep_seq)
  rowname <- ""
  for (r in 1:length(pep_names)) {
    rowname <- pep_names[r]
    new_row <- vector()
    found_hits <- FALSE
    for (p in 1:length(patterns)) {
      pat <- patterns[[p]]
      pname <- names(patterns)[p]
      column <- gregexpr(pattern=pat, text=pep_lst)
      names(column) <- names(pep_seq)
      name <- names(column)[r]
      row <- column[[r]]
      len <- nchar(pep_lst[r])
      pct <- as.numeric(row) / len
      cdist <- len - as.numeric(row)
      pos_name <- glue::glue("pos_{pname}")
      num_name <- glue::glue("number_{pname}")
      nt_name <- glue::glue("nt_{pname}")
      ct_name <- glue::glue("ct_{pname}")
      pct_name <- glue::glue("pct_{pname}")
      pos_name <- glue::glue("pos_{pname}")
      ## An important caveat here:  There may be more than one value.
      new_row["rowname"] <- rowname
      number_hits <- length(as.numeric(row))
      if (as.numeric(row)[1] == -1) {
        number_hits <- "0"
      }
      new_row[num_name] <- number_hits
      new_row[pos_name] <- toString(as.numeric(row))
      if (new_row[pos_name] == "-1") {
        new_row[pos_name] <- "0"
      } else {
        found_hits <- TRUE
      }
      new_row["length"] <- len
      op <- options(warn=2)
      if (pct[1] < 0) {
        new_row[pct_name] <- "0"
      } else {
        new_row[pct_name] <- toString(pct)
      }
      options(op)
      nt_str <- ""
      ct_str <- ""
      max_pct <- 1 - pct_limit
      for (i in pct) {
        if (i < 0) {
          next
        }
        if (i < pct_limit) {
          nt_str <- paste0(nt_str, ", ", i)
        }
        if (i > max_pct) {
          ct_str <- paste0(ct_str, ", ", i)
        }
      }
      nt_str <- gsub(pattern="^\\, ", replacement="", x=nt_str)
      ct_str <- gsub(pattern="^\\, ", replacement="", x=ct_str)
      new_row[nt_name] <- nt_str
      new_row[ct_name] <- ct_str
    }
    if (isTRUE(found_hits)) {
      pos_df <- rbind(pos_df, new_row, stringsAsFactors=FALSE)
      colnames(pos_df) <- names(new_row)
    }
  } ## End for every gene
  rownames(pos_df) <- pos_df[["rowname"]]
  pos_df <- pos_df[-1, ]

  return(pos_df)
}

##patterns <- c("Y(E|D)", "Y.(E|D)", "Y..(E|D)", "Y...(E|D)", "Y....(E|D)", "Y.....(E|D)")
mtb_cds <- "reference/mtb_cds.fasta"
patterns <- c("Y..(E|D)", "Y...(E|D)")
names(patterns) <- c("two", "three")
yed_patterns <- get_hits(patterns, mtb_cds)
written <- write_xls(yed_patterns, excel="positions_by_patterns.xlsx")

2.6 Compare subset of interesting proteins vs. all

Najib and Volker requested a comparison of the distribution pattern hits of all proteins vs. the distribution in a specific subset of proteins. I don’t actually know the subset desired, so I will assume the

## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 083922869a37724ece10beed7b0bb758a179fdfb
## This is hpgltools commit: Thu Oct 17 11:43:00 2019 -0400: 083922869a37724ece10beed7b0bb758a179fdfb
## Saving to 01_annotation_20190801-v20190801.rda.xz
LS0tCnRpdGxlOiAiTS50dWJlcmN1bG9zaXMgMjAxOTA4MDEgcHJvdGVvbWljczogQ29sbGVjdGluZyBhbm5vdGF0aW9uIGRhdGEuIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGRmX3ByaW50OiBwYWdlZAogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgd2lkdGg6IDMwMAogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIHRvY19mbG9hdDogdHJ1ZQogIEJpb2NTdHlsZTo6aHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIHRvY19mbG9hdDogdHJ1ZQogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keSwgdGQgewogIGZvbnQtc2l6ZTogMTZweDsKfQpjb2RlLnJ7CiAgZm9udC1zaXplOiAxNnB4Owp9CnByZSB7CiBmb250LXNpemU6IDE2cHgKfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeSgiaHBnbHRvb2xzIikKdHQgPC0gZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHdpZHRoPTEyMCwKICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgZHBpPTk2KQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cz00LAogICAgICAgICAgICAgICAgICAgICAgIG1heC5wcmludD0xMjAsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWw9ImFsbG93IikKZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZT0xMCkpCnZlciA8LSAiMjAxOTA4MDEiCnByZXZpb3VzX2ZpbGUgPC0gImluZGV4LlJtZCIKCnRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lPXBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cHJldmlvdXNfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKSkpKQpybWRfZmlsZSA8LSBwYXN0ZTAoIjAxX2Fubm90YXRpb25fIiwgdmVyLCAiLlJtZCIpCmBgYAoKQSBmcmVzaCBydW5uaW5nIG9mIGFsbCBwcm90ZW9taWNzIHRhc2tzCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKSSB0aGluayBJIGZpbmFsbHkgd29ya2VkIG91dCBhbGwobW9zdD8pIG9mIHRoZSBraW5rcyBpbiB0aGUgcHJvY2Vzc2luZyBvZiBESUEgZGF0YS4KVGh1cyBJIHdhbnQgdG8gaGF2ZSBhIGZyZXNoIHJ1biBvZiBhbGwgdGhlIHRhc2tzIHJlcXVpcmVkIHRvIGludGVycHJldCB0aGUgcmVzdWx0cy4KCiMgQW5ub3RhdGlvbiB2ZXJzaW9uOiBgciB2ZXJgCgojIyBHZW5vbWUgYW5ub3RhdGlvbiBpbnB1dAoKIyMjIFJlYWQgYSBnZmYgZmlsZQoKSW4gY29udHJhc3QsIGl0IGlzIHBvc3NpYmxlIHRvIGxvYWQgbW9zdCBhbm5vdGF0aW9ucyBvZiBpbnRlcmVzdCBkaXJlY3RseSBmcm9tIHRoZSBnZmYgZmlsZXMgdXNlZCBpbgp0aGUgYWxpZ25tZW50cy4gIE1vcmUgaW4tZGVwdGggaW5mb3JtYXRpb24gZm9yIHRoZSBodW1hbiB0cmFuc2NyaXB0b21lIG1heSBiZSBleHRyYWN0ZWQgZnJvbSBiaW9tYXJ0LgoKYGBge3IgZ2Vub21lX2lucHV0fQojIyBUaGUgb2xkIHdheSBvZiBnZXR0aW5nIGdlbm9tZS9hbm5vdGF0aW9uIGRhdGEKbXRiX2dmZiA8LSAicmVmZXJlbmNlL215Y29iYWN0ZXJpdW1fdHViZXJjdWxvc2lzX2gzN3J2XzIuZ2ZmLmd6IgptdGJfZ2Vub21lIDwtICJyZWZlcmVuY2UvbXR1YmVyY3Vsb3Npc19oMzdydl9nZW5iYW5rLmZhc3RhIgptdGJfY2RzIDwtICJyZWZlcmVuY2UvbXRiX2Nkcy5mYXN0YSIKCm10Yl9hbm5vdGF0aW9ucyA8LSBzbShsb2FkX2dmZl9hbm5vdGF0aW9ucyhtdGJfZ2ZmLCB0eXBlPSJnZW5lIikpCmNvbG5hbWVzKG10Yl9hbm5vdGF0aW9ucykgPC0gZ3N1YihwYXR0ZXJuPSJcXC4iLCByZXBsYWNlbWVudD0iIiwgeD1jb2xuYW1lcyhtdGJfYW5ub3RhdGlvbnMpKQptdGJfYW5ub3RhdGlvbnNbWyJkZXNjcmlwdGlvbiJdXSA8LSBnc3ViKHBhdHRlcm49IlxcKyIsIHJlcGxhY2VtZW50PSIgIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4PW10Yl9hbm5vdGF0aW9uc1tbImRlc2NyaXB0aW9uIl1dKQptdGJfYW5ub3RhdGlvbnNbWyJmdW5jdGlvbiJdXSA8LSBnc3ViKHBhdHRlcm49IlxcKyIsIHJlcGxhY2VtZW50PSIgIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4PW10Yl9hbm5vdGF0aW9uc1tbImZ1bmN0aW9uIl1dKQpyb3duYW1lcyhtdGJfYW5ub3RhdGlvbnMpIDwtIG10Yl9hbm5vdGF0aW9uc1tbIklEIl1dCmBgYAoKIyMjIERvd25sb2FkIGZyb20gbWljcm9iZXNvbmxpbmUKCkFwcGFyZW50bHkgSSBxdWVyaWVkIHRoZSBtaWNyb2Jlc29ubGluZSB0b28gb2Z0ZW4gYW5kIG5vdyBJIGdldCBhbiBlcnJvcgp3aGVuZXZlciBJIHRyeSB0byB1c2UgdGhlbSwgdGhpcyBkaXNhcHBvaW50cyBtZS4KCmBgYHtyIGdlbmJhbmt9CiMjIEkgbWFkZSBhIG5pZnR5IGZ1bmN0aW9uIHRvIGRvIHRoaXMgc3R1ZmY6IGxvYWRfdW5pcHJvdHdzX2Fubm90YXRpb25zKCkuCiMjIEl0IGlzIHNsb3csIHRob3VnaC4KbXRiX21pY3JvYmVzIDwtIGxvYWRfbWljcm9iZXNvbmxpbmVfYW5ub3RhdGlvbnMoaWQ9ODMzMzIpCiMjIG10Yl91bmlwcm90X2Fubm90IDwtIGxvYWRfdW5pcHJvdHdzX2Fubm90YXRpb25zKCkKbXRiX3VuaXByb3RfYW5ub3QgPC0gc20obG9hZF91bmlwcm90X2Fubm90YXRpb25zKGZpbGU9InJlZmVyZW5jZS91bmlwcm90XzNBVVAwMDAwMDE1ODQudHh0Lmd6IikpCmBgYAoKIyMgR2V0dGluZyBvbnRvbG9neSBkYXRhCgpgYGB7ciBvbnRvbG9neX0KbXRiX2dvIDwtIGxvYWRfbWljcm9iZXNvbmxpbmVfZ28oaWQ9ODMzMzIpCmBgYAoKIyMgU29tZSBwYXR0ZXJuIG1hdGNoaW5nCgpUaGlzIGxpdHRsZSBibG9jayBpcyBpbnRlbmRlZCB0byBzZWVrIG91dCBwZXB0aWRlIHNlcXVlbmNlcyB3aXRoIHRoZSBoaWdobHkgZGVnZW5lcmF0ZSBwYXR0ZXJuOgpZKEV8RCkgd2l0aCBhIHZhcnlpbmcgbnVtYmVyIG9mIGFtaW5vIGFjaWRzIGJldHdlZW4gdGhlIFkgYW5kIChFIG9yIEQpLgoKYGBge3IgcGF0dGVybiwgZXZhbD1GQUxTRX0KZ2V0X2hpdHMgPC0gZnVuY3Rpb24ocGF0dGVybnMsIHBlcHRpZGVfZmlsZSwgcGN0X2xpbWl0PTAuMjUpIHsKICBwZXBfc2VxIDwtIEJpb3N0cmluZ3M6OnJlYWRBQVN0cmluZ1NldChwZXB0aWRlX2ZpbGUpCiAgcGVwX2xzdCA8LSBhcy5kYXRhLmZyYW1lKHBlcF9zZXEpW1sieCJdXQogIHBvc19kZiA8LSBkYXRhLmZyYW1lKHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCiAgcGVwX25hbWVzIDwtIG5hbWVzKHBlcF9zZXEpCiAgcm93bmFtZSA8LSAiIgogIGZvciAociBpbiAxOmxlbmd0aChwZXBfbmFtZXMpKSB7CiAgICByb3duYW1lIDwtIHBlcF9uYW1lc1tyXQogICAgbmV3X3JvdyA8LSB2ZWN0b3IoKQogICAgZm91bmRfaGl0cyA8LSBGQUxTRQogICAgZm9yIChwIGluIDE6bGVuZ3RoKHBhdHRlcm5zKSkgewogICAgICBwYXQgPC0gcGF0dGVybnNbW3BdXQogICAgICBwbmFtZSA8LSBuYW1lcyhwYXR0ZXJucylbcF0KICAgICAgY29sdW1uIDwtIGdyZWdleHByKHBhdHRlcm49cGF0LCB0ZXh0PXBlcF9sc3QpCiAgICAgIG5hbWVzKGNvbHVtbikgPC0gbmFtZXMocGVwX3NlcSkKICAgICAgbmFtZSA8LSBuYW1lcyhjb2x1bW4pW3JdCiAgICAgIHJvdyA8LSBjb2x1bW5bW3JdXQogICAgICBsZW4gPC0gbmNoYXIocGVwX2xzdFtyXSkKICAgICAgcGN0IDwtIGFzLm51bWVyaWMocm93KSAvIGxlbgogICAgICBjZGlzdCA8LSBsZW4gLSBhcy5udW1lcmljKHJvdykKICAgICAgcG9zX25hbWUgPC0gZ2x1ZTo6Z2x1ZSgicG9zX3twbmFtZX0iKQogICAgICBudW1fbmFtZSA8LSBnbHVlOjpnbHVlKCJudW1iZXJfe3BuYW1lfSIpCiAgICAgIG50X25hbWUgPC0gZ2x1ZTo6Z2x1ZSgibnRfe3BuYW1lfSIpCiAgICAgIGN0X25hbWUgPC0gZ2x1ZTo6Z2x1ZSgiY3Rfe3BuYW1lfSIpCiAgICAgIHBjdF9uYW1lIDwtIGdsdWU6OmdsdWUoInBjdF97cG5hbWV9IikKICAgICAgcG9zX25hbWUgPC0gZ2x1ZTo6Z2x1ZSgicG9zX3twbmFtZX0iKQogICAgICAjIyBBbiBpbXBvcnRhbnQgY2F2ZWF0IGhlcmU6ICBUaGVyZSBtYXkgYmUgbW9yZSB0aGFuIG9uZSB2YWx1ZS4KICAgICAgbmV3X3Jvd1sicm93bmFtZSJdIDwtIHJvd25hbWUKICAgICAgbnVtYmVyX2hpdHMgPC0gbGVuZ3RoKGFzLm51bWVyaWMocm93KSkKICAgICAgaWYgKGFzLm51bWVyaWMocm93KVsxXSA9PSAtMSkgewogICAgICAgIG51bWJlcl9oaXRzIDwtICIwIgogICAgICB9CiAgICAgIG5ld19yb3dbbnVtX25hbWVdIDwtIG51bWJlcl9oaXRzCiAgICAgIG5ld19yb3dbcG9zX25hbWVdIDwtIHRvU3RyaW5nKGFzLm51bWVyaWMocm93KSkKICAgICAgaWYgKG5ld19yb3dbcG9zX25hbWVdID09ICItMSIpIHsKICAgICAgICBuZXdfcm93W3Bvc19uYW1lXSA8LSAiMCIKICAgICAgfSBlbHNlIHsKICAgICAgICBmb3VuZF9oaXRzIDwtIFRSVUUKICAgICAgfQogICAgICBuZXdfcm93WyJsZW5ndGgiXSA8LSBsZW4KICAgICAgb3AgPC0gb3B0aW9ucyh3YXJuPTIpCiAgICAgIGlmIChwY3RbMV0gPCAwKSB7CiAgICAgICAgbmV3X3Jvd1twY3RfbmFtZV0gPC0gIjAiCiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV3X3Jvd1twY3RfbmFtZV0gPC0gdG9TdHJpbmcocGN0KQogICAgICB9CiAgICAgIG9wdGlvbnMob3ApCiAgICAgIG50X3N0ciA8LSAiIgogICAgICBjdF9zdHIgPC0gIiIKICAgICAgbWF4X3BjdCA8LSAxIC0gcGN0X2xpbWl0CiAgICAgIGZvciAoaSBpbiBwY3QpIHsKICAgICAgICBpZiAoaSA8IDApIHsKICAgICAgICAgIG5leHQKICAgICAgICB9CiAgICAgICAgaWYgKGkgPCBwY3RfbGltaXQpIHsKICAgICAgICAgIG50X3N0ciA8LSBwYXN0ZTAobnRfc3RyLCAiLCAiLCBpKQogICAgICAgIH0KICAgICAgICBpZiAoaSA+IG1heF9wY3QpIHsKICAgICAgICAgIGN0X3N0ciA8LSBwYXN0ZTAoY3Rfc3RyLCAiLCAiLCBpKQogICAgICAgIH0KICAgICAgfQogICAgICBudF9zdHIgPC0gZ3N1YihwYXR0ZXJuPSJeXFwsICIsIHJlcGxhY2VtZW50PSIiLCB4PW50X3N0cikKICAgICAgY3Rfc3RyIDwtIGdzdWIocGF0dGVybj0iXlxcLCAiLCByZXBsYWNlbWVudD0iIiwgeD1jdF9zdHIpCiAgICAgIG5ld19yb3dbbnRfbmFtZV0gPC0gbnRfc3RyCiAgICAgIG5ld19yb3dbY3RfbmFtZV0gPC0gY3Rfc3RyCiAgICB9CiAgICBpZiAoaXNUUlVFKGZvdW5kX2hpdHMpKSB7CiAgICAgIHBvc19kZiA8LSByYmluZChwb3NfZGYsIG5ld19yb3csIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCiAgICAgIGNvbG5hbWVzKHBvc19kZikgPC0gbmFtZXMobmV3X3JvdykKICAgIH0KICB9ICMjIEVuZCBmb3IgZXZlcnkgZ2VuZQogIHJvd25hbWVzKHBvc19kZikgPC0gcG9zX2RmW1sicm93bmFtZSJdXQogIHBvc19kZiA8LSBwb3NfZGZbLTEsIF0KCiAgcmV0dXJuKHBvc19kZikKfQoKIyNwYXR0ZXJucyA8LSBjKCJZKEV8RCkiLCAiWS4oRXxEKSIsICJZLi4oRXxEKSIsICJZLi4uKEV8RCkiLCAiWS4uLi4oRXxEKSIsICJZLi4uLi4oRXxEKSIpCm10Yl9jZHMgPC0gInJlZmVyZW5jZS9tdGJfY2RzLmZhc3RhIgpwYXR0ZXJucyA8LSBjKCJZLi4oRXxEKSIsICJZLi4uKEV8RCkiKQpuYW1lcyhwYXR0ZXJucykgPC0gYygidHdvIiwgInRocmVlIikKeWVkX3BhdHRlcm5zIDwtIGdldF9oaXRzKHBhdHRlcm5zLCBtdGJfY2RzKQp3cml0dGVuIDwtIHdyaXRlX3hscyh5ZWRfcGF0dGVybnMsIGV4Y2VsPSJwb3NpdGlvbnNfYnlfcGF0dGVybnMueGxzeCIpCmBgYAoKIyMgUmFuZG9tIHF1ZXJ5IGZyb20gVm9sa2VyCgpXaGF0IHByb3RlaW5zIGRvIG5vdCBoYXZlIGdseWNpbmU/CgpHbHljaW5lIDogR2x5IDogRwoKYGBge3IgZ2x5Y2luZSwgZXZhbD1GQUxTRX0KcGVwX3NlcSA8LSBCaW9zdHJpbmdzOjpyZWFkQUFTdHJpbmdTZXQobXRiX2NkcykKcGVwX2xzdCA8LSBhcy5kYXRhLmZyYW1lKHBlcF9zZXEpW1sieCJdXQpwb3NfZGYgPC0gZGF0YS5mcmFtZShzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpwZXBfbmFtZXMgPC0gbmFtZXMocGVwX3NlcSkKcGVwX2RmIDwtIGFzLmRhdGEuZnJhbWUocGVwX3NlcSkKZ2x5Y2luZV9oaXRzIDwtIGdyZXBsKHBhdHRlcm49IkciLCB4PXBlcF9kZltbIngiXV0pCnJvd25hbWVzKHBlcF9kZilbIWdseWNpbmVfaGl0c10KYGBgCgojIyBBZGQgdGhlIFlFRCBwYXR0ZXJucyB0byB0aGUgYW5ub3RhdGlvbiBkYXRhCgpgYGB7ciB5ZWRfYWRkZWQsIGV2YWw9RkFMU0V9Cm10Yl9hbm5vdGF0aW9ucyA8LSBtZXJnZShtdGJfYW5ub3RhdGlvbnMsIHllZF9wYXR0ZXJucywgYnk9InJvdy5uYW1lcyIsIGFsbC54PVRSVUUpCnJvd25hbWVzKG10Yl9hbm5vdGF0aW9ucykgPC0gbXRiX2Fubm90YXRpb25zW1siUm93Lm5hbWVzIl1dCm10Yl9hbm5vdGF0aW9ucyA8LSBtdGJfYW5ub3RhdGlvbnNbLTEsIF0KYGBgCgojIyBDb21wYXJlIHN1YnNldCBvZiBpbnRlcmVzdGluZyBwcm90ZWlucyB2cy4gYWxsCgpOYWppYiBhbmQgVm9sa2VyIHJlcXVlc3RlZCBhIGNvbXBhcmlzb24gb2YgdGhlIGRpc3RyaWJ1dGlvbiBwYXR0ZXJuIGhpdHMgb2YgYWxsCnByb3RlaW5zIHZzLiB0aGUgZGlzdHJpYnV0aW9uIGluIGEgc3BlY2lmaWMgc3Vic2V0IG9mIHByb3RlaW5zLiAgSSBkb24ndAphY3R1YWxseSBrbm93IHRoZSBzdWJzZXQgZGVzaXJlZCwgc28gSSB3aWxsIGFzc3VtZSB0aGUKCmBgYHtyIHBlX3Rlc3RpbmcsIGV2YWw9RkFMU0V9CnBlX2lkcyA8LSByZWFkLnRhYmxlKCJyZWZlcmVuY2UvYW5ub3RhdGVkX3BlX2dlbmVzLnR4dCIpW1siVjEiXV0KCnllZF9wZSA8LSB5ZWRfcGF0dGVybnNbcGVfaWRzLCBdCgphbGxfbnVtYmVycyA8LSBhcy5udW1lcmljKHllZF9wYXR0ZXJuc1tbIm51bWJlcl90d28iXV0pCnBlX251bWJlcnMgPC0gYXMubnVtZXJpYyh5ZWRfcGVbWyJudW1iZXJfdHdvIl1dKQoKYWxsdGhyZWVfbnVtYmVycyA8LSBhcy5udW1lcmljKHllZF9wYXR0ZXJuc1tbIm51bWJlcl90aHJlZSJdXSkKcGV0aHJlZV9udW1iZXJzIDwtIGFzLm51bWVyaWMoeWVkX3BlW1sibnVtYmVyX3RocmVlIl1dKQoKYWxsX3BjdCA8LSB5ZWRfcGF0dGVybnNbWyJwY3RfdHdvIl1dCnBlX3BjdCA8LSB5ZWRfcGVbWyJwY3RfdHdvIl1dCmFsbF9wb3NpdGlvbnMgPC0geWVkX3BhdHRlcm5zW1sicG9zX3R3byJdXQpwZV9wb3NpdGlvbnMgPC0geWVkX3BlW1sicG9zX3R3byJdXQoKc2FtcGxlZF9udW1iZXJzX3R3byA8LSBzYW1wbGUoeD1hbGxfbnVtYmVycywgc2l6ZT0xMDAwLCByZXBsYWNlPVRSVUUpCnN1bW1hcnkoc2FtcGxlZF9udW1iZXJzX3R3bykKcGVfbnVtYmVyc1tpcy5uYShwZV9udW1iZXJzKV0gPC0gMApzdW1tYXJ5KHBlX251bWJlcnMpCgpzYW1wbGVkX251bWJlcnNfdGhyZWUgPC0gc2FtcGxlKHg9YWxsdGhyZWVfbnVtYmVycywgc2l6ZT0xMDAwLCByZXBsYWNlPVRSVUUpCnN1bW1hcnkoc2FtcGxlZF9udW1iZXJzX3RocmVlKQpwZXRocmVlX251bWJlcnNbaXMubmEocGV0aHJlZV9udW1iZXJzKV0gPC0gMApzdW1tYXJ5KHBldGhyZWVfbnVtYmVycykKYGBgCgpgYGB7ciBzYXZlbWV9CmlmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewogIHBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCiAgbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCiAgdGhpc19zYXZlIDwtIHBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cm1kX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikKICBtZXNzYWdlKHBhc3RlMCgiU2F2aW5nIHRvICIsIHRoaXNfc2F2ZSkpCiAgdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT10aGlzX3NhdmUpKQp9CmBgYAo=