Repository: microsoft/Qcodes

Issue:
Conversion from xarray dataset fails for transposed array

###
The conversion from an xarray `Dataset` to qcodes format can fail of the order of the dimensions of a dataarray is not equal to the order of the coords.

### Steps to reproduce

A minimal example is
```
import qcodes.data.data_set
import qcodes.tests.legacy.data_mocks
qd=qcodes.tests.legacy.data_mocks.DataSet2D()
ds=qd.to_xarray().transpose()
qdt = qcodes.data.data_set.DataSet.from_xarray(ds)
print(qdt) 

# qdt has incorrect dimensions of the setpoints. this is due to the ordering of the coords which are not taken from the dims of the dataarray

# the correct order is given by
print(ds.to_dict()['data_vars']['z']['dims'])
```
This has output
```
DataSet:
   location = '2021-12-10/10-16-33_qtt_generic'
   <Type>   | <array_id> | <array.name> | <array.shape>
   Setpoint | x_set      | x_set        | (6,)
   Setpoint | y_set      | y_set        | (6, 4)
   Measured | z          | z            | (4, 6)
('y_set', 'x_set')
```

### Expected behaviour
The converted dataset `qdt` should be a correct qcodes dataset

### Actual behaviour

The output dataset has incorrect setpoints `y_set` and `x_set`.

### System

**operating system** Windows 10
**qcodes version** '0.30.1+43.gdd1d53811'



Discussion:

Resolving patch:
diff --git a/qcodes/data/data_array.py b/qcodes/data/data_array.py
--- a/qcodes/data/data_array.py
+++ b/qcodes/data/data_array.py
@@ -573,12 +573,12 @@ def data_array_to_xarray_dictionary(data_array: DataArray) -> Dict[str, Any]:
     Returns:
         dict: A dictionary containing the data in xarray format.
     """
-    key_mapping = {"unit": "unit", "name": "name", "label": "label"}
+    key_mapping = {"unit": "units", "name": "name", "label": "long_name"}
 
-    data_dictionary = {
+    data_dictionary: Dict[str, Any] = {"name": data_array.array_id}
+    data_dictionary["attrs"] = {
         target_key: getattr(data_array, key) for key, target_key in key_mapping.items()
     }
-    data_dictionary['long_name'] = data_array.name
     if data_array.is_setpoint:
         data_dictionary["dims"] = tuple([data_array.array_id])
         data_dictionary["depends_on"] = data_dictionary["dims"]
@@ -614,12 +614,12 @@ def xarray_data_array_dictionary_to_data_array(
         preset_data = np.array(array_dictionary["data"])
     array_name = array_dictionary.get("name", array_id)
 
-    array_full_name = array_dictionary.get("long_name", array_name)
+    array_full_name = array_dictionary["attrs"].get("long_name", array_name)
     data_array = DataArray(
         name=array_name,
         full_name=array_full_name,
-        label=array_dictionary.get("label", ""),
-        unit=array_dictionary.get("unit", None),
+        label=array_dictionary["attrs"].get("long_name", ""),
+        unit=array_dictionary["attrs"].get("units", None),
         is_setpoint=is_setpoint,
         shape=preset_data.shape,
         array_id=array_id,
diff --git a/qcodes/data/data_set.py b/qcodes/data/data_set.py
--- a/qcodes/data/data_set.py
+++ b/qcodes/data/data_set.py
@@ -784,7 +784,16 @@ def xarray_dictionary_to_dataset(
 
     grid_coords: List[Any] = []
     set_array_names = []
-    for array_key, coord_dictionary in xarray_dictionary["coords"].items():
+
+    coordinate_names = list(xarray_dictionary["data_vars"].values())[0]["dims"]
+
+    assert set(coordinate_names) == set(xarray_dictionary["coords"]), (
+        "conversion to qcodes requires all coordinates"
+        + " to match data variable coordinates"
+    )
+
+    for array_key in coordinate_names:
+        coord_dictionary = xarray_dictionary["coords"][array_key]
         preset_data = np.array(coord_dictionary["data"])
 
         tiled_preset_data = np.tile(preset_data, [g.size for g in grid_coords] + [1])


Test patch:
diff --git a/qcodes/tests/legacy/test_data.py b/qcodes/tests/legacy/test_data.py
--- a/qcodes/tests/legacy/test_data.py
+++ b/qcodes/tests/legacy/test_data.py
@@ -1,23 +1,33 @@
-from unittest import TestCase
-import numpy as np
+import logging
 import os
 import pickle
-import logging
+from unittest import TestCase
+
+import numpy as np
 import pandas as pd
 import xarray as xr
 
-from qcodes.data.location import FormatLocation
 from qcodes.data.data_array import DataArray, data_array_to_xarray_dictionary
+from qcodes.data.data_set import (
+    DataSet,
+    load_data,
+    new_data,
+    qcodes_dataset_to_xarray_dataset,
+    xarray_dataset_to_qcodes_dataset,
+)
 from qcodes.data.io import DiskIO
-from qcodes.data.data_set import load_data, new_data, DataSet, qcodes_dataset_to_xarray_dataset,\
-    xarray_dataset_to_qcodes_dataset
+from qcodes.data.location import FormatLocation
 from qcodes.logger.logger import LogCapture
 
-from .data_mocks import (MockFormatter, MatchIO,
-                         DataSet2D, DataSet1D,
-                         DataSetCombined, RecordingMockFormatter)
-
 from ..common import strip_qc
+from .data_mocks import (
+    DataSet1D,
+    DataSet2D,
+    DataSetCombined,
+    MatchIO,
+    MockFormatter,
+    RecordingMockFormatter,
+)
 
 
 class TestDataArray(TestCase):
@@ -295,8 +305,8 @@ def test_xarray_conversions(self):
         xarray_dataarray = da.to_xarray()
         da_transformed = DataArray.from_xarray(xarray_dataarray)
 
-        for key in ["name", "unit", "label"]:
-            self.assertEqual(da.name, da_transformed.name)
+        for key in ["array_id", "unit", "label"]:
+            self.assertEqual(getattr(da, key), getattr(da_transformed, key))
 
 
 class TestLoadData(TestCase):
@@ -634,3 +644,14 @@ def test_xarray_example_conversion(self):
         self.assertEqual(list(xarray_dataset.coords.keys()), list(xarray_dataset2.coords.keys()))
         self.assertEqual(list(xarray_dataset.data_vars.keys()), list(xarray_dataset2.data_vars.keys()))
         self.assertEqual(xarray_dataset.tmin.shape, xarray_dataset2.tmin.shape)
+
+    def test_dataset_conversion_transpose_regression(self):
+        qd = DataSet2D(name="test")
+        qd.x_set.label = "X label"
+        qd.x_set.unit = "seconds"
+        ds = qd.to_xarray().transpose()
+        qdt = DataSet.from_xarray(ds)
+
+        self.assertEqual(qd.x_set.label, qdt.x_set.label)
+        self.assertEqual(qd.x_set.unit, qdt.x_set.unit)
+        self.assertEqual([a.name for a in qdt.z.set_arrays], ["y_set", "x_set"])