Handy progress monitor
From BioPerl
Contents |
Mark's monitor
Here's a useful little device for monitoring progess as a large number of things (sequences, e.g.) are being stepped through. It's written as a configurator that returns an iterator. Call the iterator on every pass through the loop, it will know when to do the right thing. The callback allows you to get fancy if desired. --MAJ
# dodot() args -- # $every : hashref of { $modulus => $symbol, ... } # (i.e., "every $modulus things, print $symbol...") # $title : print (or whatever) this on the first call # $callback : do this every $modulus things: # $callback->($current_symbol, $current_modulus, $current_count_of_things # sub dodot { my ($every, $title, $callback) = @_; my $i=0; my @every = sort {$b<=>$a} keys %$every; $callback||= sub { print STDERR shift() }; return sub { $i++; $callback->("$title\n") if ($title && ($i==1)); for (@every) { unless ($i % $_) { $callback->($every->{$_},$_,$i); last; } }; }; }
Use it like so:
my $dot = dodot( { 10 => '.', 100 => '|', 1000 => '@' }, 'Enormo' ); while (my $seq = $seqio->next_seq) { # doing doing doing... $dot->(); }
to produce something like:
Enormo .........|.........|.........|.........|.........|.........|.........|.........|.........|.... .....@.........|.........|.........|.........|.........|.........|.........|.........|........ .|.........@.........|.........|.........|.........|.........|
For nice linebreaks, try
my $dot = dodot( { 10 => '.', 100 => '|', 701 => "\n", 1000 => '@' }, 'Enormo');
to get
Enormo .........|.........|.........|.........|.........|.........|.........| .........|.........|.........@.........|.........|.........|.........| .........|.........|.........|.........|.........|.........@.........| .........|.........|.........|.........|
To start over for a new routine, just create a new iterator:
sub validate { my @seqs = @_; my $vdot = dodot( { 500 => '.' }, 'validating' ); while ($_ = $seqio->next_seq) { $vdot->(); # validate validate validate } return @valid; } sub preprocess { my @seqs = @_; my $pdot = dodot( { 500 => '.' }, 'preprocessing'); while ($_ = $seqio->next_seq) { $pdot->(); # preprocess preprocess preprocess } return @processed; } ## main ... my $aln = $alnio->next_aln; my @valid_processed = preprocess( validate($aln->each_seq) ); ...
Russell's monitor
Here's the monitor I use. Gives a "wget"-like progress display with percentage of the job remaining.
sub progress_bar { my ( $got, $total, $width, $char ) = @_; $width ||= 25; $char ||= '='; my $num_width = length $total; sprintf "|%-${width}s| Processed %${num_width}s rows of %s (%.2f%%)\r", $char x (($width-1)*$got/$total). '>', $got + 1, $total, 100*$got/+$total; } # as an example of how it's used, # here's what I did when I was processing # a very large amount of mass-spec data $mass_count = keys (%mass_data); $mass_num = 0; foreach $mass (sort {$a <=> $b} (keys %mass_data)){ # do stuff with your data $t2mdata .= pack("f",$mass); # show progress print progress_bar( $mass_num++, $mass_count, 25, '=' ); }
Term::ProgressBar
Or use a cpan module that you can use as simple or as complex as you want.
use Term::ProgressBar; my $max = 10; my $progressBar = Term::ProgressBar->new( { name => 'Running Test', count => $max, ETA => 'linear', max_update_rate => 1, remove => 1, } ); for my $i (1..$max){ $progressBar->update ($i); sleep 1; }