From 98ca26bf863b45f535ccc748e23488bf8d726c97 Mon Sep 17 00:00:00 2001
From: Martin Lange <martin.lange@ufz.de>
Date: Thu, 8 Dec 2022 11:37:57 +0100
Subject: [PATCH] rename `to_xarray` to `prepare`, cleanup

---
 benchmarks/data/test_tools.py                 | 42 ++++++-------
 docs/source/conf.py                           |  1 -
 .../finam-book/development/data_metadata.rst  |  4 +-
 src/finam/adapters/time.py                    |  2 +-
 src/finam/data/__init__.py                    |  6 +-
 src/finam/data/grid_tools.py                  |  2 -
 src/finam/data/tools.py                       | 48 ++++++++-------
 src/finam/interfaces.py                       |  4 +-
 src/finam/sdk/adapter.py                      | 10 ++--
 src/finam/sdk/input.py                        |  2 +-
 src/finam/sdk/output.py                       |  8 +--
 tests/core/test_schedule.py                   | 58 +-----------------
 tests/core/test_sdk.py                        | 46 +--------------
 tests/data/test_tools.py                      | 59 +++++++++----------
 14 files changed, 99 insertions(+), 193 deletions(-)

diff --git a/benchmarks/data/test_tools.py b/benchmarks/data/test_tools.py
index dcb818b2..58177e26 100644
--- a/benchmarks/data/test_tools.py
+++ b/benchmarks/data/test_tools.py
@@ -14,88 +14,88 @@ from finam.data.tools import (
     get_magnitude,
     get_units,
     is_quantified,
+    prepare,
     strip_time,
     to_units,
-    to_xarray,
 )
 
 
-class TestCheckXarray(unittest.TestCase):
+class TestCheck(unittest.TestCase):
     @pytest.fixture(autouse=True)
     def setupBenchmark(self, benchmark):
         self.benchmark = benchmark
 
     @pytest.mark.benchmark(group="data-tools")
-    def test_check_xarray_01_2x1(self):
+    def test_check_01_2x1(self):
         time = dt.datetime(2000, 1, 1)
         info = fm.Info(time=time, grid=fm.UniformGrid((2, 1)), units="m")
         xdata = full(0.0, info)
         _result = self.benchmark(check, xdata=xdata, info=info)
 
     @pytest.mark.benchmark(group="data-tools")
-    def test_check_xarray_02_512x256(self):
+    def test_check_02_512x256(self):
         time = dt.datetime(2000, 1, 1)
         info = fm.Info(time=time, grid=fm.UniformGrid((512, 256)), units="m")
         xdata = full(0.0, info)
         _result = self.benchmark(check, xdata=xdata, info=info)
 
 
-class TestToXarray(unittest.TestCase):
+class TestPrepare(unittest.TestCase):
     @pytest.fixture(autouse=True)
     def setupBenchmark(self, benchmark):
         self.benchmark = benchmark
 
-    def copy_numpy_to_xarray(self, data, info):
-        return to_xarray(np.copy(data), info=info)
+    def copy_numpy_prepare(self, data, info):
+        return prepare(np.copy(data), info=info)
 
     @pytest.mark.benchmark(group="data-tools")
-    def test_to_xarray_np_01_2x1(self):
+    def test_prepare_np_01_2x1(self):
         time = dt.datetime(2000, 1, 1)
         info = fm.Info(time=time, grid=fm.UniformGrid((2, 1)), units="m")
         xdata = full(0.0, info)
-        _result = self.benchmark(to_xarray, data=xdata, info=info)
+        _result = self.benchmark(prepare, data=xdata, info=info)
 
     @pytest.mark.benchmark(group="data-tools")
-    def test_to_xarray_np_02_512x256(self):
+    def test_prepare_np_02_512x256(self):
         time = dt.datetime(2000, 1, 1)
         info = fm.Info(time=time, grid=fm.UniformGrid((512, 256)), units="m")
         xdata = full(0.0, info)
-        _result = self.benchmark(to_xarray, data=xdata, info=info)
+        _result = self.benchmark(prepare, data=xdata, info=info)
 
     @pytest.mark.benchmark(group="data-tools")
