1 Introduction

I am looking to learn about unannotated short CDSes in 5448. In reality, I think I want to learn about all short transcripts which are likely residing in the inter-CDS regions and which have some evidence of being actively transcribed. The short CDS sequences are thus a (potentially small) subset thereof; but they are a subset for which there are quick and easy tools to hunt.

With that in mind, I compiled a new copy of prodigal in which I changed its hard-coded settings for the lower limits of its search range.

If anyone reads this who is interested, I changed the constants in node.h:

  • MIN_GENE was 90 and is now 24
  • MIN_EDGE_GENE was 60 and is now 18
  • MAX_SAM_OVLP is now 12
  • ST_WINDOW is now 12
  • OPER_DIST is now 12

I went through a few iterations of messing with these parameters.

I will just run the following commands here, I just run prodigal (default) and progial_small (modified) separately on the 5448 genome.

ok, so bizarrely my first run gave me (I think) 1778 CDS sequences, which seemed rather lower than I expected. So I decreased the inter-operon distance with the reasonable assumption that I would find a few more, but now prodigal is detecting 1773.

module add prodigal
cd reference
prodigal -i spyogenes_5448.fasta -f gff > spyogenes_5448.gff
prodigal_small -i spyogenes_5448.fasta -f gff > spyogenes_5448_small.gff

wc -l spyogenes_5448.gff
wc -l spyogenes_5448_small.gff
## bash: line 1: module: command not found
## -------------------------------------
## PRODIGAL v2.6.3 [February, 2016]         
## Univ of Tenn / Oak Ridge National Lab
## Doug Hyatt, Loren Hauser, et al.     
## -------------------------------------
## Request:  Single Genome, Phase:  Training
## Reading in the sequence(s) to train...1829516 bp seq created, 38.50 pct GC
## Locating all potential starts and stops...70248 nodes
## Looking for GC bias in different frames...frame bias scores: 2.57 0.15 0.28
## Building initial set of genes to train from...done!
## Creating coding model and scoring nodes...done!
## Examining upstream regions and training starts...done!
## -------------------------------------
## Request:  Single Genome, Phase:  Gene Finding
## Finding genes in sequence #1 (1829516 bp)...done!
## -------------------------------------
## PRODIGAL v2.6.3 [February, 2016]         
## Univ of Tenn / Oak Ridge National Lab
## Doug Hyatt, Loren Hauser, et al.     
## -------------------------------------
## Request:  Single Genome, Phase:  Training
## Reading in the sequence(s) to train...1829516 bp seq created, 38.50 pct GC
## Locating all potential starts and stops...193604 nodes
## Looking for GC bias in different frames...frame bias scores: 2.30 0.22 0.48
## Building initial set of genes to train from...done!
## Creating coding model and scoring nodes...done!
## Examining upstream regions and training starts...done!
## -------------------------------------
## Request:  Single Genome, Phase:  Gene Finding
## Finding genes in sequence #1 (1829516 bp)...done!
## 1769 spyogenes_5448.gff
## 1773 spyogenes_5448_small.gff

2 Look at the two sets of GFF annotations

I would expect that most of the resulting entries are identical, but I can easily imagine that the different parameters might cause different start codons to be chosen (which might in turn affect the number of new entries in the small set and be why I got the unexpectedly smaller number). Either way, the + strand ends and - strand starts should remain identical (start and end in this context are divorced from AUG/GUG/UUT(I thought pyogenes also had a couple CUG?) vs.ย stop codon).

normal <- load_gff_annotations("reference/spyogenes_5448.gff")
## Trying attempt: rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo = TRUE)
## Trying attempt: rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo = FALSE)
## Had a successful gff import with rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo = FALSE)
## Returning a df with 22 columns and 1766 rows.
summary(as.factor(normal[["start_type"]]))
##  ATG  GTG  TTG 
## 1599   86   81
small <- load_gff_annotations("reference/spyogenes_5448_small.gff")
## Trying attempt: rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo = TRUE)
## Trying attempt: rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo = FALSE)
## Had a successful gff import with rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo = FALSE)
## Returning a df with 22 columns and 1770 rows.
summary(as.factor(small[["start_type"]]))
##  ATG  GTG  TTG 
## 1601   90   79

