-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathasr.go
139 lines (126 loc) · 3.78 KB
/
asr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package cmd
import (
"bufio"
"fmt"
goio "io"
"os"
"strings"
"github.com/evolbioinfo/goalign/align"
"github.com/evolbioinfo/goalign/io/fasta"
"github.com/evolbioinfo/goalign/io/phylip"
"github.com/evolbioinfo/gotree/asr"
"github.com/evolbioinfo/gotree/io"
"github.com/evolbioinfo/gotree/io/utils"
"github.com/evolbioinfo/gotree/tree"
"github.com/spf13/cobra"
)
var asralign string
var asrphylip bool
var asrinputstrict bool
var asrrandomresolve bool // Resolve ambiguities randomly in the downpass/deltran/acctran algo
var outlogfile string
// asrCmd represents the asr command
var asrCmd = &cobra.Command{
Use: "asr",
Short: "Reconstructs most parsimonious ancestral sequences",
Long: `Reconstructs most parsimonious ancestral sequences.
Depending on the chosen algorithm, it will run:
1) UP-PASS and
2) Either
a) DOWN-PASS or
b) DOWN-PASS+DELTRAN or
c) ACCTRAN
d) NONE
Should work on multifurcated trees
If --random-resolve is given then, during the last pass, each time
a node with several possible states still exists, one state is chosen
randomly before going deeper in the tree.
`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
var align align.Alignment
var fi goio.Closer
var r *bufio.Reader
var algo int
var treefile goio.Closer
var treechan <-chan tree.Trees
var f *os.File
var logf *os.File
var nsteps []int
switch strings.ToLower(parsimonyAlgo) {
case "acctran":
algo = asr.ALGO_ACCTRAN
case "deltran":
algo = asr.ALGO_DELTRAN
case "downpass":
algo = asr.ALGO_DOWNPASS
case "none":
algo = asr.ALGO_NONE
default:
err = fmt.Errorf("unkown parsimony algorithm: %s", parsimonyAlgo)
io.LogError(err)
return
}
// Reading the alignment
fi, r, err = utils.GetReader(asralign)
if err != nil {
io.LogError(err)
return
}
if asrphylip {
align, err = phylip.NewParser(r, asrinputstrict).Parse()
if err != nil {
io.LogError(err)
return
}
} else {
align, err = fasta.NewParser(r).Parse()
if err != nil {
io.LogError(err)
return
}
}
fi.Close()
// Reading the trees
if treefile, treechan, err = readTrees(intreefile); err != nil {
io.LogError(err)
return
}
defer treefile.Close()
// Computing parsimony ASR and writing each trees
if f, err = openWriteFile(outtreefile); err != nil {
io.LogError(err)
return
}
defer closeWriteFile(f, outtreefile)
if logf, err = openWriteFile(outlogfile); err != nil {
io.LogError(err)
return
}
defer closeWriteFile(logf, outlogfile)
for t := range treechan {
nsteps, err = asr.ParsimonyAsr(t.Tree, align, algo, asrrandomresolve)
if err != nil {
io.LogError(err)
return
}
fmt.Fprintf(logf, "steps")
for _, s := range nsteps {
fmt.Fprintf(logf, " %d", s)
}
fmt.Fprintf(logf, "\n")
f.WriteString(t.Tree.Newick() + "\n")
}
return
},
}
func init() {
RootCmd.AddCommand(asrCmd)
asrCmd.PersistentFlags().StringVarP(&asralign, "align", "a", "stdin", "Alignment input file")
asrCmd.PersistentFlags().BoolVarP(&asrphylip, "phylip", "p", false, "Alignment is in phylip? default : false (Fasta)")
asrCmd.PersistentFlags().BoolVar(&asrinputstrict, "input-strict", false, "Strict phylip input format (only used with -p)")
asrCmd.PersistentFlags().StringVarP(&intreefile, "input", "i", "stdin", "Input tree")
asrCmd.PersistentFlags().StringVarP(&outtreefile, "output", "o", "stdout", "Output file")
asrCmd.PersistentFlags().StringVar(&outlogfile, "log", "stdout", "Output log file")
asrCmd.PersistentFlags().StringVar(&parsimonyAlgo, "algo", "acctran", "Parsimony algorithm for resolving ambiguities: acctran, deltran, or downpass")
asrCmd.PersistentFlags().BoolVar(&asrrandomresolve, "random-resolve", false, "Random resolve states when several possibilities in: acctran, deltran, or downpass")
}