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