Qcodes icon indicating copy to clipboard operation
Qcodes copied to clipboard

Setpoints are not handled correctly in measurement

Open simonzihlmann opened this issue 4 years ago • 3 comments

Measuring two different ParametersWithSetpoints (say pws1, pws2) in one measurement fails when pws1 has p1 as setpoints and pws2 has p1 and p2 as setpoints. Individual measurements of pws1 and pws2 are running smoothly.

Steps to reproduce

I will attach a jupyternotebook with an example.

Expected behaviour

Measurement should complete with measuring the 1D and the 2D parameter.

Actual behaviour

Measurement fails with the following error: ValueError: Incompatible shapes. Parameter data1d has shape (3,), but its setpoint t has shape (3, 2).

System

operating system windows 10

qcodes branch version 0.27.0

simonzihlmann avatar Aug 12 '21 09:08 simonzihlmann

There is a jupyter notebook in the zip file. I also post the code below. testing_qcodes_setpoints.zip

import qcodes as qc
import numpy as np
from qcodes.utils.dataset.doNd import  do0d, do1d, do2d
from qcodes import Parameter, ParameterWithSetpoints
from qcodes.utils.validators import Numbers, Arrays, Enum, Ints, Strings
class axis_1D(Parameter):
    """
    A parameter that holds a 1D axis, e.g. time
    """
    def __init__(self, dim, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._dim = dim
        self.vals=Arrays(shape=(self._dim,))
        
    def get_raw(self):
        # return dummy axis
        axis = np.linspace(1,self._dim,self._dim)
        return axis
# create two instances of the axis_1D, e.g. time and frequency
t_axis = axis_1D(name='t', dim=3)
f_axis = axis_1D(name='f', dim=2)
t_axis()
array([1., 2., 3.])
f_axis()
array([1., 2.])
# Let's have a ParameterWithSetpoints depending on only the t_axis
class data1d(ParameterWithSetpoints):
    """
    A ParameterWithSetpoints that depends on one of these axes
    """
    def __init__(self, setpoints1, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setpoints=(setpoints1, )
#        print((len(self.setpoints[0]()), len(self.setpoints[1]()),))
#        print(np.zeros((len(self.setpoints[0]()), len(self.setpoints[1]()),)))
#        print(np.zeros((len(self.setpoints[0]()), len(self.setpoints[1]()),)).shape)
    
    def get_raw(self):
        # return dummy array of correct shape
        data_array = np.ones((len(self.setpoints[0]()),))
        return data_array
dat1d = data1d(name='data1d', setpoints1=t_axis,vals=Arrays(shape=(len(t_axis()),)))
dat1d()
array([1., 1., 1.])
# Let's have aother ParameterWithSetpoints depending on now both of these tow axes
class data2d(ParameterWithSetpoints):
    """
    A ParameterWithSetpoints that depends on both of these axes
    """
    def __init__(self, setpoints1, setpoints2, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setpoints=(setpoints1, setpoints2, )
#        print((len(self.setpoints[0]()), len(self.setpoints[1]()),))
#        print(np.zeros((len(self.setpoints[0]()), len(self.setpoints[1]()),)))
#        print(np.zeros((len(self.setpoints[0]()), len(self.setpoints[1]()),)).shape)
    
    def get_raw(self):
        # return dummy array of correct shape
        data_array = np.zeros((len(self.setpoints[0]()), len(self.setpoints[1]()),))
        return data_array
dat2d = data2d(name='data2d', setpoints1=t_axis, setpoints2=f_axis, vals=Arrays(shape=(len(t_axis()), len(f_axis()),)))
dat2d()
array([[0., 0.],
       [0., 0.],
       [0., 0.]])
# Let's measure them individually
do0d(dat1d, measurement_name='data1d', do_plot=True)
Starting experimental run with id: 32. Using 'qcodes.utils.dataset.doNd.do0d'
![image](https://user-images.githubusercontent.com/46719478/129174283-68d439e8-322d-4abb-a11b-8fc6c11e86ab.png)
# Let's measure them individually
do0d(dat2d, measurement_name='data2d', do_plot=True)
Starting experimental run with id: 33. Using 'qcodes.utils.dataset.doNd.do0d'
![image](https://user-images.githubusercontent.com/46719478/129174394-010cc783-fb88-4cf5-98af-36bbc8820065.png)
  • Here it fails
# Let's measure them both
do0d(dat1d, dat2d, measurement_name='data1d_and_data2d', do_plot=True)
2021-08-12 11:12:09,504 ¦ qcodes.dataset.measurements ¦ WARNING ¦ measurements ¦ __exit__ ¦ 638 ¦ An exception occured in measurement with guid: aaaaaaaa-0000-0000-0000-017b39a21810;
Traceback:
Traceback (most recent call last):
  File "C:\Users\G-GRE-GRE058050\Miniconda3\lib\site-packages\qcodes\utils\dataset\doNd.py", line 151, in do0d
    datasaver.add_result(
  File "C:\Users\G-GRE-GRE058050\Miniconda3\lib\site-packages\qcodes\dataset\measurements.py", line 214, in add_result
    self._validate_result_shapes(results_dict)
  File "C:\Users\G-GRE-GRE058050\Miniconda3\lib\site-packages\qcodes\dataset\measurements.py", line 419, in _validate_result_shapes
    raise ValueError(f'Incompatible shapes. Parameter '
ValueError: Incompatible shapes. Parameter data1d has shape (3,), but its setpoint t has shape (3, 2).

Starting experimental run with id: 34. Using 'qcodes.utils.dataset.doNd.do0d'
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
C:\Users\G-GRE-~1\AppData\Local\Temp/ipykernel_66732/553837965.py in <module>
      1 # Let's measure them both
----> 2 do0d(dat1d, dat2d, measurement_name='data1d_and_data2d', do_plot=True)

~\Miniconda3\lib\site-packages\qcodes\utils\dataset\doNd.py in do0d(write_period, measurement_name, exp, do_plot, use_threads, log_info, *param_meas)
    149 
    150     with meas.run() as datasaver:
--> 151         datasaver.add_result(
    152             *process_params_meas(
    153                 param_meas,

~\Miniconda3\lib\site-packages\qcodes\dataset\measurements.py in add_result(self, *res_tuple)
    212 
    213         self._validate_result_deps(results_dict)
--> 214         self._validate_result_shapes(results_dict)
    215         self._validate_result_types(results_dict)
    216 

~\Miniconda3\lib\site-packages\qcodes\dataset\measurements.py in _validate_result_shapes(self, results_dict)
    417                 #print('Setpoint {} has shape: {}'.format(setpoint.name, setpoint_shape)) ##SZ
    418                 if setpoint_shape not in [(), required_shape]:
--> 419                     raise ValueError(f'Incompatible shapes. Parameter '
    420                                      f"{toplevel_param.name} has shape "
    421                                      f"{required_shape}, but its setpoint "

ValueError: Incompatible shapes. Parameter data1d has shape (3,), but its setpoint t has shape (3, 2).

simonzihlmann avatar Aug 12 '21 09:08 simonzihlmann

Yes I think that is an unfortunate limitation of how the dataset is designed. I am not sure how straight forward this would be to solve. Going forward we are intending to make it easier for users create individual datasets for each measurement and encourage that a dataset only contains measured parameters with the same shape. This can currently be done with the measurement context manager interface. The intention is to add this to the generalized dond functions here https://github.com/QCoDeS/Qcodes/pull/3186 as well. This should land before the next qcodes release.

jenshnielsen avatar Aug 12 '21 09:08 jenshnielsen

Thanks @jenshnielsen for the rapid response. But I am not sure if I fully understand correctly. Is it a general limitation that one can only measure parameters with the same shape? Because I am only running into the problem of the above example if they share the same setpoints. It seems to me that there is something wrong in the determination of the setpoints of a parameter during the measurement.

The two lines just differ in the order of the parameters to measure:

do0d(dat1d, dat2d, measurement_name='data1d_and_data2d', do_plot=True)
ncompatible shapes. Parameter data1d has shape (3,), but its setpoint t has shape (3, 2)
do0d(dat2d, dat1d, measurement_name='data1d_and_data2d', do_plot=True)
Incompatible shapes. Parameter data2d has shape (3, 2), but its setpoint t has shape (3,).

--> it seems registering the second parameter somehow overwrites the setpoint shape of the first one.

Example with a different setpoint but still different shapes:

# create three instances of the axis_1D, e.g. time, time2, and frequency
t_axis = axis_1D(name='t', dim=3)
t_axis2 = axis_1D(name='t2', dim=3)
f_axis = axis_1D(name='f', dim=2)
# create the parameters with setpoints
dat1d = data1d(name='data1d', setpoints1=t_axis,vals=Arrays(shape=(len(t_axis()),)))
dat2d2 = data2d(name='data2d2', setpoints1=t_axis2, setpoints2=f_axis, vals=Arrays(shape=(len(t_axis()), len(f_axis()),)))
# Let's measure them both
do0d(dat1d, dat2d2, measurement_name='data1d_and_data2d', do_plot=True)
Starting experimental run with id: 73. 
(data1d_and_data2d #73@C:\Users\SZ258708\experiments.db
 ------------------------------------------------------
 t - array
 t2 - array
 f - array
 data1d - array
 data2d2 - array,
 [<AxesSubplot:title={'center':'Run #73, Experiment LETI_test (lot_wafer_die_2G11_1)'}, xlabel='t', ylabel='data1d'>,
  <AxesSubplot:title={'center':'Run #73, Experiment LETI_test (lot_wafer_die_2G11_1)'}, xlabel='t2', ylabel='f'>],
 [None, <matplotlib.colorbar.Colorbar at 0x1c3a6ee9148>])

image image

simonzihlmann avatar Aug 12 '21 10:08 simonzihlmann