-
Notifications
You must be signed in to change notification settings - Fork 17
Support heterogeneous datasets with scalar variables in from_dataset #169
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
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -87,7 +87,39 @@ If you omit `table_names`, each table is named by joining its dimension names | |
| with underscores, e.g. `era5.time_latitude_longitude` and | ||
| `era5.time_level_latitude_longitude`. | ||
|
|
||
| A runnable version of this example lives at | ||
| ## GOES satellite imagery (scalar variables) | ||
|
|
||
| Real-world stores often mix gridded data with scalar (0-dimensional) metadata. | ||
| GOES satellite imagery, for example, pairs `(y, x)` image bands with dozens of | ||
| scalar variables such as `goes_imager_projection`. `from_dataset` groups all the | ||
| scalars into a single one-row table named `scalar`: | ||
|
|
||
| ```python | ||
| import urllib.request | ||
|
|
||
| import xarray as xr | ||
| from xarray_sql import XarrayContext | ||
|
|
||
| # A real GOES-16 ABI cloud-and-moisture file from NOAA's public bucket: | ||
| # (y, x) image bands alongside dozens of scalar metadata variables. | ||
| url = ( | ||
| 'https://noaa-goes16.s3.amazonaws.com/ABI-L2-MCMIPM/2024/001/00/' | ||
| 'OR_ABI-L2-MCMIPM1-M6_G16_s20240010000281_e20240010000350_c20240010000426.nc' | ||
| ) | ||
| urllib.request.urlretrieve(url, 'goes.nc') | ||
| ds = xr.open_dataset('goes.nc').chunk({'y': 250, 'x': 250}) | ||
|
|
||
| ctx = XarrayContext() | ||
| ctx.from_dataset('goes', ds) | ||
|
|
||
| # The gridded bands and the scalar metadata are separate tables. | ||
| ctx.sql('SELECT COUNT(*) AS n FROM goes.y_x').to_pandas()['n'][0] # -> 250000 | ||
| ctx.sql('SELECT * FROM goes.scalar').to_pandas().shape # -> (1, 89) | ||
| ``` | ||
|
|
||
| Override the default name like any other group with `table_names={(): 'metadata'}`. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, this is helpful. |
||
|
|
||
| A runnable version of the ERA5 example lives at | ||
| [`perf_tests/era5_temp_profile.py`](../perf_tests/era5_temp_profile.py). | ||
|
|
||
| [arco-era5]: https://github.com/google-research/arco-era5 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -86,10 +86,12 @@ def from_dataset( | |
| self.catalog().register_schema(name, schema) | ||
|
|
||
| for dims, var_names in groups.items(): | ||
| sub_name = table_names.get(dims, "_".join(dims)) | ||
| sub_ds = input_table[var_names] | ||
| schema.register_table(sub_name, read_xarray_table(sub_ds, chunks)) | ||
| self._maybe_register_cftime_udf(sub_ds) | ||
|
alxmrs marked this conversation as resolved.
|
||
| # Scalar variables group under empty dims, where "_".join(()) is | ||
| # the empty string; fall back to a valid default table name. | ||
| sub_name = table_names.get(dims, "_".join(dims) or "scalar") | ||
| self._from_dataset( | ||
| sub_name, input_table[var_names], chunks, schema=schema | ||
| ) | ||
|
|
||
| return self | ||
|
|
||
|
|
@@ -98,11 +100,17 @@ def _from_dataset( | |
| table_name: str, | ||
| input_table: xr.Dataset, | ||
| chunks: Chunks = None, | ||
| schema: Schema | None = None, | ||
| ): | ||
| """Register a uniform-dimension Dataset as a single SQL table.""" | ||
| """Register a Dataset as a single SQL table. | ||
|
|
||
| table = read_xarray_table(input_table, chunks) | ||
| self.register_table(table_name, table) | ||
| Registers a top-level table by default, or a table inside ``schema`` | ||
| (a SQL namespace) when one is given. | ||
| """ | ||
| register = ( | ||
| self.register_table if schema is None else schema.register_table | ||
| ) | ||
| register(table_name, read_xarray_table(input_table, chunks)) | ||
| self._maybe_register_cftime_udf(input_table) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, why was this deleted?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same thing, |
||
| return self | ||
|
|
||
|
|
||
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 don't think you need to download the netcdf file first. You should be able to open it just with Xarray, maybe first using fsspec.
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.
Just your luck -- it looks like this dataset was just virtualized: https://earthmover.io/blog/virtual-zarr/
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.
Good call. Switched to fsspec with simplecache so xarray opens it directly, no manual download step.
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.
Ha, that is the same blog that kicked this whole thread off. I kept the NOAA file here so the example stays auth free and copy pasteable, but the virtual zarr version is really cool.