1 Introduction

This is a hopefully straight forward comparison of 5 mouse DNA samples vs. the mm38 reference in order to find if/what changes have occurred in the colony and show that they are minimal and unrelated to the various ribosomal tagging processes.

FIXME: The previous paragraph is a woefully incomplete and bad representation of the goals of the project, I am assuming that when we meet I can acquire from Colenso’s team a more complete understanding of the goals.

2 Meeting notes 20230929

Information on the mouse: https://jax.org/strain/029977

  • wt: both normal copies of melanopsin, does include tagged RPL22.
  • KO: cre recombinase instead of melanopsin (across all 9 exons)
  • het samples: Two samples are ‘low expression’ (I am not going to write down which is which lest I skew the result somehow), expecting a single copy of melanopsin. The ‘old’ sample has higher levels of melanopsin and theoretically should have 1 copy as well; but they are observed to have higher expression in the bulk rna sequencing.

What are the most likely useful metrics? I am guessing some plots from IGV showing variants surrounding/in RPL22 and melanopsin. Other genes/loci of note?

So I can use my variant finder to compare the 5 samples with a specific goal of looking at how/if het_722C_old has variants which are relevant. The assumption is that the other samples will be otherwise relatively wt with the expected exceptions.

Images/worksheets which are useful?

  • I am guessing a heatmap showing the similarities across samples.
  • worksheet showing loci with near 0 coverage.
  • worksheet showing differential variants in specific samples

3 Preprocessing

The initial preprocessing of the samples should be relatively consistent.

It is worth noting that I have a pre-defined pipeline of tasks that I usually perform for DNA sequencing data, but am choosing not to use it because I do not know what all I want to play with in this dataset.

3.1 Trimming the raw reads

The following is what I ran on our cluster. It in turn created a series of trimomatic scripts which are responsible for trimming the data in preparation for mapping.

Another note: the sequencer already does an appropriate trimming process. This step is likely redundant and probably can be skipped entirely, however I like to run it still because of the quality check it adds; and upon completion it aggressively recompresses the data.

cd preprocessing
start=$(pwd)
for i in $(/bin/ls -d * | grep -v sequencer); do
    cd $i
    echo "Starting $i"
    cyoa --method trim --input $(/bin/ls | tr '\n' ':' | sed 's/:$//g')
    cd $start
done

3.1.1 A trimming script

The following is the actual trimming script for one sample. (It is actually the KO sample because my fingers hit ‘k’ when I went looking for an example).

#!/usr/bin/bash
#SBATCH --export=ALL --requeue --mail-type=NONE --open-mode=append
#SBATCH --chdir=/home/trey/sshfs/scratch/atb/dnaseq/mmusculus_iprgc_2023/preprocessing/KO_810B
#SBATCH --job-name=01trim_KO_810B_S3_R1_001 --nice=0
#SBATCH --output=outputs/log.txt.sbatch
#SBATCH --nodes=1 --ntasks=1 --cpus-per-task=4
#SBATCH --time=36:00:00
#SBATCH --mem=24G
set -o errexit
set -o errtrace
set -o pipefail
export LESS='--buffers 0 -B'
echo "## Started /home/trey/sshfs/scratch/atb/dnaseq/mmusculus_iprgc_2023/preprocessing/KO_810B/scripts/01trim_KO_810B_S3_R1_001.sh at $(date) on $(hostname) with id ${SLURM_JOBID}." >> outputs/log.txt
mod=$( { type -t module || true; } )
if [[ -z "${mod}" ]]; then
  module() {
  # shellcheck disable=SC2086
    eval "$(/usr/bin/modulecmd bash $*)"
  }
  export -f module
fi
module purge
module add  trimomatic 2>/dev/null 1>&2
## This call to trimomatic removes illumina and epicentre adapters from KO_810B_S3_R1_001.fastq.gz:KO_810B_S3_R2_001.fastq.gz.
## It also performs a sliding window removal of anything with quality <25;
## cutadapt provides an alternative to this tool.
## The original sequence data is recompressed and saved in the sequences/ directory.
mkdir -p outputs/01trimomatic
## Note that trimomatic prints all output and errors to STDERR, so send both to output
TrimmomaticPE \
  -threads 1 \
  -phred33 \
  KO_810B_S3_R1_001.fastq.gz KO_810B_S3_R2_001.fastq.gz \
  KO_810B_S3_R1_001-trimmed_paired.fastq KO_810B_S3_R1_001-trimmed_unpaired.fastq \
  KO_810B_S3_R2_001-trimmed_paired.fastq KO_810B_S3_R2_001-trimmed_unpaired.fastq \
   ILLUMINACLIP:/sw/local/cyoa/202302/prefix/lib/perl5/auto/share/dist/Bio-Adventure/genome/adapters.fa:2:20:10:2:keepBothReads  \
  SLIDINGWINDOW:4:20 MINLEN:50 \
  1>outputs/01trimomatic/KO_810B_S3_R1_001-trimomatic.stdout \
  2>outputs/01trimomatic/KO_810B_S3_R1_001-trimomatic.stderr
