annotate ffp_phylogeny.py @ 0:eb6e5e78a066 draft

Uploaded
author damion
date Mon, 23 Feb 2015 18:25:25 -0500
parents
children d1c88b118a3f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
1 #!/usr/bin/python
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
2 import optparse
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
3 import time
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
4 import os
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
5 import tempfile
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
6 import sys
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
7 import shlex, subprocess
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
8 from string import maketrans
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
9
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
10 VERSION_NUMBER = "0.1.00"
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
11
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
12 class MyParser(optparse.OptionParser):
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
13 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
14 From http://stackoverflow.com/questions/1857346/python-optparse-how-to-include-additional-info-in-usage-output
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
15 Provides a better class for displaying formatted help info in epilog() portion of optParse; allows for carriage returns.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
16 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
17 def format_epilog(self, formatter):
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
18 return self.epilog
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
19
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
20
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
21 def stop_err( msg ):
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
22 sys.stderr.write("%s\n" % msg)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
23 sys.exit(1)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
24
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
25 def getTaxonomyNames(type, multiple, abbreviate, filepaths, filenames):
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
26 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
27 Returns a taxonomic list of names corresponding to each file being analyzed by ffp.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
28 This may also include names for each fasta sequence found within a file if the
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
29 "-m" multiple option is provided. Default is to use the file names rather than fasta id's inside the files.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
30 NOTE: THIS DOES NOT (MUST NOT) REORDER NAMES IN NAME ARRAY.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
31 EACH NAME ENTRY IS TRIMMED AND MADE UNIQUE
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
32
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
33 @param type string ['text','amino','nucleotide']
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
34 @param multiple boolean Flag indicates to look within files for labels
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
35 @param abbreviate boolean Flag indicates to shorten labels
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
36 @filenames array original input file names as user selected them
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
37 @filepaths array resulting galaxy dataset file .dat paths
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
38
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
39 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
40 # Take off prefix/suffix whitespace/comma :
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
41 taxonomy = filenames.strip().strip(',').split(',')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
42 translations = maketrans(' .- ','____')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
43 names=[]
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
44 ptr = 0
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
45
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
46 for file in filepaths:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
47 # First, convert space, period to underscore in file names. ffprwn IS VERY SENSITIVE ABOUT THIS.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
48 # Also trim labels to 50 characters. Turns out ffpjsd is kneecapping a taxonomy label to 10 characters if it is greater than 50 chars.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
49 taxonomyitem = taxonomy[ptr].strip().translate(translations)[:50]
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
50 # print taxonomyitem
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
51 if not type in 'text' and multiple:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
52 #Must read each fasta file, looking for all lines beginning ">"
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
53 with open(file) as fastafile:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
54 lineptr = 0
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
55 for line in fastafile:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
56 if line[0] == '>':
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
57 name = line[1:].split(None,1)[0].strip()[:50]
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
58 # Odd case where no fasta description found
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
59 if name == '': name = taxonomyitem + '.' + str(lineptr)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
60 names.append(name)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
61 lineptr += 1
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
62 else:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
63 names.append(taxonomyitem)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
64
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
65 ptr += 1
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
66
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
67 if abbreviate:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
68 names = trimCommonPrefixes(names)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
69 names = trimCommonPrefixes(names, True) # reverse = Suffixes.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
70
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
71 return names
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
72
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
73 def trimCommonPrefixes(names, reverse=False):
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
74 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
75 Examines sorted array of names. Trims off prefix of each subsequent pair.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
76
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
77 @param names array of textual labels (file names or fasta taxonomy ids)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
78 @param reverse boolean whether to reverse array strings before doing prefix trimming.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
79 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
80 wordybits = '|.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
81
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
82 if reverse:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
83 names = map(lambda name: name[::-1], names) #reverses characters in names
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
84
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
85 sortednames = sorted(names)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
86 ptr = 0
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
87 sortedlen = len(sortednames)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
88 oldprefixlen=0
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
89 prefixlen=0
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
90 for name in sortednames:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
91 ptr += 1
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
92
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
93 #If we're not at the very last item, reevaluate prefixlen
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
94 if ptr < sortedlen:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
95
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
96 # Skip first item in an any duplicate pair. Leave duplicate name in full.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
97 if name == sortednames[ptr]:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
98 if reverse:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
99 continue
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
100 else:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
101 names[names.index(name)] = 'DupLabel-' + name
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
102 continue
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
103
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
104 # See http://stackoverflow.com/questions/9114402/regexp-finding-longest-common-prefix-of-two-strings
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
105 prefixlen = len( name[:([x[0]==x[1] for x in zip(name, sortednames[ptr])]+[0]).index(0)] )
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
106
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
107 if prefixlen <= oldprefixlen:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
108 newprefix = name[:oldprefixlen]
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
109 else:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
110 newprefix = name[:prefixlen]
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
111 # Expands label to include any preceeding characters that were probably part of it.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
112 newprefix = newprefix.rstrip(wordybits)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
113 newname = name[len(newprefix):]
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
114 # Some tree visualizers don't show numeric labels?!?!
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
115 if not reverse and newname.replace('.','',1).isdigit():
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
116 newname = 'id_' + newname
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
117 names[names.index(name)] = newname #extract name after prefix part; has nl in it
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
118 oldprefixlen = prefixlen
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
119
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
120 if reverse:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
121 names = map(lambda name: name[::-1], names) #now back to original direction
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
122
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
123 return names
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
124
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
125 def getTaxonomyFile(names):
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
126 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
127 FFP's ffpjsd -p [taxon file of labels] option creates a phylip tree with
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
128 given taxon labels
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
129
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
130 @param names array of datafile names or fasta sequence ids
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
131 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
132
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
133 try:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
134 temp = tempfile.NamedTemporaryFile(mode='w+t',delete=False)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
135 taxonomyTempFile = temp.name
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
136 temp.writelines(name + '\n' for name in names)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
137
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
138 except:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
139 stop_err("Galaxy configuration error for ffp_phylogeny tool. Unable to write taxonomy file " + taxonomyTempFile)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
140
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
141 finally:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
142 temp.close()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
143
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
144 return taxonomyTempFile
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
145
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
146
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
147 def check_output(command):
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
148 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
149 Execute a command line containing a series of pipes; and handle error cases by exiting at first error case. This is a substitute for Python 2.7 subprocess.check_output() - allowing piped commands without shell=True call . Based on Python subprocess docs 17.1.4.2
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
150
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
151 ISSUE: warnings on stderr are given with no exit code 0:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
152 ffpry: Warning: No keys of length 6 found.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
153 ffpcol: (null): Not a key valued FFP.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
154
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
155 Can't use communicate() because this closes processes' stdout
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
156 file handle even without errors because of read to end of stdout:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
157 (stdoutdata, stderrdata) = processes[ptr-1].communicate()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
158
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
159 """
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
160 commands = command.split("|")
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
161 processes = []
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
162 ptr = 0
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
163 for command_line in commands:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
164 print command_line.strip()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
165 args = shlex.split(command_line.strip())
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
166 if ptr == 0:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
167 proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
168 processes.append(proc)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
169 else:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
170 # It seems the act of reading standard error output is enough to trigger
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
171 # error code signal for that process, i.e. so that retcode returns a code.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
172 stderrdata = processes[ptr-1].stderr.read()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
173 retcode = processes[ptr-1].poll()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
174 if retcode or len(stderrdata) > 0:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
175 stop_err(stderrdata)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
176
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
177 newProcess = subprocess.Popen(args, stdin=processes[ptr-1].stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
178 processes.append(newProcess)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
179 processes[ptr-1].stdout.close() # Allow prev. process to receive a SIGPIPE if current process exits.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
180
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
181 ptr += 1
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
182
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
183 (stdoutdata, stderrdata) = processes[ptr-1].communicate()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
184 retcode = processes[ptr-1].poll()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
185 if retcode or len(stderrdata) > 0:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
186 stop_err(stderrdata)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
187
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
188 return stdoutdata
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
189
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
190
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
191 class ReportEngine(object):
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
192
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
193 def __init__(self): pass
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
194
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
195 def __main__(self):
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
196
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
197
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
198 ## *************************** Parse Command Line *****************************
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
199 parser = MyParser(
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
200 description = 'FFP (Feature frequency profile) is an alignment free comparison tool',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
201 usage = 'python ffp_phylogeny.py [input_files] [output file] [options]',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
202 epilog="""Details:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
203
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
204 FFP (Feature frequency profile) is an alignment free comparison tool for phylogenetic analysis and text comparison. It can be applied to nucleotide sequences, complete genomes, proteomes and even used for text comparison.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
205
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
206 """)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
207
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
208 parser.set_defaults(row_limit=0)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
209 # Don't use "-h" , it is reserved for --help!
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
210
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
211 parser.add_option('-t', '--type', type='choice', dest='type', default='text',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
212 choices=['amino','nucleotide','text'],
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
213 help='Choice of Amino acid, nucleotide or plain text sequences to find features in')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
214
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
215 parser.add_option('-l', '--length', type='int', dest='length', default=6,
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
216 help='Features (any string of valid characters found in data) of this length will be counted. Synonyms: l-mer, k-mer, n-gram, k-tuple')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
217
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
218 #parser.add_option('-n', '--normalize', dest='normalize', default=True, action='store_true',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
219 # help='Normalize counts into relative frequency')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
220
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
221 parser.add_option('-m', '--multiple', dest='multiple', default=False, action='store_true',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
222 help='By default all sequences in a fasta file be treated as 1 sequence to profile. This option enables each sequence found in a fasta file to have its own profile.')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
223
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
224 parser.add_option('-M', '--metric', type='string', dest='metric',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
225 help='Various metrics to measure count distances by.')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
226
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
227 parser.add_option('-x', '--taxonomy', type='string', dest='taxonomy',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
228 help='Taxanomic label for each profile/sequence.')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
229
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
230 parser.add_option('-d', '--disable', dest='disable', default=False, action='store_true',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
231 help='By default amino acid and nucleotide characters are grouped by functional category (protein or purine/pyrimidine group) before being counted. Disable this to treat individual characters as distinct.')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
232
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
233 parser.add_option('-a', '--abbreviate', dest='abbreviate', default=False, action='store_true',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
234 help='Shorten tree taxonomy labels as much as possible.')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
235
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
236 parser.add_option('-s', '--similarity', dest='similarity', default=False, action='store_true',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
237 help='Enables pearson correlation coefficient matrix and any of the binary distance measures to be turned into similarity matrixes.')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
238
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
239 parser.add_option('-f', '--filter', type='choice', dest='filter', default='none',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
240 choices=['none','f','n','e','freq','norm','evd'],
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
241 help='Choice of [f=raw frequency|n=normal|e=extreme value (Gumbel)] distribution: Features are trimmed from the data based on lower/upper cutoff points according to the given distribution.')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
242
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
243 parser.add_option('-L', '--lower', type='float', dest='lower',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
244 help='Filter lower bound is a 0.00 percentages')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
245
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
246 parser.add_option('-U', '--upper', type='float', dest='upper',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
247 help='Filter upper bound is a 0.00 percentages')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
248
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
249 parser.add_option('-o', '--output', type='string', dest='output',
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
250 help='Path of output file to create')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
251
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
252 parser.add_option('-T', '--tree', dest='tree', default=False, action='store_true', help='Generate Phylogenetic Tree output file')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
253
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
254 parser.add_option('-v', '--version', dest='version', default=False, action='store_true', help='Version number')
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
255
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
256 # Could also have -D INT decimal precision included for ffprwn .
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
257
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
258 options, args = parser.parse_args()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
259
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
260 if options.version:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
261 print VERSION_NUMBER
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
262 return
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
263
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
264 import time
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
265 time_start = time.time()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
266
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
267 try:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
268 in_files = args[:]
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
269
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
270 except:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
271 stop_err("Expecting at least 1 input data file.")
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
272
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
273
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
274 #ffptxt / ffpaa / ffpry
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
275 if options.type in 'text':
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
276 command = 'ffptxt'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
277
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
278 else:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
279 if options.type == 'amino':
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
280 command = 'ffpaa'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
281 else:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
282 command = 'ffpry'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
283
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
284 if options.disable:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
285 command += ' -d'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
286
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
287 if options.multiple:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
288 command += ' -m'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
289
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
290 command += ' -l ' + str(options.length)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
291
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
292 if len(in_files): #Note: app isn't really suited to stdio
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
293 command += ' "' + '" "'.join(in_files) + '"'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
294
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
295 #ffpcol / ffpfilt
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
296 if options.filter != 'none':
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
297 command += ' | ffpfilt'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
298 if options.filter != 'count':
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
299 command += ' -' + options.filter
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
300 if options.lower > 0:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
301 command += ' --lower ' + str(options.lower)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
302 if options.upper > 0:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
303 command += ' --upper ' + str(options.upper)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
304
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
305 else:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
306 command += ' | ffpcol'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
307
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
308 if options.type in 'text':
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
309 command += ' -t'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
310
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
311 else:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
312
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
313 if options.type == 'amino':
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
314 command += ' -a'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
315
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
316 if options.disable:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
317 command += ' -d'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
318
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
319 #if options.normalize:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
320 command += ' | ffprwn'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
321
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
322 #Now create a taxonomy label file, ensuring a name exists for each profile.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
323 taxonomyNames = getTaxonomyNames(options.type, options.multiple, options.abbreviate, in_files, options.taxonomy)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
324 taxonomyTempFile = getTaxonomyFile(taxonomyNames)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
325 # -p = Include phylip format 'infile' of the taxon names to use. Very simple, just a list of fasta identifier names.
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
326 command += ' | ffpjsd -p ' + taxonomyTempFile
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
327
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
328 if options.metric and len(options.metric) >0 :
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
329 command += ' --' + options.metric
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
330 if options.similarity:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
331 command += ' -s'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
332
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
333 # Generate Newick (.nhx) formatted tree if we have at least 3 taxonomy items:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
334 if options.tree:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
335 if len(taxonomyNames) > 2:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
336 command += ' | ffptree -q'
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
337 else:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
338 stop_err("For a phylogenetic tree display, one must have at least 3 ffp profiles.")
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
339
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
340 result = check_output(command)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
341 with open(options.output,'w') as fw:
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
342 fw.writelines(result)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
343 os.remove(taxonomyTempFile)
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
344
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
345 if __name__ == '__main__':
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
346
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
347 time_start = time.time()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
348
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
349 reportEngine = ReportEngine()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
350 reportEngine.__main__()
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
351
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
352 print('Execution time (seconds): ' + str(int(time.time()-time_start)))
eb6e5e78a066 Uploaded
damion
parents:
diff changeset
353