Handy progress monitor

From BioPerl
Jump to: navigation, search

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;
}

CPAN

[back to top]


Personal tools
Namespaces
Variants
Actions
Main Links
documentation
community
development
Toolbox