1 Calculating error rates.

I wrote the function ‘create_matrices()’ to collect mutation counts. At least in theory the results from it should be able to address most/any question regarding the counts of mutations observed in the data.

## Loading errRt
## Loading required package: dplyr
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:hpgltools':
## 
##     combine
## The following object is masked from 'package:Biobase':
## 
##     combine
## The following objects are masked from 'package:BiocGenerics':
## 
##     combine, intersect, setdiff, union
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
## Loading required package: tidyr
## Starting sample: 1.
## Reading the file containing mutations: preprocessing/s1/step4.txt.xz
## Reading the file containing the identical reads: preprocessing/s1/step2_identical_reads.txt.xz
## Removing any differences before position: 24.
## Before pruning, there are: 1156535 reads.
## After position pruning, there are: 1037310 reads.
## Removing any reads with 'N' as the hit.
## Before N pruning, there are: 1037310 reads.
## After N pruning, there are: 1021066 reads.
## Gathering information about the indexes observed, this is slow.
## Before read pruning, there are: 1742743 indexes.
## After read pruning, there are: 838158 indexes.
## Removing indexes with fewer than 3 indexes.
## Before index pruning, there are: 1021066 changed reads.
## Before index pruning, there are: 4681501 identical reads.
## After index pruning, there are: 532571 changed reads.
## After index pruning, there are: 3663814 identical reads.
## Gathering identical, mutant, and sequencer reads/indexes.
## Counting by direction.
## Counting by string.
## Subsetting based on mutations with at least 3 indexes.
## Counting by reference position.
## Counting by identity string.
## Counting by reference nucleotide.
## Counting by product nucleotide.
## Counting by mutation type.
## Counting by transitions/transversion.
## Counting strong/weak.
## Counting insertions by position.
## Counting insertions by nucleotide
## Counting deletions by position.
## Counting deletions by nucleotide.
## Starting sample: 2.
## Reading the file containing mutations: preprocessing/s2/step4.txt.xz
## Reading the file containing the identical reads: preprocessing/s2/step2_identical_reads.txt.xz
## Removing any differences before position: 24.
## Before pruning, there are: 3421203 reads.
## After position pruning, there are: 1758479 reads.
## Removing any reads with 'N' as the hit.
## Before N pruning, there are: 1758479 reads.
## After N pruning, there are: 1732605 reads.
## Gathering information about the indexes observed, this is slow.
## Before read pruning, there are: 1263563 indexes.
## After read pruning, there are: 694479 indexes.
## Removing indexes with fewer than 3 indexes.
## Before index pruning, there are: 1732605 changed reads.
## Before index pruning, there are: 5230976 identical reads.
## After index pruning, there are: 874781 changed reads.
## After index pruning, there are: 4834367 identical reads.
## Gathering identical, mutant, and sequencer reads/indexes.
## Counting by direction.
## Counting by string.
## Subsetting based on mutations with at least 3 indexes.
## Counting by reference position.
## Counting by identity string.
## Counting by reference nucleotide.
## Counting by product nucleotide.
## Counting by mutation type.
## Counting by transitions/transversion.
## Counting strong/weak.
## Counting insertions by position.
## Counting insertions by nucleotide
## Counting deletions by position.
## Counting deletions by nucleotide.
## Starting sample: 3.
## Reading the file containing mutations: preprocessing/s3/step4.txt.xz
## Reading the file containing the identical reads: preprocessing/s3/step2_identical_reads.txt.xz
## Removing any differences before position: 24.
## Before pruning, there are: 4309681 reads.
## After position pruning, there are: 1564155 reads.
## Removing any reads with 'N' as the hit.
## Before N pruning, there are: 1564155 reads.
## After N pruning, there are: 1532016 reads.
## Gathering information about the indexes observed, this is slow.
## Before read pruning, there are: 887982 indexes.
## After read pruning, there are: 465046 indexes.
## Removing indexes with fewer than 3 indexes.
## Before index pruning, there are: 1532016 changed reads.
## Before index pruning, there are: 3583390 identical reads.
## After index pruning, there are: 783358 changed reads.
## After index pruning, there are: 3332425 identical reads.
## Gathering identical, mutant, and sequencer reads/indexes.
## Counting by direction.
## Counting by string.
## Subsetting based on mutations with at least 3 indexes.
## Counting by reference position.
## Counting by identity string.
## Counting by reference nucleotide.
## Counting by product nucleotide.
## Counting by mutation type.
## Counting by transitions/transversion.
## Counting strong/weak.
## Counting insertions by position.
## Counting insertions by nucleotide
## Counting deletions by position.
## Counting deletions by nucleotide.
## Working on miss_reads_by_position.
## Working on miss_indexes_by_position.
## Working on miss_sequencer_by_position.
## Working on miss_reads_by_string.
## Warning in order(as.numeric(rownames(matrices[[t]]))): NAs introduced by
## coercion
## Working on miss_indexes_by_string.
## Warning in order(as.numeric(rownames(matrices[[t]]))): NAs introduced by
## coercion
## Working on miss_sequencer_by_string.
## Warning in order(as.numeric(rownames(matrices[[t]]))): NAs introduced by
## coercion
## Working on miss_reads_by_ref_nt.
## Working on miss_indexes_by_ref_nt.
## Working on miss_sequencer_by_ref_nt.
## Working on miss_reads_by_hit_nt.
## Working on miss_indexes_by_hit_nt.
## Working on miss_sequencer_by_hit_nt.
## Working on miss_reads_by_type.
## Working on miss_indexes_by_type.
## Working on miss_sequencer_by_type.
## Working on miss_reads_by_trans.
## Working on miss_indexes_by_trans.
## Working on miss_sequencer_by_trans.
## Working on miss_reads_by_strength.
## Working on miss_indexes_by_strength.
## Working on miss_sequencer_by_strength.
## Working on insert_reads_by_position.
## Working on insert_indexes_by_position.
## Working on insert_sequencer_by_position.
## Working on insert_reads_by_nt.
## Working on insert_indexes_by_nt.
## Working on insert_sequencer_by_nt.
## Working on delete_reads_by_position.
## Working on delete_indexes_by_position.
## Working on delete_sequencer_by_position.
## Working on delete_reads_by_nt.
## Working on delete_indexes_by_nt.
## Working on delete_sequencer_by_nt.
## Skipping table: delete_reads_by_position
## Skipping table: delete_indexes_by_position
## Skipping table: delete_sequencer_by_position
## Skipping table: delete_reads_by_nt
## Skipping table: delete_indexes_by_nt
## Skipping table: delete_sequencer_by_nt
##                      Length Class  Mode   
## samples               3     -none- list   
## reads_per_sample      3     -none- numeric
## indexes_per_sample    3     -none- numeric
## matrices             33     -none- list   
## matrices_by_counts   33     -none- list   
## normalized           33     -none- list   
## normalized_by_counts 33     -none- list
## Starting sample: 1.
## Reading the file containing mutations: preprocessing/s1/step4.txt.xz
## Reading the file containing the identical reads: preprocessing/s1/step2_identical_reads.txt.xz
## Removing any differences before position: 24.
## Before pruning, there are: 1156535 reads.
## After position pruning, there are: 1037310 reads.
## Removing any reads with 'N' as the hit.
## Before N pruning, there are: 1037310 reads.
## After N pruning, there are: 1021066 reads.
## Gathering information about the indexes observed, this is slow.
## Before read pruning, there are: 1742743 indexes.
## After read pruning, there are: 838158 indexes.
## Removing indexes with fewer than 5 indexes.
## Before index pruning, there are: 1021066 changed reads.
## Before index pruning, there are: 4681501 identical reads.
## After index pruning, there are: 532571 changed reads.
## After index pruning, there are: 3663814 identical reads.
## Gathering identical, mutant, and sequencer reads/indexes.
## Counting by direction.
## Counting by string.
## Subsetting based on mutations with at least 5 indexes.
## Counting by reference position.
## Counting by identity string.
## Counting by reference nucleotide.
## Counting by product nucleotide.
## Counting by mutation type.
## Counting by transitions/transversion.
## Counting strong/weak.
## Counting insertions by position.
## Counting insertions by nucleotide
## Counting deletions by position.
## Counting deletions by nucleotide.
## Starting sample: 2.
## Reading the file containing mutations: preprocessing/s2/step4.txt.xz
## Reading the file containing the identical reads: preprocessing/s2/step2_identical_reads.txt.xz
## Removing any differences before position: 24.
## Before pruning, there are: 3421203 reads.
## After position pruning, there are: 1758479 reads.
## Removing any reads with 'N' as the hit.
## Before N pruning, there are: 1758479 reads.
## After N pruning, there are: 1732605 reads.
## Gathering information about the indexes observed, this is slow.
## Before read pruning, there are: 1263563 indexes.
## After read pruning, there are: 694479 indexes.
## Removing indexes with fewer than 5 indexes.
## Before index pruning, there are: 1732605 changed reads.
## Before index pruning, there are: 5230976 identical reads.
## After index pruning, there are: 874781 changed reads.
## After index pruning, there are: 4834367 identical reads.
## Gathering identical, mutant, and sequencer reads/indexes.
## Counting by direction.
## Counting by string.
## Subsetting based on mutations with at least 5 indexes.
## Counting by reference position.
## Counting by identity string.
## Counting by reference nucleotide.
## Counting by product nucleotide.
## Counting by mutation type.
## Counting by transitions/transversion.
## Counting strong/weak.
## Counting insertions by position.
## Counting insertions by nucleotide
## Counting deletions by position.
## Counting deletions by nucleotide.
## Starting sample: 3.
## Reading the file containing mutations: preprocessing/s3/step4.txt.xz
## Reading the file containing the identical reads: preprocessing/s3/step2_identical_reads.txt.xz
## Removing any differences before position: 24.
## Before pruning, there are: 4309681 reads.
## After position pruning, there are: 1564155 reads.
## Removing any reads with 'N' as the hit.
## Before N pruning, there are: 1564155 reads.
## After N pruning, there are: 1532016 reads.
## Gathering information about the indexes observed, this is slow.
## Before read pruning, there are: 887982 indexes.
## After read pruning, there are: 465046 indexes.
## Removing indexes with fewer than 5 indexes.
## Before index pruning, there are: 1532016 changed reads.
## Before index pruning, there are: 3583390 identical reads.
## After index pruning, there are: 783358 changed reads.
## After index pruning, there are: 3332425 identical reads.
## Gathering identical, mutant, and sequencer reads/indexes.
## Counting by direction.
## Counting by string.
## Subsetting based on mutations with at least 5 indexes.
## Counting by reference position.
## Counting by identity string.
## Counting by reference nucleotide.
## Counting by product nucleotide.
## Counting by mutation type.
## Counting by transitions/transversion.
## Counting strong/weak.
## Counting insertions by position.
## Counting insertions by nucleotide
## Counting deletions by position.
## Counting deletions by nucleotide.
## Working on miss_reads_by_position.
## Working on miss_indexes_by_position.
## Working on miss_sequencer_by_position.
## Working on miss_reads_by_string.
## Warning in order(as.numeric(rownames(matrices[[t]]))): NAs introduced by
## coercion
## Working on miss_indexes_by_string.
## Warning in order(as.numeric(rownames(matrices[[t]]))): NAs introduced by
## coercion
## Working on miss_sequencer_by_string.
## Warning in order(as.numeric(rownames(matrices[[t]]))): NAs introduced by
## coercion
## Working on miss_reads_by_ref_nt.
## Working on miss_indexes_by_ref_nt.
## Working on miss_sequencer_by_ref_nt.
## Working on miss_reads_by_hit_nt.
## Working on miss_indexes_by_hit_nt.
## Working on miss_sequencer_by_hit_nt.
## Working on miss_reads_by_type.
## Working on miss_indexes_by_type.
## Working on miss_sequencer_by_type.
## Working on miss_reads_by_trans.
## Working on miss_indexes_by_trans.
## Working on miss_sequencer_by_trans.
## Working on miss_reads_by_strength.
## Working on miss_indexes_by_strength.
## Working on miss_sequencer_by_strength.
## Working on insert_reads_by_position.
## Working on insert_indexes_by_position.
## Working on insert_sequencer_by_position.
## Working on insert_reads_by_nt.
## Working on insert_indexes_by_nt.
## Working on insert_sequencer_by_nt.
## Working on delete_reads_by_position.
## Working on delete_indexes_by_position.
## Working on delete_sequencer_by_position.
## Working on delete_reads_by_nt.
## Working on delete_indexes_by_nt.
## Working on delete_sequencer_by_nt.
## Skipping table: delete_reads_by_position
## Skipping table: delete_indexes_by_position
## Skipping table: delete_sequencer_by_position
## Skipping table: delete_reads_by_nt
## Skipping table: delete_indexes_by_nt
## Skipping table: delete_sequencer_by_nt
##                      Length Class  Mode   
## samples               3     -none- list   
## reads_per_sample      3     -none- numeric
## indexes_per_sample    3     -none- numeric
## matrices             33     -none- list   
## matrices_by_counts   33     -none- list   
## normalized           33     -none- list   
## normalized_by_counts 33     -none- list

