def xr_interp_orientation_in_time(da: xr.DataArray, time: types_time_like) -> xr.DataArray: """Interpolate an xarray DataArray that represents orientation data in time. Parameters ---------- da : xarray DataArray containing the orientation as matrix time : Time data Returns ------- xarray.DataArray Interpolated data """ if "time" not in da.dims: return da if len(da.time) == 1: # remove "time dimension" for static case return da.isel({"time": 0}) time = Time(time).as_pandas_index() time_da = Time(da).as_pandas_index() time_ref = da.weldx.time_ref if not len(time_da) > 1: raise ValueError("Invalid time format for interpolation.") # extract intersecting times and add time range boundaries of the data set times_ds_limits = pd.Index([time_da.min(), time_da.max()]) times_union = time.union(times_ds_limits) times_intersect = times_union[(times_union >= times_ds_limits[0]) & (times_union <= times_ds_limits[1])] # interpolate rotations in the intersecting time range rotations_key = Rot.from_matrix(da.transpose(..., "time", "c", "v").data) times_key = time_da.view(np.int64) rotations_interp = Slerp(times_key, rotations_key)(times_intersect.view(np.int64)) da = xr_3d_matrix(rotations_interp.as_matrix(), times_intersect) # use interp_like to select original time values and correctly fill time dimension da = xr_interp_like(da, {"time": time}, fillna=True) # resync and reset to correct format if time_ref: da.weldx.time_ref = time_ref da = da.weldx.time_ref_restore().transpose(..., "time", "c", "v") if len(da.time) == 1: # remove "time dimension" for static case return da.isel({"time": 0}) return da
def xr_interp_orientation_in_time( dsx: xr.DataArray, times: Union[pd.DatetimeIndex, pd.TimedeltaIndex] ) -> xr.DataArray: """Interpolate an xarray DataArray that represents orientation data in time. Parameters ---------- dsx : xarray DataArray containing the orientation as matrix times : Time data Returns ------- xarray.DataArray Interpolated data """ if "time" not in dsx.coords: return dsx times = to_pandas_time_index(times) times_ds = to_pandas_time_index(dsx) time_ref = dsx.weldx.time_ref if len(times_ds) > 1: # extract intersecting times and add time range boundaries of the data set times_ds_limits = pd.Index([times_ds.min(), times_ds.max()]) times_union = times.union(times_ds_limits) times_intersect = times_union[ (times_union >= times_ds_limits[0]) & (times_union <= times_ds_limits[1]) ] # interpolate rotations in the intersecting time range rotations_key = Rot.from_matrix(dsx.transpose(..., "c", "v").data) times_key = times_ds.astype(np.int64) rotations_interp = Slerp(times_key, rotations_key)( times_intersect.astype(np.int64) ) dsx_out = xr_3d_matrix(rotations_interp.as_matrix(), times_intersect) else: # TODO: this case is not really well defined, maybe avoid? dsx_out = dsx # use interp_like to select original time values and correctly fill time dimension dsx_out = xr_interp_like(dsx_out, {"time": times}, fillna=True) # resync and reset to correct format if time_ref: dsx_out.weldx.time_ref = time_ref dsx_out = dsx_out.weldx.time_ref_restore() return dsx_out.transpose(..., "c", "v")