New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check time coords #635
Check time coords #635
Conversation
Codecov Report
@@ Coverage Diff @@
## master #635 +/- ##
=======================================
Coverage 94.49% 94.49%
=======================================
Files 93 93
Lines 6011 6014 +3
=======================================
+ Hits 5680 5683 +3
Misses 331 331
Continue to review full report at Codecov.
|
assert lcs_interp.is_time_dependent is False | ||
assert lcs_interp.time.equals(Time("2s")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is one case where the updated behavior differs slightly
lcs_interp.is_time_dependent
returns False
but we can still access the (singular) timestamp from the LCS
if time.shape: | ||
time_index = pd.Index(time.values) | ||
else: | ||
time_index = pd.Index([time.values]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
singular values weren't really handled all that well before
@@ -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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the most important change, a LCS can be time independent but still return a .time
value
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could also skip the .data
here but in that case we would have to decide which "edge" timestamp we want to assign, however this is now more consistent for coordinates and orientations
# make sure we have correct dimension order | ||
self.coordinates = self.coordinates.transpose(..., "n", "c") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was causing the troubles with scan data transformation as an incorrectly transposed xarray (p,c,n) was passed to SpatialData
@vhirtham
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice finding. I recently also passed a "misformed" xarray to ´SpatialData´ that gave me some headaches. The time coordinate was a datetime instead of a timedelta with an optional reference time. The error message was a bit cryptic and only occurred if time-dependent transformations were performed. The question is if we want to catch this too. While we might remember the format requirements, our new 2 users from the lab might get totally confused by such errors. Maybe we can introduce an xr_format_data_array
function that orders dimensions, correct wrong time inputs and possibly other stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you reproduce this bug?
the time values can be formatted here by using the .weldx.time_ref_restore
xarray accessor, however all operations that rely on these time formats (e.g. interpolation) should also make sure to handle these internally so it would be good to know where this happens.
either way we should also make use of check_coords
more often
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, one can grasp the expected format from the function inputs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import xarray as xr
from weldx import CoordinateSystemManager, SpatialData, Time, WXRotation
rot = WXRotation.from_euler("z", [0, 45, 90], True).as_matrix()
csm = CoordinateSystemManager("root")
csm.create_cs("workpiece", "root", coordinates=[0, 1, 2])
csm.create_cs(
"TCP",
"root",
orientation=rot,
coordinates=[[0, 0, 0], [1, 0, 0], [2, 0, 0]],
time=Time(["2000", "2001", "2002"]),
)
da = xr.DataArray(
[[[0, -1, 1], [0, 1, 1]], [[0, -1, 2], [0, 1, 2]], [[0, -1, -1], [0, 1, -1]]],
dims=["time", "n", "c"],
coords={"time": Time(["2000", "2001", "2002"]).as_pandas_index()},
)
sd = SpatialData(da)
csm.assign_data(sd, "data", "TCP", "workpiece")
This was the script I used to understand the error. I didn't create an issue cause I thought it was my own stupidity to violate the expected xarray format. However, it is probably better if those input violations are either handled or give an instant and clear response to the user as you said. The annoying thing here is: If you remover the instant transformation to the workpiece cs, the error happens later (for example during a .plot
call or wherever the first transformation occurs) and getting the connection isn't that easy anymore.
added some minor changes but I think this is good now @vhirtham |
Changes
time
in xarray coordinates instead of dimensions in some casesIn cases where we access the
time
coordinate value I think it makes sense to check for time in the coordinates instead of the array dimensions. If time is a dimension without coordinates we would only get integer values which would be error prone.In contrast if we actually want to check if an object is time_dependent (changing in time) we should look for time in the dimensions
However so far it is a bit inconsistent with single timestamps outside of the definition range:
Checks