2 Questions from Dr. DeStefano

I think what is best is to get the number of recovered mutations of each type from each data set. That would be A to T, A to G, A to C; T to A, T to G, T to C; G to A, G to C, G to T; and C to A, C to G, C to T; as well as deletions and insertions. I would then need the sum number of the reads that met all our criteria (i.e. at least 3 good recovered reads for that 14 nt index). Each set of 3 or more would ct as “1” read of that particular index so I would need the total with this in mind. I also need to know the total number of nucleotides that were in the region we decided to consider in the analysis. We may want to try this for 3 or more and 5 or more recovered indexes if it is not hard. This information does not include specific positions on the template where errors occurred but we can look at that latter. Right now I just want to get a general error rate and type of error. It would basically be calculated by dividing the number of recovered mutations of a particular type by sum number of the reads times the number of nucleotides screened in the template. As it ends up, this number does not really have a lot of meaning but it can be used to calculate the overall mutation rate as well as the rate for transversions, transitions, and deletions and insertions.

3 Answers

In order to address those queries, I invoked create_matrices() with a minimum index count of 3 and 5. It should be noted that this is not the same as requiring 3 or 5 reads per index. In both cases I require 3 reads per index.

3.1 Recovered mutations of each type

I am interpreting this question as the number of indexes recovered for each mutation type. I collect this information in 2 ways of interest: the indexes by type which are deemed to be from the RT and from the sequencer. In addition, I calculate a normalized (cpm) version of this information which may be used to look for changes across samples.