-    def test_to_xarray_np_03_2048x1024(self):
+    def test_prepare_np_03_2048x1024(self):
         time = dt.datetime(2000, 1, 1)
         info = fm.Info(time=time, grid=fm.UniformGrid((2048, 1024)), units="m")
         xdata = full(0.0, info)
-        _result = self.benchmark(to_xarray, data=xdata, info=info)
+        _result = self.benchmark(prepare, data=xdata, info=info)
 
     @pytest.mark.benchmark(group="data-tools-slow")
-    def test_cp_to_xarray_np_01_2x1(self):
+    def test_cp_prepare_np_01_2x1(self):
         time = dt.datetime(2000, 1, 1)
         info = fm.Info(time=time, grid=fm.UniformGrid((2, 1)), units="m")
         xdata = full(0.0, info)
-        _result = self.benchmark(self.copy_numpy_to_xarray, data=xdata, info=info)
+        _result = self.benchmark(self.copy_numpy_prepare, data=xdata, info=info)
 
     @pytest.mark.benchmark(group="data-tools-slow")
-    def test_cp_to_xarray_np_02_512x256(self):
+    def test_cp_prepare_np_02_512x256(self):
         time = dt.datetime(2000, 1, 1)
         info = fm.Info(time=time, grid=fm.UniformGrid((512, 256)), units="m")
         xdata = full(0.0, info)
-        _result = self.benchmark(self.copy_numpy_to_xarray, data=xdata, info=info)
+        _result = self.benchmark(self.copy_numpy_prepare, data=xdata, info=info)
 
     @pytest.mark.benchmark(group="data-tools-slow")
-    def test_cp_to_xarray_np_03_1024x512(self):
+    def test_cp_prepare_np_03_1024x512(self):
         time = dt.datetime(2000, 1, 1)
         info = fm.Info(time=time, grid=fm.UniformGrid((1024, 512)), units="m")
         xdata = full(0.0, info)
-        _result = self.benchmark(self.copy_numpy_to_xarray, data=xdata, info=info)
+        _result = self.benchmark(self.copy_numpy_prepare, data=xdata, info=info)
 
     @pytest.mark.benchmark(group="data-tools-slow")
-    def test_cp_to_xarray_np_04_2048x1024(self):
+    def test_cp_prepare_np_04_2048x1024(self):
         time = dt.datetime(2000, 1, 1)
         info = fm.Info(time=time, grid=fm.UniformGrid((2048, 1024)), units="m")
         xdata = full(0.0, info)
