---
# System prepended metadata

title: TAPER

---

---
title: 'taper'
disqus: hackmd
---

Correcting errors in alignments with TAPER
===
By Tanya Lama

### Objective: 

TAPER is a tool that looks for errors in small species-specific stretches of the multiple sequence alignments. TAPER uses a two-dimensional outlier detection algorithm that seeks to find what parts of a sequence are outliers given the overall level of divergence of the sequence to others and the level of the divergence of the region in the alignment. Importantly, TAPER adjusts its null expectations per site and species, and in doing so, it attempts to distinguish the real heterogeneity (signal) from errors (noise).

Zhang, C., Zhao, Y., Braun, E. L., & Mirarab, S. (2021). TAPER: Pinpointing errors in multiple sequence alignments despite varying rates of evolution. Methods in Ecology and Evolution, 00, 1– 14. https://doi.org/10.1111/2041-210X.13696

### Acknowledgements
Thanks to Bill Thomas 5ever 

## Table of Contents

[TOC]

# Installing julia/ TAPER
see the full directions [on github](https://github.com/chaoszhang/TAPER)

move to our project /bin and download and unzip Julia.

curl -fsSL https://install.julialang.org | sh

# Where is juliaup? 
which juliaup
/home/tlama_umass_edu/.juliaup/bin/juliaup

# Create the correction_multi.jl file 
```
global R = [Dict("k"=>5, "p"=>0.25, "q"=>0.1, "L"=>30),
     Dict("k"=>9, "p"=>0.25, "q"=>0.25, "L"=>54),
     Dict("k"=>17, "p"=>0.1, "q"=>0.5, "L"=>Inf)]

PROGRAM_VERSION = v"1.0.0"
try
	using ArgParse
catch
	import Pkg
	Pkg.add("ArgParse")
	using ArgParse
end
import Statistics.median

function correction(c, output, k, X, MASK, pvalue, qvalue, threshold)
	upperx = ('a' <= X && X <= 'z') ? X - 'a' + 'A' : X
	upperc = [uppercase(str) for str in c]
	arrc = [Array{Char, 1}(str) for str in c]
	n = length(c[1])
	m = length(c)
	wo = zeros(n, m)
	# read sequences and compute per column profiles. 
	for i in 1:n
		cnt = zeros(128)
		# read a column, internally represent in upper case, and count letters
		for j in 1:m
			cnt[UInt8(upperc[j][i])] += 1
		end
		cnt[UInt8(upperx)] = 0
		cnt[UInt8('-')] = 0
		unq = length([1 for t in cnt if t > 0])
		total = sum(cnt)
		for j in 1:m
			wo[i, j] = total == 0 ? 0 : total / (unq * cnt[UInt8(upperc[j][i])])
		end
	end
	w1 = [wo[:,j][(arrc[j] .!= '-') .& (arrc[j] .!= X)] for j in 1:m]
	w = [[median(arr[i:i+k-1]) for i in 1:length(arr)-k+1] for arr in w1]
	ws = [[sum(arr[i:i+k-1]) for i in 1:length(arr)-k+1] for arr in w1]
	wsorted = [sort(arr) for arr in w]
	wsum = [accumulate(+, arr) for arr in wsorted]
	f(x, y, n, m) = x^2 / n + (n == m ? 0 : (y - x)^2 / (m - n))
	var = [length(arr) > 0 ? f.(arr, arr[end], 1:length(arr), length(arr)) : [] for arr in wsum]
	wCutoff = [length(var[j]) > 0 ? wsorted[j][findmax(var[j])[2]] : 0 for j in 1:m]
	cutoffSorted = sort([wCutoff[j] for j in 1:m if length(var[j]) > 0])
	cutoffFloor = (pvalue >= 1) ? 0 : cutoffSorted[end - floor(Int, length(cutoffSorted) * pvalue)]
	s = zeros(n - k + 1, m, 2)
	tiebreaker = zeros(n - k + 1, m, 2)
	bt = zeros(Int64, n - k + 1, m, 2)
	for j in 1:m
		wj = w[j]
		wsj = ws[j]
		L = length(wj)
		if L <= k
			push!(output, c[j])
			continue
		end
		s = zeros(L, 2)
		tiebreaker = zeros(L, 2)
		bt = zeros(Int64, L, 2)
		cutoff = max(wCutoff[j], cutoffFloor, (qvalue >= 1) ? 0 : wsorted[j][end - floor(Int, length(wsorted[j]) * qvalue)], threshold)
		for i in 1:L
			v = (wj[i] > cutoff ? 0 : 1)
			if i == 1
				s[i, 1] = v
				s[i, 2] = 1 - v
				tiebreaker[i, 1] = 0
				tiebreaker[i, 2] = wsj[i]
			else
				s[i, 1] = s[i - 1, 1] + v
				s[i, 2] = s[i - 1, 2] + 1 - v
				tiebreaker[i, 1] = tiebreaker[i - 1, 1]
				tiebreaker[i, 2] = tiebreaker[i - 1, 2] + wsj[i]
				bt[i, 1] = 1
				bt[i, 2] = 2
			end
			if i > k && (s[i, 1], tiebreaker[i, 1]) < (s[i - k, 2] + v, tiebreaker[i - k, 2])
				s[i, 1] = s[i - k, 2] + v
				tiebreaker[i, 1] = tiebreaker[i - k, 2]
				bt[i, 1] = 2
			end
			if i > k && (s[i, 2], tiebreaker[i, 2]) < (s[i - k, 1] + 1 - v, tiebreaker[i - k, 1])
				s[i, 2] = s[i - k, 1] + 1 - v
				tiebreaker[i, 2] = tiebreaker[i - k, 1] + wsj[i]
				bt[i, 2] = 1
			end
		end
		str = arrc[j][(arrc[j] .!= '-') .& (arrc[j] .!= X)]
		icur = L
		if s[L, 1] < s[L, 2]
			str[L:L+k-1] .= MASK
			bcur = 2
		else
			bcur = 1
		end
		while true
			if bcur == 1 && bt[icur, bcur] == 1
				icur -= 1
				bcur = 1
			elseif bcur == 1 && bt[icur, bcur] == 2
				icur -= k
				bcur = 2
				str[icur : icur + k - 1] .= MASK
			elseif bcur == 2 && bt[icur, bcur] == 1
				icur -= k
				bcur = 1
			elseif bcur == 2 && bt[icur, bcur] == 2
				icur -= 1
				bcur = 2
				str[icur] = MASK
			elseif bcur == 1
				break
			else
				str[1:icur - 1] .= MASK
				break
			end
		end
		strout = ""
		i = 1
		for t in 1:length(c[j])
			if c[j][t] == X || c[j][t] == '-'
				strout *= c[j][t]
			else
				strout *= str[i]
				i += 1
			end
		end
		push!(output, strout)
	end
end

function ArgParse.parse_item(::Type{Char}, x::AbstractString)
	return x[1]
end

function parse_commandline()
	s = ArgParseSettings()
	
	@add_arg_table! s begin
		"--list", "-l"
			help = "running on a list of inputs; for every two lines of the list file, the first one should be the path to the input and the second should be the path to its output"
			action = :store_true
		"--mask", "-m"
			help = "the character to mask erroneous regions"
			arg_type = Char
			default = 'X'
		"--any", "-a"
			help = "the character to denote ambiguous positions or character to denote ANY in the input files"
			arg_type = Char
			default = 'X'
		"--cutoff", "-c"
			help = "set score cutoff to control the minimum aggressiveness of masking (should be > 1)"
			arg_type = Float64
			default = 3.0
		"--parameter", "-p"
			help = "(Advanced) load the list of k, p, q, and L from the input parameter file"
			arg_type = String
		"input"
			help = "a fasta file as input"
			required = true
	end
	
	return parse_args(s)
end

function correction_multi(args, fin, fout)
	inputText = read(fin, String)
	temp = split(inputText, ">")
	temp = temp[length.(temp) .> 0]
	temp = [split(arr, "\n") for arr in temp]
	header = [arr[1] for arr in temp]
	c = [string(arr[2:end]...) for arr in temp]
	arrc = [Array{Char, 1}(str) for str in c]
	n = length(c[1])
	m = length(c)
	MASK = args["mask"]
	for r in R
		output = []
		correction(c, output, get(r, "k", 9), args["any"], '*', get(r, "p", 0), get(r, "q", 0), args["cutoff"])
		L = get(r, "L", Inf)
		for j in 1:m
			start = 0
			cnt = 0
			for i in 1:n
				if start == 0 && output[j][i] == '*'
					start = i
					cnt = 1
				end
				if start != 0 && output[j][i] == '*'
					cnt += 1
				end
				if start != 0 && output[j][i] != '*' && output[j][i] != '-'
					if cnt < L
						for k in start:i-1
							arrc[j][k] = (output[j][k] == '-') ? '-' : MASK
						end
					end
					start = 0
					cnt = 0
				end
			end
			if start != 0 && cnt < L
				for k in start:n
						arrc[j][k] = (output[j][k] == '-') ? '-' : MASK
				end
			end
		end
	end
	for j in 1:m
		println(fout, ">" * header[j])
		println(fout, String(arrc[j]))
	end
end

function main()
	println(stderr, "Version " * string(PROGRAM_VERSION))
	args = parse_commandline()
	if isnothing(args["parameter"]) == false
		global R = eval(Meta.parse(read(open(args["parameter"], "r"), String)))
	end
	if args["list"] == false
		correction_multi(args, open(args["input"], "r"), stdout)
	else
		temp = split(read(open(args["input"], "r"), String), "\n")
		temp = temp[length.(temp) .> 0]
		for i = 2:2:length(temp)
			try
				println(stderr, "Processing " * temp[i - 1] * "...")
				correction_multi(args, open(temp[i - 1], "r"), open(temp[i], "w"))
			catch
				println(stderr, "Error happened when processing " * temp[i - 1] * ".")
				println(stderr)
			end
		end
	end
end

main()
```
# Run TAPER
Usage is 
/home/tlama_umass_edu/.juliaup/bin/julia correction_multi.jl -m N input > output
```
/home/tlama_umass_edu/.juliaup/bin/julia correction_multi.jl -m N ENST00000678030.PANO1.cleanLb_hmm_manual.fasta > julia-ENST00000678030.PANO1.cleanLb_hmm_manual.fasta
```

# Run aBSREL on our cleanLb_hmm_manual alignment 
hyphy -i [work through the questions in interactive mode]

# Run aBSREL on TAPER corrected alignment 
hyphy -i 

# Compare results 

### Original: 
### Adaptive branch site random effects likelihood test 
Likelihood ratio test for episodic diversifying positive selection at Holm-Bonferroni corrected _p =   0.0500_ found **13** branches under selection among **18** tested.

* HLsacLep1, p-value =  0.00000
* HLrhiTri2, p-value =  0.00000
* HLrhiSed2, p-value =  0.00000
* HLphyDis3, p-value =  0.00000
* HLaseSto2, p-value =  0.00000
* HLartJam3, p-value =  0.00000
* HLrhiLuc4, p-value =  0.00001
* HLdipEca1, p-value =  0.00001
* HLpipKuh2, p-value =  0.00002
* felCat9, p-value =  0.00006
* hg38, p-value =  0.00282
* HLphyHas1, p-value =  0.00287
* HLrouAeg4, p-value =  0.04412

### TAPER corrected
### Adaptive branch site random effects likelihood test 
Likelihood ratio test for episodic diversifying positive selection at Holm-Bonferroni corrected _p =   0.0500_ found **12** branches under selection among **18** tested.

* HLrhiTri2, p-value =  0.00000
* HLrhiSed2, p-value =  0.00000
* HLphyDis3, p-value =  0.00000
* HLsacLep1, p-value =  0.00000
* HLartJam3, p-value =  0.00000
* HLaseSto2, p-value =  0.00000
* HLrhiLuc4, p-value =  0.00001
* HLdipEca1, p-value =  0.00002
* HLpipKuh2, p-value =  0.00002
* felCat9, p-value =  0.00005
* hg38, p-value =  0.00307
* HLphyHas1, p-value =  0.00291

looks like we lost the result from HLrouAeg4, however this site likely would have fallen out with FDR correction (above are BH corrected pvalues but we do an additional correction in post processing)

# Compare results in AliView

# Compare the results using MEME
### Original: 
>Please choose an option (or press q to cancel selection):1
* Log(L) = -7306.01
* non-synonymous/synonymous rate ratio for *background* =   0.7622
* non-synonymous/synonymous rate ratio for *test* =   0.7565

### For partition 1 these sites are significant at p <=0.05

|   Codon    | Partition  |   alpha    |   beta+    |     p+     |    LRT     |Episodic selection detected?| # branches |Most common codon substitutions at this site|
|:----------:|:----------:|:----------:|:----------:|:----------:|:----------:|:--------------------------:|:----------:|:------------------------------------------:|
|     13     |     1      |    0.050   |  170.501   |    0.079   |    5.995   |      Yes, p =  0.0226      |     1      |     [1]CAT>ATC,GCT>CAT,GTT>GCT,GTT>TGC     |
|     15     |     1      |    0.830   |    9.465   |    0.495   |    4.687   |      Yes, p =  0.0443      |     7      |[1]CAC>ACC,CAT>CAC,CAT>CCC,CAT>CCT,CAT>CG...|
|     27     |     1      |    0.172   |  176.094   |    0.102   |    8.495   |      Yes, p =  0.0063      |     1      |       [2]GCG>GTG|[1]ACG>GCG,GCG>CGC        |
|     41     |     1      |    0.118   |10000.000...|    0.304   |   15.866   |      Yes, p =  0.0002      |     2      |[2]GGA>GGC|[1]ACA>CAA,ACA>GAC,GGA>AAG,GGA...|
|     46     |     1      |    1.857   |   75.370   |    0.642   |    4.849   |      Yes, p =  0.0408      |     3      |[1]GTG>AGG,GTG>ATG,GTG>CCG,GTG>CGC,GTG>GC...|
|     54     |     1      |    0.000   |   42.346   |    0.274   |    5.795   |      Yes, p =  0.0250      |     3      |[2]GGG>GCG|[1]GAG>CGG,GAG>GGA,GGG>GAG,GGG...|
|     56     |     1      |    1.001   |   29.788   |    0.245   |   10.044   |      Yes, p =  0.0029      |     4      |[2]GGC>CGC,GGC>GGT|[1]GGC>CAC,GGC>CAG,GGC...|
|     60     |     1      |    1.268   |   23.823   |    0.335   |    9.442   |      Yes, p =  0.0039      |     4      |[3]TGT>TGC|[2]TGT>GTC|[1]AGT>TGT,GGT>AGT,...|
|     65     |     1      |    0.000   |  239.277   |    0.481   |   13.944   |      Yes, p =  0.0004      |     7      |[2]GTC>CCA|[1]GTC>ATG,GTC>CAG,GTC>GAT,GTC...|
|     67     |     1      |    0.000   |   15.404   |    0.266   |   13.229   |      Yes, p =  0.0006      |     3      |[2]ACC>GAC|[1]AAC>CCA,ACC>AAC,ACC>ATG,ATG...|
|     68     |     1      |    1.052   |  114.888   |    0.290   |    7.537   |      Yes, p =  0.0103      |     4      |[2]GGG>GGC,GGG>TGG,TGG>GTC|[1]GGG>GCT,TGG...|
|     71     |     1      |    0.860   |  427.396   |    0.386   |    8.859   |      Yes, p =  0.0052      |     5      |[1]ACG>ACA,ACG>AGG,ACG>CAG,ACG>CCA,ACG>GG...|
|     73     |     1      |    0.000   |10000.000...|    0.143   |    6.481   |      Yes, p =  0.0176      |     2      |[2]ACG>ATG|[1]AAG>ACG,ACG>CCG,ACG>GTC,ATA...|
|     79     |     1      |    0.000   |  474.307   |    0.131   |   21.851   |      Yes, p =  0.0000      |     2      |             [1]CGA>GAT,CGA>GCC             |
|     91     |     1      |    0.000   |  433.397   |    0.111   |    9.688   |      Yes, p =  0.0034      |     2      |         [1]CCC>TCC,TCC>ACC,TCC>CGT         |
|    106     |     1      |    1.073   |  672.590   |    0.260   |    8.261   |      Yes, p =  0.0071      |     2      |[1]CGT>GCC,TCT>TAC,TGC>CGT,TGC>GCA,TGC>GC...|
|    108     |     1      |    0.000   |  506.817   |    0.154   |   12.511   |      Yes, p =  0.0008      |     2      |[1]CCG>CAG,CCG>GCA,CCG>GGG,CCG>TCG,CTG>GC...|
|    109     |     1      |    0.000   |  2077.696  |    0.347   |   15.398   |      Yes, p =  0.0002      |     6      |[2]GGC>GCT|[1]AGC>CCC,GGC>ACG,GGC>AGC,GGC...|
|    131     |     1      |    0.000   |   22.126   |    0.196   |    5.471   |      Yes, p =  0.0296      |     3      |           [2]CGG>CCG|[1]CGG>CTC            |
|    154     |     1      |    0.000   |   97.984   |    0.230   |    6.529   |      Yes, p =  0.0172      |     3      |     [1]CAG>GAG,CAG>GCC,GAG>ACC,GAG>CTC     |
|    196     |     1      |    0.000   |  120.736   |    0.089   |    6.833   |      Yes, p =  0.0147      |     1      |             [1]CTC>CGC,CTC>GCT             |
|    203     |     1      |    0.321   |  212.486   |    0.137   |    7.771   |      Yes, p =  0.0091      |     2      |         [1]CTC>CCG,CTC>CTG,CTC>GCA         |

### ** Found _22_ sites under episodic diversifying positive selection at p <= 0.05**

### TAPER corrected: 
>Please choose an option (or press q to cancel selection):1
* Log(L) = -7299.71
* non-synonymous/synonymous rate ratio for *background* =   0.7620
* non-synonymous/synonymous rate ratio for *test* =   0.7541

### For partition 1 these sites are significant at p <=0.05

|   Codon    | Partition  |   alpha    |   beta+    |     p+     |    LRT     |Episodic selection detected?| # branches |Most common codon substitutions at this site|
|:----------:|:----------:|:----------:|:----------:|:----------:|:----------:|:--------------------------:|:----------:|:------------------------------------------:|
|     13     |     1      |    0.053   |  149.763   |    0.080   |    5.983   |      Yes, p =  0.0227      |     1      |     [1]CAT>ATC,GCT>CAT,GTT>GCT,GTT>TGC     |
|     15     |     1      |    0.726   |   15.691   |    0.394   |    4.587   |      Yes, p =  0.0467      |     1      |[1]CAC>ACC,CAT>CAC,CAT>CCC,CAT>CCT,CAT>CG...|
|     27     |     1      |    0.172   |  176.094   |    0.102   |    8.466   |      Yes, p =  0.0064      |     1      |       [2]GCG>GTG|[1]ACG>GCG,GCG>CGC        |
|     41     |     1      |    0.119   |10000.000...|    0.302   |   15.942   |      Yes, p =  0.0001      |     2      |[2]GGA>GGC|[1]ACA>CAA,ACA>GAC,GGA>AAG,GGA...|
|     46     |     1      |    1.855   |   78.131   |    0.635   |    4.829   |      Yes, p =  0.0412      |     3      |[1]GTG>AGG,GTG>ATG,GTG>CCG,GTG>CGC,GTG>GC...|
|     54     |     1      |    0.000   |   41.961   |    0.272   |    5.756   |      Yes, p =  0.0256      |     3      |[2]GGG>GCG|[1]GAG>CGG,GAG>GGA,GGG>GAG,GGG...|
|     56     |     1      |    0.976   |   29.084   |    0.247   |   10.023   |      Yes, p =  0.0029      |     4      |[2]GGC>CGC,GGC>GGT|[1]GGC>CAC,GGC>CAG,GGC...|
|     **57**     |     1      |    1.208   |  1617.563  |    0.180   |    6.760   |      Yes, p =  0.0153      |     3      |[2]TCA>TCC,TCA>TCT|[1]TCA>CGC,TCA>CTC,TCA...|
|     60     |     1      |    1.270   |   22.526   |    0.342   |    9.401   |      Yes, p =  0.0040      |     4      |[3]TGT>TGC|[2]TGT>GTC|[1]AGT>TGT,GGT>AGT,...|
|     65     |     1      |    0.000   |  243.982   |    0.472   |   14.029   |      Yes, p =  0.0004      |     7      |[2]GTC>CCA|[1]GTC>ATG,GTC>CAG,GTC>GAT,GTC...|
|     67     |     1      |    0.000   |   15.101   |    0.274   |   13.312   |      Yes, p =  0.0006      |     3      |[2]ACC>GAC|[1]AAC>CCA,ACC>AAC,ACC>ATG,ATG...|
|     68     |     1      |    1.035   |  115.300   |    0.285   |    7.534   |      Yes, p =  0.0103      |     4      |[2]GGG>GGC,GGG>TGG,TGG>GTC|[1]GGG>GCT,TGG...|
|     71     |     1      |    0.821   |  458.703   |    0.384   |    8.918   |      Yes, p =  0.0051      |     5      |[1]ACG>ACA,ACG>AGG,ACG>CAG,ACG>CCA,ACG>GG...|
|     73     |     1      |    0.000   |  552.454   |    0.134   |    6.578   |      Yes, p =  0.0168      |     2      |[2]ACG>ATG|[1]AAG>ACG,ACG>CCG,ACG>GTC,ATA...|
|     79     |     1      |    0.000   |  501.160   |    0.132   |   21.818   |      Yes, p =  0.0000      |     2      |             [1]CGA>GAT,CGA>GCC             |
|     91     |     1      |    0.000   |  350.914   |    0.113   |    9.669   |      Yes, p =  0.0035      |     2      |         [1]CCC>TCC,TCC>ACC,TCC>CGT         |
|    106     |     1      |    1.032   |  878.243   |    0.250   |    5.719   |      Yes, p =  0.0260      |     2      |[1]CGT>GCC,TCT>TAC,TGC>CGT,TGC>GCA,TGC>GC...|
|    108     |     1      |    0.000   |  509.649   |    0.154   |   12.489   |      Yes, p =  0.0008      |     2      |[1]CCG>CAG,CCG>GCA,CCG>GGG,CCG>TCG,CTG>GC...|
|    109     |     1      |    0.000   |  1481.559  |    0.344   |   18.773   |      Yes, p =  0.0000      |     6      |[2]GGC>GCT|[1]AGC>CCC,GGC>ACG,GGC>AGC,GGC...|
|    **114**     |     1      |    0.000   |   99.765   |    0.389   |    5.620   |      Yes, p =  0.0274      |     1      |[1]CAC>CAA,CAC>CTC,CAC>GAG,CTC>GGC,CTC>TG...|
|    **116**     |     1      |    0.283   |  456.492   |    0.343   |    5.746   |      Yes, p =  0.0257      |     1      |[3]CAC>CCA|[2]CAC>CCC|[1]CAC>TAC,TAC>CCT,...|
|    131     |     1      |    0.000   |   21.031   |    0.193   |    5.454   |      Yes, p =  0.0298      |     3      |           [2]CGG>CCG|[1]CGG>CTC            |
|    154     |     1      |    0.000   |   87.358   |    0.231   |    6.526   |      Yes, p =  0.0172      |     3      |     [1]CAG>GAG,CAG>GCC,GAG>ACC,GAG>CTC     |
|    196     |     1      |    0.000   |  138.744   |    0.088   |    6.817   |      Yes, p =  0.0148      |     1      |             [1]CTC>CGC,CTC>GCT             |
|    203     |     1      |    0.322   |  192.632   |    0.133   |    7.883   |      Yes, p =  0.0086      |     2      |         [1]CTC>CCG,CTC>CTG,CTC>GCA         |

### ** Found _25_ sites under episodic diversifying positive selection at p <= 0.05**

# Do these differences in the MEME results really matter after we screen for EBF>100? 

