Warning!
This is an archived version of the documentation.
It is strongly advised to use the latest version available at
https://docs.zhinst.com/zhinst-qcodes/en/latest/index.html
UHFLI¶
We use the ziqc.UHFLI
instrument driver for the UHFLI Lock-In amplifier.
[1]:
import numpy as np
import matplotlib.pyplot as plt
import qcodes as qc
import zhinst.qcodes as ziqc
uhfli = ziqc.UHFLI("uhf1", "dev2324", interface="1GbE", host="10.42.0.226")
Successfully connected to data server at 10.42.0.2268004 api version: 6
Successfully connected to device DEV2324 on interface 1GBE
Connected to: Zurich Instruments UHFLI (serial:dev2324, firmware:65939) in 1.49s
Nodetree¶
Access the UHFLI’s nodetree:
[2]:
print([k for k in uhfli.submodules.keys()])
print([k for k in uhfli.parameters.keys()])
['awg', 'daq', 'sweeper', 'stats', 'oscs', 'demods', 'extrefs', 'triggers', 'status', 'dios', 'auxins', 'system', 'sigins', 'sigouts', 'mods', 'boxcars', 'outputpwas', 'inputpwas', 'aucarts', 'aupolars', 'pids', 'features', 'auxouts', 'cnts']
['IDN', 'clockbase']
The Parameter
sample of the demodulators uses the getSample(...)
method of the ziPython API to read the latest sample of the demodulator.
[3]:
uhfli.demods[0].sample()
[3]:
(0.35024545059240686+0.0008896467610803594j)
⚠️ Note that this parameter only returns a single sample. There is no guarantee for any precise time-relation between consecutive samples. For proper (triggered) data acquisition of signals aligned to a precise time-grid, please use the Data Acquisition Module (see below).
The Data Acquisition Module of the UHFLI¶
Similarly to the MFLI, the UHFLI comes with a Data Acquisition Module. For more details, see the corresponding example about the Data Acquisition Module.
[4]:
print([k for k in uhfli.daq.parameters.keys()])
['awgcontrol', 'bandwidth', 'bitmask', 'bits', 'buffercount', 'buffersize', 'clearhistory', 'count', 'delay', 'device', 'duration', 'edge', 'enable', 'endless', 'eventcount_mode', 'fft_absolute', 'fft_window', 'findlevel', 'flags', 'forcetrigger', 'grid_cols', 'grid_direction', 'grid_mode', 'grid_overwrite', 'grid_repetitions', 'grid_rowrepetition', 'grid_rows', 'grid_waterfall', 'historylength', 'holdoff_count', 'holdoff_time', 'hysteresis', 'level', 'preview', 'pulse_max', 'pulse_min', 'refreshrate', 'save_csvlocale', 'save_csvseparator', 'save_directory', 'save_fileformat', 'save_filename', 'save_save', 'save_saveonread', 'spectrum_autobandwidth', 'spectrum_enable', 'spectrum_frequencyspan', 'spectrum_overlapped', 'triggered', 'triggernode', 'type']
The method signals_list()
shows the available sources of streaming signals. Note that they differ with the installed options of the UHFLI.
[5]:
uhfli.daq.signals_list()
[5]:
['dio0',
'auxin0',
'scope0',
'boxcar0',
'boxcar1',
'outputpwa0',
'outputpwa1',
'inputpwa0',
'inputpwa1',
'aucart0',
'aucart1',
'aupolar0',
'aupolar1',
'cnt0',
'cnt1',
'cnt2',
'cnt3',
'demod0',
'demod1',
'demod2',
'demod3',
'demod4',
'demod5',
'demod6',
'demod7',
'pid0_value',
'pid0_error',
'pid0_shift',
'pid1_value',
'pid1_error',
'pid1_shift',
'pid2_value',
'pid2_error',
'pid2_shift',
'pid3_value',
'pid3_error',
'pid3_shift']
Use the method signals_add(..)
to specify which signals should be acquired during a measurement. The return value gives the exact node path that will be subscribed to before the measurement.
[6]:
demod_x = uhfli.daq.signals_add("demod0", "x")
demod_y = uhfli.daq.signals_add("demod0", "y")
# which signal nodes have been added?
print(uhfli.daq.signals)
['/dev2324/demods/0/sample.x.avg', '/dev2324/demods/0/sample.y.avg']
Use trigger type, grid columns, grid rows and other parameters to configure the measurement you want.
[7]:
uhfli.daq.type("continuous")
uhfli.daq.grid_cols(100)
uhfli.daq.grid_rows(100)
The measurement routine is started using the measure(...)
method. At first, the mdoule will subscribe to the signal nodes that were previously added to the measurement. Then the measurement is started. When it is finished, the results will be added to the results
property of the daq
Module.
[8]:
uhfli.daq.measure()
subscribed to: /dev2324/demods/0/sample.x.avg
subscribed to: /dev2324/demods/0/sample.y.avg
Progress: 0.0%
Progress: 5.0%
Progress: 12.0%
Progress: 19.0%
Progress: 30.0%
Progress: 37.0%
Progress: 48.0%
Progress: 55.0%
Progress: 62.0%
Progress: 73.0%
Progress: 80.0%
Progress: 91.0%
Progress: 98.0%
Finished
The results property is a dictionary with the exact signal node as its keys. The return value from signals_add(..)
can be used to access the result of that signal. The value in the dictionary is a DAQResult
object that contains all measurement information such as the measurement values, the time- or frequency-axis as well as meta-information.
[9]:
uhfli.daq.results[demod_x]
[9]:
<zhinst.toolkit.control.drivers.base.daq.DAQResult object at 0x000001DD6E8CA6D8>
path: /dev2324/demods/0/sample.x.avg
value: (100, 100)
time: (100,)
[10]:
uhfli.daq.results[demod_y]
[10]:
<zhinst.toolkit.control.drivers.base.daq.DAQResult object at 0x000001DD6E8CA710>
path: /dev2324/demods/0/sample.y.avg
value: (100, 100)
time: (100,)
[11]:
import matplotlib.pyplot as plt
result_x = uhfli.daq.results[demod_x]
plt.imshow(result_x.value, extent=[result_x.time[0], result_x.time[-1], 0, 100], aspect="auto")
plt.show()
The Sweeper Module of the UHFLI¶
The UHFLI also feeatures a Sweeper Module with all of the following Parameters:
[12]:
print([k for k in uhfli.sweeper.parameters.keys()])
['averaging_sample', 'averaging_tc', 'averaging_time', 'awgcontrol', 'bandwidth', 'bandwidthcontrol', 'bandwidthoverlap', 'clearhistory', 'device', 'endless', 'gridnode', 'historylength', 'loopcount', 'maxbandwidth', 'omegasuppression', 'order', 'phaseunwrap', 'remainingtime', 'samplecount', 'save_csvlocale', 'save_csvseparator', 'save_directory', 'save_fileformat', 'save_filename', 'save_save', 'save_saveonread', 'scan', 'settling_inaccuracy', 'settling_tc', 'settling_time', 'sincfilter', 'start', 'stop', 'xmapping']
As for the Data Acquisition Module the available signal sources can be shown with signals_list(...)
. They can differ depending on the options installed in the instrument.
[13]:
uhfli.sweeper.signals_list()
[13]:
['dio0',
'auxin0',
'scope0',
'boxcar0',
'boxcar1',
'outputpwa0',
'outputpwa1',
'inputpwa0',
'inputpwa1',
'aucart0',
'aucart1',
'aupolar0',
'aupolar1',
'cnt0',
'cnt1',
'cnt2',
'cnt3',
'demod0',
'demod1',
'demod2',
'demod3',
'demod4',
'demod5',
'demod6',
'demod7',
'pid0_value',
'pid0_error',
'pid0_shift',
'pid1_value',
'pid1_error',
'pid1_shift',
'pid2_value',
'pid2_error',
'pid2_shift',
'pid3_value',
'pid3_error',
'pid3_shift']
The Parameters that are available for sweeping can be listed with sweep_parameter_list()
.
[14]:
uhfli.sweeper.sweep_parameter_list()
[14]:
['auxout0_offset',
'auxout1_offset',
'auxout2_offset',
'auxout3_offset',
'awg_amplitude0',
'awg_amplitude1',
'awg_trigger0',
'awg_trigger1',
'awg_trigger2',
'awg_trigger3',
'awg_triggerlevel0',
'awg_triggerlevel1',
'awg_userreg0',
'awg_userreg1',
'awg_userreg2',
'awg_userreg3',
'awg_userreg4',
'awg_userreg5',
'awg_userreg6',
'awg_userreg7',
'awg_userreg8',
'awg_userreg9',
'awg_userreg10',
'awg_userreg11',
'awg_userreg12',
'awg_userreg13',
'awg_userreg14',
'awg_userreg15',
'boxcar0_windowsize',
'boxcar0_windowstart',
'boxcar1_windowsize',
'boxcar1_windowstart',
'mod0_carrieramp',
'mod0_index',
'mod0_sideband0amp',
'mod0_sideband1amp',
'mod1_carrieramp',
'mod1_index',
'mod1_sideband0amp',
'mod1_sideband1amp',
'demdod0_phase',
'demdod1_phase',
'demdod2_phase',
'demdod3_phase',
'demdod4_phase',
'demdod5_phase',
'demdod6_phase',
'demdod7_phase',
'frequency0',
'frequency1',
'frequency2',
'frequency3',
'frequency4',
'frequency5',
'frequency6',
'frequency7',
'pid0_setpoint',
'pid1_setpoint',
'pid2_setpoint',
'pid3_setpoint',
'output0_amp',
'output0_offset',
'output1_amp',
'output2_offset']
A typical frequency sweep of the first oscillator frequency (‘frequency0’) from 1-10 kHz and 100 steps is configured as follows. We add the signal from the first demodulator (‘demod0’) to the measurement.
[15]:
# turn singal output on
uhfli.sigouts[0].on(1)
# prepare a frequency sweep
uhfli.sweeper.start(1e3)
uhfli.sweeper.stop(10e3)
uhfli.sweeper.samplecount(100)
uhfli.sweeper.sweep_parameter("frequency0")
# add a singal source
demod = uhfli.sweeper.signals_add("demod0")
set sweep parameter to 'frequency0': 'oscs/0/freq'
[16]:
uhfli.sweeper.signals
[16]:
['/dev2324/demods/0/sample']
The measurement is simply started with the measure()
method:
[17]:
# perform measurement
uhfli.sweeper.measure()
subscribed to: /dev2324/demods/0/sample
Sweeping oscs/0/freq from 1000.0 to 10000.0
Progress: 0.0%
Progress: 7.0%
Progress: 14.0%
Progress: 22.0%
Progress: 29.0%
Progress: 36.0%
Progress: 43.0%
Progress: 51.0%
Progress: 59.0%
Progress: 66.0%
Progress: 74.0%
Progress: 82.0%
Progress: 90.0%
Progress: 98.0%
Finished
The results are stored in the results
dictionary with the exact node path as the key. The value is a DAQResults
object from the zhinst-toolkit
. It contains all the data of the demodulator that has been returned by the Python API.
[18]:
result = uhfli.sweeper.results[demod]
[19]:
result
[19]:
<zhinst.toolkit.control.drivers.base.sweeper.SweeperResult object at 0x000001DD6ED9F7B8>
attributes:
- header
- timestamp
- samplecount
- flags
- sampleformat
- sweepmode
- bandwidthmode
- auxin0
- auxin0pwr
- auxin0stddev
- auxin1
- auxin1pwr
- auxin1stddev
- bandwidth
- frequency
- frequencypwr
- frequencystddev
- grid
- phase
- phasepwr
- phasestddev
- r
- rpwr
- rstddev
- settling
- tc
- tcmeas
- x
- xpwr
- xstddev
- y
- ypwr
- ystddev
- count
- nexttimestamp
- settimestamp
[20]:
import matplotlib.pyplot as plt
plt.plot(result.frequency, result.x)
plt.show()