These summaries make clear that a few start codons did in fact get moved. The question therefore is, did that shift the putative CDS sizes up or down (with the caveat that the minimum went down by definition).

summary(normal[["width"]])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##      90     453     765     892    1187    6180
summary(small[["width"]])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##      63     447     759     888    1182    6180

Interestingly, even though I explicitly said the minimum is 24, the smallest observed putative CDS is 63 nucleotides.

Alrighty, let us find the intersection and (more interestingly) unique to the small (and hopefully null unique to the large) sets. I will assume the stop codons are static and split the strands +/-.

2.1 Split the plus and minus putative CDS

normal_plus_idx <- normal[["strand"]] == "+"
normal_plus <- normal[normal_plus_idx, ]
normal_minus <- normal[!normal_plus_idx, ]

small_plus_idx <- small[["strand"]] == "+"
small_plus <- small[small_plus_idx, ]
small_minus <- small[!small_plus_idx, ]

2.2 Examine plus CDS

dim(normal_plus)
## [1] 952  22
dim(small_plus)
## [1] 953  22
all_plus <- merge(normal_plus, small_plus, by="end", all.x=TRUE, all.y=TRUE)

## These ought to be the set of babies which are in the small set but _not_ the large set.
missing_normal_idx <- is.na(all_plus[["width.x"]])
missing_normal <- all_plus[missing_normal_idx, ]
missing_normal
##         end seqnames.x start.x width.x strand.x source.x type.x score.x phase.x
## 261  344192       <NA>      NA      NA     <NA>     <NA>   <NA>      NA      NA
## 488  619685       <NA>      NA      NA     <NA>     <NA>   <NA>      NA      NA
## 536  668181       <NA>      NA      NA     <NA>     <NA>   <NA>      NA      NA
## 570  689910       <NA>      NA      NA     <NA>     <NA>   <NA>      NA      NA
## 660  822606       <NA>      NA      NA     <NA>     <NA>   <NA>      NA      NA
## 863 1439115       <NA>      NA      NA     <NA>     <NA>   <NA>      NA      NA
## 873 1475677       <NA>      NA      NA     <NA>     <NA>   <NA>      NA      NA
## 885 1528425       <NA>      NA      NA     <NA>     <NA>   <NA>      NA      NA
##     ID.x partial.x start_type.x rbs_motif.x rbs_spacer.x gc_cont.x conf.x
## 261 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 488 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 536 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 570 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 660 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 863 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 873 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 885 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
##     score.1.x cscore.x sscore.x rscore.x uscore.x tscore.x seqnames.y start.y
## 261      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776  344109
## 488      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776  619566
## 536      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776  668119
## 570      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776  689800
## 660      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776  822523
## 863      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776 1439047
## 873      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776 1475570
## 885      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776 1528339
##     width.y strand.y        source.y type.y score.y phase.y   ID.y partial.y
## 261      84        + Prodigal_v2.6.3    CDS     2.6       0  1_319        00
## 488     120        + Prodigal_v2.6.3    CDS     0.1       0  1_585        00
## 536      63        + Prodigal_v2.6.3    CDS     0.6       0  1_643        00
## 570     111        + Prodigal_v2.6.3    CDS     1.6       0  1_676        00
## 660      84        + Prodigal_v2.6.3    CDS    10.7       0  1_799        00
## 863      69        + Prodigal_v2.6.3    CDS     5.3       0 1_1402        00
## 873     108        + Prodigal_v2.6.3    CDS     0.4       0 1_1448        00
## 885      87        + Prodigal_v2.6.3    CDS     2.3       0 1_1503        00
##     start_type.y   rbs_motif.y rbs_spacer.y gc_cont.y conf.y score.1.y cscore.y
## 261          ATG     GGAG/GAGG       5-10bp     0.369  64.26      2.55    -2.95
## 488          ATG AGxAGG/AGGxGG        3-4bp     0.300  50.40      0.07    -5.28
## 536          ATG   GGA/GAG/AGG       5-10bp     0.333  53.42      0.60    -1.20
## 570          ATG         AGGAG       5-10bp     0.378  59.31      1.64    -5.80
## 660          ATG         AGGAG       5-10bp     0.298  92.14     10.71     2.94
## 863          ATG         AGGAG       5-10bp     0.290  77.01      5.26    -0.60
## 873          ATG     GGAG/GAGG       5-10bp     0.333  52.51      0.44    -5.03
## 885          ATG     GGAG/GAGG       5-10bp     0.379  62.71      2.26    -3.42
##     sscore.y rscore.y uscore.y tscore.y
## 261     5.50     3.17     0.50     1.41
## 488     5.35     2.89     0.93     2.03
## 536     1.79    -3.30   -10.03     1.04
## 570     7.44     6.84    -1.48     1.87
## 660     7.77     5.13     1.24     1.41
## 863     5.86     4.18     1.03     1.15
## 873     5.47     4.11     0.69     1.82
## 885     5.69     3.28     0.52     1.46
## Conversely these are the ones which are lost in the 'small' dataset.
missing_small_idx <- is.na(all_plus[["width.y"]])
missing_small <- all_plus[missing_small_idx, ]
missing_small
##         end seqnames.x start.x width.x strand.x        source.x type.x score.x
## 84    99385   CP008776   98951     435        + Prodigal_v2.6.3    CDS    15.4
## 533  667770   CP008776  667537     234        + Prodigal_v2.6.3    CDS    15.2
## 557  681475   CP008776  681137     339        + Prodigal_v2.6.3    CDS    45.6
## 590  717868   CP008776  717641     228        + Prodigal_v2.6.3    CDS     9.8
## 601  732661   CP008776  732527     135        + Prodigal_v2.6.3    CDS     0.0
## 694  840756   CP008776  840298     459        + Prodigal_v2.6.3    CDS    26.4
## 917 1707641   CP008776 1707450     192        + Prodigal_v2.6.3    CDS    28.4
##     phase.x   ID.x partial.x start_type.x    rbs_motif.x rbs_spacer.x gc_cont.x
## 84        0   1_88        00          TTG    AGGAG/GGAGG      11-12bp     0.352
## 533       0  1_641        00          ATG    GGA/GAG/AGG      11-12bp     0.346
## 557       0  1_664        00          ATG    AGGAG/GGAGG      11-12bp     0.378
## 590       0  1_701        00          GTG          AGGAG       5-10bp     0.373
## 601       0  1_714        00          ATG AGGA/GGAG/GAGG      11-12bp     0.370
## 694       0  1_835        00          TTG           None         None     0.412
## 917       0 1_1660        00          ATG AGGA/GGAG/GAGG      11-12bp     0.401
##     conf.x score.1.x cscore.x sscore.x rscore.x uscore.x tscore.x seqnames.y
## 84   97.17     15.38    17.03    -1.66     8.25    -0.84   -10.32       <NA>
## 533  97.07     15.23    15.05     0.18    -3.24    -0.17     3.59       <NA>
## 557 100.00     45.63    31.70    13.93     8.25     1.78     3.89       <NA>
## 590  90.39      9.75     1.67     8.08    12.18     2.78    -6.88       <NA>
## 601  50.06      0.01    -3.65     3.67     1.46     1.31     2.05       <NA>
## 694  99.77     26.42    46.84   -20.42    -8.48    -1.62   -10.32       <NA>
## 917  99.86     28.44    22.17     6.26     2.08     1.24     2.94       <NA>
##     start.y width.y strand.y source.y type.y score.y phase.y ID.y partial.y
## 84       NA      NA     <NA>     <NA>   <NA>      NA      NA <NA>      <NA>
## 533      NA      NA     <NA>     <NA>   <NA>      NA      NA <NA>      <NA>
## 557      NA      NA     <NA>     <NA>   <NA>      NA      NA <NA>      <NA>
## 590      NA      NA     <NA>     <NA>   <NA>      NA      NA <NA>      <NA>
## 601      NA      NA     <NA>     <NA>   <NA>      NA      NA <NA>      <NA>
## 694      NA      NA     <NA>     <NA>   <NA>      NA      NA <NA>      <NA>
## 917      NA      NA     <NA>     <NA>   <NA>      NA      NA <NA>      <NA>
##     start_type.y rbs_motif.y rbs_spacer.y gc_cont.y conf.y score.1.y cscore.y
## 84          <NA>        <NA>         <NA>      <NA>   <NA>      <NA>     <NA>
## 533         <NA>        <NA>         <NA>      <NA>   <NA>      <NA>     <NA>
## 557         <NA>        <NA>         <NA>      <NA>   <NA>      <NA>     <NA>
## 590         <NA>        <NA>         <NA>      <NA>   <NA>      <NA>     <NA>
## 601         <NA>        <NA>         <NA>      <NA>   <NA>      <NA>     <NA>
## 694         <NA>        <NA>         <NA>      <NA>   <NA>      <NA>     <NA>
## 917         <NA>        <NA>         <NA>      <NA>   <NA>      <NA>     <NA>
##     sscore.y rscore.y uscore.y tscore.y
## 84      <NA>     <NA>     <NA>     <NA>
## 533     <NA>     <NA>     <NA>     <NA>
## 557     <NA>     <NA>     <NA>     <NA>
## 590     <NA>     <NA>     <NA>     <NA>
## 601     <NA>     <NA>     <NA>     <NA>
## 694     <NA>     <NA>     <NA>     <NA>
## 917     <NA>     <NA>     <NA>     <NA>

