|
| 1 | +""" |
| 2 | +Test the Session.read_data method. |
| 3 | +""" |
| 4 | + |
| 5 | +from pathlib import Path |
| 6 | + |
| 7 | +import pandas as pd |
| 8 | +import pytest |
| 9 | +import xarray as xr |
| 10 | +from pygmt.clib import Session |
| 11 | +from pygmt.exceptions import GMTCLibError |
| 12 | +from pygmt.helpers import GMTTempFile |
| 13 | +from pygmt.io import load_dataarray |
| 14 | +from pygmt.src import which |
| 15 | + |
| 16 | +try: |
| 17 | + import rioxarray # noqa: F401 |
| 18 | + |
| 19 | + _HAS_RIOXARRAY = True |
| 20 | +except ImportError: |
| 21 | + _HAS_RIOXARRAY = False |
| 22 | + |
| 23 | + |
| 24 | +@pytest.fixture(scope="module", name="expected_xrgrid") |
| 25 | +def fixture_expected_xrgrid(): |
| 26 | + """ |
| 27 | + The expected xr.DataArray object for the static_earth_relief.nc file. |
| 28 | + """ |
| 29 | + return load_dataarray(which("@static_earth_relief.nc")) |
| 30 | + |
| 31 | + |
| 32 | +def test_clib_read_data_dataset(): |
| 33 | + """ |
| 34 | + Test the Session.read_data method for datasets. |
| 35 | + """ |
| 36 | + with GMTTempFile(suffix=".txt") as tmpfile: |
| 37 | + # Prepare the sample data file |
| 38 | + with Path(tmpfile.name).open(mode="w", encoding="utf-8") as fp: |
| 39 | + print("# x y z name", file=fp) |
| 40 | + print(">", file=fp) |
| 41 | + print("1.0 2.0 3.0 TEXT1 TEXT23", file=fp) |
| 42 | + print("4.0 5.0 6.0 TEXT4 TEXT567", file=fp) |
| 43 | + print(">", file=fp) |
| 44 | + print("7.0 8.0 9.0 TEXT8 TEXT90", file=fp) |
| 45 | + print("10.0 11.0 12.0 TEXT123 TEXT456789", file=fp) |
| 46 | + |
| 47 | + with Session() as lib: |
| 48 | + ds = lib.read_data(tmpfile.name, kind="dataset").contents |
| 49 | + df = ds.to_dataframe(header=0) |
| 50 | + expected_df = pd.DataFrame( |
| 51 | + data={ |
| 52 | + "x": [1.0, 4.0, 7.0, 10.0], |
| 53 | + "y": [2.0, 5.0, 8.0, 11.0], |
| 54 | + "z": [3.0, 6.0, 9.0, 12.0], |
| 55 | + "name": pd.Series( |
| 56 | + [ |
| 57 | + "TEXT1 TEXT23", |
| 58 | + "TEXT4 TEXT567", |
| 59 | + "TEXT8 TEXT90", |
| 60 | + "TEXT123 TEXT456789", |
| 61 | + ], |
| 62 | + dtype=pd.StringDtype(), |
| 63 | + ), |
| 64 | + } |
| 65 | + ) |
| 66 | + pd.testing.assert_frame_equal(df, expected_df) |
| 67 | + |
| 68 | + |
| 69 | +def test_clib_read_data_grid(expected_xrgrid): |
| 70 | + """ |
| 71 | + Test the Session.read_data method for grids. |
| 72 | + """ |
| 73 | + with Session() as lib: |
| 74 | + grid = lib.read_data("@static_earth_relief.nc", kind="grid").contents |
| 75 | + xrgrid = grid.to_dataarray() |
| 76 | + xr.testing.assert_equal(xrgrid, expected_xrgrid) |
| 77 | + assert grid.header.contents.n_bands == 1 # Explicitly check n_bands |
| 78 | + |
| 79 | + |
| 80 | +def test_clib_read_data_grid_two_steps(expected_xrgrid): |
| 81 | + """ |
| 82 | + Test the Session.read_data method for grids in two steps, first reading the header |
| 83 | + and then the data. |
| 84 | + """ |
| 85 | + infile = "@static_earth_relief.nc" |
| 86 | + with Session() as lib: |
| 87 | + # Read the header first |
| 88 | + data_ptr = lib.read_data(infile, kind="grid", mode="GMT_CONTAINER_ONLY") |
| 89 | + grid = data_ptr.contents |
| 90 | + header = grid.header.contents |
| 91 | + assert header.n_rows == 14 |
| 92 | + assert header.n_columns == 8 |
| 93 | + assert header.wesn[:] == [-55.0, -47.0, -24.0, -10.0] |
| 94 | + assert header.z_min == 190.0 |
| 95 | + assert header.z_max == 981.0 |
| 96 | + assert header.n_bands == 1 # Explicitly check n_bands |
| 97 | + assert not grid.data # The data is not read yet |
| 98 | + |
| 99 | + # Read the data |
| 100 | + lib.read_data(infile, kind="grid", mode="GMT_DATA_ONLY", data=data_ptr) |
| 101 | + xrgrid = data_ptr.contents.to_dataarray() |
| 102 | + xr.testing.assert_equal(xrgrid, expected_xrgrid) |
| 103 | + |
| 104 | + |
| 105 | +def test_clib_read_data_grid_actual_image(): |
| 106 | + """ |
| 107 | + Test the Session.read_data method for grid, but actually the file is an image. |
| 108 | + """ |
| 109 | + with Session() as lib: |
| 110 | + data_ptr = lib.read_data( |
| 111 | + "@earth_day_01d_p", kind="grid", mode="GMT_CONTAINER_AND_DATA" |
| 112 | + ) |
| 113 | + image = data_ptr.contents |
| 114 | + header = image.header.contents |
| 115 | + assert header.n_rows == 180 |
| 116 | + assert header.n_columns == 360 |
| 117 | + assert header.wesn[:] == [-180.0, 180.0, -90.0, 90.0] |
| 118 | + # Explicitly check n_bands. Only one band is read for 3-band images. |
| 119 | + assert header.n_bands == 1 |
| 120 | + |
| 121 | + if _HAS_RIOXARRAY: # Full check if rioxarray is installed. |
| 122 | + xrimage = image.to_dataarray() |
| 123 | + expected_xrimage = xr.open_dataarray( |
| 124 | + which("@earth_day_01d_p"), engine="rasterio" |
| 125 | + ) |
| 126 | + assert expected_xrimage.band.size == 3 # 3-band image. |
| 127 | + xr.testing.assert_equal( |
| 128 | + xrimage, |
| 129 | + expected_xrimage.isel(band=0) |
| 130 | + .drop_vars(["band", "spatial_ref"]) |
| 131 | + .sortby("y"), |
| 132 | + ) |
| 133 | + |
| 134 | + |
| 135 | +def test_clib_read_data_fails(): |
| 136 | + """ |
| 137 | + Test that the Session.read_data method raises an exception if there are errors. |
| 138 | + """ |
| 139 | + with Session() as lib: |
| 140 | + with pytest.raises(GMTCLibError): |
| 141 | + lib.read_data("not-exsits.txt", kind="dataset") |
0 commit comments