Rewrite random lines tool. Does two passes through input file: first pass determines line offsets/count, offsets are randomly removed, second pass writes out lines by seeking to remaining offsets. The random seed can now be optionally specified.

This commit is contained in:
Daniel Blankenberg
2011-09-23 13:49:33 -04:00
parent c1055e4ae8
commit 09e8a94a5a
2 changed files with 77 additions and 2 deletions
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env python
#Dan Blankenberg
#Selects N random lines from a file and outputs to another file, maintaining original line order
#allows specifying a seed
#does two passes to determine line counts and offsets, and then to output contents
import optparse, random
def __main__():
#Parse Command Line
parser = optparse.OptionParser()
parser.add_option( '-s', '--seed', dest='seed', action='store', type="string", default=None, help='Set the random seed.' )
(options, args) = parser.parse_args()
assert len( args ) == 3, "Invalid command line specified."
input = open( args[0] )
output = open( args[1], 'wb' )
num_lines = int( args[2] )
assert num_lines > 0, "You must select at least one line."
if options.seed is not None:
random.seed( options.seed )
#get line offsets
line_offsets = []
while True:
offset = input.tell()
if input.readline():
line_offsets.append( offset )
else:
break
total_lines = len( line_offsets )
assert num_lines <= total_lines, "Error: asked to select more lines (%i) than there were in the file (%i)." % ( num_lines, total_lines )
#get random line offsets
while len( line_offsets ) > num_lines:
line_offsets.pop( random.randint( 0, len( line_offsets ) - 1 ) )
#write out random lines
for line_offset in line_offsets:
input.seek( line_offset )
output.write( input.readline() )
input.close()
output.close()
print "Kept %i of %i total lines." % ( num_lines, total_lines )
if options.seed is not None:
print 'Used random seed of "%s".' % options.seed
if __name__=="__main__": __main__()
+26 -2
View File
@@ -1,9 +1,25 @@
<tool id="random_lines1" name="Select random lines">
<tool id="random_lines1" name="Select random lines" version="2.0.0">
<description>from a file</description>
<command interpreter="python">randomlines.py $input $num_lines $out_file1</command>
<command interpreter="python">random_lines_two_pass.py "${input}" "${out_file1}" "${num_lines}"
#if str( $seed_source.seed_source_selector ) == "set_seed":
--seed "${seed_source.seed}"
#end if
</command>
<inputs>
<param name="num_lines" size="5" type="integer" value="1" label="Randomly select" help="lines"/>
<param format="txt" name="input" type="data" label="from"/>
<conditional name="seed_source">
<param name="seed_source_selector" type="select" label="Set a random seed">
<option value="no_seed" selected="True">Don't set seed</option>
<option value="set_seed">Set seed</option>
</param>
<when value="no_seed">
<!-- Do nothing here -->
</when>
<when value="set_seed">
<param name="seed" type="text" label="Random seed" />
</when>
</conditional>
</inputs>
<outputs>
<data format="input" name="out_file1" metadata_source="input"/>
@@ -12,8 +28,16 @@
<test>
<param name="num_lines" value="65"/>
<param name="input" value="1.bed"/>
<param name="seed_source_selector" value="no_seed"/>
<output name="out_file1" file="1.bed"/>
</test>
<test>
<param name="num_lines" value="1"/>
<param name="input" value="1.bed"/>
<param name="seed_source_selector" value="set_seed"/>
<param name="seed" value="asdf"/>
<output name="out_file1" file="1_bed_random_lines_1_seed_asdf_out.bed"/>
</test>
</tests>
<help>