-        _result = self.benchmark(self.copy_numpy_to_xarray, data=xdata, info=info)
+        _result = self.benchmark(self.copy_numpy_prepare, data=xdata, info=info)
 
 
 class TestFull(unittest.TestCase):
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 2fc6c742..d7a75d0d 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -135,7 +135,6 @@ intersphinx_mapping = {
     "Python": ("https://docs.python.org/3/", None),
     "NumPy": ("https://numpy.org/doc/stable/", None),
     "SciPy": ("https://docs.scipy.org/doc/scipy/", None),
-    "xarray": ("https://docs.xarray.dev/en/stable/", None),
     "pint": ("https://pint.readthedocs.io/en/stable/", None),
     "pytest": ("https://docs.pytest.org/en/7.1.x/", None),
     "pyproj": ("https://pyproj4.github.io/pyproj/stable/", None),
diff --git a/docs/source/finam-book/development/data_metadata.rst b/docs/source/finam-book/development/data_metadata.rst
index 5923fd7e..62cd419f 100644
--- a/docs/source/finam-book/development/data_metadata.rst
+++ b/docs/source/finam-book/development/data_metadata.rst
@@ -20,9 +20,9 @@ Inputs receive data in the :mod:`xarray` form, with units and time axis.
 
 Several tool functions are provided in :mod:`.data` to convert to and from :class:`xarray.DataArray`:
 
-* :func:`to_xarray(data, info, time) <.data.to_xarray>`
+* :func:`prepare(data, info, time) <.data.prepare>`
   Wraps data, adds time axis and units based on ``info`` (see `The Info object`_).
-  Performs a metadata check if ``data`` is already an :class:`xarray.DataArray`.
+  Performs a metadata checks.
 * :func:`strip_time(xdata, grid) <.data.strip_time>`
   Squeezes away the time axis if there is a single entry only, and raises an error otherwise.
   Returns an :class:`xarray.DataArray` with units.
diff --git a/src/finam/adapters/time.py b/src/finam/adapters/time.py
index 73101267..16387d22 100644
--- a/src/finam/adapters/time.py
+++ b/src/finam/adapters/time.py
@@ -360,7 +360,7 @@ class StackTime(TimeCachingAdapter):
             break
 
         arr = np.stack([d[1] for d in extract])
-        return dtools.to_xarray(arr, self.info, time_entries=len(extract))
+        return dtools.prepare(arr, self.info, time_entries=len(extract))
 
 
 class LinearTime(TimeCachingAdapter):
diff --git a/src/finam/data/__init__.py b/src/finam/data/__init__.py
index b73084c9..aa30e4d1 100644
--- a/src/finam/data/__init__.py
+++ b/src/finam/data/__init__.py
@@ -49,11 +49,11 @@ Data tools
     get_units
     has_time_axis
     is_quantified
+    prepare
     quantify
     strip_time
     to_datetime
     to_units
-    to_xarray
 """
 
 from ..errors import FinamDataError
@@ -90,11 +90,11 @@ from .tools import (
     get_units,
     has_time_axis,
     is_quantified,
+    prepare,
     quantify,
     strip_time,
     to_datetime,
     to_units,
-    to_xarray,
 )
 
 __all__ = ["grid_spec", "grid_tools", "tools"]
@@ -130,10 +130,10 @@ __all__ += [
     "get_magnitude",
     "get_units",
     "has_time_axis",
+    "prepare",
     "quantify",
     "is_quantified",
     "strip_time",
     "to_datetime",
     "to_units",
-    "to_xarray",
 ]
diff --git a/src/finam/data/grid_tools.py b/src/finam/data/grid_tools.py
index 27d4cf48..a8495678 100644
--- a/src/finam/data/grid_tools.py
+++ b/src/finam/data/grid_tools.py
@@ -569,7 +569,6 @@ class Grid(GridBase):
     @abstractmethod
     def axes_names(self):
         """list of str: Axes names (xyz order)."""
-        # should be used for xarray later on
 
     @property
     def data_axes_names(self):
@@ -676,7 +675,6 @@ class StructuredGrid(Grid):
     @abstractmethod
     def axes_attributes(self):
         """list of dict: Axes attributes following the CF convention (xyz order)."""
-        # should be used for xarray later on
 
     @property
     @abstractmethod
diff --git a/src/finam/data/tools.py b/src/finam/data/tools.py
index bc0159d1..592cd308 100644
--- a/src/finam/data/tools.py
+++ b/src/finam/data/tools.py
@@ -21,9 +21,12 @@ _UNIT_CACHE = {}
 _UNIT_PAIRS_CACHE = {}
 
 
-def to_xarray(data, info, time_entries=1, force_copy=False):
+def prepare(data, info, time_entries=1, force_copy=False):
     """
-    Convert data to a xarray.DataArray.
+    Prepares data in FINAM's internal transmission format.
+
+    Checks tha shape of the data.
+    Checks or adds units and time dimension.
 
     Parameters
     ----------
@@ -41,7 +44,7 @@ def to_xarray(data, info, time_entries=1, force_copy=False):
     Returns
     -------
     pint.Quantity
-        The converted data.
+        The prepared data as a numpy array, wrapped into a :class:`pint.Quantity`.
 
     Raises
     ------
@@ -83,7 +86,7 @@ def _check_input_shape(data, info, time_entries):
         data_size = data.size / time_entries
         if data_size != info.grid.data_size:
             raise FinamDataError(
-                f"to_xarray: data size doesn't match grid size. "
+                f"quantify: data size doesn't match grid size. "
                 f"Got {data_size}, expected {info.grid.data_size}"
             )
         # check shape of non-flat arrays
@@ -93,7 +96,7 @@ def _check_input_shape(data, info, time_entries):
                     data = np.expand_dims(data, 0)
                 else:
                     raise FinamDataError(
-                        f"to_xarray: data shape doesn't match grid shape. "
+                        f"quantify: data shape doesn't match grid shape. "
                         f"Got {data.shape}, expected {info.grid.data_shape}"
                     )
         else:
@@ -117,13 +120,13 @@ def _check_input_shape_no_grid(data, info, time_entries):
             data = np.expand_dims(data, 0)
         else:
             raise FinamDataError(
-                f"to_xarray: number of dimensions in data doesn't match expected number. "
+                f"quantify: number of dimensions in data doesn't match expected number. "
                 f"Got {len(data.shape)}, expected {info.grid.dim}"
             )
     else:
         if data.shape[0] != time_entries:
             raise FinamDataError(
-                f"to_xarray: number of time entries in data doesn't match expected number. "
+                f"quantify: number of time entries in data doesn't match expected number. "
                 f"Got {data.shape[0]}, expected {time_entries}"
             )
     return data
@@ -191,19 +194,24 @@ def get_magnitude(xdata):
 
 
 def strip_time(xdata, grid):
-    """Returns a view of the xarray data with the time dimension squeezed if there is only a single entry
+    """Returns a view of the data with the time dimension squeezed if there is only a single entry
+
+    Parameters
+    ----------
+    xdata : arraylike
+        Data to strip time dimension from
+    grid : GridBase
+        The associated grid specification
 
     Returns
     -------
-    xarray.DataArray
+    arraylike
         Stripped data
-    grid : GridBase
-        The associated grid specification
 
     Raises
     ------
     FinamDataError
-        If the data is not an xarray, or has multiple time entries.
+        If the data has multiple time entries.
     """
     if has_time_axis(xdata, grid):
         if xdata.shape[0] > 1:
@@ -238,7 +246,7 @@ def get_dimensionality(xdata):
 
     Parameters
     ----------
-    xdata : xarray.DataArray
+    xdata : pint.Quantity
         The given data array.
 
     Returns
@@ -278,21 +286,21 @@ def full_like(xdata, value):
 
     Parameters
     ----------
-    xdata : xarray.DataArray
+    xdata : pint.Quantity
         The reference object in input.
     value : scalar
         Value to fill the new object with before returning it.
 
     Returns
     -------
-    xarray.DataArray
+    pint.Quantity
         New object with the same shape and type as other,
         with the data filled with fill_value.
         Coords will be copied from other.
     """
     d = np.full_like(xdata, value)
     if is_quantified(xdata):
-        return d * xdata.units
+        return UNITS.Quantity(d, xdata.units)
 
     return d
 
@@ -310,11 +318,11 @@ def full(value, info):
 
     Returns
     -------
-    numpy.ndarray
+    pint.Quantity
         The converted data.
     """
     shape = info.grid.data_shape if isinstance(info.grid, Grid) else tuple()
-    return to_xarray(np.full([1] + list(shape), value), info)
+    return prepare(np.full([1] + list(shape), value), info)
 
 
 def check(
@@ -384,7 +392,7 @@ def is_quantified(xdata):
 
 def quantify(xdata, units=None):
     """
-    Quantifies data from its metadata.
+    Quantifies data.
 
     Parameters
     ----------
@@ -399,7 +407,7 @@ def quantify(xdata, units=None):
     """
     if is_quantified(xdata):
         raise FinamDataError(f"Data is already quantified with units '{xdata.units}'")
-    return xdata * _get_pint_units(units or "")
+    return UNITS.Quantity(xdata, _get_pint_units(units or UNITS.dimensionless))
 
 
 def check_quantified(xdata, routine="check_quantified"):
diff --git a/src/finam/interfaces.py b/src/finam/interfaces.py
index d12be145..5f371a01 100644
--- a/src/finam/interfaces.py
+++ b/src/finam/interfaces.py
@@ -217,7 +217,7 @@ class IInput(ABC):
 
         Returns
         -------
-        :class:`xarray.DataArray`
+        :class:`pint.Quantity`
             Data set for the given simulation time.
         """
 
@@ -363,7 +363,7 @@ class IOutput(ABC):
 
         Returns
         -------
-        :class:`xarray.DataArray`
+        :class:`pint.Quantity`
             data-set for the requested time.
 
         Raises
diff --git a/src/finam/sdk/adapter.py b/src/finam/sdk/adapter.py
index 672031f7..14bcb03d 100644
--- a/src/finam/sdk/adapter.py
+++ b/src/finam/sdk/adapter.py
@@ -143,7 +143,7 @@ class Adapter(IAdapter, Input, Output, ABC):
 
         Returns
         -------
-        :class:`xarray.DataArray`
+        :class:`pint.Quantity`
             Transformed data-set for the requested time.
         """
         self.logger.debug("get data")
@@ -154,7 +154,7 @@ class Adapter(IAdapter, Input, Output, ABC):
         data = self._get_data(time, target)
 
         with ErrorLogger(self.logger):
-            return tools.to_xarray(data, self._output_info)
+            return tools.prepare(data, self._output_info)
 
     def _get_data(self, time, target):
         """Get the transformed data of this adapter.
@@ -170,7 +170,7 @@ class Adapter(IAdapter, Input, Output, ABC):
 
         Returns
         -------
-        :class:`xarray.DataArray`
+        :class:`pint.Quantity`
             Transformed data-set for the requested time.
         """
         raise NotImplementedError(
@@ -312,7 +312,7 @@ class TimeDelayAdapter(Adapter, ITimeDelayAdapter, ABC):
 
         Returns
         -------
-        :class:`xarray.DataArray`
+        :class:`pint.Quantity`
             Transformed data-set for the requested time.
         """
         self.logger.debug("get data")
@@ -326,7 +326,7 @@ class TimeDelayAdapter(Adapter, ITimeDelayAdapter, ABC):
         self._pulled(time)
 
         with ErrorLogger(self.logger):
-            return tools.to_xarray(data, self._output_info)
+            return tools.prepare(data, self._output_info)
 
     def _get_data(self, time, target):
         """Get the output's data-set for the given time.
diff --git a/src/finam/sdk/input.py b/src/finam/sdk/input.py
index fbff9adc..7841f5a7 100644
--- a/src/finam/sdk/input.py
+++ b/src/finam/sdk/input.py
@@ -105,7 +105,7 @@ class Input(IInput, Loggable):
 
         Returns
         -------
-        :class:`xarray.DataArray`
+        :class:`pint.Quantity`
             Data set for the given simulation time.
         """
         self.logger.debug("pull data")
diff --git a/src/finam/sdk/output.py b/src/finam/sdk/output.py
index f585885f..f2bbaf76 100644
--- a/src/finam/sdk/output.py
+++ b/src/finam/sdk/output.py
@@ -148,7 +148,7 @@ class Output(IOutput, Loggable):
             time = None
 
         with ErrorLogger(self.logger):
-            xdata = tools.to_xarray(data, self.info)
+            xdata = tools.prepare(data, self.info)
             if len(self.data) > 0:
                 d = self.data[-1][1]
                 if np.may_share_memory(d.data, xdata.data):
@@ -206,7 +206,7 @@ class Output(IOutput, Loggable):
 
         Returns
         -------
-        :class:`xarray.DataArray`
+        :class:`pint.Quantity`
             data-set for the requested time.
 
         Raises
@@ -419,7 +419,7 @@ class CallbackOutput(Output):
 
         Returns
         -------
-        :class:`xarray.DataArray`
+        :class:`pint.Quantity`
             Data-set for the requested time.
 
         Raises
@@ -443,7 +443,7 @@ class CallbackOutput(Output):
             raise FinamNoDataError(f"No data available in {self.name}")
 
         with ErrorLogger(self.logger):
-            xdata = tools.to_xarray(data, self.info)
+            xdata = tools.prepare(data, self.info)
             if self.last_data is not None and np.may_share_memory(
                 tools.get_magnitude(self.last_data), tools.get_magnitude(xdata)
             ):
diff --git a/tests/core/test_schedule.py b/tests/core/test_schedule.py
index 1c984949..e0a7e6b6 100644
--- a/tests/core/test_schedule.py
+++ b/tests/core/test_schedule.py
@@ -909,63 +909,7 @@ class TestComposition(unittest.TestCase):
         self.assertEqual([1, 8, 13], updates["A"])
         self.assertEqual([1, 4, 7, 10], updates["B"])
 
-    def test_starting_time_numpy(self):
-        start_1 = datetime(2000, 1, 2)
-        start_2 = datetime(2000, 1, 8)
-
-        updates = {"A": [], "B": []}
-
-        def lambda_generator(t):
-            return t.day
-
-        def lambda_component(inp, t):
-            return {"Out": np.asarray(1) * fm.UNITS("")}
-
-        def lambda_debugger(name, data, t):
-            updates[name].append(t.day)
-
-        module1 = CallbackGenerator(
-            callbacks={"Out": (lambda_generator, fm.Info(time=None, grid=fm.NoGrid()))},
-            start=start_2,
-            step=timedelta(days=5),
-        )
-        module2 = CallbackComponent(
-            inputs={
-                "In": fm.Info(time=None, grid=fm.NoGrid()),
-            },
-            outputs={
-                "Out": fm.Info(time=None, grid=fm.NoGrid()),
-            },
-            callback=lambda_component,
-            start=start_1,
-            step=timedelta(days=3),
-        )
-        module3 = DebugPushConsumer(
-            inputs={
-                "A": fm.Info(time=None, grid=None),
-                "B": fm.Info(time=None, grid=None),
-            },
-            callbacks={
-                "A": lambda_debugger,
-                "B": lambda_debugger,
-            },
-        )
-
-        composition = Composition([module1, module2, module3])
-        composition.initialize()
-
-        module1.outputs["Out"] >> Scale(1.0) >> module2.inputs["In"]
-        module1.outputs["Out"] >> Scale(1.0) >> module3.inputs["A"]
-        module2.outputs["Out"] >> Scale(1.0) >> module3.inputs["B"]
-
-        composition.connect(datetime(2000, 1, 1))
-
-        composition.run(end_time=datetime(2000, 1, 10))
-
-        self.assertEqual([1, 8, 13], updates["A"])
-        self.assertEqual([1, 2, 5, 8, 11], updates["B"])
-
-    def test_starting_time_xarray(self):
+    def test_starting_time(self):
         start_1 = datetime(2000, 1, 2)
         start_2 = datetime(2000, 1, 8)
 
diff --git a/tests/core/test_sdk.py b/tests/core/test_sdk.py
index eec532fb..9c0928bd 100644
--- a/tests/core/test_sdk.py
+++ b/tests/core/test_sdk.py
@@ -358,7 +358,7 @@ class TestOutput(unittest.TestCase):
         with self.assertRaises(FinamStaticDataError):
             out.push_data(0, None)
 
-    def test_data_copied_xarray(self):
+    def test_data_copied(self):
         t = datetime(2000, 1, 1)
         info = Info(time=t, grid=fm.UniformGrid((1, 1)))
 
@@ -377,7 +377,7 @@ class TestOutput(unittest.TestCase):
         with self.assertRaises(FinamDataError):
             out.push_data(in_data, t)
 
-    def test_data_copied_xarray_units(self):
+    def test_data_copied_units(self):
         t = datetime(2000, 1, 1)
         info1 = Info(time=t, grid=fm.UniformGrid((1, 1)), units="m")
         info2 = Info(time=t, grid=fm.UniformGrid((1, 1)), units="km")
@@ -400,48 +400,6 @@ class TestOutput(unittest.TestCase):
         in_data[0, 0, 0] = 1.0 * fm.UNITS("m")
         self.assertEqual(out_data[0, 0, 0], 0.0 * fm.UNITS("km"))
 
-    def test_data_copied_numpy(self):
-        t = datetime(2000, 1, 1)
-        info = Info(time=t, grid=fm.UniformGrid((1, 1)))
-
-        out = Output(name="Output")
-        in1 = Input(name="Input")
-
-        out >> in1
-
-        in1.ping()
-
-        out.push_info(info)
-        in1.exchange_info(info)
-
-        in_data = fm.data.full(0.0, info)
-        out.push_data(in_data, t)
-        with self.assertRaises(FinamDataError):
-            out.push_data(in_data, t)
-
-    def test_data_copied_numpy_units(self):
-        t = datetime(2000, 1, 1)
-        info1 = Info(time=t, grid=fm.UniformGrid((1, 1)), units="m")
-        info2 = Info(time=t, grid=fm.UniformGrid((1, 1)), units="km")
-
-        out = Output(name="Output")
-        in1 = Input(name="Input")
-
-        out >> in1
-
-        in1.ping()
-
-        out.push_info(info1)
-        in1.exchange_info(info2)
-
-        in_data = fm.data.full(0.0, info1)
-        out.push_data(in_data, t)
-        out_data = in1.pull_data(t, in1)
-
-        self.assertEqual(out_data[0, 0, 0], 0.0 * fm.UNITS("km"))
-        in_data[0, 0] = 1.0 * fm.UNITS("m")
-        self.assertEqual(out_data[0, 0, 0], 0.0 * fm.UNITS("km"))
-
 
 class TestInput(unittest.TestCase):
     def test_fail_set_source(self):
diff --git a/tests/data/test_tools.py b/tests/data/test_tools.py
index 7c221818..8a54f657 100644
--- a/tests/data/test_tools.py
+++ b/tests/data/test_tools.py
@@ -28,8 +28,8 @@ class TestDataTools(unittest.TestCase):
         tim0 = dt(year=2021, month=10, day=12)
 
         data = np.arange(6).reshape(3, 2)
-        dar0 = finam.data.to_xarray(data, info)
-        dar1 = finam.data.to_xarray(data, info)
+        dar0 = finam.data.prepare(data, info)
+        dar1 = finam.data.prepare(data, info)
 
         # assert stuff
         self.assertIsInstance(finam.data.get_magnitude(dar0), np.ndarray)
@@ -39,15 +39,15 @@ class TestDataTools(unittest.TestCase):
         )
 
         # should work