excepted=$( { grep "Exception" "outputs/01trimomatic/KO_810B_S3_R1_001-trimomatic.stdout" || test $? = 1; } )
## The following is in case the illumina clipping fails, which it does if this has already been run I think.
if [[ "${excepted}" != "" ]]; then
  TrimmomaticPE \
    -threads 1 \
    -phred33 \
    KO_810B_S3_R1_001.fastq.gz KO_810B_S3_R2_001.fastq.gz \
    KO_810B_S3_R1_001-trimmed_paired.fastq KO_810B_S3_R1_001-trimmed_unpaired.fastq \
    KO_810B_S3_R2_001-trimmed_paired.fastq KO_810B_S3_R2_001-trimmed_unpaired.fastq \
     SLIDINGWINDOW:4:25 MINLEN:50 \
    1>outputs/01trimomatic/KO_810B_S3_R1_001-trimomatic.stdout \
    2>outputs/01trimomatic/KO_810B_S3_R1_001-trimomatic.stderr
fi
sleep 10
mv KO_810B_S3_R1_001-trimmed_paired.fastq KO_810B_S3_R1_001-trimmed.fastq
mv KO_810B_S3_R2_001-trimmed_paired.fastq KO_810B_S3_R2_001-trimmed.fastq

## Recompress the unpaired reads, this should not take long.
xz -9e -f KO_810B_S3_R1_001-trimmed_unpaired.fastq
xz -9e -f KO_810B_S3_R2_001-trimmed_unpaired.fastq
## Recompress the paired reads.
xz -9e -f KO_810B_S3_R1_001-trimmed.fastq
xz -9e -f KO_810B_S3_R2_001-trimmed.fastq
ln -sf KO_810B_S3_R1_001-trimmed.fastq.xz r1_trimmed.fastq.xz
ln -sf KO_810B_S3_R2_001-trimmed.fastq.xz r2_trimmed.fastq.xz



## The following lines give status codes and some logging
minutes_used=$(( SECONDS / 60 ))
echo "  $(hostname) Finished ${SLURM_JOBID} 01trim_KO_810B_S3_R1_001.sh at $(date), it took ${minutes_used} minutes." >> outputs/log.txt
if [[ -x "$(command -v sstat)" && -n "${SLURM_JOBID}" ]]; then
  echo "  walltime used by ${SLURM_JOBID} was: ${minutes_used:-null} minutes." >> outputs/log.txt
  maxmem=$(sstat -n -P --format=MaxVMSize -j "${SLURM_JOBID}")
  ## I am not sure why, but when I run a script in an interactive session, the maxmem variable
  ## gets set correctly everytime, but when it is run by another node, sometimes it does not.
  ## Lets try and figure that out...
  echo "TESTME: ${maxmem}"
  if [[ -n "${maxmem}" ]]; then
    echo "  maximum memory used by ${SLURM_JOBID} was: ${maxmem}." >> outputs/log.txt
  else
    echo "  The maximum memory did not get set for this job: ${SLURM_JOBID}." >> outputs/log.txt
    sstat -P -j "${SLURM_JOBID}" >> outputs/log.txt
  fi
  echo "" >> outputs/log.txt
fi
touch outputs/logs/01trim_KO_810B_S3_R1_001.finished

4 Mapping

cd preprocessing
start=$(pwd)
for i in $(/bin/ls -d * | grep -v sequencer); do
    cd $i
    echo "Starting $i"
    cyoa --method hisat --species mm38_100 --input r1_trimmed.fastq.xz:r2_trimmed.fastq.xz \
         --gff_type gene --gff_tag gene_id --stranded reverse
    cd $start
done

Interestingly, I went over my memory allocation for these mapping jobs for 2 of them. As a result I had to rerun them manually.

5 Extracting variants

cd preprocessing
start=$(pwd)
for i in $(/bin/ls -d * | grep -v sequencer); do
    cd $i
    echo "Starting $i"
    cyoa --method freebayes --species mm38_100 --input outputs/40hisat_mm38_100/mm38_100_genome.bam \
         --gff_type gene --gff_tag gene_id --stranded reverse --intron 1
    cd $start
done
pander::pander(sessionInfo())

R version 4.2.0 (2022-04-22)

Platform: x86_64-pc-linux-gnu (64-bit)

locale: LC_CTYPE=en_US.UTF-8, LC_NUMERIC=C, LC_TIME=en_US.UTF-8, LC_COLLATE=en_US.UTF-8, LC_MONETARY=en_US.UTF-8, LC_MESSAGES=en_US.UTF-8, LC_PAPER=en_US.UTF-8, LC_NAME=C, LC_ADDRESS=C, LC_TELEPHONE=C, LC_MEASUREMENT=en_US.UTF-8 and LC_IDENTIFICATION=C

attached base packages: stats4, stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: hpgltools(v.1.0), testthat(v.3.1.8), reticulate(v.1.28), glue(v.1.6.2), SummarizedExperiment(v.1.28.0), GenomicRanges(v.1.50.2), GenomeInfoDb(v.1.34.9), IRanges(v.2.32.0), S4Vectors(v.0.36.2), MatrixGenerics(v.1.10.0), matrixStats(v.0.63.0), Biobase(v.2.58.0) and BiocGenerics(v.0.44.0)

