library(plyr)
library(dplyr)
library(data.table)
library(DT)
example_annotation_file <- snakemake@input$example_annotations
example_msa_file <- snakemake@input$example_msa

Introduction

Definitions

  • Locus: sequence position (e.g. nucleotide 129)
  • V(D)J recombination:
  • Somatic hypermutation (SHM): Mutational process occurring within the germinal centers of secondary lymphoid organs acting primarily on BCR sequences
  • Clonal family: A group/cluster of B-cells/BCR sequences related by somatic hypermutation

Parent project: ITH-Ovary

Somatic hypermutation generates sequence diversity in B-cell families

Problem

Description

Examples

Data

Example input data for a clonal family:

example_annotations <- fread(example_annotation_file)
example_annotations_info <- subset(example_annotations, select = c(id, readcount, 
    site, mut_freqs, indel_reversed_seqs))

datatable(example_annotations_info, extensions = "Buttons", options = list(pageLength = 5, 
    scrollX = TRUE, dom = "Bfrtip", buttons = c("copy", "csv", "excel", "pdf", 
        "print")))

Note that all sequences are the same length (indels have been removed).

Sequence alignment

There is considerable diversification occurring within clonal families. Evidence of this in the MSA linked includes:

  • Lack of clear haplotypes (sequence positions that appear to ‘evolve together’)
  • Phylogenetic patterns difficult to discern from a cursory glance at the MSA
  • For each locus, mutated variant(s) are present at low frequency

Example MSA

Reading resources

Continuous time Markov chains in phylogenetics (high-ish level, sequence evolution models):

Basic (uniform) birth-death process:

Branch-specific birth-death process:

Literature

The concept behind this model is similar to Immunitree – see the Supplementals of the linked paper. However, the Immunitree model makes several unrealistic assumptions:

  • Uniform birth-death process
  • Sequence evolution occurs as a discrete process, overlaid onto the continuous-time Markov chain of the BDP
  • Sequence evolution matrix assumes that the transition rate from any nucleotide to another (different) nucleotide is equal (known: transversion/transition rates are different in general, in BCRs specific codons/motifs are subject to much higher evolutionary rates)
  • ‘Observed ancestor bias’: clearer to explain this in person
  • Sequence error model does not incorporate read quality information

Model description

Generative process:

  • “Cells” are created by a branch-specific birth-death process, rooted at a known ancestral sequence
  • Sequences evolve over the branches of the BDP according to a CTMC, governed by a general time reversible (GTR) transition matrix
  • Reads are produced by sequences at the tips (this could be modified to allow internal nodes to produce sequences, requires additional modeling), according to a sequence error model that incorporates read qualities
