1 Introduction

I am hoping to learn some tasks one may perform for high-throughput population genetics. This is a realm in which I have very limited understanding, so for the moment I am relying upon the ANGSD and PLINK documentation and hoping that I will understand more as I continue through them.

2 Initial ANGSD tasks

One important caveat about the following. In this iteration I am only including samples for which we have known annotations of the zymodeme. At the time of this writing, that limits the scope of this document to 35 samples (16 2.2 and 19 2.3 samples). I do not really know if this is sufficient for a valid analysis, but it does not seem unreasonable for a first pass.

2.1 Filtering the ‘raw’ data

My understanding: the first task to perform is to read in the alignments against the reference genome and filter them. Thus I created a series of text files with the relative locations of the relevant bamfiles. I initially separated them by zymodeme, but came to a realization that it is better to keep them together.

In addition, I used this ‘lst’ file to write out a ‘set’ file in the format expected by PLINK. Here is a short bash block showing what I did:

## I symlinked the preprocessing directory from my main tree.
ls -ld preprocessing

head all_samples.lst
head zymodeme_plink_sets.txt
## lrwxrwxrwx 1 trey hpgl 16 Aug  3 11:30 preprocessing -> ../preprocessing
## preprocessing/TMRC20002/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20005/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20009/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20011/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20012/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20014/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20017/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20039/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20041/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20049/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## ZY22
## preprocessing/TMRC20002/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20005/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20009/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20011/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20012/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20014/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20017/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20039/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam
## preprocessing/TMRC20041/outputs/hisat2_lpanamensis_v36/r1_trimmed.bam

Given these text inputs, I followed the snpFilters section of the ANGSD manual:

http://popgen.dk/angsd/index.php/SnpFilters

in order to perform what I think are appropriate filters and initial statistics as per the following block. I chose not to do genotype calling because the authors suggested against it:

“We really don’t recommend doing analysis based on called genotypes, but incorporate the uncertainty directly into the analysis you want to perform. But we recognise that many methods are still relying on called genotypes, and have therefore implemented a basic genotype caller into angsd.”

module add angsd
angsd -b all_samples.lst \
      -doHWE 1 -GL 1 \
      -doMajorMinor 1 -doMaf 2 \
      -snp_pval 1e-2 -P 5 \
      -dosnpstat 1 -out all_filtered
## Some other possible likely options:
## -doGeno performs genotype calling.  It takes the sum of:
##  1: major/minor calls,
##  2: write out called genotype encoded as -1,0,1,2...
##  4: write called genotype directly as AA,AC,...
##  8: write posterior probabilities of all genotypes
##  16,32: other posteriors
##    It looks like a likely value is therefore -doGeno 3 or 55
##
## -doPost I think is responsible for doing the posterior
##   probabilities, the documentation is a little sparse here.

The resulting output files are here:

ls -al all_filtered*

## Frequencies of each variant in all samples and some stats about them,
## more to the point, these are Hardy Weinberg equilibrium test results.
## This file was created because of the 'doHWE' argument above.
less all_filtered.hwe.gz | head

## Relative frequency of each allele for every site in the data.
## I think that this should be closely related to the HWE above.
## This file was created because of the 'doMaf' argument above.
less all_filtered.mafs.gz | head

