detecting a sign change in a vector

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

detecting a sign change in a vector

dirac
Hi there people,

This might be trivial but I am stuck on this.
I have a vector, V, which basically contains the values of a cos/sin function. The signs of the elements in the vector change from + to - occasionally. I would like to find these points without using a loop as I have done in the past. Is there a way to do this?

Thanks
MA
Still learning everyday.
Reply | Threaded
Open this post in threaded view
|

Re: detecting a sign change in a vector

Nir Krakauer-2
try
diff(sign(V))
_______________________________________________
Help-octave mailing list
[hidden email]
https://mailman.cae.wisc.edu/listinfo/help-octave
Reply | Threaded
Open this post in threaded view
|

Re: detecting a sign change in a vector

bpabbott
Administrator
In reply to this post by dirac

On Jan 31, 2013, at 12:52 PM, dirac wrote:

> Hi there people,
>
> This might be trivial but I am stuck on this.
> I have a vector, V, which basically contains the values of a cos/sin
> function. The signs of the elements in the vector change from + to -
> occasionally. I would like to find these points without using a loop as I
> have done in the past. Is there a way to do this?
>
> Thanks
> MA


The vector "v" will cross zero with between the m and m+1, with v(m) > 0.

        n = 1:(numel(v)-1);
        m = find (v(n) * v(n+1) < 0 & v(n) > 0);

Ben

_______________________________________________
Help-octave mailing list
[hidden email]
https://mailman.cae.wisc.edu/listinfo/help-octave
Reply | Threaded
Open this post in threaded view
|

Re: detecting a sign change in a vector

Jordi Gutiérrez Hermoso-2
In reply to this post by dirac
On 31 January 2013 12:52, dirac <[hidden email]> wrote:
> This might be trivial but I am stuck on this.
> I have a vector, V, which basically contains the values of a cos/sin
> function. The signs of the elements in the vector change from + to -
> occasionally.

idx_changes = diff(sign(vector)) != 0)

HTH,
- Jordi G. H.
_______________________________________________
Help-octave mailing list
[hidden email]
https://mailman.cae.wisc.edu/listinfo/help-octave
Reply | Threaded
Open this post in threaded view
|

Re: detecting a sign change in a vector

dirac
Thanks for all of the help guys, it's been a year and a half since I last used Octave so I've forgotten so many of the functions! I really appreciate it
Still learning everyday.
Reply | Threaded
Open this post in threaded view
|

Re: detecting a sign change in a vector

Bob Walton
In reply to this post by dirac
dirac wrote
...
I have a vector, V, which basically contains the values of a cos/sin function. The signs of the elements in the vector change from + to - occasionally. I would like to find these points without using a loop as I have done in the past. Is there a way to do this?
...
MA
Here is some code that gives the subscripts of the sign changes:

t=linspace(0,20,1001)';
x=sin(t.^2);
z=x>=0;
c=conv(z,[-1 1]);
st=find(c<-.5); %subscript of the start of a run of non-negatives
en=find(c>.5)-1; %subscript of the end of a run of non-negatives
runs=[st en]; %start and end of runs of non-negatives

Result:  

runs =

     1   178
   252   307
   356   397
   436   469
   503   532
   562   588
   615   640
   665   687
   710   731
   753   773
   794   813
   833   851
   870   887
   905   921
   939   955
   972   987

--
Bob Walton

Reply | Threaded
Open this post in threaded view
|

Re: detecting a sign change in a vector

Juan Pablo Carbajal-2
In reply to this post by Jordi Gutiérrez Hermoso-2
On Thu, Jan 31, 2013 at 7:41 PM, Jordi Gutiérrez Hermoso
<[hidden email]> wrote:

> On 31 January 2013 12:52, dirac <[hidden email]> wrote:
>> This might be trivial but I am stuck on this.
>> I have a vector, V, which basically contains the values of a cos/sin
>> function. The signs of the elements in the vector change from + to -
>> occasionally.
>
> idx_changes = diff(sign(vector)) != 0)
>
> HTH,
> - Jordi G. H.
> _______________________________________________
> Help-octave mailing list
> [hidden email]
> https://mailman.cae.wisc.edu/listinfo/help-octave

You can improve on Jordi's result by linear interpolation (or whatever
fancier interpolation). Check this out

t = linspace(0,2*pi,100);
x = sin (4*t + pi/5);
idx = find (diff (sign(x)) != 0);
% If we take the values given by the indexes we get
sin (4*t(idx) + pi/5)
  0.2264968  -0.0697565   0.1642651  -0.0063466   0.1013720  -0.1954794
 0.0380707  -0.1328855
% if we do simple linear interpolation
tzero = mean ([t(idx); t(idx+1)]);
sin (4*tzero + pi/5)
 0.1013720   0.0570888   0.0380707   0.1202944  -0.0253839  -0.0697565
-0.0887363  -0.0063466

In one case you get a worse result, but in general the abscissa of the
zero is better estimated.
Also, note that all these methods work for functions without noise. If
you have noise you will better fit a model function to your data and
get the zeros of the fitted function.
_______________________________________________
Help-octave mailing list
[hidden email]
https://mailman.cae.wisc.edu/listinfo/help-octave
Reply | Threaded
Open this post in threaded view
|

Re: detecting a sign change in a vector

Juan Pablo Carbajal-2
On Sat, Feb 2, 2013 at 7:46 PM, Juan Pablo Carbajal
<[hidden email]> wrote:

> On Thu, Jan 31, 2013 at 7:41 PM, Jordi Gutiérrez Hermoso
> <[hidden email]> wrote:
>> On 31 January 2013 12:52, dirac <[hidden email]> wrote:
>>> This might be trivial but I am stuck on this.
>>> I have a vector, V, which basically contains the values of a cos/sin
>>> function. The signs of the elements in the vector change from + to -
>>> occasionally.
>>
>> idx_changes = diff(sign(vector)) != 0)
>>
>> HTH,
>> - Jordi G. H.
>> _______________________________________________
>> Help-octave mailing list
>> [hidden email]
>> https://mailman.cae.wisc.edu/listinfo/help-octave
>
> You can improve on Jordi's result by linear interpolation (or whatever
> fancier interpolation). Check this out
>
> t = linspace(0,2*pi,100);
> x = sin (4*t + pi/5);
> idx = find (diff (sign(x)) != 0);
> % If we take the values given by the indexes we get
> sin (4*t(idx) + pi/5)
>   0.2264968  -0.0697565   0.1642651  -0.0063466   0.1013720  -0.1954794
>  0.0380707  -0.1328855
> % if we do simple linear interpolation
> tzero = mean ([t(idx); t(idx+1)]);
> sin (4*tzero + pi/5)
>  0.1013720   0.0570888   0.0380707   0.1202944  -0.0253839  -0.0697565
> -0.0887363  -0.0063466
>
> In one case you get a worse result, but in general the abscissa of the
> zero is better estimated.
> Also, note that all these methods work for functions without noise. If
> you have noise you will better fit a model function to your data and
> get the zeros of the fitted function.

ADDENDUM:

or smooth your data using an adequate filter.
_______________________________________________
Help-octave mailing list
[hidden email]
https://mailman.cae.wisc.edu/listinfo/help-octave
Reply | Threaded
Open this post in threaded view
|

Re: detecting a sign change in a vector

dirac
I had to do a bit of interpolation because the value the function takes between two indices either side of zero was huge. This was a problem with the adaptive step size of the Runge-Kutta I implemented and the fact that the steep gradient of the function. I fixed it by hard wiring the step size and the interpolation suggested.
Again thanks!
Martin
Still learning everyday.