Intro/Overview

Just going to show how to create lots of data sets that can then be run through new hybrids. We create our own nomenclature so that the directory name tells us about the simulation.

library(tidyverse)
library(stringr)
library(SalarHybPower)

We also want to have some example data. We will just use the Nova Scotia data. But we will call this dat:

dat <- readRDS("intermediates/01/tidy-west.rds") %>%
  mutate(pop = str_sub(id, 1, 3),
         group = ifelse(pop == "AQU" | pop == "WLN", "farmed", "wild"))

First, count how many individuals we have from each wild population:

dat %>%
  group_by(pop) %>%
  summarize(num = n_distinct(id))

This means that if we are doing F2’s for LHR we will only be able to make 4 or 5 per time, and for backcrosses, we will only get about 4 per data set out of them. OK. Well, let us not worry about the number of individuals we get from each population. Let’s just do SPLITS different splits of the data into training and holdout…

Set up some info for the sims:

SPLITS <- 3 # the number of times to split the data and rank markers
LOCS <- c(24, 48, 144, 192, 480, 720, 1000)  # number of loci
POPLIST <- c("BDN", "CNR", "GRR", "LHR", "LPR")  # names of wild populations
HYB_CATS <- c("PureW", "PureF", "F1", "F2", "BX")

Then just cycle over things and do it

main_out_dir <- "nh_reps_directory"
dir.create(main_out_dir)
set.seed(555)
for (s in 1:SPLITS) {
  SAR <- split_and_rank(dat)
  for (pop in POPLIST) {
    for (hc in HYB_CATS) {
      for (locs in LOCS) {
        dirname <- paste(s,pop,hc,locs, sep = "_")
        create_hybrid_dataset(SAR = SAR, wild_pop = pop, hyb_cat = hc, L = locs, 
                              dir = file.path(main_out_dir, dirname))
      }
    }
  }
  
}

That takes a few minutes and creates a large number of directories, (like 525 or so), each with a single simulated data set in it.
The directories are named like this: 1_GRR_PureF_480 which denotes:

Now I just need to run NewHybrids over each like this:

~/Documents/git-repos/newhybrids/newhybs -d nh_data.txt -g P0 1 0 0 -g p1 0 0 1 -g F1 0 1 0 -g F2 .25 .5 .25 -g BX0 .5 .5 0 -g BX1 0 .5 .5 --pi-prior fixed  1 1 1 1 1 1

We will do that using the GNU parallel script.

Creating a GNU parallel script

We could use the parallel R package, but I have had better success using GNU parallel – a Perl script. I have included it in the bin directory in the repo.

We basically need to write a series of shell commands, each one launching newhybrids on a different data set.

We can use R to write those out. Note that this all assumes that the nh_reps_directory is in the top level of the repository, and that the command to run parallel will be given in that nh_reps_directory. Note that it is imporant to divert stderr to a newhybs_stderr file so we can search for cases that had underflow issues. I am going to do 100 burn in and 500 sweeps, cuz we can do short runs when we are working with having some indivs of known origin.

comms <- lapply(dir("nh_reps_directory"), function(x) {
  paste0("echo \"Starting ", 
         x, 
         " at $(date)\"; cd ", 
         x, 
         "; ../../bin/newhybs -d nh_data.txt -g P0 1 0 0 -g p1 0 0 1 -g F1 0 1 0 -g F2 .25 .5 .25 -g BX0 .5 .5 0 -g BX1 0 .5 .5 --pi-prior fixed  1 1 1 1 1 1 --no-gui --burn-in 100 --num-sweeps 500 --seeds ",
         paste(ceiling(runif(2, min = 100, max = 10000000)), collapse = " "), 
         " > newhybs_stdout.txt 2> newhybs_stderr.txt; cd ..; echo \"Done with ", x, " at $(date)\"")
})
cat(unlist(comms), sep = "\n", file = "para-comms.txt")

I synced all that to our 24 core box and then put the runs on 22 cores:

2017-06-20 14:44 /nh_reps_directory/--% (master) pwd
/Users/eriq/Documents/git-repos/SalarHybPower/nh_reps_directory

# then put it on 22 cores:
2017-06-20 14:45 /nh_reps_directory/--% (master) cat ../para-comms.txt | ../bin/parallel -P22 > ../BIG_LOG.txt &

When doing such short runs, this seems to take less than an hour…

Slurping up the output

Since this is on the big machine at work, it will be easiest for me to grab the output using awk over ssh:

2017-06-21 05:57 /nh_reps_directory/--% (master) pwd
/Users/eriq/Documents/git-repos/SalarHybPower/nh_reps_directory

