From 796f762f86034359e77fa46b4fff2d93e23934a1 Mon Sep 17 00:00:00 2001 From: Aureliana Barghini <35919497+aurghs@users.noreply.github.com> Date: Wed, 14 Apr 2021 14:24:42 +0200 Subject: [PATCH] Fix open_orbit_dataset and ope_attitude_dataset (#10) fix --- tests/test_xarray.py | 26 ++++++++++++++++ xarray_sentinel/conventions.py | 12 +++---- xarray_sentinel/esa_safe.py | 10 +++--- xarray_sentinel/sentinel1.py | 57 ++++++++++++++++++++-------------- 4 files changed, 71 insertions(+), 34 deletions(-) diff --git a/tests/test_xarray.py b/tests/test_xarray.py index 5550bd8..f2838cd 100644 --- a/tests/test_xarray.py +++ b/tests/test_xarray.py @@ -32,6 +32,32 @@ def test_open_dataset_root() -> None: assert isinstance(res, xr.Dataset) +def test_open_dataset_orbit() -> None: + annotation_path = ( + DATA_FOLDER + / "S1B_IW_SLC__1SDV_20210401T052622_20210401T052650_026269_032297_EFA4.SAFE" + / "annotation" + / "s1b-iw1-slc-vv-20210401t052624-20210401t052649-026269-032297-004.xml" + ) + res = xr.open_dataset(annotation_path, engine="sentinel-1", group="orbit") # type: ignore + + assert isinstance(res, xr.Dataset) + assert set(res.dims) == {"time"} + + +def test_open_dataset_attitude() -> None: + annotation_path = ( + DATA_FOLDER + / "S1B_IW_SLC__1SDV_20210401T052622_20210401T052650_026269_032297_EFA4.SAFE" + / "annotation" + / "s1b-iw1-slc-vv-20210401t052624-20210401t052649-026269-032297-004.xml" + ) + res = xr.open_dataset(annotation_path, engine="sentinel-1", group="attitude") # type: ignore + + assert isinstance(res, xr.Dataset) + assert set(res.dims) == {"time"} + + def test_open_dataset_gcp() -> None: annotation_path = ( DATA_FOLDER diff --git a/xarray_sentinel/conventions.py b/xarray_sentinel/conventions.py index ccfb6b8..9379675 100644 --- a/xarray_sentinel/conventions.py +++ b/xarray_sentinel/conventions.py @@ -10,12 +10,12 @@ "roll": {"units": "degrees"}, "yaw": {"units": "degrees"}, "time": {}, - "x": {"units": "m"}, - "y": {"units": "m"}, - "z": {"units": "m"}, - "vx": {"units": "m s-1"}, - "vy": {"units": "m s-1"}, - "vz": {"units": "m s-1"}, + "x": {"units": "m", "long_name": "position_x"}, + "y": {"units": "m", "long_name": "position_y"}, + "z": {"units": "m", "long_name": "position_z"}, + "vx": {"units": "m s-1", "long_name": "velocity_x"}, + "vy": {"units": "m s-1", "long_name": "velocity_y"}, + "vz": {"units": "m s-1", "long_name": "velocity_z"}, } diff --git a/xarray_sentinel/esa_safe.py b/xarray_sentinel/esa_safe.py index 4c8a7f8..cb2a8e8 100644 --- a/xarray_sentinel/esa_safe.py +++ b/xarray_sentinel/esa_safe.py @@ -56,12 +56,12 @@ def parse_swath_timing(annotation_path: PathType,) -> T.List[T.Dict[str, T.Any]] def open_manifest( - product_folder: T.Union[str, "os.PathLike[str]"] + product_path: T.Union[str, "os.PathLike[str]"] ) -> ElementTree.ElementTree: - product_folder = pathlib.Path(product_folder) - if product_folder.is_dir(): - product_folder = product_folder / "manifest.safe" - return ElementTree.parse(product_folder) + product_path = pathlib.Path(product_path) + if product_path.is_dir(): + product_path = product_path / "manifest.safe" + return ElementTree.parse(product_path) def parse_manifest_sentinel1( diff --git a/xarray_sentinel/sentinel1.py b/xarray_sentinel/sentinel1.py index 1e291a6..fe43ff4 100644 --- a/xarray_sentinel/sentinel1.py +++ b/xarray_sentinel/sentinel1.py @@ -79,19 +79,25 @@ def open_gcp_dataset(product_path: str) -> xr.Dataset: def open_attitude_dataset(product_path: str) -> xr.Dataset: attitude = esa_safe.parse_attitude(product_path) shape = len(attitude) - variables = ["q0", "q1", "q2", "wx", "wy", "wz", "pitch", "roll", "yaw", "time"] - data_vars: T.Dict[str, T.List[T.Any]] = {var: [] for var in variables} - + variables = ["q0", "q1", "q2", "wx", "wy", "wz", "pitch", "roll", "yaw"] + time: T.List[T.Any] = [] + data_vars: T.Dict[str, T.List[T.Any]] = {var: ("time", []) for var in variables} # type: ignore for k in range(shape): + time.append(attitude[k]["time"]) for var in variables: - data_vars[var].append((attitude[k][var])) + data_vars[var][1].append(attitude[k][var]) + coords = { + "time": ("time", time, {"standard_name": "time", "long_name": "time"},), + } ds = xr.Dataset( data_vars=data_vars, # type: ignore attrs={"Conventions": "CF-1.7"}, + coords=coords, # type: ignore ) ds = conventions.update_attributes(ds) + ds = ds.update({"time": ds.time.astype(np.datetime64)}) return ds @@ -100,23 +106,17 @@ def open_orbit_dataset(product_path: str) -> xr.Dataset: shape = len(orbit) reference_system = orbit[0]["frame"] - data_vars: T.Dict[str, T.List[T.Any]] = { - "time": [], - "x": [], - "y": [], - "z": [], - "vx": [], - "vy": [], - "vz": [], - } + variables = ["x", "y", "z", "vx", "vy", "vz"] + data_vars: T.Dict[str, T.List[T.Any]] = {var: ("time", []) for var in variables} # type: ignore + time: T.List[T.Any] = [] for k in range(shape): - data_vars["time"].append(orbit[k]["time"]) - data_vars["x"].append(orbit[k]["position"]["x"]) - data_vars["y"].append(orbit[k]["position"]["y"]) - data_vars["z"].append(orbit[k]["position"]["z"]) - data_vars["x"].append(orbit[k]["velocity"]["x"]) - data_vars["y"].append(orbit[k]["velocity"]["y"]) - data_vars["z"].append(orbit[k]["velocity"]["z"]) + time.append(orbit[k]["time"]) + data_vars["x"][1].append(orbit[k]["position"]["x"]) + data_vars["y"][1].append(orbit[k]["position"]["y"]) + data_vars["z"][1].append(orbit[k]["position"]["z"]) + data_vars["vx"][1].append(orbit[k]["velocity"]["x"]) + data_vars["vy"][1].append(orbit[k]["velocity"]["y"]) + data_vars["vz"][1].append(orbit[k]["velocity"]["z"]) if orbit[k]["frame"] != reference_system: warnings.warn( f"reference_system is not consistent in all the state vectors. " @@ -124,21 +124,28 @@ def open_orbit_dataset(product_path: str) -> xr.Dataset: ) reference_system = None + coords = { + "time": ("time", time, {"standard_name": "time", "long_name": "time"},), + } attrs = {"Conventions": "CF-1.7"} if reference_system is not None: attrs.update({"reference_system": reference_system}) ds = xr.Dataset( data_vars=data_vars, # type: ignore attrs=attrs, # type: ignore + coords=coords, # type: ignore ) ds = conventions.update_attributes(ds) + ds = ds.update({"time": ds.time.astype(np.datetime64)}) return ds -def open_root_dataset(filename: str) -> xr.Dataset: - manifest = esa_safe.open_manifest(filename) +def open_root_dataset(product_path: str) -> xr.Dataset: + manifest = esa_safe.open_manifest(product_path) product_attrs, product_files = esa_safe.parse_manifest_sentinel1(manifest) - product_attrs["groups"] = ["orbit"] + product_attrs["xs:instrument_mode_swaths"] + product_attrs["groups"] = ["orbit", "attitude", "gcp"] + product_attrs[ + "xs:instrument_mode_swaths" + ] return xr.Dataset(attrs=product_attrs) # type: ignore @@ -153,6 +160,10 @@ def open_dataset( # type: ignore ds = open_root_dataset(filename_or_obj) elif group == "gcp": ds = open_gcp_dataset(filename_or_obj) + elif group == "orbit": + ds = open_orbit_dataset(filename_or_obj) + elif group == "attitude": + ds = open_attitude_dataset(filename_or_obj) return ds def guess_can_open(self, filename_or_obj: T.Any) -> bool: