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
52ce600e
Commit
52ce600e
authored
Sep 27, 2021
by
Christian Schneider
Browse files
Merge branch 'integrated_swept' into resonator
parents
21b1b195
53fcfcdf
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1514 additions
and
234 deletions
+1514
-234
DataHandling/core.py
DataHandling/core.py
+4
-1
DataHandling/hdf5.py
DataHandling/hdf5.py
+21
-5
Instruments/Drivers/Keysight/E5071C.py
Instruments/Drivers/Keysight/E5071C.py
+28
-158
Instruments/Drivers/Keysight/P5003A.py
Instruments/Drivers/Keysight/P5003A.py
+691
-0
Instruments/Drivers/Keysight/VNA_Keysight.py
Instruments/Drivers/Keysight/VNA_Keysight.py
+620
-0
Instruments/VNA.py
Instruments/VNA.py
+71
-32
Instruments/core.py
Instruments/core.py
+5
-0
experiment.py
experiment.py
+74
-38
No files found.
DataHandling/core.py
View file @
52ce600e
import
numpy
as
np
import
numpy
as
np
from
plotly.subplots
import
make_subplots
import
plotly.graph_objects
as
go
class
Parameter
():
class
Parameter
():
"""Structure to keep the name, data, unit and metadata associated to a Parameter together.
"""Structure to keep the name, data, unit and metadata associated to a Parameter together.
...
@@ -97,7 +99,8 @@ class DataSet():
...
@@ -97,7 +99,8 @@ class DataSet():
# Do it more clever
# Do it more clever
self
.
metadata
.
update
(
dataset
.
metadata
)
self
.
metadata
.
update
(
dataset
.
metadata
)
"""
"""
...
...
DataHandling/hdf5.py
View file @
52ce600e
...
@@ -7,6 +7,9 @@ from collections import ChainMap
...
@@ -7,6 +7,9 @@ from collections import ChainMap
import
functools
import
functools
from
DataHandling.core
import
Parameter
,
Measurement
,
DataSet
from
DataHandling.core
import
Parameter
,
Measurement
,
DataSet
import
plotly
import
plotly.graph_objects
as
go
class
HDF5Saver
(
h5py
.
File
):
class
HDF5Saver
(
h5py
.
File
):
"""Save a Dataset in HDF5 format using h5py.
"""Save a Dataset in HDF5 format using h5py.
...
@@ -29,17 +32,14 @@ class HDF5Saver(h5py.File):
...
@@ -29,17 +32,14 @@ class HDF5Saver(h5py.File):
super
().
__init__
(
fname
,
mode
=
'w-'
,
libver
=
'latest'
)
super
().
__init__
(
fname
,
mode
=
'w-'
,
libver
=
'latest'
)
self
.
swmr_mode
=
True
# Allow to read the file when it is being written.
self
.
swmr_mode
=
True
# Allow to read the file when it is being written.
print
([[
parameter
.
name
,
parameter
.
data
]
for
parameter
in
dataset
.
parameters
.
values
()])
self
.
parameters
=
self
.
create_group
(
'Parameters'
)
self
.
parameters
=
self
.
create_group
(
'Parameters'
)
for
parameter
in
dataset
.
parameters
.
values
():
for
parameter
in
dataset
.
parameters
.
values
():
parameter_data_set
=
self
.
parameters
.
create_dataset
(
parameter
.
name
,
parameter_data_set
=
self
.
parameters
.
create_dataset
(
parameter
.
name
,
data
=
parameter
.
data
)
data
=
parameter
.
data
)
parameter_data_set
.
attrs
[
'Unit'
]
=
parameter
.
unit
for
key
,
value
in
parameter
.
metadata
.
items
():
for
key
,
value
in
parameter
.
metadata
.
items
():
parameter_data_set
.
attrs
[
key
]
=
value
parameter_data_set
.
attrs
[
key
]
=
value
parameter_data_set
.
attrs
[
'Unit'
]
=
parameter
.
unit
self
.
shape
=
{
parameter
.
name
:
len
(
parameter
.
data
)
for
parameter
in
dataset
.
parameters
.
values
()}
self
.
shape
=
{
parameter
.
name
:
len
(
parameter
.
data
)
for
parameter
in
dataset
.
parameters
.
values
()}
...
@@ -63,9 +63,9 @@ class HDF5Saver(h5py.File):
...
@@ -63,9 +63,9 @@ class HDF5Saver(h5py.File):
for
i
,
parameter
in
enumerate
(
measurement
.
indexing
):
for
i
,
parameter
in
enumerate
(
measurement
.
indexing
):
measurement_data_set
.
dims
[
i
].
label
=
parameter
measurement_data_set
.
dims
[
i
].
label
=
parameter
for
key
,
value
in
dataset
.
metadata
.
items
():
for
key
,
value
in
dataset
.
metadata
.
items
():
self
.
attrs
[
key
]
=
value
self
.
attrs
[
key
]
=
value
print
(
key
,
value
)
self
.
flush
()
self
.
flush
()
...
@@ -79,6 +79,22 @@ class HDF5Saver(h5py.File):
...
@@ -79,6 +79,22 @@ class HDF5Saver(h5py.File):
def
load_hdf5
(
fname
):
def
load_hdf5
(
fname
):
return
HDF5Loader
(
fname
).
dataset
return
HDF5Loader
(
fname
).
dataset
def
plot_hdf5
(
fname
,
swept_parameter
,
fixed_parameter
,
measurement
):
dataset
=
load_hdf5
(
fname
)
fig
=
go
.
Figure
()
#for i, parameter in enumerate(dataset.measurements[measurement].indexing):
for
i
,
value
in
enumerate
(
dataset
.
parameters
[
swept_parameter
].
data
):
y
=
dataset
.
measurements
[
measurement
].
data
[
i
]
x
=
dataset
.
parameters
[
fixed_parameter
].
data
fig
.
add_trace
(
go
.
Scatter
(
x
=
x
,
y
=
20
*
np
.
log10
(
np
.
abs
(
y
)),
mode
=
'lines'
,
name
=
dataset
.
parameters
[
swept_parameter
].
name
+
str
(
value
),
line
=
dict
(
width
=
2
)))
fig
.
update_layout
(
plot_bgcolor
=
'white'
)
fig
.
update_xaxes
(
showline
=
True
,
linewidth
=
2
,
linecolor
=
'black'
,
showgrid
=
True
,
gridwidth
=
1
,
gridcolor
=
'Black'
,
title_text
=
'f, GHz'
)
fig
.
update_yaxes
(
showline
=
True
,
linewidth
=
2
,
linecolor
=
'black'
,
showgrid
=
True
,
gridwidth
=
1
,
gridcolor
=
'Black'
,
title_text
=
'{}'
.
format
(
measurement
))
fig
.
show
()
class
HDF5Loader
(
h5py
.
File
):
class
HDF5Loader
(
h5py
.
File
):
"""Load an HDF5 file to a Dataset
"""Load an HDF5 file to a Dataset
...
...
Instruments/Drivers/Keysight/E5071C.py
View file @
52ce600e
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
"""
"""
Created on Fri Mar 28 09:43:05 2014
@author: Seyed Iman Mirzaei, Oscar Gargiulo, Christian Schneider, David Zoepfl, Romain Albert
@author: Seyed Iman Mirzaei, Oscar Gargiulo, Christian Schneider, David Zoepfl
Driver for ENA E5071C and
Driver for ENA E5071C
"""
v2.2.0 - OSC:
- changed all units to SI
v2.1.1 - CHR:
- Changed to binary data format (to be able to use pyvisa)
v2.0.0 - CHR:
import
pyvisa
as
visa
- Adapted to Driver/Instrument structure
v2.0.1 - OSC:
- migrated to VISA
"""
import
visa
import
time
import
time
import
numpy
as
np
import
numpy
as
np
from
tqdm
import
tqdm_notebook
from
tqdm
import
tqdm_notebook
import
struct
import
struct
from
Instruments.Drivers.Keysight.VNA_Keysight
import
VNAKeysight
# Versoin
# Versoin
version
=
'
2.2
.0'
version
=
'
3.0
.0'
print
(
'E5071C {}'
.
format
(
version
))
print
(
'E5071C {}'
.
format
(
version
))
class
E5071C
(
objec
t
):
class
E5071C
(
VNAKeysigh
t
):
global
version
global
version
def
__init__
(
self
,
ip
,
*
pars
,
**
kwargs
):
def
__init__
(
self
,
ip
,
*
pars
,
**
kwargs
):
rm
=
visa
.
ResourceManager
(
'@py'
)
rm
=
visa
.
ResourceManager
(
'@py'
)
self
.
_inst
=
rm
.
open_resource
(
'TCPIP::{}::INSTR'
.
format
(
ip
))
self
.
_inst
=
rm
.
open_resource
(
'TCPIP::{}::INSTR'
.
format
(
ip
))
self
.
version
=
version
self
.
ip
=
ip
self
.
ip
=
ip
# Set timeout to a minute
# Set timeout to a minute
...
@@ -44,9 +34,8 @@ class E5071C(object):
...
@@ -44,9 +34,8 @@ class E5071C(object):
else
:
else
:
self
.
_inst
.
timeout
=
60
*
1000
# Set to a minute
self
.
_inst
.
timeout
=
60
*
1000
# Set to a minute
print
(
self
.
_inst
.
timeout
)
super
().
__init__
()
self
.
average
()
def
com
(
self
,
command
,
arg
=
"?"
,
raw
=
False
):
def
com
(
self
,
command
,
arg
=
"?"
,
raw
=
False
):
"""Function to communicate with the device. Gives the current status
"""Function to communicate with the device. Gives the current status
if no arg is given
if no arg is given
...
@@ -89,6 +78,10 @@ class E5071C(object):
...
@@ -89,6 +78,10 @@ class E5071C(object):
self
.
_inst
.
write
(
"{} {}"
.
format
(
command
,
arg
))
self
.
_inst
.
write
(
"{} {}"
.
format
(
command
,
arg
))
return
0
return
0
def
close
(
self
):
'''Close connection to the instrument'''
self
.
_inst
.
close
()
def
get_complex_value
(
self
,
command
):
def
get_complex_value
(
self
,
command
):
"""Function to communicate with the device. Gives the current status
"""Function to communicate with the device. Gives the current status
if no arg is given
if no arg is given
...
@@ -102,73 +95,16 @@ class E5071C(object):
...
@@ -102,73 +95,16 @@ class E5071C(object):
self
.
_inst
.
write
(
':form:bord norm'
)
self
.
_inst
.
write
(
':form:bord norm'
)
return
resp
return
resp
def
identify
(
self
):
"""Returns Identification String of the device"""
return
self
.
com
(
'*OPT'
)
def
close
(
self
):
'''Close connection to the instrument'''
self
.
_inst
.
close
()
def
output
(
self
,
arg
=
'?'
):
"""Turns RF output power on/off
Give no argument to query current status.
Parameters
-----------
arg : int, str
Set state to 'ON', 'OFF', 1, 0
"""
return
self
.
com
(
":OUTP"
,
arg
)
def
power
(
self
,
power
=
'?'
,
channel
=
''
):
"""Set or read current power"""
return
float
(
self
.
com
(
":SOUR{}:POW:LEV:IMM:AMPL"
.
format
(
channel
),
power
))
def
average
(
self
,
number_average
=
1
):
def
average
(
self
,
number_average
=
1
):
"""Set/reset all parameters for doing an average measurement"""
"""Set/reset all parameters for doing an average measurement"""
self
.
number_average
=
number_average
super
().
average
(
number_average
)
if
number_average
==
1
:
if
number_average
==
1
:
self
.
average_state
(
0
)
self
.
com
(
':TRIG:SEQ:AVER'
,
'OFF'
)
self
.
com
(
':TRIG:SEQ:AVER'
,
'OFF'
)
else
:
else
:
self
.
average_state
(
1
)
self
.
average_count
(
number_average
)
self
.
com
(
':TRIG:SEQ:AVER'
,
'ON'
)
self
.
com
(
':TRIG:SEQ:AVER'
,
'ON'
)
def
average_reset
(
self
,
channel
=
''
):
"""Reset averages"""
return
self
.
com
(
":SENS{}:AVER:CLE"
.
format
(
channel
),
""
)
def
average_count
(
self
,
count
=
'?'
,
channel
=
''
):
"""Set/query number of averages"""
return
int
(
self
.
com
(
":SENS{}:AVER:COUN"
.
format
(
channel
),
count
))
def
average_state
(
self
,
state
=
'?'
,
channel
=
''
):
"""Sets/query averaging state"""
return
self
.
com
(
":SENS{}:AVER:STAT"
.
format
(
channel
),
state
)
def
freq_start
(
self
,
freq
=
'?'
,
channel
=
''
):
"""Set/query start frequency"""
return
float
(
self
.
com
(
":SENS{}:FREQ:STAR"
.
format
(
channel
),
freq
))
def
freq_stop
(
self
,
freq
=
'?'
,
channel
=
''
):
"""Set/query stop frequency"""
return
float
(
self
.
com
(
":SENS{}:FREQ:STOP"
.
format
(
channel
),
freq
))
def
freq_center
(
self
,
freq
=
'?'
,
channel
=
''
):
"""Set/query center frequency in Hz"""
return
float
(
self
.
com
(
":SENS{}:FREQ:CENT"
.
format
(
channel
),
freq
))
def
freq_span
(
self
,
freq
=
'?'
,
channel
=
''
):
"""Set/query span in Hz"""
return
float
(
self
.
com
(
":SENS{}:FREQ:SPAN"
.
format
(
channel
),
freq
))
def
freq_npoints
(
self
,
points
=
'?'
,
channel
=
''
):
"""Set/Query number of points"""
return
int
(
self
.
com
(
":SENS{}:SWE:POIN"
.
format
(
channel
),
points
))
def
freq_semgents
(
self
,
segments
,
BW
=
100
,
power
=-
50
):
def
freq_semgents
(
self
,
segments
,
BW
=
100
,
power
=-
50
):
"""Defined the VNA frequency through segments.
"""Defined the VNA frequency through segments.
...
@@ -202,14 +138,6 @@ class E5071C(object):
...
@@ -202,14 +138,6 @@ class E5071C(object):
self
.
com
(
':SENS:SWE:TYPE'
,
'SEGM'
)
self
.
com
(
':SENS:SWE:TYPE'
,
'SEGM'
)
self
.
com
(
':SENS:SEGM:ARB'
,
1
)
# Allow arb. segments (reversed, etc)
self
.
com
(
':SENS:SEGM:ARB'
,
1
)
# Allow arb. segments (reversed, etc)
self
.
com
(
':SENS:SEGM:DATA'
,
segment_str
)
self
.
com
(
':SENS:SEGM:DATA'
,
segment_str
)
def
IFBW
(
self
,
BW
=
'?'
,
channel
=
''
):
"""Set/query IF Bandwidth for specified channel"""
return
self
.
com
(
":SENS{}:BAND:RES"
.
format
(
channel
),
BW
)
def
sweep_type
(
self
,
type
=
'?'
,
channel
=
''
):
"""Set/query the type of sweep. Must be either linear, logartihmic, segmented or power."""
return
self
.
com
(
":SENS{}:SWE:TYPE"
.
format
(
channel
),
type
)
def
Spar
(
self
,
Par
=
'?'
,
trace
=
1
):
def
Spar
(
self
,
Par
=
'?'
,
trace
=
1
):
if
type
(
Par
)
!=
str
:
if
type
(
Par
)
!=
str
:
...
@@ -223,13 +151,13 @@ class E5071C(object):
...
@@ -223,13 +151,13 @@ class E5071C(object):
else
:
else
:
raise
Exception
(
'''S parameter must be either 'S11', 'S12', 'S21' or 'S22'.'''
)
raise
Exception
(
'''S parameter must be either 'S11', 'S12', 'S21' or 'S22'.'''
)
def
traces_number
(
self
,
num
=
'1'
,
channel
=
'1'
):
"""Set number of traces"""
return
int
(
self
.
com
(
"CALC{}:PAR:COUN"
.
format
(
channel
),
num
))
def
trace_select
(
self
,
num
=
1
,
channel
=
'1'
):
def
trace_select
(
self
,
num
=
1
,
channel
=
'1'
):
"""Select trace number num"""
"""Select trace number num"""
self
.
com
(
'CALC{}:PAR{}:SEL'
.
format
(
channel
,
num
),
''
)
self
.
com
(
'CALC{}:PAR{}:SEL'
.
format
(
channel
,
num
),
''
)
def
set_electrical_delay
(
self
,
delay
=
0.
,
num
=
1
,
channel
=
''
):
""" Set the electrical delay of the trace. Notice that a trace should be already selected."""
self
.
com
(
"CALC{}:SEL:CORR:EDEL:TIME"
.
format
(
channel
),
delay
)
def
Format
(
self
,
Format
=
'?'
,
Trace
=
1
):
def
Format
(
self
,
Format
=
'?'
,
Trace
=
1
):
"""Set Data Format
"""Set Data Format
...
@@ -247,7 +175,7 @@ class E5071C(object):
...
@@ -247,7 +175,7 @@ class E5071C(object):
| 'PPH': Positive phase
| 'PPH': Positive phase
| '' (def): the format will be queried
| '' (def): the format will be queried
"""
"""
self
.
com
(
"CALC:SEL:CORR:EDEL:TIME"
,
0
)
return
self
.
com
(
'CALC1:SEL:FORM'
,
Format
)
return
self
.
com
(
'CALC1:SEL:FORM'
,
Format
)
# READING data
# READING data
...
@@ -266,71 +194,6 @@ class E5071C(object):
...
@@ -266,71 +194,6 @@ class E5071C(object):
"""Return the last raw S measurement (before correction) in complex form."""
"""Return the last raw S measurement (before correction) in complex form."""
return
self
.
get_complex_value
(
':CALC:TRACe{}:DATA:SDATa?'
.
format
(
trace
))
return
self
.
get_complex_value
(
':CALC:TRACe{}:DATA:SDATa?'
.
format
(
trace
))
def
read_corrected_measurement
(
self
,
spar
=
'S21'
):
"""Return the last calibrated S measurement (after correction) in complex form."""
data
=
self
.
com
(
':SENSe:DATA:CORRdata'
,
'? {}'
.
format
(
spar
),
raw
=
True
)
return
np
.
asarray
(
data
[
0
::
2
],
dtype
=
np
.
float
)
+
1.j
*
np
.
asarray
(
data
[
1
::
2
],
dtype
=
np
.
float
)
def
read_settings
(
self
):
"""Returns current state of VNA parameters as dict
Frequency in GHz.
"""
freq_start
=
self
.
freq_start
()
freq_stop
=
self
.
freq_stop
()
freq_span
=
freq_stop
-
freq_start
freq_npoints
=
self
.
freq_npoints
()
BW
=
self
.
IFBW
()
Spar
=
self
.
Spar
()
format_meas
=
self
.
Format
()
power
=
self
.
power
()
output
=
self
.
output
()
avg
=
self
.
average_count
()
par
=
{
'f_start (Hz)'
:
freq_start
,
'f_stop (Hz)'
:
freq_stop
,
'f_start (GHz)'
:
freq_start
*
1e-9
,
'f_stop (GHz)'
:
freq_stop
*
1e-9
,
'IF - BW (Hz)'
:
BW
,
'S_parameter '
:
Spar
,
'Format'
:
format_meas
,
'Span (Hz)'
:
freq_span
,
'Points'
:
freq_npoints
,
'power (dBm)'
:
power
,
'output'
:
output
,
'averages'
:
avg
,
'averaging'
:
self
.
average_state
(),
'correction'
:
self
.
correction
()}
return
par
def
set_settings
(
self
,
**
kwargs
):
com_dict
=
{
'f_start (Hz)'
:
self
.
freq_start
,
'f_stop (Hz)'
:
self
.
freq_stop
,
'IF - BW (Hz)'
:
self
.
IFBW
,
'S_parameter '
:
self
.
Spar
,
'Format'
:
self
.
Format
,
'Points'
:
self
.
freq_npoints
,
'power (dBm)'
:
self
.
power
,
'averaging'
:
self
.
average_state
,
'averages'
:
self
.
average_count
}
for
k
in
kwargs
.
keys
():
try
:
com_dict
[
k
](
kwargs
[
k
])
except
KeyError
:
pass
def
correction
(
self
,
state
=
'?'
):
"""Query or set correction status (to ON/OFF)
Parameters
-----------
state : '?', 'ON', 'OFF', 1, 0
State of correction. Use nothing or '?' for query
"""
return
self
.
com
(
'SENS:CORR:STAT'
,
state
)
def
current_correction
(
self
):
def
current_correction
(
self
):
"""Return the current type correction used."""
"""Return the current type correction used."""
...
@@ -346,6 +209,13 @@ class E5071C(object):
...
@@ -346,6 +209,13 @@ class E5071C(object):
self
.
com
(
':TRIG:AVER'
,
'OFF'
)
self
.
com
(
':TRIG:AVER'
,
'OFF'
)
self
.
com
(
':TRIG:SEQ:SOUR'
,
'INT'
)
self
.
com
(
':TRIG:SEQ:SOUR'
,
'INT'
)
def
send_trigger
(
self
):
""" Send the trigger to initiate the measurement. """
self
.
com
(
':TRIG:SEQ:SINGLE'
,
''
)
def
start_and_wait_end_measurement
(
self
):
def
start_and_wait_end_measurement
(
self
):
"""Start the measurement and wait up to the end of the measurment.
"""Start the measurement and wait up to the end of the measurment.
...
...
Instruments/Drivers/Keysight/P5003A.py
0 → 100644
View file @
52ce600e
This diff is collapsed.
Click to expand it.
Instruments/Drivers/Keysight/VNA_Keysight.py
0 → 100644
View file @
52ce600e
This diff is collapsed.
Click to expand it.
Instruments/VNA.py
View file @
52ce600e
...
@@ -56,6 +56,7 @@ class BondedVNAFrequency():
...
@@ -56,6 +56,7 @@ class BondedVNAFrequency():
self
.
_stop
=
None
self
.
_stop
=
None
self
.
_npoints
=
None
self
.
_npoints
=
None
self
.
_type
=
None
self
.
_type
=
None
self
.
unit
=
'Hz'
if
data
is
None
:
if
data
is
None
:
self
.
start
=
start
self
.
start
=
start
...
@@ -300,9 +301,12 @@ class VNA(Instrument):
...
@@ -300,9 +301,12 @@ class VNA(Instrument):
self
.
devtype
=
'VNA'
self
.
devtype
=
'VNA'
# Load driver ##########################################################
# Load driver ##########################################################
if
id_string
==
'VNA3'
or
id_string
[:
4
]
==
"VNA4"
:
if
id_string
==
'VNA3'
:
from
.Drivers.Keysight.E5080
import
E5080
from
.Drivers.Keysight.E5080
import
E5080
self
.
driver
=
E5080
self
.
driver
=
E5080
elif
id_string
[:
4
]
==
"VNA4"
:
from
.Drivers.Keysight.P5003A
import
P5003A
self
.
driver
=
P5003A
elif
id_string
==
'VNA1'
or
id_string
==
'VNA2'
:
elif
id_string
==
'VNA1'
or
id_string
==
'VNA2'
:
from
.Drivers.Keysight.E5071C
import
E5071C
from
.Drivers.Keysight.E5071C
import
E5071C
self
.
driver
=
E5071C
self
.
driver
=
E5071C
...
@@ -326,6 +330,8 @@ class VNA(Instrument):
...
@@ -326,6 +330,8 @@ class VNA(Instrument):
## We need to keep track of them to be able to store them in the metadata of the measurement
## We need to keep track of them to be able to store them in the metadata of the measurement
self
.
segments
=
None
self
.
segments
=
None
self
.
S_parameters
=
None
def
start
(
self
):
def
start
(
self
):
self
.
instr
.
set_trigger
()
self
.
instr
.
set_trigger
()
...
@@ -372,7 +378,8 @@ class VNA(Instrument):
...
@@ -372,7 +378,8 @@ class VNA(Instrument):
S_parameters
=
[
'S21'
],
S_parameters
=
[
'S21'
],
correction
=
False
,
correction
=
False
,
ignore_security
=
False
,
ignore_security
=
False
,
format_vna
=
'MLOG'
):
format_vna
=
'MLOG'
,
synchrone
=
True
):
"""
"""
Measure the S scattering matrix and return a DataSet with the result (complex number).
Measure the S scattering matrix and return a DataSet with the result (complex number).
...
@@ -398,46 +405,78 @@ class VNA(Instrument):
...
@@ -398,46 +405,78 @@ class VNA(Instrument):
| 'IMAG' imaginary part of the complex data
| 'IMAG' imaginary part of the complex data
| 'UPH': Extended phase
| 'UPH': Extended phase
| 'PPH': Positive phase
| 'PPH': Positive phase
synchrone: bool
If True, this method will perform the measurement and wait for the end of the measurement.
In that case, this method will send back the dataset with the result.
If False, this method only start the measurement and the data will need to be retrieve
using the get_data methods later.
"""
"""
S_parameters
=
[
spar
.
upper
()
for
spar
in
S_parameters
]
if
before_measurement
:
## We define all the important parameter before the first measurement
if
correction
:
self
.
instr
.
correction
(
'ON'
)
else
:
self
.
instr
.
correction
(
'OFF'
)
if
not
ignore_security
:
calibration
=
self
.
instr
.
current_correction
()
if
correction
and
calibration
[
0
]
==
"SOLT2"
:
raise
Exception
(
'The correction is activated and will send power to port 2. If '
\
'it is volontary, please put ignore_security to True.'
)
for
spar
in
S_parameters
:
if
spar
in
[
'S12'
,
'S22'
]:
raise
Exception
(
'One of the S parameter you want to measure will send power '
\
'to port 2. If it is volontary, please put ignore_security to True.'
)
number_trace
=
len
(
S_parameters
)
self
.
S_parameters
=
[
spar
.
upper
()
for
spar
in
S_parameters
]
self
.
instr
.
traces_number
(
number_trace
)
for
i
,
spar
in
enumerate
(
S_parameters
):
if
correction
:
self
.
instr
.
trace_select
(
i
+
1
)
self
.
instr
.
correction
(
'ON'
)
self
.
instr
.
Spar
(
spar
,
i
+
1
)
else
:
self
.
instr
.
Format
(
format_vna
)
self
.
instr
.
correction
(
'OFF'
)
if
not
ignore_security
:
calibration
=
self
.
instr
.
current_correction
()
if
correction
and
calibration
[
0
]
==
"SOLT2"
:
raise
Exception
(
'The correction is activated and will send power to port 2. If '
\
'it is volontary, please put ignore_security to True.'
)
for
spar
in
S_parameters
:
if
spar
in
[
'S12'
,
'S22'
]:
raise
Exception
(
'One of the S parameter you want to measure will send power '
\
'to port 2. If it is volontary, please put ignore_security to True.'
)
number_trace
=
len
(
S_parameters
)
self
.
instr
.
traces_number
(
number_trace
)
for
i
,
spar
in
enumerate
(
S_parameters
):
self
.
instr
.
trace_select
(
i
+
1
)
self
.
instr
.
Spar
(
spar
,
i
+
1
)
self
.
instr
.
Format
(
format_vna
)
self
.
set_electrical_delay
(
0
,
i
+
1
)
if
before_measurement
:
return
DataSet
({
'VNA Frequency'
:
Parameter
(
'VNA Frequency'
,
np
.
asarray
(
self
.
get_frequencies
(),
dtype
=
'float'
),
'Hz'
)},
return
DataSet
({
'VNA Frequency'
:
Parameter
(
'VNA Frequency'
,
np
.
asarray
(
self
.
get_frequencies
(),
dtype
=
'float'
),
'Hz'
)},
{
spar
:
Measurement
(
spar
,
np
.
empty
((
1
),
dtype
=
np
.
complex128
),
''
,
[
'VNA Frequency'
])
for
spar
in
S_parameters
},
{
spar
:
Measurement
(
spar
,
np
.
empty
((
1
),
dtype
=
np
.
complex128
),
''
,
[
'VNA Frequency'
])
for
spar
in
self
.
S_parameters
},
{
'Correction VNA'
:
correction
,
'Segments'
:
str
(
self
.
segments
)})
{
'Correction VNA'
:
correction
,
'Segments'
:
str
(
self
.
segments
)})
else
:
else
:
self
.
instr
.
start_and_wait_end_measurement
()
if
synchrone
:
self
.
instr
.
start
()
self
.
instr
.
wait_end_measurement
()
err
=
self
.
instr
.
get_error
()
if
err
!=
'No error'
:
raise
Exception
(
'VNA error.'
)
return
DataSet
(
measurements
=
{
spar
:
Measurement
(
spar
,
self
.
instr
.
read_measurement
(
trace
=
i
+
1
),
''
,
[
'VNA Frequency'
])
for
i
,
spar
in
enumerate
(
self
.
S_parameters
)})
else
:
self
.
instr
.
start
()
def
get_data
(
self
):