1 Introduction

One way which might be useful to learn about how to use these computers is to do everything through a document like this. In this markdown document, I can interleave text and code; I am currently (of course) typing arbitrary text.

But I can just as easily try out commands

start=$(pwd)/preprocessing
cd $start
rsync -av /mnt/cifs/sequencer/SeqData/NextSeq1000/250729_VL00136_107_AAH7C2HM5/Analysis/1/Data/fastq/ .

I then dumped a list of all the files to my editor and removed everything in the filenames starting at _S[0-9]+* This resulted in the following string which I should be able to use in order to organize the samples into reasonable sub directories.

samplenames="5448_dciaR_pSin_DMSO_R2 5448_dciaR_pSin_DMSO_R3 5448_dciaR_pSin_DMSO_R5 5448_dciaR_pSin_Heme_R2_58 5448_dciaR_pSin_Heme_R3_59 5448_dciaR_pSin_Heme_R5_60 5448_pJRS525_DMSO_R2_46 5448_pJRS525_DMSO_R3_76 5448_pJRS525_DMSO_R5_48 5448_pJRS525_Heme_R2_54 5448_pJRS525_Heme_R3_55 5448_pJRS525_Heme_R5_56 CDM_glucose_manLMN_A_5 CDM_glucose_manLMN_B_6 CDM_glucose_manLMN_C_7 CDM_glucose_manLMN_D_8 CDM_glucose_manLMN_Rescue_A_9 CDM_glucose_manLMN_Rescue_B_10 CDM_glucose_manLMN_Rescue_C_11 CDM_glucose_manLMN_Rescue_D_12 CDM_glucose_WT_5448_A_1 CDM_glucose_WT_5448_B_2 CDM_glucose_WT_5448_C_3 CDM_glucose_WT_5448_D_4 CDM_glucose_WT_NZ131_A_33 CDM_glucose_WT_NZ131_B_34 CDM_glucose_WT_NZ131_C_35 CDM_glucose_WT_NZ131_D_36 CDM_mannose_manLMN_Rescue_A_29 CDM_mannose_manLMN_Rescue_B_30 CDM_mannose_manLMN_Rescue_C_13cycles_67 CDM_mannose_manLMN_Rescue_D_32 CDM_mannose_WT_NZ131_A_41 CDM_mannose_WT_NZ131_B_42 CDM_mannose_WT_NZ131_C_43 CDM_mannose_WT_NZ131_D_44 CDM_manose_WT_5448_A_13cycles_63 CDM_manose_WT_5448_B_13cycles_64 CDM_manose_WT_5448_C_13cycles_65 CDM_manose_WT_5448_D_13cycles_66 CDM_sucrose_manLMN_A_17 CDM_sucrose_manLMN_B_18 CDM_sucrose_manLMN_C_19 CDM_sucrose_manLMN_D_20 CDM_sucrose_manLMN_Rescue_A_21 CDM_sucrose_manLMN_Rescue_B_22 CDM_sucrose_manLMN_Rescue_C_23 CDM_sucrose_manLMN_Rescue_D_24 CDM_sucrose_WT_5448_A_13 CDM_sucrose_WT_5448_B_14 CDM_sucrose_WT_5448_C_13cycles_61 CDM_sucrose_WT_5448_D_13cycles_62 CDM_sucrose_WT_NZ131_A_37 CDM_sucrose_WT_NZ131_B_38 CDM_sucrose_WT_NZ131_C_39 CDM_sucrose_WT_NZ131_D_40 Undetermined"
for i in $samplenames; do
    echo $i
    mkdir $i
    mv ${i}_*.fastq.gz ${i}/
done

2 Invoke trimomatic

Maybe I should just move to using fastp all the time?

