The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
#!/usr/bin/env perl
# created on 2016-07-26

use warnings;
use strict;
use 5.010;
use IO::Handle ();

use Bio::Gonzales::Seq::Util qw/seq_apply/;
use Parallel::ForkManager;
use Pod::Usage;
use Getopt::Long;

my %opt = ( processes => 4 );
GetOptions( \%opt, 'help', 'processes|p=i', 'tasks|t=s' ) or pod2usage(2);

pod2usage( -exitval => 0, -verbose => 2 ) if ( $opt{help} );

my $ref_f = shift @ARGV;
my $cmd = join( " ", @ARGV );

my %tasks;

if($opt{tasks}) {
  for my $tr (split(/,/, $opt{tasks})) {
    my @range = split /\.\.|-/, $tr;
    die "invalid task range $tr" if(@range > 2);

    @range = reverse @range if(@range == 2 && $range[0] > $range[1]);
    $range[1] = $range[0] if(@range == 1);
    map { $tasks{$_}++ } $range[0] .. $range[1];
  }
}

my $pm = Parallel::ForkManager->new( $opt{processes} );

my $seq_num = 0;
seq_apply(
  $ref_f,
  sub {
    my ( $info, $scmd ) = @_;

    $seq_num++;
    return if(%tasks && !$tasks{$seq_num});

    my $pid = $pm->start and return;

    $scmd =~ s/\{seq_num\}/$seq_num/;

    ( my $seq_id = $info->{id} ) =~ y/-0-9A-Za-z_.%~/_/sc;
    my $num_digits = length("$info->{num}");
    my $seq_num_fmt = sprintf( "%0${num_digits}d", $seq_num );
    $scmd =~ s/\{seq_fn\}/$seq_num_fmt.$seq_id/;

    say STDERR "[$$] $seq_num: running $scmd";
    system($scmd) == 0 or die "system failed: $?";
    $pm->finish;
  },
  $cmd
);

$pm->wait_all_children;