ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Welcome to LinuxQuestions.org, a friendly and active Linux Community.

You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!

Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.

If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.

Having a problem logging in? Please visit this page to clear all LQ-related cookies.

Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.

Exclusive for LQ members, get up to 45% off per month. Click here for more info.

I'm using Math::Bezier to create a smooth curve from a set of three x,y coordinates. I'm not having problems with accomplishing that per se, my program does, essentially, what I need it to. The thing is that 1) to get the interpolated curve to go through the correct maximum y-value (which was fed into the module as one of the three control sets) I have to multiply the resulting y-values by 2. And 2) the shape of the curve is wrong. It comes out as a simple, symmetric parabola (p<0). When I graph the same points in Excel using the "XY Scatter With Smooth Lines" function (which uses Bezier interpolation) it comes out perfect, exactly as it should. So, anyone have an idea what's happening?

Let me explain the curves in the linked file. "Control points Alpha" is just the control set I'm using to evaluate my output. In this case the three XY coordinates are (0,0; 208,67.07; 690,0). "(Excel)" means, duh, graphed in Excel. Math::Bezier Alpha corrected y-max is the resulting curve if I multiply all the y-values of Math::Bezier Alpha original by 2. Control points Beta is adding two more control points (104,33.54; 312,33.54), graphed in Excel. And Math::Bezier Beta is the output of Math::Bezier with the two extra control points. The first curve - "control points Alpha (Excel)" - is exactly what I want to see from my perl script. Hopefully, someone has some experience using Math::Bezier and can tell me what I'm doing wrong. I emailed the author but have not received a reply.

Here's my code, though it works, I'm not sure if it's the Math::Bezier that's at fault, or me. It's probably me but I can't find anyone discussing Math::Bezier anywhere.

Code:

#!/usr/bin/perl
use warnings;
use Getopt::Long;
use Getopt::ArgvFile;
use Math::Bezier;
use Math::Round;
@peaks = $ARGV[0];
open ( IN, "@peaks" ) or die "Can't open file: $!";
while (<IN>) {
next if /#/; # remove the header
next if /start/; # including column descriptor
chomp;
my @fields = split ("\t",$_);
print "fixedStep chrom=$fields[0] start=$fields[1] step=1\n";
my $bezier = Math::Bezier->new(0,0,$fields[4],$fields[6],$fields[3],0); # this feeds my control points into the bezier module
my @points = $bezier->curve($fields[3]);
while (@points) {
my ($x,$y) = splice(@points,0,2);
my $ynew = nearest(0.01,($y*2));
print "$ynew\n";
}
}
close IN;

Thanks!

Last edited by captainentropy; 10-15-2013 at 04:40 PM.
Reason: clarity

I think that Excel is trying to fit a curve that passes through a set of points. Math::Bezier is trying to create a curve based on a set of control points as described here. You might want to look at Math::Spline.

Also I really like the idea of a Math::Bizarre module on CPAN.

I think that Excel is trying to fit a curve that passes through a set of points. Math::Bezier is trying to create a curve based on a set of control points as described here. You might want to look at Math::Spline.

Also I really like the idea of a Math::Bizarre module on CPAN.

Thanks smallpond, I'll try out Math::Spline and report back

OK, I modified the program as follows (main part in bold):

Code:

#!/usr/bin/perl
use warnings;
use Getopt::Long;
use Getopt::ArgvFile;
use Math::Spline;
use Math::Derivative;
use Math::Round;
@peaks = $ARGV[0];
open ( IN, "@peaks" ) or die "Can't open file: $!";
while (<IN>) {
next if /#/; # remove the header
next if /start/; # including column descriptor
chomp;
my @fields = split ("\t",$_);
print "fixedStep chrom=$fields[0] start=$fields[1] step=1\n";
require Math::Spline;
my @x=(0,$fields[4],$fields[3]); # control X-values for spline
my @y=(0,$fields[6],0); # control Y-values for spline
$spline = Math::Spline->new(\@x,\@y);
my $iter=0;
while ($iter <= $fields[3]) {
my @ynew = $spline->evaluate($iter);
my @yRound = nearest(0.01,@ynew);
print "@yRound\n";
$iter ++;
}
}
close IN;

The output is not any better than with Math::Bezier. In fact, the y-max for the curve is greater than the y-max I used in the control (one of the three points used as controls) that I fed into the module. And adding more control points makes the curve even worse looking. Here's a graph of the output (orange curve). The one main feature that I would really like to have is the curves go through the maximum x,y point (x:208 y:67.07 in this example).

Perhaps I'm using Math::Spline incorrectly. Any ideas?

Update:10.15.2013. I experimented with adding more control points, which I have to interpolate on my own, and I found a couple more points in certain places along the hypothetical curve get me a lot closer to the Excel ideal. It's probably close enough, but I'll leave this "unsolved" until I complete a few more runs.

Last edited by captainentropy; 10-15-2013 at 05:17 PM.
Reason: update

LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.