Commit 969895ee authored by Nicolas Boucquey's avatar Nicolas Boucquey

Scripts cleaned

parent f980ad4e
# Script providing the Thermo class used to interact with the on board
# thermometer. (DS18B20U+). This file has to be run on the MicroZed + ADC board
from devmem import DevMem
import time
from scipy import signal
import numpy as np
from scipy.optimize import curve_fit
mem = DevMem(base_addr = 0x40000000, length = 0x10000,debug = 0)
TRIG0_ADDR = 0x1000
BUFF0_ADDR = 0x2000
TRIG1_ADDR = 0x3000
BUFF1_ADDR = 0x4000
TRIG2_ADDR = 0x5000
BUFF2_ADDR = 0x6000
TRIG3_ADDR = 0x7000
BUFF3_ADDR = 0x8000
THERM_ADDR = 0x9000
class Thermo:
def __init__(self, mem, addr):
self.mem = mem
self.addr = addr
def reset(self, overdrive):
self.mem.writel(0x08 | overdrive << 2 | 0x02, self.addr)
while(0x08 & self.mem.readl(self.addr)):
pass
return(self.mem.readl(self.addr) & 0x01)
def read(self, overdrive):
self.mem.writel(0x08 | overdrive << 2 | 0x01, self.addr)
while(0x08 & mem.readl(self.addr)):
pass
return(self.mem.readl(self.addr) & 0x01)
def write(self, overdrive, bit):
self.mem.writel(0x08 | overdrive << 2 | bit, self.addr)
while(0x08 & mem.readl(self.addr)):
pass
return(self.mem.readl(self.addr) & 0x01)
def change_div(self, div):
self.mem.writel(div, self.addr + 0x4)
def Write_byte(self, overdrive, byte):
for i in range (0, 8):
self.write(overdrive, (byte & 0x1))
byte >>= 1
def Read_id(self, overdrive):
self.reset(overdrive)
self.Write_byte(overdrive, 0x33)
id_thermo = 0
for i in range (0, 64):
id_thermo <<= 1
id_thermo |= self.read(overdrive)
return id_thermo
def Read_temp(self, overdrive):
self.reset(overdrive)
self.Write_byte(overdrive, 0xCC)
self.Write_byte(overdrive, 0x44)
temp = 0
# thermometer answers a 1 once the convertion is finished
while(self.read(overdrive) != 1):
pass
self.reset(overdrive)
self.Write_byte(overdrive, 0xCC)
self.Write_byte(overdrive, 0xBE)
for i in range (0, 16):
temp >>= 1
temp |= (self.read(overdrive) << 15)
return temp*0.0625 # 12 bit convert factor
ds = Thermo(mem, THERM_ADDR)
iteration = 0
overdrive = 0
result =0
ds.change_div(499)
while(True):
print(ds.Read_temp(overdrive))
time.sleep(0.5)
# Computes the statistics on the TDC measurement results. This script is used to
# estimate if the results are following the probability density function.
#
# The file "measurements.py" is required.
import numpy as np
import measurements
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import pylab
import scipy.stats as stats
n, bins, patches = plt.hist(measurements.result, bins = np.arange(840, 870,0.5), normed = 1)
mean = np.mean(measurements.result)
std = np.std(measurements.result)
y = mlab.normpdf(bins, mean, std)
plt.plot(bins,y, 'r--')
plt.show()
stats.probplot(measurements.result, dist="norm", plot= pylab)
pylab.show()
\ No newline at end of file
# Script used to estimate the linearity of the TDC. 10k phase have been
# recoded in the file "data_linearity.py". The histogram of the measured phase
# is plotted. The linearity can be estimated by the repartition of the measured
# phase over one sampling period. If they are equally spread, the TDC is linear.
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal,optimize
from textwrap import wrap
import sys
import scipy.linalg as la
import pylab
import sys
from scipy.optimize import curve_fit
from matplotlib2tikz import save as tikz_save
import math
import data_linearity
import matplotlib.mlab as mlab
BINS_SIZE = 3
def straight(x, a, b):
return a * x + b
n, bins, patches = plt.hist(data_linearity.phase,
bins = np. arange(np.min(data_linearity.phase),
np.max(data_linearity.phase), BINS_SIZE))
phase = np.linspace(np.min(data_linearity.phase),
np.max(data_linearity.phase), len(n))
popt, popc = curve_fit(straight, phase, n)
plt.xlabel("Measured phase, bins size = " + str(BINS_SIZE) + " ps")
plt.ylabel("Occurences")
plt.show()
plt.plot(phase, straight(phase, popt[0], popt[1]), 'b')
plt.plot(phase, n, 'r')
plt.show()
# Linearity error
error = straight(phase, popt[0], popt[1]) - n
n, bins, patch = plt.hist(error, normed = 1)
y = mlab.normpdf(bins, np.mean(error), np.std(error))
plt.plot(bins, y)
plt.show()
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
# Script used to evaluate the ENOB. The Total Harmonic Distortion (THD) is not
# taken into account. The filte "data_enbo.py" is required
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import data_enob
import math
FS = 100
def Sine(xdata, A, f, delay_ps, offset):
return A*np.sin(2*np.pi*f/FS*xdata + 2*np.pi*f*delay_ps/1e6) + offset
data_enob_measure = []
for i in range (0,10):
data_enob_measure.append(data_enob.chan_[i*2])
# Measurement of the standard deviation of the noise
data_enob_std = np.std(data_enob_measure)
print(data_enob_std)
# Signal to Noise Ratio (in comparision to a full scale signal)
SNR = 20*np.log10(2**14/2/np.sqrt(2)*data_enob_std)
ENOB = (SNR - 1.76)/6.02
print(ENOB)
# Delays out of the TDC. 500 experiments are done for statistics.
# The sampling frequency is 100 MHz.
# The filter is the one presented on the wiki. (CMOS gates = 5PB1108,
# operational amplifier = LMH6624, Schottky diodes are HSMS-281C-BLKG).
# The filter oscillates at 15 MHz. Use "TDC_stat.py" to see the results.
import numpy as np
result = np.empty(500)
result = [
851.105826578,
854.871027501,
854.623010316,
860.342554821,
851.147403424,
854.887415591,
853.916462804,
854.498432755,
857.906103014,
859.233595489,
852.277524318,
860.07015948,
852.824454701,
856.119353486,
852.2915553,
850.232946191,
856.899733168,
855.636395463,
854.184426333,
849.707812751,
857.087547787,
851.472316081,
858.022336955,
854.578346005,
851.97136404,
855.259640186,
858.616291768,
855.884556718,
853.959598638,
857.563110299,
855.648910406,
855.967620238,
854.00447167,
854.50566629,
853.803474384,
853.437099132,
853.514510066,
854.878976443,
854.370126981,
852.171078954,
854.931927407,
854.782750689,
856.029230296,
850.195377191,
856.362895183,
856.347435075,
859.441253336,
854.768918391,
855.872745393,
849.720067899,
857.674082885,
854.912509618,
857.305477646,
858.107874472,
853.852544506,
856.415401245,
851.696741129,
853.720016323,
854.578488163,
851.538377585,
854.97361746,
855.904772938,
856.471503371,
851.560264148,
857.735271751,
852.188850392,
856.050478854,
850.729722281,
856.55126906,
856.352201241,
856.680415595,
855.257686467,
857.572915623,
848.893296087,
859.155693717,
850.828436614,
855.393990916,
851.982416839,
856.366349649,
852.518378227,
851.356204966,
853.830947269,
856.467893585,
857.046384958,
852.730385981,
861.154346754,
858.578573137,
850.152806583,
850.468404283,
851.051905055,
853.126564013,
852.894876121,
858.280243961,
852.981711653,
855.004886908,
854.645510056,
855.827572522,
851.978380443,
854.085089272,
860.709197675,
856.202638636,
849.640917184,
856.176344567,
857.566661542,
856.551882894,
857.384784913,
857.161383176,
859.472088739,
855.642035774,
854.631528361,
857.581332434,
859.102519403,
852.459870706,
851.958177569,
856.912189679,
860.124157798,
851.021530337,
856.359541489,
857.458178439,
856.293192713,
852.57518761,
853.474135061,
851.453815915,
852.214384956,
856.273756944,
859.455408256,
857.317026278,
852.512053165,
852.016305201,
853.937823005,
859.465674965,
853.377747225,
853.616567142,
854.055860484,
849.12742255,
847.571253939,
858.231333456,
852.51754089,
852.738121418,
852.844992166,
857.279642378,
852.84364768,
857.02660165,
849.053258819,
852.567010467,
856.159777225,
853.259502021,
857.659822889,
857.045668164,
856.300061748,
854.459123356,
857.477404185,
854.603969302,
856.871491398,
851.610103127,
854.913798063,
851.433927352,
859.136100535,
856.473406076,
849.766425166,
857.678386418,
861.97674076,
858.531565022,
853.857460451,
858.823600128,
851.870597278,
852.788566959,
858.146872985,
857.587983692,
855.064323577,
851.829495329,
849.774835729,
859.875533559,
859.181090615,
854.575074355,
858.444705422,
857.974160308,
853.454180282,
851.823058691,
852.329700597,
855.950575799,
849.280241525,
853.056109386,
859.896951152,
854.620449567,
855.57550188,
854.496758842,
860.505172904,
854.17100035,
847.885733335,
852.081781571,
853.092008025,
857.254470025,
861.19556284,
859.09720044,
855.816146647,
850.964203549,
858.365404183,
848.610857722,
857.279762364,
852.036140055,
856.778246494,
850.556327315,
858.665063471,
851.923704564,
850.841421113,
852.601464748,
854.585730479,
856.240559073,
855.642464148,
854.506011388,
853.443485214,
861.259482616,
857.678881468,
853.525841656,
855.381303211,
856.599634039,
857.894940188,
861.872032513,
855.149174494,
852.010242609,
849.751164472,
857.465116796,
856.149558133,
858.333817787,
857.161115086,
855.222699813,
860.561300055,
855.249222041,
854.452039284,
854.571872362,
855.008482507,
851.742714077,
852.690671606,
853.797192601,
856.564465375,
855.991756911,
851.585678126,
848.86781545,
850.014428591,
855.022140396,
862.487894161,
862.82219536,
853.816015976,
857.129138771,
857.170234171,
854.466708389,
854.725447796,
855.951010353,
852.639913002,
859.070955774,
849.896544698,
860.285594983,
851.230402063,
859.218991882,
857.324981062,
856.530745174,
856.101836116,
852.243680901,
856.853182821,
856.496411555,
853.539901753,
861.208106853,
855.571661825,
857.233996641,
854.370259197,
859.865075619,
851.080402087,
855.417693227,
857.245707226,
856.55590707,
857.27465507,
860.396205941,
855.714115546,
860.780061787,
852.654533293,
855.12927297,
849.507209247,
854.024155889,
855.992018681,
856.238037001,
851.772196109,
857.063779123,
857.611070407,
861.144703902,
857.118321101,
848.923337232,
855.056255992,
855.756776913,
851.028893759,
849.92424058,
855.288651186,
852.77615052,
848.63694492,
856.987676561,
854.766054336,
854.81524375,
858.397188949,
853.732314827,
854.1182705,
857.801736811,
859.387486055,
854.9556832,
850.911262987,
852.572752087,
851.877203476,
860.433679903,
856.338273203,
856.540877708,
855.064181151,
852.142382273,
854.980030535,
851.888099172,
853.702766893,
853.484088765,
853.68906493,
850.057715965,
854.54326812,
857.505129987,
855.210512718,
855.555958016,
851.184331559,
859.204524704,
854.249795999,
854.093131218,
852.941832037,
854.532992064,
852.094541307,
855.905531286,
853.799164218,
855.520402815,
858.486989117,
852.118821619,
849.372539368,
854.601785487,
851.581327169,
854.097342441,
854.424365741,
850.658400199,
856.351536592,
855.742505682,
859.644113081,
859.07230649,
857.950861653,
854.130157747,
851.882122942,
853.717769206,
855.576927362,
855.142908811,
856.89742377,
859.174625859,
853.711612577,
853.614115637,
855.581455836,
853.274501174,
856.270577259,
858.150331893,
852.20772473,
854.056404469,
852.639547986,
853.887849039,
855.023317386,
857.850651,
853.655441444,
850.290807512,
854.310479299,
857.608645015,
855.11589026,
853.617284705,
856.338820206,
859.168372262,
855.062165645,
854.990862127,
854.949184225,
855.213361736,
854.801102951,
856.494974387,
851.679929281,
857.26586964,
854.692755671,
853.570790985,
855.388969386,
852.715302979,
856.122591637,
853.703143651,
855.555890505,
856.539559146,
860.032919825,
857.263874341,
850.444438049,
851.402144,
857.600864737,
858.06857798,
857.86472097,
853.675809626,
850.309915038,
853.282354172,
854.237718802,
856.592636356,
854.072922671,
852.111923705,
852.070334086,
852.923390153,
857.21810704,
854.429268538,
853.187268749,
856.708110772,
855.140748346,
853.657497987,
850.538060452,
855.254862161,
848.427497416,
860.017077212,
855.573070728,
852.624760301,
854.435690774,
855.056790427,
854.35955028,
852.66088018,
855.053277528,
850.686367205,
858.530592862,
852.08017397,
854.174002565,
851.098237534,
856.300248296,
856.18325018,
854.622549574,
855.991015101,
854.416508876,
855.830359734,
853.133952309,
853.154392647,
856.042371736,
853.475826027,
856.078501823,
851.554466601,
852.662307547,
859.724945671,
856.706508697,
853.701424805,
858.27063211,
857.206175735,
859.676469405,
854.653109792,
861.114645229,
860.372992472,
856.810112321,
860.367058404,
854.133034321,
852.05624698,
857.65790918,
857.03901377,
853.183006061,
854.54033114,
850.014693551,
856.067677959,
853.753589904,
852.223483251,
850.979500628,
858.351321973,
851.449223478,
854.228845211,
857.12928543,
854.130058601,
854.945624379,
854.655530172,
852.733569144,
859.481844587,
857.610710513,
856.504168069,
853.867030525,
853.519852297,
859.969444833,
852.871057898,
861.546097791,
859.605232351,
855.286550355,
858.497878969,
854.225820093,
852.465943679,
851.33886306,
852.885816268,
856.910015992,
858.334100568,
856.804288981,
859.852485529,
853.604836015,
858.217289112,
851.218172549,
859.180910238,
854.946402875,
858.649411768,
853.841617741,
857.00608015,
858.950564754,
856.801772239,
858.74545266,
854.490836435,
853.93822416,
]
Mean = 855.036667062
Std = 2.91585533739
# Process the raw data coming from the ADC to get the measurements statistics.
# Requires the "data_raw.py" file.
#
# 500 experiments are processed in this script. Each experiment consists in
# measuring the delay between two pulses. The delay stays the same for all
# the experiments to be able to quantify the TDC rms error on the measurement.
# The ADC outputs arrays of 1024 points for each channel and each experiment and
# the pretrigger is set to 10 samples.
#
# Only the samples from 15 to 125 are taken into account to do the fitting (cfr.
# documentation).
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy.signal import butter, lfilter, freqz
import data_raw
import math
import matplotlib.mlab as mlab
from matplotlib2tikz import save as tikz_save
from scipy import signal
FS = 100. # Set the sampling frequency in MHz
# Mathematical model for the fitting
def dampedSine(xdata, tau, A, f, delay_ps, offset):
return (A*np.sin(2*np.pi*f/FS*xdata + 2*np.pi*f*delay_ps/1e6)
*np.exp(-tau*xdata) + offset)
nbr_exp = len(data_raw.t)
delays = np.arange(nbr_exp, dtype = np.float)
amplitudes = np.arange(nbr_exp, dtype = np.float)
frequencies = np.arange(nbr_exp, dtype = np.float)
# Fitting for each experiment on each channel separately. Delay, amplitude and
# frequency are saved.
for i in range (0, nbr_exp):
popt, popc = (curve_fit(dampedSine, data_raw.t[i][10:120],
data_raw.chan_[i][15:125], p0=(2.66e-2, -6e3, 15., 0, 0),
bounds = ([-np.inf, -np.inf, -np.inf, - np.inf, - np.inf],
[np.inf, np.inf , np.inf, np.inf, np.inf])))
delays[i] = popt[3]
amplitudes[i] = popt[1]
frequencies[i] = popt[2]
result = np.arange(math.floor(nbr_exp/2), dtype = np.float)
# Correcting the computed delay by adding or removing a period.
for i in range(0, math.floor(nbr_exp/2)):
if (delays[i*2] < 0 and delays[i*2+1] < 0 and
amplitudes[i*2] < 0 and amplitudes[i*2+1] < 0):
print("case1")
measured_delay = (delays[i*2] - delays[i*2+1]
- 1/frequencies[i*2+1]/2*1e6
+ 1/frequencies[i*2]/2*1e6)
elif(delays[i*2] < 0 and delays[i*2+1] < 0 and
amplitudes[i*2] < 0 and amplitudes[i*2+1] > 0):
print("case2")
measured_delay = delays[i*2] - delays[i*2+1]
elif(delays[i*2] < 0 and delays[i*2+1] < 0 and
amplitudes[i*2] > 0 and amplitudes[i*2+1] < 0):
print("case3")
measured_delay = (delays[i*2] - delays[i*2+1]
+ 1/frequencies[i*2+1]/2*1e6
- 1/frequencies[i*2]*1e6)
elif(delays[i*2] < 0 and delays[i*2+1] < 0 and
amplitudes[i*2] > 0 and amplitudes[i*2+1] > 0):
print("case4")
measured_delay = delays[i*2] - delays[i*2+1]
elif(delays[i*2] < 0 and delays[i*2+1] > 0 and
amplitudes[i*2] < 0 and amplitudes[i*2+1] < 0):
print("case5")
measured_delay = (delays[i*2] - delays[i*2+1]
- 1/frequencies[i*2+1]/2*1e6
+ 1/frequencies[i*2]/2*1e6)
elif(delays[i*2] < 0 and delays[i*2+1] > 0 and
amplitudes[i*2] < 0 and amplitudes[i*2+1] > 0):
print("case6")
measured_delay = (delays[i*2]
- delays[i*2+1]
+ 1/frequencies[i*2]/2*1e6)
elif(delays[i*2] < 0 and delays[i*2+1] > 0 and
amplitudes[i*2] > 0 and amplitudes[i*2+1] < 0):
print("case7")
measured_delay = (delays[i*2] - delays[i*2+1]
- 1/frequencies[i*2+1]/2*1e6
+ 1/frequencies[i*2]*1e6)
elif(delays[i*2] < 0 and delays[i*2+1] > 0 and
amplitudes[i*2] > 0 and amplitudes[i*2+1] > 0):
print("case8")
measured_delay = delays[i*2] - delays[i*2+1]
elif(delays[i*2] > 0 and delays[i*2+1] < 0 and
amplitudes[i*2] < 0 and amplitudes[i*2+1] < 0):
print("case9")
measured_delay = (delays[i*2] - delays[i*2+1]
+ 1/frequencies[i*2]/2*1e6
- 1/frequencies[i*2+1]/2*1e6)
elif(delays[i*2] > 0 and delays[i*2+1] < 0 and
amplitudes[i*2] < 0 and amplitudes[i*2+1] > 0):
print("case10")
measured_delay = (-1/frequencies[i*2]/2*1e6
+ delays[i*2] - delays[i*2+1])
elif(delays[i*2] > 0 and delays[i*2+1] < 0 and
amplitudes[i*2] > 0 and amplitudes[i*2+1] < 0):
print("case11")
measured_delay = (delays[i*2] - delays[i*2+1]
- 1/frequencies[i*2+1]/2*1e6)
elif(delays[i*2] > 0 and delays[i*2+1] < 0 and
amplitudes[i*2] > 0 and amplitudes[i*2+1] > 0):
print("case12")
measured_delay = (delays[i*2] - delays[i*2+1]
- 1/frequencies[i*2+1]*1e6
+ 1/frequencies[i*2]*1e6)
elif(delays[i*2] > 0 and delays[i*2+1] > 0 and
amplitudes[i*2] < 0 and amplitudes[i*2+1] < 0):
print("case13")
measured_delay = (delays[i*2] - delays[i*2+1]
- 1/frequencies[i*2+1]/2*1e6
+ 1/frequencies[i*2]/2*1e6)
elif(delays[i*2] > 0 and delays[i*2+1] > 0 and
amplitudes[i*2] < 0 and amplitudes[i*2+1] > 0):
print("case14")
measured_delay = (delays[i*2] - delays[i*2+1]
+ 1/frequencies[i*2]/2*1e6)
elif(delays[i*2] > 0 and delays[i*2+1] > 0 and
amplitudes[i*2] > 0 and amplitudes[i*2+1] < 0):
print("case15")
measured_delay = (delays[i*2] - delays[i*2+1]
- 1/frequencies[i*2+1]/2*1e6)
elif(delays[i*2] > 0 and delays[i*2+1] > 0 and
amplitudes[i*2] > 0 and amplitudes[i*2+1] > 0):
print("case16")
measured_delay = delays[i*2] - delays[i*2+1]
else:
print("error")
measured_delay = delays[i*2] - delays[i*2+1]
result[i] = measured_delay
print(str(result[i]) + ", " + str(delays[2*i]) + ", " + str(delays[2*i+1]))
# Printing and plotting the gaussian of the results.
print(np.std(result))
print(np.mean(result))
n, bins, patches= plt.hist(result, bins = np.arange(np.min(result)-15,
np.max(result)+15), normed = 1)
mean = np.mean(result)
std = np.std(result)
y = mlab.normpdf(bins, mean, std)
plt.plot(bins,y, 'r--')
plt.xlabel("Delay")
plt.ylabel("Occurrence")
plt.show()
# Delay estimation using the DFT
# ------------------------------
#
# The phase of each channel is measured by computing the signal DFT at one
# frequency (The main oscillating frequency). The delay between the signals is
# computed by computing the phase difference
#
# Import packages
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal,optimize
from textwrap import wrap
from cmath import *
# Startup values
F = 100. # Set the frequence of the signal in MHz
FS = 125. # Set the sampling frequency in MHz
NBR_SAMPLES = 64 # Set the number of samples taken for the calculation
ENOB = 12. # ENOB of the ADC
V_MAX = 1. # Voltage range of the ADC (V_MAX = 1V => 2Vpp)
SNR = 1e6 # SNR of the input signal
NBR_TESTS = 32 # Number of tests to be done for one delay
NBR_STEPS = 270 # Number of tests to be done
RMS_JITTER = 150. # RMS jitter in fs
delay_ps1 = 0. # Delay for the first sine
delay_ps2 = 0. # Delay for the second sine
# For multiple test only. This variable sets the delay increment between
# each test.
incr1 = 6.
incr2 = 26.
# Return the signal quantized
def quantize(signal, nbr_bits, max_val):
possible_val = np.linspace(-max_val, max_val, 2**nbr_bits)
switching_val = np.zeros(len(possible_val) - 1)
for i in range (0, len(possible_val) - 1):
switching_val[i] = (possible_val[i] + possible_val[i + 1])/2
sampled = []
for sample in signal:
index = 0
while index < len(switching_val) and sample > switching_val[index]:
index += 1
sampled.append(possible_val[index])
return sampled
# This function adds the apperture and clock jitter to the samples
def AddJitter(sampling_points, fs, rms_jitter):
nbr_samples = len(sampling_points)
jittered = np.zeros(nbr_samples)
jittered = sampling_points + np.random.normal(0, rms_jitter*fs/1e9,
nbr_samples)
return jittered
# Create the model
ts = np.arange(NBR_SAMPLES)
model_sine = np.sin(2*np.pi*F/FS*ts)
model_cos = np.cos(2*np.pi*F/FS*ts)
max_error = np.zeros(NBR_STEPS)
std_devi = np.zeros(NBR_STEPS)
delay = np.zeros(NBR_STEPS)
mean_error = np.zeros(NBR_STEPS)
for e in range (0, NBR_STEPS):
tmp_res = np.zeros(NBR_TESTS)
for t in range (0, NBR_TESTS):
ts1 = AddJitter(np.arange(NBR_SAMPLES), FS, RMS_JITTER)
ts2 = AddJitter(np.arange(NBR_SAMPLES), FS, RMS_JITTER)
# Create one sine
hanning = np.hanning(NBR_SAMPLES)
sine1 = np.sin(2*np.pi*F/FS*ts + 2*np.pi*F*delay_ps1/1e6)
sine1 = sine1 + np.random.normal(0, np.sqrt(1/SNR), NBR_SAMPLES)
sine1 = quantize(sine1, ENOB, V_MAX)
# Create the second sine
sine2 = np.sin(2*np.pi*F/FS*ts + 2*np.pi*F*delay_ps2/1e6)
sine2 = sine2 + np.random.normal(0, np.sqrt(1/SNR), NBR_SAMPLES)
sine2 = quantize(sine2, ENOB, V_MAX)
z1 = (np.sum(model_cos * sine1 * hanning)
- 1j * np.sum(model_sine * sine1 * hanning))
z2 = (np.sum(model_cos * sine2 * hanning)
- 1j * np.sum(model_sine * sine2 * hanning))
del1 =((phase(z1) + np.pi / 2) / 2 / np.pi / F) * 1e6
del2 =((phase(z2) + np.pi / 2) / 2 / np.pi / F) * 1e6
measured_delay = del2 - del1
real_delay = delay_ps2 - delay_ps1
tmp_res[t] = measured_delay - real_delay
mean_error[e] += tmp_res[t]
mean_error[e] /= NBR_TESTS
std_devi[e] = np.std(tmp_res)
max_error[e] = np.max(abs(tmp_res))
delay[e] = real_delay
plt.show()
print('Error = ' + str(max_error[e])
+ ' ps. ' + 'Real delay = ' + str(delay_ps1 - delay_ps2))
print("The standard deviation = " + str(std_devi[e]) + " ps.")
print("The mean error = " + str(mean_error[e]) + " ps.")
delay_ps2 += incr2
delay_ps1 += incr1
if (NBR_STEPS>1):
fig = plt.figure()
ax = fig.add_subplot(111)
title = ax.set_title("\n".join(wrap("Error vs delay. F = " + str(F)
+ ". FS = " + str(FS) + ". NBR_SAMPLES = "
+ str(NBR_SAMPLES) + ". ENOB = " + str(ENOB)
+ ". SNR = " + str(10*np.log10(SNR)) + " dB."
+ " The standard deviation = "
+ str(np.std(max_error))
+ " ps." + " Maximum deviation = "
+ str(np.amax(max_error)) + " clock jitter = "
+ str(RMS_JITTER) + " fs RMS"
+ ". Nbr of tests for each delay = "
+ str(NBR_TESTS), 83)))
# line1, = ax.plot(delay,max_error, label = "Max error")
line1 = ax.errorbar(delay, mean_error, std_devi, label = "Mean error")
# plt.legend(handler_map = {line1: HandlerLine2D(numpoints = 4)})
fig.tight_layout()
title.set_y(1.05)
fig.subplots_adjust(top = 0.8)
plt.ylabel('Error [ps]')
plt.xlabel('Delay [ps]')
plt.show()
# Frequency Influence Simulation
# ------------------------------
#
# This script is used to estimate the influence of the damped sinewave frequency
# on the delay measurements done by the fitting algorithm (final solution,
# used in the tdc_demo.py algorithm).
# The simulation computes the several times (NBR_TESTS) one delay and save the
# standard deviation on the measurements. This is done to multiple delays in
# order to see the precision behaviour over the frequency.
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal,optimize
from textwrap import wrap
import sys
import scipy.linalg as la
import pylab
import sys
from scipy.optimize import curve_fit
from matplotlib2tikz import save as tikz_save
import math
np.set_printoptions(threshold=np.nan)
NBR_SAMPLES = 110 # Number of samples taken into account
NBR_TESTS = 1000 # Numbers of tests with the same parameters
F = 10 # Start frequency
SNR = 4e6 # Signal to Noise Ratio
FS = 100 # Sampling Frequency
NBR_STEPS = 50 # Number of different frequencies at which the test is done
DAMPING = 2.54e-2
NBR_EXP = 35
# root square sum of the adc JITTER (0.135 ps and the clock JITTER 0.05 ps)
JITTER = 0.386
def dampedSine(xdata, tau, A, freq, delay_ps, offset):
return (A*np.sin(2*np.pi*freq/FS*xdata
+ 2*np.pi*freq*delay_ps/1e6)
* np.exp(-tau*xdata) + offset)
delay1 = np.empty(NBR_TESTS)
delay2 = np.empty(NBR_TESTS)
amplitude1 = np.empty(NBR_TESTS)
frequency1 = np.empty(NBR_TESTS)
amplitude2 = np.empty(NBR_TESTS)
frequency2 = np.empty(NBR_TESTS)
result = np.empty(NBR_TESTS)
tpopt1 = np.empty([NBR_TESTS,5])
tpopt2 = np.empty([NBR_TESTS,5])
std = np.empty(NBR_EXP)
error = np.empty(NBR_STEPS)
variance = np.empty(NBR_STEPS)
mean = np.empty(NBR_EXP)
# Fitting
for j in range(0, NBR_EXP):
for i in range (0, NBR_TESTS):
t = np.arange(0, NBR_SAMPLES)
t = t + np.random.random_sample()
# Adding JITTER
t = t + np.random.normal(0, JITTER*FS/1e6, NBR_SAMPLES)
signal1 = dampedSine(t, DAMPING, 1, F, 8452, 0)
signal1 = signal1 + np.random.normal(0, np.sqrt(1/SNR), NBR_SAMPLES)
tpopt1[i], popc = curve_fit(dampedSine, np.arange(NBR_SAMPLES-1),
signal1[1:], p0=(2e-2, 1, F, 0, 0))
delay1[i] = tpopt1[i][3]
amplitude1[i] = tpopt1[i][1]
frequency1[i] = tpopt1[i][2]
# Second signal has a frequency a bit different (to match reality)
signal2 = dampedSine(t, DAMPING, 1, F +2 , 0, 0)
signal2 = signal2 + np.random.normal(0, np.sqrt(1/SNR), NBR_SAMPLES)
tpopt2[i], popc = curve_fit(dampedSine,
np.arange(NBR_SAMPLES-1),
signal2[1:], p0=(2e-2, 1, F, 0, 0))
delay2[i] = tpopt2[i][3]
amplitude2[i] = tpopt2[i][1]
frequency2[i] = tpopt2[i][2]
print(F)
# Correcting the delay using the frequency
for i in range(0, NBR_TESTS):
if (delay1[i] < 0 and delay2[i] < 0 and
amplitude1[i] < 0 and amplitude2[i] < 0):
print("case1")
measured_delay = (delay1[i] - delay2[i]
- 1/frequency2[i]/2*1e6
+ 1/frequency1[i]/2*1e6)
elif(delay1[i] < 0 and delay2[i] < 0 and
amplitude1[i] < 0 and amplitude2[i] > 0):
print("case2")
measured_delay = delay1[i] - delay2[i]
elif(delay1[i] < 0 and delay2[i] < 0 and
amplitude1[i] > 0 and amplitude2[i] < 0):
print("case3")
measured_delay = (delay1[i] - delay2[i]
+ 1/frequency1[i]*1e6
- 1/frequency2[i]/2*1e6)
elif(delay1[i] < 0 and delay2[i] < 0 and
amplitude1[i] > 0 and amplitude2[i] > 0):
print("case4")
measured_delay = (delay1[i] - delay2[i]
- 1/frequency2[i]*1e6
+ 1/frequency1[i]*1e6)
elif(delay1[i] < 0 and delay2[i] > 0 and
amplitude1[i] < 0 and amplitude2[i] < 0):
print("case5")
measured_delay = (delay1[i] - delay2[i]
- 1/frequency2[i]/2*1e6
+ 1/frequency1[i]/2*1e6)
elif(delay1[i] < 0 and delay2[i] > 0 and
amplitude1[i] < 0 and amplitude2[i] > 0):
print("case6")
measured_delay = (delay1[i]
- delay2[i]
+ 1/frequency1[i]/2*1e6)
elif(delay1[i] < 0 and delay2[i] > 0 and
amplitude1[i] > 0 and amplitude2[i] < 0):
print("case7")
measured_delay = (delay1[i] - delay2[i]
- 1/frequency2[i]/2*1e6
+ 1/frequency1[i]*1e6)
elif(delay1[i] < 0 and delay2[i] > 0 and
amplitude1[i] > 0 and amplitude2[i] > 0):
print("case8")
measured_delay = delay1[i] - delay2[i]
elif(delay1[i] > 0 and delay2[i] < 0 and
amplitude1[i] < 0 and amplitude2[i] < 0):
print("case9")
measured_delay = (delay1[i] - delay2[i]
+ 1/frequency1[i]/2*1e6
- 1/frequency2[i]/2*1e6)
elif(delay1[i] > 0 and delay2[i] < 0 and
amplitude1[i] < 0 and amplitude2[i] > 0):
print("case10")
measured_delay = (-1/frequency1[i]/2*1e6
+ delay1[i] - delay2[i])
elif(delay1[i] > 0 and delay2[i] < 0 and
amplitude1[i] > 0 and amplitude2[i] < 0):
print("case11")
measured_delay = (delay1[i] - delay2[i]
- 1/frequency2[i]/2*1e6)
elif(delay1[i] > 0 and delay2[i] < 0 and
amplitude1[i] > 0 and amplitude2[i] > 0):
print("case12")
measured_delay = (delay1[i] - delay2[i]
- 1/frequency2[i]*1e6
+ 1/frequency1[i]*1e6)
elif(delay1[i] > 0 and delay2[i] > 0 and
amplitude1[i] < 0 and amplitude2[i] < 0):
print("case13")
measured_delay = (delay1[i] - delay2[i]
- 1/frequency2[i]/2*1e6
+ 1/frequency1[i]/2*1e6)
elif(delay1[i] > 0 and delay2[i] > 0 and
amplitude1[i] < 0 and amplitude2[i] > 0):
print("case14")
measured_delay = (delay1[i] - delay2[i]
+ 1/frequency1[i]/2*1e6)
elif(delay1[i] > 0 and delay2[i] > 0 and
amplitude1[i] > 0 and amplitude2[i] < 0):
print("case15")
measured_delay = (delay1[i] - delay2[i]
- 1/frequency2[i]/2*1e6)
elif(delay1[i] > 0 and delay2[i] > 0 and
amplitude1[i] > 0 and amplitude2[i] > 0):
print("case16")
measured_delay = delay1[i] - delay2[i]
else:
print("error")
measured_delay = delay1[i] - delay2[i]
result[i] = measured_delay
print("result = " + str(result[i]))
std[j] = np.std(result)
F = F + 1
print("std = " + str(std[j]))
print(std)
plt.show()
plt.plot(np.linspace(10, 10 + NBR_EXP-1, NBR_EXP), std, 'b')
plt.xlabel("Frequency [MHz]")
plt.ylabel("Jitter [ps]")
plt.show()
\ No newline at end of file
......@@ -18,11 +18,18 @@
# In the function MinusCorrLag0, we compute function :
# (correlation without lag) = f(delay)
# To realise this, we calculate new samples from one of the sines.
# These samples are computed at time delay from the previous ones.
# These samples are computed at time delay from the first ones.
# The method used to compute these samples is the sinc interpolation.
# According to the sampling theorem, a signal can be reconstructed
# form its samples by making the convolution between the samples and
# a sinc function. This function corresponds to the time response of
# a notch filter with a cut-off frequency at the Nyquist frequency.
#
# Then the value of the correlation between the new samples and the
# samples from the other sine is computed. The function returns
# the oposite of the correlation's value estimated at lag = 0.
# the negative value of the correlation's value estimated at lag = 0.
# This is necessary because the Brent's method is done to compute
# the minimum of a function and we are looking for its maximum.
#
# The function (correlation without lag) = f(delay)
# is computed and its maximum is determined by the Brent's method.
......@@ -34,17 +41,20 @@ import matplotlib.pyplot as plt
import numpy as np
from scipy import signal,optimize
from textwrap import wrap
from pylab import *
from matplotlib2tikz import save as tikz_save
from matplotlib.legend_handler import HandlerLine2D
# Startup values
F = 50 # Set the frequence of the signal in MHz
FS = 125 # Set the sampling frequency in MHz
NBR_SAMPLES = 64 # Set the number of samples taken for the calculation
ENOB = 12 # ENOB of the ADC
V_MAX = 1 # Voltage range of the ADC (V_MAX = 1V => 2Vpp)
SNR = 1e6 # SNR of the input signal
NBR_TESTS = 100 # Number of tests to be done
RMS_JITTER = 150 # In fs
delay_ps = 0 # Starting value for the tests
F = 50. # Set the frequence of the signal in MHz
FS = 125. # Set the sampling frequency in MHz
NBR_SAMPLES = 64 # Set the number of samples taken for the calculation
ENOB = 12. # ENOB of the ADC
V_MAX = 1. # Voltage range of the ADC (V_MAX = 1V => 2Vpp)
SNR = 1e6 # SNR of the input signal
NBR_TESTS = 15 # Number of tests to be done
NBR_STEPS = 15 # Number of tests per step to be done
RMS_JITTER = 150. # RMS jitter on the sampling frequency in fs
delay_ps = 15. # Starting value for the tests
# Return the signal quantized
......@@ -61,14 +71,9 @@ def quantize(signal, nbr_bits, max_val):
sampled.append(possible_val[index])
return sampled
# Return the best possible estimation
def CRLB(snr, nbr_samples, amplitude):
CRLB = 2*1/snr*amplitude / (nbr_samples*amplitude**2)
return CRLB
# Return the opposite of the function :
# (correlation without lag) = f(delay).
# The minimum is sent to be used with the Brent's
# The negative value is sent to be used with the Brent's
# interpolation method.
def MinusCorrLag0(delay, fixed_sig, delayed_sig, apod):
new_points = np.zeros(NBR_SAMPLES)
......@@ -79,64 +84,75 @@ def MinusCorrLag0(delay, fixed_sig, delayed_sig, apod):
# Compute the points with the sinc interpolation
new_points[m] += fixed_sig[i]*np.sinc(abs(i - abscisse[m]))
corr = signal.correlate(new_points*apod, delayed_sig*apod)
lag0 = 0
# Interpolation of the correlation at lag = 0
for i in range(0, NBR_SAMPLES*2 - 1):
lag0 += corr[i] * np.sinc(abs(i - (nbr_samples - 1)))
return -lag0
corr_at_lag0 = corr[nbr_samples-1]
return -corr_at_lag0
def AddJitter(sampling_points, fs, rms_jitter):
nbr_samples = len(sampling_points)
jittered = np.zeros(nbr_samples)
jittered = sampling_points + np.random.normal(0, rms_jitter*fs/1e9, nbr_samples)
jittered = sampling_points + np.random.normal(0,
rms_jitter*fs/1e9,
nbr_samples)
return jittered
ts1 = AddJitter(np.arange(NBR_SAMPLES), FS, RMS_JITTER)
ts2 = AddJitter(np.arange(NBR_SAMPLES), FS, RMS_JITTER)
# Create fixed sine
sine1 = np.sin(2*np.pi*F/FS*ts1)
sine1 = sine1 + np.random.normal(0, np.sqrt(1/SNR), NBR_SAMPLES)
sine1 = quantize(sine1, ENOB, V_MAX)
result = np.zeros(NBR_TESTS)
delay = np.zeros(NBR_TESTS)
for e in range (0, NBR_TESTS):
sine2 = np.sin(2*np.pi*F/FS*ts2 + 2*np.pi*F*delay_ps/1e6)
sine2 = sine2 + np.random.normal(0, np.sqrt(1/SNR), NBR_SAMPLES)
sine2 = quantize(sine2, ENOB, V_MAX)
# test with the hanning window
hanning = np.hanning(NBR_SAMPLES)
# Function optimisation using Brent's method
max = optimize.brent(MinusCorrLag0, (sine1, sine2, hanning), maxiter = 100)
result[e] = max/FS * 1e6 - delay_ps
delay = np.zeros(NBR_STEPS)
max_error = np.zeros(NBR_STEPS)
std_devi = np.zeros(NBR_STEPS)
mean_error = np.zeros(NBR_STEPS)
for e in range (0, NBR_STEPS):
tmp_res = np.zeros(NBR_TESTS)
for t in range (0, NBR_TESTS):
sine2 = np.sin(2*np.pi*F/FS*ts2 + 2*np.pi*F*delay_ps/1e6)
sine2 = sine2 + np.random.normal(0, np.sqrt(1/SNR), NBR_SAMPLES)
sine2 = quantize(sine2, ENOB, V_MAX)
# Creation of the hanning window
hanning = np.hanning(NBR_SAMPLES)
# Function optimisation using Brent's method
max = optimize.brent(MinusCorrLag0,
(sine1, sine2, hanning),
maxiter = 100)
tmp_res[t] = max/FS * 1e6 - delay_ps
mean_error[e] += tmp_res[t]
# Taking the maximum error
mean_error[e] /= NBR_TESTS
std_devi[e] = np.std(tmp_res)
max_error[e] = np.max(abs(tmp_res))
delay[e] = delay_ps
print('Error = ' + str(result[e])
+ ' ps. ' + 'Real delay = ' + str(delay_ps))
print('Max Error = ' + str(max_error[e])
+ ' ps. ' + 'Real delay = ' + str(delay_ps))
delay_ps += 1/FS * 1e6 /NBR_TESTS/4
print('Cramer = ' + str(np.sqrt(CRLB(SNR, NBR_SAMPLES, 1))*1e6/2/np.pi/F))
print("The standart deviation = " + str(np.std(result))
+ " ps.")
print("The standard deviation = " + str(std_devi[e])
+ " ps.")
print("The mean error = " + str(mean_error[e]) + " ps.")
# Plot everything
if (NBR_TESTS>1):
if (NBR_STEPS>1):
fig = plt.figure()
ax = fig.add_subplot(111)
title = ax.set_title("\n".join(wrap("Error vs delay. F = " + str(F)
+ ". FS = " + str(FS) + ". NBR_SAMPLES = "
+ str(NBR_SAMPLES) + ". ENOB = " + str(ENOB)
+ ". SNR = " + str(10*np.log10(SNR)) + " dB."
+ " The standart deviation = " + str(np.std(result))
+ " ps." + " clock jitter = " + str(RMS_JITTER)
+ " fs RMS", 65)))
ax.plot(delay,result)
+ " The standard deviation = "
+ str(np.std(max_error))
+ " ps." + " Maximum deviation = "
+ str(np.amax(max_error)) + " clock jitter = "
+ str(RMS_JITTER) + " fs RMS"
+ ". Nbr of tests for each delay = "
+ str(NBR_TESTS), 83)))
# line1, = ax.plot(delay,max_error, label = "Max error")
line1 = ax.errorbar(delay,mean_error,std_devi, label = "Mean error")
# plt.legend(handler_map = {line1: HandlerLine2D(numpoints = 4)})
fig.tight_layout()
title.set_y(1.05)
fig.subplots_adjust(top = 0.8)
plt.ylabel('Error (ps)')
plt.xlabel('Delay [ps]')
plt.show()
# Delay estimation using the sinc interpolation
# ---------------------------------------------
#
# This script is made to compute the delay between two sampled
# sinewaves by fitting with a mathematical model.
#
# It can be used by two different ways.
# 1: Set NBR_STEPS to 1 to calculate one particular delay set
# by the delay_ps variable.
# 2: Set NBR_STEPS to more than 1 to make different tests
# with a time shiffting increment = 1/FS/NBR_STEPS in ps. An
# offset can be added by setting delay_ps to a value different
# than 0.
#
# Two sine are created with a delay between them. These sines are
# sampled and quantized before beeing processed.
#
# First, we do the fitting of the samples from one sine with
# a high resolution model. We can deduce the time of arrival
# of the first sine. Then, the same is done with the samples
# comming from the other sine. By making the substraction of
# the two time of arrival, we can deduce the delay between the
# two original sines.
#
# The fitting is done by checking the position giving the lowest
# least square error. Basicly, that means that we just time shift
# the samples and then compute the difference between the
# values of the samples and the values of the samples form the
# model at the same time.
#
# To find this minimum, we use the Brent's optimisation method.
#
#
# Import packages
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal,optimize
from textwrap import wrap
# Startup values
F = 50. # Set the frequence of the signal in MHz
FS = 125. # Set the sampling frequency in MHz
NBR_SAMPLES = 128 # Set the number of samples taken for the calculation
ENOB = 12. # ENOB of the ADC
V_MAX = 1. # Voltage range of the ADC (V_MAX = 1V => 2Vpp)
SNR = 1e6 # SNR of the input signal
NBR_TESTS = 30 # Number of tests to be done for one delay
NBR_STEPS = 20 # Number of tests to be done
RMS_JITTER = 150. # RMS jitter in fs
delay_ps1 = 35. # Delay for the first sine
delay_ps2 = 261.4 # Delay for the second sine
# For multiple test only. This variable set the delay increment between
# each test.
incr1 = 12.
incr2 = 51.
# Return the signal quantized
def quantize(signal, nbr_bits, max_val):
possible_val = np.linspace(-max_val, max_val, 2**nbr_bits)
switching_val = np.zeros(len(possible_val) - 1)
for i in range (0, len(possible_val) - 1):
switching_val[i] = (possible_val[i] + possible_val[i + 1])/2
sampled = []
for sample in signal:
index = 0
while index < len(switching_val) and sample > switching_val[index]:
index += 1
sampled.append(possible_val[index])
return sampled
def AddJitter(sampling_points, fs, rms_jitter):
nbr_samples = len(sampling_points)
jittered = np.zeros(nbr_samples)
jittered = sampling_points + np.random.normal(0,
rms_jitter*fs/1e9,
nbr_samples)
return jittered
# Return the square of the difference between the time shifted
# samples and the points of the model at the same time. The best
# fitting position corresponds to the lowest error.
def MaxFit (shift, model_sig, sampled_sig, fs, nbr_samples):
fit = 0
for a in range (0, NBR_SAMPLES):
fit += (model_sig[a*1/FS*1e6 + shift] - sampled_sig[a])**2
return fit
# Create the model
time1 = np.arange((NBR_SAMPLES/FS+1)*1e6) # resolution of 1 ps
model_sine = np.sin(2*np.pi*F/1e6*time1)
max_error = np.zeros(NBR_STEPS)
std_devi = np.zeros(NBR_STEPS)
delay = np.zeros(NBR_STEPS)
mean_error = np.zeros(NBR_STEPS)
for e in range (0, NBR_STEPS):
tmp_res = np.zeros(NBR_TESTS)
for t in range (0, NBR_TESTS):
ts1 = AddJitter(np.arange(NBR_SAMPLES), FS, RMS_JITTER)
ts2 = AddJitter(np.arange(NBR_SAMPLES), FS, RMS_JITTER)
# Create one sine
sine1 = np.sin(2*np.pi*F/FS*ts1 + 2*np.pi*F*delay_ps1/1e6)
sine1 = sine1 + np.random.normal(0, np.sqrt(1/SNR), NBR_SAMPLES)
sine1 = quantize(sine1, ENOB, V_MAX)
# Create the second sine
sine2 = np.sin(2*np.pi*F/FS*ts2 + 2*np.pi*F*delay_ps2/1e6)
sine2 = sine2 + np.random.normal(0, np.sqrt(1/SNR), NBR_SAMPLES)
sine2 = quantize(sine2, ENOB, V_MAX)
# Looking for the time shift giving the lowest error
# using Brent's method (a variant of the parabolic interpolation)
# This is done for the first sine and then for the second.
# The research for this minimum is done within the interval of
# one sampling period. The reason for that is that the MaxFit
# function is returnoing the error for all the samples and not
# only the first one.
del1 = optimize.brent(MaxFit,
(model_sine, sine1, FS, NBR_SAMPLES),
brack = (0, 1/FS*1e6-1),
maxiter = 100)
del2 = optimize.brent(MaxFit,
(model_sine, sine2, FS, NBR_SAMPLES),
brack = (0, 1/FS*1e6-1),
maxiter = 100)
measured_delay = del2 - del1
real_delay = delay_ps2 - delay_ps1
tmp_res[t] = measured_delay - real_delay
mean_error[e] += tmp_res[t]
mean_error[e] /= NBR_TESTS
std_devi[e] = np.std(tmp_res)
max_error[e] = np.max(abs(tmp_res))
delay[e] = real_delay
print('Error = ' + str(max_error[e])
+ ' ps. ' + 'Real delay = ' + str(delay_ps1 - delay_ps2))
print("The standard deviation = " + str(std_devi[e]) + " ps.")
print("The mean error = " + str(mean_error[e]) + " ps.")
delay_ps2 += incr2
delay_ps1 += incr1
if (NBR_STEPS>1):
fig = plt.figure()
ax = fig.add_subplot(111)
title = ax.set_title("\n".join(wrap("Error vs delay. F = " + str(F)
+ ". FS = " + str(FS) + ". NBR_SAMPLES = "
+ str(NBR_SAMPLES) + ". ENOB = " + str(ENOB)
+ ". SNR = " + str(10*np.log10(SNR)) + " dB."
+ " The standard deviation = "
+ str(np.std(max_error))
+ " ps." + " Maximum deviation = "
+ str(np.amax(max_error)) + " clock jitter = "
+ str(RMS_JITTER) + " fs RMS"
+ ". Nbr of tests for each delay = "
+ str(NBR_TESTS), 83)))
# line1, = ax.plot(delay,max_error, label = "Max error")
line1 = ax.errorbar(delay, mean_error, std_devi, label = "Mean error")
# plt.legend(handler_map = {line1: HandlerLine2D(numpoints = 4)})
fig.tight_layout()
title.set_y(1.05)
fig.subplots_adjust(top = 0.8)
plt.ylabel('Error [ps]')
plt.xlabel('Delay [ps]')
plt.show()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment