in reply to Finding local maxima/minima in noisy, pediodic data
If the data is suitable, you can try to split the signal to half periods roughly by alternatly searching for the first point when the signal reaches an upper threshold and a lower threshold. After this, you just find the minimum or maximum in each half period.
Let me show an example because my description is not clear. Assume the signal is like this:
Then you split the time to approximate half periods like this:our @s = map { sin(0.18*$_) + rand(0.6) - 0.3 } 0 .. 99;
our(@xlo, @xhi); my $t = my $t0 = $s[0] < 0; for my $x (0 .. @s - 1) { + if ($t) { if ($s[$x] > 0.5) { $t = 0; push @xhi, $x; } } else { if ( +$s[$x] < -0.5) { $t = 1; push @xlo, $x; } } }
Now values in @xlo give the start of each lower half period, and similarly @xhi contain the starting time of each higher half period. So now you search for a minimum in each lower half period and the maximum in each upper half.
our(@xmi, @xma); for my $p (0 .. @xlo - 1) { my $xmi = $xlo[$p]; for m +y $x ($xlo[$p] .. ($xhi[$p + $t0] || @s) - 1) { $s[$x] < $s[$xmi] and + $xmi = $x; } push @xmi, $xmi; } for my $p (0 .. @xhi - 1) { my $xma += $xhi[$p]; for my $x ($xhi[$p] .. ($xlo[$p + 1 - $t0] || @s) - 1) { +$s[$xma] < $s[$x] and $xma = $x; } push @xma, $xma; }
(The code is complicated only because of the boundary conditions, furthermore it is left as an exercise to the reader to fix any off by one errors.)
Let's plot the results
for my $x (0 .. @s - 1) { my $l = " "x15 . ":" . " "x15; if (@xlo && $ +xlo[0] <= $x) { shift @xlo; substr $l, 0, 10, "v"x10; } elsif (@xhi & +& $xhi[0] <= $x) { shift @xhi; substr $l, 20, 10, "v"x10; } if (@xmi +and $xmi[0] <= $x) { shift @xmi; substr $l, 0, 7, "minimum"; } elsif +(@xma and $xma[0] <= $x) { shift @xma; substr $l, 23, 7, "maximum"; } + substr $l, 15+int(10*$s[$x]), 1, "*"; print $l, "\n"; }
We get, for example, this.
* *: : * : v*vvvvvvvv : * : * : * : * : * : * : * : max*mum : * : * : * : * : * * *: * vvvvvvvv*v : * : * : * : * : min*mum : * : * : * : * : * : * : * : * : * : :* : * : * : vv*vvvvvvv : * : * : * : * : * : max*mum : * : * : * : * : * : * : * *: * * : * : * : vvvvvvvv*v : * : * : min*mum : * : * : * : * : * : * : * : * : *: : * :* : v*vvvvvvvv : * : * : * : * : * : * : * : maxi*um : * : * : * : * : * : * : * *: * : vvvvvvvv*v : * : * : * : * : * : * : minim*m : * : * :
If the data is more noisy, you may need to smooth it before comparing with the thresholds. If the amplitude varies then it's not so easy to set a fix threshold this way, so I'm not sure what to do in that case.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Finding local maxima/minima in noisy, pediodic data
by Xilman (Hermit) on Oct 14, 2009 at 08:17 UTC | |
by ambrus (Abbot) on Oct 14, 2009 at 10:11 UTC | |
by Xilman (Hermit) on Oct 14, 2009 at 13:21 UTC |