suppose you have two sets @x and @y, then to employ correlation to check for cross-correlation between them, you have to simulate the phasing yourself as far as I know; something like this is what is on my mind:
use Statistics::Basic::Correlation;
sub xcorr {
# given two sets and a phase increment, return
# at which phase the best correlation is found
# and what that value is
my ($xref, $yref, $incdeg ) = @_;
my $maxcorr = -1;
$incdeg ||= 1; default 1 degree of phase.
die "sets of unequal size" if ( $#$xref != $#$yref );
my $indexinc = $incdeg * ( 1 + $#$xref );
my $iters = 360 / $incdeg;
{ use integer;
$indexinc /= 360;
$iters++;
}
$indexinc ||=1;
my @copy = @$yref;
my $where = 0;
my $match = 0;
for (my $i = 0; $i < $iters; $i++) {
unshift @copy, ( pop @copy ) for ( 1 .. $indexinc );
my $res = correlate( $xref, \@copy );
if ( $res > $maxcorr ) {
$maxcorr = $res;
$match = $where;
}
$where += $incdeg;
}
return ( $match, $maxcorr );
}
(updated the code)
More update:
- the arrays are passed by reference i.e. \@x and \@y
- the approach does not take into account potential change of amplitude of one of the signals relative to the other, which is not taken into account by correlation alone. To compensate if necessary, find s(x)/s(y) where s() is standard deviation found using Statistics::Basic::StdDev and multiply all @copy by that before iterating through the phase shifts.
|