start=$(pwd)
for i in $(/bin/ls -d * ); do
    cd ${start}/${i}
    mkdir unprocessed
    mv ../$i*.fastq.gz unprocessed
    input=$(/bin/ls unprocessed/* | tr '\n' ':')
    cyoa --jprefix 01 --method trimom --input $input
done
cd $start

We previously did ls -l together, in this instance I added the ‘tr’ which orders the files by time (t) and in reverse order (r). Therefore the bottom lines are the newest files.

Note, McIver lab explicitly asked that we move to the following assemblies when aligning the data: NZ_CP140117.2 for 5448 and GCA_000018125.5 for NZ131.

Let us take a moment and see which assemblies I have on hand at the moment. It turns out that GCA_000018125 has been suppressed by NCBI because it is not deemed complete; but it remains the only NZ131 assembly available.

In addition, NZ_CP140117 is the accession for the chromosome associated with assembly ‘GCF_034434355.2’

cd ~/libraries/genome/downloads
cyoa --method dldataset --input GCA_000018125.1
cyoa --method dldataset --input GCF_034434355.2
mv *.gbff.gz ../genbank
mv *.fsa ../fasta
mv *.gff ../gff
cd ../genbank
gunzip *.gbff.gz
ln -s GCF_034434355.2.gbff spyogenes_nv1.gbff
ln -s GCA_000018125.1.gbff spyogenes_nz131.gbff
cd ../gff
ln -s GCF_034434355.2.gff spyogenes_nv1.gff
head -n 40 spyogenes_nv1.gff
ln -s GCA_000018125.1.gff spyogenes_nz131.gff
head -n 40 spyogenes_nz131.gff
cd ../fasta
ln -s GCF_034434355.2.fsa spyogenes_nv1.fasta
ln -s GCA_000018125.1.fsa spyogenes_nz131.fasta

Now that the two genomes of interest are in place and have easy-to-read synonyms, let us do the mapping… I am just going to map all samples against both genomes.

I printed the first 40 lines of the gff files, it looks like the most appropriate types/tags are gene and locus_tag for both.

But first, use my test directory to make sure the genomes have been indexed.

cd test
less ../Undetermined/unprocessed/Undetermined_S0_R1_001.fastq.gz | head -n 100000 > r1.fastq
less ../Undetermined/unprocessed/Undetermined_S0_R2_001.fastq.gz | head -n 100000 > r2.fastq
mkdir unprocessed
mv *.fastq unprocessed
input=$(/bin/ls unprocessed/* | tr '\n' ':')
cyoa --jprefix 01 --method trimom --input $input

sp1=spyogenes_nv1
sp2=spyogenes_nz131
input=$(/bin/ls outputs/01trimomatic/*-trimmed.fastq.xz | tr '\n' ':')
echo $input
cyoa --jprefix 02 --method hisat --input $input --species $sp1 \
     --gff_type gene --gff_tag locus_tag --introns 0
cyoa --jprefix 02 --method hisat --input $input --species $sp2 \
     --gff_type gene --gff_tag locus_tag --introns 0
## wait a minute or so
ls -l outputs/02*
sp1=spyogenes_nv1
sp2=spyogenes_nz131
cd /scratch/atb/rnaseq/spyogenes_mgas_2025/preprocessing
start=$(pwd)
for i in $(/bin/ls -d * | grep -v test); do
    cd ${start}/${i}
    input=$(/bin/ls outputs/01trimomatic/*-trimmed.fastq.xz | tr '\n' ':')
    cyoa --jprefix 02 --method hisat --input $input --species $sp1 \
         --gff_type gene --gff_tag locus_tag --introns 0
    cyoa --jprefix 02 --method hisat --input $input --species $sp2 \
         --gff_type gene --gff_tag locus_tag --introns 0
done
cd $start
pander::pander(sessionInfo())
message(paste0("This is hpgltools commit: ", get_git_commit()))
message(paste0("Saving to ", savefile))
tmp <- sm(saveme(filename = savefile))
tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiU3RyZXB0b2NvY2N1cyBweW9nZW5lcyA1NDQ4IGFuZCBOWjEzMSBjb21wYXJpc29ucy4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpiaWJsaW9ncmFwaHk6IC9ob21lL3RyZXkvc2NyYXRjaC96b3Rlcm9fbGlicmFyeS9hdGIuYmliCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogZmFsc2UKICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZSA9IEZBTFNFfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkoZ2x1ZSkKbGlicmFyeShocGdsdG9vbHMpCmxpYnJhcnkodGlkeXIpCgprbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcyA9IFRSVUUsIHZlcmJvc2UgPSBUUlVFLCB3aWR0aCA9IDkwLCBlY2hvID0gVFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVycm9yID0gVFJVRSwgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDgsIGZpZy5yZXRpbmEgPSAyLAogIG91dC53aWR0aCA9ICIxMDAlIiwgZGV2ID0gInBuZyIsCiAgZGV2LmFyZ3MgPSBsaXN0KHBuZyA9IGxpc3QodHlwZSA9ICJjYWlyby1wbmciKSkpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzID0gNCwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBrbml0ci5kdXBsaWNhdGUubGFiZWwgPSAiYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTIpKQp2ZXIgPC0gU3lzLmdldGVudigiVkVSU0lPTiIpCnJ1bmRhdGUgPC0gZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdCA9ICIlWSVtJWQiKQoKcm1kX2ZpbGUgPC0gIjAxZGF0YXNldHMuUm1kIgpzYXZlZmlsZSA8LSBnc3ViKHBhdHRlcm4gPSAiXFwuUm1kIiwgcmVwbGFjZSA9ICJcXC5yZGFcXC54eiIsIHggPSBybWRfZmlsZSkKbWV0aG9kcyA8LSBsaXN0KCJiYXNpYyIgPSBUUlVFLCAiZGVzZXEiID0gVFJVRSwgImRyZWFtIiA9IEZBTFNFLAogICAgICAgICAgICAgICAgImVic2VxIiA9IEZBTFNFLCAiZWRnZXIiID0gVFJVRSwgImxpbW1hIiA9IFRSVUUsICJub2lzZXEiID0gVFJVRSkKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoIm1ldGhvZHMiKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpPbmUgd2F5IHdoaWNoIG1pZ2h0IGJlIHVzZWZ1bCB0byBsZWFybiBhYm91dCBob3cgdG8gdXNlIHRoZXNlCmNvbXB1dGVycyBpcyB0byBkbyBldmVyeXRoaW5nIHRocm91Z2ggYSBkb2N1bWVudCBsaWtlIHRoaXMuICBJbiB0aGlzCm1hcmtkb3duIGRvY3VtZW50LCBJIGNhbiBpbnRlcmxlYXZlIHRleHQgYW5kIGNvZGU7IEkgYW0gY3VycmVudGx5IChvZgpjb3Vyc2UpIHR5cGluZyBhcmJpdHJhcnkgdGV4dC4KCgpCdXQgSSBjYW4ganVzdCBhcyBlYXNpbHkgdHJ5IG91dCBjb21tYW5kcwoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CnN0YXJ0PSQocHdkKS9wcmVwcm9jZXNzaW5nCmNkICRzdGFydApyc3luYyAtYXYgL21udC9jaWZzL3NlcXVlbmNlci9TZXFEYXRhL05leHRTZXExMDAwLzI1MDcyOV9WTDAwMTM2XzEwN19BQUg3QzJITTUvQW5hbHlzaXMvMS9EYXRhL2Zhc3RxLyAuCmBgYAoKSSB0aGVuIGR1bXBlZCBhIGxpc3Qgb2YgYWxsIHRoZSBmaWxlcyB0byBteSBlZGl0b3IgYW5kIHJlbW92ZWQKZXZlcnl0aGluZyBpbiB0aGUgZmlsZW5hbWVzIHN0YXJ0aW5nIGF0IF9TWzAtOV0rKiAgVGhpcyByZXN1bHRlZCBpbgp0aGUgZm9sbG93aW5nIHN0cmluZyB3aGljaCBJIHNob3VsZCBiZSBhYmxlIHRvIHVzZSBpbiBvcmRlciB0bwpvcmdhbml6ZSB0aGUgc2FtcGxlcyBpbnRvIHJlYXNvbmFibGUgc3ViIGRpcmVjdG9yaWVzLgoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CnNhbXBsZW5hbWVzPSI1NDQ4X2RjaWFSX3BTaW5fRE1TT19SMiA1NDQ4X2RjaWFSX3BTaW5fRE1TT19SMyA1NDQ4X2RjaWFSX3BTaW5fRE1TT19SNSA1NDQ4X2RjaWFSX3BTaW5fSGVtZV9SMl81OCA1NDQ4X2RjaWFSX3BTaW5fSGVtZV9SM181OSA1NDQ4X2RjaWFSX3BTaW5fSGVtZV9SNV82MCA1NDQ4X3BKUlM1MjVfRE1TT19SMl80NiA1NDQ4X3BKUlM1MjVfRE1TT19SM183NiA1NDQ4X3BKUlM1MjVfRE1TT19SNV80OCA1NDQ4X3BKUlM1MjVfSGVtZV9SMl81NCA1NDQ4X3BKUlM1MjVfSGVtZV9SM181NSA1NDQ4X3BKUlM1MjVfSGVtZV9SNV81NiBDRE1fZ2x1Y29zZV9tYW5MTU5fQV81IENETV9nbHVjb3NlX21hbkxNTl9CXzYgQ0RNX2dsdWNvc2VfbWFuTE1OX0NfNyBDRE1fZ2x1Y29zZV9tYW5MTU5fRF84IENETV9nbHVjb3NlX21hbkxNTl9SZXNjdWVfQV85IENETV9nbHVjb3NlX21hbkxNTl9SZXNjdWVfQl8xMCBDRE1fZ2x1Y29zZV9tYW5MTU5fUmVzY3VlX0NfMTEgQ0RNX2dsdWNvc2VfbWFuTE1OX1Jlc2N1ZV9EXzEyIENETV9nbHVjb3NlX1dUXzU0NDhfQV8xIENETV9nbHVjb3NlX1dUXzU0NDhfQl8yIENETV9nbHVjb3NlX1dUXzU0NDhfQ18zIENETV9nbHVjb3NlX1dUXzU0NDhfRF80IENETV9nbHVjb3NlX1dUX05aMTMxX0FfMzMgQ0RNX2dsdWNvc2VfV1RfTloxMzFfQl8zNCBDRE1fZ2x1Y29zZV9XVF9OWjEzMV9DXzM1IENETV9nbHVjb3NlX1dUX05aMTMxX0RfMzYgQ0RNX21hbm5vc2VfbWFuTE1OX1Jlc2N1ZV9BXzI5IENETV9tYW5ub3NlX21hbkxNTl9SZXNjdWVfQl8zMCBDRE1fbWFubm9zZV9tYW5MTU5fUmVzY3VlX0NfMTNjeWNsZXNfNjcgQ0RNX21hbm5vc2VfbWFuTE1OX1Jlc2N1ZV9EXzMyIENETV9tYW5ub3NlX1dUX05aMTMxX0FfNDEgQ0RNX21hbm5vc2VfV1RfTloxMzFfQl80MiBDRE1fbWFubm9zZV9XVF9OWjEzMV9DXzQzIENETV9tYW5ub3NlX1dUX05aMTMxX0RfNDQgQ0RNX21hbm9zZV9XVF81NDQ4X0FfMTNjeWNsZXNfNjMgQ0RNX21hbm9zZV9XVF81NDQ4X0JfMTNjeWNsZXNfNjQgQ0RNX21hbm9zZV9XVF81NDQ4X0NfMTNjeWNsZXNfNjUgQ0RNX21hbm9zZV9XVF81NDQ4X0RfMTNjeWNsZXNfNjYgQ0RNX3N1Y3Jvc2VfbWFuTE1OX0FfMTcgQ0RNX3N1Y3Jvc2VfbWFuTE1OX0JfMTggQ0RNX3N1Y3Jvc2VfbWFuTE1OX0NfMTkgQ0RNX3N1Y3Jvc2VfbWFuTE1OX0RfMjAgQ0RNX3N1Y3Jvc2VfbWFuTE1OX1Jlc2N1ZV9BXzIxIENETV9zdWNyb3NlX21hbkxNTl9SZXNjdWVfQl8yMiBDRE1fc3Vjcm9zZV9tYW5MTU5fUmVzY3VlX0NfMjMgQ0RNX3N1Y3Jvc2VfbWFuTE1OX1Jlc2N1ZV9EXzI0IENETV9zdWNyb3NlX1dUXzU0NDhfQV8xMyBDRE1fc3Vjcm9zZV9XVF81NDQ4X0JfMTQgQ0RNX3N1Y3Jvc2VfV1RfNTQ0OF9DXzEzY3ljbGVzXzYxIENETV9zdWNyb3NlX1dUXzU0NDhfRF8xM2N5Y2xlc182MiBDRE1fc3Vjcm9zZV9XVF9OWjEzMV9BXzM3IENETV9zdWNyb3NlX1dUX05aMTMxX0JfMzggQ0RNX3N1Y3Jvc2VfV1RfTloxMzFfQ18zOSBDRE1fc3Vjcm9zZV9XVF9OWjEzMV9EXzQwIFVuZGV0ZXJtaW5lZCIKZm9yIGkgaW4gJHNhbXBsZW5hbWVzOyBkbwogICAgZWNobyAkaQogICAgbWtkaXIgJGkKICAgIG12ICR7aX1fKi5mYXN0cS5neiAke2l9Lwpkb25lCmBgYAoKIyBJbnZva2UgdHJpbW9tYXRpYwoKTWF5YmUgSSBzaG91bGQganVzdCBtb3ZlIHRvIHVzaW5nIGZhc3RwIGFsbCB0aGUgdGltZT8KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzdGFydD0kKHB3ZCkKZm9yIGkgaW4gJCgvYmluL2xzIC1kICogKTsgZG8KICAgIGNkICR7c3RhcnR9LyR7aX0KICAgIG1rZGlyIHVucHJvY2Vzc2VkCiAgICBtdiAuLi8kaSouZmFzdHEuZ3ogdW5wcm9jZXNzZWQKICAgIGlucHV0PSQoL2Jpbi9scyB1bnByb2Nlc3NlZC8qIHwgdHIgJ1xuJyAnOicpCiAgICBjeW9hIC0tanByZWZpeCAwMSAtLW1ldGhvZCB0cmltb20gLS1pbnB1dCAkaW5wdXQKZG9uZQpjZCAkc3RhcnQKYGBgCgpXZSBwcmV2aW91c2x5IGRpZCBscyAtbCB0b2dldGhlciwgaW4gdGhpcyBpbnN0YW5jZSBJIGFkZGVkIHRoZSAndHInCndoaWNoIG9yZGVycyB0aGUgZmlsZXMgYnkgdGltZSAodCkgYW5kIGluIHJldmVyc2Ugb3JkZXIgKHIpLgpUaGVyZWZvcmUgdGhlIGJvdHRvbSBsaW5lcyBhcmUgdGhlIG5ld2VzdCBmaWxlcy4KCk5vdGUsIE1jSXZlciBsYWIgZXhwbGljaXRseSBhc2tlZCB0aGF0IHdlIG1vdmUgdG8gdGhlIGZvbGxvd2luZwphc3NlbWJsaWVzIHdoZW4gYWxpZ25pbmcgdGhlIGRhdGE6ICBOWl9DUDE0MDExNy4yIGZvciA1NDQ4IGFuZApHQ0FfMDAwMDE4MTI1LjUgZm9yIE5aMTMxLgoKTGV0IHVzIHRha2UgYSBtb21lbnQgYW5kIHNlZSB3aGljaCBhc3NlbWJsaWVzIEkgaGF2ZSBvbiBoYW5kIGF0IHRoZQptb21lbnQuICBJdCB0dXJucyBvdXQgdGhhdCBHQ0FfMDAwMDE4MTI1IGhhcyBiZWVuIHN1cHByZXNzZWQgYnkgTkNCSQpiZWNhdXNlIGl0IGlzIG5vdCBkZWVtZWQgY29tcGxldGU7IGJ1dCBpdCByZW1haW5zIHRoZSBvbmx5IE5aMTMxCmFzc2VtYmx5IGF2YWlsYWJsZS4KCkluIGFkZGl0aW9uLCBOWl9DUDE0MDExNyBpcyB0aGUgYWNjZXNzaW9uIGZvciB0aGUgY2hyb21vc29tZQphc3NvY2lhdGVkIHdpdGggYXNzZW1ibHkgJ0dDRl8wMzQ0MzQzNTUuMicKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCB+L2xpYnJhcmllcy9nZW5vbWUvZG93bmxvYWRzCmN5b2EgLS1tZXRob2QgZGxkYXRhc2V0IC0taW5wdXQgR0NBXzAwMDAxODEyNS4xCmN5b2EgLS1tZXRob2QgZGxkYXRhc2V0IC0taW5wdXQgR0NGXzAzNDQzNDM1NS4yCm12ICouZ2JmZi5neiAuLi9nZW5iYW5rCm12ICouZnNhIC4uL2Zhc3RhCm12ICouZ2ZmIC4uL2dmZgpjZCAuLi9nZW5iYW5rCmd1bnppcCAqLmdiZmYuZ3oKbG4gLXMgR0NGXzAzNDQzNDM1NS4yLmdiZmYgc3B5b2dlbmVzX252MS5nYmZmCmxuIC1zIEdDQV8wMDAwMTgxMjUuMS5nYmZmIHNweW9nZW5lc19uejEzMS5nYmZmCmNkIC4uL2dmZgpsbiAtcyBHQ0ZfMDM0NDM0MzU1LjIuZ2ZmIHNweW9nZW5lc19udjEuZ2ZmCmhlYWQgLW4gNDAgc3B5b2dlbmVzX252MS5nZmYKbG4gLXMgR0NBXzAwMDAxODEyNS4xLmdmZiBzcHlvZ2VuZXNfbnoxMzEuZ2ZmCmhlYWQgLW4gNDAgc3B5b2dlbmVzX256MTMxLmdmZgpjZCAuLi9mYXN0YQpsbiAtcyBHQ0ZfMDM0NDM0MzU1LjIuZnNhIHNweW9nZW5lc19udjEuZmFzdGEKbG4gLXMgR0NBXzAwMDAxODEyNS4xLmZzYSBzcHlvZ2VuZXNfbnoxMzEuZmFzdGEKYGBgCgpOb3cgdGhhdCB0aGUgdHdvIGdlbm9tZXMgb2YgaW50ZXJlc3QgYXJlIGluIHBsYWNlIGFuZCBoYXZlCmVhc3ktdG8tcmVhZCBzeW5vbnltcywgbGV0IHVzIGRvIHRoZSBtYXBwaW5nLi4uICBJIGFtIGp1c3QgZ29pbmcgdG8KbWFwIGFsbCBzYW1wbGVzIGFnYWluc3QgYm90aCBnZW5vbWVzLgoKSSBwcmludGVkIHRoZSBmaXJzdCA0MCBsaW5lcyBvZiB0aGUgZ2ZmIGZpbGVzLCBpdCBsb29rcyBsaWtlIHRoZSBtb3N0CmFwcHJvcHJpYXRlIHR5cGVzL3RhZ3MgYXJlIGdlbmUgYW5kIGxvY3VzX3RhZyBmb3IgYm90aC4KCkJ1dCBmaXJzdCwgdXNlIG15IHRlc3QgZGlyZWN0b3J5IHRvIG1ha2Ugc3VyZSB0aGUgZ2Vub21lcyBoYXZlIGJlZW4KaW5kZXhlZC4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCB0ZXN0Cmxlc3MgLi4vVW5kZXRlcm1pbmVkL3VucHJvY2Vzc2VkL1VuZGV0ZXJtaW5lZF9TMF9SMV8wMDEuZmFzdHEuZ3ogfCBoZWFkIC1uIDEwMDAwMCA+IHIxLmZhc3RxCmxlc3MgLi4vVW5kZXRlcm1pbmVkL3VucHJvY2Vzc2VkL1VuZGV0ZXJtaW5lZF9TMF9SMl8wMDEuZmFzdHEuZ3ogfCBoZWFkIC1uIDEwMDAwMCA+IHIyLmZhc3RxCm1rZGlyIHVucHJvY2Vzc2VkCm12ICouZmFzdHEgdW5wcm9jZXNzZWQKaW5wdXQ9JCgvYmluL2xzIHVucHJvY2Vzc2VkLyogfCB0ciAnXG4nICc6JykKY3lvYSAtLWpwcmVmaXggMDEgLS1tZXRob2QgdHJpbW9tIC0taW5wdXQgJGlucHV0CgpzcDE9c3B5b2dlbmVzX252MQpzcDI9c3B5b2dlbmVzX256MTMxCmlucHV0PSQoL2Jpbi9scyBvdXRwdXRzLzAxdHJpbW9tYXRpYy8qLXRyaW1tZWQuZmFzdHEueHogfCB0ciAnXG4nICc6JykKZWNobyAkaW5wdXQKY3lvYSAtLWpwcmVmaXggMDIgLS1tZXRob2QgaGlzYXQgLS1pbnB1dCAkaW5wdXQgLS1zcGVjaWVzICRzcDEgXAogICAgIC0tZ2ZmX3R5cGUgZ2VuZSAtLWdmZl90YWcgbG9jdXNfdGFnIC0taW50cm9ucyAwCmN5b2EgLS1qcHJlZml4IDAyIC0tbWV0aG9kIGhpc2F0IC0taW5wdXQgJGlucHV0IC0tc3BlY2llcyAkc3AyIFwKICAgICAtLWdmZl90eXBlIGdlbmUgLS1nZmZfdGFnIGxvY3VzX3RhZyAtLWludHJvbnMgMAojIyB3YWl0IGEgbWludXRlIG9yIHNvCmxzIC1sIG91dHB1dHMvMDIqCmBgYAoKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzcDE9c3B5b2dlbmVzX252MQpzcDI9c3B5b2dlbmVzX256MTMxCmNkIC9zY3JhdGNoL2F0Yi9ybmFzZXEvc3B5b2dlbmVzX21nYXNfMjAyNS9wcmVwcm9jZXNzaW5nCnN0YXJ0PSQocHdkKQpmb3IgaSBpbiAkKC9iaW4vbHMgLWQgKiB8IGdyZXAgLXYgdGVzdCk7IGRvCiAgICBjZCAke3N0YXJ0fS8ke2l9CiAgICBpbnB1dD0kKC9iaW4vbHMgb3V0cHV0cy8wMXRyaW1vbWF0aWMvKi10cmltbWVkLmZhc3RxLnh6IHwgdHIgJ1xuJyAnOicpCiAgICBjeW9hIC0tanByZWZpeCAwMiAtLW1ldGhvZCBoaXNhdCAtLWlucHV0ICRpbnB1dCAtLXNwZWNpZXMgJHNwMSBcCiAgICAgICAgIC0tZ2ZmX3R5cGUgZ2VuZSAtLWdmZl90YWcgbG9jdXNfdGFnIC0taW50cm9ucyAwCiAgICBjeW9hIC0tanByZWZpeCAwMiAtLW1ldGhvZCBoaXNhdCAtLWlucHV0ICRpbnB1dCAtLXNwZWNpZXMgJHNwMiBcCiAgICAgICAgIC0tZ2ZmX3R5cGUgZ2VuZSAtLWdmZl90YWcgbG9jdXNfdGFnIC0taW50cm9ucyAwCmRvbmUKY2QgJHN0YXJ0CmBgYAoKCmBgYHtyIHNhdmVtZSwgZXZhbD1GQUxTRX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCm1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgc2F2ZWZpbGUpKQp0bXAgPC0gc20oc2F2ZW1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpKQpgYGAKCmBgYHtyIGxvYWRtZV9hZnRlciwgZXZhbD1GQUxTRX0KdG1wIDwtIGxvYWRtZShmaWxlbmFtZSA9IHNhdmVmaWxlKQpgYGAK