Quick start#
A brief summary of what is needed to run a measurement.
Acquisition#
Set up configuration file for the acquisition device in /acq_dev_config.toml.
Example configruation for NIDAQ:
name = 'Daq1'
device = 'NIDAQ_Base'
[parameters]
device_name = "Dev1"
read_sample_rate = 50000.0
read_sample_rate_out = 1000.0
read_samples_per_chan = 10000.0
reads_per_sample = 1
read_samples_total = 10000.0
read_channels = ['ai1']
[latent_parameters]
units = "volts"
voltage_limits = 2
terminal_type = "RSE"
read_clock_source = "OnboardClock"
read_active_edge = "rising_edge"
read_sample_mode = "finite_samples"
read_timeout = "infinite_timeout"
read_trigger_channel = 'PFI0'
read_fill_mode = 'by_channel'
[preparations]
read = ['analog_input']
read_method = 'analog_input'
Scan Device#
Set up configuration file for the scan device in /scan_dev_config.toml.
Example configuration for SRS SG380:
name = "SG1"
device = "SG380"
[parameters]
frequency = 2.8e3
phase = 0
amplitude = 0.0
modulation_enabled = false
modulation_type = 'IQ'
modulation_function = 'External'
[latent_parameters]
IPaddress = '10.229.42.86'
port = '5025'
## Alternatively use GPIB
## GPIB = '27'
Scan Settings#
Set up the configuration for the scan in /scan_config.toml. Make sure the parameter names match those in /scan_dev_config.toml.
Example scan settings for scanning the frequency of an SG380:
name = 'SG1'
device = 'SG380'
parameter = 'frequency'
min = 1
max = 2
points = 10
repetitions = 1
scale = 'linear'
randomize = 'False'
note = ''
Measurement Generation File#
Collect the previous files in a file /generate_config.toml. For the scan_collection, the name must be {name}-{parameter}, with name being that of the scan device, and parameter is that to be scanned.
The file should look like this:
averages = 1
[acquisition_devices]
"Daq1" = ""
[scan_devices]
"SG1" = ""
[scan_collection]
"SG1-frequency" = "./scan_config.toml"
Then, the measurement configruation can be made through the generate_measurement_configuration.py script in tools. The command line arguments are -g for the generation file and -o for the file to save the generated measuremene configruation.
The prompt looks like:
>> python -m generate_measurement_configuration.py -g generate_config.toml -o measurement_config.toml
The full measurement configuration looks like:
averages = 1
[acquisition_devices.Daq1]
name = "Daq1"
device = "NIDAQ_Base"
[scan_devices.SG1]
name = "SG1"
device = "SG380"
[scan_collection.SG1-frequency]
name = "SG1"
device = "SG380"
parameter = "frequency"
min = 1
max = 2
points = 10
repetitions = 1
scale = "linear"
randomize = "False"
note = ""
[acquisition_devices.Daq1.parameters]
device_name = "Dev1"
read_sample_rate = 50000.0
read_sample_rate_out = 1000.0
read_samples_per_chan = 10000.0
reads_per_sample = 1
read_samples_total = 10000.0
read_channels = [ "ai1",]
[acquisition_devices.Daq1.latent_parameters]
units = "volts"
voltage_limits = 2
terminal_type = "RSE"
read_clock_source = "OnboardClock"
read_active_edge = "rising_edge"
read_sample_mode = "finite_samples"
read_timeout = "infinite_timeout"
read_trigger_channel = "PFI0"
read_fill_mode = "by_channel"
[acquisition_devices.Daq1.preparations]
read = [ "analog_input",]
read_method = "analog_input"
[scan_devices.SG1.parameters]
frequency = 2800.0
phase = 0
amplitude = 0.0
modulation_enabled = false
modulation_type = "IQ"
modulation_function = "External"
[scan_devices.SG1.latent_parameters]
IPaddress = "10.229.42.86"
port = "5025"
Run Measurement#
With the generated measurement configuration file, the measurement can be run with the run_baecon_measurement.py script. The command line ar are -c for the config file and -o for the file saving the data.
The prompt looks like:
>> python -m run_baecon_measurement.py -c generate_config.toml -o measurement_data.zarr
Data#
The raw data is an xarray.Dataset saved as a zarr file. For example,
if we used the frequency scan above (1 to 2 in 10 points) and the DAQ measuring
5 samples per frequency (instead of 1000), the Dataset accessing the
data would look like
In [58]: data = xarray.open_zarr('measurement_data.zarr')
In [59]: data
Out[59]:
<xarray.Dataset>
Dimensions: (frequency: 10, Daq: 5)
Coordinates:
* frequency (frequency) float64 1.0 1.111 1.222 1.333 ... 1.778 1.889 2.0
* Daq (Daq) int32 0 1 2 3 4
Data variables:
Daq_0 (frequency, Daq) float64 0.3101 0.1398 0.8195 ... 0.2323 0.07908
Coordinates:
* frequency (frequency) float64 1.0 1.111 1.222 1.333 ... 1.778 1.889 2.0
Dimensions without coordinates: Daq
Here Daq refers to the coordinate, which is the sample index, and Daq_0
is the first measurement made with Daq at each frequency. To access the data
array Daq_0, we can index the Dataset like a dictionary
In [40]: meas_0 = data['Daq_0']
In [41]: meas_0
Out[41]:
<xarray.DataArray 'Daq_0' (frequency: 10, Daq: 5)>
array([[0.31007643, 0.13983319, 0.81946348, 0.06386373, 0.84451861],
[0.72068642, 0.16112617, 0.17229398, 0.23464845, 0.91359624],
[0.50211397, 0.63015773, 0.87281202, 0.23805703, 0.16854426],
[0.12987982, 0.28634581, 0.24274497, 0.98717013, 0.57904668],
[0.18018263, 0.25442135, 0.62867808, 0.0741044 , 0.86772646],
[0.61305147, 0.65637227, 0.3857262 , 0.68949025, 0.22860304],
[0.97682538, 0.05933332, 0.00242159, 0.81892933, 0.10490373],
[0.34668295, 0.83486479, 0.54124973, 0.69320961, 0.19347784],
[0.8779518 , 0.24962297, 0.43079303, 0.90662706, 0.34527662],
[0.50067085, 0.83609408, 0.51693081, 0.23233917, 0.07908146]])
- Coordinates:
frequency (frequency) float64 1.0 1.111 1.222 1.333 … 1.778 1.889 2.0
Daq (Daq) int32 0 1 2 3 4
Then in the DataArray, the data can be indexed by the frequency
coordinates
In [43]: meas_0.sel({'frequency':1.1111}, method='nearest')
Out[43]:
<xarray.DataArray 'Daq_0' (Daq: 5)>
array([0.72068642, 0.16112617, 0.17229398, 0.23464845, 0.91359624])
Coordinates:
frequency float64 1.111
* Daq (Daq) int32 0 1 2 3 4
The method='nearest' is useful for indexing coordinates who’s values may
be complicated floats. The values of a coordinates can be accessed by
In [44]: meas_0.coords['frequency'].values
Out[44]:
array([1. , 1.11111111, 1.22222222, 1.33333333, 1.44444444,
1.55555556, 1.66666667, 1.77777778, 1.88888889, 2. ])
And the full data can be accessed simply by
In [45]: meas_0.values
Out[45]:
array([[0.31007643, 0.13983319, 0.81946348, 0.06386373, 0.84451861],
[0.72068642, 0.16112617, 0.17229398, 0.23464845, 0.91359624],
[0.50211397, 0.63015773, 0.87281202, 0.23805703, 0.16854426],
[0.12987982, 0.28634581, 0.24274497, 0.98717013, 0.57904668],
[0.18018263, 0.25442135, 0.62867808, 0.0741044 , 0.86772646],
[0.61305147, 0.65637227, 0.3857262 , 0.68949025, 0.22860304],
[0.97682538, 0.05933332, 0.00242159, 0.81892933, 0.10490373],
[0.34668295, 0.83486479, 0.54124973, 0.69320961, 0.19347784],
[0.8779518 , 0.24962297, 0.43079303, 0.90662706, 0.34527662],
[0.50067085, 0.83609408, 0.51693081, 0.23233917, 0.07908146]])