-        finam.data.to_xarray(dar0, info)
-        finam.data.to_xarray(dar1, info)
+        finam.data.prepare(dar0, info)
+        finam.data.prepare(dar1, info)
         finam.data.check(dar0, info)
         finam.data.check(dar1, info)
         finam.data.to_units(dar0, "km")
 
         # wrong shape
         with self.assertRaises(finam.errors.FinamDataError):
-            finam.data.to_xarray(1, info)
+            finam.data.prepare(1, info)
 
         # no DataArray
         with self.assertRaises(finam.errors.FinamDataError):
@@ -86,8 +86,8 @@ class TestDataTools(unittest.TestCase):
         gri1 = finam.UnstructuredPoints(points=[[0, 0], [0, 2], [2, 2]])
         info = finam.Info(time, gri0, units="s")
         data = np.arange(3)
-        dar0 = finam.data.to_xarray(data, info)
-        dar1 = finam.data.to_xarray(data, info.copy_with(grid=gri1))
+        dar0 = finam.data.prepare(data, info)
+        dar1 = finam.data.prepare(data, info.copy_with(grid=gri1))
 
         self.assertEqual((1, 3), dar0.shape)
         self.assertEqual((1, 3), dar1.shape)
@@ -96,12 +96,12 @@ class TestDataTools(unittest.TestCase):
         time = dt(2000, 1, 1)
         grid = finam.NoGrid()
 
