Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Institute of Experimental Physics
Quantum Circuits
python-repo
Commits
1badd3be
Commit
1badd3be
authored
Jul 27, 2020
by
Christian Schneider
Browse files
Merged
parents
d2461113
822b9026
Changes
34
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
679 additions
and
366 deletions
+679
-366
ADQ14.py
ADQ14.py
+52
-9
AWGSIGD.py
AWGSIGD.py
+9
-4
CircleFit/circuit.py
CircleFit/circuit.py
+2
-5
CircleFit/fit_toolbox.py
CircleFit/fit_toolbox.py
+41
-17
CircleFit/plotting.py
CircleFit/plotting.py
+383
-244
DataModule/data_complex.py
DataModule/data_complex.py
+44
-15
DataModule/data_table.py
DataModule/data_table.py
+4
-3
DataModule/functions.py
DataModule/functions.py
+7
-24
DataModule/mfit.py
DataModule/mfit.py
+13
-5
Experiments/DC_SQUID.py
Experiments/DC_SQUID.py
+65
-8
FridgeWatch/Fridge_SQL_ACQ.py
FridgeWatch/Fridge_SQL_ACQ.py
+4
-4
IPLIST.py
IPLIST.py
+10
-6
IQCALIBRATION/IQCAL_KEYAWG.py
IQCALIBRATION/IQCAL_KEYAWG.py
+1
-1
IQCALIBRATION/IQCAL_QM.py
IQCALIBRATION/IQCAL_QM.py
+3
-3
IQCALIBRATION/IQCAL_ZIAWG.py
IQCALIBRATION/IQCAL_ZIAWG.py
+3
-3
IQCALIBRATION/IQCAL_base.py
IQCALIBRATION/IQCAL_base.py
+9
-8
IQCALIBRATION/version.py
IQCALIBRATION/version.py
+5
-1
Instruments/DAQ.py
Instruments/DAQ.py
+2
-2
Instruments/Drivers/Anapico/APMS.py
Instruments/Drivers/Anapico/APMS.py
+9
-1
Instruments/Drivers/Anapico/APSIN.py
Instruments/Drivers/Anapico/APSIN.py
+13
-3
No files found.
ADQ14.py
View file @
1badd3be
...
...
@@ -3,6 +3,11 @@
Created on Tue Apr 9 11:33:36 2019
@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:
- 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)
...
...
@@ -24,8 +29,9 @@ class ADQ14(object):
import
ctypes
as
ct
import
numpy
as
np
import
copy
import
time
version
=
'1.2.
0
'
version
=
'1.2.
2
'
def
__init__
(
self
,
board_num
=
1
):
import
os
...
...
@@ -48,7 +54,7 @@ class ADQ14(object):
self
.
ADQAPI
.
ADQControlUnit_FindDevices
.
argtypes
=
[
self
.
ct
.
c_void_p
]
self
.
Connect
(
board_num
)
self
.
Print_adq_device_revisions
()
self
.
__ADCSF
=
1.0
#GSamples/s
...
...
@@ -129,11 +135,29 @@ class ADQ14(object):
#---------------------------------
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
.
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"
)
return
0
...
...
@@ -143,15 +167,23 @@ class ADQ14(object):
print
(
'Error: board_num can
\'
t be negative!'
)
return
0
if
board_num
>
DEV_NUM
:
print
(
"Erro: Selected board number {}, but only {} boards have been found!"
.
format
(
board_num
,
DEV_NUM
))
if
board_num
>
nof_devices
:
print
(
"Erro: Selected board number {}, but only {} boards have been found!"
.
format
(
board_num
,
nof_devices
))
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
# Print ADQAPI revision
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
...
...
@@ -183,7 +215,11 @@ class ADQ14(object):
print
(
'Mixed Revision
\n
'
)
else
:
print
(
'SVN Updated
\n
'
)
return
revision
[
0
]
def
Blink
(
self
):
self
.
ADQAPI
.
ADQ_Blink
(
self
.
_adq
,
self
.
devnum
)
def
Reset
(
self
,
Type
=
'COMM'
):
'''function reset([Type='COMM']):
...
...
@@ -721,7 +757,7 @@ http://localhost:8988/edit/python_repo/ADQ14.py# tmp = tm
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.
'''
...
...
@@ -742,6 +778,13 @@ http://localhost:8988/edit/python_repo/ADQ14.py# tmp = tm
if
success
==
0
:
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
#init only what is necessary:
...
...
AWGSIGD.py
View file @
1badd3be
...
...
@@ -4,6 +4,11 @@
Created on Wed Sep 6 18:09:39 2017
@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:
- inserted the stop_multiple function
- inserted ext port setup functions
...
...
@@ -462,7 +467,7 @@ class AWGChannel(object):
##------------------------------------------------------------------------------------------ a00 AWG class --------------------------------
class
Awgsigd
(
object
):
version
=
'2.5.
2
'
version
=
'2.5.
3
'
import
keysightSD1
as
sigd
import
numpy
as
np
import
matplotlib.pyplot
as
plt
...
...
@@ -1028,6 +1033,8 @@ class Awgsigd(object):
self
.
__check_command
(
self
.
_awg
.
waveformLoad
(
wave
,
n
))
del
wave
#bugfix
for
i
in
range
(
4
):
self
.
__load_waves_in_channel
(
i
)
#self.time.sleep(0.1)
def
__change_offset_slow
(
self
,
channel
):
...
...
@@ -1099,8 +1106,6 @@ class Awgsigd(object):
raise
ValueError
def
setfunc
(
Channel
):
if
load_waves_in_memory
:
self
.
load_waves_in_AWG_memory
()
self
.
__check_channel_number
(
Channel
)
tmp
=
self
.
channel
(
Channel
)
...
...
@@ -1121,7 +1126,7 @@ class Awgsigd(object):
pars
=
pars
[
'PORT'
],
pars
[
'EDGE'
],
pars
[
'Sync'
]
port_sn
=
tmp
.
ext_port_list
.
index
(
pars
[
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
])))
...
...
CircleFit/circuit.py
View file @
1badd3be
...
...
@@ -212,9 +212,6 @@ class circuit(object):
display_tables
((
df
,
df_kappa
),
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
):
"""
...
...
@@ -425,14 +422,14 @@ class Reflection(circuit):
self
.
phi0
=
np
.
arcsin
(
self
.
yc_norm
/
self
.
r_norm
)
# Fit final circle #####################################################
ftol
=
kwargs
[
'
ftol
'
]
maxfev
=
kwargs
[
'
maxfev
'
]
if
not
kwargs
[
'final_mag'
]:
self
.
_cir_fit_pars
=
ft
.
fit_model_refl
(
self
.
freq
,
self
.
circle_norm
,
Ql_est
,
absQc_est
,
fr_est
,
self
.
phi0
,
self
.
_weights
,
ftol
=
ftol
)
max_nfev
=
maxfev
)
# Calculate quality factors
self
.
Ql
,
self
.
absQc
,
self
.
fr
,
self
.
phi1
=
\
np
.
abs
(
self
.
_cir_fit_pars
[
0
])
...
...
CircleFit/fit_toolbox.py
View file @
1badd3be
...
...
@@ -97,7 +97,7 @@ def get_delay(data, comb_slopes=True, f_range=.1):
mean
=
np
.
mean
(
data
.
phase
.
y
)
SS_tot
=
np
.
sum
((
data
.
phase
.
y
-
mean
)
**
2
)
R_sq
=
1
-
res
/
SS_tot
else
:
lin_fit_first
=
np
.
polyfit
(
data
.
x
[
0
:
fit_range
],
data
.
phase
.
y
[
0
:
fit_range
],
1
)
...
...
@@ -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
[
0
:
z1d
.
size
:
2
]
=
diff
.
real
**
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
],
args
=
(
freq
,
data
),
...
...
@@ -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
)
def
fit_model_refl
(
freq
,
data
,
Ql
,
Qc
,
fr
,
phi0
,
weights
,
ftol
=
1e-16
):
"""Final circle fit of the model to get information about Ql, Qc, fr, phi0
def
fit_model_refl
(
freq
,
data
,
Ql
,
Qc
,
fr
,
phi0
,
weights
,
max_nfev
=
1000
):
"""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
):
...
...
@@ -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
return
z1d
f
=
spopt
.
leastsq
(
res
,
[
Ql
,
Qc
,
fr
,
phi0
],
args
=
(
freq
,
data
),
full_output
=
True
,
xtol
=
ftol
,
ftol
=
ftol
)
# f = spopt.least_squares(res, [Ql, Qc, fr, phi0], args=(freq, data),
# bounds=([Ql-.5*Ql, Qc-.5*Qc, fr-10*fr/Ql,
# -np.pi],
# [Ql+0.5*Ql, Qc+0.5*Qc, fr+10*fr/Ql,
# np.pi]),
# xtol=2.3e-16, ftol=2.5e-16, gtol=2.5e-16,
# loss='huber',
# verbose=2)
f
=
spopt
.
least_squares
(
res
,
[
np
.
abs
(
Ql
),
np
.
abs
(
Qc
),
fr
,
phi0
],
args
=
(
freq
,
data
),
verbose
=
0
,
max_nfev
=
max_nfev
,
xtol
=
2.3e-16
,
ftol
=
2.3e-16
,
bounds
=
([
0
,
0
,
0
,
-
np
.
pi
],
[
10e9
,
10e9
,
20e9
,
np
.
pi
]))
return
f
[
0
],
f
[
1
]
return
f
.
x
,
f
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):
def
get_weights
(
freq
,
Ql
,
fr
,
weight_width
):
"""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
weights
=
np
.
ones
(
len
(
freq
))
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
...
...
CircleFit/plotting.py
View file @
1badd3be
...
...
@@ -5,6 +5,7 @@ plotting_utilities_module_version = '1.0.1'
@author: David Zoepfl, Christian Schneider
"""
import
numpy
as
np
from
scipy.linalg
import
svd
import
pandas
as
pd
from
IPython.display
import
display
,
Markdown
try
:
...
...
@@ -17,8 +18,12 @@ from collections import OrderedDict
from
DataModule.plot_style
import
cc
from
.fit_toolbox
import
lorentzian_abs
,
tan_phase
,
notch_model
from
.fit_toolbox
import
reflection_model
,
reflection_model_mag
from
.fit_toolbox
import
notch_model_mag
# Bokeh settings
TOOLS
=
'box_zoom,pan,wheel_zoom,reset,save'
TOOLTIPS
=
[(
'Frequency'
,
'@freq{1.11111111} GHz'
),
(
"Re"
,
"@re"
),
(
"Im"
,
"@im"
),
(
'Mag'
,
'@mag dB'
),
(
'Phase'
,
'@phase°'
)]
def
_get_tools
():
tools
=
(
'box_zoom'
,
'pan'
,
'wheel_zoom'
,
'reset'
,
'save'
,
...
...
@@ -26,276 +31,404 @@ def _get_tools():
return
tools
def
plot_rawdata
(
freq
,
data
,
title
=
'-'
,
engine
=
'bokeh'
):
"""
Plot complex data in three subplots:
| Im(data) over Re(data) | Mag(data) over freq | Ang(data) over freq |
"""
# Calculate plot values
mag
=
20
*
np
.
log10
(
np
.
abs
(
data
))
# Power Mag in dB
phase
=
np
.
unwrap
(
np
.
angle
(
data
))
*
180
/
np
.
pi
# Phase in degree
def
plot_rawdata
(
module
,
engine
=
'b'
,
fig
=
None
,
**
kwargs
):
"""Plot complex data in three subplots:
# Holoviews
if
engine
[
0
].
lower
()
==
'h'
:
pass
| Im(data) over Re(data) | Mag(data) over freq | Ang(data) over freq |
"""
if
engine
==
'bokeh'
:
# Calculate data for HoverTool
source_data
=
ColumnDataSource
(
data
=
dict
(
freq
=
freq
,
re
=
data
.
real
,
im
=
data
.
imag
,
phase
=
phase
,
mag
=
mag
,
))
tooltips
=
[(
'Frequency'
,
'@freq{1.11111111} GHz'
),
(
"Re"
,
"@re"
),
(
"Im"
,
"@im"
),
(
'Mag'
,
'@mag dB'
),
(
'Phase'
,
'@phase°'
)]
print
(
title
)
# Re over Im
fig1
=
figure
(
title
=
'rawdata'
,
tools
=
_get_tools
())
fig1
.
xaxis
.
axis_label
=
'Re'
fig1
.
yaxis
.
axis_label
=
'Im'
fig1
.
diamond
(
data
.
real
,
data
.
imag
,
size
=
4
,
fill_color
=
'white'
)
c1
=
fig1
.
circle
(
're'
,
'im'
,
source
=
source_data
,
size
=
3
,
legend
=
'Data'
)
# Format nicer HoverTool
hover
=
HoverTool
(
renderers
=
[
c1
])
fig1
.
add_tools
(
hover
)
fig1
.
select
(
dict
(
type
=
HoverTool
)).
tooltips
=
OrderedDict
(
tooltips
)
if
engine
[
0
].
lower
()
==
'b'
:
# Real/Imaginary
fig1
=
plot_ReIm
(
module
,
engine
=
engine
,
fit
=
False
,
**
kwargs
)
# Mag over freq
fig2
=
figure
(
tools
=
_get_tools
())
fig2
.
xaxis
.
axis_label
=
'Frequency (GHz)'
fig2
.
yaxis
.
axis_label
=
'Magnitude (dB)'
c2
=
fig2
.
line
(
'freq'
,
'mag'
,
source
=
source_data
,
line_width
=
2
)
# Format nicer HoverTool
hover
=
HoverTool
(
renderers
=
[
c2
])
fig2
.
add_tools
(
hover
)
fig2
.
select
(
dict
(
type
=
HoverTool
)).
tooltips
=
OrderedDict
(
tooltips
)
fig2
=
plot_MagFreq
(
module
,
engine
=
engine
,
fit
=
False
,
**
kwargs
)
# Phase over freq
fig3
=
figure
(
tools
=
_get_tools
())
fig3
.
xaxis
.
axis_label
=
'Frequency (GHz)'
fig3
.
yaxis
.
axis_label
=
'Phase (deg)'
c3
=
fig3
.
line
(
'freq'
,
'phase'
,
source
=
source_data
,
line_width
=
2
)
# Format nicer HoverTool
hover
=
HoverTool
(
renderers
=
[
c3
])
fig3
.
add_tools
(
hover
)
fig3
.
select
(
dict
(
type
=
HoverTool
)).
tooltips
=
OrderedDict
(
tooltips
)
fig3
=
plot_PhaseFreq
(
module
,
engine
=
engine
,
fit
=
False
,
**
kwargs
)
fig
=
gridplot
([
fig1
,
fig2
,
fig3
],
ncols
=
3
,
plot_width
=
300
,
plot_height
=
300
)
show
(
fig
)
elif
engine
==
'pyplot'
:
fig
=
plt
.
figure
(
figsize
=
(
12
,
4
))
fig
.
subplots_adjust
(
wspace
=
0.2
)
# Re over Im
elif
engine
[
0
].
lower
()
==
'p'
:
if
fig
is
None
:
plt
.
figure
(
dpi
=
200
,
figsize
=
(
12
,
3
))
plt
.
subplots_adjust
(
wspace
=
0.33
)
# Real/Imaginary
plt
.
subplot
(
131
)
plt
.
plot
(
data
.
real
,
data
.
imag
,
'.'
)
plt
.
title
(
'Im and Re'
)
plt
.
xlabel
(
'Re'
)
plt
.
ylabel
(
'Im'
)
plt
.
grid
()
plt
.
locator_params
(
axis
=
'x'
,
nbins
=
4
)
# Reduce x ticks
# Mag over Freq
plot_ReIm
(
module
,
engine
=
engine
,
fit
=
False
,
**
kwargs
)
# Mag over freq
plt
.
subplot
(
132
)
plt
.
plot
(
freq
,
mag
)
plt
.
title
(
'Magnitude (dB)'
)
plt
.
xlabel
(
'Frequency (GHz)'
)
plt
.
grid
()
plt
.
xlim
([
freq
[
0
],
freq
[
-
1
]])
# Phase over Freq
plot_MagFreq
(
module
,
engine
=
engine
,
fit
=
False
,
**
kwargs
)
# Phase over freq
plt
.
subplot
(
133
)
plt
.
plot
(
freq
,
phase
)
plt
.
xlabel
(
'Frequency (GHz)'
)
plt
.
title
(
'Phase (deg)'
)
plt
.
grid
()
plt
.
xlim
([
freq
[
0
],
freq
[
-
1
]])
plot_PhaseFreq
(
module
,
engine
=
engine
,
fit
=
False
,
**
kwargs
)
def
plot_cfit
(
circuit
,
engine
=
'bokeh'
,
title
=
''
):
def
plot_cfit
(
module
,
engine
=
'bokeh'
,
fig
=
None
,
**
kwargs
):
"""Plot data and fit.
"""
Plot the data and fit.
if
engine
[
0
].
lower
()
==
'b'
:
# Real/Imaginary
fig1
=
plot_ReIm
(
module
,
engine
=
engine
,
fit
=
True
,
**
kwargs
)
# Mag over freq
fig2
=
plot_MagFreq
(
module
,
engine
=
engine
,
fit
=
True
,
**
kwargs
)
# Phase over freq
fig3
=
plot_PhaseFreq
(
module
,
engine
=
engine
,
fit
=
True
,
**
kwargs
)
# Normalized circle
fig4
=
plot_NormCircle
(
module
,
engine
=
engine
,
fit
=
True
)
fig
=
gridplot
([
fig2
,
fig3
,
fig1
,
fig4
],
ncols
=
2
,
plot_height
=
350
,
plot_width
=
350
)
show
(
fig
)
elif
engine
[
0
].
lower
()
==
'p'
:
if
fig
is
None
:
plt
.
figure
(
dpi
=
150
,
figsize
=
(
8.5
,
8.5
))
plt
.
subplots_adjust
(
wspace
=
0.35
,
hspace
=
0.35
)
# Magnitude
plt
.
subplot
(
221
)
plt
.
title
(
'Magnitude'
)
plot_MagFreq
(
module
,
engine
=
engine
,
**
kwargs
)
# Phase over freq
plt
.
subplot
(
222
)
plt
.
title
(
'Phase'
)
plot_PhaseFreq
(
module
,
engine
=
engine
,
**
kwargs
)
# Re/Im
plt
.
subplot
(
223
)
plt
.
title
(
'Re/Im'
)
plot_ReIm
(
module
,
engine
=
engine
,
**
kwargs
)
# Normalized circle
plt
.
subplot
(
224
)
plt
.
title
(
'Normalized Circle'
)
plot_NormCircle
(
module
,
engine
=
engine
,
**
kwargs
)
def
plot_ReIm
(
module
,
engine
=
'b'
,
fit
=
True
,
**
kwargs
):
"""Plots imaginary over real part of S parameters
Parameters
-----------
module : data_cplx
Complex datamodule
engine : 'b', 'p'
Engine for plotting. Chose between bokeh and pyplot
fit : bool
Plot fit if available
"""
# Format data
freq
=
circuit
.
freq
data
=
circuit
.
value_raw
fit_data
=
circuit
.
value_calc
z_data_norm
=
circuit
.
circle_norm
xc1
=
circuit
.
fitresults_full_model
.
Value
.
xc
yc1
=
circuit
.
fitresults_full_model
.
Value
.
yc
r
=
circuit
.
fitresults_full_model
.
Value
.
r
if
circuit
.
type
==
'Notch'
:
offres
=
1
# Easy access variable names
freq
=
module
.
x
if
module
.
circuit
is
not
None
and
fit
:
# Plot data without electrical delay corrected
data
=
module
.
value_raw
else
:
offres
=
-
1
# Calculate plot values
# # Data
mag_data
=
20
*
np
.
log10
(
np
.
abs
(
circuit
.
value_raw
))
# Power Mag in dB
phase_data
=
np
.
unwrap
(
np
.
angle
(
circuit
.
value
),
0.5
)
*
180
/
np
.
pi
# Phase
# # Fit
# # # Correct electric delay
fit_tmp
=
fit_data
*
np
.
exp
(
2j
*
np
.
pi
*
freq
*
circuit
.
delay
)
mag_fit
=
20
*
np
.
log10
(
np
.
abs
(
fit_tmp
))
# Power Mag in dB
phase_fit
=
np
.
unwrap
(
np
.
angle
(
fit_tmp
),
0.5
)
*
180
/
np
.
pi
# Phase
if
engine
in
[
'bokeh'
,
'b'
]:
# Calculate data for HoverTool
data
=
module
.
value
# Bokeh
if
engine
[
0
].
lower
()
==
'b'
:
# Data
source_data
=
ColumnDataSource
(
data
=
dict
(
freq
=
freq
,
re
=
data
.
real
,
im
=
data
.
imag
,
phase
=
phase_data
,
mag
=
mag_data
,
))
source_fit
=
ColumnDataSource
(
data
=
dict
(
freq
=
freq
,
re
=
fit_data
.
real
,
im
=
fit_data
.
imag
,
phase
=
phase_fit
,
mag
=
mag_fit
,
mag
=
20
*
np
.
log10
(
np
.
abs
(
data
)),
phase
=
np
.
unwrap
(
np
.
angle
(
data
),
0.5
)
*
180
/
np
.
pi
))
# Figure
fig
=
figure
(
tools
=
TOOLS
)
fig
.
xaxis
.
axis_label
=
'Re'
fig
.
yaxis
.
axis_label
=
'Im'
c1
=
fig
.
circle
(
're'
,
'im'
,
source
=
source_data
,
size
=
3
)
# Format nicer HoverTool
hover
=
HoverTool
(
renderers
=
[
c1
])
fig
.
add_tools
(
hover
)
fig
.
select
(
dict
(
type
=
HoverTool
)).
tooltips
=
OrderedDict
(
TOOLTIPS
)
# Fit
if
fit
and
module
.
circuit
is
not
None
:
# Correct electrical delay and calculate mag and phase values
fit_tmp
=
(
module
.
circuit
.
value_calc
*
np
.
exp
(
2j
*
np
.
pi
*
freq
*
module
.
circuit
.
delay
))
mag_fit
=
20
*
np
.
log10
(
np
.
abs
(
fit_tmp
))
# Power Mag in dB
phase_fit
=
np
.
unwrap
(
np
.
angle
(
fit_tmp
),
0.5
)
*
180
/
np
.
pi
# Phase
source_fit
=
ColumnDataSource
(
data
=
dict
(
freq
=
freq
,
re
=
module
.
circuit
.
value_calc
.
real
,
im
=
module
.
circuit
.
value_calc
.
imag
,
phase
=
phase_fit
,
mag
=
mag_fit
,
))
source_norm
=
ColumnDataSource
(
fig
.
line
(
're'
,
'im'
,
source
=
source_fit
,
line_width
=
2
,
color
=
'firebrick'
)
# Return figure
return
fig
elif
engine
[
0
].
lower
()
==
'p'
:
# Plot
plt
.
plot
(
data
.
real
,
data
.
imag
,
'.'
)
plt
.
xlabel
(
'Re'
)
plt
.
ylabel
(
'Im'
)
plt
.
grid
()
plt
.
locator_params
(
axis
=
'x'
,
nbins
=
4
)
# Reduce x ticks
plt
.
locator_params
(
axis
=
'y'
,
nbins
=
4
)
# Reduce x ticks
# Fit
if
fit
and
module
.
circuit
is
not
None
:
# Correct electrical delay and calculate mag and phase values
fit_tmp
=
(
module
.
circuit
.
value_calc
*
np
.
exp
(
2j
*
np
.
pi
*
freq
*
module
.
circuit
.
delay
))
mag_fit
=
20
*
np
.
log10
(
np
.
abs
(
fit_tmp
))
# Power Mag in dB
phase_fit
=
np
.
unwrap
(
np
.
angle
(
fit_tmp
),
0.5
)
*
180
/
np
.
pi
# Phase
plt
.
plot
(
module
.
circuit
.
value_calc
.
real
,
module
.
circuit
.
value_calc
.
imag
,
color
=
cc
[
'r'
],
linewidth
=
1.3
)
return
None
def
plot_MagFreq
(
module
,
engine
=
'b'
,
fit
=
True
,
**
kwargs
):
"""Plot Magnitude over frequency"""
# Easy access variable names
freq
=
module
.
x
data
=
module
.
value
# Bokeh
if
engine
[
0
].
lower
()
==
'b'
:
source_data
=
ColumnDataSource
(
data
=
dict
(
freq
=
freq
,
re
=
z_
data
_norm
.
real
,
im
=
z_
data
_norm
.
imag
,
phase
=
phase_
data
,
mag
=
mag_data
,
re
=
data
.
real
,
im
=
data
.
imag
,