=head1 NAME

iPE::Model - Base class for all models in iParameterEstimation.

=head1 DESCRIPTION

This is the base class for all models in iParameterEstimation.  These are all initialized with XML tags and associated attributes.  The new function is passed the start tag itself along with the attributes in a hash reference, as they read in the XML file.

If anything besides the XML start tag needs to be parsed for initialization (parsed character data between the start and end tags or other tags below the heirarchy), derived classes must implement the handle_submodels method to take in any nested models in the XML document.

Alternatively, if nested tags are within your model, you can create another class derived from iPE::Model, and parse the start tags via a new function.

=cut

package iPE::Model;
require Exporter;
use iPE::Smoother;
use iPE::Smoother::Null;
use iPE::Smoother::Pseudocount;
use iPE::Smoother::Gaussian;
use iPE::Smoother::Kernel;
use base ("iPE::XML::Object", "Exporter");
use strict;

=head1 CONSTANTS

=over 8

=item getSmootherClass (string), defaultSmoothing (), defaultSmoothingData ()

The getSmootherClass function will return the class of the smoother as given by the name as it appears in the gHMM XML file.

defaultSmoothing and defaultSmoothingData () are the smoothing method and associated data that is used when nothing is specified in the gHMM file.  

The smoother is automatically constructed in the Model base class.  The default smoother for any particular model can be altered by overriding these functions, and the smoother still does not have to be manually constructed.

=back

=cut
sub defaultSmoothing { "none" }
sub defaultSmoothingData { 0 }

sub getSmootherClass {
    my ($smoothing) = @_;

    if($smoothing eq "none") {
        return "iPE::Smoother::Null";
    }
    elsif($smoothing eq "kernel") {
        return "iPE::Smoother::Kernel";
    }
    elsif($smoothing eq "gaussian") {
        return "iPE::Smoother::Gaussian";
    }
    else { die __PACKAGE__.": unknown smoother: $smoothing\n"; }
}


=head1 FUNCTIONS

=over 8

=item new(tag, attributes, data, element)

The new function is basically passed the start tag of the object via the tag string and the attributes hash reference.  The hash reference mirrors exactly the attributes and their values in the XML file.  For example, if the tag were

    <marble color="red" size="1" />

    then the following would be true:

    $tag eq "marble"
    $att->{color} eq red
    $att->{size} == 1

When deriving from this class, it is important to note that as always, perl does not automatically call the superclass constructor.  The following should be included in your derived class:

    sub new {
        my $this = shift;
        my ($tag, $att, $data, $element) = @_;
        $this->SUPER::init(@_);

        #initialization here.
    }

=cut
sub new {
    my $class = shift;
    my $this = $class->SUPER::new(@_);
    my ($tag, $m, $data, $element) = @_;

    if(defined $m->{pseudocounts}) {
        $this->{pseudocountSmoother_} = 
            new iPE::Smoother::Pseudocount($m->{pseudocounts});
    }
    else {
        $this->{pseudocountSmoother_} = new iPE::Smoother::Null(0);
    }

    if(defined $m->{smoothing}) {
        $this->{smoothing_} = $m->{smoothing};
        $this->{smoothingData_} = $m->{smoothing_data};
    }
    else {
        $this->{smoothing_} = $this->defaultSmoothing;
        $this->{smoothingData_} = $this->defaultSmoothingData;
    }

    $this->{smoother_} =
        getSmootherClass($this->smoothing)->new ($this->smoothingData);

    return $this;
}

=item smoothing ()

Returns the smoothing method requested for this model.

=cut
sub smoothing { shift->{smoothing_} }

=item smoothingData ()

Returns the value in the smoothing_data tag.  For pseudocounts, this is the value of the pseudocount.

=cut
sub smoothingData { shift->{smoothingData_} }

=item smoother ()

Returns the smoother object for this model.

=cut
sub smoother { shift->{smoother_} }

=item pseudocountSmoother ()

Returns the pseudocount smoother for this model.  This should always be used in the smooth method before the smoother.

=cut
sub pseudocountSmoother { shift->{pseudocountSmoother_} }

sub handle_submodels  { shift->handle_children(@_) }
sub handle_subelement { shift->handle_submodel(@_) }
sub handle_submodel {}

=item outputPrepare (out, mode)

This function is called before outputting occurs.  Two things should happen:  (1) you should set the parameter string, and (2) any other preparation for columnar format should be set up.  You can set the parameter string with the setParamString () method.  It is necessary to do it this way in order to be able to output your model in XML format.  You may use the iPE::Util::Output class to prepare your data for columnar output and/or format your parameter string.

The mode string will indicate one of the "count", "prob", or "score" modes.  Depending on which it is, your parameter string should be prepared as such.

=cut
sub outputPrepare {}

=item outputZoe (out, mode)

This function should be overriden to handle the outputting of models in zoe format.  Refer to the direct superclasses of your class (Emission or Duration) for mmore details.

The mode string will indicate one of the "count", "prob", or "score" modes.  

=cut
sub outputZoe {}

=item setParamString (), getParamString ()

These functions can be used to get and set the parameter string.  You should only use these functions, since it is necessary for proper XML output.

=cut
sub setParamString { shift->setPCData(@_) }
sub getParamString { shift->getPCData(@_) }

=back

=head1 SEE ALSO

L<iPE::XML::Object>

=head1 AUTHOR

Bob Zimmermann (rpz@cse.wustl.edu)

=cut

1;
