Skip to content

Commit

Permalink
Check time coords (#635)
Browse files Browse the repository at this point in the history
* check for time in coords instead of dims

* check time dependency on dims

* allow Time conversion from singular times, update LCS interpolation to xarray

* adjust cs_manager

* revert to old behavior

* make warning more specific

* update test

* transpose SpatialData on init, fix is_time_dependent

* update coordinate interpolation

* update CHANGELOG.rst
  • Loading branch information
CagtayFabry committed Nov 10, 2021
1 parent 299d199 commit abe5cb3
Show file tree
Hide file tree
Showing 9 changed files with 30 additions and 13 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ changes
from the dictionary interface. To access these, there are separate
properties `[#625] <https://github.com/BAMWeldX/weldx/pull/625>`__.

- Allow handling of ``time`` values as singular coordinates without
dimensions in some classes `[#635]
<https://github.com/BAMWeldX/weldx/pull/635>`__.

fixes
=====

- Fix wrong dimension order being passed through in `SpatialData`
`[#635] <https://github.com/BAMWeldX/weldx/pull/635>`__.

documentation
=============

Expand Down
3 changes: 3 additions & 0 deletions weldx/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2538,6 +2538,9 @@ def __post_init__(self, time):
add_dims=["n"],
)

# make sure we have correct dimension order
self.coordinates = self.coordinates.transpose(..., "n", "c")

if self.triangles is not None:
if not isinstance(self.triangles, np.ndarray):
self.triangles = np.array(self.triangles, dtype="uint")
Expand Down
2 changes: 1 addition & 1 deletion weldx/tags/core/transformations/local_coordinate_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def to_yaml_tree(self, obj: LocalCoordinateSystem, tag: str, ctx) -> dict:
# ctx.set_array_storage(coordinates.data, "inline")
tree["coordinates"] = coordinates

if "time" in obj.dataset.dims:
if "time" in obj.dataset.coords:
tree["time"] = obj.time.as_timedelta_index()