2.3 Examine minus CDS

dim(normal_minus)
## [1] 814  22
dim(small_minus)
## [1] 817  22
all_minus <- merge(normal_minus, small_minus, by="start", all.x=TRUE, all.y=TRUE)

## These ought to be the set of babies which are in the small set but _not_ the large set.
missing_normal_idx <- is.na(all_minus[["width.x"]])
missing_normal <- all_minus[missing_normal_idx, ]
missing_normal
##       start seqnames.x end.x width.x strand.x source.x type.x score.x phase.x
## 522 1401665       <NA>    NA      NA     <NA>     <NA>   <NA>      NA      NA
## 655 1564785       <NA>    NA      NA     <NA>     <NA>   <NA>      NA      NA
## 796 1789077       <NA>    NA      NA     <NA>     <NA>   <NA>      NA      NA
## 803 1797083       <NA>    NA      NA     <NA>     <NA>   <NA>      NA      NA
##     ID.x partial.x start_type.x rbs_motif.x rbs_spacer.x gc_cont.x conf.x
## 522 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 655 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 796 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
## 803 <NA>      <NA>         <NA>        <NA>         <NA>      <NA>   <NA>
##     score.1.x cscore.x sscore.x rscore.x uscore.x tscore.x seqnames.y   end.y
## 522      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776 1401736
## 655      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776 1564868
## 796      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776 1789160
## 803      <NA>     <NA>     <NA>     <NA>     <NA>     <NA>   CP008776 1797157
##     width.y strand.y        source.y type.y score.y phase.y   ID.y partial.y
## 522      72        - Prodigal_v2.6.3    CDS     5.6       0 1_1369        00
## 655      84        - Prodigal_v2.6.3    CDS     3.1       0 1_1539        00
## 796      84        - Prodigal_v2.6.3    CDS     2.6       0 1_1736        00
## 803      75        - Prodigal_v2.6.3    CDS     5.5       0 1_1743        00
##     start_type.y rbs_motif.y rbs_spacer.y gc_cont.y conf.y score.1.y cscore.y
## 522          ATG        AGGA       5-10bp     0.222  78.31      5.58     1.21
## 655          ATG   GGAG/GAGG       5-10bp     0.357  66.86      3.05    -2.44
## 796          ATG   GGAG/GAGG       5-10bp     0.357  64.26      2.55    -2.95
## 803          ATG        None         None     0.373  78.15      5.54     3.04
##     sscore.y rscore.y uscore.y tscore.y
## 522     4.38     2.13     1.70     1.20
## 655     5.50     3.17     0.50     1.41
## 796     5.50     3.17     0.50     1.41
## 803     2.50   -30.03    -2.18     1.25
## Conversely these are the ones which are lost in the 'small' dataset.
missing_small_idx <- is.na(all_minus[["width.y"]])
missing_small <- all_minus[missing_small_idx, ]
missing_small
##     start seqnames.x  end.x width.x strand.x        source.x type.x score.x
## 12 118120   CP008776 118347     228        - Prodigal_v2.6.3    CDS    39.1
##    phase.x  ID.x partial.x start_type.x rbs_motif.x rbs_spacer.x gc_cont.x
## 12       0 1_108        00          ATG      AGGAGG       5-10bp     0.412
##    conf.x score.1.x cscore.x sscore.x rscore.x uscore.x tscore.x seqnames.y
## 12  99.99     39.10    19.72    19.38    12.99     2.16     3.50       <NA>
##    end.y width.y strand.y source.y type.y score.y phase.y ID.y partial.y
## 12    NA      NA     <NA>     <NA>   <NA>      NA      NA <NA>      <NA>
##    start_type.y rbs_motif.y rbs_spacer.y gc_cont.y conf.y score.1.y cscore.y
## 12         <NA>        <NA>         <NA>      <NA>   <NA>      <NA>     <NA>
##    sscore.y rscore.y uscore.y tscore.y
## 12     <NA>     <NA>     <NA>     <NA>
pander::pander(sessionInfo())
message(paste0("This is hpgltools commit: ", get_git_commit()))
this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
message(paste0("Saving to ", this_save))
tmp <- sm(saveme(filename=this_save))
LS0tCnRpdGxlOiAiQ29tcGFyZSBwcm9kaWdhbCBydW5zIGZyb20gdHdvIHBhcmFtZXRlciBzZXRzLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGRmX3ByaW50OiBwYWdlZAogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgd2lkdGg6IDMwMAogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIHRvY19mbG9hdDogdHJ1ZQogIEJpb2NTdHlsZTo6aHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIHRvY19mbG9hdDogdHJ1ZQotLS0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CmJvZHksIHRkIHsKICBmb250LXNpemU6IDE2cHg7Cn0KY29kZS5yewogIGZvbnQtc2l6ZTogMTZweDsKfQpwcmUgewogZm9udC1zaXplOiAxNnB4Cn0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoImhwZ2x0b29scyIpCnR0IDwtIGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKQprbml0cjo6b3B0c19rbml0JHNldCh3aWR0aD0xMjAsCiAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgZWNobz1UUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoZXJyb3I9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGRwaT05NikKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHM9NCwKICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbD0iYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplPTEwKSkKcnVuZGF0ZSA8LSBmb3JtYXQoU3lzLkRhdGUoKSwgZm9ybWF0PSIlWSVtJWQiKQpwcmV2aW91c19maWxlIDwtICIiCnZlciA8LSBmb3JtYXQoU3lzLkRhdGUoKSwgIiVZJW0lZCIpCgojI3RtcCA8LSBzbShsb2FkbWUoZmlsZW5hbWU9cGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1wcmV2aW91c19maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpKSkKcm1kX2ZpbGUgPC0gImNvbXBhcmVfcHJvZGlnYWwuUm1kIgpgYGAKCiMgSW50cm9kdWN0aW9uCgpJIGFtIGxvb2tpbmcgdG8gbGVhcm4gYWJvdXQgdW5hbm5vdGF0ZWQgc2hvcnQgQ0RTZXMgaW4gNTQ0OC4gIEluCnJlYWxpdHksIEkgdGhpbmsgSSB3YW50IHRvIGxlYXJuIGFib3V0IGFsbCBzaG9ydCB0cmFuc2NyaXB0cyB3aGljaCBhcmUKbGlrZWx5IHJlc2lkaW5nIGluIHRoZSBpbnRlci1DRFMgcmVnaW9ucyBhbmQgd2hpY2ggaGF2ZSBzb21lIGV2aWRlbmNlCm9mIGJlaW5nIGFjdGl2ZWx5IHRyYW5zY3JpYmVkLiAgVGhlIHNob3J0IENEUyBzZXF1ZW5jZXMgYXJlIHRodXMgYQoocG90ZW50aWFsbHkgc21hbGwpIHN1YnNldCB0aGVyZW9mOyBidXQgdGhleSBhcmUgYSBzdWJzZXQgZm9yIHdoaWNoCnRoZXJlIGFyZSBxdWljayBhbmQgZWFzeSB0b29scyB0byBodW50LgoKV2l0aCB0aGF0IGluIG1pbmQsIEkgY29tcGlsZWQgYSBuZXcgY29weSBvZiBwcm9kaWdhbCBpbiB3aGljaCBJCmNoYW5nZWQgaXRzIGhhcmQtY29kZWQgc2V0dGluZ3MgZm9yIHRoZSBsb3dlciBsaW1pdHMgb2YgaXRzIHNlYXJjaApyYW5nZS4KCklmIGFueW9uZSByZWFkcyB0aGlzIHdobyBpcyBpbnRlcmVzdGVkLCBJIGNoYW5nZWQgdGhlIGNvbnN0YW50cyBpbgpub2RlLmg6CgoqIE1JTl9HRU5FIHdhcyA5MCBhbmQgaXMgbm93IDI0CiogTUlOX0VER0VfR0VORSB3YXMgNjAgYW5kIGlzIG5vdyAxOAoqIE1BWF9TQU1fT1ZMUCBpcyBub3cgMTIKKiBTVF9XSU5ET1cgaXMgbm93IDEyCiogT1BFUl9ESVNUIGlzIG5vdyAxMgoKSSB3ZW50IHRocm91Z2ggYSBmZXcgaXRlcmF0aW9ucyBvZiBtZXNzaW5nIHdpdGggdGhlc2UgcGFyYW1ldGVycy4KCkkgd2lsbCBqdXN0IHJ1biB0aGUgZm9sbG93aW5nIGNvbW1hbmRzIGhlcmUsIEkganVzdCBydW4gcHJvZGlnYWwKKGRlZmF1bHQpIGFuZCBwcm9naWFsX3NtYWxsIChtb2RpZmllZCkgc2VwYXJhdGVseSBvbiB0aGUgNTQ0OCBnZW5vbWUuCgpvaywgc28gYml6YXJyZWx5IG15IGZpcnN0IHJ1biBnYXZlIG1lIChJIHRoaW5rKSAxNzc4IENEUyBzZXF1ZW5jZXMsCndoaWNoIHNlZW1lZCByYXRoZXIgbG93ZXIgdGhhbiBJIGV4cGVjdGVkLiAgU28gSSBkZWNyZWFzZWQgdGhlCmludGVyLW9wZXJvbiBkaXN0YW5jZSB3aXRoIHRoZSByZWFzb25hYmxlIGFzc3VtcHRpb24gdGhhdCBJIHdvdWxkIGZpbmQKYSBmZXcgbW9yZSwgYnV0IG5vdyBwcm9kaWdhbCBpcyBkZXRlY3RpbmcgMTc3My4KCmBgYHtiYXNoIHJ1bl90d29fcHJvZGlnYWxzfQptb2R1bGUgYWRkIHByb2RpZ2FsCmNkIHJlZmVyZW5jZQpwcm9kaWdhbCAtaSBzcHlvZ2VuZXNfNTQ0OC5mYXN0YSAtZiBnZmYgPiBzcHlvZ2VuZXNfNTQ0OC5nZmYKcHJvZGlnYWxfc21hbGwgLWkgc3B5b2dlbmVzXzU0NDguZmFzdGEgLWYgZ2ZmID4gc3B5b2dlbmVzXzU0NDhfc21hbGwuZ2ZmCgp3YyAtbCBzcHlvZ2VuZXNfNTQ0OC5nZmYKd2MgLWwgc3B5b2dlbmVzXzU0NDhfc21hbGwuZ2ZmCmBgYAoKIyBMb29rIGF0IHRoZSB0d28gc2V0cyBvZiBHRkYgYW5ub3RhdGlvbnMKCkkgd291bGQgZXhwZWN0IHRoYXQgbW9zdCBvZiB0aGUgcmVzdWx0aW5nIGVudHJpZXMgYXJlIGlkZW50aWNhbCwgYnV0IEkKY2FuIGVhc2lseSBpbWFnaW5lIHRoYXQgdGhlIGRpZmZlcmVudCBwYXJhbWV0ZXJzIG1pZ2h0IGNhdXNlIGRpZmZlcmVudApzdGFydCBjb2RvbnMgdG8gYmUgY2hvc2VuICh3aGljaCBtaWdodCBpbiB0dXJuIGFmZmVjdCB0aGUgbnVtYmVyIG9mCm5ldyBlbnRyaWVzIGluIHRoZSBzbWFsbCBzZXQgYW5kIGJlIHdoeSBJIGdvdCB0aGUgdW5leHBlY3RlZGx5IHNtYWxsZXIKbnVtYmVyKS4gIEVpdGhlciB3YXksIHRoZSArIHN0cmFuZCBlbmRzIGFuZCAtIHN0cmFuZCBzdGFydHMgc2hvdWxkCnJlbWFpbiBpZGVudGljYWwgKHN0YXJ0IGFuZCBlbmQgaW4gdGhpcyBjb250ZXh0IGFyZSBkaXZvcmNlZCBmcm9tCkFVRy9HVUcvVVVUKEkgdGhvdWdodCBweW9nZW5lcyBhbHNvIGhhZCBhIGNvdXBsZSBDVUc/KSB2cy4gc3RvcApjb2RvbikuCgpgYGB7ciBwb2tlX2dmZn0Kbm9ybWFsIDwtIGxvYWRfZ2ZmX2Fubm90YXRpb25zKCJyZWZlcmVuY2Uvc3B5b2dlbmVzXzU0NDguZ2ZmIikKc3VtbWFyeShhcy5mYWN0b3Iobm9ybWFsW1sic3RhcnRfdHlwZSJdXSkpCgpzbWFsbCA8LSBsb2FkX2dmZl9hbm5vdGF0aW9ucygicmVmZXJlbmNlL3NweW9nZW5lc181NDQ4X3NtYWxsLmdmZiIpCnN1bW1hcnkoYXMuZmFjdG9yKHNtYWxsW1sic3RhcnRfdHlwZSJdXSkpCmBgYAoKVGhlc2Ugc3VtbWFyaWVzIG1ha2UgY2xlYXIgdGhhdCBhIGZldyBzdGFydCBjb2RvbnMgZGlkIGluIGZhY3QgZ2V0Cm1vdmVkLiAgVGhlIHF1ZXN0aW9uIHRoZXJlZm9yZSBpcywgZGlkIHRoYXQgc2hpZnQgdGhlIHB1dGF0aXZlIENEUwpzaXplcyB1cCBvciBkb3duICh3aXRoIHRoZSBjYXZlYXQgdGhhdCB0aGUgbWluaW11bSB3ZW50IGRvd24gYnkgZGVmaW5pdGlvbikuCgpgYGB7ciB3aWR0aH0Kc3VtbWFyeShub3JtYWxbWyJ3aWR0aCJdXSkKc3VtbWFyeShzbWFsbFtbIndpZHRoIl1dKQpgYGAKCkludGVyZXN0aW5nbHksIGV2ZW4gdGhvdWdoIEkgZXhwbGljaXRseSBzYWlkIHRoZSBtaW5pbXVtIGlzIDI0LCB0aGUKc21hbGxlc3Qgb2JzZXJ2ZWQgcHV0YXRpdmUgQ0RTIGlzIDYzIG51Y2xlb3RpZGVzLgoKQWxyaWdodHksIGxldCB1cyBmaW5kIHRoZSBpbnRlcnNlY3Rpb24gYW5kIChtb3JlIGludGVyZXN0aW5nbHkpIHVuaXF1ZQp0byB0aGUgc21hbGwgKGFuZCBob3BlZnVsbHkgbnVsbCB1bmlxdWUgdG8gdGhlIGxhcmdlKSBzZXRzLiAgSSB3aWxsCmFzc3VtZSB0aGUgc3RvcCBjb2RvbnMgYXJlIHN0YXRpYyBhbmQgc3BsaXQgdGhlIHN0cmFuZHMgKy8tLgoKIyMgU3BsaXQgdGhlIHBsdXMgYW5kIG1pbnVzIHB1dGF0aXZlIENEUwoKYGBge3IgaW50ZXJzZWN0aW9ufQpub3JtYWxfcGx1c19pZHggPC0gbm9ybWFsW1sic3RyYW5kIl1dID09ICIrIgpub3JtYWxfcGx1cyA8LSBub3JtYWxbbm9ybWFsX3BsdXNfaWR4LCBdCm5vcm1hbF9taW51cyA8LSBub3JtYWxbIW5vcm1hbF9wbHVzX2lkeCwgXQoKc21hbGxfcGx1c19pZHggPC0gc21hbGxbWyJzdHJhbmQiXV0gPT0gIisiCnNtYWxsX3BsdXMgPC0gc21hbGxbc21hbGxfcGx1c19pZHgsIF0Kc21hbGxfbWludXMgPC0gc21hbGxbIXNtYWxsX3BsdXNfaWR4LCBdCmBgYAoKIyMgRXhhbWluZSBwbHVzIENEUwoKYGBge3IgcGx1c19wb2tlfQpkaW0obm9ybWFsX3BsdXMpCmRpbShzbWFsbF9wbHVzKQphbGxfcGx1cyA8LSBtZXJnZShub3JtYWxfcGx1cywgc21hbGxfcGx1cywgYnk9ImVuZCIsIGFsbC54PVRSVUUsIGFsbC55PVRSVUUpCgojIyBUaGVzZSBvdWdodCB0byBiZSB0aGUgc2V0IG9mIGJhYmllcyB3aGljaCBhcmUgaW4gdGhlIHNtYWxsIHNldCBidXQgX25vdF8gdGhlIGxhcmdlIHNldC4KbWlzc2luZ19ub3JtYWxfaWR4IDwtIGlzLm5hKGFsbF9wbHVzW1sid2lkdGgueCJdXSkKbWlzc2luZ19ub3JtYWwgPC0gYWxsX3BsdXNbbWlzc2luZ19ub3JtYWxfaWR4LCBdCm1pc3Npbmdfbm9ybWFsCgojIyBDb252ZXJzZWx5IHRoZXNlIGFyZSB0aGUgb25lcyB3aGljaCBhcmUgbG9zdCBpbiB0aGUgJ3NtYWxsJyBkYXRhc2V0LgptaXNzaW5nX3NtYWxsX2lkeCA8LSBpcy5uYShhbGxfcGx1c1tbIndpZHRoLnkiXV0pCm1pc3Npbmdfc21hbGwgPC0gYWxsX3BsdXNbbWlzc2luZ19zbWFsbF9pZHgsIF0KbWlzc2luZ19zbWFsbApgYGAKCiMjIEV4YW1pbmUgbWludXMgQ0RTCgpgYGB7ciBtaW51c19wb2tlfQpkaW0obm9ybWFsX21pbnVzKQpkaW0oc21hbGxfbWludXMpCmFsbF9taW51cyA8LSBtZXJnZShub3JtYWxfbWludXMsIHNtYWxsX21pbnVzLCBieT0ic3RhcnQiLCBhbGwueD1UUlVFLCBhbGwueT1UUlVFKQoKIyMgVGhlc2Ugb3VnaHQgdG8gYmUgdGhlIHNldCBvZiBiYWJpZXMgd2hpY2ggYXJlIGluIHRoZSBzbWFsbCBzZXQgYnV0IF9ub3RfIHRoZSBsYXJnZSBzZXQuCm1pc3Npbmdfbm9ybWFsX2lkeCA8LSBpcy5uYShhbGxfbWludXNbWyJ3aWR0aC54Il1dKQptaXNzaW5nX25vcm1hbCA8LSBhbGxfbWludXNbbWlzc2luZ19ub3JtYWxfaWR4LCBdCm1pc3Npbmdfbm9ybWFsCgojIyBDb252ZXJzZWx5IHRoZXNlIGFyZSB0aGUgb25lcyB3aGljaCBhcmUgbG9zdCBpbiB0aGUgJ3NtYWxsJyBkYXRhc2V0LgptaXNzaW5nX3NtYWxsX2lkeCA8LSBpcy5uYShhbGxfbWludXNbWyJ3aWR0aC55Il1dKQptaXNzaW5nX3NtYWxsIDwtIGFsbF9taW51c1ttaXNzaW5nX3NtYWxsX2lkeCwgXQptaXNzaW5nX3NtYWxsCmBgYAoKYGBge3IgaW50ZXJzZWN0aW9uc19taW51c30KCmBgYHtyIHNhdmVtZSwgZXZhbD1GQUxTRX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCnRoaXNfc2F2ZSA8LSBwYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXJtZF9maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpCm1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgdGhpc19zYXZlKSkKdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT10aGlzX3NhdmUpKQpgYGAK