=head1 NAME

iPE::Smoother - Abstract base class for all smoother classes.

=head1 DESCRIPTION

This class does nothing but define the stub functions expected for all Smoothers.

=head1 FUNCTIONS

=over 8

=cut

package iPE::Smoother;
use iPE;
use strict;

=item new (data)

Instantiates a new smoother.  The smoother will receive the data included in the gHMM XML file.

=cut
sub new {
    my ($class, $data) = @_;
    my $this = bless {}, $class;

    $this->{data_} = $data if( defined($data));
    $this->{data_} = ""    if(!defined($data));
    $this->init;

    return $this;
}

=item init ()

Initialize the parameters of the smoother given by data.  This is optionally implemented in subclasses and empty in the base class.

=cut
sub init {}

=item data ()

Returns the data attribute that this smoother was instantiated with in the gHMM XML file.

=cut
sub data { shift->{data_} }


=item smoothAref (aref[, biasedSamples])

Smooths a series of numbers in an array reference.  The array must be flat.  You may pass in a series of array references or flatten your array reference to get all of the data in a single call.  

If the entire distribution is biased by some amount not present in the hash reference, pass the total samples (including those in the hash) in the biasedSamples argument.

=cut
sub smoothAref { 
    die __PACKAGE__.": smoothArray unimplemented for ".ref($_[0])."\n"; 
}

=item smoothHref (href[, biasedSamples])

Smooths all keys in a hash reference.  If the entire distribution is biased by some amount not present in the hash reference, pass the total samples (including those in the hash) in the biasedSamples argument.

=cut
sub smoothHref {
    die __PACKAGE__.": smoothHref unimplemented for ".ref($_[0])."\n";
}

=item getArefTotal (aref), getHrefTotal (href)

This function simply totals up the size of the array or hash reference.  This should be used at the beginning of smothing so that it can be renormalized at the end (see below).

=cut
sub getArefTotal {
    my ($this, $aref) = @_;
    my $tot = 0;
    for (my $i = 0; $i < scalar(@$aref); $i++) {
        $tot += $aref->[$i] if(defined($aref->[$i]));
    }
    return $tot;
}

sub getHrefTotal {
    my ($this, $href) = @_;
    my $tot = 0;
    for my $key (keys (%$href)) {
        $tot += $href->{$key};
    }
    return $tot;
}

=cut

=item renormalizeAref (aref, oldN), renormalizeHref(href, oldN)

This is a function that should used by all smoothers at the end of the routine to restore the original density of the distribution.  This will restore the original density of the submodel, so that in normalizing multiple models, the relative densities will be correct.

=cut
sub renormalizeAref {
    my ($this, $aref, $oldN) = @_;
    my $newN = $this->getArefTotal($aref);

    return if($newN == 0);
    for (my $i = 0; $i < scalar(@$aref); $i++) {
        $aref->[$i] *= $oldN/$newN;
    }

}

sub renormalizeHref {
    my ($this, $href, $oldN) = @_;
    my $newN = $this->getHrefTotal($href);

    return if($newN == 0);
    for my $key (keys (%$href)) {
        $href->{$key} *= $oldN/$newN;
    }
}

=back

=head1 SEE ALSO

L<iPE> L<iPE::Model::Emission> L<iPE::Model::DurationDistribution>

=head1 AUTHOR

Bob Zimmermann (rpz@cse.wustl.edu).

=cut
1;
