The Measure class

qcodespp.Measure is used to measure a set of Parameter s at a single point in time. The typical use case is where the Parameter (s)’s get function(s) return(s) an array, e.g. an oscilloscope trace, or a spectrum analyser trace, or an instrument buffer. Importantly, the array shape(s) do(es) not need to be known in advance.

The Parameter s to be measured are provided at init or through station.set_measurement(). Optionally, setpoints may be provided, but this is usually not required nor recommended. If no setpoints are provided, dummy setpoints are created for each dimension found in the measured parameters (recommended, see Setpoints section below).

Examples:

Measure two parameters:

station.set_measurement(array_param1, array_param2)
data = qc.Measure(name='Name for dataset filename').run()

Measure two parameters twice, changing some value in between:

station.set_measurement(array_param1, array_param2)
measure = qc.Measure()
data=measure.run(name='instrument parameter value = 0')
instrument.some_parameter(1.0)  # Set some parameter to a value
data=measure.run(name='instrument parameter value = 1')

Iteratively:

station.set_measurement(array_param1, array_param2)
measure = qc.Measure()
for i in range(10):
    instrument.some_parameter(i)  # Set some parameter to a value
    data=measure.run(name=f'iteration {i}')

And of course if the parameters return 1D or 2D rectangular arrays, you can plot the results using

pp=qc.live_plot(data.array_param1, data.array_param2)

Comparison with Loop

The major difference is that Measure can be used in situations where the shape of the data is not known in advance, or where the shape of the data changes between measurements. This is because Measure constructs the DataSetPP after the data is collected. By contrast, the DataSetPP in a Loop is constructed with a known shape, before measurement, based on the sweep parameters. Each get() call from each measured Parameter in a Loop must therefore return the same shape, otherwise data will not fit in the pre-constructed array.

Note however that Loop is perfectly capable of storing rectangular ND arrays as elements. In the case that array_param1 and array_param2 don’t change their shape when varying instrument.some_parameter you can run the iterative measurement above using Loop:

station.set_measurement(array_param1, array_param2)
loop = qc.loop1d(sweep_parameter=instrument.some_parameter,
                start=0,stop=9,num=10,delay=0.1,
                device_info='info', instrument_info='info')
data=loop.run()

Setpoints

Elements in a DataSetPP can either be ‘setpoints’ (i.e. independent parameters) or ‘measured’ (i.e. dependent parameters). Each ‘measured’ element must have corresponding ‘setpoints’ with the correct dimensions. In the case of Loop, the setpoints are automatically generated based on the sweep parameters, and the measured data is automatically assigned to the correct setpoints. For Measure, this has no obvious meaning since it’s not obvious what the independent parameters are. By default, each measured element gets associated with setpoints that are simply the indices of the measured data, i.e. for a measured element with shape (10,), the setpoints will be (0, 1, 2, …, 9). Therefore, it’s usually much more interesting to plot two measured elements against each other, rather than against the default setpoints.

For example, if you measure the x-axis and y-axis of an oscilloscope trace, you can do:

station.set_measurement(oscilloscope.x_axis,oscilloscope.y_axis)
measure = qc.Measure(name='dummy_name')
data = measure.run()
pp=qc.live_plot()
pp.add(data.oscilloscope_x_axis, data.oscilloscope_y_axis,
        title='Oscilloscope trace', name='oscilloscope_trace', subplot=0)

Optionally, one can provide setpoints to the Measure class, which has the disadvantage of being tricky to set up, but the advantage that if you do set it up correctly, live_plot will detect the axes automatically. A measured element with shape (10,) must have a corresponding setpoint with shape (10,), and a measured element with shape (10, 5) must have two corresponding setpoints: one with shape (10, 5) and a second with shape (10,). If you are familiar with the DataSetPP objects generated by the Loop class, hopefully this system will also be familiar.

Examples of using setpoints:

For measuring a set of parameters with a shape of (101,):

setpoints=np.linspace(0,0.5,101)
measure = qc.Measure(setpoints=[setpoints],name='dummy_name')
data = measure.run()

The setpoints can also be a Parameter which returns an array of the correct shape. Taking the oscilloscope example from above, you can also do:

station.set_measurement(oscilloscope.y_axis)
setpoints=oscilloscope.x_axis
measure = qc.Measure(setpoints=[setpoints],name='dummy_name')
data = measure.run()
pp=qc.live_plot(data.oscilloscope_y_axis)

and the two axes will be plotted against each other correctly.

However, you can just as easily simply measure both parameters as measured elements, let the setpoints be created automatically, and then plot the data manually. This is the recommended way to do it, as it is much less error-prone.