|
46 | 46 | _CRS_WGS84 = pyproj.CRS.from_string("EPSG:4326") |
47 | 47 | _DEM_CHUNKSIZE = dict(lat=1800, lon=1800) |
48 | 48 | _CHUNKSIZE = (2048, 2048) |
| 49 | +_SLC_SWATHS = ["IW1", "IW2", "IW3"] |
49 | 50 | _REGISTERED_CACHE_URIS = [] |
50 | 51 |
|
51 | 52 |
|
@@ -367,26 +368,28 @@ def _open_data( |
367 | 368 | ) -> xr.Dataset: |
368 | 369 | """Load, calibrate, and merge SLC bursts into a single dataset.""" |
369 | 370 |
|
370 | | - children = self._get_groups(datatree) |
| 371 | + children, modes = self._get_groups(datatree) |
371 | 372 |
|
372 | 373 | # First combine all polarizations within each burst. |
373 | | - dss_burst = np.empty(children.shape[1:], dtype=object) |
374 | | - for swath_i, swath in enumerate(children.swath.values): |
375 | | - for burst_idx in children.burst.values: |
| 374 | + dss_all = [] |
| 375 | + for swath_i, _ in enumerate(_SLC_SWATHS): |
| 376 | + dss_swath = [] |
| 377 | + for burst_i, _ in enumerate(children[0][swath_i]): |
376 | 378 | burst_dataset = xr.Dataset() |
377 | | - for mode_i, mode in enumerate(children.mode.values): |
378 | | - child = children.sel(mode=mode, swath=swath, burst=burst_idx).item() |
| 379 | + for mode_i, mode in enumerate(modes): |
| 380 | + child = children[mode_i][swath_i][burst_i] |
379 | 381 | burst = datatree[child] |
380 | 382 | beta0 = self._calibrate_burst(burst) |
381 | 383 | beta0 = self._extract_valid_region(beta0, burst) |
382 | 384 | beta0 = beta0.drop_vars(["line", "pixel"]) |
383 | 385 | beta0 = beta0.rename({"slc": f"beta0_{mode.lower()}"}) |
384 | 386 | burst_dataset.update(beta0) |
385 | | - dss_burst[swath_i, burst_idx] = burst_dataset |
| 387 | + dss_swath.append(burst_dataset) |
| 388 | + dss_all.append(dss_swath) |
386 | 389 |
|
387 | | - dss_swaths = np.empty(children.shape[1], dtype=object) |
388 | | - for swath_i, swath in enumerate(children.swath.values): |
389 | | - dss_swaths[swath_i] = self._merge_bursts(dss_burst[swath_i, :]) |
| 390 | + dss_swaths = [] |
| 391 | + for swath_i, swath in enumerate(_SLC_SWATHS): |
| 392 | + dss_swaths.append(self._merge_bursts(dss_all[swath_i])) |
390 | 393 | dss_swaths = self._align_azimuth(dss_swaths) |
391 | 394 | merged = self._merge_swaths(dss_swaths) |
392 | 395 |
|
@@ -415,32 +418,21 @@ def _expand_names( |
415 | 418 | return merged |
416 | 419 |
|
417 | 420 | @staticmethod |
418 | | - def _get_groups(datatree): |
| 421 | + def _get_groups(datatree: xr.DataTree) -> tuple[list[list[list[str]]], list[str]]: |
419 | 422 | """Return child group names organized by polarization, swath, and burst.""" |
420 | | - swaths = ["IW1", "IW2", "IW3"] |
421 | 423 | modes = ["VV", "VH", "HV", "HH"] |
| 424 | + modes_sel = [] |
422 | 425 | children = [] |
423 | 426 | for mode in modes: |
424 | 427 | mode_children = [] |
425 | | - for swath_i, swath in enumerate(swaths): |
| 428 | + for swath_i, swath in enumerate(_SLC_SWATHS): |
426 | 429 | bursts = [x for x in datatree.children if f"_{mode}_{swath}" in x] |
427 | 430 | if bursts: |
428 | 431 | mode_children.append(bursts) |
| 432 | + modes_sel.append(modes_sel) |
429 | 433 | if mode_children: |
430 | 434 | children.append(mode_children) |
431 | | - children = np.array(children, dtype=str) |
432 | | - return xr.DataArray( |
433 | | - children, |
434 | | - dims=("mode", "swath", "burst"), |
435 | | - coords={ |
436 | | - "mode": [ |
437 | | - m for m in modes if any(f"_{m}_" in x for x in datatree.children) |
438 | | - ], |
439 | | - "swath": swaths[: children.shape[1]], |
440 | | - "burst": np.arange(children.shape[2]), |
441 | | - }, |
442 | | - name="burst_groups", |
443 | | - ) |
| 435 | + return children, list(np.unique(modes_sel)) |
444 | 436 |
|
445 | 437 | @staticmethod |
446 | 438 | def _calibrate_burst(burst: xr.DataTree) -> xr.Dataset: |
@@ -468,7 +460,7 @@ def _extract_valid_region(dataset: xr.Dataset, burst: xr.DataTree) -> xr.Dataset |
468 | 460 | ) |
469 | 461 |
|
470 | 462 | @staticmethod |
471 | | - def _merge_bursts(dss: np.ndarray, tolerance: float = 0.01) -> xr.Dataset: |
| 463 | + def _merge_bursts(dss: list[xr.Dataset], tolerance: float = 0.01) -> xr.Dataset: |
472 | 464 | """Merge overlapping bursts along azimuth time.""" |
473 | 465 | idxs = np.zeros((len(dss), 2), dtype=int) |
474 | 466 | tol = 0.01 * np.diff(dss[0].azimuth_time.values[:2])[0] |
@@ -525,7 +517,9 @@ def _merge_bursts(dss: np.ndarray, tolerance: float = 0.01) -> xr.Dataset: |
525 | 517 | return out |
526 | 518 |
|
527 | 519 | @staticmethod |
528 | | - def _align_azimuth(dss: np.ndarray, tolerance: float = 0.01) -> list[xr.Dataset]: |
| 520 | + def _align_azimuth( |
| 521 | + dss: list[xr.Dataset], tolerance: float = 0.01 |
| 522 | + ) -> list[xr.Dataset]: |
529 | 523 | """Align all swaths to a shared azimuth-time axis.""" |
530 | 524 | tol = 0.1 * np.diff(dss[0].azimuth_time.values[:2])[0] |
531 | 525 |
|
@@ -832,17 +826,25 @@ def get_dem( |
832 | 826 | lon=slice(bbox_wgs84[0], bbox_wgs84[2]), |
833 | 827 | ).chunk(_DEM_CHUNKSIZE) |
834 | 828 | else: |
835 | | - if resolution is None: |
836 | | - raise ValueError("Resolution must be provided if CRS is not None.") |
| 829 | + dem = dem.to_dataset(name="dem") |
837 | 830 | if crs is None: |
838 | 831 | crs = _CRS_WGS84 |
| 832 | + if resolution is None: |
| 833 | + source_gm = GridMapping.from_dataset(dem) |
| 834 | + ref_point = ( |
| 835 | + (bbox_wgs84[0] + bbox_wgs84[2]) / 2, |
| 836 | + (bbox_wgs84[1] + bbox_wgs84[3]) / 2, |
| 837 | + ) |
| 838 | + resolution = transform_resolution( |
| 839 | + ref_point, source_gm.xy_res, source_gm.crs, crs |
| 840 | + ) |
839 | 841 | target_gm = GridMapping.regular_from_bbox( |
840 | 842 | bbox, |
841 | 843 | resolution, |
842 | 844 | crs, |
843 | 845 | tile_size=(_DEM_CHUNKSIZE["lat"], _DEM_CHUNKSIZE["lon"]), |
844 | 846 | ) |
845 | | - dem = resample_in_space(dem.to_dataset(name="dem"), target_gm=target_gm).dem |
| 847 | + dem = resample_in_space(dem, target_gm=target_gm).dem |
846 | 848 |
|
847 | 849 | return dem |
848 | 850 |
|
|
0 commit comments