Angharad has asked for the wisdom of the Perl Monks concerning the following question:

I'm not entirely sure what the best way to explain this is, but here goes. I'm trying to create a graph. i have a text file that looks something like this
-70.6 -27.5 -60.8 52.9 -123.0 -132.9 110.1 119.9 -62.4 -45.6
I am currently trying to write a perl script to do the following

Convert the numbers so instead of being between -180 and 180 they are between 0 and 360.
Place the resulting x, y values into blocks of 5. So, now if we have a value of 12.3 it's now placed in the '10-15' block (I hope that makes sense).
Create a two dimensional array, and using the blocked x y values, increment the corresponding element of the array by one
This is what I have managed so far.

#!/usr/bin/perl use strict; use warnings; my $input = $ARGV[0]; my $x = 0; my $y = 0; my $zeroed_x = 0; my $zeroed_y = 0; my $binned_x = 0; my $binned_y = 0; my @binarray = (); open(INPUT, "$input") || die "Oops! Can't open INPUT file: $!\n"; while(<INPUT>) { $x = substr($_, 0, 6); $y = substr($_, 7, 6); $zeroed_x = ConvertToFromZero($x); $zeroed_y = ConvertToFromZero($y); $binned_x = BinAngles($zeroed_x); $binned_y = BinAngles($zeroed_y); $binarray[$binned_x][$binned_y]++; } for(my $i = 0; $i < @binarray; $i++) { for(my $j = 0; $j < @binarray; $j++) { print "$binarray[$i][$j]\n"; } } ###################################################### sub ConvertToFromZero { my ($axis) = @_; my $zeroed_axis = 0; $zeroed_axis = 180 + $axis; return($zeroed_axis); } ####################################################### sub BinAngles { my ($axisforbin) = @_; my $binnedaxis = 0; $binnedaxis = int($axisforbin/5); return($binnedaxis); }
I get the following error which I don't understand (google doesn't help)
Use of uninitialized value in concatenation (.) or string at ./script. +pl line 34, <INPUT> line 22.
Any suggestions much appreciated.

Replies are listed 'Best First'.
Re: Problems processing data for graph
by tlm (Prior) on May 04, 2005 at 12:24 UTC

    I wrote a brief description on how to do this problem here. The error you are getting is probably because some of your bins are not initialized. Put this in your code before the print statement:

    $binarray[ $i ][ $j ] ||= 0;

    the lowliest monk

Re: Problems processing data for graph
by Animator (Hermit) on May 04, 2005 at 12:17 UTC

    My first guess is that your printing-loop is incorrect.

    for(my $i = 0; $i < @binarray; $i++) { for(my $j = 0; $j < @binarray; $j++) { print "$binarray[$i][$j]\n"; } }
    Is it a fact that the amount of rows is the same as the aoount of columns? (at all times that is).

    If it isn't, then you need something like: for (my $j = 0; $j < @{ $binarray[$i] }; ...

    Update: Also you are not getting an error, you are getting a warning. And if you want some more information about the erros/warnings you get, you can look in `perldoc perldiag` (the perldiag pod), and/or add 'use diagnostics' to your code. (note the last one should not be used in production code (that is to say, code that is finished))

Re: Problems processing data for graph
by polettix (Vicar) on May 04, 2005 at 13:51 UTC
    Range -180 .. 180 transformed into 0 .. 360 smells like angles. If this is the case, simply adding 180 will invert your phase, so you'd probably better do something like:
    # Add a complete round angle, i.e. 360 degrees $angle += 360 if ($angle < 0);
    unless you actually want to invert phase. Or unless they're not angles :)

    Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

    Don't fool yourself.

      In this case adding 180 amounts to the first part of the standard binning transformation of subtracting the minimum value, and dividing by the bin size. In fact the OP's two routines ConvertToFromZero and BinAngles just spread this transformation over two subroutines.

      the lowliest monk

        Oh, I now see they're angles indeed. What I want to point out is that the OP is doing a 180 degrees translation, while he could mean to evaluate the Principal Argument, in which case should use the transformation I propose above.

        Of course, if the problem is only that of binning, for example to produce some graphics, it all reduces to choosing the correct x-axis; OTOH, if the OP wants to use these angles for some evaluations (e.g. sin, cos, stability of a system, whatever) he'd better use the correct angle wrapping function.

        Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

        Don't fool yourself.
Re: Problems processing data for graph
by Angharad (Pilgrim) on May 04, 2005 at 12:35 UTC
    Thank you both for your suggestions. They are much appreciated. As a general question if anyone would like to answer ... I know that theres 'more than one way to do it in perl, but is the approach I used a reasonably sensible one in your opinion?
    Thanks again
      #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @binarray; while (<DATA>) { my ($x,$y)=split / +/; my $ax = [ (0) x 72 ]; my $ay = [ (0) x 72 ]; $ax->[int ($x+180) / 5] = 1; $ay->[int ($y+180) / 5] = 1; push @binarray, [$ax, $ay]; } print Dumper (\@binarray); __DATA__ -70.6 -27.5 -60.8 52.9 -123.0 -132.9 110.1 119.9 -62.4 -45.6


      holli, /regexed monk/

      I think your code is fine, though it could be made more succinct without sacrificing clarity, and it has a strong "C accent". :-). Here's how I would "perlify" it:

      use strict; use warnings; my $input = shift; my $min = -180; my $range = 360; my $bin_size = 5; my $n_bins = $range/$bin_size; my @binarray = map [ ( 0 ) x $n_bins ], 1..$n_bins; open my $in, $input or die "Oops! Can't open $input: $!\n"; while ( <$in> ) { my @indices = map to_index( $_ ), split; $binarray[$indices[ 0 ]][$indices[ 1 ]]++; } close $in or die "Failed to close $input: $!\n"; for my $row ( @binarray ) { print "$_\n" for @$row; } sub to_index { return ( $_[ 0 ] - $min )/$bin_size; }

      the lowliest monk

        Thanks. Yeah, well my strongest programming language is C, and I have been using it for a lot longer than I have been using perl (although i would not claim to be an expert at C even and am certainly a novice at perl!) so I guess its not surprising my code is a bit 'C' like in nature :)

        Thanks for the tips. I'll make a perl programmer yet (in about a decade or so maybe ... lol.)

      ... but is the approach I used a reasonably sensible one in your opinion?

      You have only described the manipulations you are doing to create your graph. Without some idea about what the raw data represents and what you are hoping to discover (or just show) with your graph, it is impossible to say whether your manipulations are good or not.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about question the status quo. Questioning authority".
      The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: Problems processing data for graph
by Angharad (Pilgrim) on May 04, 2005 at 14:12 UTC
    Thanks again for your comments. The data indeed represents angles. All help and suggestions much appreciated :)