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
from
plotly.subplots
import
make_subplots
import
plotly.graph_objects
as
go
class
Parameter
():
"""Structure to keep the name, data, unit and metadata associated to a Parameter together.
...
...
@@ -97,7 +99,8 @@ class DataSet():
# Do it more clever
self
.
metadata
.
update
(
dataset
.
metadata
)
"""
...
...
DataHandling/hdf5.py
View file @
52ce600e
...
...
@@ -7,6 +7,9 @@ from collections import ChainMap
import
functools
from
DataHandling.core
import
Parameter
,
Measurement
,
DataSet
import
plotly
import
plotly.graph_objects
as
go
class
HDF5Saver
(
h5py
.
File
):
"""Save a Dataset in HDF5 format using h5py.
...
...
@@ -29,17 +32,14 @@ class HDF5Saver(h5py.File):
super
().
__init__
(
fname
,
mode
=
'w-'
,
libver
=
'latest'
)
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'
)
for
parameter
in
dataset
.
parameters
.
values
():
parameter_data_set
=
self
.
parameters
.
create_dataset
(
parameter
.
name
,
data
=
parameter
.
data
)
parameter_data_set
.
attrs
[
'Unit'
]
=
parameter
.
unit
for
key
,
value
in
parameter
.
metadata
.
items
():
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
()}
...
...
@@ -63,9 +63,9 @@ class HDF5Saver(h5py.File):
for
i
,
parameter
in
enumerate
(
measurement
.
indexing
):
measurement_data_set
.
dims
[
i
].
label
=
parameter
for
key
,
value
in
dataset
.
metadata
.
items
():
self
.
attrs
[
key
]
=
value
print
(
key
,
value
)
self
.
flush
()
...
...
@@ -79,6 +79,22 @@ class HDF5Saver(h5py.File):
def
load_hdf5
(
fname
):
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
):
"""Load an HDF5 file to a Dataset
...
...
Instruments/Drivers/Keysight/E5071C.py
View file @
52ce600e
# -*- 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:
- Adapted to Driver/Instrument structure
v2.0.1 - OSC:
- migrated to VISA
"""
import
visa
import
pyvisa
as
visa
import
time
import
numpy
as
np
from
tqdm
import
tqdm_notebook
import
struct
from
Instruments.Drivers.Keysight.VNA_Keysight
import
VNAKeysight
# Versoin
version
=
'
2.2
.0'
version
=
'
3.0
.0'
print
(
'E5071C {}'
.
format
(
version
))
class
E5071C
(
objec
t
):
class
E5071C
(
VNAKeysigh
t
):
global
version
def
__init__
(
self
,
ip
,
*
pars
,
**
kwargs
):
rm
=
visa
.
ResourceManager
(
'@py'
)
self
.
_inst
=
rm
.
open_resource
(
'TCPIP::{}::INSTR'
.
format
(
ip
))
self
.
version
=
version
self
.
ip
=
ip
# Set timeout to a minute
...
...
@@ -44,9 +34,8 @@ class E5071C(object):
else
:
self
.
_inst
.
timeout
=
60
*
1000
# Set to a minute
print
(
self
.
_inst
.
timeout
)
self
.
average
()
super
().
__init__
()
def
com
(
self
,
command
,
arg
=
"?"
,
raw
=
False
):
"""Function to communicate with the device. Gives the current status
if no arg is given
...
...
@@ -89,6 +78,10 @@ class E5071C(object):
self
.
_inst
.
write
(
"{} {}"
.
format
(
command
,
arg
))
return
0
def
close
(
self
):
'''Close connection to the instrument'''
self
.
_inst
.
close
()
def
get_complex_value
(
self
,
command
):
"""Function to communicate with the device. Gives the current status
if no arg is given
...
...
@@ -102,73 +95,16 @@ class E5071C(object):
self
.
_inst
.
write
(
':form:bord norm'
)
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
):
"""Set/reset all parameters for doing an average measurement"""
self
.
number_average
=
number_average
super
().
average
(
number_average
)
if
number_average
==
1
:
self
.
average_state
(
0
)
self
.
com
(
':TRIG:SEQ:AVER'
,
'OFF'
)
else
:
self
.
average_state
(
1
)
self
.
average_count
(
number_average
)
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
):
"""Defined the VNA frequency through segments.
...
...
@@ -202,14 +138,6 @@ class E5071C(object):
self
.
com
(
':SENS:SWE:TYPE'
,
'SEGM'
)
self
.
com
(
':SENS:SEGM:ARB'
,
1
)
# Allow arb. segments (reversed, etc)
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
):
if
type
(
Par
)
!=
str
:
...
...
@@ -223,13 +151,13 @@ class E5071C(object):
else
:
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'
):
"""Select trace number 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
):
"""Set Data Format
...
...
@@ -247,7 +175,7 @@ class E5071C(object):
| 'PPH': Positive phase
| '' (def): the format will be queried
"""
self
.
com
(
"CALC:SEL:CORR:EDEL:TIME"
,
0
)
return
self
.
com
(
'CALC1:SEL:FORM'
,
Format
)
# READING data
...
...
@@ -266,71 +194,6 @@ class E5071C(object):
"""Return the last raw S measurement (before correction) in complex form."""
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
):
"""Return the current type correction used."""
...
...
@@ -346,6 +209,13 @@ class E5071C(object):
self
.
com
(
':TRIG:AVER'
,
'OFF'
)
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
):
"""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():
self
.
_stop
=
None
self
.
_npoints
=
None
self
.
_type
=
None
self
.
unit
=
'Hz'
if
data
is
None
:
self
.
start
=
start
...
...
@@ -300,9 +301,12 @@ class VNA(Instrument):
self
.
devtype
=
'VNA'
# Load driver ##########################################################
if
id_string
==
'VNA3'
or
id_string
[:
4
]
==
"VNA4"
:
if
id_string
==
'VNA3'
:
from
.Drivers.Keysight.E5080
import
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'
:
from
.Drivers.Keysight.E5071C
import
E5071C
self
.
driver
=
E5071C
...
...
@@ -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
self
.
segments
=
None
self
.
S_parameters
=
None
def
start
(
self
):
self
.
instr
.
set_trigger
()
...
...
@@ -372,7 +378,8 @@ class VNA(Instrument):
S_parameters
=
[
'S21'
],
correction
=
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).
...
...
@@ -398,46 +405,78 @@ class VNA(Instrument):
| 'IMAG' imaginary part of the complex data
| 'UPH': Extended 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
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.'
)
if
before_measurement
:
## We define all the important parameter before the first measurement
number_trace
=
len
(
S_parameters
)
self
.
instr
.
traces_number
(
number_trace
)
self
.
S_parameters
=
[
spar
.
upper
()
for
spar
in
S_parameters
]
for
i
,
spar
in
enumerate
(
S_parameters
):
self
.
instr
.
trace_select
(
i
+
1
)
self
.
instr
.
Spar
(
spar
,
i
+
1
)
self
.
instr
.
Format
(
format_vna
)
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
.
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'
)},
{
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
)})
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
):
""" Get the data from last measurement. Notice that you should have started the measurement
using the measure methods. """
if
self
.
S_parameters
is
not
None
:
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
(
S_parameters
)})
self
.
instr
.
read_measurement
(
trace
=
i
+
1
),
''
,
[
'VNA Frequency'
])
for
i
,
spar
in
enumerate
(
self
.
S_parameters
)})
else
:
raise
Exception
(
'You should start the measurement before trying to get data.'
)
# Measurement functions ####################################################
def
meas
(
self
,
f_range
,
npoints
=
1601
,
navg
=
10
,
power
=-
50
,
BW
=
1e3
,
...
...
Instruments/core.py
View file @
52ce600e
...
...
@@ -76,6 +76,11 @@ class Instrument():
pass
def
start
(
self
):
""" Activate the output of the instrument but not necessary the measurement.
For example, for a VNA, you have to start the instrument to activate the power and finish to
setup it. Then you will need to call the measure function to perform an actual measurement.
"""
pass
def
stop
(
self
):
...
...
experiment.py
View file @
52ce600e
...
...
@@ -23,7 +23,7 @@ class BondedParameter():
self
.
fixed_value
=
fixed_value
self
.
unit
=
unit
self
.
metadata
=
{
'Coupled'
:
False
,
'OnOff'
:
False
,
'Off'
:
Non
e
}
self
.
metadata
=
{
'Coupled'
:
False
,
'OnOff'
:
False
,
'Off'
:
Fals
e
}
self
.
on_off_parameter
=
False
self
.
swept_by_instrument
=
False
...
...
@@ -53,7 +53,7 @@ class BondedOnOffParameter(BondedParameter):
self
.
off_value
=
off_value
self
.
metadata
[
'OnOff'
]
=
True
self
.
meta
t
dat
[
'Off'
]
=
self
.
off_value
self
.
metadat
a
[
'Off'
]
=
self
.
off_value
self
.
must_be_swept
=
True
def
turn_on
(
self
,
instruments
,
value
):
...
...
@@ -79,7 +79,7 @@ class CoupledBondedParameters():
self
.
data
=
np
.
arange
(
len_data
)
self
.
default
=
None
self
.
unit
=
None
self
.
metadata
=
{
'Coupled'
:
True
,
'OnOff'
:
False
,
'Off'
:
Non
e
}
self
.
metadata
=
{
'Coupled'
:
True
,
'OnOff'
:
False
,
'Off'
:
Fals
e
}
self
.
metadata
.
update
({
parameter
.
parameter_name
+
'_data'
:
parameter
.
data
for
parameter
in
bonded_parameters
})
self
.
metadata
.
update
({
parameter
.
parameter_name
+
'_unit'
:
parameter
.
unit
for
parameter
in
bonded_parameters
})
self
.
swept_by_instrument
=
False
...
...
@@ -111,6 +111,9 @@ class BondedMeasurement():
def
__call__
(
self
,
instruments
,
additionnal_option
=
{}):
return
self
.
instrument_func
(
instruments
[
self
.
instrument_name
].
instrument_instance
,
**
additionnal_option
,
**
self
.
options
)
def
get_data
(
self
,
instruments
):
return
instruments
[
self
.
instrument_name
].
instrument_instance
.
get_data
()
class
BondedInstrument
():
...
...
@@ -364,7 +367,7 @@ class Experiment():
string_sweep_parameters
=
'Parameters which will be swept by python code:
\n
'
for
parameter
in
list
_parameters
:
for
parameter
in
sweep
_parameters
:
self
.
parameters
[
parameter
](
self
.
instruments
,
self
.
parameters
[
parameter
].
data
[
0
])
string_sweep_parameters
+=
'
\t
'
+
parameter
+
': '
string_sweep_parameters
+=
'start %.3g %s'
%
(
self
.
parameters
[
parameter
].
data
[
0
],
...
...
@@ -381,17 +384,19 @@ class Experiment():
self
.
parameters
[
parameter
].
metadata
)
\
for
parameter
in
sweep_parameters
})
def
measure
(
self
,
sweep_parameters
,
list_measurements
):
def
measure
(
self
,
sweep_parameters
,
list_measurements
,
sequential
=
True
):
"""
list
_parameters are parameters which will be sw
ip
, other parameter link to the instrument will
sweep
_parameters are parameters which will be sw
ept
, other parameter link to the instrument will
be initialized to the default parameter or the data[0] if no default value is provided
list_measurements are the parameter
sequential if true, then measurements are performed one after another.
"""
# We first initialize everything
# Initialize fixed & swept parameters for the instrument
initialized_instruments
=
self
.
initialize_instruments
(
sweep_parameters
,
list_measurements
)
dataset
=
self
.
initialize_fixed_parameters
(
initialized_instruments
,
sweep_parameters
)
...
...
@@ -410,6 +415,7 @@ class Experiment():
iterate_on_off
=
list
(
itertools
.
product
(
*
([[
parameter
,
'on'
],
[
parameter
,
'off'
]]
\
for
parameter
in
on_off_sweep_parameter
)))
def
get_name_measurement
(
on_off
):
string
=
''
for
el
in
on_off
:
...
...
@@ -418,18 +424,19 @@ class Experiment():
# In case we want to save the temperature through the measurement,
# we add it to the measurement list
if
self
.
save_temperature
:
list_measurement
.
append
(
[
'temperature'
]
)
list_measurement
s
.
append
(
'temperature'
)
# Create the dataset for each measurement. Each dataset is multidimensional, indexing is determined be the number of swept parameters
for
measurement
in
list_measurements
:
dataset_measurements
=
self
.
measurements
[
measurement
](
self
.
instruments
,
{
'before_measurement'
:
True
})
# Take into account the indexing with the parameters of the measurements
for
meas
in
dataset_measurements
.
measurements
.
values
():
#Wasn't meas.indexing empty after the initialization?
meas
.
indexing
=
sweep_parameters
+
meas
.
indexing