LS0tCnRpdGxlOiAiQkNSIHBoeWxvZ2VuZXRpY3MiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6IHRydWUKcGFyYW1zOgogIHJtZDogImJjcl9waHlsb19leGFtcGxlcy5SbWQiCi0tLQogICAgICAgICAgICAgICAgICAgICAgICBgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMjIyMjIyMjIFNuYWtlbWFrZSBoZWFkZXIgIyMjIyMjIyMKbGlicmFyeShtZXRob2RzKQpTbmFrZW1ha2UgPC0gc2V0Q2xhc3MoCiAgICAiU25ha2VtYWtlIiwKICAgIHNsb3RzID0gYygKICAgICAgICBpbnB1dCA9ICJsaXN0IiwKICAgICAgICBvdXRwdXQgPSAibGlzdCIsCiAgICAgICAgcGFyYW1zID0gImxpc3QiLAogICAgICAgIHdpbGRjYXJkcyA9ICJsaXN0IiwKICAgICAgICB0aHJlYWRzID0gIm51bWVyaWMiLAogICAgICAgIGxvZyA9ICJsaXN0IiwKICAgICAgICByZXNvdXJjZXMgPSAibGlzdCIsCiAgICAgICAgY29uZmlnID0gImxpc3QiLAogICAgICAgIHJ1bGUgPSAiY2hhcmFjdGVyIgogICAgKQopCnNuYWtlbWFrZSA8LSBTbmFrZW1ha2UoCiAgICBpbnB1dCA9IGxpc3QoJ1JtZC9iY3JfcGh5bG9fZXhhbXBsZXMuUm1kJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3dlYi9yZXNvdXJjZXMvbXNhLmh0bWwnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL2FuYWx5c2lzL1JtZC9fc2l0ZS55bWwnLCAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMTMvZmluYWxfcGFydGl0aW9ucy9pdGgyXzIvY2x1c3Q5L2Fubm90YXRpb25zX2ZsYWdnZWQudHN2JywgIm5vdGVib29rIiA9ICdSbWQvYmNyX3BoeWxvX2V4YW1wbGVzLlJtZCcsICJtc2FfcGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvd2ViL3Jlc291cmNlcy9tc2EuaHRtbCcsICJzaXRlX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9hbmFseXNpcy9SbWQvX3NpdGUueW1sJywgImV4YW1wbGVfYW5ub3RhdGlvbnMiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2lncGFydGl0aW9uL3J1bjEzL2ZpbmFsX3BhcnRpdGlvbnMvaXRoMl8yL2NsdXN0OS9hbm5vdGF0aW9uc19mbGFnZ2VkLnRzdicpLAogICAgb3V0cHV0ID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvd2ViL2Jjcl9waHlsb19leGFtcGxlcy5uYi5odG1sJyksCiAgICBwYXJhbXMgPSBsaXN0KCdpdGhpLWFuYWx5c2lzLWJjcnBoeWxvLWV4YW1wbGVzJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJywgIm5hbWUiID0gJ2l0aGktYW5hbHlzaXMtYmNycGh5bG8tZXhhbXBsZXMnLCAiZGIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJyksCiAgICB3aWxkY2FyZHMgPSBsaXN0KCksCiAgICB0aHJlYWRzID0gMSwKICAgIGxvZyA9IGxpc3QoJy9zaGFobGFiL2FsemhhbmcvY2x1c3R0bXAvcGFwZXJhbmFseXNpczIvYmNycGh5bG9fZXhhbXBsZXMubG9nJyksCiAgICByZXNvdXJjZXMgPSBsaXN0KCksCiAgICBjb25maWcgPSBsaXN0KCJpY2djX21vbGVjdWxhcl9zdWJ0eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvaWNnY19wcmltYXJ5X3R1bW91cl9zdWJ0eXBlcy50c3YnLCAidGNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL1RSQi9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAidGlsc19mb3JfY2x1c3RlciIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAiY2xvbmVfdHJlZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvdHJlZV9kYXRhLnRzdicsICJtbWN0bV9zYW1wbGVfc2lncGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktc2FtcGxlL3Bsb3RzL2l0aC1ieS1zYW1wbGVfc252LXN2X3NpZ3NfbXVsdGlwYW5lbC5wZGYnLCAiaWhjX3J1bjIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2loYy9jZDc5Y2QxMzhjZDY4L3ZhbGlkYXRlZF9zdGF0c193ZWlnaHRlZC5yZGF0YScsICJtbWN0bV9zYW1wbGVfcmVzdWx0X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktc2FtcGxlL291dHB1dCcsICJuY2x1c3RzIiA9IDMsICJpbW10eXBlcl9sZW5ndGhzIiA9ICcxMSAxMiAxMyAxNCAxNSAxNiAxNyAxOCcsICJqX2RpY3Rpb25hcnkiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9zdWJwcm9qZWN0cy9pbW10eXBlci9tZXRhZGF0YS9pbWd0L0hvbW9fc2FwaWVuc19UUkJKLmZhc3RhJywgImtub3duX3N1YnR5cGVzX21lcmdlZCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9rbm93bl9zdWJ0eXBlc19tZXJnZWQudHN2JywgImltbXVuZV92YXJpYWJpbGl0eV9ub3RlYm9vayIgPSAnUm1kL2ltbXVuZV92YXJpYWJpbGl0eS5SbWQnLCAidGNyX2Nsb25vdHlwZXMiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9jbG9ub3R5cGVzL1RSQl9jbG9ub3R5cGVzX2ZpbHRlcmVkLnR4dCcsICJuZW9lZGl0aW5nX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbmVvZWRpdGluZy9ydW40JywgImljZ2Nfc3BlY2ltZW5fZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0Mvc3BlY2ltZW4udHN2JywgImZpZ3VyZV9nYWxsZXJ5X25vdGVib29rIiA9ICdSbWQvZmlndXJlcy5SbWQnLCAidGFibGVfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMicsICJpdGhfc3RhdHNfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaXRoL2NvbXBsZXRlL2Nsb25hbF9tZWFzdXJlcy50c3YnLCAibW1jdG1fcGF0aWVudF9hZF9zaWdwbG90IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1wYXRpZW50LWFuY2VzdHJ5L3Bsb3RzL2l0aC1ieS1wYXRpZW50LWFuY2VzdHJ5X3Nudi1zdl9zaWdzX211bHRpcGFuZWwucGRmJywgInBoZW5vdHlwZV90aHJlc2hvbGQiID0gMC44NSwgInRjZ2Ffb3ZfYW5ub3RhdGlvbnMiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9UQ0dBL3RjZ2Ffb3ZfYW5ub3RhdGlvbl9zdXAxMy50eHQnLCAiUE5HX1FVQUxJVFkiID0gMzAwLCAidmFyaWFiaWxpdHlfdHlwZSIgPSAnc3RhYmlsaXplJywgIm1tY3RtX2ZpbmFsX3BhdGllbnRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1wYXRpZW50X3dpdGgtb3YnLCAiaXRoX3N0YXRpc3RpY3Nfbm90ZWJvb2siID0gJ1JtZC9pdGhfc3RhdGlzdGljcy5SbWQnLCAibmVvYW50aWdlbl9lZGl0aW5nX25vdGVib29rIiA9ICdSbWQvaW1tdW5vZWRpdGluZy5SbWQnLCAidl9kaWN0aW9uYXJ5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvc3VicHJvamVjdHMvaW1tdHlwZXIvbWV0YWRhdGEvaW1ndC9Ib21vX3NhcGllbnNfVFJCVi5mYXN0YScsICJQTkdfREVOU0lUWSIgPSAzMDAsICJtbWN0bV9maW5hbF9wYXRpZW50X3NpZ3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXBhdGllbnRfd2l0aC1vdi9wbG90cy9pdGgtYnktcGF0aWVudF9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJsb2dkaXIiID0gJy9zaGFobGFiL2FsemhhbmcvY2x1c3R0bXAvcGFwZXJhbmFseXNpczInLCAibW9sc3VidHlwZV9ub3RlYm9vayIgPSAnUm1kL21vbGVjdWxhcl9zdWJ0eXBlcy5SbWQnLCAidGNnYV9leHByX21hdHJpeCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL1RDR0EvZXhwcl9tYXRyaXhfbm9ybWFsaXplX3N0YW5kYXJkaXplX25vZHVwbGljYXRlcy50c3YnLCAic2l0ZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvYW5hbHlzaXMvUm1kL19zaXRlLnltbCcsICJjbG9uYWxfc2FtcGxlcnMiID0gYygnSE1DJywgJ05VVFMnKSwgInNwYXRpYWxfcmVzdWx0X2RpcnMiID0gbGlzdCgic3Ryb21hbCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvc3BhdHNpbS9pdGg1L2FiYycsICJlcGl0aGVsaWFsIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9zcGF0c2ltL2l0aDMvYWJjJyksICJiY3JwaHlsb19leGFtcGxlc19ub3RlYm9vayIgPSAnUm1kL2Jjcl9waHlsb19leGFtcGxlcy5SbWQnLCAibWFzdGVyX2JyZWFrcG9pbnRfZmlsZSIgPSAnL3NoYWhsYWIvYW1jcGhlcnNvbi9wcm9qZWN0cy9pdGgzL2l0aDMvbm90ZWJvb2tzL2Jlc3Bva2UvaXRoX2JyZWFrcG9pbnRzLnRzdicsICJtdXRzaWdfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgIm1tY3RtX2FuY2VzdHJhbF9kZXNjZW5kYW50X3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LWFuY2VzdHJ5LXNhbXBsZS9vdXRwdXQnLCAiZXhhbXBsZV9hbm5vdGF0aW9ucyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMTMvZmluYWxfcGFydGl0aW9ucy9pdGgyXzIvY2x1c3Q5L2Fubm90YXRpb25zX2ZsYWdnZWQudHN2JywgIndhbmdfZmJpX3N0YXR1cyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvbmcuMzg0OS1TMTIudHh0JywgImltbXR5cGVyX21vZGVscyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvaW1tdHlwZXJfcmVzdWx0cy9rbGFyZW5iZWVrL2FhX3ZqL2dyYWRib29zdCcsICJtdmNsdXN0X25jbHVzdCIgPSAzLCAiaWNnY19jbGluaWNhbCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvZG9ub3IuT1YtQVUudHN2JywgImlncGFydGl0aW9uX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMjInLCAiYmVuY2htYXJrZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2JlbmNobWFya3MvcGFwZXJhbmFseXNpczInLCAic3BhdGlhbF9ub3RlYm9vayIgPSAnUm1kL3NwYXRpYWxfYW5hbHlzaXMuUm1kJywgImV4YW1wbGVfbXNhX3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2lncGFydGl0aW9uL3J1bjEzL29sZC9hbGlnbm1lbnRfcGxvdHMvbXNhL2l0aDJfMi9jbHVzdDkvaW5kZWxfcmV2ZXJzZWQuaHRtbCcsICJtdmNsdXN0X3RpbHR5cGVzIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJuYW5vc3RyaW5nX2RhdGEiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL25hbm9zdHJpbmdfcmVzdWx0cy9pdGhfZnVsbC9xYy9saW1tYV9xdWFudGlsZS9ub3JtYWxpemVkX2V4cHJlc3Npb25fdm9hX2xhYmVsc19maWx0ZXJlZC50c3YnLCAibXVsdGl2aWV3Y2x1c3RlcmluZ19ub3RlYm9vayIgPSAnUm1kL211bHRpdmlld2NsdXN0ZXJpbmcuUm1kJywgIm1tY3RtX292X2NvbWJpbmVkX3NpZ3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvY29tYmluZWRfb3ZfbW1jdG0vcGxvdHMvb3Zfc252LXN2X3NpZ3NfbXVsdGlwYW5lbC5wZGYnLCAiZGIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJywgInhjcl9xY19ub3RlYm9vayIgPSAnUm1kL3JlcGxpY2F0ZXMuUm1kJywgImRlZmF1bHRfc2FtcGxlciIgPSAnSE1DJywgInRjZ2FfY2xpbmljYWwiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9UQ0dBL3N5bmFwc2VfY2xpbkFsbF9kYXRhLnRzdicsICJ4Y3JtYXBzY2FwZV9ub3RlYm9vayIgPSAnUm1kL3hjcm1hcHNjYXBlLlJtZCcsICJtb2xzdWJ0eXBlX3RpbHR5cGVzIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJub3RlYm9va19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3dlYicsICJkcml2ZXJfbWFwIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvc3VicHJvamVjdHMvZHJpdmVycy9kYXRhL2dlbmVfbGlzdF9tYXBwZWQuYmVkJywgImRyaXZlcl9hbmFseXNpc19ub3RlYm9vayIgPSAnUm1kL2RyaXZlcl9hbmFseXNpcy5SbWQnLCAiaWNnY19leHByX21lbHRlZCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvT1ZBVV9leHByX21lbHRlZC50c3YnLCAieGNyX2Nsb25lc19ub3RlYm9vayIgPSAnUm1kL3hjcl9jbG9uZXNfYW5hbHlzaXMuUm1kJywgImNsYXNzaWZpZXJfdHlwZSIgPSAna25uJywgImluZGV4X25vdGVib29rIiA9ICdSbWQvaW5kZXguUm1kJywgImloY194Y3Jfc3RhdHNfbm90ZWJvb2siID0gJ1JtZC9paGNfeGNyX3N0YXRzLlJtZCcsICJtbWN0bV9wYXRpZW50X2FuY2VzdHJhbF9kZXNjZW5kYW50X3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXBhdGllbnQtYW5jZXN0cnkvb3V0cHV0JywgImtub3duX3N1YnR5cGVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9hcnJheS9zdWJ0eXBlcy9rbm93bl9zdWJ0eXBlcy50c3YnLCAicHJldmFsZW5jZV90aHJlc2hvbGQiID0gMC4wMSwgImNsb25lX2JyYW5jaF9sZW5ndGhfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaXRoL2NvbXBsZXRlL2JyYW5jaF9kYXRhLnRzdicsICJiY3JfY2xvbm90eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L2Nsb25vdHlwZXMvSUdIX2Nsb25vdHlwZXNfZmlsdGVyZWQudHh0JywgImJjcl9kaXZlcnNpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9wb3N0cHJvY2Vzcy9JR0gvcG9zdGZpbHRlcl9kaXZlcnNpdHlfc3RhdHMvZGl2ZXJzaXR5LnN0cmljdC5yZXNhbXBsZWQudHh0JywgImloY19ydW4xIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9paGMvY2Q4Y2QzY2QyMC92YWxpZGF0ZWRfc3RhdHNfd2VpZ2h0ZWRfbmV3LnJkYXRhJywgInByb3BvcnRpb25fc3ViY2xvbmFsX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2l0aC9jb21wbGV0ZS9vbGRfcHJvcG9ydGlvbl9zdWJjbG9uYWwudHN2JywgIm5hbm9zdHJpbmdfYW5ub3RhdGlvbnMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24vbmFub3N0cmluZy9wYW5jYW5jZXJfYW5ub3RhdGlvbnMudHN2JywgImloY194Y3JfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgInNhZF9ub3RlYm9vayIgPSAnUm1kL3NwZWNpZXNfYWJ1bmRhbmNlX2Rpc3RyaWJ1dGlvbnMuUm1kJywgIm11dGF0aW9uX3NpZ25hdHVyZV9ub3RlYm9vayIgPSAnUm1kL211dGF0aW9uX3NpZ25hdHVyZXMuUm1kJywgIml0aF9wcm9qZWN0X3Jlc3VsdHMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvaXRoMy9kYXRhL3Jlc3VsdHMnLCAiaXRoX3RpbF9ub3RlYm9vayIgPSAnUm1kL2l0aF90aWxfZGVuc2l0aWVzLlJtZCcsICJuYW5vc3RyaW5nX3NpZ25hdHVyZV9ub3RlYm9vayIgPSAnUm1kL25hbm9zdHJpbmdfc2lnbmF0dXJlcy5SbWQnLCAiYmNycGh5bG9fY29ycmVsYXRpb25zX25vdGVib29rIiA9ICdSbWQvYmNyX3BoeWxvX2NvcnJlbGF0aW9ucy5SbWQnLCAiaWNnY19ub3JtYWxpemVkX3JlYWRzX21hdHJpeCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvT1ZBVV9leHByX21hdHJpeC50c3YnLCAiaW50ZXJtZWRpYXRlX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvaW50ZXJtZWRpYXRlcy9ydW4yJywgImxpYnJhcnlfc2l6ZXMiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9saWJyYXJ5X3NpemVzLnRzdicsICJtYXBzY2FwZV9ub3RlYm9vayIgPSAnUm1kL21hcHNjYXBlLlJtZCcsICJwYXRpZW50c19mb3JfY2xvbmFsIiA9IGMoMSwgMiwgMywgNCwgNywgOSwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNSwgMTYsIDE3KSwgIml0aF9zdGF0X3R5cGVzIiA9IGMoJ2VudHJvcHknLCAncG9zdHByb2Nlc3NlZF9kaXZlcmdlbmNlJywgJ2NvbWJpbmVkX2l0aF9ub3JtYWxpemVkJywgJ3Byb3BvcnRpb25fc3ViY2xvbmFsJyksICJtbWN0bV9vdl9jb21iaW5lZF9yZXN1bHRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2NvbWJpbmVkX292X21tY3RtL291dHB1dCcsICJ4Y3JfbWFwcGluZ19ub3RlYm9vayIgPSAnUm1kL3hjcl9tYXBwaW5nLlJtZCcsICJ4Y3JfZGlzdGFuY2VfbWV0aG9kIiA9ICdob3JuJywgImJjcnBoeWxvX3RpbHR5cGVzIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JywgJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JyksICJ0aWxfY2xhc3NpZmllcl9ub3RlYm9vayIgPSAnUm1kL3RpbF9jbGFzc2lmaWVyLlJtZCcsICJtYXN0ZXJfdmFyaWFudF9maWxlIiA9ICcvc2hhaGxhYi9hbWNwaGVyc29uL3Byb2plY3RzL2l0aDMvaXRoMy9ub3RlYm9va3MvYmVzcG9rZS9pdGhfc252cy50c3YnLCAiY2xvbmVfcHJldmFsZW5jZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvY2xvbmVfZGF0YS50c3YnLCAibW1jdG1fc2FtcGxlX2FkX3NpZ3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LWFuY2VzdHJ5LXNhbXBsZS9wbG90cy9pdGgtYnktYW5jZXN0cmFsLXNhbXBsZV9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJzdWJ0eXBlX21hcmtlcl9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL25hbm9zdHJpbmcvc3VidHlwZV9tYXJrZXJzLnRzdicsICJ0aWxzX2Zvcl92YXJpYWJpbGl0eSIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpKSwKICAgIHJ1bGUgPSAnYmNycGh5bG9fZXhhbXBsZXMnCikKIyMjIyMjIyMgT3JpZ2luYWwgc2NyaXB0ICMjIyMjIyMjIwoKICAgICAgICAgICAgICAgICAgICAgICAgYGBgCgoKYGBge3IgZ2xvYmFsX2NodW5rX29wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgdGlkeT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHBseXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShEVCkKYGBgCgpgYGB7cn0KZXhhbXBsZV9hbm5vdGF0aW9uX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGV4YW1wbGVfYW5ub3RhdGlvbnMKZXhhbXBsZV9tc2FfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkZXhhbXBsZV9tc2EKYGBgCgojIyBJbnRyb2R1Y3Rpb24KCiMjIyBEZWZpbml0aW9ucwoKKiBMb2N1czogc2VxdWVuY2UgcG9zaXRpb24gKGUuZy4gbnVjbGVvdGlkZSAxMjkpCiogVihEKUogcmVjb21iaW5hdGlvbjogCiogU29tYXRpYyBoeXBlcm11dGF0aW9uIChTSE0pOiBNdXRhdGlvbmFsIHByb2Nlc3Mgb2NjdXJyaW5nIHdpdGhpbiB0aGUgZ2VybWluYWwgY2VudGVycyBvZiBzZWNvbmRhcnkgbHltcGhvaWQgb3JnYW5zIGFjdGluZyBwcmltYXJpbHkgb24gQkNSIHNlcXVlbmNlcwoqICpDbG9uYWwgZmFtaWx5KjogQSBncm91cC9jbHVzdGVyIG9mIEItY2VsbHMvQkNSIHNlcXVlbmNlcyByZWxhdGVkIGJ5IHNvbWF0aWMgaHlwZXJtdXRhdGlvbgoKIyMjIFBhcmVudCBwcm9qZWN0OiBJVEgtT3ZhcnkKCgoKIyMjIFNvbWF0aWMgaHlwZXJtdXRhdGlvbiBnZW5lcmF0ZXMgc2VxdWVuY2UgZGl2ZXJzaXR5IGluIEItY2VsbCBmYW1pbGllcwoKCgoKIyMgUHJvYmxlbQoKIyMjIERlc2NyaXB0aW9uCgohW10ocmVzb3VyY2VzL2JjcnBoeWxvLXByb2plY3QucG5nKQoKIyMjIEV4YW1wbGVzCgojIyMjIERhdGEKCkV4YW1wbGUgaW5wdXQgZGF0YSBmb3IgYSBjbG9uYWwgZmFtaWx5OgoKYGBge3J9CmV4YW1wbGVfYW5ub3RhdGlvbnMgPC0gZnJlYWQoZXhhbXBsZV9hbm5vdGF0aW9uX2ZpbGUpCmV4YW1wbGVfYW5ub3RhdGlvbnNfaW5mbyA8LSBzdWJzZXQoZXhhbXBsZV9hbm5vdGF0aW9ucywgc2VsZWN0PWMoaWQsIHJlYWRjb3VudCwgc2l0ZSwgbXV0X2ZyZXFzLCBpbmRlbF9yZXZlcnNlZF9zZXFzKSkKCmRhdGF0YWJsZShleGFtcGxlX2Fubm90YXRpb25zX2luZm8sIGV4dGVuc2lvbnMgPSAiQnV0dG9ucyIsIG9wdGlvbnM9bGlzdChwYWdlTGVuZ3RoPTUsIHNjcm9sbFg9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbT0nQmZydGlwJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjb3B5JywgJ2NzdicsICdleGNlbCcsICdwZGYnLCAncHJpbnQnKSkpCmBgYAoKTm90ZSB0aGF0IGFsbCBzZXF1ZW5jZXMgYXJlIHRoZSBzYW1lIGxlbmd0aCAoaW5kZWxzIGhhdmUgYmVlbiByZW1vdmVkKS4gCgojIyMjIFNlcXVlbmNlIGFsaWdubWVudAoKVGhlcmUgaXMgY29uc2lkZXJhYmxlIGRpdmVyc2lmaWNhdGlvbiBvY2N1cnJpbmcgd2l0aGluIGNsb25hbCBmYW1pbGllcy4gRXZpZGVuY2Ugb2YgdGhpcyBpbiB0aGUgTVNBIGxpbmtlZCBpbmNsdWRlczoKCiogTGFjayBvZiBjbGVhciBoYXBsb3R5cGVzIChzZXF1ZW5jZSBwb3NpdGlvbnMgdGhhdCBhcHBlYXIgdG8gJ2V2b2x2ZSB0b2dldGhlcicpCiogUGh5bG9nZW5ldGljIHBhdHRlcm5zIGRpZmZpY3VsdCB0byBkaXNjZXJuIGZyb20gYSBjdXJzb3J5IGdsYW5jZSBhdCB0aGUgTVNBCiogRm9yIGVhY2ggbG9jdXMsIG11dGF0ZWQgdmFyaWFudChzKSBhcmUgcHJlc2VudCBhdCBsb3cgZnJlcXVlbmN5CgpbRXhhbXBsZSBNU0FdKHJlc291cmNlcy9tc2EuaHRtbCkKCgojIyMgUmVhZGluZyByZXNvdXJjZXMKCkNvbnRpbnVvdXMgdGltZSBNYXJrb3YgY2hhaW5zIGluIHBoeWxvZ2VuZXRpY3MgKGhpZ2gtaXNoIGxldmVsLCBzZXF1ZW5jZSBldm9sdXRpb24gbW9kZWxzKToKCiogW0NUTUMgdHV0b3JpYWxdKGh0dHBzOi8vZ2l0aHViLmNvbS9yZXZiYXllcy9yZXZiYXllc190dXRvcmlhbC9yYXcvbWFzdGVyL3R1dG9yaWFsX1RlWC9SQl9DVE1DX1R1dG9yaWFsL1JCX0NUTUNfVHV0b3JpYWwucGRmKQoKQmFzaWMgKHVuaWZvcm0pIGJpcnRoLWRlYXRoIHByb2Nlc3M6CgoqIFtCRFAgdHV0b3JpYWxdKGh0dHBzOi8vZ2l0aHViLmNvbS9yZXZiYXllcy9yZXZiYXllc190dXRvcmlhbC9yYXcvbWFzdGVyL3R1dG9yaWFsX1RlWC9SQl9EaXZlcnNpZmljYXRpb25SYXRlX1R1dG9yaWFsL1JCX0RpdmVyc2lmaWNhdGlvblJhdGVfVHV0b3JpYWwucGRmKQoKQnJhbmNoLXNwZWNpZmljIGJpcnRoLWRlYXRoIHByb2Nlc3M6CgoqIFtCU0JEUCB0dXRvcmlhbF0oaHR0cHM6Ly9naXRodWIuY29tL3JldmJheWVzL3JldmJheWVzX3R1dG9yaWFsL3Jhdy9tYXN0ZXIvdHV0b3JpYWxfVGVYL1JCX0RpdmVyc2lmaWNhdGlvblJhdGVfQnJhbmNoU3BlY2lmaWNfVHV0b3JpYWwvUkJfRGl2ZXJzaWZpY2F0aW9uUmF0ZV9CcmFuY2hTcGVjaWZpY19UdXRvcmlhbC5wZGYpCgoKIyMjIExpdGVyYXR1cmUKClRoZSBjb25jZXB0IGJlaGluZCB0aGlzIG1vZGVsIGlzIHNpbWlsYXIgdG8gW0ltbXVuaXRyZWVdKGh0dHA6Ly9qb3VybmFscy5wbG9zLm9yZy9wbG9zcGF0aG9nZW5zL2FydGljbGU/aWQ9MTAuMTM3MS9qb3VybmFsLnBwYXQuMTAwMzc1NCkgLS0gc2VlIHRoZSBTdXBwbGVtZW50YWxzIG9mIHRoZSBsaW5rZWQgcGFwZXIuIEhvd2V2ZXIsIHRoZSBJbW11bml0cmVlIG1vZGVsIG1ha2VzIHNldmVyYWwgdW5yZWFsaXN0aWMgYXNzdW1wdGlvbnM6CgoqIFVuaWZvcm0gYmlydGgtZGVhdGggcHJvY2VzcwoqIFNlcXVlbmNlIGV2b2x1dGlvbiBvY2N1cnMgYXMgYSBkaXNjcmV0ZSBwcm9jZXNzLCBvdmVybGFpZCBvbnRvIHRoZSBjb250aW51b3VzLXRpbWUgTWFya292IGNoYWluIG9mIHRoZSBCRFAKKiBTZXF1ZW5jZSBldm9sdXRpb24gbWF0cml4IGFzc3VtZXMgdGhhdCB0aGUgdHJhbnNpdGlvbiByYXRlIGZyb20gYW55IG51Y2xlb3RpZGUgdG8gYW5vdGhlciAoZGlmZmVyZW50KSBudWNsZW90aWRlIGlzIGVxdWFsIChrbm93bjogdHJhbnN2ZXJzaW9uL3RyYW5zaXRpb24gcmF0ZXMgYXJlIGRpZmZlcmVudCBpbiBnZW5lcmFsLCBpbiBCQ1JzIHNwZWNpZmljIGNvZG9ucy9tb3RpZnMgYXJlIHN1YmplY3QgdG8gbXVjaCBoaWdoZXIgZXZvbHV0aW9uYXJ5IHJhdGVzKQoqICdPYnNlcnZlZCBhbmNlc3RvciBiaWFzJzogY2xlYXJlciB0byBleHBsYWluIHRoaXMgaW4gcGVyc29uCiogU2VxdWVuY2UgZXJyb3IgbW9kZWwgZG9lcyBub3QgaW5jb3Jwb3JhdGUgcmVhZCBxdWFsaXR5IGluZm9ybWF0aW9uCgojIyMgTW9kZWwgZGVzY3JpcHRpb24KCkdlbmVyYXRpdmUgcHJvY2VzczoKCiogIkNlbGxzIiBhcmUgY3JlYXRlZCBieSBhIGJyYW5jaC1zcGVjaWZpYyBiaXJ0aC1kZWF0aCBwcm9jZXNzLCByb290ZWQgYXQgYSBrbm93biBhbmNlc3RyYWwgc2VxdWVuY2UKKiBTZXF1ZW5jZXMgZXZvbHZlIG92ZXIgdGhlIGJyYW5jaGVzIG9mIHRoZSBCRFAgYWNjb3JkaW5nIHRvIGEgQ1RNQywgZ292ZXJuZWQgYnkgYSBnZW5lcmFsIHRpbWUgcmV2ZXJzaWJsZSAoR1RSKSB0cmFuc2l0aW9uIG1hdHJpeAoqIFJlYWRzIGFyZSBwcm9kdWNlZCBieSBzZXF1ZW5jZXMgYXQgdGhlIHRpcHMgKHRoaXMgY291bGQgYmUgbW9kaWZpZWQgdG8gYWxsb3cgaW50ZXJuYWwgbm9kZXMgdG8gcHJvZHVjZSBzZXF1ZW5jZXMsIHJlcXVpcmVzIGFkZGl0aW9uYWwgbW9kZWxpbmcpLCBhY2NvcmRpbmcgdG8gYSBzZXF1ZW5jZSBlcnJvciBtb2RlbCB0aGF0IGluY29ycG9yYXRlcyByZWFkIHF1YWxpdGllcwoK