Introduction
This metabarcoding pipeline is based around the targets package, which is
a Make-like pipeline tool for R. The benefit of this is that all the
code is automatically run, and the pipeline skips costly runtime for
tasks that are already up to date.
This page lists the general workflow and all the options that can be
adapted for your dataset.
Clone the pipeRline github repository
The first step is to clone this github repository, which contains the
required code and directory structure to run the pipeline. To do this,
you will need Git installed on your
computer. If you are running the pipeline in Rstudio, it is best to
create a new project from the github repository. This can be done by
going file > new project > version control >
git then adding https://github.com/alexpiper/piperline.git then change
the name of the project to whatever you are working with.
Alternatively, the repository can be cloned using the command line,
change the ‘folder-name’ to the desired name
# Change into the main directory you wish to make the project in
cd metabarcoding
# Clone the repository
git clone https://github.com/alexpiper/piperline.git folder-name
Updating the pipeline
To update to the latest version of the pipeline, run the below code
in the terminal.
git pull
Prior to analysis
The PipeRline workflow assumes that your sequencing data meets
certain criteria:
- Samples have been demultiplexed, i.e. split into individual
per-sample fastq files. If you want the pipeline to calculate the
index-switching rate, the fastq files need to be re-demultiplexed as the
miseq does not put indexes in fasta headers by default
- For paired-end sequencing data, the forward and reverse reads are in
separate files (ie. not interleaved) with reads arranged in matched
order.
The output directory should be unique for each sequencing run, named
as the flowcell id, within a directory called data
For example:
root/
├── data/
├── CJL7D/
You will also need BLAST+ installed on your computer, it can be
downloaded from the NCBI
website
Sequencing reads
For this workflow to run, we will need some sequencing runs to work
with. If you are working with MiSeq data, it is recommended that the
data is demultiplexed again using bcl2fastq (see Demultiplex
MiSeq run tab below), as the miseq does not put indexes in
fasta headers by default which is required for the index swtiching
calculation.
If you do not yet have any data, some test sequencing reads have been
hosted on Zenodo for testing purposes. The below code in the
Download example reads tab below will download these
and put them inside the data folder.
Demultiplex MiSeq run
The below code is written for the Agriculture Victoria BASC server,
and the locations will be different if you are using a different HPC
cluster.
#load module
module load bcl2fastq2/2.20.0-foss-2018b
#raise amount of available file handles
ulimit -n 4000
###Run1
#Set up input and outputs
inputdir=/group/sequencing/210219_M03633_0489_000000000-JDYG3 #CHANGE TO YOUR SEQ RUN
outputdir=/group/pathogens/IAWS/Projects/Metabarcoding/dros_surveillance/data/JDYG3 #CHANGE TO YOUR DATA FOLDER RUN
samplesheet=/group/pathogens/IAWS/Projects/Metabarcoding/dros_surveillance/SampleSheet_JDYG3.csv #CHANGE TO YOUR SAMPLESHEET
# convert samplesheet to unix format
dos2unix $samplesheet
#Demultiplex
bcl2fastq -p 12 --runfolder-dir $inputdir \
--output-dir $outputdir \
--sample-sheet $samplesheet \
--no-lane-splitting --barcode-mismatches 1
# Copy other necessary files and move fastqs
cd $outputdir
cp -r $inputdir/InterOp $outputdir
cp $inputdir/RunInfo.xml $outputdir
cp $inputdir/[Rr]unParameters.xml $outputdir
cp $samplesheet $outputdir
mv **/*.fastq.gz $outputdir
# Append fcid to start of sample names if missing
fcid=$(echo $inputdir | sed 's/^.*-//')
for i in *.fastq.gz; do
if ! [[ $i == $fcid* ]]; then
new=$(echo ${fcid} ${i}) #append together
new=$(echo ${new// /_}) #remove any white space
mv -v "$i" "$new"
fi
done
Optional: Run R on BASC
You may wish to run this workflow through the command line on
Agriculture Victorias BASC server in order to take advantage of more
processing power. To do this, you can start a new SLURM interactive
session. Press the CODE button to the lower right to display the code
for this optional step.
# Create new interactive SLURM session
sinteractive --ntasks=1 --cpus-per-task=10 --mem-per-cpu=10GB --time=72:00:00
module load R/4.2.0-foss-2021b
module load pkgconfig/1.5.1-GCCcore-9.3.0-Python-3.8.2
module load GDAL/3.3.0-foss-2021a
module load BLAST+/2.11.0-gompi-2020a
module load Pandoc/2.5
module load ZeroMQ/4.3.2-GCCcore-9.3.0
# Load R
R
Download example reads
Example tephritid metabarcoding reads have been hosted on Zenodo, either
download them manually or with R below:
# Source the functions file which contains code to download from zenodo
source("R/functions.R")
# Create directory for data
if(!dir.exists("data/K77JP")) {dir.create("data/K77JP", recursive = TRUE)}
if(!dir.exists("data/K77JP/InterOp")) {dir.create("data/K77JP/InterOp", recursive = TRUE)}
# Download files from zenodo
download_zenodo(
doi = "10.5281/zenodo.7112162",
path = "data/K77JP"
)
# Move the interop files to the interop folder
fs::dir_ls(path="data/K77JP", glob="*.bin") %>%
purrr::map(function(x){
fs::file_copy(path = x, new_path = x %>% str_replace("data/K77JP", "data/K77JP/InterOp"))
file.remove(x)
})
Install and load R packages and setup
directories
This pipeline depends on a number of other R packages which this step
will install. The versions of these packages are managed using renv to
ensure they match the versions the pipeline was developed on. The first
time installing packages may take some time, but they should be quick to
load for any future runs.
# Load the targets and renv packages
library(targets)
library(tarchetypes)
# Load all packages using renv::restore() and source package list
renv::restore()
source("_targets_packages.R")
# Source ancillary functions
source("R/functions.R")
source("R/themes.R")
Reference databases
The pipeRline workflow uses the IDTAXA
and BLAST software to assign taxonomy to the sequence reads. These
require a pre-trained IDTAXA model, and a fasta file with heirarchial
taxonomy. For insects, these
Download reference database
Reference databases for insects and arachnids have been hosted on Zenodo, either
download them manually, or with R below:
# Source the functions file which contains code to download from zenodo
source("R/functions.R")
# Download files from zenodo
download_zenodo(
doi = "10.5281/zenodo.7655352",
path = "reference"
)
Create your own reference database
If you need a new database, these can be created from genbank and
blast using taxreturn or other
simialr database curation packages.
>Accession|Root;Kingdom;Phylum;Class;Order;Family;Genus;Species
ACCTAGAAAGTCGTAGATCGAAGTTGAAGCATCGCCCGATGATCGTCTGAAGCTGTAGCATGAGTCGATTTTCACATTCAGGGATACCATAGGATAC
>Root;Kingdom;Phylum;Class;Order;Family;Genus;Species
CGCTAGAAAGTCGTAGAAGGCTCGGAGGTTTGAAGCATCGCCCGATGGGATCTCGTTGCTGTAGCATGAGTACGGACATTCAGGGATCATAGGATAC
The IDTAXA model can then be trained on this reference fasta - See
the IDTAXA
manual
Create sample tracking sheet
In order to track samples and relevant QC statistics throughout the
metabarcoding pipeline, we will first create a new sample tracking sheet
from our input illumina samplesheets. This function requires both the
SampleSheet.csv used for the sequencing run, and the runParameters.xml,
both of which should have been automatically obtained from the
demultiplexed sequencing run folder in the bash step above
runs <- dir("data/") #Find all directories within data
SampleSheet <- list.files(paste0("data/", runs), pattern= "SampleSheet", full.names = TRUE)
runParameters <- list.files(paste0("data/", runs), pattern= "[Rr]unParameters.xml", full.names = TRUE)
# Create samplesheet containing samples and run parameters for all runs
samdf <- create_samplesheet(SampleSheet = SampleSheet, runParameters = runParameters, template = "V4") %>%
distinct()
# Check that sample_ids contain fcid, if not; attatch
samdf <- samdf %>%
mutate(sample_id = case_when(
!str_detect(sample_id, fcid) ~ paste0(fcid,"_",sample_id),
TRUE ~ sample_id
))
# Check that samples match samplesheet
fastqFs <- purrr::map(list.dirs("data", recursive=FALSE),
list.files, pattern="_R1_", full.names = TRUE) %>%
unlist() %>%
str_remove(pattern = "^(.*)\\/") %>%
str_remove(pattern = "(?:.(?!_S))+$")
# Filter undetermined reads from sample sheet
fastqFs <- fastqFs[!str_detect(fastqFs, "Undetermined")]
# Check for fastq files that are missing from samplesheet
if (length(setdiff(fastqFs, samdf$sample_id)) > 0) {warning("The fastq file/s: ", setdiff(fastqFs, samdf$sample_id), " are not in the sample sheet") }
# Check for sample_ids that dont have a corresponding fastq file
if (length(setdiff(samdf$sample_id, fastqFs)) > 0) {
warning(paste0("The fastq file: ",
setdiff(samdf$sample_id, fastqFs),
" is missing, dropping from samplesheet \n"))
samdf <- samdf %>%
filter(!sample_id %in% setdiff(samdf$sample_id, fastqFs))
}
# Write out sample tracking sheet
write_csv(samdf, "sample_data/Sample_info.csv")
Add PCR primers to sample sheet
This can either be done manually by editing the
sample_data/Sample_info.csv file, or it can be done in R as below.
If a single primer set was used across all samples, these can simply
be added using a mutate call (tab 1).
If different primers were used for different samples, these can be
set using pattern matching on the sample names with case_when
(tab 2).
If multiple primer sets are used per sample, before indexing, the
pipeline will conduct an extra round of demultiplexing to split each
sample by primer. This option can be set by splitting each primer set
with a semicolon (tab 3)
Single primer set
# Add primers to sample sheet
samdf <- samdf %>%
mutate(pcr_primers = "fwhF2-fwhR2n",
for_primer_seq = "GGDACWGGWTGAACWGTWTAYCCHCC",
rev_primer_seq = "GTRATWGCHCCDGCTARWACWGG"
)
write_csv(samdf, "sample_data/Sample_info.csv")
Different primer sets per sample
# Add PCR primers to sample sheet
samdf <- samdf %>%
mutate(pcr_primers = case_when(
str_detect(sample_name, "primer1") ~ "fwhF2-fwhR2n",
str_detect(sample_name, "primer2") ~ "EIF3LminiF4-EIF3lminiR4"
),
for_primer_seq = case_when(
str_detect(sample_name, "primer1") ~ "GGDACWGGWTGAACWGTWTAYCCHCC",
str_detect(sample_name, "primer2") ~ "GATGCGYCGTTATGCYGATGC"
),
rev_primer_seq = case_when(
str_detect(sample_name, "primer1") ~ "GTRATWGCHCCDGCTARWACWGG",
str_detect(sample_name, "primer2") ~ "TTRAAYACTTCYARATCRCC"
))
write_csv(samdf, "sample_data/Sample_info.csv")
Multiple primer sets per sample
# Add PCR primers to sample sheet
samdf <- samdf %>%
mutate(
pcr_primers = "fwhF2-fwhR2nDac;EIF3LminiF4-EIF3lminiR4",
for_primer_seq = "GGDACWGGWTGAACWGTWTAYCCHCC;GATGCGYCGTTATGCYGATGC",
rev_primer_seq = "GTRATWGCHCCIGCTAADACHGG;TTRAAYACTTCYARATCRCC"
)
write_csv(samdf, "sample_data/Sample_info.csv")
Create parameters file
The parameters file table the respective target gene, reference
databases, and filtering parameters for each primer set used to amplify
the samples. As the pcr_primers column is used in the pipeline to match
the parameters to the respective sample, it is critical that the primer
names match those set in the previous step.
If a single primer set was used across all samples, these can simply
be added to the table as below (tab 1).
If different primers were used for different samples, these can be
set as different rows in the table using c() when creatign the tibble
(tab 2).
If multiple primer reference databases are to be used for each
sample, these can be set by splitting each a semicolon. The taxonomic
assignment will be conducted sequentially through the databases from
left to right, with the second reference database only being used for
those ASVs that couldnt be assigned to species level using the first
databases (tab 3)
Parameter options
- Primer parameters:
- pcr_primers - Name of PCR primers - must match
samdf file
- target_gene - Name of target gene
- max_primer_mismatch - How much mismatch to allow
when detecting primer sequences
- Read filtering:
- read_min_length - Minimum length of primer trimmed
reads
- read_max_length - Maximum length of primer trimmed
reads
- read_max_ee - Maximum expected errors of primer
trimmed reads
- read_trunc_length - Length to cut all longer reads
to
- read_trim_left - Remove this many bp from left side
of primer trimmed reads
- read_trim_right - Remove this many bp from right
side of primer trimmed reads
- ASV filtering
- asv_min_length - Minimum length of amplicon
- asv_max_length - Maximum length of amplicon
- high_sensitivity - Option to turn on pseudo pooling,
setting this to FALSE greatly speeds up ASV inference at the expense of
detecting fewer rare (<5 reads) taxa.
- concat_unmerged - Retain any unmerged read pairs by
concatenating them together separated by a string of 10 N bases
- genetic_code - Genetic code for amplicon - see
Biostrings::GENETIC_CODE_TABLE
- coding - Is the amplicon from a protein coding
gene
- phmm - Path to profile hidden markov model
(Optional)
- Taxonomic assignment:
- idtaxa_db - Path to trained IDTAXA model
- ref_fasta - Path to fasta file of reference
database
- idtaxa_confidence - Minimum bootstrap confidence
for IDTAXA
- run_blast - Whether a blast top hit search should
be conducted in addition to IDTAXA
- blast_min_identity - Minimum nucleotide identity
for BLAST
- blast_min_coverage - Minimum query coverage for
BLAST
- target_kingdom - Subset to target kingdom
- target_phylum - Subset to target phylum
- target_class - Subset to target class
- target_order - Subset to target order
- target_family - Subset to target family
- target_genus - Subset to target genus
- target_species - Subset to target species
- Sample & Taxon filtering:
- min_sample_reads - Minimum reads per sample after
filtering
- min_taxa_reads - Minimum reads per ASV to
retain
- min_taxa_ra - Minimum relative abundance per ASV to
retain. 1e-4 is 0.01%
- General pipeline parameters
- threads - Number of CPU threads to run the pipeline
across
Single primer set
# Params to add in step_add_parameters
params <- tibble(
# Primer parameters
pcr_primers = "fwhF2-fwhR2n",
target_gene="COI",
max_primer_mismatch=0,
# Read filtering
read_min_length = 20,
read_max_length = Inf,
read_max_ee = 1,
read_trunc_length = 150,
read_trim_left = 0,
read_trim_right = 0,
# ASV filtering
asv_min_length = 195,
asv_max_length = 215,
high_sensitivity = TRUE,
concat_unmerged = FALSE,
genetic_code = "SGC4",
coding = TRUE,
phmm = "reference/folmer_fullength_model.rds",
# Taxonomic assignment
idtaxa_db = "reference/idtaxa_bftrimmed.rds",
ref_fasta = "reference/insecta_hierarchial_bftrimmed.fa.gz",
idtaxa_confidence = 60,
run_blast=TRUE,
blast_min_identity = 97,
blast_min_coverage = 90,
target_kingdom = "Metazoa",
target_phylum = "Arthropoda",
target_class = NA,
target_order = NA,
target_family = NA,
target_genus = NA,
target_species= NA,
# Sample & Taxon filtering
min_sample_reads = 1000,
min_taxa_reads= NA,
min_taxa_ra = 1e-4, #1e-4 is 0.01%
# General pipeline parameters
threads = 1
)
write_csv(params, "sample_data/loci_params.csv")
Different or multiple primer sets per sample
# Params to add in step_add_parameters
params <- tibble(
# Primer parameters
pcr_primers = c("fwhF2-fwhR2nDac", "EIF3LminiF4-EIF3lminiR4"),
target_gene=c("COI", "EIF3L"),
max_primer_mismatch=1,
# Read filtering
read_min_length = 20,
read_max_length = Inf,
read_max_ee = 1,
read_trunc_length = 150,
read_trim_left = 0,
read_trim_right = 0,
# ASV filtering
asv_min_length = c(195, 207),
asv_max_length = c(215, 227),
high_sensitivity = TRUE,
concat_unmerged = FALSE,
genetic_code = c("SGC4", "SGC0"),
coding = c(TRUE, TRUE),
phmm = c("reference/phmm/Bactrocera_COI.rds", "reference/phmm/Bactrocera_EIF3L.rds"),
# Taxonomic assignment
idtaxa_db = c("reference/COI_idtaxa.rds","reference/EIF3L_idtaxa.rds"),
ref_fasta = c("reference/COI_hierarchial.fa.gz", "reference/EIF3L_hierarchial.fa.gz"),
idtaxa_confidence = 60,
run_blast=TRUE,
blast_min_identity = 97,
blast_min_coverage = 90,
target_kingdom = c("Metazoa", "Metazoa"),
target_phylum = c("Arthropoda","Arthropoda"),
target_class = NA,
target_order = NA,
target_family = NA,
target_genus = NA,
target_species= NA,
# Sample & Taxon filtering
min_sample_reads = c(1000, 1000),
min_taxa_reads= NA,
min_taxa_ra = c(1e-4, 1e-4),
)
write_csv(params, "sample_data/loci_params.csv")
Multiple reference databases
params <- tibble(
# Primer parameters
pcr_primers = c("fwhF2-fwhR2nDac", "EIF3LminiF4-EIF3lminiR4"),
target_gene=c("COI", "EIF3L"),
max_primer_mismatch=0,
# Read filtering
read_min_length = 20,
read_max_length = Inf,
read_max_ee = 1,
read_trunc_length = 150,
read_trim_left = 0,
read_trim_right = 0,
# ASV filtering
asv_min_length = c(195, 207),
asv_max_length = c(215, 227),
high_sensitivity = TRUE,
concat_unmerged = FALSE,
genetic_code = c("SGC4", "SGC0"),
coding = c(TRUE, TRUE),
phmm = c("reference/phmm/Bactrocera_COI.rds", "reference/phmm/Bactrocera_EIF3L.rds"),
# Taxonomic assignment
idtaxa_db = c("reference/COI_internal_idtaxa.rds;reference/COI_idtaxa.rds",
"reference/EIF3L_internal_idtaxa.rds;reference/EIF3L_idtaxa.rds"),
ref_fasta = c("reference/COI_internal.fa.gz;reference/COI_hierarchial.fa.gz",
"reference/EIF3L_internal.fa.gz;reference/EIF3L_hierarchial.fa.gz"),
idtaxa_confidence = 60,
run_blast=TRUE,
blast_min_identity = 97,
blast_min_coverage = 90,
target_kingdom = c("Metazoa", "Metazoa"),
target_phylum = c("Arthropoda","Arthropoda"),
target_class = NA,
target_order = NA,
target_family = NA,
target_genus = NA,
target_species= NA,
# Sample & Taxon filtering
min_sample_reads = c(1000, 1000),
min_taxa_reads= NA,
min_taxa_ra = c(1e-4, 1e-4),
)
write_csv(params, "sample_data/loci_params.csv")
Run pipeline
Now that the sample data sheet and parameters are defined, the
pipeline steps can now be run automatically using the tar_make()
command
tar_make()
Results
After the run, two directories should have been made within the
output folder, output/results/unfiltered which contains the results
before any taxonomic subsetting, sample minimum abundance, and ASV
minimum abundance filtering, and output/results/filtered containing the
results after these steps. Within each of these folders there should be
a series of outputs:
summary.csv - This is the main summary file
which lists the abundance of each ASV, the taxonomy assigned to it, and
the read counts for each sample it was detected in.
ps.rds - This phyloseq object contains the same
information as the summary file, but in a format that can be analysed
further using the phyloseq
R package, a useful tool for plotting and further analysis of
metabarcoding and microbiome datasets.
asvs.fasta - This contains the amplification
sequence variants inferred from the data set
seqtab.csv - This lists the abundance of each
ASV and the sample it was detected in. This file is generally for
development purposes only, and all information contained here is present
in the summmary csv.
taxtab.csv - This lists the heirarchial taxonomy
assigned to each ASV. This file is generally for development purposes
only, and all information contained here is present in the summmary
csv.
samdf.csv - This is the sample tracking sheet
that lists the sequencing details for each sample. This file is
generally for development purposes only, and all information contained
here is present in the summmary csv.
raw.csv - This is a large file containing all
the above results in a single csv in a ‘long’ format appropriate for
further statistical analysis.
Quality control
The pipeline also outputs some quality control plots that should be
checked to ensure the pipeline has run correctly and the outputs are as
desired
- Per-flowcell quality checks
output/logs/FCID/FCID_flowcell_qc.pdf - This set
of plots summarises the raw outputs from the sequencing run. The first
page shows the average imaging intensity for the 90% percentile of the
data for each tile on the sequencing flow cell. The second page shows
the number of clusters (reads) imaged by the seqeuncer, and the number
of clusters passing the machines filtering. The third page shows the
Qscore by cycle for all reads.
output/logs/FCID/FCID_index_switching.pdf - This
is a heatmap of the amount of index switching per index set and flowcell
used. On the diagonal of the plot is the indexes applied to the samples,
while the other squares on the grid display instances where either the
i5 or i7 index has switched causing this read to end up in the
undetermined reads file. The text above the plot lists the total reads
demultiplex from that flowcell, the switch rate (only one of the indexes
switching causing the read to end up in the undetermined reads file) as
a percentage, the cross-contamination rate (both indexes switching the
read ending up in another sample) as a percentage, and the number of
“other reads” which were those where no applied indexes were detected.
The cross-contamination rate is calculated as the square of the index
switching rate as per (costello et al), and should be a rough guide to
determine an appropriate ASV minimum abundance threshold for filtering.
NOTE: This plot is only created when unique dual indexes were used on
the sample.
output/logs/FCID/FCID_prefilt_qualplots.pdf -
This multiplot summarises the read quality scores for the forward and
reverse reads, pre filtering. These plots can serve as an indicator for
adjusting read filtering parameters of the pipeline. The top two plots
summarise the mean quality score by position for the forward and reverse
reads respectively. For illumina data, these will start to decrease
towards the end of the reads, particularly for the reverse reads. The
two bottom plots show the cumulative expected errors along the reads,
with different coloured dots for different quantiles of the read data
(i.e. lower 10% to upper 90%). The red lines show the potential max
expecter error cutoffs, with all reads above the set maximum expected
error filter beign removed (param read_max_ee). For example, if the
lower 10% quantile of reads goes above the red line for maxEE=1, you
would expect 10% of the reads to be removed if read_max_ee was set to 1.
As more errors commonly occur in the ends of the read, if there is
sufficient overlap between the reads to cover the length of the
amplicon, the reads could instead be truncated to smaller lengths to
reduce the amount of reads that cross this minimum expected error filter
which would retain more data. Note that when truncating reads you should
aim to have at least 20bp of overlap to facilitate forward and reverse
read merging.
output/logs/FCID/FCID_postfilt_qualplots.pdf -
This multiplot summarises the read quality scores for the forward and
reverse reads, pre filtering. These plots list the same information as
the pre-filtering quality plots, and should be checked to ensure that
the filtering has been correctly applied. i.e., if reads were truncated
or trimmed on the left or right (params read_trunc_length,
read_trim_left, read_trim_right) they should be shorter then the
pre-filter plots, and if a maximum expected error filter (param
read_max_ee) was applied, none of the EE quantiles should be above the
corresponding red line
output/logs/FCID/FCID_pcrprimers_errormodel.pdf
- There is a separate PDF for the forward and reverse error models for
each primer set and flow cell. Each plot summarises the error model used
for dada2 that was inferred from the data for the respective flow cell.
The error rates for each possible transition (A→C, A→G, etc) are shown
in each subplot. The dot-points are the error rates observed in the data
for each quality score. The black line shows the estimated error rates
from the machine-learning algorithm. The red line shows the error rates
that would be expected if the Q-scores assigned by the sequencer were
completely accurate. This plot can be more subjective to interpret, but
generally you want to see the estimated error rates (black line)
decrease as the quality score (x axis) increases, in a relatively linear
fashion. Minor humps in the black line are no problem, but a very jagged
line may indicate that the error model did not fit correctly. Note: for
NextSeq and NovaSeq data, the binned quality scores provided by the
sequencer can cause large humps or dips in the error model fit. This is
generally not a big problem, see this github
issue for a deeper discussion on fitting error models for binned
quality scores.
- Whole dataset quality checks:
output/logs/ASV_cleanup_summary.pdf - This plot
lists the abundance, and number of unique sequence variance inferred
from dada2, their lengths, and whether they were retained or filtered
out during the ASV filtering step. Generally you should see a lot of
unique sequences filtered out in this step, but the majority of the
abundance should remain.
output/logs/ASV_cleanup_summary.csv - This table
lists the individual sequence variants, their abudnance, length and
whether they were retained or filtered out during the ASV filtering
step. This table is useful for deeper investigation to ensure that real
sequences were not removed in any of the ASV filtering steps.
output/logs/taxonomic_assignment_summary.pdf -
This plot summarises the genetic distance of the ASVs to the reference
database (from BLAST top hit identity), and what taxonomy was assigned
to each. This plot gives a good overview of how well the analysed
sequences are represented in the reference database, and how successful
the taxonomic assignment was.
output/logs/taxonomic_assignment_summary.csv -
This table lists the individual sequence variants and their assigned
taxonomy and confidence scores with IDTAXA. The columns to the right
also indicate the BLAST top hit and their distance to the closest blast
hit. This table is useful for deeper investigation of how different
sequences were assigned.
output/logs/read_tracker.pdf This plot
summarises the number of reads retained through all steps of the
pipeline, as well as how many reads were classified to different
taxonomic ranks. This plot provides a useful overview of all pipeline
steps to determine if too many reads are being lost at a certain
step
output/logs/read_tracker.csv - Similar to the
above plot, this table summarises the number of reads retained through
all steps of the pipeline, as well as how many reads were classified to
different taxonomic ranks.
output/logs/accumulation_curve.pdf - This plot
shows the accumulation of ASVs within each sample as sequencing depth
increases. The curves should start to plateau if adequate sequencing
depth has been achieved to characterise the community. If the curves
have not reached a plateau it may indicate that these samples should be
sequenced again so that all taxa are captured in the data.
LS0tDQp0aXRsZTogIlBpcGVSbGluZSINCnN1YnRpdGxlOiAiR2VuZXJhbCBleGFtcGxlIg0KYXV0aG9yOiAiQS5NLiBQaXBlciINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgaGlnaGxpZ2h0ZXI6IG51bGwNCiAgICB0aGVtZTogImZsYXRseSINCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiANCiAgICAgIGNvbGxhcHNlZDogZmFsc2UNCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICBkZl9wcmludDogcGFnZWQgICAgDQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBLbml0ciBnbG9iYWwgc2V0dXAgLSBjaGFuZ2UgZXZhbCB0byB0cnVlIHRvIHJ1biBjb2RlDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeSh0YXJnZXRzKQ0KbGlicmFyeSh0YXJjaGV0eXBlcykNCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVycm9yPUZBTFNFLCBmaWcuc2hvdyA9ICJob2xkIiwgZmlnLmtlZXAgPSAiYWxsIikNCm9wdHNfY2h1bmskc2V0KGRldiA9ICdwbmcnKQ0KYGBgDQoNCiMgSW50cm9kdWN0aW9uDQoNClRoaXMgbWV0YWJhcmNvZGluZyBwaXBlbGluZSBpcyBiYXNlZCBhcm91bmQgdGhlIFt0YXJnZXRzXShodHRwczovL2Jvb2tzLnJvcGVuc2NpLm9yZy90YXJnZXRzLykgcGFja2FnZSwgd2hpY2ggaXMgYSBNYWtlLWxpa2UgcGlwZWxpbmUgdG9vbCBmb3IgUi4gVGhlIGJlbmVmaXQgb2YgdGhpcyBpcyB0aGF0IGFsbCB0aGUgY29kZSBpcyBhdXRvbWF0aWNhbGx5IHJ1biwgYW5kIHRoZSBwaXBlbGluZSBza2lwcyBjb3N0bHkgcnVudGltZSBmb3IgdGFza3MgdGhhdCBhcmUgYWxyZWFkeSB1cCB0byBkYXRlLg0KDQpUaGlzIHBhZ2UgbGlzdHMgdGhlIGdlbmVyYWwgd29ya2Zsb3cgYW5kIGFsbCB0aGUgb3B0aW9ucyB0aGF0IGNhbiBiZSBhZGFwdGVkIGZvciB5b3VyIGRhdGFzZXQuDQoNCiMgQ2xvbmUgdGhlIHBpcGVSbGluZSBnaXRodWIgcmVwb3NpdG9yeQ0KDQpUaGUgZmlyc3Qgc3RlcCBpcyB0byBjbG9uZSB0aGlzIGdpdGh1YiByZXBvc2l0b3J5LCB3aGljaCBjb250YWlucyB0aGUgcmVxdWlyZWQgY29kZSBhbmQgZGlyZWN0b3J5IHN0cnVjdHVyZSB0byBydW4gdGhlIHBpcGVsaW5lLiBUbyBkbyB0aGlzLCB5b3Ugd2lsbCBuZWVkIFtHaXRdKGh0dHBzOi8vZ2l0LXNjbS5jb20vKSBpbnN0YWxsZWQgb24geW91ciBjb21wdXRlci4gSWYgeW91IGFyZSBydW5uaW5nIHRoZSBwaXBlbGluZSBpbiBSc3R1ZGlvLCBpdCBpcyBiZXN0IHRvIGNyZWF0ZSBhIG5ldyBwcm9qZWN0IGZyb20gdGhlIGdpdGh1YiByZXBvc2l0b3J5LiBUaGlzIGNhbiBiZSBkb25lIGJ5IGdvaW5nICoqZmlsZSA+IG5ldyBwcm9qZWN0ID4gdmVyc2lvbiBjb250cm9sID4gZ2l0KiogdGhlbiBhZGRpbmcgaHR0cHM6Ly9naXRodWIuY29tL2FsZXhwaXBlci9waXBlcmxpbmUuZ2l0IHRoZW4gY2hhbmdlIHRoZSBuYW1lIG9mIHRoZSBwcm9qZWN0IHRvIHdoYXRldmVyIHlvdSBhcmUgd29ya2luZyB3aXRoLiANCg0KQWx0ZXJuYXRpdmVseSwgdGhlIHJlcG9zaXRvcnkgY2FuIGJlIGNsb25lZCB1c2luZyB0aGUgY29tbWFuZCBsaW5lLCBjaGFuZ2UgdGhlICdmb2xkZXItbmFtZScgdG8gdGhlIGRlc2lyZWQgbmFtZQ0KYGBge2Jhc2h9DQojIENoYW5nZSBpbnRvIHRoZSBtYWluIGRpcmVjdG9yeSB5b3Ugd2lzaCB0byBtYWtlIHRoZSBwcm9qZWN0IGluDQpjZCBtZXRhYmFyY29kaW5nDQoNCiMgQ2xvbmUgdGhlIHJlcG9zaXRvcnkNCmdpdCBjbG9uZSBodHRwczovL2dpdGh1Yi5jb20vYWxleHBpcGVyL3BpcGVybGluZS5naXQgZm9sZGVyLW5hbWUNCmBgYA0KDQojIyBVcGRhdGluZyB0aGUgcGlwZWxpbmUNCg0KVG8gdXBkYXRlIHRvIHRoZSBsYXRlc3QgdmVyc2lvbiBvZiB0aGUgcGlwZWxpbmUsIHJ1biB0aGUgYmVsb3cgY29kZSBpbiB0aGUgdGVybWluYWwuDQoNCmBgYHtiYXNofQ0KZ2l0IHB1bGwNCmBgYA0KDQojIFByaW9yIHRvIGFuYWx5c2lzDQpUaGUgUGlwZVJsaW5lIHdvcmtmbG93IGFzc3VtZXMgdGhhdCB5b3VyIHNlcXVlbmNpbmcgZGF0YSBtZWV0cyBjZXJ0YWluIGNyaXRlcmlhOg0KDQoxLiBTYW1wbGVzIGhhdmUgYmVlbiBkZW11bHRpcGxleGVkLCBpLmUuIHNwbGl0IGludG8gaW5kaXZpZHVhbCBwZXItc2FtcGxlIGZhc3RxIGZpbGVzLiBJZiB5b3Ugd2FudCB0aGUgcGlwZWxpbmUgdG8gY2FsY3VsYXRlIHRoZSBpbmRleC1zd2l0Y2hpbmcgcmF0ZSwgdGhlIGZhc3RxIGZpbGVzIG5lZWQgdG8gYmUgcmUtZGVtdWx0aXBsZXhlZCBhcyB0aGUgbWlzZXEgZG9lcyBub3QgcHV0IGluZGV4ZXMgaW4gZmFzdGEgaGVhZGVycyBieSBkZWZhdWx0DQoyLiBGb3IgcGFpcmVkLWVuZCBzZXF1ZW5jaW5nIGRhdGEsIHRoZSBmb3J3YXJkIGFuZCByZXZlcnNlIHJlYWRzIGFyZSBpbiBzZXBhcmF0ZSBmaWxlcyAoaWUuIG5vdCBpbnRlcmxlYXZlZCkgd2l0aCByZWFkcyBhcnJhbmdlZCBpbiBtYXRjaGVkIG9yZGVyLg0KDQpUaGUgb3V0cHV0IGRpcmVjdG9yeSBzaG91bGQgYmUgdW5pcXVlIGZvciBlYWNoIHNlcXVlbmNpbmcgcnVuLCBuYW1lZCBhcyB0aGUgZmxvd2NlbGwgaWQsIHdpdGhpbiBhIGRpcmVjdG9yeSBjYWxsZWQgZGF0YQ0KDQpGb3IgZXhhbXBsZToNCg0KICAgIHJvb3QvDQogICAgICDilJzilIDilIAgZGF0YS8NCiAgICAgICAgIOKUnOKUgOKUgCBDSkw3RC8NCiAgICAgICAgIA0KWW91IHdpbGwgYWxzbyBuZWVkIEJMQVNUKyBpbnN0YWxsZWQgb24geW91ciBjb21wdXRlciwgaXQgY2FuIGJlIGRvd25sb2FkZWQgZnJvbSB0aGUgW05DQkkgd2Vic2l0ZV0oaHR0cHM6Ly9ibGFzdC5uY2JpLm5sbS5uaWguZ292L0JsYXN0LmNnaT9QQUdFX1RZUEU9Qmxhc3REb2NzJkRPQ19UWVBFPURvd25sb2FkKSANCg0KIyBTZXF1ZW5jaW5nIHJlYWRzIHsudGFic2V0fQ0KDQpGb3IgdGhpcyB3b3JrZmxvdyB0byBydW4sIHdlIHdpbGwgbmVlZCBzb21lIHNlcXVlbmNpbmcgcnVucyB0byB3b3JrIHdpdGguIElmIHlvdSBhcmUgd29ya2luZyB3aXRoIE1pU2VxIGRhdGEsIGl0IGlzIHJlY29tbWVuZGVkIHRoYXQgdGhlIGRhdGEgaXMgZGVtdWx0aXBsZXhlZCBhZ2FpbiB1c2luZyBiY2wyZmFzdHEgKHNlZSAqKkRlbXVsdGlwbGV4IE1pU2VxIHJ1bioqIHRhYiBiZWxvdyksIGFzIHRoZSBtaXNlcSBkb2VzIG5vdCBwdXQgaW5kZXhlcyBpbiBmYXN0YSBoZWFkZXJzIGJ5IGRlZmF1bHQgd2hpY2ggaXMgcmVxdWlyZWQgZm9yIHRoZSBpbmRleCBzd3RpY2hpbmcgY2FsY3VsYXRpb24uDQoNCklmIHlvdSBkbyBub3QgeWV0IGhhdmUgYW55IGRhdGEsIHNvbWUgdGVzdCBzZXF1ZW5jaW5nIHJlYWRzIGhhdmUgYmVlbiBob3N0ZWQgb24gWmVub2RvIGZvciB0ZXN0aW5nIHB1cnBvc2VzLiBUaGUgYmVsb3cgY29kZSBpbiB0aGUgKipEb3dubG9hZCBleGFtcGxlIHJlYWRzKiogdGFiIGJlbG93IHdpbGwgZG93bmxvYWQgdGhlc2UgYW5kIHB1dCB0aGVtIGluc2lkZSB0aGUgZGF0YSBmb2xkZXIuDQoNCiMjIERlbXVsdGlwbGV4IE1pU2VxIHJ1bg0KVGhlIGJlbG93IGNvZGUgaXMgd3JpdHRlbiBmb3IgdGhlIEFncmljdWx0dXJlIFZpY3RvcmlhIEJBU0Mgc2VydmVyLCBhbmQgdGhlIGxvY2F0aW9ucyB3aWxsIGJlIGRpZmZlcmVudCBpZiB5b3UgYXJlIHVzaW5nIGEgZGlmZmVyZW50IEhQQyBjbHVzdGVyLg0KDQpgYGB7YmFzaCBkZW11bHRpcGxleCAxIG1pc21hdGNofQ0KI2xvYWQgbW9kdWxlDQptb2R1bGUgbG9hZCBiY2wyZmFzdHEyLzIuMjAuMC1mb3NzLTIwMThiDQoNCiNyYWlzZSBhbW91bnQgb2YgYXZhaWxhYmxlIGZpbGUgaGFuZGxlcw0KdWxpbWl0IC1uIDQwMDANCg0KIyMjUnVuMQ0KDQojU2V0IHVwIGlucHV0IGFuZCBvdXRwdXRzDQppbnB1dGRpcj0vZ3JvdXAvc2VxdWVuY2luZy8yMTAyMTlfTTAzNjMzXzA0ODlfMDAwMDAwMDAwLUpEWUczICNDSEFOR0UgVE8gWU9VUiBTRVEgUlVODQpvdXRwdXRkaXI9L2dyb3VwL3BhdGhvZ2Vucy9JQVdTL1Byb2plY3RzL01ldGFiYXJjb2RpbmcvZHJvc19zdXJ2ZWlsbGFuY2UvZGF0YS9KRFlHMyAjQ0hBTkdFIFRPIFlPVVIgREFUQSBGT0xERVIgUlVODQpzYW1wbGVzaGVldD0vZ3JvdXAvcGF0aG9nZW5zL0lBV1MvUHJvamVjdHMvTWV0YWJhcmNvZGluZy9kcm9zX3N1cnZlaWxsYW5jZS9TYW1wbGVTaGVldF9KRFlHMy5jc3YgI0NIQU5HRSBUTyBZT1VSIFNBTVBMRVNIRUVUDQoNCiMgY29udmVydCBzYW1wbGVzaGVldCB0byB1bml4IGZvcm1hdA0KZG9zMnVuaXggJHNhbXBsZXNoZWV0DQoNCiNEZW11bHRpcGxleA0KYmNsMmZhc3RxIC1wIDEyIC0tcnVuZm9sZGVyLWRpciAkaW5wdXRkaXIgXA0KLS1vdXRwdXQtZGlyICRvdXRwdXRkaXIgXA0KLS1zYW1wbGUtc2hlZXQgJHNhbXBsZXNoZWV0IFwNCi0tbm8tbGFuZS1zcGxpdHRpbmcgLS1iYXJjb2RlLW1pc21hdGNoZXMgMQ0KDQojIENvcHkgb3RoZXIgbmVjZXNzYXJ5IGZpbGVzIGFuZCBtb3ZlIGZhc3Rxcw0KY2QgJG91dHB1dGRpcg0KY3AgLXIgJGlucHV0ZGlyL0ludGVyT3AgJG91dHB1dGRpcg0KY3AgJGlucHV0ZGlyL1J1bkluZm8ueG1sICRvdXRwdXRkaXINCmNwICRpbnB1dGRpci9bUnJddW5QYXJhbWV0ZXJzLnhtbCAkb3V0cHV0ZGlyDQpjcCAkc2FtcGxlc2hlZXQgJG91dHB1dGRpcg0KbXYgKiovKi5mYXN0cS5neiAkb3V0cHV0ZGlyDQoNCiMgQXBwZW5kIGZjaWQgdG8gc3RhcnQgb2Ygc2FtcGxlIG5hbWVzIGlmIG1pc3NpbmcNCmZjaWQ9JChlY2hvICRpbnB1dGRpciB8IHNlZCAncy9eLiotLy8nKQ0KZm9yIGkgaW4gKi5mYXN0cS5nejsgZG8NCiAgaWYgISBbWyAkaSA9PSAkZmNpZCogXV07IHRoZW4NCiAgbmV3PSQoZWNobyAke2ZjaWR9ICR7aX0pICNhcHBlbmQgdG9nZXRoZXINCiAgbmV3PSQoZWNobyAke25ldy8vIC9ffSkgI3JlbW92ZSBhbnkgd2hpdGUgc3BhY2UNCiAgbXYgLXYgIiRpIiAiJG5ldyINCiAgZmkNCmRvbmUNCg0KYGBgDQoNCg0KIyBPcHRpb25hbDogUnVuIFIgb24gQkFTQw0KDQpZb3UgbWF5IHdpc2ggdG8gcnVuIHRoaXMgd29ya2Zsb3cgdGhyb3VnaCB0aGUgY29tbWFuZCBsaW5lIG9uIEFncmljdWx0dXJlIFZpY3RvcmlhcyBCQVNDIHNlcnZlciBpbiBvcmRlciB0byB0YWtlIGFkdmFudGFnZSBvZiBtb3JlIHByb2Nlc3NpbmcgcG93ZXIuIFRvIGRvIHRoaXMsIHlvdSBjYW4gc3RhcnQgYSBuZXcgU0xVUk0gaW50ZXJhY3RpdmUgc2Vzc2lvbi4gUHJlc3MgdGhlIENPREUgYnV0dG9uIHRvIHRoZSBsb3dlciByaWdodCB0byBkaXNwbGF5IHRoZSBjb2RlIGZvciB0aGlzIG9wdGlvbmFsIHN0ZXAuDQoNCmBgYHtiYXNoLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1oaWRlJ30NCiMgQ3JlYXRlIG5ldyBpbnRlcmFjdGl2ZSBTTFVSTSBzZXNzaW9uDQpzaW50ZXJhY3RpdmUgLS1udGFza3M9MSAtLWNwdXMtcGVyLXRhc2s9MTAgLS1tZW0tcGVyLWNwdT0xMEdCIC0tdGltZT03MjowMDowMA0KDQptb2R1bGUgbG9hZCBSLzQuMi4wLWZvc3MtMjAyMWINCm1vZHVsZSBsb2FkIHBrZ2NvbmZpZy8xLjUuMS1HQ0Njb3JlLTkuMy4wLVB5dGhvbi0zLjguMg0KbW9kdWxlIGxvYWQgR0RBTC8zLjMuMC1mb3NzLTIwMjFhDQptb2R1bGUgbG9hZCBCTEFTVCsvMi4xMS4wLWdvbXBpLTIwMjBhDQptb2R1bGUgbG9hZCBQYW5kb2MvMi41DQptb2R1bGUgbG9hZCBaZXJvTVEvNC4zLjItR0NDY29yZS05LjMuMA0KDQojIExvYWQgUg0KUg0KYGBgDQoNCg0KDQojIyBEb3dubG9hZCBleGFtcGxlIHJlYWRzDQoNCkV4YW1wbGUgdGVwaHJpdGlkIG1ldGFiYXJjb2RpbmcgcmVhZHMgaGF2ZSBiZWVuIGhvc3RlZCBvbiBbWmVub2RvXShodHRwczovL3plbm9kby5vcmcvcmVjb3JkLzcxMTIxNjIjLllfTG9CWFpCei1nKSwgZWl0aGVyIGRvd25sb2FkIHRoZW0gbWFudWFsbHkgb3Igd2l0aCBSIGJlbG93OiANCg0KYGBge3J9DQojIFNvdXJjZSB0aGUgZnVuY3Rpb25zIGZpbGUgd2hpY2ggY29udGFpbnMgY29kZSB0byBkb3dubG9hZCBmcm9tIHplbm9kbw0Kc291cmNlKCJSL2Z1bmN0aW9ucy5SIikNCg0KIyBDcmVhdGUgZGlyZWN0b3J5IGZvciBkYXRhDQppZighZGlyLmV4aXN0cygiZGF0YS9LNzdKUCIpKSB7ZGlyLmNyZWF0ZSgiZGF0YS9LNzdKUCIsIHJlY3Vyc2l2ZSA9IFRSVUUpfQ0KaWYoIWRpci5leGlzdHMoImRhdGEvSzc3SlAvSW50ZXJPcCIpKSB7ZGlyLmNyZWF0ZSgiZGF0YS9LNzdKUC9JbnRlck9wIiwgcmVjdXJzaXZlID0gVFJVRSl9DQoNCiMgRG93bmxvYWQgZmlsZXMgZnJvbSB6ZW5vZG8NCmRvd25sb2FkX3plbm9kbygNCiAgZG9pID0gIjEwLjUyODEvemVub2RvLjcxMTIxNjIiLA0KICBwYXRoID0gImRhdGEvSzc3SlAiDQopDQoNCiMgTW92ZSB0aGUgaW50ZXJvcCBmaWxlcyB0byB0aGUgaW50ZXJvcCBmb2xkZXINCmZzOjpkaXJfbHMocGF0aD0iZGF0YS9LNzdKUCIsIGdsb2I9IiouYmluIikgJT4lDQogIHB1cnJyOjptYXAoZnVuY3Rpb24oeCl7DQogICAgZnM6OmZpbGVfY29weShwYXRoID0geCwgbmV3X3BhdGggPSB4ICU+JSBzdHJfcmVwbGFjZSgiZGF0YS9LNzdKUCIsICJkYXRhL0s3N0pQL0ludGVyT3AiKSkNCiAgICBmaWxlLnJlbW92ZSh4KQ0KICB9KQ0KYGBgDQoNCiMgSW5zdGFsbCBhbmQgbG9hZCBSIHBhY2thZ2VzIGFuZCBzZXR1cCBkaXJlY3RvcmllcyB7LX0NCg0KVGhpcyBwaXBlbGluZSBkZXBlbmRzIG9uIGEgbnVtYmVyIG9mIG90aGVyIFIgcGFja2FnZXMgd2hpY2ggdGhpcyBzdGVwIHdpbGwgaW5zdGFsbC4gVGhlIHZlcnNpb25zIG9mIHRoZXNlIHBhY2thZ2VzIGFyZSBtYW5hZ2VkIHVzaW5nIFtyZW52XShodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL3JlbnYvYXJ0aWNsZXMvcmVudi5odG1sKSB0byBlbnN1cmUgdGhleSBtYXRjaCB0aGUgdmVyc2lvbnMgdGhlIHBpcGVsaW5lIHdhcyBkZXZlbG9wZWQgb24uIFRoZSBmaXJzdCB0aW1lIGluc3RhbGxpbmcgcGFja2FnZXMgbWF5IHRha2Ugc29tZSB0aW1lLCBidXQgdGhleSBzaG91bGQgYmUgcXVpY2sgdG8gbG9hZCBmb3IgYW55IGZ1dHVyZSBydW5zLiANCg0KYGBge3IgTWFudWFsIGluc3RhbGx9IA0KIyBMb2FkIHRoZSB0YXJnZXRzIGFuZCByZW52IHBhY2thZ2VzDQpsaWJyYXJ5KHRhcmdldHMpDQpsaWJyYXJ5KHRhcmNoZXR5cGVzKQ0KDQojIExvYWQgYWxsIHBhY2thZ2VzIHVzaW5nIHJlbnY6OnJlc3RvcmUoKSBhbmQgc291cmNlIHBhY2thZ2UgbGlzdA0KcmVudjo6cmVzdG9yZSgpDQpzb3VyY2UoIl90YXJnZXRzX3BhY2thZ2VzLlIiKQ0KDQojIFNvdXJjZSBhbmNpbGxhcnkgZnVuY3Rpb25zDQpzb3VyY2UoIlIvZnVuY3Rpb25zLlIiKQ0Kc291cmNlKCJSL3RoZW1lcy5SIikNCmBgYA0KDQojIFJlZmVyZW5jZSBkYXRhYmFzZXMgey50YWJzZXR9DQoNClRoZSBwaXBlUmxpbmUgd29ya2Zsb3cgdXNlcyB0aGUgW0lEVEFYQV0oaHR0cHM6Ly9taWNyb2Jpb21lam91cm5hbC5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2L3M0MDE2OC0wMTgtMDUyMS01KSBhbmQgQkxBU1Qgc29mdHdhcmUgdG8gYXNzaWduIHRheG9ub215IHRvIHRoZSBzZXF1ZW5jZSByZWFkcy4gVGhlc2UgcmVxdWlyZSBhIHByZS10cmFpbmVkIElEVEFYQSBtb2RlbCwgYW5kIGEgZmFzdGEgZmlsZSB3aXRoIGhlaXJhcmNoaWFsIHRheG9ub215LiBGb3IgaW5zZWN0cywgdGhlc2UgDQoNCiMjIERvd25sb2FkIHJlZmVyZW5jZSBkYXRhYmFzZQ0KDQpSZWZlcmVuY2UgZGF0YWJhc2VzIGZvciBpbnNlY3RzIGFuZCBhcmFjaG5pZHMgaGF2ZSBiZWVuIGhvc3RlZCBvbiBbWmVub2RvXShodHRwczovL3plbm9kby5vcmcvcmVjb3JkLzc2NTUzNTIjLllfTGdzSFpCei1nKSwgZWl0aGVyIGRvd25sb2FkIHRoZW0gbWFudWFsbHksIG9yIHdpdGggUiBiZWxvdzoNCg0KYGBge3J9DQojIFNvdXJjZSB0aGUgZnVuY3Rpb25zIGZpbGUgd2hpY2ggY29udGFpbnMgY29kZSB0byBkb3dubG9hZCBmcm9tIHplbm9kbw0Kc291cmNlKCJSL2Z1bmN0aW9ucy5SIikNCg0KIyBEb3dubG9hZCBmaWxlcyBmcm9tIHplbm9kbw0KZG93bmxvYWRfemVub2RvKA0KICBkb2kgPSAiMTAuNTI4MS96ZW5vZG8uNzY1NTM1MiIsDQogIHBhdGggPSAicmVmZXJlbmNlIg0KKQ0KYGBgDQoNCiMjIENyZWF0ZSB5b3VyIG93biByZWZlcmVuY2UgZGF0YWJhc2UNCg0KSWYgeW91IG5lZWQgYSBuZXcgZGF0YWJhc2UsIHRoZXNlIGNhbiBiZSBjcmVhdGVkIGZyb20gZ2VuYmFuayBhbmQgYmxhc3QgdXNpbmcgW3RheHJldHVybl0oaHR0cHM6Ly9naXRodWIuY29tL2FsZXhwaXBlci90YXhyZXR1cm4pIG9yIG90aGVyIHNpbWlhbHIgZGF0YWJhc2UgY3VyYXRpb24gcGFja2FnZXMuICANCg0KYGBge2NvZGV9DQo+QWNjZXNzaW9ufFJvb3Q7S2luZ2RvbTtQaHlsdW07Q2xhc3M7T3JkZXI7RmFtaWx5O0dlbnVzO1NwZWNpZXMNCkFDQ1RBR0FBQUdUQ0dUQUdBVENHQUFHVFRHQUFHQ0FUQ0dDQ0NHQVRHQVRDR1RDVEdBQUdDVEdUQUdDQVRHQUdUQ0dBVFRUVENBQ0FUVENBR0dHQVRBQ0NBVEFHR0FUQUMNCj5Sb290O0tpbmdkb207UGh5bHVtO0NsYXNzO09yZGVyO0ZhbWlseTtHZW51cztTcGVjaWVzDQpDR0NUQUdBQUFHVENHVEFHQUFHR0NUQ0dHQUdHVFRUR0FBR0NBVENHQ0NDR0FUR0dHQVRDVENHVFRHQ1RHVEFHQ0FUR0FHVEFDR0dBQ0FUVENBR0dHQVRDQVRBR0dBVEFDDQpgYGANCg0KVGhlIElEVEFYQSBtb2RlbCBjYW4gdGhlbiBiZSB0cmFpbmVkIG9uIHRoaXMgcmVmZXJlbmNlIGZhc3RhIC0gU2VlIHRoZSBbSURUQVhBIG1hbnVhbF0oaHR0cDovL3d3dzIuZGVjaXBoZXIuY29kZXMvRG9jdW1lbnRhdGlvbi9Eb2N1bWVudGF0aW9uLUNsYXNzaWZ5U2VxdWVuY2VzLmh0bWwpDQoNCiMgQ3JlYXRlIHNhbXBsZSB0cmFja2luZyBzaGVldCB7LX0NCg0KSW4gb3JkZXIgdG8gdHJhY2sgc2FtcGxlcyBhbmQgcmVsZXZhbnQgUUMgc3RhdGlzdGljcyB0aHJvdWdob3V0IHRoZSBtZXRhYmFyY29kaW5nIHBpcGVsaW5lLCB3ZSB3aWxsIGZpcnN0IGNyZWF0ZSBhIG5ldyBzYW1wbGUgdHJhY2tpbmcgc2hlZXQgZnJvbSBvdXIgaW5wdXQgaWxsdW1pbmEgc2FtcGxlc2hlZXRzLiBUaGlzIGZ1bmN0aW9uIHJlcXVpcmVzIGJvdGggdGhlIFNhbXBsZVNoZWV0LmNzdiB1c2VkIGZvciB0aGUgc2VxdWVuY2luZyBydW4sIGFuZCB0aGUgcnVuUGFyYW1ldGVycy54bWwsIGJvdGggb2Ygd2hpY2ggc2hvdWxkIGhhdmUgYmVlbiBhdXRvbWF0aWNhbGx5IG9idGFpbmVkIGZyb20gdGhlIGRlbXVsdGlwbGV4ZWQgc2VxdWVuY2luZyBydW4gZm9sZGVyIGluIHRoZSBiYXNoIHN0ZXAgYWJvdmUNCg0KYGBge3IgY3JlYXRlIHNhbXBsZXNoZWV0fQ0KcnVucyA8LSBkaXIoImRhdGEvIikgI0ZpbmQgYWxsIGRpcmVjdG9yaWVzIHdpdGhpbiBkYXRhDQpTYW1wbGVTaGVldCA8LSBsaXN0LmZpbGVzKHBhc3RlMCgiZGF0YS8iLCBydW5zKSwgcGF0dGVybj0gIlNhbXBsZVNoZWV0IiwgZnVsbC5uYW1lcyA9IFRSVUUpDQpydW5QYXJhbWV0ZXJzIDwtIGxpc3QuZmlsZXMocGFzdGUwKCJkYXRhLyIsIHJ1bnMpLCBwYXR0ZXJuPSAiW1JyXXVuUGFyYW1ldGVycy54bWwiLCBmdWxsLm5hbWVzID0gVFJVRSkNCg0KIyBDcmVhdGUgc2FtcGxlc2hlZXQgY29udGFpbmluZyBzYW1wbGVzIGFuZCBydW4gcGFyYW1ldGVycyBmb3IgYWxsIHJ1bnMNCnNhbWRmIDwtIGNyZWF0ZV9zYW1wbGVzaGVldChTYW1wbGVTaGVldCA9IFNhbXBsZVNoZWV0LCBydW5QYXJhbWV0ZXJzID0gcnVuUGFyYW1ldGVycywgdGVtcGxhdGUgPSAiVjQiKSAlPiUNCiAgZGlzdGluY3QoKQ0KDQojIENoZWNrIHRoYXQgc2FtcGxlX2lkcyBjb250YWluIGZjaWQsIGlmIG5vdDsgYXR0YXRjaA0Kc2FtZGYgPC0gc2FtZGYgJT4lDQogIG11dGF0ZShzYW1wbGVfaWQgPSBjYXNlX3doZW4oDQogICAgIXN0cl9kZXRlY3Qoc2FtcGxlX2lkLCBmY2lkKSB+IHBhc3RlMChmY2lkLCJfIixzYW1wbGVfaWQpLA0KICAgIFRSVUUgfiBzYW1wbGVfaWQNCiAgKSkNCg0KIyBDaGVjayB0aGF0IHNhbXBsZXMgbWF0Y2ggc2FtcGxlc2hlZXQNCmZhc3RxRnMgPC0gcHVycnI6Om1hcChsaXN0LmRpcnMoImRhdGEiLCByZWN1cnNpdmU9RkFMU0UpLA0KICAgICAgICAgICAgICAgICAgICAgIGxpc3QuZmlsZXMsIHBhdHRlcm49Il9SMV8iLCBmdWxsLm5hbWVzID0gVFJVRSkgJT4lDQogIHVubGlzdCgpICU+JQ0KICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSAiXiguKilcXC8iKSAlPiUNCiAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIig/Oi4oPyFfUykpKyQiKQ0KDQojIEZpbHRlciB1bmRldGVybWluZWQgcmVhZHMgZnJvbSBzYW1wbGUgc2hlZXQNCmZhc3RxRnMgPC0gZmFzdHFGc1shc3RyX2RldGVjdChmYXN0cUZzLCAiVW5kZXRlcm1pbmVkIildDQoNCiMgQ2hlY2sgZm9yIGZhc3RxIGZpbGVzIHRoYXQgYXJlIG1pc3NpbmcgZnJvbSBzYW1wbGVzaGVldA0KaWYgKGxlbmd0aChzZXRkaWZmKGZhc3RxRnMsIHNhbWRmJHNhbXBsZV9pZCkpID4gMCkge3dhcm5pbmcoIlRoZSBmYXN0cSBmaWxlL3M6ICIsIHNldGRpZmYoZmFzdHFGcywgc2FtZGYkc2FtcGxlX2lkKSwgIiBhcmUgbm90IGluIHRoZSBzYW1wbGUgc2hlZXQiKSB9DQoNCiMgQ2hlY2sgZm9yIHNhbXBsZV9pZHMgdGhhdCBkb250IGhhdmUgYSBjb3JyZXNwb25kaW5nIGZhc3RxIGZpbGUNCmlmIChsZW5ndGgoc2V0ZGlmZihzYW1kZiRzYW1wbGVfaWQsIGZhc3RxRnMpKSA+IDApIHsNCiAgd2FybmluZyhwYXN0ZTAoIlRoZSBmYXN0cSBmaWxlOiAiLA0KICAgICAgICAgICAgICAgICBzZXRkaWZmKHNhbWRmJHNhbXBsZV9pZCwgZmFzdHFGcyksDQogICAgICAgICAgICAgICAgICIgaXMgbWlzc2luZywgZHJvcHBpbmcgZnJvbSBzYW1wbGVzaGVldCBcbiIpKSANCiAgc2FtZGYgPC0gc2FtZGYgJT4lDQogICAgZmlsdGVyKCFzYW1wbGVfaWQgJWluJSBzZXRkaWZmKHNhbWRmJHNhbXBsZV9pZCwgZmFzdHFGcykpDQp9DQoNCiMgV3JpdGUgb3V0IHNhbXBsZSB0cmFja2luZyBzaGVldA0Kd3JpdGVfY3N2KHNhbWRmLCAic2FtcGxlX2RhdGEvU2FtcGxlX2luZm8uY3N2IikNCmBgYA0KDQojIEFkZCBQQ1IgcHJpbWVycyB0byBzYW1wbGUgc2hlZXQgey50YWJzZXR9DQoNClRoaXMgY2FuIGVpdGhlciBiZSBkb25lIG1hbnVhbGx5IGJ5IGVkaXRpbmcgdGhlIHNhbXBsZV9kYXRhL1NhbXBsZV9pbmZvLmNzdiBmaWxlLCBvciBpdCBjYW4gYmUgZG9uZSBpbiBSIGFzIGJlbG93Lg0KDQpJZiBhIHNpbmdsZSBwcmltZXIgc2V0IHdhcyB1c2VkIGFjcm9zcyBhbGwgc2FtcGxlcywgdGhlc2UgY2FuIHNpbXBseSBiZSBhZGRlZCB1c2luZyBhIG11dGF0ZSBjYWxsICgqKnRhYiAxKiopLg0KDQpJZiBkaWZmZXJlbnQgcHJpbWVycyB3ZXJlIHVzZWQgZm9yIGRpZmZlcmVudCBzYW1wbGVzLCB0aGVzZSBjYW4gYmUgc2V0IHVzaW5nIHBhdHRlcm4gbWF0Y2hpbmcgb24gdGhlIHNhbXBsZSBuYW1lcyB3aXRoIGNhc2Vfd2hlbiAoKip0YWIgMioqKS4NCg0KSWYgbXVsdGlwbGUgcHJpbWVyIHNldHMgYXJlIHVzZWQgcGVyIHNhbXBsZSwgYmVmb3JlIGluZGV4aW5nLCB0aGUgcGlwZWxpbmUgd2lsbCBjb25kdWN0IGFuIGV4dHJhIHJvdW5kIG9mIGRlbXVsdGlwbGV4aW5nIHRvIHNwbGl0IGVhY2ggc2FtcGxlIGJ5IHByaW1lci4gVGhpcyBvcHRpb24gY2FuIGJlIHNldCBieSBzcGxpdHRpbmcgZWFjaCBwcmltZXIgc2V0IHdpdGggYSBzZW1pY29sb24gKCoqdGFiIDMqKikgDQoNCiMjIFNpbmdsZSBwcmltZXIgc2V0DQoNCmBgYHtSfQ0KIyBBZGQgcHJpbWVycyB0byBzYW1wbGUgc2hlZXQNCnNhbWRmIDwtIHNhbWRmICU+JQ0KICBtdXRhdGUocGNyX3ByaW1lcnMgPSAiZndoRjItZndoUjJuIiwNCiAgZm9yX3ByaW1lcl9zZXEgPSAiR0dEQUNXR0dXVEdBQUNXR1RXVEFZQ0NIQ0MiLA0KICByZXZfcHJpbWVyX3NlcSA9ICJHVFJBVFdHQ0hDQ0RHQ1RBUldBQ1dHRyINCiAgKQ0KDQp3cml0ZV9jc3Yoc2FtZGYsICJzYW1wbGVfZGF0YS9TYW1wbGVfaW5mby5jc3YiKQ0KYGBgDQoNCiMjIERpZmZlcmVudCBwcmltZXIgc2V0cyBwZXIgc2FtcGxlDQoNCmBgYHtSfQ0KIyBBZGQgUENSIHByaW1lcnMgdG8gc2FtcGxlIHNoZWV0DQpzYW1kZiA8LSBzYW1kZiAlPiUNCiAgbXV0YXRlKHBjcl9wcmltZXJzID0gY2FzZV93aGVuKA0KICAgIHN0cl9kZXRlY3Qoc2FtcGxlX25hbWUsICJwcmltZXIxIikgfiAiZndoRjItZndoUjJuIiwNCiAgICBzdHJfZGV0ZWN0KHNhbXBsZV9uYW1lLCAicHJpbWVyMiIpIH4gIkVJRjNMbWluaUY0LUVJRjNsbWluaVI0Ig0KICApLA0KICBmb3JfcHJpbWVyX3NlcSA9IGNhc2Vfd2hlbigNCiAgICBzdHJfZGV0ZWN0KHNhbXBsZV9uYW1lLCAicHJpbWVyMSIpIH4gIkdHREFDV0dHV1RHQUFDV0dUV1RBWUNDSENDIiwNCiAgICBzdHJfZGV0ZWN0KHNhbXBsZV9uYW1lLCAicHJpbWVyMiIpIH4gIkdBVEdDR1lDR1RUQVRHQ1lHQVRHQyINCiAgKSwNCiAgcmV2X3ByaW1lcl9zZXEgPSBjYXNlX3doZW4oDQogICAgc3RyX2RldGVjdChzYW1wbGVfbmFtZSwgInByaW1lcjEiKSB+ICJHVFJBVFdHQ0hDQ0RHQ1RBUldBQ1dHRyIsDQogICAgc3RyX2RldGVjdChzYW1wbGVfbmFtZSwgInByaW1lcjIiKSB+ICJUVFJBQVlBQ1RUQ1lBUkFUQ1JDQyINCiAgKSkNCg0Kd3JpdGVfY3N2KHNhbWRmLCAic2FtcGxlX2RhdGEvU2FtcGxlX2luZm8uY3N2IikNCmBgYA0KDQojIyBNdWx0aXBsZSBwcmltZXIgc2V0cyBwZXIgc2FtcGxlDQoNCmBgYHtSfQ0KIyBBZGQgUENSIHByaW1lcnMgdG8gc2FtcGxlIHNoZWV0DQpzYW1kZiA8LSBzYW1kZiAlPiUNCiAgbXV0YXRlKA0KICAgIHBjcl9wcmltZXJzID0gImZ3aEYyLWZ3aFIybkRhYztFSUYzTG1pbmlGNC1FSUYzbG1pbmlSNCIsDQogICAgZm9yX3ByaW1lcl9zZXEgPSAiR0dEQUNXR0dXVEdBQUNXR1RXVEFZQ0NIQ0M7R0FUR0NHWUNHVFRBVEdDWUdBVEdDIiwNCiAgICByZXZfcHJpbWVyX3NlcSA9ICJHVFJBVFdHQ0hDQ0lHQ1RBQURBQ0hHRztUVFJBQVlBQ1RUQ1lBUkFUQ1JDQyINCiAgICApDQoNCndyaXRlX2NzdihzYW1kZiwgInNhbXBsZV9kYXRhL1NhbXBsZV9pbmZvLmNzdiIpDQpgYGANCg0KDQojIENyZWF0ZSBwYXJhbWV0ZXJzIGZpbGUgey50YWJzZXR9DQoNClRoZSBwYXJhbWV0ZXJzIGZpbGUgdGFibGUgdGhlIHJlc3BlY3RpdmUgdGFyZ2V0IGdlbmUsIHJlZmVyZW5jZSBkYXRhYmFzZXMsIGFuZCBmaWx0ZXJpbmcgcGFyYW1ldGVycyBmb3IgZWFjaCBwcmltZXIgc2V0IHVzZWQgdG8gYW1wbGlmeSB0aGUgc2FtcGxlcy4gQXMgdGhlIHBjcl9wcmltZXJzIGNvbHVtbiBpcyB1c2VkIGluIHRoZSBwaXBlbGluZSB0byBtYXRjaCB0aGUgcGFyYW1ldGVycyB0byB0aGUgcmVzcGVjdGl2ZSBzYW1wbGUsIGl0IGlzIGNyaXRpY2FsIHRoYXQgdGhlIHByaW1lciBuYW1lcyBtYXRjaCB0aG9zZSBzZXQgaW4gdGhlIHByZXZpb3VzIHN0ZXAuDQoNCklmIGEgc2luZ2xlIHByaW1lciBzZXQgd2FzIHVzZWQgYWNyb3NzIGFsbCBzYW1wbGVzLCB0aGVzZSBjYW4gc2ltcGx5IGJlIGFkZGVkIHRvIHRoZSB0YWJsZSBhcyBiZWxvdyAoKip0YWIgMSoqKS4NCg0KSWYgZGlmZmVyZW50IHByaW1lcnMgd2VyZSB1c2VkIGZvciBkaWZmZXJlbnQgc2FtcGxlcywgdGhlc2UgY2FuIGJlIHNldCBhcyBkaWZmZXJlbnQgcm93cyBpbiB0aGUgdGFibGUgdXNpbmcgYygpIHdoZW4gY3JlYXRpZ24gdGhlIHRpYmJsZSAoKip0YWIgMioqKS4NCg0KSWYgbXVsdGlwbGUgcHJpbWVyIHJlZmVyZW5jZSBkYXRhYmFzZXMgYXJlIHRvIGJlIHVzZWQgZm9yIGVhY2ggc2FtcGxlLCB0aGVzZSBjYW4gYmUgc2V0IGJ5IHNwbGl0dGluZyBlYWNoIGEgc2VtaWNvbG9uLiBUaGUgdGF4b25vbWljIGFzc2lnbm1lbnQgd2lsbCBiZSBjb25kdWN0ZWQgc2VxdWVudGlhbGx5IHRocm91Z2ggdGhlIGRhdGFiYXNlcyBmcm9tIGxlZnQgdG8gcmlnaHQsIHdpdGggdGhlIHNlY29uZCByZWZlcmVuY2UgZGF0YWJhc2Ugb25seSBiZWluZyB1c2VkIGZvciB0aG9zZSBBU1ZzIHRoYXQgY291bGRudCBiZSBhc3NpZ25lZCB0byBzcGVjaWVzIGxldmVsIHVzaW5nIHRoZSBmaXJzdCBkYXRhYmFzZXMgKCoqdGFiIDMqKikgDQoNCioqUGFyYW1ldGVyIG9wdGlvbnMqKg0KDQoqICoqUHJpbWVyIHBhcmFtZXRlcnM6KioNCiAgICArICoqcGNyX3ByaW1lcnMqKiAtIE5hbWUgb2YgUENSIHByaW1lcnMgLSBtdXN0IG1hdGNoIHNhbWRmIGZpbGUNCiAgICArICoqdGFyZ2V0X2dlbmUqKiAtIE5hbWUgb2YgdGFyZ2V0IGdlbmUNCiAgICArICoqbWF4X3ByaW1lcl9taXNtYXRjaCoqIC0gSG93IG11Y2ggbWlzbWF0Y2ggdG8gYWxsb3cgd2hlbiBkZXRlY3RpbmcgcHJpbWVyIHNlcXVlbmNlcw0KDQoqICoqUmVhZCBmaWx0ZXJpbmc6KioNCiAgICArICoqcmVhZF9taW5fbGVuZ3RoKiogLSBNaW5pbXVtIGxlbmd0aCBvZiBwcmltZXIgdHJpbW1lZCByZWFkcw0KICAgICsgKipyZWFkX21heF9sZW5ndGgqKiAtIE1heGltdW0gbGVuZ3RoIG9mIHByaW1lciB0cmltbWVkIHJlYWRzDQogICAgKyAqKnJlYWRfbWF4X2VlKiogLSBNYXhpbXVtIGV4cGVjdGVkIGVycm9ycyBvZiBwcmltZXIgdHJpbW1lZCByZWFkcw0KICAgICsgKipyZWFkX3RydW5jX2xlbmd0aCoqIC0gTGVuZ3RoIHRvIGN1dCBhbGwgbG9uZ2VyIHJlYWRzIHRvDQogICAgKyAqKnJlYWRfdHJpbV9sZWZ0KiogLSBSZW1vdmUgdGhpcyBtYW55IGJwIGZyb20gbGVmdCBzaWRlIG9mIHByaW1lciB0cmltbWVkIHJlYWRzDQogICAgKyAqKnJlYWRfdHJpbV9yaWdodCoqIC0gUmVtb3ZlIHRoaXMgbWFueSBicCBmcm9tIHJpZ2h0IHNpZGUgb2YgcHJpbWVyIHRyaW1tZWQgcmVhZHMNCg0KKiAqKkFTViBmaWx0ZXJpbmcqKg0KICAgICsgKiphc3ZfbWluX2xlbmd0aCoqIC0gTWluaW11bSBsZW5ndGggb2YgYW1wbGljb24NCiAgICArICoqYXN2X21heF9sZW5ndGgqKiAtIE1heGltdW0gbGVuZ3RoIG9mIGFtcGxpY29uDQogICAgKyAqKmhpZ2hfc2Vuc2l0aXZpdHkqKiAtIE9wdGlvbiB0byB0dXJuIG9uIFtwc2V1ZG8gcG9vbGluZ10oaHR0cHM6Ly9iZW5qam5lYi5naXRodWIuaW8vZGFkYTIvcHNldWRvLmh0bWwpLCBzZXR0aW5nIHRoaXMgdG8gRkFMU0UgZ3JlYXRseSBzcGVlZHMgdXAgQVNWIGluZmVyZW5jZSBhdCB0aGUgZXhwZW5zZSBvZiBkZXRlY3RpbmcgZmV3ZXIgcmFyZSAoPDUgcmVhZHMpIHRheGEuDQogICAgKyAqKmNvbmNhdF91bm1lcmdlZCoqIC0gUmV0YWluIGFueSB1bm1lcmdlZCByZWFkIHBhaXJzIGJ5IGNvbmNhdGVuYXRpbmcgdGhlbSB0b2dldGhlciBzZXBhcmF0ZWQgYnkgYSBzdHJpbmcgb2YgMTAgTiBiYXNlcw0KICAgICsgKipnZW5ldGljX2NvZGUqKiAtIEdlbmV0aWMgY29kZSBmb3IgYW1wbGljb24gLSBzZWUgQmlvc3RyaW5nczo6R0VORVRJQ19DT0RFX1RBQkxFDQogICAgKyAqKmNvZGluZyoqIC0gSXMgdGhlIGFtcGxpY29uIGZyb20gYSBwcm90ZWluIGNvZGluZyBnZW5lDQogICAgKyAqKnBobW0qKiAtIFBhdGggdG8gcHJvZmlsZSBoaWRkZW4gbWFya292IG1vZGVsIChPcHRpb25hbCkNCg0KKiAqKlRheG9ub21pYyBhc3NpZ25tZW50OioqDQogICAgKyAqKmlkdGF4YV9kYioqIC0gUGF0aCB0byB0cmFpbmVkIElEVEFYQSBtb2RlbA0KICAgICsgKipyZWZfZmFzdGEqKiAtIFBhdGggdG8gZmFzdGEgZmlsZSBvZiByZWZlcmVuY2UgZGF0YWJhc2UNCiAgICArICoqaWR0YXhhX2NvbmZpZGVuY2UqKiAtIE1pbmltdW0gYm9vdHN0cmFwIGNvbmZpZGVuY2UgZm9yIElEVEFYQQ0KICAgICsgKipydW5fYmxhc3QqKiAtIFdoZXRoZXIgYSBibGFzdCB0b3AgaGl0IHNlYXJjaCBzaG91bGQgYmUgY29uZHVjdGVkIGluIGFkZGl0aW9uIHRvIElEVEFYQQ0KICAgICsgKipibGFzdF9taW5faWRlbnRpdHkqKiAtIE1pbmltdW0gbnVjbGVvdGlkZSBpZGVudGl0eSBmb3IgQkxBU1QNCiAgICArICoqYmxhc3RfbWluX2NvdmVyYWdlKiogLSBNaW5pbXVtIHF1ZXJ5IGNvdmVyYWdlIGZvciBCTEFTVA0KICAgICsgKip0YXJnZXRfa2luZ2RvbSoqIC0gU3Vic2V0IHRvIHRhcmdldCBraW5nZG9tDQogICAgKyAqKnRhcmdldF9waHlsdW0qKiAtIFN1YnNldCB0byB0YXJnZXQgcGh5bHVtDQogICAgKyAqKnRhcmdldF9jbGFzcyoqIC0gU3Vic2V0IHRvIHRhcmdldCBjbGFzcw0KICAgICsgKip0YXJnZXRfb3JkZXIqKiAtIFN1YnNldCB0byB0YXJnZXQgb3JkZXINCiAgICArICoqdGFyZ2V0X2ZhbWlseSoqIC0gU3Vic2V0IHRvIHRhcmdldCBmYW1pbHkNCiAgICArICoqdGFyZ2V0X2dlbnVzKiogLSBTdWJzZXQgdG8gdGFyZ2V0IGdlbnVzDQogICAgKyAqKnRhcmdldF9zcGVjaWVzKiogLSBTdWJzZXQgdG8gdGFyZ2V0IHNwZWNpZXMNCg0KKiAqKlNhbXBsZSAmIFRheG9uIGZpbHRlcmluZzoqKg0KICAgICsgKiptaW5fc2FtcGxlX3JlYWRzKiogLSBNaW5pbXVtIHJlYWRzIHBlciBzYW1wbGUgYWZ0ZXIgZmlsdGVyaW5nDQogICAgKyAqKm1pbl90YXhhX3JlYWRzKiogLSBNaW5pbXVtIHJlYWRzIHBlciBBU1YgdG8gcmV0YWluDQogICAgKyAqKm1pbl90YXhhX3JhKiogLSBNaW5pbXVtIHJlbGF0aXZlIGFidW5kYW5jZSBwZXIgQVNWIHRvIHJldGFpbi4gMWUtNCBpcyAwLjAxJQ0KDQoqICoqR2VuZXJhbCBwaXBlbGluZSBwYXJhbWV0ZXJzKioNCiAgICArICoqdGhyZWFkcyoqIC0gTnVtYmVyIG9mIENQVSB0aHJlYWRzIHRvIHJ1biB0aGUgcGlwZWxpbmUgYWNyb3NzDQogICAgDQojIyBTaW5nbGUgcHJpbWVyIHNldA0KDQpgYGB7Un0NCiMgUGFyYW1zIHRvIGFkZCBpbiBzdGVwX2FkZF9wYXJhbWV0ZXJzDQpwYXJhbXMgPC0gdGliYmxlKA0KICAjIFByaW1lciBwYXJhbWV0ZXJzDQogIHBjcl9wcmltZXJzID0gImZ3aEYyLWZ3aFIybiIsDQogIHRhcmdldF9nZW5lPSJDT0kiLA0KICBtYXhfcHJpbWVyX21pc21hdGNoPTAsDQoNCiAgIyBSZWFkIGZpbHRlcmluZw0KICByZWFkX21pbl9sZW5ndGggPSAyMCwNCiAgcmVhZF9tYXhfbGVuZ3RoID0gSW5mLA0KICByZWFkX21heF9lZSA9IDEsDQogIHJlYWRfdHJ1bmNfbGVuZ3RoID0gMTUwLA0KICByZWFkX3RyaW1fbGVmdCA9IDAsIA0KICByZWFkX3RyaW1fcmlnaHQgPSAwLA0KICANCiAgIyBBU1YgZmlsdGVyaW5nDQogIGFzdl9taW5fbGVuZ3RoID0gMTk1LCANCiAgYXN2X21heF9sZW5ndGggPSAyMTUsDQogIGhpZ2hfc2Vuc2l0aXZpdHkgPSBUUlVFLA0KICBjb25jYXRfdW5tZXJnZWQgPSBGQUxTRSwNCiAgZ2VuZXRpY19jb2RlID0gIlNHQzQiLA0KICBjb2RpbmcgPSBUUlVFLA0KICBwaG1tID0gInJlZmVyZW5jZS9mb2xtZXJfZnVsbGVuZ3RoX21vZGVsLnJkcyIsDQogIA0KICAjIFRheG9ub21pYyBhc3NpZ25tZW50DQogIGlkdGF4YV9kYiA9ICJyZWZlcmVuY2UvaWR0YXhhX2JmdHJpbW1lZC5yZHMiLA0KICByZWZfZmFzdGEgPSAicmVmZXJlbmNlL2luc2VjdGFfaGllcmFyY2hpYWxfYmZ0cmltbWVkLmZhLmd6IiwNCiAgaWR0YXhhX2NvbmZpZGVuY2UgPSA2MCwNCiAgcnVuX2JsYXN0PVRSVUUsDQogIGJsYXN0X21pbl9pZGVudGl0eSA9IDk3LA0KICBibGFzdF9taW5fY292ZXJhZ2UgPSA5MCwNCiAgdGFyZ2V0X2tpbmdkb20gPSAiTWV0YXpvYSIsDQogIHRhcmdldF9waHlsdW0gPSAiQXJ0aHJvcG9kYSIsDQogIHRhcmdldF9jbGFzcyA9IE5BLA0KICB0YXJnZXRfb3JkZXIgPSBOQSwNCiAgdGFyZ2V0X2ZhbWlseSA9IE5BLA0KICB0YXJnZXRfZ2VudXMgPSBOQSwNCiAgdGFyZ2V0X3NwZWNpZXM9IE5BLA0KICANCiAgIyBTYW1wbGUgJiBUYXhvbiBmaWx0ZXJpbmcNCiAgbWluX3NhbXBsZV9yZWFkcyA9IDEwMDAsDQogIG1pbl90YXhhX3JlYWRzPSBOQSwNCiAgbWluX3RheGFfcmEgPSAxZS00LCAjMWUtNCBpcyAwLjAxJQ0KICAgIA0KICAjIEdlbmVyYWwgcGlwZWxpbmUgcGFyYW1ldGVycw0KICB0aHJlYWRzID0gMQ0KKQ0KDQp3cml0ZV9jc3YocGFyYW1zLCAic2FtcGxlX2RhdGEvbG9jaV9wYXJhbXMuY3N2IikNCmBgYA0KDQojIyBEaWZmZXJlbnQgb3IgbXVsdGlwbGUgcHJpbWVyIHNldHMgcGVyIHNhbXBsZQ0KDQpgYGB7Un0NCiMgUGFyYW1zIHRvIGFkZCBpbiBzdGVwX2FkZF9wYXJhbWV0ZXJzDQpwYXJhbXMgPC0gdGliYmxlKA0KICAjIFByaW1lciBwYXJhbWV0ZXJzDQogIHBjcl9wcmltZXJzID0gYygiZndoRjItZndoUjJuRGFjIiwgIkVJRjNMbWluaUY0LUVJRjNsbWluaVI0IiksDQogIHRhcmdldF9nZW5lPWMoIkNPSSIsICJFSUYzTCIpLA0KICBtYXhfcHJpbWVyX21pc21hdGNoPTEsDQoNCiAgIyBSZWFkIGZpbHRlcmluZw0KICByZWFkX21pbl9sZW5ndGggPSAyMCwNCiAgcmVhZF9tYXhfbGVuZ3RoID0gSW5mLA0KICByZWFkX21heF9lZSA9IDEsDQogIHJlYWRfdHJ1bmNfbGVuZ3RoID0gMTUwLA0KICByZWFkX3RyaW1fbGVmdCA9IDAsDQogIHJlYWRfdHJpbV9yaWdodCA9IDAsDQogIA0KICAjIEFTViBmaWx0ZXJpbmcNCiAgYXN2X21pbl9sZW5ndGggPSBjKDE5NSwgMjA3KSwNCiAgYXN2X21heF9sZW5ndGggPSBjKDIxNSwgMjI3KSwNCiAgaGlnaF9zZW5zaXRpdml0eSA9IFRSVUUsDQogIGNvbmNhdF91bm1lcmdlZCA9IEZBTFNFLA0KICBnZW5ldGljX2NvZGUgPSBjKCJTR0M0IiwgIlNHQzAiKSwNCiAgY29kaW5nID0gYyhUUlVFLCBUUlVFKSwNCiAgcGhtbSA9IGMoInJlZmVyZW5jZS9waG1tL0JhY3Ryb2NlcmFfQ09JLnJkcyIsICJyZWZlcmVuY2UvcGhtbS9CYWN0cm9jZXJhX0VJRjNMLnJkcyIpLA0KICANCiAgIyBUYXhvbm9taWMgYXNzaWdubWVudA0KICBpZHRheGFfZGIgPSBjKCJyZWZlcmVuY2UvQ09JX2lkdGF4YS5yZHMiLCJyZWZlcmVuY2UvRUlGM0xfaWR0YXhhLnJkcyIpLA0KICByZWZfZmFzdGEgPSBjKCJyZWZlcmVuY2UvQ09JX2hpZXJhcmNoaWFsLmZhLmd6IiwgInJlZmVyZW5jZS9FSUYzTF9oaWVyYXJjaGlhbC5mYS5neiIpLA0KICBpZHRheGFfY29uZmlkZW5jZSA9IDYwLA0KICBydW5fYmxhc3Q9VFJVRSwNCiAgYmxhc3RfbWluX2lkZW50aXR5ID0gOTcsDQogIGJsYXN0X21pbl9jb3ZlcmFnZSA9IDkwLA0KICB0YXJnZXRfa2luZ2RvbSA9IGMoIk1ldGF6b2EiLCAiTWV0YXpvYSIpLA0KICB0YXJnZXRfcGh5bHVtID0gYygiQXJ0aHJvcG9kYSIsIkFydGhyb3BvZGEiKSwNCiAgdGFyZ2V0X2NsYXNzID0gTkEsDQogIHRhcmdldF9vcmRlciA9IE5BLA0KICB0YXJnZXRfZmFtaWx5ID0gTkEsIA0KICB0YXJnZXRfZ2VudXMgPSBOQSwgIA0KICB0YXJnZXRfc3BlY2llcz0gTkEsICANCiAgDQogICMgU2FtcGxlICYgVGF4b24gZmlsdGVyaW5nDQogIG1pbl9zYW1wbGVfcmVhZHMgPSBjKDEwMDAsIDEwMDApLA0KICBtaW5fdGF4YV9yZWFkcz0gTkEsIA0KICBtaW5fdGF4YV9yYSA9IGMoMWUtNCwgMWUtNCksDQopDQoNCndyaXRlX2NzdihwYXJhbXMsICJzYW1wbGVfZGF0YS9sb2NpX3BhcmFtcy5jc3YiKQ0KYGBgDQoNCiMjIE11bHRpcGxlIHJlZmVyZW5jZSBkYXRhYmFzZXMNCg0KYGBge3J9DQpwYXJhbXMgPC0gdGliYmxlKA0KICAjIFByaW1lciBwYXJhbWV0ZXJzDQogIHBjcl9wcmltZXJzID0gYygiZndoRjItZndoUjJuRGFjIiwgIkVJRjNMbWluaUY0LUVJRjNsbWluaVI0IiksDQogIHRhcmdldF9nZW5lPWMoIkNPSSIsICJFSUYzTCIpLA0KICBtYXhfcHJpbWVyX21pc21hdGNoPTAsDQoNCiAgIyBSZWFkIGZpbHRlcmluZw0KICByZWFkX21pbl9sZW5ndGggPSAyMCwNCiAgcmVhZF9tYXhfbGVuZ3RoID0gSW5mLA0KICByZWFkX21heF9lZSA9IDEsDQogIHJlYWRfdHJ1bmNfbGVuZ3RoID0gMTUwLA0KICByZWFkX3RyaW1fbGVmdCA9IDAsDQogIHJlYWRfdHJpbV9yaWdodCA9IDAsDQogIA0KICAjIEFTViBmaWx0ZXJpbmcNCiAgYXN2X21pbl9sZW5ndGggPSBjKDE5NSwgMjA3KSwNCiAgYXN2X21heF9sZW5ndGggPSBjKDIxNSwgMjI3KSwNCiAgaGlnaF9zZW5zaXRpdml0eSA9IFRSVUUsDQogIGNvbmNhdF91bm1lcmdlZCA9IEZBTFNFLA0KICBnZW5ldGljX2NvZGUgPSBjKCJTR0M0IiwgIlNHQzAiKSwNCiAgY29kaW5nID0gYyhUUlVFLCBUUlVFKSwNCiAgcGhtbSA9IGMoInJlZmVyZW5jZS9waG1tL0JhY3Ryb2NlcmFfQ09JLnJkcyIsICJyZWZlcmVuY2UvcGhtbS9CYWN0cm9jZXJhX0VJRjNMLnJkcyIpLA0KICANCiAgIyBUYXhvbm9taWMgYXNzaWdubWVudA0KICBpZHRheGFfZGIgPSBjKCJyZWZlcmVuY2UvQ09JX2ludGVybmFsX2lkdGF4YS5yZHM7cmVmZXJlbmNlL0NPSV9pZHRheGEucmRzIiwNCiAgICAgICAgICAgICAicmVmZXJlbmNlL0VJRjNMX2ludGVybmFsX2lkdGF4YS5yZHM7cmVmZXJlbmNlL0VJRjNMX2lkdGF4YS5yZHMiKSwNCiAgcmVmX2Zhc3RhID0gYygicmVmZXJlbmNlL0NPSV9pbnRlcm5hbC5mYS5nejtyZWZlcmVuY2UvQ09JX2hpZXJhcmNoaWFsLmZhLmd6IiwNCiAgICAgICAgICAgICAgICJyZWZlcmVuY2UvRUlGM0xfaW50ZXJuYWwuZmEuZ3o7cmVmZXJlbmNlL0VJRjNMX2hpZXJhcmNoaWFsLmZhLmd6IiksDQogIGlkdGF4YV9jb25maWRlbmNlID0gNjAsDQogIHJ1bl9ibGFzdD1UUlVFLA0KICBibGFzdF9taW5faWRlbnRpdHkgPSA5NywNCiAgYmxhc3RfbWluX2NvdmVyYWdlID0gOTAsDQogIHRhcmdldF9raW5nZG9tID0gYygiTWV0YXpvYSIsICJNZXRhem9hIiksDQogIHRhcmdldF9waHlsdW0gPSBjKCJBcnRocm9wb2RhIiwiQXJ0aHJvcG9kYSIpLA0KICB0YXJnZXRfY2xhc3MgPSBOQSwNCiAgdGFyZ2V0X29yZGVyID0gTkEsDQogIHRhcmdldF9mYW1pbHkgPSBOQSwgDQogIHRhcmdldF9nZW51cyA9IE5BLCAgDQogIHRhcmdldF9zcGVjaWVzPSBOQSwgIA0KICANCiAgIyBTYW1wbGUgJiBUYXhvbiBmaWx0ZXJpbmcNCiAgbWluX3NhbXBsZV9yZWFkcyA9IGMoMTAwMCwgMTAwMCksDQogIG1pbl90YXhhX3JlYWRzPSBOQSwNCiAgbWluX3RheGFfcmEgPSBjKDFlLTQsIDFlLTQpLA0KKQ0KDQp3cml0ZV9jc3YocGFyYW1zLCAic2FtcGxlX2RhdGEvbG9jaV9wYXJhbXMuY3N2IikNCmBgYA0KDQojIFJ1biBwaXBlbGluZSB7LX0NCk5vdyB0aGF0IHRoZSBzYW1wbGUgZGF0YSBzaGVldCBhbmQgcGFyYW1ldGVycyBhcmUgZGVmaW5lZCwgdGhlIHBpcGVsaW5lIHN0ZXBzIGNhbiBub3cgYmUgcnVuIGF1dG9tYXRpY2FsbHkgdXNpbmcgdGhlIHRhcl9tYWtlKCkgY29tbWFuZA0KDQpgYGB7cn0NCnRhcl9tYWtlKCkNCmBgYA0KDQojIFJlc3VsdHMNCg0KQWZ0ZXIgdGhlIHJ1biwgdHdvIGRpcmVjdG9yaWVzIHNob3VsZCBoYXZlIGJlZW4gbWFkZSB3aXRoaW4gdGhlIG91dHB1dCBmb2xkZXIsIG91dHB1dC9yZXN1bHRzL3VuZmlsdGVyZWQgd2hpY2ggY29udGFpbnMgdGhlIHJlc3VsdHMgYmVmb3JlIGFueSB0YXhvbm9taWMgc3Vic2V0dGluZywgc2FtcGxlIG1pbmltdW0gYWJ1bmRhbmNlLCBhbmQgQVNWIG1pbmltdW0gYWJ1bmRhbmNlIGZpbHRlcmluZywgYW5kIG91dHB1dC9yZXN1bHRzL2ZpbHRlcmVkIGNvbnRhaW5pbmcgdGhlIHJlc3VsdHMgYWZ0ZXIgdGhlc2Ugc3RlcHMuIFdpdGhpbiBlYWNoIG9mIHRoZXNlIGZvbGRlcnMgdGhlcmUgc2hvdWxkIGJlIGEgc2VyaWVzIG9mIG91dHB1dHM6DQoNCiogKipzdW1tYXJ5LmNzdioqIC0gVGhpcyBpcyB0aGUgbWFpbiBzdW1tYXJ5IGZpbGUgd2hpY2ggbGlzdHMgdGhlIGFidW5kYW5jZSBvZiBlYWNoIEFTViwgdGhlIHRheG9ub215IGFzc2lnbmVkIHRvIGl0LCBhbmQgdGhlIHJlYWQgY291bnRzIGZvciBlYWNoIHNhbXBsZSBpdCB3YXMgZGV0ZWN0ZWQgaW4uDQoNCiogKipwcy5yZHMqKiAtIFRoaXMgcGh5bG9zZXEgb2JqZWN0IGNvbnRhaW5zIHRoZSBzYW1lIGluZm9ybWF0aW9uIGFzIHRoZSBzdW1tYXJ5IGZpbGUsIGJ1dCBpbiBhIGZvcm1hdCB0aGF0IGNhbiBiZSBhbmFseXNlZCBmdXJ0aGVyIHVzaW5nIHRoZSBbcGh5bG9zZXEgUiBwYWNrYWdlXShodHRwczovL2pvZXk3MTEuZ2l0aHViLmlvL3BoeWxvc2VxLyksIGEgdXNlZnVsIHRvb2wgZm9yIHBsb3R0aW5nIGFuZCBmdXJ0aGVyIGFuYWx5c2lzIG9mIG1ldGFiYXJjb2RpbmcgYW5kIG1pY3JvYmlvbWUgZGF0YXNldHMuDQoNCiogKiphc3ZzLmZhc3RhKiogLSBUaGlzIGNvbnRhaW5zIHRoZSBhbXBsaWZpY2F0aW9uIHNlcXVlbmNlIHZhcmlhbnRzIGluZmVycmVkIGZyb20gdGhlIGRhdGEgc2V0DQoNCiogKipzZXF0YWIuY3N2KiogLSBUaGlzIGxpc3RzIHRoZSBhYnVuZGFuY2Ugb2YgZWFjaCBBU1YgYW5kIHRoZSBzYW1wbGUgaXQgd2FzIGRldGVjdGVkIGluLiBUaGlzIGZpbGUgaXMgZ2VuZXJhbGx5IGZvciBkZXZlbG9wbWVudCBwdXJwb3NlcyBvbmx5LCBhbmQgYWxsIGluZm9ybWF0aW9uIGNvbnRhaW5lZCBoZXJlIGlzIHByZXNlbnQgaW4gdGhlIHN1bW1tYXJ5IGNzdi4NCg0KKiAqKnRheHRhYi5jc3YqKiAtIFRoaXMgbGlzdHMgdGhlIGhlaXJhcmNoaWFsIHRheG9ub215IGFzc2lnbmVkIHRvIGVhY2ggQVNWLiBUaGlzIGZpbGUgaXMgZ2VuZXJhbGx5IGZvciBkZXZlbG9wbWVudCBwdXJwb3NlcyBvbmx5LCBhbmQgYWxsIGluZm9ybWF0aW9uIGNvbnRhaW5lZCBoZXJlIGlzIHByZXNlbnQgaW4gdGhlIHN1bW1tYXJ5IGNzdi4NCg0KKiAqKnNhbWRmLmNzdioqIC0gVGhpcyBpcyB0aGUgc2FtcGxlIHRyYWNraW5nIHNoZWV0IHRoYXQgbGlzdHMgdGhlIHNlcXVlbmNpbmcgZGV0YWlscyBmb3IgZWFjaCBzYW1wbGUuIFRoaXMgZmlsZSBpcyBnZW5lcmFsbHkgZm9yIGRldmVsb3BtZW50IHB1cnBvc2VzIG9ubHksIGFuZCBhbGwgaW5mb3JtYXRpb24gY29udGFpbmVkIGhlcmUgaXMgcHJlc2VudCBpbiB0aGUgc3VtbW1hcnkgY3N2Lg0KDQoqICoqcmF3LmNzdioqIC0gVGhpcyBpcyBhIGxhcmdlIGZpbGUgY29udGFpbmluZyBhbGwgdGhlIGFib3ZlIHJlc3VsdHMgaW4gYSBzaW5nbGUgY3N2IGluIGEgJ2xvbmcnIGZvcm1hdCBhcHByb3ByaWF0ZSBmb3IgZnVydGhlciBzdGF0aXN0aWNhbCBhbmFseXNpcy4NCg0KIyMgUXVhbGl0eSBjb250cm9sDQoNClRoZSBwaXBlbGluZSBhbHNvIG91dHB1dHMgc29tZSBxdWFsaXR5IGNvbnRyb2wgcGxvdHMgdGhhdCBzaG91bGQgYmUgY2hlY2tlZCB0byBlbnN1cmUgdGhlIHBpcGVsaW5lIGhhcyBydW4gY29ycmVjdGx5IGFuZCB0aGUgb3V0cHV0cyBhcmUgYXMgZGVzaXJlZA0KDQoqICoqUGVyLWZsb3djZWxsIHF1YWxpdHkgY2hlY2tzKioNCiAgICArICoqb3V0cHV0L2xvZ3MvRkNJRC9GQ0lEX2Zsb3djZWxsX3FjLnBkZioqIC0gVGhpcyBzZXQgb2YgcGxvdHMgc3VtbWFyaXNlcyB0aGUgcmF3IG91dHB1dHMgZnJvbSB0aGUgc2VxdWVuY2luZyBydW4uIFRoZSBmaXJzdCBwYWdlIHNob3dzIHRoZSBhdmVyYWdlIGltYWdpbmcgaW50ZW5zaXR5IGZvciB0aGUgOTAlIHBlcmNlbnRpbGUgb2YgdGhlIGRhdGEgZm9yIGVhY2ggdGlsZSBvbiB0aGUgc2VxdWVuY2luZyBmbG93IGNlbGwuIFRoZSBzZWNvbmQgcGFnZSBzaG93cyB0aGUgbnVtYmVyIG9mIGNsdXN0ZXJzIChyZWFkcykgaW1hZ2VkIGJ5IHRoZSBzZXFldW5jZXIsIGFuZCB0aGUgbnVtYmVyIG9mIGNsdXN0ZXJzIHBhc3NpbmcgdGhlIG1hY2hpbmVzIGZpbHRlcmluZy4gVGhlIHRoaXJkIHBhZ2Ugc2hvd3MgdGhlIFFzY29yZSBieSBjeWNsZSBmb3IgYWxsIHJlYWRzLg0KICAgIA0KICAgICsgKipvdXRwdXQvbG9ncy9GQ0lEL0ZDSURfaW5kZXhfc3dpdGNoaW5nLnBkZioqIC0gVGhpcyBpcyBhIGhlYXRtYXAgb2YgdGhlIGFtb3VudCBvZiBpbmRleCBzd2l0Y2hpbmcgcGVyIGluZGV4IHNldCBhbmQgZmxvd2NlbGwgdXNlZC4gT24gdGhlIGRpYWdvbmFsIG9mIHRoZSBwbG90IGlzIHRoZSBpbmRleGVzIGFwcGxpZWQgdG8gdGhlIHNhbXBsZXMsIHdoaWxlIHRoZSBvdGhlciBzcXVhcmVzIG9uIHRoZSBncmlkIGRpc3BsYXkgaW5zdGFuY2VzIHdoZXJlIGVpdGhlciB0aGUgaTUgb3IgaTcgaW5kZXggaGFzIHN3aXRjaGVkIGNhdXNpbmcgdGhpcyByZWFkIHRvIGVuZCB1cCBpbiB0aGUgdW5kZXRlcm1pbmVkIHJlYWRzIGZpbGUuIFRoZSB0ZXh0IGFib3ZlIHRoZSBwbG90IGxpc3RzIHRoZSB0b3RhbCByZWFkcyBkZW11bHRpcGxleCBmcm9tIHRoYXQgZmxvd2NlbGwsIHRoZSBzd2l0Y2ggcmF0ZSAob25seSBvbmUgb2YgdGhlIGluZGV4ZXMgc3dpdGNoaW5nIGNhdXNpbmcgdGhlIHJlYWQgdG8gZW5kIHVwIGluIHRoZSB1bmRldGVybWluZWQgcmVhZHMgZmlsZSkgYXMgYSBwZXJjZW50YWdlLCB0aGUgY3Jvc3MtY29udGFtaW5hdGlvbiByYXRlIChib3RoIGluZGV4ZXMgc3dpdGNoaW5nIHRoZSByZWFkIGVuZGluZyB1cCBpbiBhbm90aGVyIHNhbXBsZSkgYXMgYSBwZXJjZW50YWdlLCBhbmQgdGhlIG51bWJlciBvZiAib3RoZXIgcmVhZHMiIHdoaWNoIHdlcmUgdGhvc2Ugd2hlcmUgbm8gYXBwbGllZCBpbmRleGVzIHdlcmUgZGV0ZWN0ZWQuIFRoZSBjcm9zcy1jb250YW1pbmF0aW9uIHJhdGUgaXMgY2FsY3VsYXRlZCBhcyB0aGUgc3F1YXJlIG9mIHRoZSBpbmRleCBzd2l0Y2hpbmcgcmF0ZSBhcyBwZXIgKGNvc3RlbGxvIGV0IGFsKSwgYW5kIHNob3VsZCBiZSBhIHJvdWdoIGd1aWRlIHRvIGRldGVybWluZSBhbiBhcHByb3ByaWF0ZSBBU1YgbWluaW11bSBhYnVuZGFuY2UgdGhyZXNob2xkIGZvciBmaWx0ZXJpbmcuIE5PVEU6IFRoaXMgcGxvdCBpcyBvbmx5IGNyZWF0ZWQgd2hlbiB1bmlxdWUgZHVhbCBpbmRleGVzIHdlcmUgdXNlZCBvbiB0aGUgc2FtcGxlLg0KDQogICAgKyAqKm91dHB1dC9sb2dzL0ZDSUQvRkNJRF9wcmVmaWx0X3F1YWxwbG90cy5wZGYqKiAtIFRoaXMgbXVsdGlwbG90IHN1bW1hcmlzZXMgdGhlIHJlYWQgcXVhbGl0eSBzY29yZXMgZm9yIHRoZSBmb3J3YXJkIGFuZCByZXZlcnNlIHJlYWRzLCBwcmUgZmlsdGVyaW5nLiBUaGVzZSBwbG90cyBjYW4gc2VydmUgYXMgYW4gaW5kaWNhdG9yIGZvciBhZGp1c3RpbmcgcmVhZCBmaWx0ZXJpbmcgcGFyYW1ldGVycyBvZiB0aGUgcGlwZWxpbmUuIFRoZSB0b3AgdHdvIHBsb3RzIHN1bW1hcmlzZSB0aGUgbWVhbiBxdWFsaXR5IHNjb3JlIGJ5IHBvc2l0aW9uIGZvciB0aGUgZm9yd2FyZCBhbmQgcmV2ZXJzZSByZWFkcyByZXNwZWN0aXZlbHkuIEZvciBpbGx1bWluYSBkYXRhLCB0aGVzZSB3aWxsIHN0YXJ0IHRvIGRlY3JlYXNlIHRvd2FyZHMgdGhlIGVuZCBvZiB0aGUgcmVhZHMsIHBhcnRpY3VsYXJseSBmb3IgdGhlIHJldmVyc2UgcmVhZHMuIFRoZSB0d28gYm90dG9tIHBsb3RzIHNob3cgdGhlIGN1bXVsYXRpdmUgZXhwZWN0ZWQgZXJyb3JzIGFsb25nIHRoZSByZWFkcywgd2l0aCBkaWZmZXJlbnQgY29sb3VyZWQgZG90cyBmb3IgZGlmZmVyZW50IHF1YW50aWxlcyBvZiB0aGUgcmVhZCBkYXRhIChpLmUuIGxvd2VyIDEwJSB0byB1cHBlciA5MCUpLiBUaGUgcmVkIGxpbmVzIHNob3cgdGhlIHBvdGVudGlhbCBtYXggZXhwZWN0ZXIgZXJyb3IgY3V0b2Zmcywgd2l0aCBhbGwgcmVhZHMgYWJvdmUgdGhlIHNldCBtYXhpbXVtIGV4cGVjdGVkIGVycm9yIGZpbHRlciBiZWlnbiByZW1vdmVkIChwYXJhbSByZWFkX21heF9lZSkuIEZvciBleGFtcGxlLCBpZiB0aGUgbG93ZXIgMTAlIHF1YW50aWxlIG9mIHJlYWRzIGdvZXMgYWJvdmUgdGhlIHJlZCBsaW5lIGZvciBtYXhFRT0xLCB5b3Ugd291bGQgZXhwZWN0IDEwJSBvZiB0aGUgcmVhZHMgdG8gYmUgcmVtb3ZlZCBpZiByZWFkX21heF9lZSB3YXMgc2V0IHRvIDEuIEFzIG1vcmUgZXJyb3JzIGNvbW1vbmx5IG9jY3VyIGluIHRoZSBlbmRzIG9mIHRoZSByZWFkLCBpZiB0aGVyZSBpcyBzdWZmaWNpZW50IG92ZXJsYXAgYmV0d2VlbiB0aGUgcmVhZHMgdG8gY292ZXIgdGhlIGxlbmd0aCBvZiB0aGUgYW1wbGljb24sIHRoZSByZWFkcyBjb3VsZCBpbnN0ZWFkIGJlIHRydW5jYXRlZCB0byBzbWFsbGVyIGxlbmd0aHMgdG8gcmVkdWNlIHRoZSBhbW91bnQgb2YgcmVhZHMgdGhhdCBjcm9zcyB0aGlzIG1pbmltdW0gZXhwZWN0ZWQgZXJyb3IgZmlsdGVyIHdoaWNoIHdvdWxkIHJldGFpbiBtb3JlIGRhdGEuIE5vdGUgdGhhdCB3aGVuIHRydW5jYXRpbmcgcmVhZHMgeW91IHNob3VsZCBhaW0gdG8gaGF2ZSBhdCBsZWFzdCAyMGJwIG9mIG92ZXJsYXAgdG8gZmFjaWxpdGF0ZSBmb3J3YXJkIGFuZCByZXZlcnNlIHJlYWQgbWVyZ2luZy4gDQogICAgDQogICAgKyAqKm91dHB1dC9sb2dzL0ZDSUQvRkNJRF9wb3N0ZmlsdF9xdWFscGxvdHMucGRmKiogLSBUaGlzIG11bHRpcGxvdCBzdW1tYXJpc2VzIHRoZSByZWFkIHF1YWxpdHkgc2NvcmVzIGZvciB0aGUgZm9yd2FyZCBhbmQgcmV2ZXJzZSByZWFkcywgcHJlIGZpbHRlcmluZy4gVGhlc2UgcGxvdHMgbGlzdCB0aGUgc2FtZSBpbmZvcm1hdGlvbiBhcyB0aGUgcHJlLWZpbHRlcmluZyBxdWFsaXR5IHBsb3RzLCBhbmQgc2hvdWxkIGJlIGNoZWNrZWQgdG8gZW5zdXJlIHRoYXQgdGhlIGZpbHRlcmluZyBoYXMgYmVlbiBjb3JyZWN0bHkgYXBwbGllZC4gaS5lLiwgaWYgcmVhZHMgd2VyZSB0cnVuY2F0ZWQgb3IgdHJpbW1lZCBvbiB0aGUgbGVmdCBvciByaWdodCAocGFyYW1zIHJlYWRfdHJ1bmNfbGVuZ3RoLCByZWFkX3RyaW1fbGVmdCwgcmVhZF90cmltX3JpZ2h0KSB0aGV5IHNob3VsZCBiZSBzaG9ydGVyIHRoZW4gdGhlIHByZS1maWx0ZXIgcGxvdHMsIGFuZCBpZiBhIG1heGltdW0gZXhwZWN0ZWQgZXJyb3IgZmlsdGVyIChwYXJhbSByZWFkX21heF9lZSkgd2FzIGFwcGxpZWQsIG5vbmUgb2YgdGhlIEVFIHF1YW50aWxlcyBzaG91bGQgYmUgYWJvdmUgdGhlIGNvcnJlc3BvbmRpbmcgcmVkIGxpbmUNCg0KICAgICsgKipvdXRwdXQvbG9ncy9GQ0lEL0ZDSURfcGNycHJpbWVyc19lcnJvcm1vZGVsLnBkZioqIC0gVGhlcmUgaXMgYSBzZXBhcmF0ZSBQREYgZm9yIHRoZSBmb3J3YXJkIGFuZCByZXZlcnNlIGVycm9yIG1vZGVscyBmb3IgZWFjaCBwcmltZXIgc2V0IGFuZCBmbG93IGNlbGwuIEVhY2ggcGxvdCBzdW1tYXJpc2VzIHRoZSBlcnJvciBtb2RlbCB1c2VkIGZvciBkYWRhMiB0aGF0IHdhcyBpbmZlcnJlZCBmcm9tIHRoZSBkYXRhIGZvciB0aGUgcmVzcGVjdGl2ZSBmbG93IGNlbGwuIFRoZSBlcnJvciByYXRlcyBmb3IgZWFjaCBwb3NzaWJsZSB0cmFuc2l0aW9uIChB4oaSQywgQeKGkkcsIGV0YykgYXJlIHNob3duIGluIGVhY2ggc3VicGxvdC4gVGhlIGRvdC1wb2ludHMgYXJlIHRoZSBlcnJvciByYXRlcyBvYnNlcnZlZCBpbiB0aGUgZGF0YSBmb3IgZWFjaCBxdWFsaXR5IHNjb3JlLiBUaGUgYmxhY2sgbGluZSBzaG93cyB0aGUgZXN0aW1hdGVkIGVycm9yIHJhdGVzIGZyb20gdGhlIG1hY2hpbmUtbGVhcm5pbmcgYWxnb3JpdGhtLiBUaGUgcmVkIGxpbmUgc2hvd3MgdGhlIGVycm9yIHJhdGVzIHRoYXQgd291bGQgYmUgZXhwZWN0ZWQgaWYgdGhlIFEtc2NvcmVzIGFzc2lnbmVkIGJ5IHRoZSBzZXF1ZW5jZXIgd2VyZSBjb21wbGV0ZWx5IGFjY3VyYXRlLiBUaGlzIHBsb3QgY2FuIGJlIG1vcmUgc3ViamVjdGl2ZSB0byBpbnRlcnByZXQsIGJ1dCBnZW5lcmFsbHkgeW91IHdhbnQgdG8gc2VlIHRoZSBlc3RpbWF0ZWQgZXJyb3IgcmF0ZXMgKGJsYWNrIGxpbmUpIGRlY3JlYXNlIGFzIHRoZSBxdWFsaXR5IHNjb3JlICh4IGF4aXMpIGluY3JlYXNlcywgaW4gYSByZWxhdGl2ZWx5IGxpbmVhciBmYXNoaW9uLiBNaW5vciBodW1wcyBpbiB0aGUgYmxhY2sgbGluZSBhcmUgbm8gcHJvYmxlbSwgYnV0IGEgdmVyeSBqYWdnZWQgbGluZSBtYXkgaW5kaWNhdGUgdGhhdCB0aGUgZXJyb3IgbW9kZWwgZGlkIG5vdCBmaXQgY29ycmVjdGx5LiBOb3RlOiBmb3IgTmV4dFNlcSBhbmQgTm92YVNlcSBkYXRhLCB0aGUgYmlubmVkIHF1YWxpdHkgc2NvcmVzIHByb3ZpZGVkIGJ5IHRoZSBzZXF1ZW5jZXIgY2FuIGNhdXNlIGxhcmdlIGh1bXBzIG9yIGRpcHMgaW4gdGhlIGVycm9yIG1vZGVsIGZpdC4gVGhpcyBpcyBnZW5lcmFsbHkgbm90IGEgYmlnIHByb2JsZW0sIHNlZSBbdGhpcyBnaXRodWIgaXNzdWVdKGh0dHBzOi8vZ2l0aHViLmNvbS9iZW5qam5lYi9kYWRhMi9pc3N1ZXMvMTMwNykgZm9yIGEgZGVlcGVyIGRpc2N1c3Npb24gb24gZml0dGluZyBlcnJvciBtb2RlbHMgZm9yIGJpbm5lZCBxdWFsaXR5IHNjb3Jlcy4NCg0KKiAqKldob2xlIGRhdGFzZXQgcXVhbGl0eSBjaGVja3M6KioNCiAgICArICoqb3V0cHV0L2xvZ3MvQVNWX2NsZWFudXBfc3VtbWFyeS5wZGYqKiAtIFRoaXMgcGxvdCBsaXN0cyB0aGUgYWJ1bmRhbmNlLCBhbmQgbnVtYmVyIG9mIHVuaXF1ZSBzZXF1ZW5jZSB2YXJpYW5jZSBpbmZlcnJlZCBmcm9tIGRhZGEyLCB0aGVpciBsZW5ndGhzLCBhbmQgd2hldGhlciB0aGV5IHdlcmUgcmV0YWluZWQgb3IgZmlsdGVyZWQgb3V0IGR1cmluZyB0aGUgQVNWIGZpbHRlcmluZyBzdGVwLiBHZW5lcmFsbHkgeW91IHNob3VsZCBzZWUgYSBsb3Qgb2YgdW5pcXVlIHNlcXVlbmNlcyBmaWx0ZXJlZCBvdXQgaW4gdGhpcyBzdGVwLCBidXQgdGhlIG1ham9yaXR5IG9mIHRoZSBhYnVuZGFuY2Ugc2hvdWxkIHJlbWFpbi4gDQoNCiAgICArICoqb3V0cHV0L2xvZ3MvQVNWX2NsZWFudXBfc3VtbWFyeS5jc3YqKiAtIFRoaXMgdGFibGUgbGlzdHMgdGhlIGluZGl2aWR1YWwgc2VxdWVuY2UgdmFyaWFudHMsIHRoZWlyIGFidWRuYW5jZSwgbGVuZ3RoIGFuZCB3aGV0aGVyIHRoZXkgd2VyZSByZXRhaW5lZCBvciBmaWx0ZXJlZCBvdXQgZHVyaW5nIHRoZSBBU1YgZmlsdGVyaW5nIHN0ZXAuIFRoaXMgdGFibGUgaXMgdXNlZnVsIGZvciBkZWVwZXIgaW52ZXN0aWdhdGlvbiB0byBlbnN1cmUgdGhhdCByZWFsIHNlcXVlbmNlcyB3ZXJlIG5vdCByZW1vdmVkIGluIGFueSBvZiB0aGUgQVNWIGZpbHRlcmluZyBzdGVwcy4NCg0KICAgICsgKipvdXRwdXQvbG9ncy90YXhvbm9taWNfYXNzaWdubWVudF9zdW1tYXJ5LnBkZioqIC0gVGhpcyBwbG90IHN1bW1hcmlzZXMgdGhlIGdlbmV0aWMgZGlzdGFuY2Ugb2YgdGhlIEFTVnMgdG8gdGhlIHJlZmVyZW5jZSBkYXRhYmFzZSAoZnJvbSBCTEFTVCB0b3AgaGl0IGlkZW50aXR5KSwgYW5kIHdoYXQgdGF4b25vbXkgd2FzIGFzc2lnbmVkIHRvIGVhY2guIFRoaXMgcGxvdCBnaXZlcyBhIGdvb2Qgb3ZlcnZpZXcgb2YgaG93IHdlbGwgdGhlIGFuYWx5c2VkIHNlcXVlbmNlcyBhcmUgcmVwcmVzZW50ZWQgaW4gdGhlIHJlZmVyZW5jZSBkYXRhYmFzZSwgYW5kIGhvdyBzdWNjZXNzZnVsIHRoZSB0YXhvbm9taWMgYXNzaWdubWVudCB3YXMuICANCg0KICAgICsgKipvdXRwdXQvbG9ncy90YXhvbm9taWNfYXNzaWdubWVudF9zdW1tYXJ5LmNzdioqIC0gVGhpcyB0YWJsZSBsaXN0cyB0aGUgaW5kaXZpZHVhbCBzZXF1ZW5jZSB2YXJpYW50cyBhbmQgdGhlaXIgYXNzaWduZWQgdGF4b25vbXkgYW5kIGNvbmZpZGVuY2Ugc2NvcmVzIHdpdGggSURUQVhBLiBUaGUgY29sdW1ucyB0byB0aGUgcmlnaHQgYWxzbyBpbmRpY2F0ZSB0aGUgQkxBU1QgdG9wIGhpdCBhbmQgdGhlaXIgZGlzdGFuY2UgdG8gdGhlIGNsb3Nlc3QgYmxhc3QgaGl0LiBUaGlzIHRhYmxlIGlzIHVzZWZ1bCBmb3IgZGVlcGVyIGludmVzdGlnYXRpb24gb2YgaG93IGRpZmZlcmVudCBzZXF1ZW5jZXMgd2VyZSBhc3NpZ25lZC4NCg0KICAgICsgKipvdXRwdXQvbG9ncy9yZWFkX3RyYWNrZXIucGRmKiogVGhpcyBwbG90IHN1bW1hcmlzZXMgdGhlIG51bWJlciBvZiByZWFkcyByZXRhaW5lZCB0aHJvdWdoIGFsbCBzdGVwcyBvZiB0aGUgcGlwZWxpbmUsIGFzIHdlbGwgYXMgaG93IG1hbnkgcmVhZHMgd2VyZSBjbGFzc2lmaWVkIHRvIGRpZmZlcmVudCB0YXhvbm9taWMgcmFua3MuIFRoaXMgcGxvdCBwcm92aWRlcyBhIHVzZWZ1bCBvdmVydmlldyBvZiBhbGwgcGlwZWxpbmUgc3RlcHMgdG8gZGV0ZXJtaW5lIGlmIHRvbyBtYW55IHJlYWRzIGFyZSBiZWluZyBsb3N0IGF0IGEgY2VydGFpbiBzdGVwDQoNCiAgICArICoqb3V0cHV0L2xvZ3MvcmVhZF90cmFja2VyLmNzdioqIC0gU2ltaWxhciB0byB0aGUgYWJvdmUgcGxvdCwgdGhpcyB0YWJsZSBzdW1tYXJpc2VzIHRoZSBudW1iZXIgb2YgcmVhZHMgcmV0YWluZWQgdGhyb3VnaCBhbGwgc3RlcHMgb2YgdGhlIHBpcGVsaW5lLCBhcyB3ZWxsIGFzIGhvdyBtYW55IHJlYWRzIHdlcmUgY2xhc3NpZmllZCB0byBkaWZmZXJlbnQgdGF4b25vbWljIHJhbmtzLg0KDQogICAgKyAqKm91dHB1dC9sb2dzL2FjY3VtdWxhdGlvbl9jdXJ2ZS5wZGYqKiAtIFRoaXMgcGxvdCBzaG93cyB0aGUgYWNjdW11bGF0aW9uIG9mIEFTVnMgd2l0aGluIGVhY2ggc2FtcGxlIGFzIHNlcXVlbmNpbmcgZGVwdGggaW5jcmVhc2VzLiBUaGUgY3VydmVzIHNob3VsZCBzdGFydCB0byBwbGF0ZWF1IGlmIGFkZXF1YXRlIHNlcXVlbmNpbmcgZGVwdGggaGFzIGJlZW4gYWNoaWV2ZWQgdG8gY2hhcmFjdGVyaXNlIHRoZSBjb21tdW5pdHkuIElmIHRoZSBjdXJ2ZXMgaGF2ZSBub3QgcmVhY2hlZCBhIHBsYXRlYXUgaXQgbWF5IGluZGljYXRlIHRoYXQgdGhlc2Ugc2FtcGxlcyBzaG91bGQgYmUgc2VxdWVuY2VkIGFnYWluIHNvIHRoYXQgYWxsIHRheGEgYXJlIGNhcHR1cmVkIGluIHRoZSBkYXRhLg0KDQo=