Repository navigation
FIX: legacy open_*_datatree regressions after #335 - #484
Conversation
openradar#335 made the deprecated open_*_datatree functions and xd.open_datatree call the backend's open_datatree directly, which skipped xarray's dataset wrapping and dropped most backend_kwargs. Both now go through xr.open_datatree (shared _open_legacy_datatree helper), so: - chunks, cache and other xarray options work again - backend_kwargs reach the backend; xarray options passed there are lifted to the top level; legacy `Optional` and `site_as_coords` map to `optional` and `site_coords` (passing both site spellings raises) - legacy optional=False no longer raises "multiple values" - iris, rainbow, furuno and datamet sweeps keep their range index Also: - metadata subgroups no longer copy latitude/longitude/altitude - reindex_angle is resolved once per tree; its FutureWarning, the NEXRAD drop warnings and the CfRadial2 warnings point at the caller - cfradial1/cfradial2 backend option for the netCDF reader is netcdf_engine (engine collided with xarray's argument); the legacy engine= keyword maps to it - CfRadial2 keeps its inner file open for the tree's lifetime and DataTree.close() closes it (closing and reopening crashed netCDF4) - open_uf_datatree has its signature and docstring back; docstrings no longer list parameters an engine rejects; IRIS drops an unused `group` Closes openradar#481
Legacy open_*_datatree output must equal xd.open_datatree for the same options; cover chunks, backend_kwargs (incl. decoders and `Optional`), optional=False, optional_groups, site_as_coords, the range index, xd vs xr equality, sweep identity, the reindex_angle warning, the UF signature, docstrings, netcdf_engine and CfRadial2 close. Refs openradar#481
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #484 +/- ##
==========================================
+ Coverage 95.54% 95.69% +0.14%
==========================================
Files 29 29
Lines 6783 6759 -24
==========================================
- Hits 6481 6468 -13
+ Misses 302 291 -11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The legacy open_cfradial1_datatree and open_cfradial2_datatree map an inner netCDF `engine` given in backend_kwargs to netcdf_engine; check it reaches the reader.
Going through xr.open_datatree made xarray reopen the CfRadial2 file for lazy reads after the backend had closed it; with several handles on the same file netCDF4/HDF5 segfaulted intermittently (locally and once in CI). The backend now loads the normalized groups inside the `with` block and closes the file before returning, so a tree holds no open handle. Refs openradar#481
@aladinor Just to get this right, when reading CfRadial2 we now materialize everything in memory? Is there no way to have this data lazy? Can this be eventually fixed on xarray side? There where some changes in xarray recently (pydata/xarray#11692 and pydata/xarray#11629) which might resolve this (not checked). Another question wrt CfRadial2, what's the difference in using |
syedhamidali
left a comment
There was a problem hiding this comment.
Thanks @aladinor, I tested this independently. The full suite passes locally (1084 passed). Compared with the commit before #335, I ran 10 engines × 10 legacy keyword cases: all four regressions from #481 are fixed, and reindex_angle now warns once at the caller (14 → 1).
Findings:
- IMD regression:
open_imd_datatree(f, backend_kwargs=dict(Optional=False))worked before #335 and onmain(IMD has no optional variables and ignored it), but raisesTypeErrorhere, because the helper maps it tooptional=and the engine rejects it. The helper could dropoptionalfor engines that don't take it; a test for it would be good too. - Not in the description: NEXRAD and UF now honour
first_diminbackend_kwargs(dimstimeinstead ofazimuth), and UF also gets arangeindex. Both are consistent with the other engines, just worth listing.
On @kmuehlbauer's CfRadial2 question: with a copy of a CfRadial2 file that I delete before reading, engine="cfradial2" on main is lazy but fails with FileNotFoundError (it reopens the closed file), while here the read works and no handle stays open. engine="netcdf4" stays lazy with one open handle. With chunks={} you get dask arrays, but over already-loaded data. Same values as engine="netcdf4", plus platform_is_mobile and wmo__cf_profile in the root and a length-1 frequency variable in each sweep.
…imd should not raise
…o unittests.yml, use xarray from conda again
|
@aladinor CI is finally green. Please feel free to use any of that or remove if you are not satisfied or have another solution in mind. I also did not want to fiddle around with the history.md entry. It's already quite long. But here is what I did in the last commits:
|
|
Thanks @kmuehlbauer for making CfRadial2 lazy and CI green, and @syedhamidali for the thorough testing! CI changes stay here. Next: single cache layer + close on errors, check the IMD Optional case vs main, update changelog/description, then review. |
909aab2 to
d23bab1
Compare
|
@kmuehlbauer I tried to move forward with the suggested additions, but CI kept failing on a flaky segfault. It comes from pydata/xarray#11692 (unreleased): on d23bab1, |
* ci: test on Python 3.12-3.14 with numpy 2 main requires the checks "xradar unit tests - linux (3.12, 2)" and "(3.14, 2)", which the old 3.11/3.13 matrix never produced, so no PR could merge. Take the matrix and CI environments from #484 by @kmuehlbauer (8607831, 5fe4348): Python 3.12, 3.13 and 3.14 with numpy 2, python>=3.12 and xarray from conda, filelock for the tests. * build: require Python >= 3.12 CI no longer tests 3.11. Set requires-python to >=3.12, list 3.12-3.14 in the classifiers, and pin the dev/ReadTheDocs environment to python >=3.12 so the docs build cannot resolve to an unsupported version. * docs: link issue #487 and PR #488 in the changelog
|
@aladinor Just for testing, can you run this for xarray main? I'll catch up tomorrow. |
|
@kmuehlbauer done: with xarray |
|
@syedhamidali IMD |
* ci: test against released xarray again, time out hung test jobs The temporary xarray main install from #484 only moved the flaky HDF5 crash between Python versions; #503 fixed it. The unit, notebook and nightly jobs time out after 30 minutes instead of GitHub's 6 hours. * docs: link #495 and #510 in the changelog * docs: keep one #484 changelog entry, without the xarray main note * docs: shorten the #510 changelog entry
Closes #481. Follow-up to #335.
#335 made the deprecated
open_*_datatreefunctions andxd.open_datatreecall each backend'sopen_datatreedirectly. That skipped xarray's dataset wrapping (chunks, caching, default indexes) and dropped mostbackend_kwargs. Both now go throughxr.open_datatree, with one shared helper (_open_legacy_datatreeincommon.py) for the 12 deprecated wrappers.Fixed (each checked against 77534e4,
mainbefore #335)open_odim_datatree(f, chunks={})(also gamic, iris, rainbow, datamet, cfradial1, cfradial2),xd.open_datatree(..., chunks={})TypeErrorbackend_kwargs=dict(first_dim="time")(8 engines)optional=False(iris, hpl, metek)TypeErrorrangeindex on iris, rainbow, furuno, datamet sweepsoptional_groups=True: station vars in/radar_parametersAlso:
reindex_angleFutureWarning is emitted once and points at the caller. Before, it fired once per sweep (14 times for one ODIM volume) and pointed inside xradar. The NEXRAD "Dropped incomplete sweeps" warnings and the CfRadial2 warnings also point at the caller.open_uf_datatreehas its signature and docstring back.fix_second_angleon rainbow and datamet,optionalon imd), and IRIS drops an unusedgroupparameter.backend_kwargsgiven to the NEXRAD and UF wrappers may contain decoders such asdecode_timesagain.Behaviour changes worth knowing
netcdf_engine.enginecollided with xarray's ownengineargument, soxr.open_datatree(f, engine="cfradial1", backend_kwargs={"engine": ...})could not work. The legacyopen_cfradial1_datatree(engine=...)andopen_cfradial2_datatree(engine=...)still acceptengine. ENH: add xarray-native open_datatree with engine= parameter #335 is not released yet, so no released API changes.xr.open_datatree, a keyword given both directly and inbackend_kwargstakes thebackend_kwargsvalue. Passing bothsite_coordsandsite_as_coordsraisesTypeError, as IMD already did.chunks={}, root variables are chunked too, because xarray chunks the whole tree.rangeindex like the other engines.xr.open_datatreemade xarray reopen the closed file for lazy reads, and with several handles on the same file netCDF4/HDF5 segfaulted intermittently, locally and once in CI. A CfRadial2 tree now holds no open file handle.Tests
New tests in
tests/io/test_backend_datatree.pycompare legacy output withxd.open_datatreefor every deprecated function. They also cover:chunks;backend_kwargs, including decoders andOptional;optional=False,optional_groupsandsite_as_coords;rangeindex andxdvsxrequality;reindex_anglewarning;netcdf_engineand CfRadial2close().Mutation checks (reverting each hunk on its own) confirmed a test fails for each fix.
pytest -n 4 --dist loadfile tests: 1085 passed, 18 skippedblack --check .,ruff check .pytest docs/notebooks: 25 passed. Two failed only becauseffmpeg(multiple-sweeps-into-volume-scan) andpyart(Gridding) are not installed locally.Not in this PR (listed in #481)
DataTree.close()does not close files for the other engines (same before ENH: add xarray-native open_datatree with engine= parameter #335)."sweep_1_0").site_coordshas no effect on most engines._ENGINE_REGISTRYduplicates the entry points.#472 touches
common.pytoo; whichever merges second resolves the conflict.