3.1.1 Mutations by RT index

This following block should print out tables of the numbers of mutant indexes observed for each type for the RT and the sequencer. One would hope that the sequencer will be consistent for all samples, but I think the results will instead suggest that my metric is not yet stringent enough.

s1 s2 s3
A_C 1294 4516 9418
A_G 728 14896 53401
A_T 235 2243 5053
C_A 9305 29486 34851
C_G 342 3848 10038
C_T 2133 18061 61965
G_A 1685 30686 37225
G_C 283 1683 3087
G_T 9630 12295 15293
T_A 222 5119 8532
T_C 854 4466 9521
T_G 1195 5972 11188
s1 s2 s3
A_C 2381 18295 15010
A_G 659 7440 5942
A_T 224 3157 2592
C_A 1278 15254 11862
C_G 601 6072 4442
C_T 732 7343 5703
G_A 555 5215 4268
G_C 476 6334 5631
G_T 997 8701 7109
T_A 453 4280 3403
T_C 997 10482 8692
T_G 2471 27537 22137
s1 s2 s3
A_C 1281 4516 9418
A_G 708 14896 53401
A_T 215 2243 5053
C_A 9305 29486 34851
C_G 318 3844 10038
C_T 2129 18061 61965
G_A 1677 30686 37225
G_C 255 1679 3087
G_T 9627 12295 15293
T_A 198 5119 8532
T_C 842 4466 9521
T_G 1195 5969 11188
s1 s2 s3
A_C 2374 18295 15010
A_G 651 7440 5942
A_T 202 3157 2592
C_A 1254 15254 11862
C_G 591 6072 4442
C_T 713 7343 5703
G_A 545 5215 4268
G_C 445 6334 5631
G_T 977 8701 7109
T_A 424 4280 3403
T_C 990 10482 8692
T_G 2458 27537 22137

Plots of this information

This suggests to me that this information needs to be normalized in some more sensible fashion. Thus the following:

3.1.2 Mutations by RT index, post normalization

The same numbers may be expressed in the context of the number of indexes observed / sample and/or as a cpm across samples. Thus in the first instance one can look at the apparent error rate for each sample, and in the second instance one may look for relative changes in apparent error rate across samples.

3.1.2.1 Rewriting the matrices as cpm to account for library sizes.

s1 s2 s3
A_C 46370 33886 36283
A_G 26088 111772 205727
A_T 8421 16830 19467
C_A 333441 221248 134263
C_G 12255 28873 38671
C_T 76435 135521 238720
G_A 60381 230253 143409
G_C 10141 12628 11893
G_T 345087 92256 58916
T_A 7955 38410 32869
T_C 30603 33511 36680
T_G 42822 44811 43102
s1 s2 s3
A_C 201370 152319 155076
A_G 55734 61943 61390
A_T 18945 26284 26779
C_A 108085 127000 122553
C_G 50829 50554 45893
C_T 61908 61136 58921
G_A 46938 43419 44095
G_C 40257 52735 58177
G_T 84320 72442 73447
T_A 38312 35634 35158
T_C 84320 87270 89802
T_G 208982 229265 228709
s1 s2 s3
A_C 46162 33889 36283
A_G 25514 111781 205727
A_T 7748 16832 19467
C_A 335315 221267 134263
C_G 11459 28846 38671
C_T 76721 135532 238720
G_A 60432 230272 143409
G_C 9189 12599 11893
G_T 346919 92263 58916
T_A 7135 38414 32869
T_C 30342 33513 36680
T_G 43063 44792 43102
s1 s2 s3
A_C 204233 152319 155076
A_G 56005 61943 61390
A_T 17378 26284 26779
C_A 107880 127000 122553
C_G 50843 50554 45893
C_T 61339 61136 58921
G_A 46886 43419 44095
G_C 38283 52735 58177
G_T 84050 72442 73447
T_A 36476 35634 35158
T_C 85169 87270 89802
T_G 211459 229265 228709

3.1.2.2 Rewriting the matrices by dividing by all indexes

This I think starts to address the later text in your query.

s1 s2 s3
A_C 0.0015 0.0054 0.0112
A_G 0.0010 0.0214 0.0769
A_T 0.0005 0.0048 0.0109
C_A 0.0111 0.0352 0.0416
C_G 0.0005 0.0055 0.0145
C_T 0.0046 0.0388 0.1332
G_A 0.0020 0.0366 0.0444
G_C 0.0004 0.0024 0.0044
G_T 0.0207 0.0264 0.0329
T_A 0.0003 0.0061 0.0102
T_C 0.0012 0.0064 0.0137
T_G 0.0026 0.0128 0.0241
s1 s2 s3
A_C 0.0028 0.0218 0.0179
A_G 0.0009 0.0107 0.0086
A_T 0.0005 0.0068 0.0056
C_A 0.0015 0.0182 0.0142
C_G 0.0009 0.0087 0.0064
C_T 0.0016 0.0158 0.0123
G_A 0.0007 0.0062 0.0051
G_C 0.0007 0.0091 0.0081
G_T 0.0021 0.0187 0.0153
T_A 0.0005 0.0051 0.0041
T_C 0.0014 0.0151 0.0125
T_G 0.0053 0.0592 0.0476
s1 s2 s3
A_C 0.0015 0.0054 0.0112
A_G 0.0010 0.0214 0.0769
A_T 0.0005 0.0048 0.0109
C_A 0.0111 0.0352 0.0416
C_G 0.0005 0.0055 0.0145
C_T 0.0046 0.0388 0.1332
G_A 0.0020 0.0366 0.0444
G_C 0.0004 0.0024 0.0044
G_T 0.0207 0.0264 0.0329
T_A 0.0002 0.0061 0.0102
T_C 0.0012 0.0064 0.0137
T_G 0.0026 0.0128 0.0241
s1 s2 s3
A_C 0.0028 0.0218 0.0179
A_G 0.0009 0.0107 0.0086
A_T 0.0004 0.0068 0.0056
C_A 0.0015 0.0182 0.0142
C_G 0.0009 0.0087 0.0064
C_T 0.0015 0.0158 0.0123
G_A 0.0007 0.0062 0.0051
G_C 0.0006 0.0091 0.0081
G_T 0.0021 0.0187 0.0153
T_A 0.0005 0.0051 0.0041
T_C 0.0014 0.0151 0.0125
T_G 0.0053 0.0592 0.0476

3.1.2.3 Rewriting the matrices by dividing by all indexes and cpm

I think this might prove to be where we get the most meaningful results.

The nicest thing in it is that after accounting for library sizes and total indexes observed, we finally see that the sequencer error is mostly consistent across all samples and mutation types – with a couple of notable exceptions.

