#!perl -w

=pod

=head1 NAME

Neuron::Morphometrics::EntireNeuron - Information on an entire neuron

=head1 SYNOPSIS

Neuron::Morphometrics::EntireNeuron provides different functions to return
morphometric values concerning an entire neuron, like number of terminal tips,
number of segments etc.

=head1 FUNCTIONS

=over 0

=item *
I<$n> = numStems(I<neuron>);

returns the number of stems in the neuron.

=item *
I<$n> = numTerminals(I<neuron> [, I<min>, I<max>, I<which>]);

returns the number of terminal tips in the neuron. The optional parameters 
I<min> and I<max> define limits in the parameter specified by I<which>: branch 
order ("order"), path distance ("distance") or euclidian distance ("edistance"); 
for example, numSegments(\@myneuron, 2, 4, order) would only consider segments 
of branch orders 2 through 4, inclusively. If parameters are given at all, both 
I<min> and I<max> must be given. 

=item *
I<$n> = area(I<neuron>);

returns the neuron's surface area.

=item *
I<$n> = volume(I<neuron>);

returns the neuron's volume.

=item *
I<$n> = (min|max)(X|Y|Z)(I<neuron>);

returns minimal or maximal X, Y or Z value.

=back

=head1 AUTHOR

Gunther Schmidl <gschmidl@gmx.at>

=cut

package Neuron::Morphometrics::EntireNeuron;
use strict;
use warnings;
no warnings 'recursion';

use Neuron::Morphometrics::Tools;

# prepare variable export

use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(numTerminals numStems minX maxX minY maxY minZ maxZ volume area);
@EXPORT_OK = qw();
$VERSION = 0.01;






#==============================================================================
#
# numStems(neuron) - return number of stems.
#
#==============================================================================

sub numStems(@)
{
    my $stems = 0;
    my @arr = @{$_[0]};
    my $num = numCompartments(\@arr);

    for (my $i = 1; $i <= $num; $i++)        # count all whose parent is 1
    {
        if ($arr[$i]->{'parent'} == 1)
        {
            $stems++;
        }
    }
    return $stems;
}






#==============================================================================
#
# numTerminals(neuron) - return number of terminals.
#
#==============================================================================

sub numTerminals
{
    my @arr = @{$_[0]};
    my $min = (defined($_[1]) ? $_[1] : 0);
    my $max = (defined($_[2]) ? $_[2] : maxBranchOrder(\@arr));
    my $wch = (defined($_[3]) ? $_[3] : "order");

    my $terminals = 0;
    my $num = numCompartments(\@arr);

    for (my $i = 1; $i <= $num; $i++)       # no children => terminal
    {
        if (not($arr[$i]->{'kids'}))
        {
            if ($arr[$i]->{'order'} >= $min && $arr[$i]->{'order'} <= $max)
            {
                $terminals++;
            }
        }
    }
    return $terminals;
}






#==============================================================================
#
# minX(neuron), maxX(neuron), minY(neuron), maxY(neuron), minZ(neuron), 
# maxZ(neuron) - return information about coordinates.
#
#==============================================================================

sub minX(@) { return minmax(\@{$_[0]}, "x", 0); }

sub maxX(@) { return minmax(\@{$_[0]}, "x", 1); }

sub minY(@) { return minmax(\@{$_[0]}, "y", 0); }

sub maxY(@) { return minmax(\@{$_[0]}, "y", 1); }

sub minZ(@) { return minmax(\@{$_[0]}, "z", 0); }

sub maxZ(@) { return minmax(\@{$_[0]}, "z", 1); }






#==============================================================================
#
# volume(neuron) - return neuron volume.
#
#==============================================================================

sub volume(@)
{
    my $sum = 0;
    my @arr = @{$_[0]};
    my $num = numCompartments(\@arr);

    for (my $i = 1; $i <= $num; $i++)
    {
        $sum = $sum + $arr[$i]->{'volume'};
    }
    return $sum;
}






#==============================================================================
#
# area(neuron) - return neuron surface area.
#
#==============================================================================


sub area(@)
{
    my $sum = 0;
    my @arr = @{$_[0]};
    my $num = numCompartments(\@arr);

    for (my $i = 1; $i <= $num; $i++)
    {
        $sum = $sum + $arr[$i]->{'area'};
    }
    return $sum;
} 