From bae8dec3f0597f2d38f87332e4af9728be8772ca Mon Sep 17 00:00:00 2001 From: vhirtham Date: Fri, 30 Apr 2021 09:52:56 +0200 Subject: [PATCH 01/14] Update docstring --- weldx/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/weldx/core.py b/weldx/core.py index 0c6849e4e..84e556dc5 100644 --- a/weldx/core.py +++ b/weldx/core.py @@ -449,7 +449,7 @@ def time(self) -> Union[None, pd.TimedeltaIndex]: def interp_time( self, time: Union[pd.TimedeltaIndex, pint.Quantity], time_unit: str = "s" - ) -> xr.DataArray: + ) -> "TimeSeries": """Interpolate the TimeSeries in time. If the internal data consists of discrete values, an interpolation with the @@ -470,7 +470,7 @@ def interp_time( Returns ------- - xarray.DataArray: + TimeSeries : A data array containing the interpolated data. """ From 6248385f757841518db2cc171dee939aab3e9a50 Mon Sep 17 00:00:00 2001 From: vhirtham Date: Fri, 7 May 2021 11:07:58 +0200 Subject: [PATCH 02/14] Change interface of interp_time --- weldx/core.py | 110 ++++++++++++++++++++++++--------------- weldx/tests/conftest.py | 1 + weldx/tests/test_core.py | 8 +-- 3 files changed, 75 insertions(+), 44 deletions(-) diff --git a/weldx/core.py b/weldx/core.py index 84e556dc5..dcce8d166 100644 --- a/weldx/core.py +++ b/weldx/core.py @@ -385,6 +385,68 @@ def __repr__(self): ) return representation + f"Units:\n\t{self.units}\n" + def _interp_time_discrete( + self, time: Union[pd.TimedeltaIndex, pint.Quantity] + ) -> xr.DataArray: + """Interpolate the time series if its data is composed of discrete values. + + See `interp_time` for interface description. + + """ + if isinstance(self._data, xr.DataArray): + if isinstance(time, pint.Quantity): + time = ut.to_pandas_time_index(time) + if not isinstance(time, pd.TimedeltaIndex): + raise ValueError( + '"time" must be a time quantity or a "pandas.TimedeltaIndex".' + ) + # constant values are also treated by this branch + if self._data.attrs["interpolation"] == "linear" or self.shape[0] == 1: + return ut.xr_interp_like( + self._data, + {"time": time}, + assume_sorted=False, + broadcast_missing=False, + ) + + dax = self._data.reindex({"time": time}, method="ffill") + return dax.fillna(self._data[0]) + + def _interp_time_expression( + self, time: Union[pd.TimedeltaIndex, pint.Quantity], time_unit: str + ) -> xr.DataArray: + """Interpolate the time series if its data is a mathematical expression. + + See `interp_time` for interface description. + + """ + # Transform time to both formats + if isinstance(time, pint.Quantity) and time.check(UREG.get_dimensionality("s")): + time_q = time + time_pd = ut.to_pandas_time_index(time) + elif isinstance(time, pd.TimedeltaIndex): + time_q = ut.pandas_time_delta_to_quantity(time, time_unit) + time_pd = time + else: + raise ValueError( + '"time" must be a time quantity or a "pandas.TimedeltaIndex".' + ) + + if len(self.shape) > 1 and np.iterable(time_q): + while len(time_q.shape) < len(self.shape): + time_q = time_q[:, np.newaxis] + + # evaluate expression + data = self._data.evaluate(**{self._time_var_name: time_q}) + data = data.astype(float).to_reduced_units() # float conversion before reduce! + + # create data array + if not np.iterable(data): # make sure quantity is not scalar value + data = np.expand_dims(data, 0) + + dax = xr.DataArray(data=data) # don't know exact dimensions so far + return dax.rename({"dim_0": "time"}).assign_coords({"time": time_pd}) + @property def data(self) -> Union[pint.Quantity, MathematicalExpression]: """Return the data of the TimeSeries. @@ -475,50 +537,16 @@ def interp_time( """ if isinstance(self._data, xr.DataArray): - if isinstance(time, pint.Quantity): - time = ut.to_pandas_time_index(time) - if not isinstance(time, pd.TimedeltaIndex): - raise ValueError( - '"time" must be a time quantity or a "pandas.TimedeltaIndex".' - ) - # constant values are also treated by this branch - if self._data.attrs["interpolation"] == "linear" or self.shape[0] == 1: - return ut.xr_interp_like( - self._data, - {"time": time}, - assume_sorted=False, - broadcast_missing=False, - ) - - dax = self._data.reindex({"time": time}, method="ffill") - return dax.fillna(self._data[0]) - - # Transform time to both formats - if isinstance(time, pint.Quantity) and time.check(UREG.get_dimensionality("s")): - time_q = time - time_pd = ut.to_pandas_time_index(time) - elif isinstance(time, pd.TimedeltaIndex): - time_q = ut.pandas_time_delta_to_quantity(time, time_unit) - time_pd = time + dax = self._interp_time_discrete(time) else: - raise ValueError( - '"time" must be a time quantity or a "pandas.TimedeltaIndex".' - ) + dax = self._interp_time_expression(time, time_unit) - if len(self.shape) > 1 and np.iterable(time_q): - while len(time_q.shape) < len(self.shape): - time_q = time_q[:, np.newaxis] - - # evaluate expression - data = self._data.evaluate(**{self._time_var_name: time_q}) - data = data.astype(float).to_reduced_units() # float conversion before reduce! + interpolation = self.interpolation + if interpolation is None: + interpolation = "linear" - # create data array - if not np.iterable(data): # make sure quantity is not scalar value - data = np.expand_dims(data, 0) - - dax = xr.DataArray(data=data) # don't know exact dimensions so far - return dax.rename({"dim_0": "time"}).assign_coords({"time": time_pd}) + ts = TimeSeries(data=dax.data, time=time, interpolation=interpolation) + return ts @property def shape(self) -> Tuple: diff --git a/weldx/tests/conftest.py b/weldx/tests/conftest.py index f06651988..b4c5dce62 100644 --- a/weldx/tests/conftest.py +++ b/weldx/tests/conftest.py @@ -1,5 +1,6 @@ """pytest configuration.""" import pytest + from weldx.asdf.cli.welding_schema import single_pass_weld_example diff --git a/weldx/tests/test_core.py b/weldx/tests/test_core.py index 72376a2b7..1cf7cddbb 100644 --- a/weldx/tests/test_core.py +++ b/weldx/tests/test_core.py @@ -409,12 +409,14 @@ def test_interp_time(ts, time, magnitude_exp, unit_exp): result = ts.interp_time(time) assert np.all(np.isclose(result.data.magnitude, magnitude_exp)) - assert Q_(1, str(result.data.units)) == Q_(1, unit_exp) + assert Q_(1, str(result.units)) == Q_(1, unit_exp) + + print(result.time) if isinstance(time, pint.Quantity): - assert np.all(result.time == ut.to_pandas_time_index(time)) + assert np.all(result.data_array.time == ut.to_pandas_time_index(time)) else: - assert np.all(result.time == time) + assert np.all(result.data_array.time == time) # test_interp_time_exceptions ------------------------------------------------------ From cabf13796844cee3d67590647523ccd107fdf697 Mon Sep 17 00:00:00 2001 From: vhirtham Date: Fri, 7 May 2021 11:34:39 +0200 Subject: [PATCH 03/14] Emit warning when interpolating interpolated data --- weldx/core.py | 9 +++++++++ weldx/tests/test_core.py | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/weldx/core.py b/weldx/core.py index dcce8d166..4022ab5db 100644 --- a/weldx/core.py +++ b/weldx/core.py @@ -2,6 +2,7 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Union +from warnings import warn import numpy as np import pandas as pd @@ -276,6 +277,7 @@ def __init__( self._time_var_name = None self._shape = None self._units = None + self._interp_counter = 0 if isinstance(data, pint.Quantity): if not np.iterable(data): # expand dim for scalar input @@ -536,6 +538,12 @@ def interp_time( A data array containing the interpolated data. """ + if self._interp_counter > 0: + warn( + "The data of the time series has already been interpolated " + f"{self._interp_counter} time(s)." + ) + if isinstance(self._data, xr.DataArray): dax = self._interp_time_discrete(time) else: @@ -546,6 +554,7 @@ def interp_time( interpolation = "linear" ts = TimeSeries(data=dax.data, time=time, interpolation=interpolation) + ts._interp_counter = self._interp_counter + 1 return ts @property diff --git a/weldx/tests/test_core.py b/weldx/tests/test_core.py index 1cf7cddbb..fe43255cf 100644 --- a/weldx/tests/test_core.py +++ b/weldx/tests/test_core.py @@ -418,6 +418,19 @@ def test_interp_time(ts, time, magnitude_exp, unit_exp): else: assert np.all(result.data_array.time == time) + # test_interp_time_warning --------------------------------------------------------- + + @staticmethod + def test_interp_time_warning(): + """Test if a warning is emitted when interpolating already interpolated data.""" + ts = TimeSeries(data=Q_([1, 2, 3], "m"), time=Q_([0, 1, 2], "s")) + with pytest.warns(None) as recorded_warnings: + ts_interp = ts.interp_time(Q_([0.25, 0.5, 0.75, 1], "s")) + assert len(recorded_warnings) == 0 + + with pytest.warns(UserWarning): + ts_interp.interp_time(Q_([0.4, 0.6], "s")) + # test_interp_time_exceptions ------------------------------------------------------ @staticmethod From 3c6a014402fe299bb995dd26f3c3dab6777ff774 Mon Sep 17 00:00:00 2001 From: vhirtham Date: Fri, 7 May 2021 11:49:59 +0200 Subject: [PATCH 04/14] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b58056edc..1ff72086c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ - `get_yaml_header` received a new option parse, which optionally returns the parsed YAML header as `asdf.tagged.TaggedDict`. [[#338]](https://github.com/BAMWelDX/weldx/pull/338) - refactor `asdf_json_repr` into `view_tree` [[#339]](https://github.com/BAMWelDX/weldx/pull/339) +- `TimeSeries.interp_time` [[#353]](https://github.com/BAMWelDX/weldx/pull/353) + - now returns a new `TimeSeries` instead of a `xarray.DataArray` + - if the data has already been interpolated before, a warning is emitted ### ASDF From d14f3d857a24be88ca7c546248e6b4d3108edaec Mon Sep 17 00:00:00 2001 From: vhirtham Date: Mon, 21 Jun 2021 12:14:02 +0200 Subject: [PATCH 05/14] Update weldx/core.py Co-authored-by: Cagtay Fabry <43667554+CagtayFabry@users.noreply.github.com> --- weldx/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weldx/core.py b/weldx/core.py index 4022ab5db..eedd8900f 100644 --- a/weldx/core.py +++ b/weldx/core.py @@ -535,7 +535,7 @@ def interp_time( Returns ------- TimeSeries : - A data array containing the interpolated data. + A new `TimeSeries` object containing the interpolated data. """ if self._interp_counter > 0: From 430ab61642797aee257041518bb37bad6c0a0763 Mon Sep 17 00:00:00 2001 From: vhirtham Date: Wed, 23 Jun 2021 12:51:13 +0200 Subject: [PATCH 06/14] Enhance discrete interpolation --- weldx/core.py | 53 ++++++++++++++++++++-------------------- weldx/tests/test_core.py | 16 ++++++------ 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/weldx/core.py b/weldx/core.py index eedd8900f..9dcead3bd 100644 --- a/weldx/core.py +++ b/weldx/core.py @@ -254,7 +254,7 @@ def __init__( self, data: Union[pint.Quantity, MathematicalExpression], time: Union[None, pd.TimedeltaIndex, pint.Quantity] = None, - interpolation: str = "linear", + interpolation: str = None, ): """Construct a TimSeries. @@ -280,11 +280,19 @@ def __init__( self._interp_counter = 0 if isinstance(data, pint.Quantity): - if not np.iterable(data): # expand dim for scalar input + # set default interpolation + if interpolation is None: + interpolation = "step" + + # expand dim for scalar input + if not np.iterable(data): data = np.expand_dims(data, 0) - if time is None: # constant value case + + # constant value case + if time is None: time = pd.TimedeltaIndex([0]) - interpolation = None + interpolation = "step" + # check intreplolation is valid for non constant case elif interpolation not in self._valid_interpolations: raise ValueError( "A valid interpolation method must be specified if discrete " @@ -395,24 +403,21 @@ def _interp_time_discrete( See `interp_time` for interface description. """ - if isinstance(self._data, xr.DataArray): - if isinstance(time, pint.Quantity): - time = ut.to_pandas_time_index(time) - if not isinstance(time, pd.TimedeltaIndex): - raise ValueError( - '"time" must be a time quantity or a "pandas.TimedeltaIndex".' - ) - # constant values are also treated by this branch - if self._data.attrs["interpolation"] == "linear" or self.shape[0] == 1: - return ut.xr_interp_like( - self._data, - {"time": time}, - assume_sorted=False, - broadcast_missing=False, - ) - dax = self._data.reindex({"time": time}, method="ffill") - return dax.fillna(self._data[0]) + if isinstance(time, pint.Quantity): + time = ut.to_pandas_time_index(time) + if not isinstance(time, pd.TimedeltaIndex): + raise ValueError( + '"time" must be a time quantity or a "pandas.TimedeltaIndex".' + ) + + return ut.xr_interp_like( + self._data, + {"time": time}, + method=self.interpolation, + assume_sorted=False, + broadcast_missing=False, + ) def _interp_time_expression( self, time: Union[pd.TimedeltaIndex, pint.Quantity], time_unit: str @@ -549,11 +554,7 @@ def interp_time( else: dax = self._interp_time_expression(time, time_unit) - interpolation = self.interpolation - if interpolation is None: - interpolation = "linear" - - ts = TimeSeries(data=dax.data, time=time, interpolation=interpolation) + ts = TimeSeries(data=dax.data, time=time, interpolation=self.interpolation) ts._interp_counter = self._interp_counter + 1 return ts diff --git a/weldx/tests/test_core.py b/weldx/tests/test_core.py index fe43255cf..29a0a8bcb 100644 --- a/weldx/tests/test_core.py +++ b/weldx/tests/test_core.py @@ -242,10 +242,13 @@ class TestTimeSeries: def test_construction_discrete(data, time, interpolation, shape_exp): """Test the construction of the TimeSeries class.""" # set expected values - if isinstance(time, pint.Quantity): - time_exp = pd.TimedeltaIndex(time.magnitude, unit="s") - else: - time_exp = time + time_exp = time + if isinstance(time_exp, pint.Quantity): + time_exp = pd.TimedeltaIndex(time_exp.m, unit="s") + + exp_interpolation = interpolation + if len(data.m.shape) == 0 and interpolation is None: + exp_interpolation = "step" # create instance ts = TimeSeries(data=data, time=time, interpolation=interpolation) @@ -253,12 +256,12 @@ def test_construction_discrete(data, time, interpolation, shape_exp): # check assert np.all(ts.data == data) assert np.all(ts.time == time_exp) - assert ts.interpolation == interpolation + assert ts.interpolation == exp_interpolation assert ts.shape == shape_exp assert data.check(UREG.get_dimensionality(ts.units)) assert np.all(ts.data_array.data == data) - assert ts.data_array.attrs["interpolation"] == interpolation + assert ts.data_array.attrs["interpolation"] == exp_interpolation if time_exp is None: assert "time" not in ts.data_array else: @@ -302,7 +305,6 @@ def test_construction_expression(data, shape_exp, unit_exp): "data, time, interpolation, exception_type, test_name", [ (values_def, time_def, "int", ValueError, "# unknown interpolation"), - (values_def, time_def, None, ValueError, "# wrong interp. parameter type"), (values_def, time_def.magnitude, "step", ValueError, "# invalid time type"), (me_too_many_vars, None, None, Exception, "# too many free variables"), (me_param_units, None, None, Exception, "# incompatible parameter units"), From 1f9fa684971e7a8616f15590f1ec2c48a36ad3a4 Mon Sep 17 00:00:00 2001 From: vhirtham Date: Wed, 23 Jun 2021 14:36:25 +0200 Subject: [PATCH 07/14] Add interpolation setter --- weldx/core.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/weldx/core.py b/weldx/core.py index 9dcead3bd..574656469 100644 --- a/weldx/core.py +++ b/weldx/core.py @@ -291,13 +291,7 @@ def __init__( # constant value case if time is None: time = pd.TimedeltaIndex([0]) - interpolation = "step" - # check intreplolation is valid for non constant case - elif interpolation not in self._valid_interpolations: - raise ValueError( - "A valid interpolation method must be specified if discrete " - f'values are used. "{interpolation}" is not supported' - ) + if isinstance(time, pint.Quantity): time = ut.to_pandas_time_index(time) if not isinstance(time, pd.TimedeltaIndex): @@ -305,11 +299,9 @@ def __init__( '"time" must be a time quantity or a "pandas.TimedeltaIndex".' ) - dax = xr.DataArray( - data=data, - attrs={"interpolation": interpolation}, - ) + dax = xr.DataArray(data=data) self._data = dax.rename({"dim_0": "time"}).assign_coords({"time": time}) + self.interpolation = interpolation elif isinstance(data, MathematicalExpression): @@ -502,6 +494,18 @@ def interpolation(self) -> Union[str, None]: return self._data.attrs["interpolation"] return None + @interpolation.setter + def interpolation(self, interpolation): + if isinstance(self._data, xr.DataArray): + if interpolation not in self._valid_interpolations: + raise ValueError( + "A valid interpolation method must be specified if discrete " + f'values are used. "{interpolation}" is not supported' + ) + if self.time is None and interpolation != "step": + interpolation = "step" + self.data_array.attrs["interpolation"] = interpolation + @property def time(self) -> Union[None, pd.TimedeltaIndex]: """Return the data's timestamps. From 20738227c0cb7b5a9267c6555a693fe024fd83de Mon Sep 17 00:00:00 2001 From: vhirtham Date: Wed, 23 Jun 2021 14:57:22 +0200 Subject: [PATCH 08/14] Modify test --- weldx/tests/test_core.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/weldx/tests/test_core.py b/weldx/tests/test_core.py index 29a0a8bcb..2c4f7be7f 100644 --- a/weldx/tests/test_core.py +++ b/weldx/tests/test_core.py @@ -413,12 +413,13 @@ def test_interp_time(ts, time, magnitude_exp, unit_exp): assert np.all(np.isclose(result.data.magnitude, magnitude_exp)) assert Q_(1, str(result.units)) == Q_(1, unit_exp) - print(result.time) + exp_time = time + if isinstance(exp_time, pint.Quantity): + exp_time = ut.to_pandas_time_index(time) + if len(exp_time) == 1: + exp_time = None - if isinstance(time, pint.Quantity): - assert np.all(result.data_array.time == ut.to_pandas_time_index(time)) - else: - assert np.all(result.data_array.time == time) + assert np.all(result.time == exp_time) # test_interp_time_warning --------------------------------------------------------- From 6ec94f184a8785c3d120b230d00e0299f33f1dbb Mon Sep 17 00:00:00 2001 From: vhirtham Date: Wed, 23 Jun 2021 15:20:23 +0200 Subject: [PATCH 09/14] Clean up __init__ --- weldx/core.py | 133 +++++++++++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 60 deletions(-) diff --git a/weldx/core.py b/weldx/core.py index 574656469..47d4a9579 100644 --- a/weldx/core.py +++ b/weldx/core.py @@ -280,66 +280,9 @@ def __init__( self._interp_counter = 0 if isinstance(data, pint.Quantity): - # set default interpolation - if interpolation is None: - interpolation = "step" - - # expand dim for scalar input - if not np.iterable(data): - data = np.expand_dims(data, 0) - - # constant value case - if time is None: - time = pd.TimedeltaIndex([0]) - - if isinstance(time, pint.Quantity): - time = ut.to_pandas_time_index(time) - if not isinstance(time, pd.TimedeltaIndex): - raise ValueError( - '"time" must be a time quantity or a "pandas.TimedeltaIndex".' - ) - - dax = xr.DataArray(data=data) - self._data = dax.rename({"dim_0": "time"}).assign_coords({"time": time}) - self.interpolation = interpolation - + self._initialize_discrete(data, time, interpolation) elif isinstance(data, MathematicalExpression): - - if data.num_variables != 1: - raise Exception( - "The mathematical expression must have exactly 1 free " - "variable that represents time." - ) - time_var_name = data.get_variable_names()[0] - try: - eval_data = data.evaluate(**{time_var_name: Q_(1, "second")}) - self._units = eval_data.units - if np.iterable(eval_data): - self._shape = eval_data.shape - else: - self._shape = (1,) - except pint.errors.DimensionalityError: - raise Exception( - "Expression can not be evaluated with " - '"weldx.Quantity(1, "seconds")"' - ". Ensure that every parameter posses the correct unit." - ) - - self._data = data - self._time_var_name = time_var_name - - try: - self.interp_time(Q_([1, 2], "second")) - self.interp_time(Q_([1, 2, 3], "second")) - except Exception as e: - raise Exception( - "The expression can not be evaluated with arrays of time deltas. " - "Ensure that all parameters that are multiplied with the time " - "variable have an outer dimension of size 1. This dimension is " - "broadcasted during multiplication. The original error message was:" - f' "{str(e)}"' - ) - + self._init_expression(data) else: raise TypeError(f'The data type "{type(data)}" is not supported.') @@ -387,6 +330,77 @@ def __repr__(self): ) return representation + f"Units:\n\t{self.units}\n" + def _initialize_discrete( + self, + data: pint.Quantity, + time: Union[None, pd.TimedeltaIndex, pint.Quantity], + interpolation: str, + ): + """Initialize the internal data with discrete values.""" + # set default interpolation + if interpolation is None: + interpolation = "step" + + # expand dim for scalar input + if not np.iterable(data): + data = np.expand_dims(data, 0) + + # constant value case + if time is None: + time = pd.TimedeltaIndex([0]) + + if isinstance(time, pint.Quantity): + time = ut.to_pandas_time_index(time) + if not isinstance(time, pd.TimedeltaIndex): + raise ValueError( + '"time" must be a time quantity or a "pandas.TimedeltaIndex".' + ) + + dax = xr.DataArray(data=data) + self._data = dax.rename({"dim_0": "time"}).assign_coords({"time": time}) + self.interpolation = interpolation + + def _init_expression(self, data): + """Initialize the internal data with a mathematical expression.""" + if data.num_variables != 1: + raise Exception( + "The mathematical expression must have exactly 1 free " + "variable that represents time." + ) + + # check that the expression can be evaluated with a time quantity + time_var_name = data.get_variable_names()[0] + try: + eval_data = data.evaluate(**{time_var_name: Q_(1, "second")}) + self._units = eval_data.units + if np.iterable(eval_data): + self._shape = eval_data.shape + else: + self._shape = (1,) + except pint.errors.DimensionalityError: + raise Exception( + "Expression can not be evaluated with " + '"weldx.Quantity(1, "seconds")"' + ". Ensure that every parameter posses the correct unit." + ) + + # assign internal variables + self._data = data + self._time_var_name = time_var_name + + # check that all parameters of the expression support time arrays + try: + self.interp_time(Q_([1, 2], "second")) + self.interp_time(Q_([1, 2, 3], "second")) + except Exception as e: + raise Exception( + "The expression can not be evaluated with arrays of time deltas. " + "Ensure that all parameters that are multiplied with the time " + "variable have an outer dimension of size 1. This dimension is " + "broadcasted during multiplication. The original error message was:" + f' "{str(e)}"' + ) + def _interp_time_discrete( self, time: Union[pd.TimedeltaIndex, pint.Quantity] ) -> xr.DataArray: @@ -395,7 +409,6 @@ def _interp_time_discrete( See `interp_time` for interface description. """ - if isinstance(time, pint.Quantity): time = ut.to_pandas_time_index(time) if not isinstance(time, pd.TimedeltaIndex): From 924fe4c81257710fd36e8f701696cb52c89444e9 Mon Sep 17 00:00:00 2001 From: vhirtham Date: Wed, 23 Jun 2021 15:38:53 +0200 Subject: [PATCH 10/14] Fix a bug related to new return type of interp_time --- weldx/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weldx/util.py b/weldx/util.py index 31aa079b7..53d7a462e 100644 --- a/weldx/util.py +++ b/weldx/util.py @@ -281,7 +281,7 @@ def lcs_coords_from_ts( A DataArray with correctly labeled dimensions to be used for LCS creation. """ - ts_data = ts.interp_time(time=time) + ts_data = ts.interp_time(time=time).data_array # assign vector coordinates and convert to mm ts_data = ts_data.rename({"dim_1": "c"}).assign_coords({"c": ["x", "y", "z"]}) ts_data.data = ts_data.data.to("mm").magnitude From 44de63418b65ef7d7b47fdc1e0f6207f64c0ff45 Mon Sep 17 00:00:00 2001 From: vhirtham Date: Wed, 23 Jun 2021 15:55:50 +0200 Subject: [PATCH 11/14] Fix tutorials --- tutorials/timeseries_01.ipynb | 3 ++- tutorials/welding_example_02_weaving.ipynb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tutorials/timeseries_01.ipynb b/tutorials/timeseries_01.ipynb index 9416471b4..1d6b284e4 100644 --- a/tutorials/timeseries_01.ipynb +++ b/tutorials/timeseries_01.ipynb @@ -39,6 +39,7 @@ "outputs": [], "source": [ "def plot_ts(ts):\n", + " ts = ts.data_array\n", " fig, ax = plt.subplots(1,1)\n", " x = ts.time.data.astype('timedelta64[ms]').astype(int)/1000.0\n", " plt.plot(x,ts.data.magnitude,'-o')\n", @@ -397,7 +398,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.2" + "version": "3.9.4" } }, "nbformat": 4, diff --git a/tutorials/welding_example_02_weaving.ipynb b/tutorials/welding_example_02_weaving.ipynb index f16ac415c..b6574f53e 100644 --- a/tutorials/welding_example_02_weaving.ipynb +++ b/tutorials/welding_example_02_weaving.ipynb @@ -629,7 +629,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.2" + "version": "3.9.4" } }, "nbformat": 4, From 7f70a6153d002212b2f9e5e513a36133f784161d Mon Sep 17 00:00:00 2001 From: vhirtham Date: Wed, 23 Jun 2021 16:07:28 +0200 Subject: [PATCH 12/14] Update valid interpolations --- weldx/core.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/weldx/core.py b/weldx/core.py index 47d4a9579..60aa61505 100644 --- a/weldx/core.py +++ b/weldx/core.py @@ -248,7 +248,15 @@ def evaluate(self, **kwargs) -> Any: class TimeSeries: """Describes the behaviour of a quantity in time.""" - _valid_interpolations = ["step", "linear"] + _valid_interpolations = [ + "step", + "linear", + "nearest", + "zero", + "slinear", + "quadratic", + "cubic", + ] def __init__( self, From e9355c9e1e5406db4c9a7c481ff4ac8ba3a11999 Mon Sep 17 00:00:00 2001 From: vhirtham Date: Fri, 25 Jun 2021 08:31:08 +0200 Subject: [PATCH 13/14] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3166bdbca..120d33f9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ fields [[#378]](https://github.com/BAMWelDX/weldx/pull/378) - adds a `dataclass_serialization_class` utility function that automatically generates the asdf serialization class for python dataclasses. [[#380]](https://github.com/BAMWelDX/weldx/pull/380) +- Added method to set the interpolation method to the `TimeSeries` [[#353]](https://github.com/BAMWelDX/weldx/pull/353) ### changes From 131d4141100cdf878e706d6d936ad3c60a0022c0 Mon Sep 17 00:00:00 2001 From: vhirtham Date: Fri, 25 Jun 2021 09:28:28 +0200 Subject: [PATCH 14/14] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 120d33f9c..ea5da232c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - `TimeSeries.interp_time` [[#353]](https://github.com/BAMWelDX/weldx/pull/353) - now returns a new `TimeSeries` instead of a `xarray.DataArray` - if the data has already been interpolated before, a warning is emitted + - `TimeSeries` supports now all interpolation methods supported by xarray - The `MeasurementChain` is now internally based on a `networkx.DiGraph`. New functions are also added to the class to simplify its usage. [[#326]](https://github.com/BAMWelDX/weldx/pull/326) The following additional changes were applied during the update of the `MeasurementChain`: