Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python signal counter

I have two arrays of data taken from an experiment; x (time) and y (voltage). These are plotted below. Every 200 microseconds, the signal is one of three states:

  1. Take a negative value (i.e. < -0.25 V)
  2. Take a positive value (i.e. > 0.3 V)
  3. Remain at the level of the noise (i.e. ~between 0 and 0.1 V)

x,y plotted

I would like to 'digitise' this signal, so that case 1., 2., and 3., correspond to discrete values of -1, +1 or 0.

How to do this best by analysing the arrays of data?

My current idea:

  • To interpolate to find x values where y meet each threshold.

np.interp(0.5,x,y)

Issue:

  • How do this for multiple positions where the y threshold is met?
like image 463
8765674 Avatar asked Nov 18 '16 18:11

8765674


1 Answers

For N thresholds, there are N+1 levels. Level crossings are found using the following steps:

  • Iterate through all the samples and then thresholds,
  • Check the current level and sample for a crossing, by comparing the products of a combination of absolute values, for example: abs(y1)*y0 != y1*abs(y0).
  • If a level crossing has occurred, the x-value of the crossing is found using a linear equation.
  • The polarity of the slope tells you if the crossing came from a level below or above, indicating the current level.

The following function implements the above:

def quantizer(time,voltage,thresholds):
    x0=time[0]; y0=voltage[0];
    l0 = 0
    for level,thresh in enumerate(thresholds):
        l0 = level if y0>thresh else l0
    xings=[tuple([x0,l0])]
    for x1,y1 in zip(time[1:],voltage[1:]):
        xings_i=[]
        dy=y1-y0
        dx=x1-x0
        dy_dx = dy/dx
        for level,thresh in enumerate(thresholds):
            y1s=y1-thresh
            y0s=y0-thresh
            if dy!=0:
                if abs(y1s)*y0s!=y1s*abs(y0s):
                    xings_i.append(tuple([x0-y0s/dy_dx,level+1*(dy_dx>0)]))
        xings_i.sort(key=lambda tup: tup[0])
        xings+=xings_i
        x0=x1
        y0=y1
    return xings

The following inputs were used to test the function:

time =    [  0,   1,   2,   3,   4 ]
voltage = [-2.0,-1.2, 2.0, 1.1,-4.0]
thresholds = [-0.25,0.3]

The levels returned by this function are unsigned and start from zero, so the result of the function is shifted down by one:

def main():
    for t,level in quantizer(time,voltage,thresholds):
        print(str(round(t,2)) + "\t" + str(level-1))

The results look as follows:

0       -1
1.3     0
1.47    1
3.16    0
3.26    -1
like image 132
Tjaart Avatar answered Nov 19 '22 23:11

Tjaart