Commit 1badd3be authored by Christian Schneider's avatar Christian Schneider
Browse files

Merged

parents d2461113 822b9026
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
Created on Tue Apr 9 11:33:36 2019 Created on Tue Apr 9 11:33:36 2019
@author: Oscar @author: Oscar
v1.2.2 - OSC:
- inserted wait for WFA completion in the acquire data function
v1.2.1 - OSC:
- implemented connection to multiple boards when more than one is in the
chassis
v1.2.0 - OSC: v1.2.0 - OSC:
- removed 'SW' trigger mode (useless and it wasn't implemented correctly in this library) and Trigger function - removed 'SW' trigger mode (useless and it wasn't implemented correctly in this library) and Trigger function
- removed 'ChannelUsed' and relative function (it is always asked in the AcquireData function) - removed 'ChannelUsed' and relative function (it is always asked in the AcquireData function)
...@@ -24,8 +29,9 @@ class ADQ14(object): ...@@ -24,8 +29,9 @@ class ADQ14(object):
import ctypes as ct import ctypes as ct
import numpy as np import numpy as np
import copy import copy
import time
version='1.2.0' version='1.2.2'
def __init__(self,board_num = 1): def __init__(self,board_num = 1):
import os import os
...@@ -48,7 +54,7 @@ class ADQ14(object): ...@@ -48,7 +54,7 @@ class ADQ14(object):
self.ADQAPI.ADQControlUnit_FindDevices.argtypes = [self.ct.c_void_p] self.ADQAPI.ADQControlUnit_FindDevices.argtypes = [self.ct.c_void_p]
self.Connect(board_num) self.Connect(board_num)
self.Print_adq_device_revisions()
self.__ADCSF = 1.0 #GSamples/s self.__ADCSF = 1.0 #GSamples/s
...@@ -129,11 +135,29 @@ class ADQ14(object): ...@@ -129,11 +135,29 @@ class ADQ14(object):
#--------------------------------- #---------------------------------
def Connect(self,board_num=1): def Connect(self,board_num=1):
class stwrapper(self.ct.Structure):
""" creates a struct to match emxArray_real_T """
_fields_ = [('HWIFType', self.ct.c_int),
('ProductID', self.ct.c_int),
('VendorID', self.ct.c_uint),
('AddressField1', self.ct.c_int),
('AddressField2', self.ct.c_int),
('DevFile', (self.ct.c_char*64)),
('DeviceInterfaceOpened', self.ct.c_uint),
('DeviceSetupCompleted', self.ct.c_uint)]
self._adq = self.ct.c_void_p(self.ADQAPI.CreateADQControlUnit()) self._adq = self.ct.c_void_p(self.ADQAPI.CreateADQControlUnit())
self.ADQAPI.ADQControlUnit_FindDevices(self._adq)
DEV_NUM=self.ADQAPI.ADQControlUnit_NofADQ(self._adq)
if DEV_NUM==0: nof_devices = self.ct.c_int(0)
e = stwrapper()
success = self.ADQAPI.ADQControlUnit_ListDevices(self._adq,self.ct.pointer(e),self.ct.pointer(nof_devices))
nof_devices = nof_devices.value
if nof_devices==0:
print("WARNING: No device has been found") print("WARNING: No device has been found")
return 0 return 0
...@@ -143,15 +167,23 @@ class ADQ14(object): ...@@ -143,15 +167,23 @@ class ADQ14(object):
print('Error: board_num can\'t be negative!') print('Error: board_num can\'t be negative!')
return 0 return 0
if board_num > DEV_NUM: if board_num > nof_devices:
print("Erro: Selected board number {}, but only {} boards have been found!".format(board_num,DEV_NUM)) print("Erro: Selected board number {}, but only {} boards have been found!".format(board_num,nof_devices))
return 0 return 0
self.devnum = board_num success = success and self.ADQAPI.ADQControlUnit_OpenDeviceInterface(self._adq,board_num-1)
success = success and self.ADQAPI.ADQControlUnit_SetupDevice(self._adq, board_num-1)
self.devnum = 1
self.id = 'ADQ14' #to implement better self.id = 'ADQ14' #to implement better
# Print ADQAPI revision # Print ADQAPI revision
print('ADQAPI loaded, revision {:d}.'.format(self.ADQAPI.ADQAPI_GetRevision())) print('ADQAPI loaded, revision {:d}.'.format(self.ADQAPI.ADQAPI_GetRevision()))
rev=self.Print_adq_device_revisions()
if rev<30e3:
print('WARNING: FPGA revision is not in the correct range, are you sure you are using the right board?\n')
self.Clock_ref() #ext ref activated by def self.Clock_ref() #ext ref activated by def
...@@ -184,6 +216,10 @@ class ADQ14(object): ...@@ -184,6 +216,10 @@ class ADQ14(object):
else : else :
print('SVN Updated\n') print('SVN Updated\n')
return revision[0]
def Blink(self):
self.ADQAPI.ADQ_Blink(self._adq,self.devnum)
def Reset(self,Type='COMM'): def Reset(self,Type='COMM'):
'''function reset([Type='COMM']): '''function reset([Type='COMM']):
...@@ -721,7 +757,7 @@ http://localhost:8988/edit/python_repo/ADQ14.py# tmp = tm ...@@ -721,7 +757,7 @@ http://localhost:8988/edit/python_repo/ADQ14.py# tmp = tm
return data_32bit return data_32bit
""" """
def Acquire_data(self,channel_mask = 3,conversion_to_volt=True): def Acquire_data(self,channel_mask = 3,conversion_to_volt=True,timeout=5):
'''This function start the acquisition, it will wait for the trigger. '''This function start the acquisition, it will wait for the trigger.
''' '''
...@@ -742,6 +778,13 @@ http://localhost:8988/edit/python_repo/ADQ14.py# tmp = tm ...@@ -742,6 +778,13 @@ http://localhost:8988/edit/python_repo/ADQ14.py# tmp = tm
if success == 0: if success == 0:
self.__ADQEXC('STARTERR','ADQ_ATDStartWFA failed!') self.__ADQEXC('STARTERR','ADQ_ATDStartWFA failed!')
#Waiting for WFA
start_time = self.time.time()
while(not self.ADQAPI.ADQ_ATDWaitForWFACompletion(self._adq,self.devnum)):
if (self.time.time()-start_time) > timeout:
self.__BASEEXC('TIMEOUT','WFA failed!')
#getting data #getting data
#init only what is necessary: #init only what is necessary:
......
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
Created on Wed Sep 6 18:09:39 2017 Created on Wed Sep 6 18:09:39 2017
@author: oscar @author: oscar
v2.5.3 - OSC:
- when loading waves in memory, the channels queue is cleaned. Now after
calling the function load_waves_in_AWG_memory, they will be re-queued
automatically
v2.5.2 - OSC: v2.5.2 - OSC:
- inserted the stop_multiple function - inserted the stop_multiple function
- inserted ext port setup functions - inserted ext port setup functions
...@@ -462,7 +467,7 @@ class AWGChannel(object): ...@@ -462,7 +467,7 @@ class AWGChannel(object):
##------------------------------------------------------------------------------------------ a00 AWG class -------------------------------- ##------------------------------------------------------------------------------------------ a00 AWG class --------------------------------
class Awgsigd(object): class Awgsigd(object):
version = '2.5.2' version = '2.5.3'
import keysightSD1 as sigd import keysightSD1 as sigd
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
...@@ -1028,6 +1033,8 @@ class Awgsigd(object): ...@@ -1028,6 +1033,8 @@ class Awgsigd(object):
self.__check_command( self._awg.waveformLoad(wave,n)) self.__check_command( self._awg.waveformLoad(wave,n))
del wave #bugfix del wave #bugfix
for i in range(4):
self.__load_waves_in_channel(i)
#self.time.sleep(0.1) #self.time.sleep(0.1)
def __change_offset_slow(self,channel): def __change_offset_slow(self,channel):
...@@ -1099,8 +1106,6 @@ class Awgsigd(object): ...@@ -1099,8 +1106,6 @@ class Awgsigd(object):
raise ValueError raise ValueError
def setfunc(Channel): def setfunc(Channel):
if load_waves_in_memory:
self.load_waves_in_AWG_memory()
self.__check_channel_number(Channel) self.__check_channel_number(Channel)
tmp = self.channel(Channel) tmp = self.channel(Channel)
...@@ -1121,7 +1126,7 @@ class Awgsigd(object): ...@@ -1121,7 +1126,7 @@ class Awgsigd(object):
pars = pars['PORT'],pars['EDGE'],pars['Sync'] pars = pars['PORT'],pars['EDGE'],pars['Sync']
port_sn = tmp.ext_port_list.index(pars[0]) port_sn = tmp.ext_port_list.index(pars[0])
if port_sn>0: if port_sn>0:
port_sn= int(port_sn+3999) port_sn= int(port_sn+3999) #flags for ext port
self.__check_command(self._awg.AWGtriggerExternalConfig(Channel,port_sn,tmp.trigger_edge_list.index(pars[1]),int(pars[2]))) self.__check_command(self._awg.AWGtriggerExternalConfig(Channel,port_sn,tmp.trigger_edge_list.index(pars[1]),int(pars[2])))
......
...@@ -212,9 +212,6 @@ class circuit(object): ...@@ -212,9 +212,6 @@ class circuit(object):
display_tables((df, df_kappa), display_tables((df, df_kappa),
names=['Main Results', 'Linewidths']) names=['Main Results', 'Linewidths'])
# Plot of data, raw data and (successfully) fitted data if wanted
if plt_res:
cp.plot_cfit(self)
def plot_steps(self): def plot_steps(self):
""" """
...@@ -425,14 +422,14 @@ class Reflection(circuit): ...@@ -425,14 +422,14 @@ class Reflection(circuit):
self.phi0 = np.arcsin(self.yc_norm / self.r_norm) self.phi0 = np.arcsin(self.yc_norm / self.r_norm)
# Fit final circle ##################################################### # Fit final circle #####################################################
ftol = kwargs['ftol'] maxfev = kwargs['maxfev']
if not kwargs['final_mag']: if not kwargs['final_mag']:
self._cir_fit_pars = ft.fit_model_refl(self.freq, self._cir_fit_pars = ft.fit_model_refl(self.freq,
self.circle_norm, self.circle_norm,
Ql_est, absQc_est, fr_est, Ql_est, absQc_est, fr_est,
self.phi0, self.phi0,
self._weights, self._weights,
ftol=ftol) max_nfev=maxfev)
# Calculate quality factors # Calculate quality factors
self.Ql, self.absQc, self.fr, self.phi1 = \ self.Ql, self.absQc, self.fr, self.phi1 = \
np.abs(self._cir_fit_pars[0]) np.abs(self._cir_fit_pars[0])
......
...@@ -196,7 +196,7 @@ def fit_model_notch(freq, data, Ql, absQc, fr, phi0, weights, max_nfev=1000): ...@@ -196,7 +196,7 @@ def fit_model_notch(freq, data, Ql, absQc, fr, phi0, weights, max_nfev=1000):
z1d = np.zeros(data.size * 2, dtype=np.float64) z1d = np.zeros(data.size * 2, dtype=np.float64)
z1d[0:z1d.size:2] = diff.real ** 2 * weights z1d[0:z1d.size:2] = diff.real ** 2 * weights
z1d[1:z1d.size:2] = diff.imag ** 2 * weights z1d[1:z1d.size:2] = diff.imag ** 2 * weights
return z1d.sum() return z1d
f = spopt.least_squares(res, [np.abs(Ql), np.abs(absQc), fr, phi0], f = spopt.least_squares(res, [np.abs(Ql), np.abs(absQc), fr, phi0],
args=(freq, data), args=(freq, data),
...@@ -233,8 +233,28 @@ def reflection_model_mag(x, Ql, Qc, x0, c): ...@@ -233,8 +233,28 @@ def reflection_model_mag(x, Ql, Qc, x0, c):
return c - (2 * Ql / Qc) ** 2 / (1. + 4 * Ql ** 2 * ((x - x0) / x0) ** 2) return c - (2 * Ql / Qc) ** 2 / (1. + 4 * Ql ** 2 * ((x - x0) / x0) ** 2)
def fit_model_refl(freq, data, Ql, Qc, fr, phi0, weights, ftol=1e-16): def fit_model_refl(freq, data, Ql, Qc, fr, phi0, weights, max_nfev=1000):
"""Final circle fit of the model to get information about Ql, Qc, fr, phi0 """Final fit of the model for reflection to get information about Ql,
Qc and fr.
Parameters
-----------
freq : np.array, list
List of frequencies
data : np.array, list
List of complex data points
Ql : float
Guess value for Ql
absQc : float
Guess value for Qc
fr : float
Guess value for resonance frequency
phi0 : float
Guess value for impedance mismatch
weights : np.array, list
Weights for fit.
max_nfev : int
Maximum number of iterations. Increase for increased precision.
""" """
def res(params, f, data): def res(params, f, data):
...@@ -245,18 +265,14 @@ def fit_model_refl(freq, data, Ql, Qc, fr, phi0, weights, ftol=1e-16): ...@@ -245,18 +265,14 @@ def fit_model_refl(freq, data, Ql, Qc, fr, phi0, weights, ftol=1e-16):
z1d[1:z1d.size:2] = diff.imag ** 2 * weights z1d[1:z1d.size:2] = diff.imag ** 2 * weights
return z1d return z1d
f = spopt.leastsq(res, [Ql, Qc, fr, phi0], args=(freq, data), f = spopt.least_squares(res, [np.abs(Ql), np.abs(Qc), fr, phi0],
full_output=True, xtol=ftol, ftol=ftol) args=(freq, data),
# f = spopt.least_squares(res, [Ql, Qc, fr, phi0], args=(freq, data), verbose=0, max_nfev=max_nfev, xtol=2.3e-16,
# bounds=([Ql-.5*Ql, Qc-.5*Qc, fr-10*fr/Ql, ftol=2.3e-16,
# -np.pi], bounds=([0, 0, 0, -np.pi],
# [Ql+0.5*Ql, Qc+0.5*Qc, fr+10*fr/Ql, [10e9, 10e9, 20e9, np.pi]))
# np.pi]),
# xtol=2.3e-16, ftol=2.5e-16, gtol=2.5e-16,
# loss='huber',
# verbose=2)
return f[0], f[1] return f.x, f
def fit_mag_refl(freq, data, Ql, Qc, fr, phi0, weights, ftol=1e-16): def fit_mag_refl(freq, data, Ql, Qc, fr, phi0, weights, ftol=1e-16):
...@@ -286,13 +302,21 @@ def subtract_linear_bg(freq, data, fit_range=0.1): ...@@ -286,13 +302,21 @@ def subtract_linear_bg(freq, data, fit_range=0.1):
def get_weights(freq, Ql, fr, weight_width): def get_weights(freq, Ql, fr, weight_width):
"""Weighting of the function. In range of FWHM, determined by """Weighting of the function. In range of FWHM, determined by
(Ql/fr)*weight_width. Outer values are weighted prop. to 1/abs(f-fr) (Ql/fr)*weight_width. Outer values are weighted prop. to 1/abs(f-fr)^r
""" """
width = fr / Ql width = fr / Ql
weights = np.ones(len(freq)) weights = np.ones(len(freq))
outer_idx = np.abs(freq - fr) > width * weight_width outer_idx = np.abs(freq - fr) > width * weight_width
weights[outer_idx] = (width * weight_width) / (np.abs(freq[outer_idx] - fr))
left_idx = np.argwhere(outer_idx == 0)[0][0]
right_idx = np.argwhere(outer_idx == 0)[-1][0]
r = 2
weights[right_idx:] = 1 / ((freq[right_idx:] - freq[right_idx]) / (
freq[right_idx] - fr) + 1) ** r
weights[:left_idx] = 1 / ((freq[:left_idx] - freq[left_idx]) / (
freq[left_idx] - fr) + 1) ** r
return weights return weights
......
This diff is collapsed.
...@@ -7,6 +7,7 @@ from CircleFit.plotting import plot_rawdata ...@@ -7,6 +7,7 @@ from CircleFit.plotting import plot_rawdata
import CircleFit.plotting as cp import CircleFit.plotting as cp
from CircleFit.circuit import Notch, Reflection from CircleFit.circuit import Notch, Reflection
from CircleFit.fit_toolbox import get_delay from CircleFit.fit_toolbox import get_delay
from bokeh.plotting import show
class data_complex(data_table): class data_complex(data_table):
...@@ -235,11 +236,6 @@ class data_complex(data_table): ...@@ -235,11 +236,6 @@ class data_complex(data_table):
f_range=f_range) f_range=f_range)
self._delayOffset = offset self._delayOffset = offset
else:
_, offset = get_delay(self, comb_slopes=comb_slopes,
f_range=f_range)
self._delayOffset = offset
# Save set delay # Save set delay
self.delay = delay self.delay = delay
...@@ -254,16 +250,43 @@ class data_complex(data_table): ...@@ -254,16 +250,43 @@ class data_complex(data_table):
engine : str engine : str
Chose the plot engine between 'bokeh' (default) and 'pyplot' Chose the plot engine between 'bokeh' (default) and 'pyplot'
""" """
# TODO Rewrite without try and except if self.circuit is not None:
try:
self.plot_fitted_data(engine=engine, **kwargs) self.plot_fitted_data(engine=engine, **kwargs)
except: else:
self.plot_rawdata(engine=engine, **kwargs) self.plot_rawdata(engine=engine, **kwargs)
def plot_rawdata(self, **kwargs): def plot_rawdata(self, engine='b', **kwargs):
"""Plots plain data""" """Plots plain data"""
plot_rawdata(self.x, self.value, **kwargs) plot_rawdata(self, engine=engine, **kwargs)
def plot_single(self, type='dB', engine='b', fit=True, **kwargs):
"""Plot a single figure. Choose between 'dB', 'phase', 'ReIm',
'Circle'
Parameters
-----------
type : 'dB', 'phase', 'ReIm', 'Circle'
Choose type of plot.
engine : 'b', 'p'
Bokeh or pyplot
fit : bool
Try to plot fit if possible?
**kwargs
Additional keywords for plot.
"""
if type[0].lower() == 'd':
p = cp.plot_MagFreq(self, engine, fit, **kwargs)
elif type[0].lower() == 'p':
p = cp.plot_PhaseFreq(self, engine, fit, **kwargs)
elif type[0].lower() == 'c':
p = cp.plot_NormCircle(self, engine, fit, **kwargs)
else:
p = cp.plot_ReIm(self, engine, fit, **kwargs)
if engine[0].lower() == 'b':
show(p)
def circle_fit_notch(self, delay=None, a=None, alpha=None, phi0=None, def circle_fit_notch(self, delay=None, a=None, alpha=None, phi0=None,
subtract_bg=True, fr_init=None, Ql_init=None, subtract_bg=True, fr_init=None, Ql_init=None,
...@@ -336,18 +359,21 @@ class data_complex(data_table): ...@@ -336,18 +359,21 @@ class data_complex(data_table):
kwargs = {'delay': delay, 'a': a, 'alpha': alpha, 'phi0': phi0, kwargs = {'delay': delay, 'a': a, 'alpha': alpha, 'phi0': phi0,
'subtract_bg': subtract_bg, 'fr_init': fr_init, 'subtract_bg': subtract_bg, 'fr_init': fr_init,
'Ql_init': Ql_init, 'weight_width': weight_width, 'Ql_init': Ql_init, 'weight_width': weight_width,
'print_res': print_res, 'plt_res': plot_res, 'print_res': print_res, 'plt_res':plot_res,
'maxfev': maxfev, 'comb_slopes': comb_slopes, 'maxfev': maxfev, 'comb_slopes': comb_slopes,
'final_mag': final_mag, 'ftol': ftol, 'final_mag': final_mag, 'ftol': ftol,
'fit_range': fit_range} 'fit_range': fit_range}
self.circuit = Notch(self, **kwargs) self.circuit = Notch(self, **kwargs)
# Plot if wanted
if plot_res:
cp.plot_cfit(self)
# Further save fitresults in data_complex class # Further save fitresults in data_complex class
self.fitresults = self.circuit.fitresults self.fitresults = self.circuit.fitresults
def circle_fit_reflection(self, delay=None, a=None, alpha=None, phi0=0, def circle_fit_reflection(self, delay=None, a=None, alpha=None, phi0=0,
subtract_bg=True, fr_init=None, Ql_init=None, subtract_bg=True, fr_init=None, Ql_init=None,
weight_width=1, print_res=True, plt_res=True, weight_width=1, print_res=True, plot_res=True,
comb_slopes=False, final_mag=False, maxfev=1e3, comb_slopes=False, final_mag=False, maxfev=1e3,
ftol=1e-16, fit_range=0.15): ftol=1e-16, fit_range=0.15):
"""Circle fit for reflection configuration. """Circle fit for reflection configuration.
...@@ -418,17 +444,20 @@ class data_complex(data_table): ...@@ -418,17 +444,20 @@ class data_complex(data_table):
kwargs = {'delay': delay, 'a': a, 'alpha': alpha, 'phi0': phi0, kwargs = {'delay': delay, 'a': a, 'alpha': alpha, 'phi0': phi0,
'subtract_bg': subtract_bg, 'fr_init': fr_init, 'subtract_bg': subtract_bg, 'fr_init': fr_init,
'Ql_init': Ql_init, 'weight_width': weight_width, 'Ql_init': Ql_init, 'weight_width': weight_width,
'print_res': print_res, 'plt_res': plt_res, 'maxfev': maxfev, 'print_res': print_res, 'plt_res': plot_res, 'maxfev': maxfev,
'comb_slopes': comb_slopes, 'final_mag': final_mag, 'comb_slopes': comb_slopes, 'final_mag': final_mag,
'ftol': ftol, 'fit_range': fit_range} 'ftol': ftol, 'fit_range': fit_range}
self.circuit = Reflection(self, **kwargs) self.circuit = Reflection(self, **kwargs)
# Plot if wanted
if plot_res:
cp.plot_cfit(self)
# Further save fitresults in data_complex class # Further save fitresults in data_complex class
self.fitresults = self.circuit.fitresults self.fitresults = self.circuit.fitresults
def plot_fitted_data(self, **kwargs): def plot_fitted_data(self, engine='b', **kwargs):
"""Plot fitted data""" """Plot fitted data"""
cp.plot_cfit(self.circuit, **kwargs) cp.plot_cfit(self, engine=engine, **kwargs)
def plot_steps(self): def plot_steps(self):
"""Plot each step of the circlefit routine""" """Plot each step of the circlefit routine"""
......
...@@ -348,9 +348,10 @@ class data_table(data_module_base): ...@@ -348,9 +348,10 @@ class data_table(data_module_base):
kws['x_axis_type'] = 'log' kws['x_axis_type'] = 'log'
if logy: if logy:
kws['y_axis_type'] = 'log' kws['y_axis_type'] = 'log'
fig = bp.figure(plot_width=800, plot_height=400, tools=tools, fig = bp.figure(tools=tools,
toolbar_location='above', title=title, height=300,
**kws) sizing_mode='scale_width',
title=title, **kws)
# Empty legend if no legend is given # Empty legend if no legend is given
if legend is None: if legend is None:
......
...@@ -12,8 +12,8 @@ import pickle ...@@ -12,8 +12,8 @@ import pickle
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from .downwards_compatibility.data_line import data_line from .downwards_compatibility.data_line import data_line,data_2d
from .downwards_compatibility.data_surface import data_surface from .downwards_compatibility.data_surface import data_surface,data_3d
from .data_complex import data_complex from .data_complex import data_complex
from .data_grid import data_grid from .data_grid import data_grid
...@@ -170,26 +170,9 @@ def plot_multiple(dm_list, label_list, figure=None, colormap=None, ...@@ -170,26 +170,9 @@ def plot_multiple(dm_list, label_list, figure=None, colormap=None,
kwargs : keywords kwargs : keywords
Optional: Keywords for bokeh or pyplot Optional: Keywords for bokeh or pyplot
""" """
# Get colors # Import default colormap
# Get number of plots if colormap is None:
n_plots = len(dm_list)
# Get colormap
if isinstance(colormap, str):
# Get colormap from default library by name
tmp = plt.cm.get_cmap(colormap, n_plots)
colormap = [matplotlib.colors.rgb2hex(tmp(i)) for
i in range(n_plots)]
elif colormap is None:
# Use 8 default colors if less than 8 columns to plot
if n_plots <= len(color_scheme):