|
33 | 33 | import warnings |
34 | 34 | from datetime import datetime |
35 | 35 |
|
| 36 | +import zarr |
36 | 37 | import numpy as np |
| 38 | +import pandas as pd |
| 39 | +from fibgrid.realization import FibGrid |
37 | 40 |
|
38 | 41 | try: |
39 | 42 | import pygrib |
@@ -318,3 +321,114 @@ def __init__(self, |
318 | 321 |
|
319 | 322 | super().__init__(cdr_path, fn_format, grid_filename, static_layer_path, |
320 | 323 | **kwargs) |
| 324 | + |
| 325 | + |
| 326 | +class H121Zarr: |
| 327 | + """ |
| 328 | + Class reading ASCAT SSM CDR v8 12.5 km (H121) in zarr data format |
| 329 | + stored as incomplete multidimensional array representation. |
| 330 | +
|
| 331 | + This class is for testing purpose only. |
| 332 | + """ |
| 333 | + |
| 334 | + def __init__(self): |
| 335 | + """Initialize.""" |
| 336 | + self.path = "https://www.geo.tuwien.ac.at/shahn/h121/" |
| 337 | + self.lut = zarr.open(self.path, mode="r", path="lut")[:] |
| 338 | + self.data = zarr.open(self.path, mode="r") |
| 339 | + self.grid = FibGrid(12.5) |
| 340 | + |
| 341 | + def read(self, *args): |
| 342 | + """ |
| 343 | + Read time series either by GPI (1 argument) or lon/lat (2 arguments). |
| 344 | +
|
| 345 | + Parameters |
| 346 | + ---------- |
| 347 | + gpi : int |
| 348 | + Grid point index. |
| 349 | +
|
| 350 | + or |
| 351 | +
|
| 352 | + lon : float |
| 353 | + Longitude in degrees. |
| 354 | + lat : float |
| 355 | + Latitude in degrees. |
| 356 | +
|
| 357 | + Returns |
| 358 | + ------- |
| 359 | + pandas.DataFrame |
| 360 | + Time series data. |
| 361 | + """ |
| 362 | + if len(args) == 1: |
| 363 | + gpi = args[0] |
| 364 | + return self.read_gpi(gpi) |
| 365 | + elif len(args) == 2: |
| 366 | + lon, lat = args |
| 367 | + return self.read_lonlat(lon, lat) |
| 368 | + else: |
| 369 | + raise ValueError("Pass either (gpi) or (lon, lat)") |
| 370 | + |
| 371 | + def read_gpi(self, gpi): |
| 372 | + """ |
| 373 | + Read time series for given grid point (Fibonacci 12.5 km). |
| 374 | +
|
| 375 | + Parameters |
| 376 | + ---------- |
| 377 | + gpi : int32 |
| 378 | + Grid point index. |
| 379 | +
|
| 380 | + Returns |
| 381 | + ------- |
| 382 | + df : pandas.DataFrame |
| 383 | + Time series data. |
| 384 | + """ |
| 385 | + return self._read_by_gpi(gpi) |
| 386 | + |
| 387 | + def read_lonlat(self, lon, lat, max_dist=15000.): |
| 388 | + """ |
| 389 | + Read the time series data for the grid point closest |
| 390 | + to the given lon/lat coordinates. |
| 391 | +
|
| 392 | + Parameters |
| 393 | + ---------- |
| 394 | + lon : float32 |
| 395 | + Longitude coordinate. |
| 396 | + lat : float32 |
| 397 | + Latitude coordinate. |
| 398 | + max_dist : float32 |
| 399 | + Maximum searching distance. |
| 400 | +
|
| 401 | + Returns |
| 402 | + ------- |
| 403 | + df : pandas.DataFrame |
| 404 | + Time series data. |
| 405 | + """ |
| 406 | + gpi, distance = self.grid.find_nearest_gpi(lon, lat, max_dist) |
| 407 | + return self._read_by_gpi(gpi) |
| 408 | + |
| 409 | + def _read_by_gpi(self, gpi): |
| 410 | + """ |
| 411 | + Read data from grid point index. |
| 412 | + """ |
| 413 | + i = self.lut[gpi] |
| 414 | + if i == 861789: |
| 415 | + raise RuntimeError(f"Grid point {gpi} not found in data.") |
| 416 | + |
| 417 | + dt = self.data["time"][i].astype(np.dtype("<M8[ns]")) |
| 418 | + |
| 419 | + df = pd.DataFrame( |
| 420 | + { |
| 421 | + "as_des_pass": self.data["as_des_pass"][i], |
| 422 | + "swath_indicator": self.data["swath_indicator"][i], |
| 423 | + "ssm": self.data["surface_soil_moisture"][i], |
| 424 | + "ssm_noise": self.data["surface_soil_moisture_noise"][i], |
| 425 | + "backscatter40": self.data["backscatter40"][i], |
| 426 | + "slope40": self.data["slope40"][i], |
| 427 | + "curvature40": self.data["curvature40"][i], |
| 428 | + }, |
| 429 | + index=dt) |
| 430 | + |
| 431 | + df = df[df.index != np.datetime64("1970-01-01")] |
| 432 | + df.replace(-2**31, np.nan, inplace=True) |
| 433 | + |
| 434 | + return df |
0 commit comments