if obj.reference_time is not None:
Expand Down
1 change: 1 addition & 0 deletions weldx/tests/transformations/test_cs_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2614,6 +2614,7 @@ def test_issue_289_interp_outside_time_range(
exp_orient = WXRotation.from_euler("x", exp_angle, degrees=True).as_matrix()
exp_coords = [0, 0, 0] if time_dep_coords and all_less else [1, 1, 1]

assert cs_br.is_time_dependent is False
assert cs_br.time is None
assert cs_br.coordinates.values.shape == (3,)
assert cs_br.orientation.values.shape == (3, 3)
Expand Down
4 changes: 3 additions & 1 deletion weldx/tests/transformations/test_local_cs.py
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ def test_issue_289_interp_outside_time_range(
exp_orient = WXRotation.from_euler("x", exp_angle, degrees=True).as_matrix()
exp_coords = [0, 0, 0] if time_dep_coords and all_less else [1, 1, 1]

assert lcs_interp.is_time_dependent is False
assert lcs_interp.time is None
assert lcs_interp.coordinates.values.shape == (3,)
assert lcs_interp.orientation.values.shape == (3, 3)
Expand All @@ -518,7 +519,8 @@ def test_interp_time_discrete_single_time():
exp_orient = WXRotation.from_euler("x", 90, degrees=True).as_matrix()

lcs_interp = lcs.interp_time("2s")
assert lcs_interp.time is None
assert lcs_interp.is_time_dependent is False
assert lcs_interp.time.equals(Time("2s"))
assert lcs_interp.coordinates.values.shape == (3,)
assert lcs_interp.orientation.values.shape == (3, 3)
assert np.all(lcs_interp.coordinates.data == exp_coords)
Expand Down
5 changes: 4 additions & 1 deletion weldx/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,10 @@ def _convert_xarray(
if "time" in time.coords:
time = time.time
time_ref = time.weldx.time_ref
time_index = pd.Index(time.values)
if time.shape:
time_index = pd.Index(time.values)
else:
time_index = pd.Index([time.values])
if time_ref is not None:
time_index = time_index + time_ref
return time_index
Expand Down
2 changes: 1 addition & 1 deletion weldx/transformations/cs_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1697,7 +1697,7 @@ def transform_data(
if not isinstance(data, xr.DataArray):
data = xr.DataArray(data, dims=["n", "c"], coords={"c": ["x", "y", "z"]})

time = data.time if "time" in data.dims else None
time = data.time if "time" in data.coords else None
lcs = self.get_cs(
source_coordinate_system_name, target_coordinate_system_name, time=time
)
Expand Down
13 changes: 7 additions & 6 deletions weldx/transformations/local_cs.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def __init__(
# warn about dropped time data
if (
time is not None
and len(Time(time)) > 1
and "time" not in orientation.dims
and (isinstance(coordinates, TimeSeries) or "time" not in coordinates.dims)
):
Expand Down Expand Up @@ -548,7 +549,7 @@ def is_time_dependent(self) -> bool:
`True` if the coordinate system is time dependent, `False` otherwise.
"""
return self.time is not None or self._coord_ts is not None
return self._coord_ts is not None or ("time" in self._dataset.dims)

@property
def has_timeseries(self) -> bool:
Expand Down Expand Up @@ -593,7 +594,7 @@ def time(self) -> Union[Time, None]:
Time-like data array representing the time union of the LCS
"""
if "time" in self._dataset.dims:
if "time" in self._dataset.coords:
return Time(self._dataset.time, self.reference_time)
return None

Expand Down Expand Up @@ -667,9 +668,9 @@ def _interp_time_orientation(self, time: Time) -> xr.DataArray:
if "time" not in self.orientation.dims: # don't interpolate static
return self.orientation
if time.max() <= self.time.min(): # only use edge timestamp
return self.orientation.values[0]
return self.orientation.isel(time=0).data
if time.min() >= self.time.max(): # only use edge timestamp
return self.orientation.values[-1]
return self.orientation.isel(time=-1).data
# full interpolation with overlapping times
return ut.xr_interp_orientation_in_time(self.orientation, time)

Expand All @@ -686,9 +687,9 @@ def _interp_time_coordinates(self, time: Time) -> xr.DataArray:
if "time" not in self.coordinates.dims: # don't interpolate static
return self.coordinates
if time.max() <= self.time.min(): # only use edge timestamp
return self.coordinates[0]
return self.coordinates.isel(time=0).data
if time.min() >= self.time.max(): # only use edge timestamp
return self.coordinates[-1]
return self.coordinates.isel(time=-1).data
# full interpolation with overlapping times
return ut.xr_interp_coordinates_in_time(self.coordinates, time)

Expand Down
6 changes: 3 additions & 3 deletions weldx/util/xarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ def xr_interp_coordinates_in_time(
Interpolated data
"""
if "time" not in da.dims:
if "time" not in da.dims: # not time dependent
return da

times = Time(times).as_pandas_index()
Expand Down Expand Up @@ -734,7 +734,7 @@ def time_ref_unset(self) -> xr.DataArray:
def time_ref_restore(self) -> xr.DataArray:
"""Convert DatetimeIndex back to TimedeltaIndex + reference Timestamp."""
da = self._obj.copy()
if "time" not in da.dims:
if "time" not in da.coords:
return da

if is_datetime64_dtype(da.time):
Expand All @@ -757,7 +757,7 @@ def reset_reference_time(self, time_ref_new: pd.Timestamp) -> xr.DataArray:
def time_ref(self) -> Union[pd.Timestamp, None]:
"""Get the time_ref value or `None` if not set."""
da = self._obj
if "time" in da.dims and "time_ref" in da.time.attrs:
if "time" in da.coords and "time_ref" in da.time.attrs:
return da.time.attrs["time_ref"]

return None
Expand Down

0 comments on commit abe5cb3

Please sign in to comment.