loaded via a namespace (and not attached): utf8(v.1.2.3), RUnit(v.0.4.32), tidyselect(v.1.2.0), lme4(v.1.1-33), RSQLite(v.2.3.1), AnnotationDbi(v.1.60.2), htmlwidgets(v.1.6.2), grid(v.4.2.0), BiocParallel(v.1.32.6), scatterpie(v.0.1.9), devtools(v.2.4.5), munsell(v.0.5.0), codetools(v.0.2-19), miniUI(v.0.1.1.1), withr(v.2.5.0), colorspace(v.2.1-0), GOSemSim(v.2.24.0), filelock(v.1.0.2), knitr(v.1.44), rstudioapi(v.0.14), DOSE(v.3.24.2), Rdpack(v.2.4), GenomeInfoDbData(v.1.2.9), polyclip(v.1.10-4), farver(v.2.1.1), bit64(v.4.0.5), downloader(v.0.4), rprojroot(v.2.0.3), treeio(v.1.22.0), vctrs(v.0.6.3), generics(v.0.1.3), gson(v.0.1.0), clusterGeneration(v.1.3.7), xfun(v.0.39), BiocFileCache(v.2.6.1), R6(v.2.5.1), doParallel(v.1.0.17), graphlayouts(v.1.0.0), locfit(v.1.5-9.7), gridGraphics(v.0.5-1), bitops(v.1.0-7), cachem(v.1.0.8), fgsea(v.1.24.0), DelayedArray(v.0.24.0), promises(v.1.2.0.1), BiocIO(v.1.8.0), scales(v.1.2.1), ggraph(v.2.1.0), enrichplot(v.1.18.4), gtable(v.0.3.3), sva(v.3.46.0), processx(v.3.8.1), tidygraph(v.1.2.3), rlang(v.1.1.1), genefilter(v.1.80.3), splines(v.4.2.0), rtracklayer(v.1.58.0), lazyeval(v.0.2.2), broom(v.1.0.4), yaml(v.2.3.7), reshape2(v.1.4.4), GenomicFeatures(v.1.50.4), backports(v.1.4.1), httpuv(v.1.6.10), qvalue(v.2.30.0), clusterProfiler(v.4.6.2), tools(v.4.2.0), usethis(v.2.1.6), ggplotify(v.0.1.0), ggplot2(v.3.4.2), ellipsis(v.0.3.2), gplots(v.3.1.3), RColorBrewer(v.1.1-3), jquerylib(v.0.1.4), sessioninfo(v.1.2.2), Rcpp(v.1.0.10), plyr(v.1.8.8), progress(v.1.2.2), zlibbioc(v.1.44.0), purrr(v.1.0.1), RCurl(v.1.98-1.12), ps(v.1.7.5), prettyunits(v.1.1.1), remaCor(v.0.0.11), viridis(v.0.6.3), cowplot(v.1.1.1), urlchecker(v.1.0.1), ggrepel(v.0.9.3), fs(v.1.6.2), variancePartition(v.1.28.9), magrittr(v.2.0.3), data.table(v.1.14.8), mvtnorm(v.1.1-3), pkgload(v.1.3.2), patchwork(v.1.1.2), hms(v.1.1.3), mime(v.0.12), evaluate(v.0.21), xtable(v.1.8-4), HDO.db(v.0.99.1), pbkrtest(v.0.5.2), RhpcBLASctl(v.0.23-42), XML(v.3.99-0.14), gridExtra(v.2.3), compiler(v.4.2.0), biomaRt(v.2.54.1), tibble(v.3.2.1), shadowtext(v.0.1.2), KernSmooth(v.2.23-21), crayon(v.1.5.2), minqa(v.1.2.5), htmltools(v.0.5.5), ggfun(v.0.0.9), mgcv(v.1.8-42), later(v.1.3.1), aplot(v.0.1.10), tidyr(v.1.3.0), DBI(v.1.1.3), tweenr(v.2.0.2), dbplyr(v.2.3.2), MASS(v.7.3-60), rappdirs(v.0.3.3), boot(v.1.3-28.1), Matrix(v.1.5-4), brio(v.1.1.3), cli(v.3.6.1), rbibutils(v.2.2.13), igraph(v.1.4.2), parallel(v.4.2.0), forcats(v.1.0.0), pkgconfig(v.2.0.3), GenomicAlignments(v.1.34.1), plotly(v.4.10.1), xml2(v.1.3.4), foreach(v.1.5.2), ggtree(v.3.6.2), annotate(v.1.76.0), bslib(v.0.4.2), XVector(v.0.38.0), yulab.utils(v.0.0.6), stringr(v.1.5.0), callr(v.3.7.3), digest(v.0.6.31), graph(v.1.76.0), Biostrings(v.2.66.0), rmarkdown(v.2.21), fastmatch(v.1.1-3), tidytree(v.0.4.2), edgeR(v.3.40.2), PROPER(v.1.30.0), GSEABase(v.1.60.0), restfulr(v.0.0.15), curl(v.5.0.1), shiny(v.1.7.4), Rsamtools(v.2.14.0), gtools(v.3.9.4), rjson(v.0.2.21), nloptr(v.2.0.3), lifecycle(v.1.0.3), nlme(v.3.1-162), jsonlite(v.1.8.7), aod(v.1.3.2), desc(v.1.4.2), viridisLite(v.0.4.2), limma(v.3.54.2), fansi(v.1.0.4), pillar(v.1.9.0), lattice(v.0.21-8), KEGGREST(v.1.38.0), fastmap(v.1.1.1), httr(v.1.4.6), pkgbuild(v.1.4.0), survival(v.3.5-5), GO.db(v.3.16.0), remotes(v.2.4.2), png(v.0.1-8), iterators(v.1.0.14), pander(v.0.6.5), bit(v.4.0.5), ggforce(v.0.4.1), stringi(v.1.7.12), sass(v.0.4.6), profvis(v.0.3.8), blob(v.1.2.4), caTools(v.1.18.2), memoise(v.2.0.1), dplyr(v.1.1.2) and ape(v.5.7-1)