for i in *; do 
  warn=$(wc -l $i/newhybs_stderr.txt | awk '{print $1}'); 
  awk -v w=$warn -v i=$i 'NR>1 && !/train_/ {print i, w, $0}' $i/aa-PofZ.txt;
done  > ../3_splits_output.txt

Then I gzipped that and brought it over to the outputs folder in the repository (but which I won’t commit…)

Reading in the output, and making a quick plot

First, a job for readr:

nh_output <- read_table2("outputs/3_splits_output.txt.gz",   # requires readr 1.1.1
                         col_names = c("sim", "warn", "idx", "iname", 
                                       "pure_farmed", "pure_wild", "F1", "F2", "bx_farm", "bx_wild"))
Parsed with column specification:
cols(
  sim = col_character(),
  warn = col_integer(),
  idx = col_integer(),
  iname = col_character(),
  pure_farmed = col_double(),
  pure_wild = col_double(),
  F1 = col_double(),
  F2 = col_double(),
  bx_farm = col_double(),
  bx_wild = col_double()
)

Then separate some columns and then gather

nh_sepped <- nh_output %>%
  separate(col = sim, into = c("split", "pop", "true_hyb_cat", "num_loci"), sep = "_", convert = TRUE) %>%
  separate(col = iname, into = c("drop", "s_idx"), sep = "_", convert = TRUE) %>% 
  mutate(s_idx = paste("split", split, s_idx, sep = "_")) %>%
  select(-drop) 

Really quickly, check which runs received warnings:

nh_sepped %>%
  filter(warn > 0)

OK, all of them have num_loci = 1000.

Let’s just filter out the ones that had warnings and gather it, and make a infferred_hyb_cat a factor so it comes out in a good order in the plots.

nh_tidy <- nh_sepped %>% 
  filter(warn == 0) %>% 
  gather(key = "inferred_hyb_cat", value = "post_prob", pure_farmed:bx_wild) %>%
  mutate(inferred_hyb_cat = factor(inferred_hyb_cat, levels = c("bx_wild", "bx_farm", "F2", "F1", "pure_wild", "pure_farmed")))
# and save this
saveRDS(nh_tidy, file = "outputs/3_splits_nh_tidy.rds", compress = "xz")

And now we should be able to plot it.

# some colors that might work out better than ggplots defaults
hc_colors <- c(
  pure_farmed = rgb(152, 78, 163, maxColorValue = 255), # purple
  pure_wild = rgb(77, 175, 74, maxColorValue = 255), # green
  F1 = rgb(255, 255, 51, maxColorValue = 255),  # yellow
  F2 = rgb(247, 129, 191, maxColorValue = 255), # pink
  bx_wild = rgb(255, 127, 0, maxColorValue = 255),  # orange
  bx_farm = rgb(228, 26, 28, maxColorValue = 255) # red
)
nh_list <- nh_tidy %>% 
  split(., .$true_hyb_cat)
gg_list <- lapply(nh_list, function(x) {
  g <- ggplot(x, aes(x = s_idx, y = post_prob, fill = inferred_hyb_cat)) +
    geom_col() +
    facet_grid(num_loci ~ pop) +
    scale_fill_manual(values = hc_colors)
  
  g
})
dump <- lapply(names(gg_list), function(n) {
  ggsave(gg_list[[n]], 
         filename = paste0("outputs/first_look_", n, ".pdf"),
         width = 10, 
         height = 10)})

I will send those figures to Brendan.

From my first looking over of them, there are a couple of trends it seems to me:

