in reply to Prob with 'while' loop and subroutine calling

The edited version of the code contains ## comments where I made changes or inserted comments.

Note in particular that the array @Y2 was renamed to @y2! That (presumed) typo was picked up by use strict;.

I don't see any particular issue with the while loop. Perhaps you could describe the problem that you are having with it?

#use GD; use strict; use warnings; my @x1; my @y1; my $max1; my $min1; my $lines = LoadFile ("fwd.stb", \@x1, \@y1, \$min1, \$max1); # Define constants my $X1start = 50+20; # X-axis my $Y1start = 300; # X-axis my $X1end = 450+$lines-400; # X-axis my $Y1end = 300; # X-axis my $X2start = 50+20; my $Y2start = 100; my $X2end = 50+20; my $Y2end = 300; # create a new image my $im = new GD::Image($X1end+50,$Y2end+100); # allocate some colors my $white = $im->colorAllocate(255,255,255); my $green = $im->colorAllocate(0,255,0); my $black = $im->colorAllocate(0,0,0); my $red = $im->colorAllocate(255,0,0); my $blue = $im->colorAllocate(0,0,255); # set the caption for the graph $im->string(gdLargeFont,int($lines/2)-50,20,"ENERGY GRAPH",$black); # draw the y-axis & x-axis $im->line($X2start,$Y2start,$X2end,$Y2end,$black); $im->line($X1start,$Y1start,$X1end,$Y1end,$black); # set the caption for x-axis and y-axis $im->string(gdLargeFont,int($lines/2)-50,335,"NUCLEOTIDE POSITION",$bl +ack); $im->stringUp(gdLargeFont,5,260,"FREE ENERGY(delta G)",$black); $im->string(gdSmallFont,int($lines/2)+100,20," Genomic Sequence ----- +--",$red); $im->string(gdSmallFont,int($lines/2)+100,40," Shuffled Sequence ----- +--",$blue); my @x2; my @y2; ## Was @Y2 - probably a bug. Caught by use strict my $min2; my $max2; $lines = LoadFile ("total_shuffle.stb", \@x1, \@y1, \$min2, \$max2); my $min = $min1 <= $min2 ? $min1 : $min2; my $max = $max1 >= $max2 ? $max1 : $max2; my @y = @y1; my @x = @x1; graph(); @y = @y2; @x = @x2; my $png_data = $im->png; open (DISPLAY,"| display -") || die; #open (DISPLAY,">image.jpg") || die; binmode DISPLAY; print DISPLAY $png_data; close DISPLAY; sub graph { # set min and max energy my $minEnergy = $min; my $maxEnergy = $max; # set the length of x-axis and y-axis my $xLen = $X1end-$X1start; my $yLen = $Y2end-$Y2start; # Scaling the values my $Yscale = $yLen/(abs($minEnergy)-abs($maxEnergy)); my $scale = ($minEnergy-$maxEnergy)/5; my $incEnergy = $maxEnergy; while ($incEnergy > $minEnergy) { ##### Prob loop#### my $x1 = $X1start-2; my $y1 = int(((abs($incEnergy)-abs($maxEnergy))*$Yscale)+$Y2st +art); my $x2 = $X1start+2; $im->line($x1,$y1,$x2,$y1,$black); my $displayEnergy = sprintf("%2.1f",$incEnergy); $im->string(gdSmallFont,$x1-35,$y1-10,$displayEnergy,$black); $incEnergy = $incEnergy+$scale; } my $count = 0; ## $count was not declared my $len = @x; # set the length of nucleotide my $posSkip = int(@x/10); # mark 10 points on the position axis my $skipPixel = $xLen/$len; # If the length of the fragment is les +ser than the x-axis for(my $i=0;$i<$len-1;$i++) { my $x1 = int(($i*$skipPixel)+$X1start); my $y1 = int(((abs($y[$i])-abs($maxEnergy))*$Yscale)+$Y2start) +; my $x2 = int((($i+1)*$skipPixel)+$X1start); my $y2 = int(((abs($y[$i+1])-abs($maxEnergy))*$Yscale)+$Y2star +t); ## graph is only called once in this code so $call can only ev +er be undef ##if($call == 0) { $im->line($x1,$y1,$x2,$y2,$red); ##} else { ## $im->line($x1,$y1,$x2,$y2,$blue); ##} $count++; if($count == $posSkip) { $x1 = int(($i*$skipPixel)+$X1start); $y1 = $Y1end-2; $x2 = int(($i*$skipPixel)+$X1start); $y2 = $Y1end+2; ## graph is only called once in this code so $call can onl +y ever be undef ##if($call == 0) { $im->line($x1,$y1,$x2,$y2,$black); $im->string(gdSmallFont,$x1,$y1+10,$i+1,$black); ##} $count = 0; } } ## graph is only called once in this code so $call can only ever b +e undef ## $call++; } ## Common file reading code in sub sub LoadFile { my ($filename, $x, $y, $min, $max) = @_; ## Three parameter open and check result open FILE1,'<', $filename or die "Failed to open $filename: $!"; ## Remove $i from while loop - [-1] is last element while(<FILE1>) { my @value = split(/\s+/,$_); next if 2 != @value; # Skip if bad input line - could die or w +arn push @x, $value[0]-7; push @y, $value[1];
if(@$x1) { $$max = $y->[-1] if $y->[-1] > $max; $$min = $y->[-1] if $y->[-1] < $min;
if(@$x) { $$max = $y->[-1] if $y->[-1] > $$max; $$min = $y->[-1] if $y->[-1] < $$min; } else { $$min = $$max = $y->[-1]; } } return $.; ## Number of lines }