message("This is hpgltools commit: ", get_git_commit())
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 169bc6dbf7ff8f90c297d2da5082d1bbc132566a
## This is hpgltools commit: Fri Sep 29 13:10:10 2023 -0400: 169bc6dbf7ff8f90c297d2da5082d1bbc132566a
this_save <- paste0(gsub(pattern = "\\.Rmd", replace = "", x = rmd_file), "-v", ver, ".rda.xz")
#message("Saving to ", this_save)
#tmp <- sm(saveme(filename = this_save))
LS0tCnRpdGxlOiAiU2VxdWVuY2luZyB0aGUgZ2Vub21lIG9mIDUgV1QvaGV0L0tPIElQUkdDIG1pY2U6IGByIFN5cy5nZXRlbnYoJ1ZFUlNJT04nKWAiCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGRmX3ByaW50OiBwYWdlZAogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICB3aWR0aDogMzAwCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCiAgQmlvY1N0eWxlOjpodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgpib2R5LCB0ZCB7CiAgZm9udC1zaXplOiAxNnB4Owp9CmNvZGUucnsKICBmb250LXNpemU6IDE2cHg7Cn0KcHJlIHsKIGZvbnQtc2l6ZTogMTZweAp9CmJvZHkgLm1haW4tY29udGFpbmVyIHsKICBtYXgtd2lkdGg6IDE2MDBweDsKfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShocGdsdG9vbHMpCmxpYnJhcnkocmV0aWN1bGF0ZSkKdHQgPC0gZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KAogIHByb2dyZXNzID0gVFJVRSwgdmVyYm9zZSA9IFRSVUUsIHdpZHRoID0gOTAsIGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZXJyb3IgPSBUUlVFLCBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gOCwgZmlnLnJldGluYSA9IDIsCiAgZmlnLnBvcyA9ICJ0IiwgZmlnLmFsaWduID0gImNlbnRlciIsIGRwaSA9IGlmIChrbml0cjo6aXNfbGF0ZXhfb3V0cHV0KCkpIDcyIGVsc2UgMzAwLAogIG91dC53aWR0aCA9ICIxMDAlIiwgZGV2ID0gInBuZyIsCiAgZGV2LmFyZ3MgPSBsaXN0KHBuZyA9IGxpc3QodHlwZSA9ICJjYWlyby1wbmciKSkpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzID0gNCwKICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsID0gImFsbG93IikKZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSkKdmVyIDwtIFN5cy5nZXRlbnYoIlZFUlNJT04iKQpwcmV2aW91c19maWxlIDwtICIiCgojI3RtcCA8LSBzbShsb2FkbWUoZmlsZW5hbWU9cGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1wcmV2aW91c19maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpKSkKcm1kX2ZpbGUgPC0gImluZGV4LlJtZCIKYGBgCgojIEludHJvZHVjdGlvbgoKVGhpcyBpcyBhIGhvcGVmdWxseSBzdHJhaWdodCBmb3J3YXJkIGNvbXBhcmlzb24gb2YgNSBtb3VzZSBETkEgc2FtcGxlcwp2cy4gdGhlIG1tMzggcmVmZXJlbmNlIGluIG9yZGVyIHRvIGZpbmQgaWYvd2hhdCBjaGFuZ2VzIGhhdmUgb2NjdXJyZWQKaW4gdGhlIGNvbG9ueSBhbmQgc2hvdyB0aGF0IHRoZXkgYXJlIG1pbmltYWwgYW5kIHVucmVsYXRlZCB0byB0aGUKdmFyaW91cyByaWJvc29tYWwgdGFnZ2luZyBwcm9jZXNzZXMuCgoqRklYTUUqOiBUaGUgcHJldmlvdXMgcGFyYWdyYXBoIGlzIGEgd29lZnVsbHkgaW5jb21wbGV0ZSBhbmQgYmFkCnJlcHJlc2VudGF0aW9uIG9mIHRoZSBnb2FscyBvZiB0aGUgcHJvamVjdCwgSSBhbSBhc3N1bWluZyB0aGF0IHdoZW4gd2UKbWVldCBJIGNhbiBhY3F1aXJlIGZyb20gQ29sZW5zbydzIHRlYW0gYSBtb3JlIGNvbXBsZXRlIHVuZGVyc3RhbmRpbmcKb2YgdGhlIGdvYWxzLgoKIyBNZWV0aW5nIG5vdGVzIDIwMjMwOTI5CgpJbmZvcm1hdGlvbiBvbiB0aGUgbW91c2U6IGh0dHBzOi8vamF4Lm9yZy9zdHJhaW4vMDI5OTc3CgoqIHd0OiBib3RoIG5vcm1hbCBjb3BpZXMgb2YgbWVsYW5vcHNpbiwgZG9lcyBpbmNsdWRlIHRhZ2dlZCBSUEwyMi4KKiBLTzogY3JlIHJlY29tYmluYXNlIGluc3RlYWQgb2YgbWVsYW5vcHNpbiAoYWNyb3NzIGFsbCA5IGV4b25zKQoqIGhldCBzYW1wbGVzOiBUd28gc2FtcGxlcyBhcmUgJ2xvdyBleHByZXNzaW9uJyAoSSBhbSBub3QgZ29pbmcgdG8KICB3cml0ZSBkb3duIHdoaWNoIGlzIHdoaWNoIGxlc3QgSSBza2V3IHRoZSByZXN1bHQgc29tZWhvdyksIGV4cGVjdGluZwogIGEgc2luZ2xlIGNvcHkgb2YgbWVsYW5vcHNpbi4gIFRoZSAnb2xkJyBzYW1wbGUgaGFzIGhpZ2hlciBsZXZlbHMgb2YKICBtZWxhbm9wc2luIGFuZCB0aGVvcmV0aWNhbGx5IHNob3VsZCBoYXZlIDEgY29weSBhcyB3ZWxsOyBidXQgdGhleQogIGFyZSBvYnNlcnZlZCB0byBoYXZlIGhpZ2hlciBleHByZXNzaW9uIGluIHRoZSBidWxrIHJuYSBzZXF1ZW5jaW5nLgoKV2hhdCBhcmUgdGhlIG1vc3QgbGlrZWx5IHVzZWZ1bCBtZXRyaWNzPyAgSSBhbSBndWVzc2luZyBzb21lIHBsb3RzCmZyb20gSUdWIHNob3dpbmcgdmFyaWFudHMgc3Vycm91bmRpbmcvaW4gUlBMMjIgYW5kIG1lbGFub3BzaW4uICBPdGhlcgpnZW5lcy9sb2NpIG9mIG5vdGU/CgpTbyBJIGNhbiB1c2UgbXkgdmFyaWFudCBmaW5kZXIgdG8gY29tcGFyZSB0aGUgNSBzYW1wbGVzIHdpdGggYQpzcGVjaWZpYyBnb2FsIG9mIGxvb2tpbmcgYXQgaG93L2lmIGhldF83MjJDX29sZCBoYXMgdmFyaWFudHMgd2hpY2ggYXJlCnJlbGV2YW50LiAgVGhlIGFzc3VtcHRpb24gaXMgdGhhdCB0aGUgb3RoZXIgc2FtcGxlcyB3aWxsIGJlIG90aGVyd2lzZQpyZWxhdGl2ZWx5IHd0IHdpdGggdGhlIGV4cGVjdGVkIGV4Y2VwdGlvbnMuCgpJbWFnZXMvd29ya3NoZWV0cyB3aGljaCBhcmUgdXNlZnVsPwoKKiBJIGFtIGd1ZXNzaW5nIGEgaGVhdG1hcCBzaG93aW5nIHRoZSBzaW1pbGFyaXRpZXMgYWNyb3NzIHNhbXBsZXMuCiogd29ya3NoZWV0IHNob3dpbmcgbG9jaSB3aXRoIG5lYXIgMCBjb3ZlcmFnZS4KKiB3b3Jrc2hlZXQgc2hvd2luZyBkaWZmZXJlbnRpYWwgdmFyaWFudHMgaW4gc3BlY2lmaWMgc2FtcGxlcwoKIyBQcmVwcm9jZXNzaW5nCgpUaGUgaW5pdGlhbCBwcmVwcm9jZXNzaW5nIG9mIHRoZSBzYW1wbGVzIHNob3VsZCBiZSByZWxhdGl2ZWx5CmNvbnNpc3RlbnQuCgpJdCBpcyB3b3J0aCBub3RpbmcgdGhhdCBJIGhhdmUgYSBwcmUtZGVmaW5lZCBwaXBlbGluZSBvZiB0YXNrcyB0aGF0IEkKdXN1YWxseSBwZXJmb3JtIGZvciBETkEgc2VxdWVuY2luZyBkYXRhLCBidXQgYW0gY2hvb3Npbmcgbm90IHRvIHVzZSBpdApiZWNhdXNlIEkgZG8gbm90IGtub3cgd2hhdCBhbGwgSSB3YW50IHRvIHBsYXkgd2l0aCBpbiB0aGlzIGRhdGFzZXQuCgojIyBUcmltbWluZyB0aGUgcmF3IHJlYWRzCgpUaGUgZm9sbG93aW5nIGlzIHdoYXQgSSByYW4gb24gb3VyIGNsdXN0ZXIuICBJdCBpbiB0dXJuIGNyZWF0ZWQgYQpzZXJpZXMgb2YgdHJpbW9tYXRpYyBzY3JpcHRzIHdoaWNoIGFyZSByZXNwb25zaWJsZSBmb3IgdHJpbW1pbmcgdGhlCmRhdGEgaW4gcHJlcGFyYXRpb24gZm9yIG1hcHBpbmcuCgpBbm90aGVyIG5vdGU6IHRoZSBzZXF1ZW5jZXIgYWxyZWFkeSBkb2VzIGFuIGFwcHJvcHJpYXRlIHRyaW1taW5nCnByb2Nlc3MuICBUaGlzIHN0ZXAgaXMgbGlrZWx5IHJlZHVuZGFudCBhbmQgcHJvYmFibHkgY2FuIGJlIHNraXBwZWQKZW50aXJlbHksIGhvd2V2ZXIgSSBsaWtlIHRvIHJ1biBpdCBzdGlsbCBiZWNhdXNlIG9mIHRoZSBxdWFsaXR5IGNoZWNrCml0IGFkZHM7IGFuZCB1cG9uIGNvbXBsZXRpb24gaXQgYWdncmVzc2l2ZWx5IHJlY29tcHJlc3NlcyB0aGUgZGF0YS4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCBwcmVwcm9jZXNzaW5nCnN0YXJ0PSQocHdkKQpmb3IgaSBpbiAkKC9iaW4vbHMgLWQgKiB8IGdyZXAgLXYgc2VxdWVuY2VyKTsgZG8KICAgIGNkICRpCiAgICBlY2hvICJTdGFydGluZyAkaSIKICAgIGN5b2EgLS1tZXRob2QgdHJpbSAtLWlucHV0ICQoL2Jpbi9scyB8IHRyICdcbicgJzonIHwgc2VkICdzLzokLy9nJykKICAgIGNkICRzdGFydApkb25lCmBgYAoKIyMjIEEgdHJpbW1pbmcgc2NyaXB0CgpUaGUgZm9sbG93aW5nIGlzIHRoZSBhY3R1YWwgdHJpbW1pbmcgc2NyaXB0IGZvciBvbmUgc2FtcGxlLiAoSXQgaXMKYWN0dWFsbHkgdGhlIEtPIHNhbXBsZSBiZWNhdXNlIG15IGZpbmdlcnMgaGl0ICdrJyB3aGVuIEkgd2VudCBsb29raW5nCmZvciBhbiBleGFtcGxlKS4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQojIS91c3IvYmluL2Jhc2gKI1NCQVRDSCAtLWV4cG9ydD1BTEwgLS1yZXF1ZXVlIC0tbWFpbC10eXBlPU5PTkUgLS1vcGVuLW1vZGU9YXBwZW5kCiNTQkFUQ0ggLS1jaGRpcj0vaG9tZS90cmV5L3NzaGZzL3NjcmF0Y2gvYXRiL2RuYXNlcS9tbXVzY3VsdXNfaXByZ2NfMjAyMy9wcmVwcm9jZXNzaW5nL0tPXzgxMEIKI1NCQVRDSCAtLWpvYi1uYW1lPTAxdHJpbV9LT184MTBCX1MzX1IxXzAwMSAtLW5pY2U9MAojU0JBVENIIC0tb3V0cHV0PW91dHB1dHMvbG9nLnR4dC5zYmF0Y2gKI1NCQVRDSCAtLW5vZGVzPTEgLS1udGFza3M9MSAtLWNwdXMtcGVyLXRhc2s9NAojU0JBVENIIC0tdGltZT0zNjowMDowMAojU0JBVENIIC0tbWVtPTI0RwpzZXQgLW8gZXJyZXhpdApzZXQgLW8gZXJydHJhY2UKc2V0IC1vIHBpcGVmYWlsCmV4cG9ydCBMRVNTPSctLWJ1ZmZlcnMgMCAtQicKZWNobyAiIyMgU3RhcnRlZCAvaG9tZS90cmV5L3NzaGZzL3NjcmF0Y2gvYXRiL2RuYXNlcS9tbXVzY3VsdXNfaXByZ2NfMjAyMy9wcmVwcm9jZXNzaW5nL0tPXzgxMEIvc2NyaXB0cy8wMXRyaW1fS09fODEwQl9TM19SMV8wMDEuc2ggYXQgJChkYXRlKSBvbiAkKGhvc3RuYW1lKSB3aXRoIGlkICR7U0xVUk1fSk9CSUR9LiIgPj4gb3V0cHV0cy9sb2cudHh0Cm1vZD0kKCB7IHR5cGUgLXQgbW9kdWxlIHx8IHRydWU7IH0gKQppZiBbWyAteiAiJHttb2R9IiBdXTsgdGhlbgogIG1vZHVsZSgpIHsKICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwODYKICAgIGV2YWwgIiQoL3Vzci9iaW4vbW9kdWxlY21kIGJhc2ggJCopIgogIH0KICBleHBvcnQgLWYgbW9kdWxlCmZpCm1vZHVsZSBwdXJnZQptb2R1bGUgYWRkICB0cmltb21hdGljIDI+L2Rldi9udWxsIDE+JjIKIyMgVGhpcyBjYWxsIHRvIHRyaW1vbWF0aWMgcmVtb3ZlcyBpbGx1bWluYSBhbmQgZXBpY2VudHJlIGFkYXB0ZXJzIGZyb20gS09fODEwQl9TM19SMV8wMDEuZmFzdHEuZ3o6S09fODEwQl9TM19SMl8wMDEuZmFzdHEuZ3ouCiMjIEl0IGFsc28gcGVyZm9ybXMgYSBzbGlkaW5nIHdpbmRvdyByZW1vdmFsIG9mIGFueXRoaW5nIHdpdGggcXVhbGl0eSA8MjU7CiMjIGN1dGFkYXB0IHByb3ZpZGVzIGFuIGFsdGVybmF0aXZlIHRvIHRoaXMgdG9vbC4KIyMgVGhlIG9yaWdpbmFsIHNlcXVlbmNlIGRhdGEgaXMgcmVjb21wcmVzc2VkIGFuZCBzYXZlZCBpbiB0aGUgc2VxdWVuY2VzLyBkaXJlY3RvcnkuCm1rZGlyIC1wIG91dHB1dHMvMDF0cmltb21hdGljCiMjIE5vdGUgdGhhdCB0cmltb21hdGljIHByaW50cyBhbGwgb3V0cHV0IGFuZCBlcnJvcnMgdG8gU1RERVJSLCBzbyBzZW5kIGJvdGggdG8gb3V0cHV0ClRyaW1tb21hdGljUEUgXAogIC10aHJlYWRzIDEgXAogIC1waHJlZDMzIFwKICBLT184MTBCX1MzX1IxXzAwMS5mYXN0cS5neiBLT184MTBCX1MzX1IyXzAwMS5mYXN0cS5neiBcCiAgS09fODEwQl9TM19SMV8wMDEtdHJpbW1lZF9wYWlyZWQuZmFzdHEgS09fODEwQl9TM19SMV8wMDEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cSBcCiAgS09fODEwQl9TM19SMl8wMDEtdHJpbW1lZF9wYWlyZWQuZmFzdHEgS09fODEwQl9TM19SMl8wMDEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cSBcCiAgIElMTFVNSU5BQ0xJUDovc3cvbG9jYWwvY3lvYS8yMDIzMDIvcHJlZml4L2xpYi9wZXJsNS9hdXRvL3NoYXJlL2Rpc3QvQmlvLUFkdmVudHVyZS9nZW5vbWUvYWRhcHRlcnMuZmE6MjoyMDoxMDoyOmtlZXBCb3RoUmVhZHMgIFwKICBTTElESU5HV0lORE9XOjQ6MjAgTUlOTEVOOjUwIFwKICAxPm91dHB1dHMvMDF0cmltb21hdGljL0tPXzgxMEJfUzNfUjFfMDAxLXRyaW1vbWF0aWMuc3Rkb3V0IFwKICAyPm91dHB1dHMvMDF0cmltb21hdGljL0tPXzgxMEJfUzNfUjFfMDAxLXRyaW1vbWF0aWMuc3RkZXJyCmV4Y2VwdGVkPSQoIHsgZ3JlcCAiRXhjZXB0aW9uIiAib3V0cHV0cy8wMXRyaW1vbWF0aWMvS09fODEwQl9TM19SMV8wMDEtdHJpbW9tYXRpYy5zdGRvdXQiIHx8IHRlc3QgJD8gPSAxOyB9ICkKIyMgVGhlIGZvbGxvd2luZyBpcyBpbiBjYXNlIHRoZSBpbGx1bWluYSBjbGlwcGluZyBmYWlscywgd2hpY2ggaXQgZG9lcyBpZiB0aGlzIGhhcyBhbHJlYWR5IGJlZW4gcnVuIEkgdGhpbmsuCmlmIFtbICIke2V4Y2VwdGVkfSIgIT0gIiIgXV07IHRoZW4KICBUcmltbW9tYXRpY1BFIFwKICAgIC10aHJlYWRzIDEgXAogICAgLXBocmVkMzMgXAogICAgS09fODEwQl9TM19SMV8wMDEuZmFzdHEuZ3ogS09fODEwQl9TM19SMl8wMDEuZmFzdHEuZ3ogXAogICAgS09fODEwQl9TM19SMV8wMDEtdHJpbW1lZF9wYWlyZWQuZmFzdHEgS09fODEwQl9TM19SMV8wMDEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cSBcCiAgICBLT184MTBCX1MzX1IyXzAwMS10cmltbWVkX3BhaXJlZC5mYXN0cSBLT184MTBCX1MzX1IyXzAwMS10cmltbWVkX3VucGFpcmVkLmZhc3RxIFwKICAgICBTTElESU5HV0lORE9XOjQ6MjUgTUlOTEVOOjUwIFwKICAgIDE+b3V0cHV0cy8wMXRyaW1vbWF0aWMvS09fODEwQl9TM19SMV8wMDEtdHJpbW9tYXRpYy5zdGRvdXQgXAogICAgMj5vdXRwdXRzLzAxdHJpbW9tYXRpYy9LT184MTBCX1MzX1IxXzAwMS10cmltb21hdGljLnN0ZGVycgpmaQpzbGVlcCAxMAptdiBLT184MTBCX1MzX1IxXzAwMS10cmltbWVkX3BhaXJlZC5mYXN0cSBLT184MTBCX1MzX1IxXzAwMS10cmltbWVkLmZhc3RxCm12IEtPXzgxMEJfUzNfUjJfMDAxLXRyaW1tZWRfcGFpcmVkLmZhc3RxIEtPXzgxMEJfUzNfUjJfMDAxLXRyaW1tZWQuZmFzdHEKCiMjIFJlY29tcHJlc3MgdGhlIHVucGFpcmVkIHJlYWRzLCB0aGlzIHNob3VsZCBub3QgdGFrZSBsb25nLgp4eiAtOWUgLWYgS09fODEwQl9TM19SMV8wMDEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cQp4eiAtOWUgLWYgS09fODEwQl9TM19SMl8wMDEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cQojIyBSZWNvbXByZXNzIHRoZSBwYWlyZWQgcmVhZHMuCnh6IC05ZSAtZiBLT184MTBCX1MzX1IxXzAwMS10cmltbWVkLmZhc3RxCnh6IC05ZSAtZiBLT184MTBCX1MzX1IyXzAwMS10cmltbWVkLmZhc3RxCmxuIC1zZiBLT184MTBCX1MzX1IxXzAwMS10cmltbWVkLmZhc3RxLnh6IHIxX3RyaW1tZWQuZmFzdHEueHoKbG4gLXNmIEtPXzgxMEJfUzNfUjJfMDAxLXRyaW1tZWQuZmFzdHEueHogcjJfdHJpbW1lZC5mYXN0cS54egoKCgojIyBUaGUgZm9sbG93aW5nIGxpbmVzIGdpdmUgc3RhdHVzIGNvZGVzIGFuZCBzb21lIGxvZ2dpbmcKbWludXRlc191c2VkPSQoKCBTRUNPTkRTIC8gNjAgKSkKZWNobyAiICAkKGhvc3RuYW1lKSBGaW5pc2hlZCAke1NMVVJNX0pPQklEfSAwMXRyaW1fS09fODEwQl9TM19SMV8wMDEuc2ggYXQgJChkYXRlKSwgaXQgdG9vayAke21pbnV0ZXNfdXNlZH0gbWludXRlcy4iID4+IG91dHB1dHMvbG9nLnR4dAppZiBbWyAteCAiJChjb21tYW5kIC12IHNzdGF0KSIgJiYgLW4gIiR7U0xVUk1fSk9CSUR9IiBdXTsgdGhlbgogIGVjaG8gIiAgd2FsbHRpbWUgdXNlZCBieSAke1NMVVJNX0pPQklEfSB3YXM6ICR7bWludXRlc191c2VkOi1udWxsfSBtaW51dGVzLiIgPj4gb3V0cHV0cy9sb2cudHh0CiAgbWF4bWVtPSQoc3N0YXQgLW4gLVAgLS1mb3JtYXQ9TWF4Vk1TaXplIC1qICIke1NMVVJNX0pPQklEfSIpCiAgIyMgSSBhbSBub3Qgc3VyZSB3aHksIGJ1dCB3aGVuIEkgcnVuIGEgc2NyaXB0IGluIGFuIGludGVyYWN0aXZlIHNlc3Npb24sIHRoZSBtYXhtZW0gdmFyaWFibGUKICAjIyBnZXRzIHNldCBjb3JyZWN0bHkgZXZlcnl0aW1lLCBidXQgd2hlbiBpdCBpcyBydW4gYnkgYW5vdGhlciBub2RlLCBzb21ldGltZXMgaXQgZG9lcyBub3QuCiAgIyMgTGV0cyB0cnkgYW5kIGZpZ3VyZSB0aGF0IG91dC4uLgogIGVjaG8gIlRFU1RNRTogJHttYXhtZW19IgogIGlmIFtbIC1uICIke21heG1lbX0iIF1dOyB0aGVuCiAgICBlY2hvICIgIG1heGltdW0gbWVtb3J5IHVzZWQgYnkgJHtTTFVSTV9KT0JJRH0gd2FzOiAke21heG1lbX0uIiA+PiBvdXRwdXRzL2xvZy50eHQKICBlbHNlCiAgICBlY2hvICIgIFRoZSBtYXhpbXVtIG1lbW9yeSBkaWQgbm90IGdldCBzZXQgZm9yIHRoaXMgam9iOiAke1NMVVJNX0pPQklEfS4iID4+IG91dHB1dHMvbG9nLnR4dAogICAgc3N0YXQgLVAgLWogIiR7U0xVUk1fSk9CSUR9IiA+PiBvdXRwdXRzL2xvZy50eHQKICBmaQogIGVjaG8gIiIgPj4gb3V0cHV0cy9sb2cudHh0CmZpCnRvdWNoIG91dHB1dHMvbG9ncy8wMXRyaW1fS09fODEwQl9TM19SMV8wMDEuZmluaXNoZWQKYGBgCgojIE1hcHBpbmcKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCBwcmVwcm9jZXNzaW5nCnN0YXJ0PSQocHdkKQpmb3IgaSBpbiAkKC9iaW4vbHMgLWQgKiB8IGdyZXAgLXYgc2VxdWVuY2VyKTsgZG8KICAgIGNkICRpCiAgICBlY2hvICJTdGFydGluZyAkaSIKICAgIGN5b2EgLS1tZXRob2QgaGlzYXQgLS1zcGVjaWVzIG1tMzhfMTAwIC0taW5wdXQgcjFfdHJpbW1lZC5mYXN0cS54ejpyMl90cmltbWVkLmZhc3RxLnh6IFwKICAgICAgICAgLS1nZmZfdHlwZSBnZW5lIC0tZ2ZmX3RhZyBnZW5lX2lkIC0tc3RyYW5kZWQgcmV2ZXJzZQogICAgY2QgJHN0YXJ0CmRvbmUKYGBgCgpJbnRlcmVzdGluZ2x5LCBJIHdlbnQgb3ZlciBteSBtZW1vcnkgYWxsb2NhdGlvbiBmb3IgdGhlc2UgbWFwcGluZyBqb2JzCmZvciAyIG9mIHRoZW0uICBBcyBhIHJlc3VsdCBJIGhhZCB0byByZXJ1biB0aGVtIG1hbnVhbGx5LgoKIyBFeHRyYWN0aW5nIHZhcmlhbnRzCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KY2QgcHJlcHJvY2Vzc2luZwpzdGFydD0kKHB3ZCkKZm9yIGkgaW4gJCgvYmluL2xzIC1kICogfCBncmVwIC12IHNlcXVlbmNlcik7IGRvCiAgICBjZCAkaQogICAgZWNobyAiU3RhcnRpbmcgJGkiCiAgICBjeW9hIC0tbWV0aG9kIGZyZWViYXllcyAtLXNwZWNpZXMgbW0zOF8xMDAgLS1pbnB1dCBvdXRwdXRzLzQwaGlzYXRfbW0zOF8xMDAvbW0zOF8xMDBfZ2Vub21lLmJhbSBcCiAgICAgICAgIC0tZ2ZmX3R5cGUgZ2VuZSAtLWdmZl90YWcgZ2VuZV9pZCAtLXN0cmFuZGVkIHJldmVyc2UgLS1pbnRyb24gMQogICAgY2QgJHN0YXJ0CmRvbmUKYGBgCgoKCmBgYHtyIHNhdmVtZX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZSgiVGhpcyBpcyBocGdsdG9vbHMgY29tbWl0OiAiLCBnZXRfZ2l0X2NvbW1pdCgpKQp0aGlzX3NhdmUgPC0gcGFzdGUwKGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLCByZXBsYWNlID0gIiIsIHggPSBybWRfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKQojbWVzc2FnZSgiU2F2aW5nIHRvICIsIHRoaXNfc2F2ZSkKI3RtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWUgPSB0aGlzX3NhdmUpKQpgYGAK