Python Signal Counter

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

  • Take a negative value (i.e. -0.25 V)
  • Take a positive value (i.e.> 0.3 V)
  • Stay at a noise level (i.e. 0 to 0.1 V)

x, y plotted

I would like to "digitize" this signal, so that the cases 1., 2. and 3. correspond to discrete values โ€‹โ€‹of -1, +1 or 0.

How to do this best by analyzing data arrays?

My current idea is:

  • To interpolate, to find the values โ€‹โ€‹of x, where y corresponds to each threshold.

np.interp(0.5,x,y)

Problem:

  • How to do this for several positions where the threshold y occurs?
+5
source share
4 answers

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

  • Iterate through all the samples, and then through the thresholds,
  • Check the current level and cross pattern by comparing products of a combination of absolute values, for example: abs (y1) * y0! = Y1 * abs (y0).
  • If a level intersection occurs, the x-value of the intersection is found using the linear equation.
  • The tilt polarity tells you if an intersection has occurred from a level lower or higher, indicating the current level.

The following function implements the following:

 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 shifts down by one:

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

The results are as follows:

 0 -1 1.3 0 1.47 1 3.16 0 3.26 -1 
+2
source

Assuming you have data in pandas datatable ( data with columns x and y ), I would first clear your data a bit (digitize it).

 data.loc[data['y'] > 0.3, 'y'] = +1 data.loc[data['y'] < -0.25, 'y'] = -1 data.loc[(data['y'] >= -0.25) & (data['y'] <= 0.3), 'y'] = 0 

Afterwars, I would check the slope by calculating the difference between additional elements

 data_diff = data.set_index('x').diff(periods=1, axis=0) 

Now follow your differences and count

 state = 0 pos_peaks = 0 neg_peaks = 0 flats = 0 for row in data_diff.itertuples(): if row[1] > 0 and state == 0: pos_peaks += 1 state = 1 elif row[1] < 0 and state == 0: neg_peaks +=1 state = -1 elif row[1] < 0 and state == 1: flats += 1 state = 0 elif row[1] > 0 and state == -1: flats += 1 state = 0 
0
source

As one of the solutions, you can replace them with the necessary values:

  >>> a=np.random.rand(10)-0.5 # just for test >>> a array([-0.16532652, 0.17079655, -0.08183734, -0.42446642, -0.15749626, 0.31809266, 0.09871911, 0.10324168, 0.43021048, 0.16749866]) >>> a[a<-0.3] = -1 >>> a[a>0.25] = +1 >>> a array([-0.16532652, 0.17079655, -0.08183734, -1. , -0.15749626, 1. , 0.09871911, 0.10324168, 1. , 0.16749866]) >>> a[(a>-1) & (a<1)]=0 >>> a array([ 0., 0., 0., -1., 0., 1., 0., 0., 1., 0.]) >>> 
0
source

You can sample data by performing checks such as my_array > 0.3 , which returns a boolean array that can be converted to 1 and 0: np.array( my_array > 0.3 ,int) .

The jump positions can be found by subtracting the shifted signal (by inserting a copy of the first element of the signal) from the signal:

 def jump(time,signal): d_signal = np.array(signal>.3,int) -np.array(signal<-.25,int) shift = d_signal - np.insert(d_signal,0,d_signal[0])[:-1] time_of_jump = time[shift!=0] jump_to_value = d_signal[shift!=0] return time_of_jump,jump_to_value 

I tested this on a random signal that looks somewhat similar to yours:

 import numpy as np import matplotlib.pyplot as plt jumps=np.around(np.random.rand(30)*2-1)*.5 signal=np.array([]) for i in jumps: signal=np.hstack((signal , np.ones(10)*i + np.random.normal(0,.05,10))) time=np.arange(0,len(signal))*.01+239 print(jump(time,signal)) # Python 3 print jump(time,signal) # Python 2 

Returns an array of times when the jumps occurred (the first element with a new value), and the values โ€‹โ€‹(+ 1,0, -1) to which the signal was pressed.

0
source

Source: https://habr.com/ru/post/1259986/


All Articles