Set up a database of SRA runs
Raw reads from NGS experiments tend to be distributed through the Short Read Archive (SRA). The SRAdb
Bioconductor package can be used to query and download files that are hosted in SRA. More information can be found in the package vignette.
vignette("SRAdb")
Firstly, we need to download a database file. This is a large file and could take some time (25.82 )Gb.
library(SRAdb)
sqlfile <-'SRAmetadb.sqlite'
if(!file.exists('SRAmetadb.sqlite')) sqlfile <<- getSRAdbFile()
sra_con <- dbConnect(SQLite(),sqlfile)
Download the set of sra files
We can now directly download each sra
file. The sra
file is SRA’s own archive format, but we can extract the raw reads in the more common .fastq
format in the next step.
Here, sapply
is a convenient way of repeating the same operation for a vector of arguments. In this case we want to run the getSRAfile
function with different file names.
sapply(sraInf$run, function(x) try(getSRAfile(x,sra_con, fileType="sra"),silent=TRUE))
Quality assessment of reads
The fastqc is recommened for a preliminary assessment of the read quality. However, caution should be exercised when interpreting the results as the reports are not specifically-tailored for RNA-seq. Some sections are know to flag-up warning or error messages for perfectly fine RNA-seq experiments.
We can run this at the command line:-
for fq in *.fastq
do
fastqc $fq
done
Downloading the reference genome
To align to the mm10
genome, we will first download the reference genome from UCSC. We have to download each individual chromosome separately, and then join together into a single file.
wget --timestamping 'ftp://hgdownload.cse.ucsc.edu/goldenPath/mm10/bigZips/chromFa.tar.gz' -O chromFa.tar.gz
gunzip chromFa.tar.gz
tar xvf chromFa.tar
cat *.fa > mm10.fa
rm chr*.fa
rm chromFa.tar.gz
Alignment using bowtie
Firstly, we need to build an index file from the reference genome that we have downloaded:-
bowtie2-build mm10.fa mm10
In practice, we would probably run the alignment of each sample in parallel using the high-performance cluster. However, for illustration purposes, we give the script that will align each sample individually.
bowtie2 -x mm10 -U SRR1552444.fastq -S SRR1552444.sam
samtools view -bS SRR1552444.sam > SRR1552444.bam
samtools sort SRR1552444.bam -o SRR1552444.sorted.bam
samtools index SRR1552444.sorted.bam
bowtie2 -x mm10 -U SRR1552445.fastq -S SRR1552445.sam
samtools view -bS SRR1552445.sam > SRR1552445.bam
samtools sort SRR1552445.bam -o SRR1552445.sorted.bam
samtools index SRR1552445.sorted.bam
bowtie2 -x mm10 -U SRR1552446.fastq -S SRR1552446.sam
samtools view -bS SRR1552446.sam > SRR1552446.bam
samtools sort SRR1552446.bam -o SRR1552446.sorted.bam
samtools index SRR1552446.sorted.bam
bowtie2 -x mm10 -U SRR1552447.fastq -S SRR1552447.sam
samtools view -bS SRR1552447.sam > SRR1552447.bam
samtools sort SRR1552447.bam -o SRR1552447.sorted.bam
samtools index SRR1552447.sorted.bam
bowtie2 -x mm10 -U SRR1552448.fastq -S SRR1552448.sam
samtools view -bS SRR1552448.sam > SRR1552448.bam
samtools sort SRR1552448.bam -o SRR1552448.sorted.bam
samtools index SRR1552448.sorted.bam
bowtie2 -x mm10 -U SRR1552449.fastq -S SRR1552449.sam
samtools view -bS SRR1552449.sam > SRR1552449.bam
samtools sort SRR1552449.bam -o SRR1552449.sorted.bam
samtools index SRR1552449.sorted.bam
bowtie2 -x mm10 -U SRR1552450.fastq -S SRR1552450.sam
samtools view -bS SRR1552450.sam > SRR1552450.bam
samtools sort SRR1552450.bam -o SRR1552450.sorted.bam
samtools index SRR1552450.sorted.bam
bowtie2 -x mm10 -U SRR1552451.fastq -S SRR1552451.sam
samtools view -bS SRR1552451.sam > SRR1552451.bam
samtools sort SRR1552451.bam -o SRR1552451.sorted.bam
samtools index SRR1552451.sorted.bam
bowtie2 -x mm10 -U SRR1552452.fastq -S SRR1552452.sam
samtools view -bS SRR1552452.sam > SRR1552452.bam
samtools sort SRR1552452.bam -o SRR1552452.sorted.bam
samtools index SRR1552452.sorted.bam
bowtie2 -x mm10 -U SRR1552453.fastq -S SRR1552453.sam
samtools view -bS SRR1552453.sam > SRR1552453.bam
samtools sort SRR1552453.bam -o SRR1552453.sorted.bam
samtools index SRR1552453.sorted.bam
bowtie2 -x mm10 -U SRR1552454.fastq -S SRR1552454.sam
samtools view -bS SRR1552454.sam SRR1552454.bam
samtools sort SRR1552454.bam -o SRR1552454.sorted.bam
samtools index SRR1552454.sorted.bam
bowtie2 -x mm10 -U SRR1552455.fastq -S SRR1552455.sam
samtools view -bS SRR1552455.sam > SRR1552455.bam
samtools sort SRR1552455.bam -o SRR1552455.sorted.bam
samtools index SRR1552455.sorted.bam
Renaming to be consistent with GEO
The files we have just created are named according to their SRA identifier. However, these names are not very useful for analysis. The Gene Expression Omnibus (GEO) entry for the dataset has the mapping information between SRA and sample identifers.
library(GEOquery)
tmp <- getGEO("GSE60450")
gseInf <- pData(tmp[[1]])
gseInf
We obtain a new name for each bam file by joining the metadata from SRA and GEO.
library(dplyr)
sraInf <- mutate(sraInf, bam=paste0(run, ".sorted.bam"))
gseInf <- mutate(gseInf, experiment = basename(as.character(supplementary_file_2)),
newbam = gsub("Sample name: ","", description),
newbam = gsub("-",".",newbam,fixed=TRUE),
newbam = paste0(newbam, ".bam"))
gseInf
combinedInf <- left_join(gseInf, sraInf, by="experiment")
combinedInf %>% select(description,description.1,experiment,bam,newbam)
combinedInf
The base R function file.symblink
can be used to create symbolic links from one file to another; thus retaining the original file name and avoid creating a complete copy of each file. Such links are often used in NGS data when we don’t want to create copies of files that are potentially rather large. With this approach, when we want to access MCL1.LA.bam
(for example), the file system will know to actually access SRR1552444.sorted.bam
.
for(i in seq_along(combinedInf$bam)){
file.symlink(combinedInf$bam[i], combinedInf$newbam[i])
file.symlink(paste0(combinedInf$bam[i],".bai"), paste0(combinedInf$newbam[i],".bai"))
}
list.files()
Alignment using Rsubread
Alignment could also be performed using Rsubread
as we did in the first practical session. The only difference is to use the entire mm10
genome and point to the newly-downloaded fastq files.
library(Rsubread)
buildindex("mm10",reference="mm10.fa")
fastqfiles <- list.files(pattern=".fastq")
align("mm10",readfile1=fastqfiles)
LS0tCnRpdGxlOiAiUk5BLXNlcSBhbmFseXNpcyBpbiBSIgphdXRob3I6ICJTdGVwaGFuZSBCYWxsZXJlYXUsIE1hcmsgRHVubmluZywgT3NjYXIgUnVlZGEsIEFzaGxleSBTYXdsZSIKZGF0ZTogJ2ByIGZvcm1hdChTeXMudGltZSgpLCAiTGFzdCBtb2RpZmllZDogJWQgJWIgJVkiKWAnCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwpsYXlvdXQ6IHBhZ2UKc3VidGl0bGU6IE9idGFpbmluZyBhbmQgYWxpZ25pbmcgUk5BLXNlcSByZWFkcyBmcm9tIHB1YmxpYyByZXBvc2l0b3JpZXMKYmlibGlvZ3JhcGh5OiByZWYuYmliCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSxldmFsPUZBTFNFKQpgYGAKCiMjIFNldCB1cCBhIGRhdGFiYXNlIG9mIFNSQSBydW5zCgpSYXcgcmVhZHMgZnJvbSBOR1MgZXhwZXJpbWVudHMgdGVuZCB0byBiZSBkaXN0cmlidXRlZCB0aHJvdWdoIHRoZSBTaG9ydCBSZWFkIEFyY2hpdmUgKFNSQSkuIFRoZSBgU1JBZGJgIEJpb2NvbmR1Y3RvciBwYWNrYWdlIGNhbiBiZSB1c2VkIHRvIHF1ZXJ5IGFuZCBkb3dubG9hZCBmaWxlcyB0aGF0IGFyZSBob3N0ZWQgaW4gU1JBLiBNb3JlIGluZm9ybWF0aW9uIGNhbiBiZSBmb3VuZCBpbiB0aGUgW3BhY2thZ2UgdmlnbmV0dGVdKGh0dHA6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy92aWduZXR0ZXMvU1JBZGIvaW5zdC9kb2MvU1JBZGIucGRmKS4gCgpgYGB7ciBldmFsPUZBTFNFfQp2aWduZXR0ZSgiU1JBZGIiKQpgYGAKCgpGaXJzdGx5LCB3ZSBuZWVkIHRvIGRvd25sb2FkIGEgZGF0YWJhc2UgZmlsZS4gVGhpcyBpcyBhIGxhcmdlIGZpbGUgYW5kIGNvdWxkIHRha2Ugc29tZSB0aW1lIChgciByb3VuZChmaWxlLnNpemUoIlNSQW1ldGFkYi5zcWxpdGUiKS8xMDAwMDAwMDAwLDIpYCApR2IuCgpgYGB7cn0KbGlicmFyeShTUkFkYikKc3FsZmlsZSA8LSdTUkFtZXRhZGIuc3FsaXRlJwppZighZmlsZS5leGlzdHMoJ1NSQW1ldGFkYi5zcWxpdGUnKSkgc3FsZmlsZSA8PC0gZ2V0U1JBZGJGaWxlKCkKc3JhX2NvbiA8LSBkYkNvbm5lY3QoU1FMaXRlKCksc3FsZmlsZSkKYGBgCgojIyBPYnRhaW4gaW5mb3JtYXRpb24gZm9yIGEgcGFydGljdWxhciBleHBlcmltZW50CgpXZSBjYW4gbm93IHF1ZXJ5IHdoYXQgaW5mb3JtYXRpb24gaXMgYXZhaWxhYmxlIGZvciBhIHBhcnRpY3VsYXIgZXhwZXJpbWVudDsgaW4gdGhpcyBjYXNlIGBTUlAwNDU1MzRgLiBUaGlzIHNob3VsZCBsaXN0IHRoZSBzYW1wbGVzIHRoYXQgYXJlIGF2YWlsYWJsZSBhbmQgdGhlaXIgcmVzcGVjdGl2ZSBpZGVudGlmaWVycy4KCmBgYHtyfQpzcmFJbmYgPC0gZ2V0U1JBaW5mbygiU1JQMDQ1NTM0IixzcmFfY29uLCBzcmFUeXBlPSJzcmEiKQpzcmFJbmYKYGBgCgojIyBEb3dubG9hZCB0aGUgc2V0IG9mIHNyYSBmaWxlcwoKV2UgY2FuIG5vdyBkaXJlY3RseSBkb3dubG9hZCBlYWNoIGBzcmFgIGZpbGUuIFRoZSBgc3JhYCBmaWxlIGlzIFNSQSdzIG93biBhcmNoaXZlIGZvcm1hdCwgYnV0IHdlIGNhbiBleHRyYWN0IHRoZSByYXcgcmVhZHMgaW4gdGhlIG1vcmUgY29tbW9uIGAuZmFzdHFgIGZvcm1hdCBpbiB0aGUgbmV4dCBzdGVwLgoKSGVyZSwgYHNhcHBseWAgaXMgYSBjb252ZW5pZW50IHdheSBvZiByZXBlYXRpbmcgdGhlIHNhbWUgb3BlcmF0aW9uIGZvciBhIHZlY3RvciBvZiBhcmd1bWVudHMuIEluIHRoaXMgY2FzZSB3ZSB3YW50IHRvIHJ1biB0aGUgYGdldFNSQWZpbGVgIGZ1bmN0aW9uIHdpdGggZGlmZmVyZW50IGZpbGUgbmFtZXMuIAoKYGBge3J9CnNhcHBseShzcmFJbmYkcnVuLCBmdW5jdGlvbih4KSB0cnkoZ2V0U1JBZmlsZSh4LHNyYV9jb24sIGZpbGVUeXBlPSJzcmEiKSxzaWxlbnQ9VFJVRSkpCmBgYAoKIyMgRXh0cmFjdGluZyBmYXN0cSBmaWxlcwoKVXNpbmcgdGhlIFtzcmEtdG9vbGtpdF0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9zcmEpIGNvbW1hbmQtbGluZSB1dGlsaXR5IGZyb20gTkNCSSB3ZSBjYW4gZ2VuZXJhdGUgdGhlIGBmYXN0cWAgZmlsZXMgZnJvbSB0aGVzZSBhcmNoaXZlIGZpbGVzLiBXZSBjYW4gZG8gdGhpcyB3aXRoaW4gYSBUZXJtaW5hbCAoaS5lLiBub3Qgd2l0aGluIFJTdHVkaW8pIHdpdGggdGhlIGZvbGxvd2luZywgbWFraW5nIHN1cmUgeW91ciB3b3JraW5nIGRpcmVjdG9yeSBjb250YWlucyB0aGUgYC5zcmFgIGZpbGVzLgoKYGBge2Jhc2h9CmZvciBzcmEgaW4gKi5zcmEKZG8KZmFzdHEtZHVtcCAkc3JhCmRvbmUKCmBgYAoKQWZ0ZXIgZWFjaCBmYXN0cSBmaWxlIGhhcyBiZWVuIGV4dHJhY3RlZCwgeW91IHNob3VsZCBzZWUgYSBtZXNzYWdlIHRvIHJlcG9ydCBoYXZlIG1hbnkgcmVhZHMgKHNwb3RzKSBhcmUgY29udGFpbmVkIGluIHRoZSBmaWxlCgoKIyMgUXVhbGl0eSBhc3Nlc3NtZW50IG9mIHJlYWRzCgpUaGUgW2Zhc3RxY10oaHR0cDovL3d3dy5iaW9pbmZvcm1hdGljcy5iYWJyYWhhbS5hYy51ay9wcm9qZWN0cy9mYXN0cWMvKSBpcyByZWNvbW1lbmVkIGZvciBhIHByZWxpbWluYXJ5IGFzc2Vzc21lbnQgb2YgdGhlIHJlYWQgcXVhbGl0eS4gSG93ZXZlciwgY2F1dGlvbiBzaG91bGQgYmUgZXhlcmNpc2VkIHdoZW4gaW50ZXJwcmV0aW5nIHRoZSByZXN1bHRzIGFzIHRoZSByZXBvcnRzIGFyZSBub3Qgc3BlY2lmaWNhbGx5LXRhaWxvcmVkIGZvciBSTkEtc2VxLiBTb21lIHNlY3Rpb25zIGFyZSBrbm93IHRvIGZsYWctdXAgd2FybmluZyBvciBlcnJvciBtZXNzYWdlcyBmb3IgcGVyZmVjdGx5IGZpbmUgUk5BLXNlcSBleHBlcmltZW50cy4KCldlIGNhbiBydW4gdGhpcyBhdCB0aGUgY29tbWFuZCBsaW5lOi0KCmBgYHtiYXNoIGNhY2hlPVRSVUUsZXZhbD1GQUxTRX0KZm9yIGZxIGluICouZmFzdHEKZG8KZmFzdHFjICRmcQpkb25lCgpgYGAKCiMjIERvd25sb2FkaW5nIHRoZSByZWZlcmVuY2UgZ2Vub21lCgpUbyBhbGlnbiB0byB0aGUgYG1tMTBgIGdlbm9tZSwgd2Ugd2lsbCBmaXJzdCBkb3dubG9hZCB0aGUgcmVmZXJlbmNlIGdlbm9tZSBmcm9tIFVDU0MuIFdlIGhhdmUgdG8gZG93bmxvYWQgZWFjaCBpbmRpdmlkdWFsIGNocm9tb3NvbWUgc2VwYXJhdGVseSwgYW5kIHRoZW4gam9pbiB0b2dldGhlciBpbnRvIGEgc2luZ2xlIGZpbGUuIAoKYGBge2Jhc2ggZXZhbD1GQUxTRX0Kd2dldCAtLXRpbWVzdGFtcGluZyAnZnRwOi8vaGdkb3dubG9hZC5jc2UudWNzYy5lZHUvZ29sZGVuUGF0aC9tbTEwL2JpZ1ppcHMvY2hyb21GYS50YXIuZ3onIC1PIGNocm9tRmEudGFyLmd6Cmd1bnppcCBjaHJvbUZhLnRhci5negp0YXIgeHZmIGNocm9tRmEudGFyCmNhdCAqLmZhID4gbW0xMC5mYQpybSBjaHIqLmZhCnJtIGNocm9tRmEudGFyLmd6CmBgYAoKIyMgQWxpZ25tZW50IHVzaW5nIGJvd3RpZQoKRmlyc3RseSwgd2UgbmVlZCB0byBidWlsZCBhbiAqaW5kZXgqIGZpbGUgZnJvbSB0aGUgcmVmZXJlbmNlIGdlbm9tZSB0aGF0IHdlIGhhdmUgZG93bmxvYWRlZDotCgpgYGB7YmFzaCBldmFsPUZBTFNFfQpib3d0aWUyLWJ1aWxkIG1tMTAuZmEgbW0xMApgYGAKCkluIHByYWN0aWNlLCB3ZSB3b3VsZCBwcm9iYWJseSBydW4gdGhlIGFsaWdubWVudCBvZiBlYWNoIHNhbXBsZSBpbiAqcGFyYWxsZWwqIHVzaW5nIHRoZSBoaWdoLXBlcmZvcm1hbmNlIGNsdXN0ZXIuIEhvd2V2ZXIsIGZvciBpbGx1c3RyYXRpb24gcHVycG9zZXMsIHdlIGdpdmUgdGhlIHNjcmlwdCB0aGF0IHdpbGwgYWxpZ24gZWFjaCBzYW1wbGUgaW5kaXZpZHVhbGx5LgoKYGBge2Jhc2ggZXZhbD1GQUxTRX0KYm93dGllMiAteCBtbTEwIC1VIFNSUjE1NTI0NDQuZmFzdHEgLVMgU1JSMTU1MjQ0NC5zYW0Kc2FtdG9vbHMgdmlldyAtYlMgU1JSMTU1MjQ0NC5zYW0gPiBTUlIxNTUyNDQ0LmJhbQpzYW10b29scyBzb3J0IFNSUjE1NTI0NDQuYmFtIC1vIFNSUjE1NTI0NDQuc29ydGVkLmJhbQpzYW10b29scyBpbmRleCBTUlIxNTUyNDQ0LnNvcnRlZC5iYW0KCmJvd3RpZTIgLXggbW0xMCAtVSBTUlIxNTUyNDQ1LmZhc3RxIC1TIFNSUjE1NTI0NDUuc2FtCnNhbXRvb2xzIHZpZXcgLWJTIFNSUjE1NTI0NDUuc2FtID4gU1JSMTU1MjQ0NS5iYW0Kc2FtdG9vbHMgc29ydCBTUlIxNTUyNDQ1LmJhbSAtbyBTUlIxNTUyNDQ1LnNvcnRlZC5iYW0Kc2FtdG9vbHMgaW5kZXggU1JSMTU1MjQ0NS5zb3J0ZWQuYmFtCgpib3d0aWUyIC14IG1tMTAgLVUgU1JSMTU1MjQ0Ni5mYXN0cSAtUyBTUlIxNTUyNDQ2LnNhbQpzYW10b29scyB2aWV3IC1iUyBTUlIxNTUyNDQ2LnNhbSA+IFNSUjE1NTI0NDYuYmFtCnNhbXRvb2xzIHNvcnQgU1JSMTU1MjQ0Ni5iYW0gLW8gU1JSMTU1MjQ0Ni5zb3J0ZWQuYmFtCnNhbXRvb2xzIGluZGV4IFNSUjE1NTI0NDYuc29ydGVkLmJhbQoKYm93dGllMiAteCBtbTEwIC1VIFNSUjE1NTI0NDcuZmFzdHEgLVMgU1JSMTU1MjQ0Ny5zYW0Kc2FtdG9vbHMgdmlldyAtYlMgU1JSMTU1MjQ0Ny5zYW0gPiBTUlIxNTUyNDQ3LmJhbQpzYW10b29scyBzb3J0IFNSUjE1NTI0NDcuYmFtIC1vIFNSUjE1NTI0NDcuc29ydGVkLmJhbQpzYW10b29scyBpbmRleCBTUlIxNTUyNDQ3LnNvcnRlZC5iYW0KCmJvd3RpZTIgLXggbW0xMCAtVSBTUlIxNTUyNDQ4LmZhc3RxIC1TIFNSUjE1NTI0NDguc2FtCnNhbXRvb2xzIHZpZXcgLWJTIFNSUjE1NTI0NDguc2FtID4gU1JSMTU1MjQ0OC5iYW0Kc2FtdG9vbHMgc29ydCBTUlIxNTUyNDQ4LmJhbSAtbyBTUlIxNTUyNDQ4LnNvcnRlZC5iYW0Kc2FtdG9vbHMgaW5kZXggU1JSMTU1MjQ0OC5zb3J0ZWQuYmFtCgpib3d0aWUyIC14IG1tMTAgLVUgU1JSMTU1MjQ0OS5mYXN0cSAtUyBTUlIxNTUyNDQ5LnNhbQpzYW10b29scyB2aWV3IC1iUyBTUlIxNTUyNDQ5LnNhbSA+IFNSUjE1NTI0NDkuYmFtCnNhbXRvb2xzIHNvcnQgU1JSMTU1MjQ0OS5iYW0gLW8gU1JSMTU1MjQ0OS5zb3J0ZWQuYmFtCnNhbXRvb2xzIGluZGV4IFNSUjE1NTI0NDkuc29ydGVkLmJhbQoKYm93dGllMiAteCBtbTEwIC1VIFNSUjE1NTI0NTAuZmFzdHEgLVMgU1JSMTU1MjQ1MC5zYW0Kc2FtdG9vbHMgdmlldyAtYlMgU1JSMTU1MjQ1MC5zYW0gPiBTUlIxNTUyNDUwLmJhbQpzYW10b29scyBzb3J0IFNSUjE1NTI0NTAuYmFtIC1vIFNSUjE1NTI0NTAuc29ydGVkLmJhbQpzYW10b29scyBpbmRleCBTUlIxNTUyNDUwLnNvcnRlZC5iYW0KCmJvd3RpZTIgLXggbW0xMCAtVSBTUlIxNTUyNDUxLmZhc3RxIC1TIFNSUjE1NTI0NTEuc2FtCnNhbXRvb2xzIHZpZXcgLWJTIFNSUjE1NTI0NTEuc2FtID4gU1JSMTU1MjQ1MS5iYW0Kc2FtdG9vbHMgc29ydCBTUlIxNTUyNDUxLmJhbSAtbyBTUlIxNTUyNDUxLnNvcnRlZC5iYW0Kc2FtdG9vbHMgaW5kZXggU1JSMTU1MjQ1MS5zb3J0ZWQuYmFtCgpib3d0aWUyIC14IG1tMTAgLVUgU1JSMTU1MjQ1Mi5mYXN0cSAtUyBTUlIxNTUyNDUyLnNhbQpzYW10b29scyB2aWV3IC1iUyBTUlIxNTUyNDUyLnNhbSA+IFNSUjE1NTI0NTIuYmFtCnNhbXRvb2xzIHNvcnQgU1JSMTU1MjQ1Mi5iYW0gLW8gU1JSMTU1MjQ1Mi5zb3J0ZWQuYmFtCnNhbXRvb2xzIGluZGV4IFNSUjE1NTI0NTIuc29ydGVkLmJhbQoKYm93dGllMiAteCBtbTEwIC1VIFNSUjE1NTI0NTMuZmFzdHEgLVMgU1JSMTU1MjQ1My5zYW0Kc2FtdG9vbHMgdmlldyAtYlMgU1JSMTU1MjQ1My5zYW0gPiBTUlIxNTUyNDUzLmJhbQpzYW10b29scyBzb3J0IFNSUjE1NTI0NTMuYmFtIC1vIFNSUjE1NTI0NTMuc29ydGVkLmJhbQpzYW10b29scyBpbmRleCBTUlIxNTUyNDUzLnNvcnRlZC5iYW0KCmJvd3RpZTIgLXggbW0xMCAtVSBTUlIxNTUyNDU0LmZhc3RxIC1TIFNSUjE1NTI0NTQuc2FtCnNhbXRvb2xzIHZpZXcgLWJTIFNSUjE1NTI0NTQuc2FtIFNSUjE1NTI0NTQuYmFtCnNhbXRvb2xzIHNvcnQgU1JSMTU1MjQ1NC5iYW0gLW8gU1JSMTU1MjQ1NC5zb3J0ZWQuYmFtCnNhbXRvb2xzIGluZGV4IFNSUjE1NTI0NTQuc29ydGVkLmJhbQoKYm93dGllMiAteCBtbTEwIC1VIFNSUjE1NTI0NTUuZmFzdHEgLVMgU1JSMTU1MjQ1NS5zYW0Kc2FtdG9vbHMgdmlldyAtYlMgU1JSMTU1MjQ1NS5zYW0gPiBTUlIxNTUyNDU1LmJhbQpzYW10b29scyBzb3J0IFNSUjE1NTI0NTUuYmFtIC1vIFNSUjE1NTI0NTUuc29ydGVkLmJhbQpzYW10b29scyBpbmRleCBTUlIxNTUyNDU1LnNvcnRlZC5iYW0KYGBgCgojIyBSZW5hbWluZyB0byBiZSBjb25zaXN0ZW50IHdpdGggR0VPCgpUaGUgZmlsZXMgd2UgaGF2ZSBqdXN0IGNyZWF0ZWQgYXJlIG5hbWVkIGFjY29yZGluZyB0byB0aGVpciBTUkEgaWRlbnRpZmllci4gSG93ZXZlciwgdGhlc2UgbmFtZXMgYXJlIG5vdCB2ZXJ5IHVzZWZ1bCBmb3IgYW5hbHlzaXMuIFRoZSBHZW5lIEV4cHJlc3Npb24gT21uaWJ1cyAoR0VPKSBlbnRyeSBmb3IgdGhlIGRhdGFzZXQgaGFzIHRoZSBtYXBwaW5nIGluZm9ybWF0aW9uIGJldHdlZW4gU1JBIGFuZCBzYW1wbGUgaWRlbnRpZmVycy4KCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoR0VPcXVlcnkpCnRtcCA8LSBnZXRHRU8oIkdTRTYwNDUwIikKZ3NlSW5mIDwtIHBEYXRhKHRtcFtbMV1dKQpnc2VJbmYKCmBgYAoKV2Ugb2J0YWluIGEgbmV3IG5hbWUgZm9yIGVhY2ggYmFtIGZpbGUgYnkgam9pbmluZyB0aGUgbWV0YWRhdGEgZnJvbSBTUkEgYW5kIEdFTy4KYGBge3J9CgpsaWJyYXJ5KGRwbHlyKQpzcmFJbmYgPC0gbXV0YXRlKHNyYUluZiwgYmFtPXBhc3RlMChydW4sICIuc29ydGVkLmJhbSIpKQoKZ3NlSW5mIDwtIG11dGF0ZShnc2VJbmYsIGV4cGVyaW1lbnQgPSBiYXNlbmFtZShhcy5jaGFyYWN0ZXIoc3VwcGxlbWVudGFyeV9maWxlXzIpKSwKICAgICAgICAgICAgICAgICBuZXdiYW0gPSBnc3ViKCJTYW1wbGUgbmFtZTogIiwiIiwgZGVzY3JpcHRpb24pLAogICAgICAgICAgICAgICAgIG5ld2JhbSA9IGdzdWIoIi0iLCIuIixuZXdiYW0sZml4ZWQ9VFJVRSksCiAgICAgICAgICAgICAgICAgbmV3YmFtID0gcGFzdGUwKG5ld2JhbSwgIi5iYW0iKSkKZ3NlSW5mCmNvbWJpbmVkSW5mIDwtIGxlZnRfam9pbihnc2VJbmYsIHNyYUluZiwgYnk9ImV4cGVyaW1lbnQiKQpjb21iaW5lZEluZiAlPiUgc2VsZWN0KGRlc2NyaXB0aW9uLGRlc2NyaXB0aW9uLjEsZXhwZXJpbWVudCxiYW0sbmV3YmFtKQpjb21iaW5lZEluZgpgYGAKClRoZSBiYXNlIFIgZnVuY3Rpb24gYGZpbGUuc3ltYmxpbmtgIGNhbiBiZSB1c2VkIHRvIGNyZWF0ZSAqc3ltYm9saWMgbGlua3MqIGZyb20gb25lIGZpbGUgdG8gYW5vdGhlcjsgdGh1cyByZXRhaW5pbmcgdGhlIG9yaWdpbmFsIGZpbGUgbmFtZSBhbmQgYXZvaWQgY3JlYXRpbmcgYSBjb21wbGV0ZSBjb3B5IG9mIGVhY2ggZmlsZS4gU3VjaCBsaW5rcyBhcmUgb2Z0ZW4gdXNlZCBpbiBOR1MgZGF0YSB3aGVuIHdlIGRvbid0IHdhbnQgdG8gY3JlYXRlIGNvcGllcyBvZiBmaWxlcyB0aGF0IGFyZSBwb3RlbnRpYWxseSByYXRoZXIgbGFyZ2UuIFdpdGggdGhpcyBhcHByb2FjaCwgd2hlbiB3ZSB3YW50IHRvIGFjY2VzcyBgTUNMMS5MQS5iYW1gIChmb3IgZXhhbXBsZSksIHRoZSBmaWxlIHN5c3RlbSB3aWxsIGtub3cgdG8gYWN0dWFsbHkgYWNjZXNzIGBTUlIxNTUyNDQ0LnNvcnRlZC5iYW1gLgoKYGBge3J9CmZvcihpIGluIHNlcV9hbG9uZyhjb21iaW5lZEluZiRiYW0pKXsKICAKICBmaWxlLnN5bWxpbmsoY29tYmluZWRJbmYkYmFtW2ldLCBjb21iaW5lZEluZiRuZXdiYW1baV0pCiAgZmlsZS5zeW1saW5rKHBhc3RlMChjb21iaW5lZEluZiRiYW1baV0sIi5iYWkiKSwgcGFzdGUwKGNvbWJpbmVkSW5mJG5ld2JhbVtpXSwiLmJhaSIpKQogIAp9Cmxpc3QuZmlsZXMoKQpgYGAKCgojIyBBbGlnbm1lbnQgdXNpbmcgUnN1YnJlYWQKCkFsaWdubWVudCBjb3VsZCBhbHNvIGJlIHBlcmZvcm1lZCB1c2luZyBgUnN1YnJlYWRgIGFzIHdlIGRpZCBpbiB0aGUgZmlyc3QgcHJhY3RpY2FsIHNlc3Npb24uIFRoZSBvbmx5IGRpZmZlcmVuY2UgaXMgdG8gdXNlIHRoZSBlbnRpcmUgYG1tMTBgIGdlbm9tZSBhbmQgcG9pbnQgdG8gdGhlIG5ld2x5LWRvd25sb2FkZWQgZmFzdHEgZmlsZXMuCmBgYHtyIGV2YWw9RkFMU0V9CmxpYnJhcnkoUnN1YnJlYWQpCmJ1aWxkaW5kZXgoIm1tMTAiLHJlZmVyZW5jZT0ibW0xMC5mYSIpCmZhc3RxZmlsZXMgPC0gbGlzdC5maWxlcyhwYXR0ZXJuPSIuZmFzdHEiKQphbGlnbigibW0xMCIscmVhZGZpbGUxPWZhc3RxZmlsZXMpCmBgYAoK