I think I'm getting the hang of threading, but I'd appreciate if someone could
double check me. I'm interested in speed, but also is it in good PDL style?

I need to calculate 'closeness' scores for each location in a 2 dimensional
piddle .

For example, given the piddle
[
 [1 0 0 1]
 [0 0 0 0]
 [0 1 1 0]
 [0 0 1 0]
 [0 0 1 1]
]

The weights should be

[
 [10  8  8 10]
 [ 9  9  9  9]
 [ 8 10 10  8]
 [ 7  9 10  9]
 [ 6  8 10 10]
]

Every time I got a hit, then it's score 10. The cell above and below the hit
is scored 9, the cell above and below that is 8 and so on.

This is the routine that I've come up with:

sub calcscore {
    my $f     = $_[0];
    my @score = @{ $_[1] };

    # create a new piddle to store the results, the same size as the input
    my $r = zeroes dims $f;

    # record the width of the piddle.

    my $max = ( dims $f)[1] - 1;

    #create an empty array of piddles of the right size

    my @got;

    @got[ 2 * ( scalar @score - 1 ) ] = undef;

    # $got[0] is those which are hits

    $got[0] = whichND( $f != 0 );
    for my $i ( 1 .. scalar @score ) {
        $got[$i] = null;
        my $tmp    = null;
        my $new    = null;
        my $change = null;

        #calculate $got[+1] as those where the hit is 1 above
        $tmp .= $got[ $i - 1 ];
        $tmp->slice('1')--;

        # remove those which have gone off the edge
        $change = $tmp->slice('1') >= 0;
        $got[$i] .=
          $tmp->where( $change->dummy( 1, 2 )->transpose )
          ->reshape( 2, $change->sum );

        $got[ -$i ] = null;
        $tmp        = null;
        $new        = null;
        $change     = null;

        #repeat for -1 where the hit is 1 below, and the other edge

        $tmp .= $got[ -$i + 1 ];
        $tmp->slice('1')++;
        $change .= $tmp->slice('1') <= $max;
        $got[ -$i ] .=
          $tmp->where( $change->dummy( 1, 2 )->transpose )
          ->reshape( 2, $change->sum );
    }

    # use the @got's to score each item. I do it in reverse so that
    # the overwrites are correcting earlier further aways
    foreach my $i ( reverse( 0 .. scalar @score ) ) {
        my $res = $r->indexND( $got[$i] );
        $res .= $score[$i];

        $res = $r->indexND( $got[ -$i ] );
        $res .= $score[$i];
    }
    return $r;
}

_______________________________________________
Perldl mailing list
[email protected]
http://mailman.jach.hawaii.edu/mailman/listinfo/perldl

Reply via email to