package GIFgraph::EvenlySpaced;
use strict;
use MRP::BaseClass;
use vars qw(@ISA %fields $AUTOLOAD $VERSION);
$VERSION = 1.0;
sub AUTOLOAD {
my $thing = shift;
my ($package, $function) = $AUTOLOAD =~ m/^(.*)::([^:]+)$/;
return if $function eq 'DESTROY';
if(ref($thing)) {
return $thing->_DelegateGraph->$function(@_);
}
# my $super = join '::', 'SUPER', $function;
# return $thing->$super(@_);
die "Could not find $AUTOLOAD via $thing ";
}
sub new {
my $class = shift;
my $graph = shift;
my $self = new MRP::BaseClass;
$self->rebless($class);
$self->_DelegateGraph($graph);
return $self;
}
sub plot {
my ($self, $data) = @_;
my $fudge = $self->fudge;
my @processed;
my @x = @{$data->[0]};
my @distances;
my ($min, $max) = ($x[0], $x[$#x]);
my $len = $max-$min;
foreach my $i (1 .. $#x) {
$distances[$i-1] = $x[$i] - $x[$i-1];
}
my @sdist = sort { $a<=>$b } @distances;
my $sd = shift @sdist;
while(@sdist) {
my $nd = shift @sdist;
my $diff = $nd/$sd;
$diff = $diff - int($diff);
$diff = 1-$diff if $diff > 0.5;
next if $diff < $fudge;
my $rat = $nd/$sd;
my $continue = 1;
for(my $ax = 2; $continue; $ax++) {
my $yx = $ax*$rat;
if($yx !~ /\./) {
$sd = $nd/$yx;
$continue = 0;
}
}
}
my $lowest = shift @x;
my $column = 0;
for(my $newX = $min; ($newX-$sd) < $max; $newX+=$sd) {
if($newX >= $lowest) {
foreach my $series (0 .. $#$data) {
push @{$processed[$series]}, $data->[$series][$column];
}
$column++;
$lowest = shift @x;
} else {
foreach my $series (0 .. $#$data) {
push @{$processed[$series]}, undef;
}
}
}
local $^W = undef;
return $self->_DelegateGraph->plot(\@processed);
}
sub isa {
my ($thing, $type) = @_;
return $thing->_DelegateGraph->isa($type) || $thing->SUPER::isa($type);
}
BEGIN {
@ISA = qw(MRP::BaseClass);
%fields = (
fudge => 0.1,
_DelegateGraph => undef,
);
GIFgraph::EvenlySpaced->check4Clashes;
}
$VERSION;
__END__
=head1 NAME
GIFgraph::EvenlySpaced - spaces the data points evenly
=head1 DESCRIPTION
This module wraps a GIFgraph object so that the data points become
numericaly spaced (aproximately).
=head1 SYNOPSIS
Wrapps a GIFgraph object (probably a GIFgraph::lines) so that the x
values are spaced numericaly. Use exactly as your GIFgraph object. Due
to a problem I had with AUTOLOAD, it must be the outer wrapper class.
=head1 Use
$graph = new GIFgraph::lines(400,300);
$es = new GIFgraph::EvenlySpaced($graph);
or
$graph = new GIFgraph::lines(400,300);
$withmap = new GIFgraph::WithMap($graph);
$es = new GIFgraph::EvenlySpaced($withmap);
or even
$es = new GIFgraph::EvenlySpaced(new GIFgraph::WithMap(new GIFgraph::lines(400,300)));
etc. etc. etc.
=head1 Functions
=over
=item new
Returns a new GIFgraph::EvenlySpaced object
$es = new GIFgraph::EvenlySpaced($parentGraph);
where $parentGraph is any object that behaves like a GIFgraph::lines
type object such as a GIFgraph::WithMap.
=item plot
This function is overridden to space the data numericaly along the
x-axis.
=back
=head1 Fields
=over
=item fudge
This is a fudge factor used in checking whether one number roughly
devides into another. It defaults to 0.1 but if it is obviously doing
silly things then change it. Good luck - I don't realy know how it
works.
=back
=head1 Guts
This module uses MRP::BaseClass to implement member access functions.
To make the 'parent' object behave as if it the super class I have
done some magic with AUTOLOAD. This has produced the restriction that
you can not wrap an EvenlySpaced object inside another - such as
WithMap - that also uses magic.
@ISA does not include the parent type as it is not known. The isa()
method is overridden to account for this.
=head1 AUTHOR
Matthew Pocock mrp@sanger.ac.uk