Mercurial > forge
changeset 10420:bfc8b33828a5 octave-forge
signal: Adding new functions. clustersegment is old and can be improved a lot.
author | jpicarbajal |
---|---|
date | Sat, 09 Jun 2012 00:52:28 +0000 |
parents | 66ec9da43f53 |
children | 4b25237504f0 |
files | main/signal/INDEX main/signal/NEWS main/signal/inst/clustersegment.m main/signal/inst/movingrms.m main/signal/inst/schtrig.m |
diffstat | 5 files changed, 268 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/main/signal/INDEX Fri Jun 08 19:20:19 2012 +0000 +++ b/main/signal/INDEX Sat Jun 09 00:52:28 2012 +0000 @@ -27,6 +27,7 @@ sgolayfilt sosfilt medfilt1 + movingrms Filter analysis freqs freqs_plot grpdelay @@ -119,7 +120,8 @@ kaiser nuttallwin triang - gaussian gausswin + gaussian + gausswin tukeywin rectwin welchwin @@ -160,3 +162,5 @@ wrev zerocrossing sampled2continuous + schtrig + clustersegment
--- a/main/signal/NEWS Fri Jun 08 19:20:19 2012 +0000 +++ b/main/signal/NEWS Sat Jun 09 00:52:28 2012 +0000 @@ -4,6 +4,9 @@ signal-1.1.4 Release Date: 2012-XX-XX Release Manager: =============================================================================== + ** The following functions are new: + movingrms schtrig clustersegment + ** signal is no longer dependent on the image package. ** signal is now dependent on the general package.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/signal/inst/clustersegment.m Sat Jun 09 00:52:28 2012 +0000 @@ -0,0 +1,69 @@ +## Copyright (c) 2010 Juan Pablo Carbajal <carbajal@ifi.uzh.ch> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see <http://www.gnu.org/licenses/>. + +%% contRange = clustersegment(xhi) +% The function calculates the initial and end index values of the sequences of +% 1's in the rows of xhi. The result is returned in a cell of size 1xNp, with Np +% the numer of rows in xhi. Each element of the cell has two rows; the first row +% is the inital index of a sequence of 1's and the second row is the end index +% of that sequence. + +function contRange = clustersegment(xhi) + + % Find discontinuities + bool_discon = diff(xhi,1,2); + [Np Na] = size(xhi); + contRange = cell(1,Np); + + for i = 1:Np + idxUp = find(bool_discon(i,:)>0)+1; + idxDwn = find(bool_discon(i,:)<0); + tLen = length(idxUp) + length(idxDwn); + + if xhi(i,1)==1 + % first event was down + contRange{i}(1) = 1; + contRange{i}(2:2:tLen+1) = idxDwn; + contRange{i}(3:2:tLen+1) = idxUp; + else + % first event was up + contRange{i}(1:2:tLen) = idxUp; + contRange{i}(2:2:tLen) = idxDwn; + end + + if xhi(i,end)==1 + % last event was up + contRange{i}(end+1) = Na; + end + + tLen = length(contRange{i}); + if tLen ~=0 + contRange{i}=reshape(contRange{i},2,tLen/2); + end + + end + +endfunction + +%!demo +%! xhi = [0 0 1 1 1 0 0 1 0 0 0 1 1]; +%! ranges = intervalSegment(xhi) +%! +%! % The first sequence of 1's in xhi is +%! xhi(ranges{1}(1,:)) + +%!demo +%! xhi = rand(3,10)>0.4 +%! ranges = intervalSegment(xhi)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/signal/inst/movingrms.m Sat Jun 09 00:52:28 2012 +0000 @@ -0,0 +1,96 @@ +## Copyright (c) 2012 Juan Pablo Carbajal <carbajal@ifi.uzh.ch> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{rmsx},@var{w}] =} movingrms (@var{x},@var{w},@var{rc},@var{Fs}=1) +## Calculates moving RMS value of the signal in @var{x}. +## +## The signla is convoluted against a sigmoid window of width @var{w} and risetime +## @var{rc}. The units of these to parameters are relative ot the vlaue of the sampling +## frequency given in @var{Fs} (Default value = 1). +## +## Run @code{demo movingrms} to see an example. +## +## @seealso{sigmoid_train} +## @end deftypefn + +function [rmsx w]= movingrms (x,width, risetime, Fs=1) + + [N nc] = size (x); + if width*Fs > N/2 + idx = [1 N]; + w = ones(N,1); + else + idx = round ((N + width*Fs*[-1 1])/2); + w = sigmoid_train ((1:N)', idx, risetime*Fs); + end + fw = fft (w.^2); + fx = fft (x.^2); + rmsx = real(ifft (fx.*fw)/(N-1)); + + rmsx (rmsx < eps*max(rmsx(:))) = 0; + + rmsx = circshift (sqrt (rmsx), round(mean(idx))); +% w = circshift (w, -idx(1)); + +endfunction + +%!demo +%! N = 128; +%! t = linspace(0,1,N)'; +%! x = sigmoid_train (t,[0.4 inf],1e-2).*(2*rand(size(t))-1); +%! +%! Fs = 1/diff(t(1:2)); +%! width = 0.05; +%! rc = 5e-3; +%! [wx w] = movingrms (zscore (x),width,rc,Fs); +%! +%! close all +%! figure () +%! +%! area (t,wx,'facecolor',[0.85 0.85 1],'edgecolor','b','linewidth',2); +%! hold on; +%! h = plot (t,x,'r-;Data;',t,w,'g-;Window;'); +%! set (h, 'linewidth', 2); +%! hold off +%! +%! % --------------------------------------------------------------------------- +%! % The shaded plot shows the local RMS of the Data: white noise with onset at +%! % aprox. t== 0.4. +%! % The observation window is also shown. + +%!demo +%! N = 128; +%! t = linspace(0,1,N)'; +%! x = exp(-((t-0.5)/0.1).^2) + 0.1*rand(N,1); +%! +%! Fs = 1/diff(t(1:2)); +%! width = 0.1; +%! rc = 2e-3; +%! [wx w] = movingrms (zscore (x),width,rc,Fs); +%! +%! close all +%! figure () +%! +%! area (t,wx,'facecolor',[0.85 0.85 1],'edgecolor','b','linewidth',2); +%! hold on; +%! h = plot (t,x,'r-;Data;',t,w,'g-;Window;'); +%! set (h, 'linewidth', 2); +%! hold off +%! +%! % --------------------------------------------------------------------------- +%! % The shaded plot shows the local RMS of the Data: Gausian with centered at +%! % aprox. t== 0.5. +%! % The observation window is also shown.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/signal/inst/schtrig.m Sat Jun 09 00:52:28 2012 +0000 @@ -0,0 +1,95 @@ +## Copyright (c) 2012 Juan Pablo Carbajal <carbajal@ifi.uzh.ch> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{rmsx},@var{w}] =} schtrig (@var{x},@var{lvl},@var{rst}=1) +## Implements a multisignal Schmitt trigger with levels @var{lvl}. +## +## The triger works along the first dimension of the array @var{x}. When @code{@var{rst}==1} +## the state of the trigger for all signals is set to the low state (i.e. 0). +## +## Run @code{demo schtrig} to see an example. +## +## @seealso{clustersegment} +## @end deftypefn + +function v = schtrig (x, lvl, rst = 1) + + persistent st0; + + if length(lvl) == 1 + lvl = abs (lvl)*[1 -1]; + else + lvl = sort(lvl,'descend'); + end + + [nT nc] = size(x); + + v = NA (nT, nc); + + if rst || isempty(st0) + st0 = zeros(1,nc); + printf ("Trigger initialized!\n"); + flush (stdout); + end + + v(1,:) = st0; + + % Signal is above up level + up = x > lvl(1); + v(up) = 1; + + % Signal is below down level + dw = x < lvl(2); + v(dw) = 0; + + % Resolve intermediate states + % Find data between the levels + idx = isnan (v); + ranges = clustersegment (idx'); + + for i=1:nc + % Record the state at the begining of the interval between levels + if !isempty (ranges{i}) + prev = ranges{i}(1,:)-1; + prev(prev<1) = 1; + st0 = v(prev,i); + + % Copy the initial state to the interval + ini_idx = ranges{i}(1,:); + end_idx = ranges{i}(2,:); + for j =1:length(ini_idx) + v(ini_idx(j):end_idx(j),i) = st0(j); + end + end + end + + st0 = v(end,:); + +endfunction + +%!demo +%! t = linspace(0,1,100)'; +%! x = sin (2*pi*2*t) + sin (2*pi*5*t).*[0.8 0.3]; +%! +%! lvl = [0.8 0.25]'; +%! v = schtrig (x,lvl); +%! +%! h = plot(t,x,t,v); +%! set (h([1 3]),'color','b'); +%! set (h([2 4]),'color',[0 1 0.5]); +%! set (h,'linewidth',2); +%! line([0; 1],lvl([1; 1]),'color','r'); +%! line([0;1],lvl([2;2]),'color','b')