## Summary statistics for every variant.
## This file was created because of the 'doSnpStat' above.
less all_filtered.snpStat.gz | head
## -rw-rw-r-- 1 trey 10186    8192 Aug  2 14:27 all_filtered.arg
## -rw-rw-r-- 1 trey 10186 2082575 Aug  2 19:10 all_filtered.hwe.gz
## -rw-rw-r-- 1 trey 10186  986600 Aug  2 19:10 all_filtered.mafs.gz
## -rw-rw-r-- 1 trey 10186 5466471 Aug  2 19:15 all_filtered.snpStat.gz
## Chromo   Position    Major   Minor   hweFreq Freq    F   LRT p-value
## LpaL13_01    44  C   T   0.031864    0.059486    0.999106    1.211539e+01    5.000728e-04
## LpaL13_01    63  T   C   0.095021    0.202719    0.999691    1.712653e+01    3.497047e-05
## LpaL13_01    66  T   C   0.091056    0.186261    0.999670    1.527911e+01    9.273653e-05
## LpaL13_01    160 C   A   0.101253    0.091189    0.999397    1.791205e+01    2.313519e-05
## LpaL13_01    258 G   A   0.028581    0.028755    -0.026026   4.757321e-02    8.273412e-01
## LpaL13_01    260 A   G   0.028582    0.028756    -0.026027   4.757476e-02    8.273384e-01
## LpaL13_01    262 A   G   0.028642    0.028818    -0.026101   4.780990e-02    8.269190e-01
## LpaL13_01    295 C   T   0.206553    0.208134    -0.262234   3.614116e+00    5.729116e-02
## LpaL13_01    444 A   C   0.021996    0.030348    0.998301    7.336812e+00    6.755654e-03
## chromo   position    major   minor   unknownEM   pu-EM   nInd
## LpaL13_01    44  C   T   0.031862    5.854110e-05    34
## LpaL13_01    63  T   C   0.095021    0.000000e+00    33
## LpaL13_01    66  T   C   0.091057    0.000000e+00    33
## LpaL13_01    160 C   A   0.101254    0.000000e+00    33
## LpaL13_01    258 G   A   0.028577    1.901286e-04    32
## LpaL13_01    260 A   G   0.028575    3.826105e-04    32
## LpaL13_01    262 A   G   0.028635    3.811637e-04    32
## LpaL13_01    295 C   T   0.206554    0.000000e+00    33
## LpaL13_01    444 A   C   0.021995    3.330669e-16    33
## Chromo   Position    +Major +Minor -Major -Minor SB1:SB2:SB3 HWE_LRT:HWE_pval    baseQ_Z:baseQ_pval  mapQ_Z:mapQ_pval    edge_z:edge_pval
## LpaL13_01    44  634 9 125 0 1.194401:0.014163:0.368423  12.115394:5.000727e-04  -1.975427:4.821962e-02  -3.989394:6.627263e-05  -3.040978:2.358248e-03
## LpaL13_01    63  413 23 260 0    1.596330:0.054555:0.000025  17.126526:3.497047e-05  -1.694273:9.021327e-02  -8.113846:4.440892e-16  -1.390011:1.645257e-01
## LpaL13_01    66  361 23 301 0    1.783854:0.061977:0.000001  15.279108:9.273653e-05  -1.452362:1.464010e-01  -8.123046:4.440892e-16  -2.426678:1.523779e-02
## LpaL13_01    160 1012 120 854 70 0.327331:0.107952:0.021459  17.912048:2.313519e-05  -6.342156:2.275872e-10  -4.224533:2.395913e-05  -6.494033:8.397893e-11
## LpaL13_01    258 488 3 16 0  1.032587:0.006146:1.000000  0.047573:8.273412e-01   -1.588945:1.120728e-01  -0.515814:6.059841e-01  -2.440731:1.465759e-02
## LpaL13_01    260 483 3 16 0  1.032922:0.006210:1.000000  0.047575:8.273384e-01   -1.485042:1.375328e-01  -0.520962:6.023931e-01  -2.530958:1.137518e-02
## LpaL13_01    262 481 3 17 0  1.035124:0.006236:1.000000  0.047810:8.269190e-01   -1.464012:1.431908e-01  -0.516004:6.058515e-01  -2.696022:7.017410e-03
## LpaL13_01    295 1053 106 348 103    -1.054767:0.238448:0.000000 3.614116:5.729116e-02   -3.947932:7.886299e-05  -4.633368:3.601517e-06  -8.565749:0.000000e+00
## LpaL13_01    444 97 3 992 3  4.924749:0.030074:0.012061  7.336812:6.755654e-03   -2.679576:7.371634e-03  0.000000:1.000000e+00   -0.678308:4.975762e-01

2.2 Site Frequency Spectrum

