$left_idx++ if $store->[$left_idx] < $start;
####
# $left_idx++ if $store->[$left_idx] < $start; #normal
$left_idx++ if ($store->[$left_idx]+1) < ($start+1); #0.6 bug workaround
####
1.6 [8]: 0.8 1 1.2 1.4 1.8 2 2.2 2.4 2.6
2.2 [11]: 1.4 1.6 1.8 2 2.4 2.6 2.8 3 3.2
4.4 [22]: 3.6 3.8 4 4.2 4.6 4.8 5 5.2 5.4
8.8 [44]: 8 8.2 8.4 8.6 9 9.2 9.4 9.6 9.8
16.6 [83]: 15.8 16 16.2 16.4 16.8 17 17.2 17.4 17.6
32.2 [161]: 31.4 31.6 31.8 32 32.4 32.6 32.8 33 33.2
64.4 [322]: 63.6 63.8 64 64.2 64.6 64.8 65 65.2 65.4
####
DB<25> x ($store->[3]) == $start
0 ''
DB<26> x ($store->[3]+0) == $start
0 ''
DB<27> x $start
0 0.6
DB<28> x $store->[3]
0 0.6
DB<29> x 0.6 == $start
0 ''
DB<30> x $start == 0.6
0 ''
DB<31> x 0.6 == 0.6
0 1
DB<32> x ($store->[3]+0) == ($start+0)
0 ''
DB<33> x ($store->[3]+1) == ($start+1)
0 1
####
#call:
use Spikehisto;
$histo=autocorr([map{$_/5}(0..1000)],2,100,2000);
print join "\t", grep {$_} @$histo;
####
#!/usr/bin/perl -w
package Spikehisto;
use strict;
use warnings;
use diagnostics;
use Math::Round;
use Exporter;
use vars qw( @EXPORT @ISA @VERSION);
@VERSION = 0.01;
@ISA = qw( Exporter );
@EXPORT = qw( &autocorr &crosscorr &interval);
=head1 $a = crosscorr( $source, $compare, $interval, $number_bins, $max_count)
Calculates crosscorrelation histogram of $compare (arrayref) to the source
(arrayref). The $interval gives the interval around the source event about
which the crosscorrelation is calculated. The $num_bins denotes the number
of bins of the interval. If the number of bins is odd, the boundaries will
be lower. The $max_count gives the maximum number of spikes to count.
=cut
my $PDL = <<'_PDL';
_crosscorr_
extract arguments
prepare
return empty histogram unless the source has more than two items
skip the items at the beginning of the source for a length of half an interval
skip the items at the end of the source for a length of half an interval
walk over the remaining items
fill the buffer
if the buffer has one or more items
add the buffer to the histogram
increase the count
exit if the count reaches the desired count
return the histogram
_PDL
sub crosscorr {
#extract arguments
my $source = shift;
my $comp = shift;
my $cross_interval = shift;
my $cross_bins = shift;
my $count_crosscorr = shift;
my $count = 0;
my @times_source = @$source;
my @times_comp = @$comp;
my $start_time = $times_source[0];
my $end_time = $times_source[ $#times_source ] - $cross_bins/2;
my @cross_histo = (0) x $cross_bins;
return \@cross_histo unless scalar(@times_source)>1;
my $idx = 1;
$idx++ while( $times_source[$idx] < ($start_time + $cross_interval/2)
and $idx < $#times_source );
my $last_idx = $#times_source;
$last_idx-- while( $times_source[$last_idx] > $end_time and $last_idx > 0 );
my ($comp_begin_idx, $comp_last_idx) = (0,0);
while( $idx <= $last_idx ) {
my $buff = _fill_crossbuffer( \@times_comp, $times_source[$idx], $cross_interval,
\$comp_begin_idx, \$comp_last_idx);
if (scalar @$buff){
_buffer2histo( $buff, \@cross_histo, $times_source[$idx] - $cross_interval/2,
$cross_interval, $cross_bins );
$count++;
}
last if $count > $count_crosscorr;
$idx++;
}
\@cross_histo;
}
=head1 $a = autocorr( $source, $interval, $number_bins, $max_count)
Calculates autocorrelation histogram of $source (arrayref). The $interval
gives the interval around the source event about which the autocorrelation
is calculated. The $num_bins denotes the number of bins of the interval. If
the nubmer of bins is odd, the boundaries will be lower. The $max_count
gives the maximum number of spikes to count.
=cut
$PDL = <<'_PDL';
_autocorr_
extract arguments
prepare
return empty histogram unless the source has more than two items
skip the items at the beginning of the source for a length of half an interval
skip the items at the start of the source for a length of half an interval
walk over the remaining times
fill the buffer with an interval around the current spike
if the buffer has one or more items
add the buffer to the histogram
increase the count
exit if the count reaches the desired count
return the histogram
_PDL
sub autocorr {
my $source = shift;
my $auto_interval = shift;
my $auto_bins = shift;
my $count_autocorr = shift;
my $count = 0;
my @times = @$source;
my $start_time = $times[0];
my @auto_histo = (0) x $auto_bins;
return \@auto_histo unless scalar(@times)>1;
my $idx = 1;
$idx++ while( $times[$idx] < ($start_time + $auto_interval/2) and $idx < $#times );
my $last_idx = $#times;
my $end_time = $times[ $#times ] - $auto_bins/2;
$last_idx-- while( $times[$last_idx] > $end_time and $last_idx > 0 );
while( $idx <= $last_idx ) {
my $buff = _fill_autobuffer( \@times, $idx, $auto_interval );
if (scalar @$buff){
_buffer2histo( $buff, \@auto_histo, $times[$idx] - $auto_interval/2,
$auto_interval, $auto_bins );
$count++;
}
last if $count > $count_autocorr;
$idx++;
}
\@auto_histo;
}
=head1 $a = interval( $source, $interval, $number_bins)
Calculates inter-event interval histogram of the source (arrayref). The
$interval gives the maximum inter-event interval that should be counted. The
$number_bins denotes the number of bins of the interval.
=cut
$PDL = <<'_PDL';
_interval_
extract arguments
prepare
return empty histogram unless the source has more than two items
get the first item of the series as a reference
walk over series
calculate difference between item and reference
assign current item to reference
add the buffer to the histogram
return the histogram
_PDL
sub interval {
my $source = shift;
my $interval = shift;
my $interval_bins = shift;
my @times = @$source;
my $start_time = $times[0];
my @interval_histo = (0) x $interval_bins;
return \@interval_histo unless scalar(@times)>1;
my $prev = shift @times;
my @buff = map { my $time = $_ - $prev; $prev = $_; $time} @times;
buffer2histo( \@buff, \@interval_histo, 0, $interval, $interval_bins ) if scalar @buff;
\@interval_histo;
}
$PDL = <<'_PDL';
__buffer2histo_
extract arguments
walk over buffer
calculate time relative to reference spike
add time to histogram
_PDL
sub _buffer2histo{
my $buff = shift;
my $histo = shift;
my $reftime = shift;
my $interval = shift;
my $length = shift;
for (@$buff){
my $time = $_ - $reftime;
my $idx = round( $time * ($length-1) / $interval );
next if $idx >= $length or $idx < 0;
$histo->[$idx]++;
}
}
$PDL = <<'_PDL';
__fill_autobuffer_
extract arguments
determine start and end borders, a half interval before and after the reference spike
determine the index of start and end
assign the slice to the buffer, leaving out the reference spike
return the buffer
_PDL
sub _fill_autobuffer{
my $store = shift;
my $store_idx = shift;
my $interval = shift;
my @buff;
my $left_idx = $store_idx;
my $start = $store->[$store_idx] - $interval/2;
my $end = $store->[$store_idx] + $interval/2;
$left_idx-- while( $store->[$left_idx] > $start and $left_idx > 0);
$left_idx++ if $store->[$left_idx] < $start; #normal
# $left_idx++ if ($store->[$left_idx]+1) < ($start+1); #0.6 bug workaround
my $right_idx = $store_idx;
$right_idx++ while( $#{$store} > $right_idx and $store->[$right_idx] < $end );
$right_idx-- if not defined $store->[$right_idx] or $store->[$right_idx] > $end;
my $idx = $store_idx;
@buff = @{$store}[
$left_idx .. ($store_idx - 1), ($store_idx + 1) .. $right_idx
];
\@buff;
}
$PDL = <<'_PDL';
__fill_crossbuffer_
extract arguments
determine start and end borders, a half interval before and after the reference spike
determine the index of start and end
assign the slice to the buffer
point the index-references to the new start and end
return the buffer
_PDL
sub _fill_crossbuffer{
my $store = shift;
my $time_source = shift;
my $interval = shift;
my $left_idx_ref = shift;
my $right_idx_ref = shift;
my $left_idx = $$left_idx_ref;
my $right_idx = $$right_idx_ref;
my @buff;
my $start = $time_source - $interval/2;
my $end = $time_source + $interval/2;
# $left_idx++ while( $store->[$left_idx] < $start and $left_idx < $#{$store}); #normal
$left_idx++ while( ($store->[$left_idx]+1) < ($start+1) and $left_idx < $#{$store}); #bug workaround
$right_idx++ while( $#{$store} > $right_idx and $store->[$right_idx] < $end );
$right_idx-- if not defined $store->[$right_idx] or $store->[$right_idx] > $end;
@buff = @{$store}[ $left_idx .. $right_idx ] ;
$left_idx_ref = \$left_idx;
$right_idx_ref = \$right_idx;
\@buff;
}
1;