Files
galaxy/tools/filters/uniq.py
T
peterjc aafd2d0a51 Add sorting option to Count1 (tools/filters/uniq.xml)
When using this tool to produce a tally table, often want to
have the most common entries listed first - rather than the
sort order coming from the values being counted.
2015-03-13 16:43:02 -04:00

139 lines
4.2 KiB
Python

# Filename: uniq.py
# Author: Ian N. Schenck
# Version: 19/12/2005
#
# This script accepts an input file, an output file, a column
# delimiter, and a list of columns. The script then grabs unique
# lines based on the columns, and returns those records with a count
# of occurences of each unique column (ignoring trailing spaces),
# inserted before the columns.
#
# This executes the command pipeline:
# cut -f $fields | sort | uniq -C
#
# -i Input file
# -o Output file
# -d Delimiter
# -c Column list (Comma Seperated)
import sys
import re
import string
import commands
# This function is exceedingly useful, perhaps package for reuse?
def getopts(argv):
opts = {}
while argv:
if argv[0][0] == '-':
opts[argv[0]] = argv[1]
argv = argv[2:]
else:
argv = argv[1:]
return opts
def main():
args = sys.argv[1:]
try:
opts = getopts(args)
except IndexError:
print "Usage:"
print " -i Input file"
print " -o Output file"
print " -c Column list (comma seperated)"
print " -d Delimiter:"
print " T Tab"
print " C Comma"
print " D Dash"
print " U Underscore"
print " P Pipe"
print " Dt Dot"
print " Sp Space"
print " -s Sorting: value (default), largest, or smallest"
return 0
outputfile = opts.get("-o")
if outputfile == None:
print "No output file specified."
return -1
inputfile = opts.get("-i")
if inputfile == None:
print "No input file specified."
return -2
delim = opts.get("-d")
if delim == None:
print "Field delimiter not specified."
return -3
columns = opts.get("-c")
if columns == None or columns == 'None':
print "Columns not specified."
return -4
sorting = opts.get("-s")
if sorting is None:
sorting = "value"
if sorting not in ["value", "largest", "smallest"]:
print "Unknown sorting option %r" % sorting
return -5
# All inputs have been specified at this point, now validate.
fileRegEx = re.compile("^[A-Za-z0-9./\-_]+$")
columnRegEx = re.compile("([0-9]{1,},?)+")
if not columnRegEx.match(columns):
print "Illegal column specification."
return -4
if not fileRegEx.match(outputfile):
print "Illegal output filename."
return -5
if not fileRegEx.match(inputfile):
print "Illegal input filename."
return -6
column_list = re.split(",",columns)
columns_for_display = "c" + ", c".join(column_list)
commandline = "cut "
# Set delimiter
if delim=='C':
commandline += "-d \",\" "
if delim=='D':
commandline += "-d \"-\" "
if delim=='U':
commandline += "-d \"_\" "
if delim=='P':
commandline += "-d \"|\" "
if delim=='Dt':
commandline += "-d \".\" "
if delim=='Sp':
commandline += "-d \" \" "
# set columns
commandline += "-f " + columns
# we want to remove *trailing* spaces from each field,
# so look for spaces then tab (for first and middle selected columns)
# and replacw with just tab, and remove any spaces at end of the line
# (for the final selected column):
commandline += " " + inputfile + " | sed 's/\ *\t/\t/' | sed 's/\ *$//'"
commandline += " | sort | uniq -c"
# uniq -C puts counts at the start, so we can sort lines by numerical value
if sorting == "largest":
commandline += " | sort -n -r"
elif sorting == "smallest":
commandline += " | sort -n"
# uniq -C produces lines with leading spaces, use sed to remove that
# uniq -C puts a space between the count and the field, want a tab.
# To replace just first tab, use sed again with 1 as the index
commandline += " | sed 's/^\ *//' | sed 's/ /\t/1' > " + outputfile
errorcode, stdout = commands.getstatusoutput(commandline)
print "Count of unique values in " + columns_for_display
return errorcode
if __name__ == "__main__":
main()