By the same token, for the mutations which are identical for the sequencer, we have some which are decidedly different for the non-sequencer data. The most notable examples I think are A to G but _not G to A; and C to T.

s1 s2 s3
A_C 0.0553 0.0404 0.0433
A_G 0.0376 0.1609 0.2962
A_T 0.0181 0.0362 0.0419
C_A 0.3978 0.2640 0.1602
C_G 0.0176 0.0416 0.0557
C_T 0.1644 0.2914 0.5133
G_A 0.0720 0.2747 0.1711
G_C 0.0146 0.0182 0.0171
G_T 0.7420 0.1984 0.1267
T_A 0.0095 0.0458 0.0392
T_C 0.0441 0.0483 0.0528
T_G 0.0921 0.0964 0.0927
s1 s2 s3
A_C 0.2403 0.1817 0.1850
A_G 0.0803 0.0892 0.0884
A_T 0.0407 0.0565 0.0576
C_A 0.1290 0.1515 0.1462
C_G 0.0732 0.0728 0.0661
C_T 0.1331 0.1315 0.1267
G_A 0.0560 0.0518 0.0526
G_C 0.0580 0.0759 0.0838
G_T 0.1813 0.1558 0.1579
T_A 0.0457 0.0425 0.0419
T_C 0.1214 0.1257 0.1293
T_G 0.4494 0.4930 0.4918
s1 s2 s3
A_C 0.0551 0.0404 0.0433
A_G 0.0367 0.1610 0.2962
A_T 0.0167 0.0362 0.0419
C_A 0.4001 0.2640 0.1602
C_G 0.0165 0.0415 0.0557
C_T 0.1650 0.2914 0.5133
G_A 0.0721 0.2747 0.1711
G_C 0.0132 0.0181 0.0171
G_T 0.7460 0.1984 0.1267
T_A 0.0085 0.0458 0.0392
T_C 0.0437 0.0483 0.0528
T_G 0.0926 0.0963 0.0927
s1 s2 s3
A_C 0.2437 0.1817 0.1850
A_G 0.0806 0.0892 0.0884
A_T 0.0374 0.0565 0.0576
C_A 0.1287 0.1515 0.1462
C_G 0.0732 0.0728 0.0661
C_T 0.1319 0.1315 0.1267
G_A 0.0559 0.0518 0.0526
G_C 0.0551 0.0759 0.0838
G_T 0.1807 0.1558 0.1579
T_A 0.0435 0.0425 0.0419
T_C 0.1226 0.1257 0.1293
T_G 0.4547 0.4930 0.4918

3.1.3 Indels by RT index

The following blocks will repeat the above, but looking for insertions. This data does not observe sufficient deletions to make a proper count for them.

s1 s2 s3
A 0 25 382
C 0 23 70
G 0 31 89
T 0 51 221
s1 s2 s3
A 0 3 8
C 0 23 24
G 0 14 16
T 0 0 3
s1 s2 s3
A 0 25 382
C 0 20 66
G 0 27 89
T 0 48 217
s1 s2 s3
A 0 0 5
C 0 16 14
G 0 10 5

Plots of this information

3.1.4 Insertions by RT index, post normalization

3.1.4.1 Rewriting the matrices as cpm to account for library sizes.

s2 s3
A 192308 501312
C 176923 91864
G 238462 116798
T 392308 290026
s2 s3
A 75000 156863
C 575000 470588
G 350000 313725
T 0 58824
s2 s3
A 208333 506631
C 166667 87533
G 225000 118037
T 400000 287798
s2 s3
A 0 208333
C 615385 583333
G 384615 208333

3.1.4.2 Rewriting the matrices by dividing by all indexes

I think that there are few enough insertion events that this gets a bit messed up. I will double check the logic of this, but that is my initial guess given how few insertions I was seeing when reading the outputs manually. Unfortunately, this means that for these I also cannot provide a cpm measurement.

s1 s2 s3
A 0 0e+00 8e-04
C 0 0e+00 1e-04
G 0 0e+00 1e-04
T 0 1e-04 5e-04
s1 s2 s3
A 0 0 0
C 0 0 0
G 0 0 0
T 0 0 0
s1 s2 s3
A 0 0e+00 8e-04
C 0 0e+00 1e-04
G 0 0e+00 1e-04
T 0 1e-04 5e-04
s1 s2 s3
A 0 0 0
C 0 0 0
G 0 0 0

The following is my previous writing of this worksheet which just dumped the various tables.

