Qcodes icon indicating copy to clipboard operation
Qcodes copied to clipboard

Parameter.__getitem__ behavior

Open thangleiter opened this issue 9 months ago • 5 comments

Parameters can be indexed to return SweepFixedValues. This is a handy shortcut if you know it exists and use it correctly. However, it can lead to extremely unpredictable behavior when parameters are used in the wrong context, for example if a Parameter is passed to a function that expects an Iterable.

The function might try to convert the Iterable to a list and calls list(param), which runs forever if the parameter's validator passes all positive integers. In my opinion, this is very unhandy behavior and not worth the syntactic sugar of writing param[:10] instead of having a method that achieves the same thing without the unintended consequences of making Parameter iterable.

An example, where the unassuming user passes a Parameter instead of a sequence of parameters as setpoints to Measurement.register_parameter:

from qcodes.parameters import ManualParameter, ParameterWithSetpoints
from qcodes.validators import Arrays
from qcodes.dataset import Measurement

getme = ManualParameter('foo')
setme = ManualParameter('bar')

meas = Measurement()
meas.register_parameter(setme)
meas.register_parameter(getme, setpoints=setme)
# should error, since setpoints should be Sequence[Union[str, "ParameterBase"]]
# instead, raises obscure error
AttributeError: 'SweepFixedValues' object has no attribute 'register_name'

For ParameterWithSetpoints, register_parameter ends up trying to convert the argument to a list:

getme_setpoints = ParameterWithSetpoints('baz', setpoints=(setme,), vals=Arrays(shape=(10,)))

meas = Measurement()
meas.register_parameter(setme)
meas.register_parameter(getme_setpoints, setpoints=setme)
# should error, instead runs forever

In this case, it would even be cumbersome to check in _register_parameter_with_setpoints() if setpoints is the correct type, i.e., , because iter(setpoints) works even if setpoints is a Parameter! (*Well, Parameter is not an instance of Sequence, so not too cumbersome.)

Also runs forever:

for _ in setme:
    pass

My proposal is therefore to deprecate Parameter.__getitem__ and instead introduce a method like Parameter.sweep(keys: int | slice) or even mirror xarray and call it Parameter.iloc or something.

thangleiter avatar May 16 '24 15:05 thangleiter