-        xdata = finam.data.to_xarray(1.0, finam.Info(time, grid=grid))
+        xdata = finam.data.prepare(1.0, finam.Info(time, grid=grid))
         self.assertEqual(xdata.shape, (1,))
         stripped = finam.data.strip_time(xdata, grid)
         self.assertEqual(stripped.shape, ())
 
-        xdata = finam.data.to_xarray(
+        xdata = finam.data.prepare(
             [1.0, 2.0, 3.0],
             finam.Info(time, grid=finam.NoGrid(dim=1)),
         )
@@ -111,11 +111,11 @@ class TestDataTools(unittest.TestCase):
         stripped2 = finam.data.strip_time(xdata, finam.NoGrid(dim=1))
         self.assertEqual(stripped2.shape, stripped.shape)
 
-        arr1 = finam.data.to_xarray(
+        arr1 = finam.data.prepare(
             1.0,
             finam.Info(time, grid=finam.NoGrid()),
         )
-        arr2 = finam.data.to_xarray(
+        arr2 = finam.data.prepare(
             1.0,
             finam.Info(time, grid=finam.NoGrid()),
         )
@@ -123,73 +123,72 @@ class TestDataTools(unittest.TestCase):
         with self.assertRaises(finam.errors.FinamDataError):
             stripped_ = finam.data.strip_time(data, finam.NoGrid())
 
-    def test_to_xarray(self):
+    def test_prepare(self):
         time = dt(2000, 1, 1)
 
-        data = finam.data.to_xarray(1.0, finam.Info(time, grid=finam.NoGrid()))
+        data = finam.data.prepare(1.0, finam.Info(time, grid=finam.NoGrid()))
         self.assertEqual(np.asarray([1.0]) * finam.UNITS(""), data)
 
-        data = finam.data.to_xarray(
+        data = finam.data.prepare(
             [[1.0, 1.0], [1.0, 1.0]], finam.Info(time, grid=finam.UniformGrid((3, 3)))
         )
         self.assertEqual((1, 2, 2), data.shape)
 
         with self.assertRaises(finam.errors.FinamDataError):
-            finam.data.to_xarray(
+            finam.data.prepare(
                 np.asarray([1, 2]), finam.Info(time, grid=finam.NoGrid())
             )
 
         with self.assertRaises(finam.errors.FinamDataError):
-            finam.data.to_xarray(
+            finam.data.prepare(
                 1.0 * finam.UNITS.meter, finam.Info(time, grid=finam.NoGrid())
             )
 
         with self.assertRaises(finam.errors.FinamDataError):
-            finam.data.to_xarray(
+            finam.data.prepare(
                 1.0 * finam.UNITS.meter,
                 finam.Info(time, grid=finam.NoGrid(), units="m^3"),
             )
 
-    def test_to_xarray_copy(self):
+    def test_prepare_copy(self):
         time = dt(2000, 1, 1)
         info_1 = finam.Info(time, grid=finam.NoGrid(1), units="m")
         info_2 = finam.Info(time, grid=finam.NoGrid(1), units="km")
 
         # using numpy arrays without units
         data = np.asarray([1, 2])
-        xdata = finam.data.to_xarray(data, info_1, force_copy=True)
+        xdata = finam.data.prepare(data, info_1, force_copy=True)
         data[0] = 0
         self.assertNotEqual(xdata[0, 0], data[0])
 
         # using numpy arrays with units
         data = np.asarray([1, 2]) * finam.UNITS("m")
-        xdata = finam.data.to_xarray(data, info_1)
+        xdata = finam.data.prepare(data, info_1)
         data[0] = 0 * finam.UNITS("m")
         self.assertEqual(xdata[0, 0], data[0])
 
         data = np.asarray([1, 2]) * finam.UNITS("m")
-        xdata = finam.data.to_xarray(data, info_1, force_copy=True)
+        xdata = finam.data.prepare(data, info_1, force_copy=True)
         data[0] = 0 * finam.UNITS("m")
         self.assertNotEqual(xdata[0, 0], data[0])
 
         data = np.asarray([1, 2]) * finam.UNITS("m")
-        xdata = finam.data.to_xarray(data, info_2)
+        xdata = finam.data.prepare(data, info_2)
         data[0] = 0 * finam.UNITS("m")
         self.assertNotEqual(finam.data.get_magnitude(xdata[0, 0]), 0.0)
 
-        # using xarray arrays
-        xdata = finam.data.to_xarray(np.asarray([1, 2]), info_1)
-        xdata2 = finam.data.to_xarray(xdata, info_1)
+        xdata = finam.data.prepare(np.asarray([1, 2]), info_1)
+        xdata2 = finam.data.prepare(xdata, info_1)
         xdata[0, 0] = 0 * finam.UNITS("m")
         self.assertEqual(xdata2[0, 0], xdata[0, 0])
 
-        xdata = finam.data.to_xarray(np.asarray([1, 2]), info_1)
-        xdata2 = finam.data.to_xarray(xdata, info_1, force_copy=True)
+        xdata = finam.data.prepare(np.asarray([1, 2]), info_1)
+        xdata2 = finam.data.prepare(xdata, info_1, force_copy=True)
         xdata[0, 0] = 0 * finam.UNITS("m")
         self.assertNotEqual(xdata2[0, 0], xdata[0, 0])
 
-        xdata = finam.data.to_xarray(np.asarray([1, 2]), info_1)
-        xdata2 = finam.data.to_xarray(xdata, info_2)
+        xdata = finam.data.prepare(np.asarray([1, 2]), info_1)
+        xdata2 = finam.data.prepare(xdata, info_2)
         xdata[0, 0] = 0 * finam.UNITS("m")
         self.assertNotEqual(finam.data.get_magnitude(xdata2[0, 0]), 0.0)
 
@@ -242,7 +241,7 @@ class TestDataTools(unittest.TestCase):
 
     def test_check_shape(self):
         time = dt(2000, 1, 1)
-        xdata = finam.data.to_xarray(
+        xdata = finam.data.prepare(
             1.0,
             finam.Info(time, grid=finam.NoGrid()),
         )
-- 
GitLab