Modified sort to allow sorting by multiple columns

This commit is contained in:
Kelly Vincent
2009-09-21 17:02:26 -04:00
parent b25dc1f1e9
commit 33ad975b3f
2 changed files with 42 additions and 108 deletions
+18 -99
View File
@@ -1,113 +1,32 @@
# Filename: sorter.py
# Author: Ian N. Schenck
# Version: 8/22/2005
#
# This script sorts a file based on the inputs:
# -cols - column to sort on
# -order - ASC or DESC-ing order
# -order - ASC- or DESCending order
# -i - input filename
# -o - output filename
import string
import sys
import re
import commands
from os import environ
import os, re, string, sys
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 stop_err( msg ):
sys.stderr.write( "%s\n" % msg )
sys.exit()
def main():
args = sys.argv[1:]
try:
opts = getopts(args)
except IndexError:
print "Usage:"
print " -o Output filename"
print " -i Input filename"
print " -cols Column to sort (base 1)"
print " -order ASC or DESC"
print " -style num or alpha"
return 0
inputfile = sys.argv[1]
outputfile = '-o %s' % sys.argv[2]
order = ('', '-r')[sys.argv[3] == 'DESC']
sort_type = ('','-n')[sys.argv[4] == 'num']
columns = sys.argv[5:]
cols = [ '-k%s,%s'%(n, n) for n in columns ]
except Exception, ex:
stop_err('Error parsing input parameters\n' + str(ex))
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
column = opts.get("-cols")
if column == None or column == 'None':
print "Sort column not specified."
return -3
order = opts.get("-order")
if order == None:
print "Sort order not specified."
return -4
style = opts.get("-style")
if style == None:
style = "num"
# At this point, all command line options have been collected.
# Verify arguments are valid.
fileRegEx = re.compile("^[A-Za-z0-9./\-_]+$")
numberRegEx = re.compile("^[0-9]+$")
sortRegEx = re.compile("^(ASC|DESC)$")
if not fileRegEx.match(outputfile):
print "Illegal output filename."
return -5
if not fileRegEx.match(inputfile):
print "Illegal input filename."
return -6
if not numberRegEx.match(column):
print "Column number not an integer."
return -7
if not sortRegEx.match(order):
print "Sort order must be ASCending or DESCending."
return -8
# Check sort column against max columns in input file.
column = string.atoi(column)
if column > len( open(inputfile).readline().split('\t') ):
print "Column "+str(column)+" does not exist."
return -9
# Everything is kosher.
if order == "DESC":
order = " -r"
else:
order = ""
if style == "num":
style = " -n "
else:
style = " "
# Launch sort.
environ['LC_ALL'] = 'POSIX'
commandline = "sort -f"+style+"-k "+str(column)+" -t $'\t' -o "+outputfile+" "+inputfile+order
errorcode, stdout = commands.getstatusoutput(commandline)
return errorcode
cmd = "sort -f -t $'\t' %s %s %s %s %s" % (sort_type, ' '.join(cols), order, outputfile, inputfile)
try:
os.system(cmd)
except Exception, ex:
stop_err('Error running sort command\n' + str(ex))
if __name__ == "__main__":
main()
+24 -9
View File
@@ -1,14 +1,27 @@
<tool id="sort1" name="Sort" version="1.0.1">
<description>data in ascending or descending order</description>
<command interpreter="python">sorter.py -i $input -o $out_file1 -cols $column -order $order -style $style</command>
<command interpreter="python">
sorter.py
$input
$out_file1
$order
$style
$firstcol
#for $col in $column_set:
${col.column}
#end for
</command>
<inputs>
<param format="tabular" name="input" type="data" label="Sort Query" />
<param name="column" label="on column" type="data_column" data_ref="input" accept_default="true" />
<param name="firstcol" label="on column" type="data_column" data_ref="input" accept_default="true" />
<repeat name="column_set" title="Column selection">
<param name="column" label="on column" type="data_column" data_ref="input" accept_default="true" />
</repeat>
<param name="order" type="select" label="in">
<option value="DESC">Descending order</option>
<option value="ASC">Ascending order</option>
</param>
<param name="style" type="select" label="Flavor">
<param name="style" type="select" label="with flavor">
<option value="num">Numerical sort</option>
<option value="alpha">Alphabetical sort</option>
</param>
@@ -18,18 +31,20 @@
</outputs>
<tests>
<test>
<param name="input" value="1.bed"/>
<param name="column" value="1"/>
<param name="input" value="sort_in1.bed"/>
<param name="firstcol" value="1"/>
<param name="column" value="3" />
<param name="order" value="ASC"/>
<param name="style" value="num"/>
<output name="out_file1" file="sort1_num.bed"/>
<output name="out_file1" file="sort_out1.bed"/>
</test>
<test>
<param name="input" value="7.bed"/>
<param name="input" value="sort_in1.bed"/>
<param name="firstcol" value="3" />
<param name="column" value="1"/>
<param name="order" value="ASC"/>
<param name="style" value="alpha"/>
<output name="out_file1" file="sort1_alpha.bed"/>
<output name="out_file1" file="sort_out2.bed"/>
</test>
</tests>
<help>
@@ -42,7 +57,7 @@
**Syntax**
This tool sorts the dataset on any column in either ascending or descending order.
This tool sorts the dataset on any number of columns in either ascending or descending order (all columns will be ascending or descending).
* Numerical sort orders numbers by their magnitude, ignores all characters besides numbers, and evaluates a string of numbers to the value they signify.
* Alphabetical sort is a phonebook type sort based on the conventional order of letters in an alphabet. Each nth letter is compared with the nth letter of other words in the list, starting at the first letter of each word and advancing to the second, third, fourth, and so on, until the order is established. Therefore, in an alphabetical sort, 2 comes after 100 (1 &lt; 2).