xarray dataset dependency is incorrect when adding an independent parameter to the measurement
- Dominant language
- Python
- Stars
- 459
- Forks
- 359
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 73
Description
I created a parameter with setpoints `Y` which depends on setpoint `X`.
Then I created another parameter `Z` which is independent from the other two.
I measured `Y` and `Z` in the measurement context, then convert the result dataset to an xarray.
### Expected behaviour
I expect that the `Y` would be a data variable that depends on `X`, and `Z` on index, as inferred from the `paramspecs`.
```
{'foo_instrument_X': ParamSpec('foo_instrument_X', 'array', 'X', '', inferred_from=[], depends_on=[]),
'foo_instrument_Y': ParamSpec('foo_instrument_Y', 'array', 'Y', '', inferred_from=[], depends_on=['foo_instrument_X']),
'foo_instrument_Z': ParamSpec('foo_instrument_Z', 'numeric', 'Z', '', inferred_from=[], depends_on=[])}
```
### Actual behaviour
All parameters became data variables that depended on index.
### Steps to reproduce
Run the following snippet
```python
import numpy as np
import qcodes as qc
from qcodes import Measurement
from qcodes.instrument import Instrument
from qcodes.parameters import Parameter, ParameterWithSetpoints
from qcodes.validators import Arrays, Numbers
class FooGeneratedSetpoints(Parameter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def get_raw(self):
return np.array(range(4,8))
class FooArray(ParameterWithSetpoints):
def get_raw(self):
return np.array(range(4))
class FooInstrument(Instrument):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.add_parameter(
"X",
parameter_class=FooGeneratedSetpoints,
vals=Arrays(shape=(4,))
)
self.add_parameter(
"Y",
parameter_class=FooArray,
setpoints=(self.X,),
vals=Arrays(shape=(4,))
)
foo = FooInstrument("foo_instrument")
foo.add_parameter("Z", set_cmd=None)
meas = Measurement()
meas.register_parameter(foo.Y)
meas.register_parameter(foo.Z)
with meas.run() as datasaver:
for z in range(8,12):
datasaver.add_result(
(foo.Y, foo.Y()), (foo.Z, z)
)
dataset = datasaver.dataset
dataset.to_xarray_dataset()
```
If I modify the setpoint to the following, the issue disappeared and the result dataset is as expected.
```python
from random import random
class FooGeneratedSetpoints(Parameter):
...
def get_raw(self):
return np.array([random() + i for i in range(4,8)])
...
```
Contributor guide
Research direction
Start with the Measurement, datasaver.dataset, and to_xarray_dataset entry points from the reproduction, then trace how ParamSpec depends_on metadata is converted into xarray variables. Reproduce the example with deterministic setpoints and compare the resulting dependencies for X, Y, and independent Z. Done means Y depends on X while Z depends on the index, with regression coverage for this case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- numpy, python
- Domain
- data
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100