LS0tCnRpdGxlOiAiQ291bnRpbmcgUlQgbXV0YXRpb25zIGZyb20gaWxsdW1pbmEgc2VxdWVuY2luZyBkYXRhLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGRmX3ByaW50OiBwYWdlZAogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgd2lkdGg6IDMwMAogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIHRvY19mbG9hdDogdHJ1ZQogIEJpb2NTdHlsZTo6aHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIHRvY19mbG9hdDogdHJ1ZQotLS0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CmJvZHksIHRkIHsKICBmb250LXNpemU6IDE2cHg7Cn0KY29kZS5yewogIGZvbnQtc2l6ZTogMTZweDsKfQpwcmUgewogZm9udC1zaXplOiAxNnB4Cn0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoImhwZ2x0b29scyIpCnR0IDwtIGRldnRvb2xzOjpsb2FkX2FsbCgiL2RhdGEvaHBnbHRvb2xzIikKa25pdHI6Om9wdHNfa25pdCRzZXQod2lkdGg9MTIwLAogICAgICAgICAgICAgICAgICAgICBwcm9ncmVzcz1UUlVFLAogICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgIGVjaG89VFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBkcGk9OTYpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzPTQsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWw9ImFsbG93IikKZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZT0xMCkpCnJ1bmRhdGUgPC0gZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdD0iJVklbSVkIikKcHJldmlvdXNfZmlsZSA8LSAiaW5kZXguUm1kIgp2ZXIgPC0gIjIwMTkxMjAxIgoKIyN0bXAgPC0gc20obG9hZG1lKGZpbGVuYW1lPXBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cHJldmlvdXNfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKSkpCiMjcm1kX2ZpbGUgPC0gIjAzX2V4cHJlc3Npb25faW5mZWN0aW9uXzIwMTgwODIyLlJtZCIKYGBgCgojIENhbGN1bGF0aW5nIGVycm9yIHJhdGVzLgoKSSB3cm90ZSB0aGUgZnVuY3Rpb24gJ2NyZWF0ZV9tYXRyaWNlcygpJyB0byBjb2xsZWN0IG11dGF0aW9uIGNvdW50cy4gIEF0IGxlYXN0CmluIHRoZW9yeSB0aGUgcmVzdWx0cyBmcm9tIGl0IHNob3VsZCBiZSBhYmxlIHRvIGFkZHJlc3MgbW9zdC9hbnkgcXVlc3Rpb24KcmVnYXJkaW5nIHRoZSBjb3VudHMgb2YgbXV0YXRpb25zIG9ic2VydmVkIGluIHRoZSBkYXRhLgoKYGBge3IgdGVzdGluZ30KZGV2dG9vbHM6OmxvYWRfYWxsKCJlcnJSdCIpCgp0cmlwbGV0cyA8LSBjcmVhdGVfbWF0cmljZXMoc2FtcGxlX3NoZWV0PSJzYW1wbGVfc2hlZXRzL2FsbF9zYW1wbGVzLnhsc3giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbnRfY29sdW1uPSJpZGVudHRhYmxlIiwgbXV0X2NvbHVtbj0ibXV0YXRpb250YWJsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5fcmVhZHM9MywgbWluX2luZGV4ZXM9MywgbWluX3NlcXVlbmNlcj0xMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9wb3NpdGlvbj0yNCwgcHJ1bmVfbj1UUlVFLCB2ZXJib3NlPVRSVUUpCnRyaXBsZXRfcGxvdHMgPC0gYmFycGxvdF9tYXRyaWNlcyh0cmlwbGV0cykKc3VtbWFyeSh0cmlwbGV0cykKcXVpbnR1cGxldHMgPC0gY3JlYXRlX21hdHJpY2VzKHNhbXBsZV9zaGVldD0ic2FtcGxlX3NoZWV0cy9hbGxfc2FtcGxlcy54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50X2NvbHVtbj0iaWRlbnR0YWJsZSIsIG11dF9jb2x1bW49Im11dGF0aW9udGFibGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluX3JlYWRzPTMsIG1pbl9pbmRleGVzPTUsIG1pbl9zZXF1ZW5jZXI9MTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5fcG9zaXRpb249MjQsIHBydW5lX249VFJVRSwgdmVyYm9zZT1UUlVFKQpxdWludHVwbGV0X3Bsb3RzIDwtIGJhcnBsb3RfbWF0cmljZXMocXVpbnR1cGxldHMpCnN1bW1hcnkodHJpcGxldHMpCmBgYAoKIyBRdWVzdGlvbnMgZnJvbSBEci4gRGVTdGVmYW5vCgpJIHRoaW5rIHdoYXQgaXMgYmVzdCBpcyB0byBnZXQgdGhlIG51bWJlciBvZiByZWNvdmVyZWQgbXV0YXRpb25zIG9mIGVhY2ggdHlwZQpmcm9tIGVhY2ggZGF0YSBzZXQuICBUaGF0IHdvdWxkIGJlIEEgdG8gVCwgQSB0byBHLCBBIHRvIEM7IFQgdG8gQSwgVCB0byBHLCBUIHRvCkM7IEcgdG8gQSwgRyB0byBDLCBHIHRvIFQ7IGFuZCBDIHRvIEEsIEMgdG8gRywgQyB0byBUOyBhcyB3ZWxsIGFzIGRlbGV0aW9ucyBhbmQKaW5zZXJ0aW9ucy4gIEkgd291bGQgdGhlbiBuZWVkIHRoZSBzdW0gbnVtYmVyIG9mIHRoZSByZWFkcyB0aGF0IG1ldCBhbGwgb3VyCmNyaXRlcmlhIChpLmUuIGF0IGxlYXN0IDMgZ29vZCByZWNvdmVyZWQgcmVhZHMgZm9yIHRoYXQgMTQgbnQgaW5kZXgpLiAgRWFjaCBzZXQKb2YgMyBvciBtb3JlIHdvdWxkIGN0IGFzICIxIiByZWFkIG9mIHRoYXQgcGFydGljdWxhciBpbmRleCBzbyBJIHdvdWxkIG5lZWQgdGhlCnRvdGFsIHdpdGggdGhpcyBpbiBtaW5kLiAgSSBhbHNvIG5lZWQgdG8ga25vdyB0aGUgdG90YWwgbnVtYmVyIG9mIG51Y2xlb3RpZGVzCnRoYXQgd2VyZSBpbiB0aGUgcmVnaW9uIHdlIGRlY2lkZWQgdG8gY29uc2lkZXIgaW4gdGhlIGFuYWx5c2lzLiAgV2UgbWF5IHdhbnQgdG8KdHJ5IHRoaXMgZm9yIDMgb3IgbW9yZSBhbmQgNSBvciBtb3JlIHJlY292ZXJlZCBpbmRleGVzIGlmIGl0IGlzIG5vdCBoYXJkLiAgVGhpcwppbmZvcm1hdGlvbiBkb2VzIG5vdCBpbmNsdWRlIHNwZWNpZmljIHBvc2l0aW9ucyBvbiB0aGUgdGVtcGxhdGUgd2hlcmUgZXJyb3JzCm9jY3VycmVkIGJ1dCB3ZSBjYW4gbG9vayBhdCB0aGF0IGxhdHRlci4gIFJpZ2h0IG5vdyBJIGp1c3Qgd2FudCB0byBnZXQgYSBnZW5lcmFsCmVycm9yIHJhdGUgYW5kIHR5cGUgb2YgZXJyb3IuICBJdCB3b3VsZCBiYXNpY2FsbHkgYmUgY2FsY3VsYXRlZCBieSBkaXZpZGluZyB0aGUKbnVtYmVyIG9mIHJlY292ZXJlZCBtdXRhdGlvbnMgb2YgYSBwYXJ0aWN1bGFyIHR5cGUgYnkgc3VtIG51bWJlciBvZiB0aGUgcmVhZHMKdGltZXMgdGhlIG51bWJlciBvZiBudWNsZW90aWRlcyBzY3JlZW5lZCBpbiB0aGUgdGVtcGxhdGUuICBBcyBpdCBlbmRzIHVwLCB0aGlzCm51bWJlciBkb2VzIG5vdCByZWFsbHkgaGF2ZSBhIGxvdCBvZiBtZWFuaW5nIGJ1dCBpdCBjYW4gYmUgdXNlZCB0byBjYWxjdWxhdGUgdGhlCm92ZXJhbGwgbXV0YXRpb24gcmF0ZSBhcyB3ZWxsIGFzIHRoZSByYXRlIGZvciB0cmFuc3ZlcnNpb25zLCB0cmFuc2l0aW9ucywgYW5kCmRlbGV0aW9ucyBhbmQgaW5zZXJ0aW9ucy4KCiMgQW5zd2VycwoKSW4gb3JkZXIgdG8gYWRkcmVzcyB0aG9zZSBxdWVyaWVzLCBJIGludm9rZWQgY3JlYXRlX21hdHJpY2VzKCkgd2l0aCBhIG1pbmltdW0KaW5kZXggY291bnQgb2YgMyBhbmQgNS4gIEl0IHNob3VsZCBiZSBub3RlZCB0aGF0IHRoaXMgaXMgbm90IHRoZSBzYW1lIGFzCnJlcXVpcmluZyAzIG9yIDUgcmVhZHMgcGVyIGluZGV4LiAgSW4gYm90aCBjYXNlcyBJIHJlcXVpcmUgMyByZWFkcyBwZXIgaW5kZXguCgojIyBSZWNvdmVyZWQgbXV0YXRpb25zIG9mIGVhY2ggdHlwZQoKSSBhbSBpbnRlcnByZXRpbmcgdGhpcyBxdWVzdGlvbiBhcyB0aGUgbnVtYmVyIG9mIGluZGV4ZXMgcmVjb3ZlcmVkIGZvciBlYWNoCm11dGF0aW9uIHR5cGUuICBJIGNvbGxlY3QgdGhpcyBpbmZvcm1hdGlvbiBpbiAyIHdheXMgb2YgaW50ZXJlc3Q6IHRoZSBpbmRleGVzIGJ5CnR5cGUgd2hpY2ggYXJlIGRlZW1lZCB0byBiZSBmcm9tIHRoZSBSVCBhbmQgZnJvbSB0aGUgc2VxdWVuY2VyLiAgSW4gYWRkaXRpb24sIEkKY2FsY3VsYXRlIGEgbm9ybWFsaXplZCAoY3BtKSB2ZXJzaW9uIG9mIHRoaXMgaW5mb3JtYXRpb24gd2hpY2ggbWF5IGJlIHVzZWQgdG8gbG9vayBmb3IKY2hhbmdlcyBhY3Jvc3Mgc2FtcGxlcy4KCiMjIyBNdXRhdGlvbnMgYnkgUlQgaW5kZXgKClRoaXMgZm9sbG93aW5nIGJsb2NrIHNob3VsZCBwcmludCBvdXQgdGFibGVzIG9mIHRoZSBudW1iZXJzIG9mIG11dGFudCBpbmRleGVzCm9ic2VydmVkIGZvciBlYWNoIHR5cGUgZm9yIHRoZSBSVCBhbmQgdGhlIHNlcXVlbmNlci4gIE9uZSB3b3VsZCBob3BlIHRoYXQgdGhlCnNlcXVlbmNlciB3aWxsIGJlIGNvbnNpc3RlbnQgZm9yIGFsbCBzYW1wbGVzLCBidXQgSSB0aGluayB0aGUgcmVzdWx0cyB3aWxsCmluc3RlYWQgc3VnZ2VzdCB0aGF0IG15IG1ldHJpYyBpcyBub3QgeWV0IHN0cmluZ2VudCBlbm91Z2guCgpgYGB7ciBtdXRhdGlvbl9pbmRleF9jb3VudCwgcmVzdWx0cz0nYXNpcyd9CmtuaXRyOjprYWJsZSh0cmlwbGV0c1tbIm1hdHJpY2VzIl1dW1sibWlzc19pbmRleGVzX2J5X3R5cGUiXV0pCgprbml0cjo6a2FibGUodHJpcGxldHNbWyJtYXRyaWNlcyJdXVtbIm1pc3Nfc2VxdWVuY2VyX2J5X3R5cGUiXV0pCgprbml0cjo6a2FibGUocXVpbnR1cGxldHNbWyJtYXRyaWNlcyJdXVtbIm1pc3NfaW5kZXhlc19ieV90eXBlIl1dKQoKa25pdHI6OmthYmxlKHF1aW50dXBsZXRzW1sibWF0cmljZXMiXV1bWyJtaXNzX3NlcXVlbmNlcl9ieV90eXBlIl1dKQpgYGAKClBsb3RzIG9mIHRoaXMgaW5mb3JtYXRpb24KCmBgYHtyIG11dGF0aW9uX2luZGV4X2NvdW50X3Bsb3RzfQp0cmlwbGV0X3Bsb3RzW1sibWF0cmljZXMiXV1bWyJtaXNzX2luZGV4ZXNfYnlfdHlwZSJdXQp0cmlwbGV0X3Bsb3RzW1sibm9ybWFsIl1dW1sibWlzc19pbmRleGVzX2J5X3R5cGUiXV0KCnF1aW50dXBsZXRfcGxvdHNbWyJtYXRyaWNlcyJdXVtbIm1pc3NfaW5kZXhlc19ieV90eXBlIl1dCnF1aW50dXBsZXRfcGxvdHNbWyJub3JtYWwiXV1bWyJtaXNzX2luZGV4ZXNfYnlfdHlwZSJdXQpgYGAKClRoaXMgc3VnZ2VzdHMgdG8gbWUgdGhhdCB0aGlzIGluZm9ybWF0aW9uIG5lZWRzIHRvIGJlIG5vcm1hbGl6ZWQgaW4gc29tZSBtb3JlCnNlbnNpYmxlIGZhc2hpb24uICBUaHVzIHRoZSBmb2xsb3dpbmc6CgojIyMgTXV0YXRpb25zIGJ5IFJUIGluZGV4LCBwb3N0IG5vcm1hbGl6YXRpb24KClRoZSBzYW1lIG51bWJlcnMgbWF5IGJlIGV4cHJlc3NlZCBpbiB0aGUgY29udGV4dCBvZiB0aGUgbnVtYmVyIG9mIGluZGV4ZXMKb2JzZXJ2ZWQgLyBzYW1wbGUgYW5kL29yIGFzIGEgY3BtIGFjcm9zcyBzYW1wbGVzLiAgVGh1cyBpbiB0aGUgZmlyc3QgaW5zdGFuY2UKb25lIGNhbiBsb29rIGF0IHRoZSBhcHBhcmVudCBlcnJvciByYXRlIGZvciBlYWNoIHNhbXBsZSwgYW5kIGluIHRoZSBzZWNvbmQKaW5zdGFuY2Ugb25lIG1heSBsb29rIGZvciByZWxhdGl2ZSBjaGFuZ2VzIGluIGFwcGFyZW50IGVycm9yIHJhdGUgYWNyb3NzCnNhbXBsZXMuCgojIyMjIFJld3JpdGluZyB0aGUgbWF0cmljZXMgYXMgY3BtIHRvIGFjY291bnQgZm9yIGxpYnJhcnkgc2l6ZXMuCgpgYGB7ciBtdXRhdGlvbl9pbmRleF9ub3JtYWxpemVkLCByZXN1bHRzPSdhc2lzJ30Ka25pdHI6OmthYmxlKHRyaXBsZXRzW1sibm9ybWFsaXplZCJdXVtbIm1pc3NfaW5kZXhlc19ieV90eXBlIl1dKQoKa25pdHI6OmthYmxlKHRyaXBsZXRzW1sibm9ybWFsaXplZCJdXVtbIm1pc3Nfc2VxdWVuY2VyX2J5X3R5cGUiXV0pCgprbml0cjo6a2FibGUocXVpbnR1cGxldHNbWyJub3JtYWxpemVkIl1dW1sibWlzc19pbmRleGVzX2J5X3R5cGUiXV0pCgprbml0cjo6a2FibGUocXVpbnR1cGxldHNbWyJub3JtYWxpemVkIl1dW1sibWlzc19zZXF1ZW5jZXJfYnlfdHlwZSJdXSkKYGBgCgojIyMjIFJld3JpdGluZyB0aGUgbWF0cmljZXMgYnkgZGl2aWRpbmcgYnkgYWxsIGluZGV4ZXMKClRoaXMgSSB0aGluayBzdGFydHMgdG8gYWRkcmVzcyB0aGUgbGF0ZXIgdGV4dCBpbiB5b3VyIHF1ZXJ5LgoKYGBge3IgbXV0YXRpb25faW5kZXhfbm9ybWFsaXplZF9ieV9jb3VudHMsIHJlc3VsdHM9J2FzaXMnfQprbml0cjo6a2FibGUodHJpcGxldHNbWyJtYXRyaWNlc19ieV9jb3VudHMiXV1bWyJtaXNzX2luZGV4ZXNfYnlfdHlwZSJdXSkKCmtuaXRyOjprYWJsZSh0cmlwbGV0c1tbIm1hdHJpY2VzX2J5X2NvdW50cyJdXVtbIm1pc3Nfc2VxdWVuY2VyX2J5X3R5cGUiXV0pCgprbml0cjo6a2FibGUocXVpbnR1cGxldHNbWyJtYXRyaWNlc19ieV9jb3VudHMiXV1bWyJtaXNzX2luZGV4ZXNfYnlfdHlwZSJdXSkKCmtuaXRyOjprYWJsZShxdWludHVwbGV0c1tbIm1hdHJpY2VzX2J5X2NvdW50cyJdXVtbIm1pc3Nfc2VxdWVuY2VyX2J5X3R5cGUiXV0pCmBgYAoKIyMjIyBSZXdyaXRpbmcgdGhlIG1hdHJpY2VzIGJ5IGRpdmlkaW5nIGJ5IGFsbCBpbmRleGVzIGFuZCBjcG0KCkkgdGhpbmsgdGhpcyBtaWdodCBwcm92ZSB0byBiZSB3aGVyZSB3ZSBnZXQgdGhlIG1vc3QgbWVhbmluZ2Z1bCByZXN1bHRzLgoKVGhlIG5pY2VzdCB0aGluZyBpbiBpdCBpcyB0aGF0IGFmdGVyIGFjY291bnRpbmcgZm9yIGxpYnJhcnkgc2l6ZXMgYW5kIHRvdGFsCmluZGV4ZXMgb2JzZXJ2ZWQsIHdlIGZpbmFsbHkgc2VlIHRoYXQgdGhlIHNlcXVlbmNlciBlcnJvciBpcyBtb3N0bHkgY29uc2lzdGVudAphY3Jvc3MgYWxsIHNhbXBsZXMgYW5kIG11dGF0aW9uIHR5cGVzIC0tIHdpdGggYSBjb3VwbGUgb2Ygbm90YWJsZSBleGNlcHRpb25zLgoKQnkgdGhlIHNhbWUgdG9rZW4sIGZvciB0aGUgbXV0YXRpb25zIHdoaWNoIF9hcmVfIGlkZW50aWNhbCBmb3IgdGhlIHNlcXVlbmNlciwgd2UKaGF2ZSBzb21lIHdoaWNoIGFyZSBkZWNpZGVkbHkgZGlmZmVyZW50IGZvciB0aGUgbm9uLXNlcXVlbmNlciBkYXRhLiAgVGhlIG1vc3QKbm90YWJsZSBleGFtcGxlcyBJIHRoaW5rIGFyZSBBIHRvIEcgYnV0IF9ub3QgRyB0byBBOyBhbmQgQyB0byBULgoKYGBge3IgbXV0YXRpb25faW5kZXhfY3BtX2J5X2NvdW50cywgcmVzdWx0cz0nYXNpcyd9CmtuaXRyOjprYWJsZSh0cmlwbGV0c1tbIm5vcm1hbGl6ZWRfYnlfY291bnRzIl1dW1sibWlzc19pbmRleGVzX2J5X3R5cGUiXV0pCgprbml0cjo6a2FibGUodHJpcGxldHNbWyJub3JtYWxpemVkX2J5X2NvdW50cyJdXVtbIm1pc3Nfc2VxdWVuY2VyX2J5X3R5cGUiXV0pCgprbml0cjo6a2FibGUocXVpbnR1cGxldHNbWyJub3JtYWxpemVkX2J5X2NvdW50cyJdXVtbIm1pc3NfaW5kZXhlc19ieV90eXBlIl1dKQoKa25pdHI6OmthYmxlKHF1aW50dXBsZXRzW1sibm9ybWFsaXplZF9ieV9jb3VudHMiXV1bWyJtaXNzX3NlcXVlbmNlcl9ieV90eXBlIl1dKQpgYGAKCiMjIyBJbmRlbHMgYnkgUlQgaW5kZXgKClRoZSBmb2xsb3dpbmcgYmxvY2tzIHdpbGwgcmVwZWF0IHRoZSBhYm92ZSwgYnV0IGxvb2tpbmcgZm9yIGluc2VydGlvbnMuClRoaXMgZGF0YSBkb2VzIG5vdCBvYnNlcnZlIHN1ZmZpY2llbnQgZGVsZXRpb25zIHRvIG1ha2UgYSBwcm9wZXIgY291bnQgZm9yIHRoZW0uCgpgYGB7ciBpbnNlcnRfaW5kZXhfY291bnQsIHJlc3VsdHM9J2FzaXMnfQprbml0cjo6a2FibGUodHJpcGxldHNbWyJtYXRyaWNlcyJdXVtbImluc2VydF9pbmRleGVzX2J5X250Il1dKQoKa25pdHI6OmthYmxlKHRyaXBsZXRzW1sibWF0cmljZXMiXV1bWyJpbnNlcnRfc2VxdWVuY2VyX2J5X250Il1dKQoKa25pdHI6OmthYmxlKHF1aW50dXBsZXRzW1sibWF0cmljZXMiXV1bWyJpbnNlcnRfaW5kZXhlc19ieV9udCJdXSkKCmtuaXRyOjprYWJsZShxdWludHVwbGV0c1tbIm1hdHJpY2VzIl1dW1siaW5zZXJ0X3NlcXVlbmNlcl9ieV9udCJdXSkKYGBgCgpQbG90cyBvZiB0aGlzIGluZm9ybWF0aW9uCgpgYGB7ciBpbnNlcnRfaW5kZXhfY291bnRfcGxvdHN9CnRyaXBsZXRfcGxvdHNbWyJtYXRyaWNlcyJdXVtbImluc2VydF9pbmRleGVzX2J5X250Il1dCnRyaXBsZXRfcGxvdHNbWyJub3JtYWwiXV1bWyJpbnNlcnRfaW5kZXhlc19ieV9udCJdXQoKcXVpbnR1cGxldF9wbG90c1tbIm1hdHJpY2VzIl1dW1siaW5zZXJ0X2luZGV4ZXNfYnlfbnQiXV0KcXVpbnR1cGxldF9wbG90c1tbIm1hdHJpY2VzIl1dW1siaW5zZXJ0X3NlcXVlbmNlcl9ieV9udCJdXQpxdWludHVwbGV0X3Bsb3RzW1sibm9ybWFsIl1dW1siaW5zZXJ0X2luZGV4ZXNfYnlfbnQiXV0KcXVpbnR1cGxldF9wbG90c1tbIm5vcm1hbCJdXVtbImluc2VydF9zZXF1ZW5jZXJfYnlfbnQiXV0KYGBgCgojIyMgSW5zZXJ0aW9ucyBieSBSVCBpbmRleCwgcG9zdCBub3JtYWxpemF0aW9uCgojIyMjIFJld3JpdGluZyB0aGUgbWF0cmljZXMgYXMgY3BtIHRvIGFjY291bnQgZm9yIGxpYnJhcnkgc2l6ZXMuCgpgYGB7ciBpbnNlcnRfaW5kZXhfbm9ybWFsaXplZCwgcmVzdWx0cz0nYXNpcyd9CmtuaXRyOjprYWJsZSh0cmlwbGV0c1tbIm5vcm1hbGl6ZWQiXV1bWyJpbnNlcnRfaW5kZXhlc19ieV9udCJdXSkKCmtuaXRyOjprYWJsZSh0cmlwbGV0c1tbIm5vcm1hbGl6ZWQiXV1bWyJpbnNlcnRfc2VxdWVuY2VyX2J5X250Il1dKQoKa25pdHI6OmthYmxlKHF1aW50dXBsZXRzW1sibm9ybWFsaXplZCJdXVtbImluc2VydF9pbmRleGVzX2J5X250Il1dKQoKa25pdHI6OmthYmxlKHF1aW50dXBsZXRzW1sibm9ybWFsaXplZCJdXVtbImluc2VydF9zZXF1ZW5jZXJfYnlfbnQiXV0pCmBgYAoKIyMjIyBSZXdyaXRpbmcgdGhlIG1hdHJpY2VzIGJ5IGRpdmlkaW5nIGJ5IGFsbCBpbmRleGVzCgpJIHRoaW5rIHRoYXQgdGhlcmUgYXJlIGZldyBlbm91Z2ggaW5zZXJ0aW9uIGV2ZW50cyB0aGF0IHRoaXMgZ2V0cyBhIGJpdCBtZXNzZWQKdXAuICBJIHdpbGwgZG91YmxlIGNoZWNrIHRoZSBsb2dpYyBvZiB0aGlzLCBidXQgdGhhdCBpcyBteSBpbml0aWFsIGd1ZXNzIGdpdmVuCmhvdyBmZXcgaW5zZXJ0aW9ucyBJIHdhcyBzZWVpbmcgd2hlbiByZWFkaW5nIHRoZSBvdXRwdXRzIG1hbnVhbGx5LgpVbmZvcnR1bmF0ZWx5LCB0aGlzIG1lYW5zIHRoYXQgZm9yIHRoZXNlIEkgYWxzbyBjYW5ub3QgcHJvdmlkZSBhIGNwbSBtZWFzdXJlbWVudC4KCmBgYHtyIGluc2VydF9pbmRleF9ub3JtYWxpemVkX2J5X2NvdW50cywgcmVzdWx0cz0nYXNpcyd9CmtuaXRyOjprYWJsZSh0cmlwbGV0c1tbIm1hdHJpY2VzX2J5X2NvdW50cyJdXVtbImluc2VydF9pbmRleGVzX2J5X250Il1dKQoKa25pdHI6OmthYmxlKHRyaXBsZXRzW1sibWF0cmljZXNfYnlfY291bnRzIl1dW1siaW5zZXJ0X3NlcXVlbmNlcl9ieV9udCJdXSkKCmtuaXRyOjprYWJsZShxdWludHVwbGV0c1tbIm1hdHJpY2VzX2J5X2NvdW50cyJdXVtbImluc2VydF9pbmRleGVzX2J5X250Il1dKQoKa25pdHI6OmthYmxlKHF1aW50dXBsZXRzW1sibWF0cmljZXNfYnlfY291bnRzIl1dW1siaW5zZXJ0X3NlcXVlbmNlcl9ieV9udCJdXSkKYGBgCgpUaGUgZm9sbG93aW5nIGlzIG15IHByZXZpb3VzIHdyaXRpbmcgb2YgdGhpcyB3b3Jrc2hlZXQgd2hpY2gganVzdCBkdW1wZWQgdGhlCnZhcmlvdXMgdGFibGVzLgoKIyBQcmludCByYXcgdGFibGVzCgpgYGB7ciByYXcsIHJlc3VsdHM9J2FzaXMnfQpmb3IgKHQgaW4gMTpsZW5ndGgodHJpcGxldHNbWyJtYXRyaWNlcyJdXSkpIHsKICB0YWJsZV9uYW1lIDwtIG5hbWVzKHRyaXBsZXRzW1sibWF0cmljZXMiXV0pW3RdCiAgbWVzc2FnZSgiUmF3IHRhYmxlOiAiLCB0YWJsZV9uYW1lLCAiLiIpCiAgcHJpbnQoa25pdHI6OmthYmxlKHRyaXBsZXRzW1sibWF0cmljZXMiXV1bdF0pKQp9CmBgYAoKIyBQcmludCByYXcgcGxvdHMKCmBgYHtyIHJhd19wbG90c30KZm9yICh0IGluIDE6bGVuZ3RoKHRyaXBsZXRzW1sibWF0cmljZXMiXV0pKSB7CiAgbWVzc2FnZSgiUmF3IHRhYmxlOiAiLCB0YWJsZV9uYW1lLCAiLiIpCiAgcHJpbnQoZGF0YV9wbG90c1tbIm1hdHJpY2VzIl1dW3RdKQp9CmBgYAoKIyBQcmludCBub3JtYWxpemVkIHRhYmxlcwoKYGBge3Igbm9ybSwgcmVzdWx0cz0nYXNpcyd9CmZvciAodCBpbiAxOmxlbmd0aCh0cmlwbGV0c1tbIm5vcm1hbGl6ZWQiXV0pKSB7CiAgdGFibGVfbmFtZSA8LSBuYW1lcyh0cmlwbGV0c1tbIm5vcm1hbGl6ZWQiXV0pW3RdCiAgbWVzc2FnZSgiTm9ybWFsaXplZCB0YWJsZTogIiwgdGFibGVfbmFtZSwgIi4iKQogIHByaW50KGtuaXRyOjprYWJsZSh0cmlwbGV0c1tbIm5vcm1hbGl6ZWQiXV1bdF0pKQp9CmBgYAoKIyBQcmludCBub3JtYWxpemVkIHBsb3RzCgpgYGB7ciBub3JtX3Bsb3RzfQpmb3IgKHQgaW4gMTpsZW5ndGgodHJpcGxldHNbWyJub3JtYWxpemVkIl1dKSkgewogIG1lc3NhZ2UoIk5vcm1hbGl6ZWQgdGFibGU6ICIsIHRhYmxlX25hbWUsICIuIikKICBwcmludChkYXRhX3Bsb3RzW1sibm9ybWFsIl1dW3RdKQp9CmBgYAoKYGBge3Igc2F2ZW1lfQpwYW5kZXI6OnBhbmRlcihzZXNzaW9uSW5mbygpKQptZXNzYWdlKHBhc3RlMCgiVGhpcyBpcyBocGdsdG9vbHMgY29tbWl0OiAiLCBnZXRfZ2l0X2NvbW1pdCgpKSkKdGhpc19zYXZlIDwtIHBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cm1kX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikKbWVzc2FnZShwYXN0ZTAoIlNhdmluZyB0byAiLCB0aGlzX3NhdmUpKQp0bXAgPC0gc20oc2F2ZW1lKGZpbGVuYW1lPXRoaXNfc2F2ZSkpCmBgYAoKCmBgYHtyIGxvYWRtZSwgZXZhbD1GQUxTRX0KbG9hZG1lKGZpbGVuYW1lPXRoaXNfc2F2ZSkKYGBgCg==