This provides a distribution of alleles at polymorphic sites. As the authors put it, “inferring the SFS from low coverage sequencing data in a straightforward manner by using genotype calls can lead to significant bias.”

Again, I am relatively ignorant of population genetics, so I am paraphrasing the authors’ paper; but it looks like these statistics provide proxies for measurements of various processes which may be uncovered by a population genetics study: expansions, bottlenecks, migration. It also appears to be the starting statistic for later analyses.

In order to perform this, one must have an ancestral genome and the set of alignments. In our case, the ancestral must be the panamensis reference, which I copied to reference/lpanamensis.fasta

I will run it once with and once without filtering.

module add angsd
## Index the reference
samtools faidx reference/lpanamensis.fasta

## The doSaf argument may be 1-4:
## 1: assume HWE
## 2: include inbreeding coefficients (which we cannot)
## 3: Use a prior distribution for all sites to calculate posterior
##    probabilities, potentially two pass from an existing -doSaf 1
## 4: Calculate posterior probabilities from genotype probabilities,
##    potentially two pass after using the '-beagle' options.

## Do no filtering
angsd -b all_samples.lst \
      -gl 1 -anc reference/lpanamensis.fasta \
      -doSaf 1 -out all_saf_unfiltered
realSFS all_saf_unfiltered.saf.idx > all_saf_unfiltered_realsfs.txt

## Filter for high quality hits
angsd -b all_samples.lst \
      -gl 1 -anc reference/lpanamensis.fasta \
      -doSaf 1 -baq 1 \
      -C 50 -minMapQ 30 \
      -minQ 20 -out all_saf_filtered
