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)

Obtain information for a particular experiment

We can now query what information is available for a particular experiment; in this case SRP045534. This should list the samples that are available and their respective identifiers.

sraInf <- getSRAinfo("SRP045534",sra_con, sraType="sra")
sraInf

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))

Extracting fastq files

Using the sra-toolkit command-line utility from NCBI we can generate the fastq files from these archive files. We can do this within a Terminal (i.e. not within RStudio) with the following, making sure your working directory contains the .sra files.

for sra in *.sra
do
fastq-dump $sra
done

After each fastq file has been extracted, you should see a message to report have many reads (spots) are contained in the file

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