Update bugs fixed - see replies


DWIM is Perl's answer to Gödel

Replies are listed 'Best First'.
Re^2: Prob with 'while' loop and subroutine calling
by cool (Scribe) on Aug 18, 2006 at 21:12 UTC
    Dear GrandFather,

    First of all, thanks for taking so much pain for my problem.

    In the code I posted, mistakenly graph()(line 126) left out while pasting.

    The code I have pasted is working and giving results. But without 'use warning' I don feel confident. And also global variable of this code are interfering with rest of my code(actually this piece is part of a large work).

    For whileloop case, I didn't get, what is prompting it to run over complete array. like it is not written as while (@x) or while ($fh)

    So what I think is, this should run only once when it enters in the sub; when for the first time control enters the loop while($incEnergy > $minEnergy)What is prompting it to return? I know its something v silly that I am not getting, but pl guide me.

    Can you pl explain me how this part of your code is working!! Just briefly, what is the concept behind or some link.. Also while compiling its showing this line

    Global symbol "$x1" requires explicit package name at monk_graph.pl line 150.

    if(@$x1) { $$max = $y->[-1] if $y->[-1] > $max; $$min = $y->[-1] if $y->[-1] < $min; } else { $$min = $$max = $y->[-1];}

      while ($incEnergy > $minEnergy)
      In that while loop there is:
      $incEnergy = $incEnergy+$scale;
      So presumably, incEnergy will grow until it is larger than minEnergy(update: incEnergy will shrink until its less than minEnergy), and the while loop will terminate eventually if $scale is greaterless than zero. But you have:
      $scale = ($minEnergy-$maxEnergy)/5;
      Which is greater? min or max? Normally I'd think the max would be greater, so scale would be negative, and you may have an infinite loop. If the code is correct, then it is confusing. Nevermind. But at least it answers your question on how the loop terminates.
      Global symbol "$x1" requires explicit package name at monk_graph.pl line 150.
      I assume that is supposed to be "@x", not "@$x1" in the code.

      The while loop decrements $incEnergy from $maxEnergy downward in steps of $scale (which is negative) until $incEnergy is less than $minEnergy. It looks fine to me, although it may be a good place for a C type for loop:

      for ($incEnergy = $maxEnergy; $incEnergy > $minEnergy; $incEnergy += $ +scale)

      and omit the $incEnergy = $incEnergy+$scale; at the end of the loop. It looks like the while loop is generating points along an energy axis.

      if(@$x1) { should be if(@$x) {. The test checks to see if @$x contains any elements.

      The LoadFile sub takes a number of reference parameters. The first line in the sub:

      my ($filename, $x, $y, $min, $max) = @_;

      declares the variables and sets them to the parameter values. The last four variables are references. So $$max is the scalar variable that $max refers to. $x and $y are references to arrays and $y->[-1] is the last element of the array refered to by $y. So the line:

      $$max = $y->[-1] if $y->[-1] > $$max;

      means assign the last element of @$Y (the array that $Y refers to) to the scalar that $max refers to if the element is greater than the current maximum. (Note there was an error in this code. See update in previous post.)


      DWIM is Perl's answer to Gödel