LS0tCnRpdGxlOiAiTWFraW5nIE11bHRpcGxlIERhdGEgU2V0cyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMgc2V0IHRoZSB3b3JraW5nIGRpcmVjdG9yeSBhbHdheXMgdG8gdGhlIHByb2plY3QgZGlyZWN0b3J5IChvbmUgbGV2ZWwgdXApCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gbm9ybWFsaXplUGF0aChycHJvanJvb3Q6OmZpbmRfcnN0dWRpb19yb290X2ZpbGUoKSkpIApgYGAKCgojIyBJbnRyby9PdmVydmlldwoKSnVzdCBnb2luZyB0byBzaG93IGhvdyB0byBjcmVhdGUgbG90cyBvZiBkYXRhIHNldHMgdGhhdCBjYW4gdGhlbiBiZSBydW4gdGhyb3VnaCBuZXcgaHlicmlkcy4KV2UgY3JlYXRlIG91ciBvd24gbm9tZW5jbGF0dXJlIHNvIHRoYXQgdGhlIGRpcmVjdG9yeSBuYW1lIHRlbGxzIHVzIGFib3V0IHRoZSBzaW11bGF0aW9uLgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoU2FsYXJIeWJQb3dlcikKYGBgCgpXZSBhbHNvIHdhbnQgdG8gaGF2ZSBzb21lIGV4YW1wbGUgZGF0YS4gIFdlIHdpbGwganVzdCB1c2UgdGhlIE5vdmEgU2NvdGlhIGRhdGEuIEJ1dCB3ZSB3aWxsCmNhbGwgdGhpcyBkYXQ6CmBgYHtyfQpkYXQgPC0gcmVhZFJEUygiaW50ZXJtZWRpYXRlcy8wMS90aWR5LXdlc3QucmRzIikgJT4lCiAgbXV0YXRlKHBvcCA9IHN0cl9zdWIoaWQsIDEsIDMpLAogICAgICAgICBncm91cCA9IGlmZWxzZShwb3AgPT0gIkFRVSIgfCBwb3AgPT0gIldMTiIsICJmYXJtZWQiLCAid2lsZCIpKQpgYGAKCkZpcnN0LCBjb3VudCBob3cgbWFueSBpbmRpdmlkdWFscyB3ZSBoYXZlIGZyb20gZWFjaCB3aWxkIHBvcHVsYXRpb246CmBgYHtyfQpkYXQgJT4lCiAgZ3JvdXBfYnkocG9wKSAlPiUKICBzdW1tYXJpemUobnVtID0gbl9kaXN0aW5jdChpZCkpCmBgYAoKVGhpcyBtZWFucyB0aGF0IGlmIHdlIGFyZSBkb2luZyBGMidzIGZvciBMSFIgd2Ugd2lsbCBvbmx5IGJlIGFibGUgdG8gbWFrZSA0IG9yIDUgcGVyIHRpbWUsCmFuZCBmb3IgYmFja2Nyb3NzZXMsIHdlIHdpbGwgb25seSBnZXQgYWJvdXQgNCBwZXIgZGF0YSBzZXQgb3V0IG9mIHRoZW0uICBPSy4gIFdlbGwsIGxldCB1cyAKbm90IHdvcnJ5IGFib3V0IHRoZSBudW1iZXIgb2YgaW5kaXZpZHVhbHMgd2UgZ2V0IGZyb20gZWFjaCBwb3B1bGF0aW9uLiAgTGV0J3MganVzdCBkbyBTUExJVFMgCmRpZmZlcmVudCBzcGxpdHMgb2YgdGhlIGRhdGEgaW50byB0cmFpbmluZyBhbmQgaG9sZG91dC4uLgoKClNldCB1cCBzb21lIGluZm8gZm9yIHRoZSBzaW1zOgpgYGB7cn0KU1BMSVRTIDwtIDMgIyB0aGUgbnVtYmVyIG9mIHRpbWVzIHRvIHNwbGl0IHRoZSBkYXRhIGFuZCByYW5rIG1hcmtlcnMKTE9DUyA8LSBjKDI0LCA0OCwgMTQ0LCAxOTIsIDQ4MCwgNzIwLCAxMDAwKSAgIyBudW1iZXIgb2YgbG9jaQpQT1BMSVNUIDwtIGMoIkJETiIsICJDTlIiLCAiR1JSIiwgIkxIUiIsICJMUFIiKSAgIyBuYW1lcyBvZiB3aWxkIHBvcHVsYXRpb25zCkhZQl9DQVRTIDwtIGMoIlB1cmVXIiwgIlB1cmVGIiwgIkYxIiwgIkYyIiwgIkJYIikKYGBgCgpUaGVuIGp1c3QgY3ljbGUgb3ZlciB0aGluZ3MgYW5kIGRvIGl0CmBgYHtyLCBldmFsPUZBTFNFfQptYWluX291dF9kaXIgPC0gIm5oX3JlcHNfZGlyZWN0b3J5IgpkaXIuY3JlYXRlKG1haW5fb3V0X2RpcikKc2V0LnNlZWQoNTU1KQpmb3IgKHMgaW4gMTpTUExJVFMpIHsKICBTQVIgPC0gc3BsaXRfYW5kX3JhbmsoZGF0KQogIGZvciAocG9wIGluIFBPUExJU1QpIHsKICAgIGZvciAoaGMgaW4gSFlCX0NBVFMpIHsKICAgICAgZm9yIChsb2NzIGluIExPQ1MpIHsKICAgICAgICBkaXJuYW1lIDwtIHBhc3RlKHMscG9wLGhjLGxvY3MsIHNlcCA9ICJfIikKICAgICAgICBjcmVhdGVfaHlicmlkX2RhdGFzZXQoU0FSID0gU0FSLCB3aWxkX3BvcCA9IHBvcCwgaHliX2NhdCA9IGhjLCBMID0gbG9jcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpciA9IGZpbGUucGF0aChtYWluX291dF9kaXIsIGRpcm5hbWUpKQogICAgICB9CiAgICB9CiAgfQogIAp9CgpgYGAKClRoYXQgdGFrZXMgYSBmZXcgbWludXRlcyBhbmQgY3JlYXRlcyBhIGxhcmdlIG51bWJlciBvZiBkaXJlY3RvcmllcywgKGxpa2UgNTI1IG9yIHNvKSwgZWFjaCB3aXRoIGEgc2luZ2xlIHNpbXVsYXRlZCBkYXRhIHNldCBpbiBpdC4gIApUaGUgZGlyZWN0b3JpZXMgYXJlIG5hbWVkIGxpa2UgdGhpczogYDFfR1JSX1B1cmVGXzQ4MGAgIHdoaWNoIGRlbm90ZXM6CgotIFNwbGl0ID0gMQotIFBvcHVsYXRpb24gPSBHUlIKLSBTaW11bGF0ZWQgaHlicmlkIGNhdGVnb3J5ID0gUHVyZSBGYXJtZWQKLSBOdW1iZXIgb2YgbG9jaSA9IDQ4MAoKCgoKTm93IEkganVzdCBuZWVkIHRvIHJ1biBOZXdIeWJyaWRzIG92ZXIgZWFjaCBsaWtlIHRoaXM6CmBgYHNoCn4vRG9jdW1lbnRzL2dpdC1yZXBvcy9uZXdoeWJyaWRzL25ld2h5YnMgLWQgbmhfZGF0YS50eHQgLWcgUDAgMSAwIDAgLWcgcDEgMCAwIDEgLWcgRjEgMCAxIDAgLWcgRjIgLjI1IC41IC4yNSAtZyBCWDAgLjUgLjUgMCAtZyBCWDEgMCAuNSAuNSAtLXBpLXByaW9yIGZpeGVkICAxIDEgMSAxIDEgMQpgYGAKCldlIHdpbGwgZG8gdGhhdCB1c2luZyB0aGUgR05VIHBhcmFsbGVsIHNjcmlwdC4KCiMjIENyZWF0aW5nIGEgR05VIHBhcmFsbGVsIHNjcmlwdAoKV2UgY291bGQgdXNlIHRoZSBgcGFyYWxsZWxgIFIgcGFja2FnZSwgYnV0IEkgaGF2ZSBoYWQgYmV0dGVyIHN1Y2Nlc3MgdXNpbmcgR05VIHBhcmFsbGVsIC0tIGEgUGVybCBzY3JpcHQuICBJIGhhdmUgaW5jbHVkZWQgaXQgaW4gdGhlIApgYmluYCBkaXJlY3RvcnkgaW4gdGhlIHJlcG8uCgpXZSBiYXNpY2FsbHkgbmVlZCB0byB3cml0ZSBhIHNlcmllcyBvZiBzaGVsbCBjb21tYW5kcywgZWFjaCBvbmUgbGF1bmNoaW5nIG5ld2h5YnJpZHMgb24gYSBkaWZmZXJlbnQgZGF0YSBzZXQuCgpXZSBjYW4gdXNlIFIgdG8gd3JpdGUgdGhvc2Ugb3V0LiAgTm90ZSB0aGF0IHRoaXMgYWxsIGFzc3VtZXMgdGhhdCB0aGUgYG5oX3JlcHNfZGlyZWN0b3J5YCBpcyBpbiB0aGUgdG9wIGxldmVsCm9mIHRoZSByZXBvc2l0b3J5LCBhbmQgdGhhdCB0aGUgY29tbWFuZCB0byBydW4gcGFyYWxsZWwgd2lsbCBiZSBnaXZlbiBpbiB0aGF0IG5oX3JlcHNfZGlyZWN0b3J5LgpOb3RlIHRoYXQgaXQgaXMgaW1wb3JhbnQgdG8gZGl2ZXJ0IHN0ZGVyciB0byBhIG5ld2h5YnNfc3RkZXJyIGZpbGUgc28gd2UgY2FuIHNlYXJjaCBmb3IgY2FzZXMKdGhhdCBoYWQgdW5kZXJmbG93IGlzc3Vlcy4gIEkgYW0gZ29pbmcgdG8gZG8gMTAwIGJ1cm4gaW4gYW5kIDUwMCBzd2VlcHMsIGN1eiB3ZSBjYW4gZG8gc2hvcnQgcnVucwp3aGVuIHdlIGFyZSB3b3JraW5nIHdpdGggaGF2aW5nIHNvbWUgaW5kaXZzIG9mIGtub3duIG9yaWdpbi4KYGBge3J9CmNvbW1zIDwtIGxhcHBseShkaXIoIm5oX3JlcHNfZGlyZWN0b3J5IiksIGZ1bmN0aW9uKHgpIHsKICBwYXN0ZTAoImVjaG8gXCJTdGFydGluZyAiLCAKICAgICAgICAgeCwgCiAgICAgICAgICIgYXQgJChkYXRlKVwiOyBjZCAiLCAKICAgICAgICAgeCwgCiAgICAgICAgICI7IC4uLy4uL2Jpbi9uZXdoeWJzIC1kIG5oX2RhdGEudHh0IC1nIFAwIDEgMCAwIC1nIHAxIDAgMCAxIC1nIEYxIDAgMSAwIC1nIEYyIC4yNSAuNSAuMjUgLWcgQlgwIC41IC41IDAgLWcgQlgxIDAgLjUgLjUgLS1waS1wcmlvciBmaXhlZCAgMSAxIDEgMSAxIDEgLS1uby1ndWkgLS1idXJuLWluIDEwMCAtLW51bS1zd2VlcHMgNTAwIC0tc2VlZHMgIiwKICAgICAgICAgcGFzdGUoY2VpbGluZyhydW5pZigyLCBtaW4gPSAxMDAsIG1heCA9IDEwMDAwMDAwKSksIGNvbGxhcHNlID0gIiAiKSwgCiAgICAgICAgICIgPiBuZXdoeWJzX3N0ZG91dC50eHQgMj4gbmV3aHlic19zdGRlcnIudHh0OyBjZCAuLjsgZWNobyBcIkRvbmUgd2l0aCAiLCB4LCAiIGF0ICQoZGF0ZSlcIiIpCn0pCmNhdCh1bmxpc3QoY29tbXMpLCBzZXAgPSAiXG4iLCBmaWxlID0gInBhcmEtY29tbXMudHh0IikKYGBgCgpJIHN5bmNlZCBhbGwgdGhhdCB0byBvdXIgMjQgY29yZSBib3ggYW5kIHRoZW4gcHV0IHRoZSBydW5zIG9uIDIyIGNvcmVzOgpgYGBzaAoyMDE3LTA2LTIwIDE0OjQ0IC9uaF9yZXBzX2RpcmVjdG9yeS8tLSUgKG1hc3RlcikgcHdkCi9Vc2Vycy9lcmlxL0RvY3VtZW50cy9naXQtcmVwb3MvU2FsYXJIeWJQb3dlci9uaF9yZXBzX2RpcmVjdG9yeQoKIyB0aGVuIHB1dCBpdCBvbiAyMiBjb3JlczoKMjAxNy0wNi0yMCAxNDo0NSAvbmhfcmVwc19kaXJlY3RvcnkvLS0lIChtYXN0ZXIpIGNhdCAuLi9wYXJhLWNvbW1zLnR4dCB8IC4uL2Jpbi9wYXJhbGxlbCAtUDIyID4gLi4vQklHX0xPRy50eHQgJgoKYGBgCgpXaGVuIGRvaW5nIHN1Y2ggc2hvcnQgcnVucywgdGhpcyBzZWVtcyB0byB0YWtlIGxlc3MgdGhhbiBhbiBob3VyLi4uCgojIyBTbHVycGluZyB1cCB0aGUgb3V0cHV0CgpTaW5jZSB0aGlzIGlzIG9uIHRoZSBiaWcgbWFjaGluZSBhdCB3b3JrLCBpdCB3aWxsIGJlIGVhc2llc3QgZm9yIG1lIHRvIGdyYWIKdGhlIG91dHB1dCB1c2luZyBhd2sgb3ZlciBzc2g6CmBgYHNoCjIwMTctMDYtMjEgMDU6NTcgL25oX3JlcHNfZGlyZWN0b3J5Ly0tJSAobWFzdGVyKSBwd2QKL1VzZXJzL2VyaXEvRG9jdW1lbnRzL2dpdC1yZXBvcy9TYWxhckh5YlBvd2VyL25oX3JlcHNfZGlyZWN0b3J5Cgpmb3IgaSBpbiAqOyBkbyAKICB3YXJuPSQod2MgLWwgJGkvbmV3aHlic19zdGRlcnIudHh0IHwgYXdrICd7cHJpbnQgJDF9Jyk7IAogIGF3ayAtdiB3PSR3YXJuIC12IGk9JGkgJ05SPjEgJiYgIS90cmFpbl8vIHtwcmludCBpLCB3LCAkMH0nICRpL2FhLVBvZloudHh0Owpkb25lICA+IC4uLzNfc3BsaXRzX291dHB1dC50eHQKCgpgYGAKVGhlbiBJIGd6aXBwZWQgdGhhdCBhbmQgYnJvdWdodCBpdCBvdmVyIHRvIHRoZSBgb3V0cHV0c2AgZm9sZGVyIGluIHRoZSByZXBvc2l0b3J5IChidXQgd2hpY2ggCkkgd29uJ3QgY29tbWl0Li4uKQoKIyMgUmVhZGluZyBpbiB0aGUgb3V0cHV0LCBhbmQgbWFraW5nIGEgcXVpY2sgcGxvdAoKRmlyc3QsIGEgam9iIGZvciByZWFkcjoKYGBge3J9Cm5oX291dHB1dCA8LSByZWFkX3RhYmxlMigib3V0cHV0cy8zX3NwbGl0c19vdXRwdXQudHh0Lmd6IiwgICAjIHJlcXVpcmVzIHJlYWRyIDEuMS4xCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBjKCJzaW0iLCAid2FybiIsICJpZHgiLCAiaW5hbWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInB1cmVfZmFybWVkIiwgInB1cmVfd2lsZCIsICJGMSIsICJGMiIsICJieF9mYXJtIiwgImJ4X3dpbGQiKSkKYGBgCgpUaGVuIHNlcGFyYXRlIHNvbWUgY29sdW1ucyBhbmQgdGhlbiBnYXRoZXIKYGBge3J9Cm5oX3NlcHBlZCA8LSBuaF9vdXRwdXQgJT4lCiAgc2VwYXJhdGUoY29sID0gc2ltLCBpbnRvID0gYygic3BsaXQiLCAicG9wIiwgInRydWVfaHliX2NhdCIsICJudW1fbG9jaSIpLCBzZXAgPSAiXyIsIGNvbnZlcnQgPSBUUlVFKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBpbmFtZSwgaW50byA9IGMoImRyb3AiLCAic19pZHgiKSwgc2VwID0gIl8iLCBjb252ZXJ0ID0gVFJVRSkgJT4lIAogIG11dGF0ZShzX2lkeCA9IHBhc3RlKCJzcGxpdCIsIHNwbGl0LCBzX2lkeCwgc2VwID0gIl8iKSkgJT4lCiAgc2VsZWN0KC1kcm9wKSAKCgpgYGAKClJlYWxseSBxdWlja2x5LCBjaGVjayB3aGljaCBydW5zIHJlY2VpdmVkIHdhcm5pbmdzOgpgYGB7cn0Kbmhfc2VwcGVkICU+JQogIGZpbHRlcih3YXJuID4gMCkKYGBgCgpPSywgYWxsIG9mIHRoZW0gaGF2ZSBudW1fbG9jaSA9IDEwMDAuCgpMZXQncyBqdXN0IGZpbHRlciBvdXQgdGhlIG9uZXMgdGhhdCBoYWQgd2FybmluZ3MgYW5kIGdhdGhlciBpdCwgYW5kIG1ha2UgYSBpbmZmZXJyZWRfaHliX2NhdCBhCmZhY3RvciBzbyBpdCBjb21lcyBvdXQgaW4gYSBnb29kIG9yZGVyIGluIHRoZSBwbG90cy4KYGBge3J9Cm5oX3RpZHkgPC0gbmhfc2VwcGVkICU+JSAKICBmaWx0ZXIod2FybiA9PSAwKSAlPiUgCiAgZ2F0aGVyKGtleSA9ICJpbmZlcnJlZF9oeWJfY2F0IiwgdmFsdWUgPSAicG9zdF9wcm9iIiwgcHVyZV9mYXJtZWQ6Ynhfd2lsZCkgJT4lCiAgbXV0YXRlKGluZmVycmVkX2h5Yl9jYXQgPSBmYWN0b3IoaW5mZXJyZWRfaHliX2NhdCwgbGV2ZWxzID0gYygiYnhfd2lsZCIsICJieF9mYXJtIiwgIkYyIiwgIkYxIiwgInB1cmVfd2lsZCIsICJwdXJlX2Zhcm1lZCIpKSkKCiMgYW5kIHNhdmUgdGhpcwpzYXZlUkRTKG5oX3RpZHksIGZpbGUgPSAib3V0cHV0cy8zX3NwbGl0c19uaF90aWR5LnJkcyIsIGNvbXByZXNzID0gInh6IikKYGBgCgpBbmQgbm93IHdlIHNob3VsZCBiZSBhYmxlIHRvIHBsb3QgaXQuCmBgYHtyfQojIHNvbWUgY29sb3JzIHRoYXQgbWlnaHQgd29yayBvdXQgYmV0dGVyIHRoYW4gZ2dwbG90cyBkZWZhdWx0cwpoY19jb2xvcnMgPC0gYygKICBwdXJlX2Zhcm1lZCA9IHJnYigxNTIsIDc4LCAxNjMsIG1heENvbG9yVmFsdWUgPSAyNTUpLCAjIHB1cnBsZQogIHB1cmVfd2lsZCA9IHJnYig3NywgMTc1LCA3NCwgbWF4Q29sb3JWYWx1ZSA9IDI1NSksICMgZ3JlZW4KICBGMSA9IHJnYigyNTUsIDI1NSwgNTEsIG1heENvbG9yVmFsdWUgPSAyNTUpLCAgIyB5ZWxsb3cKICBGMiA9IHJnYigyNDcsIDEyOSwgMTkxLCBtYXhDb2xvclZhbHVlID0gMjU1KSwgIyBwaW5rCiAgYnhfd2lsZCA9IHJnYigyNTUsIDEyNywgMCwgbWF4Q29sb3JWYWx1ZSA9IDI1NSksICAjIG9yYW5nZQogIGJ4X2Zhcm0gPSByZ2IoMjI4LCAyNiwgMjgsIG1heENvbG9yVmFsdWUgPSAyNTUpICMgcmVkCikKCm5oX2xpc3QgPC0gbmhfdGlkeSAlPiUgCiAgc3BsaXQoLiwgLiR0cnVlX2h5Yl9jYXQpCgpnZ19saXN0IDwtIGxhcHBseShuaF9saXN0LCBmdW5jdGlvbih4KSB7CiAgZyA8LSBnZ3Bsb3QoeCwgYWVzKHggPSBzX2lkeCwgeSA9IHBvc3RfcHJvYiwgZmlsbCA9IGluZmVycmVkX2h5Yl9jYXQpKSArCiAgICBnZW9tX2NvbCgpICsKICAgIGZhY2V0X2dyaWQobnVtX2xvY2kgfiBwb3ApICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGhjX2NvbG9ycykKICAKICBnCn0pCgpkdW1wIDwtIGxhcHBseShuYW1lcyhnZ19saXN0KSwgZnVuY3Rpb24obikgewogIGdnc2F2ZShnZ19saXN0W1tuXV0sIAogICAgICAgICBmaWxlbmFtZSA9IHBhc3RlMCgib3V0cHV0cy9maXJzdF9sb29rXyIsIG4sICIucGRmIiksCiAgICAgICAgIHdpZHRoID0gMTAsIAogICAgICAgICBoZWlnaHQgPSAxMCl9KQpgYGAKCkkgd2lsbCBzZW5kIHRob3NlIGZpZ3VyZXMgdG8gQnJlbmRhbi4KCkZyb20gbXkgZmlyc3QgbG9va2luZyBvdmVyIG9mIHRoZW0sIHRoZXJlIGFyZSBhIGNvdXBsZSBvZiB0cmVuZHMgaXQgc2VlbXMgdG8gbWU6CgotIFBvcHVsYXRpb25zIHdpdGggZmV3ZXIgaW5kaXZpZHVhbHMgaGF2ZSBmZXdlciBzaW11bGF0ZWQgaW5kaXZpZHVhbHMtLS10aGF0IGlzIHdoeSB0aGVyZSBhcmUgZ2FwcyBpbiB0aGVyZS4KKHRob3VnaCBzb21lIG9mIHRoZSBiaWcgZ2FwcyBhdCAxMDAwIGxvY2kgYXJlIGR1ZSB0byB0aGUgZmFjdCB0aGF0IG5ld2h5YnJpZHMgaGFzIHVuZGVyZmxvdyBwcm9ibGVtcyB3aXRoIApsb3RzIG9mIGxvY2kuKQoKLSBJdCBpcyBpbXBvcnRhbnQgdG8gdW5kZXJzdGFuZCB0aGF0IEkgc2ltdWxhdGVkIGluZGl2aWR1YWxzIGZyb20gc2VwYXJhdGUgcG9wdWxhdGlvbnMgcmF0aGVyCnRoYW4gc2x1cnJ5aW5nIHRoZWlyIGFsbGVsZXMgdG9nZXRoZXIgdG8gbWFrZSBhIG1lYW4td2lsZC1hbGxlbGUtZnJlcSBwb29sLiAgRnJvbSB0aGUgcmVzdWx0cywgaXQgaXMKY2xlYXIgdGhhdCBkaWZmZXJlbnQgcG9wdWxhdGlvbnMgbXVzdCBoYXZlIGRpZmZlcmVudCBhbGxlbGUgZnJlcXVlbmNpZXMsIHN1Y2ggdGhhdCB3aGVuIGFsbCB0aGUgdHJhaW5pbmcgaW5kaXZpZHVhbHMKYXJlIHVzZWQgYXMgcmVmZXJlbmNlIHdpbGQgYW5kIGZhcm1lZCBmaXNoIHdpdGggdGhlIGB6YCBvcHRpb24gaW4gTmV3SHlicmlkcywgc29tZSB3aWxkIGZpc2ggb2Ygc29tZSBwb3B1bGF0aW9ucwplbmQgdXAgbG9va2luZyBsaWtlIGJ4X3dpbGRzLCBldGMuICBfYW5kXyBzb21lIHB1cmUgRmFybWVkIGZpc2ggbG9vayBsaWtlIGJ4X2Zhcm1zLiAgVGhlIGxhdHRlciBpcyBub3Qgc28gYmFkLCBJIHdvdWxkIHRoaW5rLApiZWNhdXNlIHlvdSBkb24ndCByZWFsbHkgZXhwZWN0IGJ4X2Zhcm1lZCB0byBvY2N1ciwgYXMgb2Z0ZW4gaW4gdGhlIHBvcHVsYXRpb25zLgoKLSBJdCBpcyBpbnRlcmVzdGluZyB0aGF0IHRoZSB0cnVseS1wdXJlIGZhcm1lZCBmaXNoIGFyZSBpbmNvcnJlY3RseSBpbmZlcnJlZCB0byBiZSBieF9mYXJtIGZpc2ggYXQgYSBoaWdoZXIgcmF0ZSB3aXRoCm1vcmUgbG9jaS4gIEkgaGF2ZSBjaGVja2VkIG15IHNpbXVsYXRpb24gcHJvZ3JhbXMgYW5kIEkgZG9uJ3QgdGhpbmsgdGhleSBhcmUgaW5jb3JyZWN0LiAgSSB0aGluayBpdCBtaWdodCBoYXZlIHRvIGRvIAp3aXRoIHVzaW5nIGEgbWl4dHVyZSBvZiBwb3B1bGF0aW9ucyBpbiB0aGUgZmlzaCB3aXRoIHRoZSBgemAgb3B0aW9uLgoKLSBJdCBtaWdodCBiZSBiZXR0ZXIgdG8gcnVuIG5ld2h5YnJpZHMgd2l0aCB3aWxkIHRyYWluaW5nIGluZGl2aWR1YWxzIGJlaW5nIGluY2x1ZGVkIGFuZCBnZXR0aW5nIHRoZSBgemAgb3B0aW9uCl9vbmx5IGlmIHRoZXkgYXJlIGZyb20gdGhlIHNhbWUgcG9wdWxhdGlvbiBhcyB0aGUgc2FtcGxlZCAoc2ltdWxhdGVkKSBoeWJyaWRzLl8gIFRoaXMgaXMgdGhlIG5leHQgdGhpbmcgSSBuZWVkIAp0byBnZXQgb24sIGJ1dCB3YW50ZWQgdG8gc2VuZCB0aGVzZSByZXN1bHRzIG9uIGZvciBub3cuCgotIEZvciBzb21lIG9mIHRoZSBwb3B1bGF0aW9ucywgbGlrZSBCRE4sIENOUiwgYW5kIExIUiBpdCBsb29rcyBsaWtlIGh5YnJpZHMvZmFybWVkIGZpc2ggY2FuIGJlIGlkZW50aWZpZWQKcHJldHR5IHJlbGlhYmx5LiAgRm9yIEdSUiBhbmQgTFBSLCBpdCBpcyBhIGxpdHRsZSB0b3VnaGVyIGFzIHRoZXJlIGlzIGEgbG90IG9mIG92ZXJsYXAgYmV0d2VlbiBwdXJlIHdpbGQgYW5kIApiYWNrY3Jvc3NlZCBmaXNoLiAgCg==