realSFS all_saf_filtered.saf.idx > all_saf_filtered_realsfs.txt
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))
LS0tCnRpdGxlOiAiRXhwbG9yaW5nIHBvcHVsYXRpb24gZ2VuZXRpY3Mgd2l0aCBBTkdTRCBhbmQgUExJTksuIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogZmFsc2UKICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UKICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB3aWR0aDogMzAwCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCiAgQmlvY1N0eWxlOjpodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keSwgdGQgewogIGZvbnQtc2l6ZTogMTZweDsKfQpjb2RlLnJ7CiAgZm9udC1zaXplOiAxNnB4Owp9CnByZSB7CiBmb250LXNpemU6IDE2cHgKfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeSgiaHBnbHRvb2xzIikKdHQgPC0gZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHdpZHRoPTEyMCwKICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgZHBpPTk2KQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cz00LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsPSJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQ9IiVZJW0lZCIpCnByZXZpb3VzX2ZpbGUgPC0gIiIKdmVyIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCAiJVklbSVkIikKCiMjdG1wIDwtIHNtKGxvYWRtZShmaWxlbmFtZT1wYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXByZXZpb3VzX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikpKQpybWRfZmlsZSA8LSAiYW5nc2RfcGxpbmsuUm1kIgpgYGAKCiMgSW50cm9kdWN0aW9uCgpJIGFtIGhvcGluZyB0byBsZWFybiBzb21lIHRhc2tzIG9uZSBtYXkgcGVyZm9ybSBmb3IgaGlnaC10aHJvdWdocHV0CnBvcHVsYXRpb24gZ2VuZXRpY3MuICBUaGlzIGlzIGEgcmVhbG0gaW4gd2hpY2ggSSBoYXZlIHZlcnkgbGltaXRlZAp1bmRlcnN0YW5kaW5nLCBzbyBmb3IgdGhlIG1vbWVudCBJIGFtIHJlbHlpbmcgdXBvbiB0aGUgQU5HU0QgYW5kIFBMSU5LCmRvY3VtZW50YXRpb24gYW5kIGhvcGluZyB0aGF0IEkgd2lsbCB1bmRlcnN0YW5kIG1vcmUgYXMgSSBjb250aW51ZQp0aHJvdWdoIHRoZW0uCgojIEluaXRpYWwgQU5HU0QgdGFza3MKCk9uZSBpbXBvcnRhbnQgY2F2ZWF0IGFib3V0IHRoZSBmb2xsb3dpbmcuICBJbiB0aGlzIGl0ZXJhdGlvbiBJIGFtIG9ubHkKaW5jbHVkaW5nIHNhbXBsZXMgZm9yIHdoaWNoIHdlIGhhdmUga25vd24gYW5ub3RhdGlvbnMgb2YgdGhlCnp5bW9kZW1lLiAgQXQgdGhlIHRpbWUgb2YgdGhpcyB3cml0aW5nLCB0aGF0IGxpbWl0cyB0aGUgc2NvcGUgb2YgdGhpcwpkb2N1bWVudCB0byAzNSBzYW1wbGVzICgxNiAyLjIgYW5kIDE5IDIuMyBzYW1wbGVzKS4gIEkgZG8gbm90IHJlYWxseQprbm93IGlmIHRoaXMgaXMgc3VmZmljaWVudCBmb3IgYSB2YWxpZCBhbmFseXNpcywgYnV0IGl0IGRvZXMgbm90Cl9zZWVtXyB1bnJlYXNvbmFibGUgZm9yIGEgZmlyc3QgcGFzcy4KCiMjIEZpbHRlcmluZyB0aGUgJ3JhdycgZGF0YQoKTXkgdW5kZXJzdGFuZGluZzogdGhlIGZpcnN0IHRhc2sgdG8gcGVyZm9ybSBpcyB0byByZWFkIGluIHRoZQphbGlnbm1lbnRzIGFnYWluc3QgdGhlIHJlZmVyZW5jZSBnZW5vbWUgYW5kIGZpbHRlciB0aGVtLiAgVGh1cyBJCmNyZWF0ZWQgYSBzZXJpZXMgb2YgdGV4dCBmaWxlcyB3aXRoIHRoZSByZWxhdGl2ZSBsb2NhdGlvbnMgb2YgdGhlCnJlbGV2YW50IGJhbWZpbGVzLiAgSSBpbml0aWFsbHkgc2VwYXJhdGVkIHRoZW0gYnkgenltb2RlbWUsIGJ1dCBjYW1lCnRvIGEgcmVhbGl6YXRpb24gdGhhdCBpdCBpcyBiZXR0ZXIgdG8ga2VlcCB0aGVtIHRvZ2V0aGVyLgoKSW4gYWRkaXRpb24sIEkgdXNlZCB0aGlzICdsc3QnIGZpbGUgdG8gd3JpdGUgb3V0IGEgJ3NldCcgZmlsZSBpbiB0aGUKZm9ybWF0IGV4cGVjdGVkIGJ5IFBMSU5LLiAgSGVyZSBpcyBhIHNob3J0IGJhc2ggYmxvY2sgc2hvd2luZyB3aGF0IEkgZGlkOgoKYGBge2Jhc2ggYWxsX3NhbXBsZXN9CiMjIEkgc3ltbGlua2VkIHRoZSBwcmVwcm9jZXNzaW5nIGRpcmVjdG9yeSBmcm9tIG15IG1haW4gdHJlZS4KbHMgLWxkIHByZXByb2Nlc3NpbmcKCmhlYWQgYWxsX3NhbXBsZXMubHN0CmhlYWQgenltb2RlbWVfcGxpbmtfc2V0cy50eHQKYGBgCgpHaXZlbiB0aGVzZSB0ZXh0IGlucHV0cywgSSBmb2xsb3dlZCB0aGUgc25wRmlsdGVycyBzZWN0aW9uIG9mIHRoZQpBTkdTRCBtYW51YWw6Cgo8aHR0cDovL3BvcGdlbi5kay9hbmdzZC9pbmRleC5waHAvU25wRmlsdGVycz4KCmluIG9yZGVyIHRvIHBlcmZvcm0gd2hhdCBJIHRoaW5rIGFyZSBhcHByb3ByaWF0ZSBmaWx0ZXJzIGFuZCBpbml0aWFsCnN0YXRpc3RpY3MgYXMgcGVyIHRoZSBmb2xsb3dpbmcgYmxvY2suICBJIGNob3NlIG5vdCB0byBkbyBnZW5vdHlwZQpjYWxsaW5nIGJlY2F1c2UgdGhlIGF1dGhvcnMgc3VnZ2VzdGVkIGFnYWluc3QgaXQ6IAoKIldlIHJlYWxseSBkb24ndCByZWNvbW1lbmQgZG9pbmcgYW5hbHlzaXMgYmFzZWQgb24gY2FsbGVkIGdlbm90eXBlcywKYnV0IGluY29ycG9yYXRlIHRoZSB1bmNlcnRhaW50eSBkaXJlY3RseSBpbnRvIHRoZSBhbmFseXNpcyB5b3Ugd2FudCB0bwpwZXJmb3JtLiBCdXQgd2UgcmVjb2duaXNlIHRoYXQgbWFueSBtZXRob2RzIGFyZSBzdGlsbCByZWx5aW5nIG9uCmNhbGxlZCBnZW5vdHlwZXMsIGFuZCBoYXZlIHRoZXJlZm9yZSBpbXBsZW1lbnRlZCBhIGJhc2ljIGdlbm90eXBlCmNhbGxlciBpbnRvIGFuZ3NkLiIKCmBgYHtiYXNoIGFuZ3NkX2ZpbHRlciwgZXZhbD1GQUxTRX0KbW9kdWxlIGFkZCBhbmdzZAphbmdzZCAtYiBhbGxfc2FtcGxlcy5sc3QgXAogICAgICAtZG9IV0UgMSAtR0wgMSBcCiAgICAgIC1kb01ham9yTWlub3IgMSAtZG9NYWYgMiBcCiAgICAgIC1zbnBfcHZhbCAxZS0yIC1QIDUgXAogICAgICAtZG9zbnBzdGF0IDEgLW91dCBhbGxfZmlsdGVyZWQKIyMgU29tZSBvdGhlciBwb3NzaWJsZSBsaWtlbHkgb3B0aW9uczoKIyMgLWRvR2VubyBwZXJmb3JtcyBnZW5vdHlwZSBjYWxsaW5nLiAgSXQgdGFrZXMgdGhlIHN1bSBvZjoKIyMgIDE6IG1ham9yL21pbm9yIGNhbGxzLAojIyAgMjogd3JpdGUgb3V0IGNhbGxlZCBnZW5vdHlwZSBlbmNvZGVkIGFzIC0xLDAsMSwyLi4uCiMjICA0OiB3cml0ZSBjYWxsZWQgZ2Vub3R5cGUgZGlyZWN0bHkgYXMgQUEsQUMsLi4uCiMjICA4OiB3cml0ZSBwb3N0ZXJpb3IgcHJvYmFiaWxpdGllcyBvZiBhbGwgZ2Vub3R5cGVzCiMjICAxNiwzMjogb3RoZXIgcG9zdGVyaW9ycwojIyAgICBJdCBsb29rcyBsaWtlIGEgbGlrZWx5IHZhbHVlIGlzIHRoZXJlZm9yZSAtZG9HZW5vIDMgb3IgNTUKIyMKIyMgLWRvUG9zdCBJIHRoaW5rIGlzIHJlc3BvbnNpYmxlIGZvciBkb2luZyB0aGUgcG9zdGVyaW9yCiMjICAgcHJvYmFiaWxpdGllcywgdGhlIGRvY3VtZW50YXRpb24gaXMgYSBsaXR0bGUgc3BhcnNlIGhlcmUuCmBgYAoKVGhlIHJlc3VsdGluZyBvdXRwdXQgZmlsZXMgYXJlIGhlcmU6CgpgYGB7YmFzaCBhbmdzZF9maWx0ZXJfb3V0fQpscyAtYWwgYWxsX2ZpbHRlcmVkKgoKIyMgRnJlcXVlbmNpZXMgb2YgZWFjaCB2YXJpYW50IGluIGFsbCBzYW1wbGVzIGFuZCBzb21lIHN0YXRzIGFib3V0IHRoZW0sCiMjIG1vcmUgdG8gdGhlIHBvaW50LCB0aGVzZSBhcmUgSGFyZHkgV2VpbmJlcmcgZXF1aWxpYnJpdW0gdGVzdCByZXN1bHRzLgojIyBUaGlzIGZpbGUgd2FzIGNyZWF0ZWQgYmVjYXVzZSBvZiB0aGUgJ2RvSFdFJyBhcmd1bWVudCBhYm92ZS4KbGVzcyBhbGxfZmlsdGVyZWQuaHdlLmd6IHwgaGVhZAoKIyMgUmVsYXRpdmUgZnJlcXVlbmN5IG9mIGVhY2ggYWxsZWxlIGZvciBldmVyeSBzaXRlIGluIHRoZSBkYXRhLgojIyBJIHRoaW5rIHRoYXQgdGhpcyBzaG91bGQgYmUgY2xvc2VseSByZWxhdGVkIHRvIHRoZSBIV0UgYWJvdmUuCiMjIFRoaXMgZmlsZSB3YXMgY3JlYXRlZCBiZWNhdXNlIG9mIHRoZSAnZG9NYWYnIGFyZ3VtZW50IGFib3ZlLgpsZXNzIGFsbF9maWx0ZXJlZC5tYWZzLmd6IHwgaGVhZAoKIyMgU3VtbWFyeSBzdGF0aXN0aWNzIGZvciBldmVyeSB2YXJpYW50LgojIyBUaGlzIGZpbGUgd2FzIGNyZWF0ZWQgYmVjYXVzZSBvZiB0aGUgJ2RvU25wU3RhdCcgYWJvdmUuCmxlc3MgYWxsX2ZpbHRlcmVkLnNucFN0YXQuZ3ogfCBoZWFkCmBgYAoKIyMgU2l0ZSBGcmVxdWVuY3kgU3BlY3RydW0KClRoaXMgcHJvdmlkZXMgYSBkaXN0cmlidXRpb24gb2YgYWxsZWxlcyBhdCBwb2x5bW9ycGhpYyBzaXRlcy4gIEFzIHRoZQphdXRob3JzIHB1dCBpdCwgImluZmVycmluZyB0aGUgU0ZTIGZyb20gbG93IGNvdmVyYWdlIHNlcXVlbmNpbmcgZGF0YQppbiBhIHN0cmFpZ2h0Zm9yd2FyZCBtYW5uZXIgYnkgdXNpbmcgZ2Vub3R5cGUgY2FsbHMgY2FuIGxlYWQgdG8Kc2lnbmlmaWNhbnQgYmlhcy4iCgpBZ2FpbiwgSSBhbSByZWxhdGl2ZWx5IGlnbm9yYW50IG9mIHBvcHVsYXRpb24gZ2VuZXRpY3MsIHNvIEkgYW0KcGFyYXBocmFzaW5nIHRoZSBhdXRob3JzJyBwYXBlcjsgYnV0IGl0IGxvb2tzIGxpa2UgdGhlc2Ugc3RhdGlzdGljcwpwcm92aWRlIHByb3hpZXMgZm9yIG1lYXN1cmVtZW50cyBvZiB2YXJpb3VzIHByb2Nlc3NlcyB3aGljaCBtYXkgYmUKdW5jb3ZlcmVkIGJ5IGEgcG9wdWxhdGlvbiBnZW5ldGljcyBzdHVkeTogZXhwYW5zaW9ucywgYm90dGxlbmVja3MsCm1pZ3JhdGlvbi4gIEl0IGFsc28gYXBwZWFycyB0byBiZSB0aGUgc3RhcnRpbmcgc3RhdGlzdGljIGZvciBsYXRlcgphbmFseXNlcy4KCkluIG9yZGVyIHRvIHBlcmZvcm0gdGhpcywgb25lIG11c3QgaGF2ZSBhbiBhbmNlc3RyYWwgZ2Vub21lIGFuZCB0aGUKc2V0IG9mIGFsaWdubWVudHMuICBJbiBvdXIgY2FzZSwgdGhlIGFuY2VzdHJhbCBtdXN0IGJlIHRoZSBwYW5hbWVuc2lzCnJlZmVyZW5jZSwgd2hpY2ggSSBjb3BpZWQgdG8gcmVmZXJlbmNlL2xwYW5hbWVuc2lzLmZhc3RhCgpJIHdpbGwgcnVuIGl0IG9uY2Ugd2l0aCBhbmQgb25jZSB3aXRob3V0IGZpbHRlcmluZy4KCmBgYHtiYXNoIHJ1bl9zZnMsIGV2YWw9RkFMU0V9Cm1vZHVsZSBhZGQgYW5nc2QKIyMgSW5kZXggdGhlIHJlZmVyZW5jZQpzYW10b29scyBmYWlkeCByZWZlcmVuY2UvbHBhbmFtZW5zaXMuZmFzdGEKCiMjIFRoZSBkb1NhZiBhcmd1bWVudCBtYXkgYmUgMS00OgojIyAxOiBhc3N1bWUgSFdFCiMjIDI6IGluY2x1ZGUgaW5icmVlZGluZyBjb2VmZmljaWVudHMgKHdoaWNoIHdlIGNhbm5vdCkKIyMgMzogVXNlIGEgcHJpb3IgZGlzdHJpYnV0aW9uIGZvciBhbGwgc2l0ZXMgdG8gY2FsY3VsYXRlIHBvc3RlcmlvcgojIyAgICBwcm9iYWJpbGl0aWVzLCBwb3RlbnRpYWxseSB0d28gcGFzcyBmcm9tIGFuIGV4aXN0aW5nIC1kb1NhZiAxCiMjIDQ6IENhbGN1bGF0ZSBwb3N0ZXJpb3IgcHJvYmFiaWxpdGllcyBmcm9tIGdlbm90eXBlIHByb2JhYmlsaXRpZXMsCiMjICAgIHBvdGVudGlhbGx5IHR3byBwYXNzIGFmdGVyIHVzaW5nIHRoZSAnLWJlYWdsZScgb3B0aW9ucy4KCiMjIERvIG5vIGZpbHRlcmluZwphbmdzZCAtYiBhbGxfc2FtcGxlcy5sc3QgXAogICAgICAtZ2wgMSAtYW5jIHJlZmVyZW5jZS9scGFuYW1lbnNpcy5mYXN0YSBcCiAgICAgIC1kb1NhZiAxIC1vdXQgYWxsX3NhZl91bmZpbHRlcmVkCnJlYWxTRlMgYWxsX3NhZl91bmZpbHRlcmVkLnNhZi5pZHggPiBhbGxfc2FmX3VuZmlsdGVyZWRfcmVhbHNmcy50eHQKCiMjIEZpbHRlciBmb3IgaGlnaCBxdWFsaXR5IGhpdHMKYW5nc2QgLWIgYWxsX3NhbXBsZXMubHN0IFwKICAgICAgLWdsIDEgLWFuYyByZWZlcmVuY2UvbHBhbmFtZW5zaXMuZmFzdGEgXAogICAgICAtZG9TYWYgMSAtYmFxIDEgXAogICAgICAtQyA1MCAtbWluTWFwUSAzMCBcCiAgICAgIC1taW5RIDIwIC1vdXQgYWxsX3NhZl9maWx0ZXJlZApyZWFsU0ZTIGFsbF9zYWZfZmlsdGVyZWQuc2FmLmlkeCA+IGFsbF9zYWZfZmlsdGVyZWRfcmVhbHNmcy50eHQKYGBgCgoKCgpgYGB7ciBzYXZlbWUsIGV2YWw9RkFMU0V9CnBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCm1lc3NhZ2UocGFzdGUwKCJUaGlzIGlzIGhwZ2x0b29scyBjb21taXQ6ICIsIGdldF9naXRfY29tbWl0KCkpKQp0aGlzX3NhdmUgPC0gcGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1ybWRfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKQptZXNzYWdlKHBhc3RlMCgiU2F2aW5nIHRvICIsIHRoaXNfc2F2ZSkpCnRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWU9dGhpc19zYXZlKSkKYGBgCg==