|
| 1 | +import netCDF4 |
| 2 | +import numpy as np |
1 | 3 | import matplotlib |
2 | 4 | import pytest |
3 | 5 |
|
@@ -72,3 +74,67 @@ def pytest_collection_modifyitems(config, items): |
72 | 74 | for item in items: |
73 | 75 | if "slow" in item.keywords: |
74 | 76 | item.add_marker(skip_slow) |
| 77 | + |
| 78 | + |
| 79 | +@pytest.fixture |
| 80 | +def merra2_file_path(tmp_path): # pylint: disable=too-many-statements |
| 81 | + """ |
| 82 | + Generates a temporary NetCDF file that STRICTLY mimics the structure of a |
| 83 | + NASA MERRA-2 'inst3_3d_asm_Np' file (Assimilated Meteorological Fields) |
| 84 | + because MERRA-2 files are too large. |
| 85 | +
|
| 86 | + """ |
| 87 | + file_path = tmp_path / "MERRA2_300.inst3_3d_asm_Np.20230620.nc4" |
| 88 | + |
| 89 | + with netCDF4.Dataset(file_path, "w", format="NETCDF4") as nc: |
| 90 | + # Define Dimensions |
| 91 | + nc.createDimension("lon", 5) |
| 92 | + nc.createDimension("lat", 5) |
| 93 | + nc.createDimension("lev", 5) |
| 94 | + nc.createDimension("time", None) |
| 95 | + |
| 96 | + # Define Coordinates |
| 97 | + lon = nc.createVariable("lon", "f8", ("lon",)) |
| 98 | + lon.units = "degrees_east" |
| 99 | + lon[:] = np.linspace(-180, 180, 5) |
| 100 | + |
| 101 | + lat = nc.createVariable("lat", "f8", ("lat",)) |
| 102 | + lat.units = "degrees_north" |
| 103 | + lat[:] = np.linspace(-90, 90, 5) |
| 104 | + |
| 105 | + lev = nc.createVariable("lev", "f8", ("lev",)) |
| 106 | + lev.units = "hPa" |
| 107 | + lev[:] = np.linspace(1000, 100, 5) |
| 108 | + |
| 109 | + time = nc.createVariable("time", "i4", ("time",)) |
| 110 | + time.units = "minutes since 2023-06-20 00:00:00" |
| 111 | + time[:] = [720] |
| 112 | + |
| 113 | + # Define Data Variables |
| 114 | + # NetCDF names are uppercase ("T") to match NASA specs. |
| 115 | + |
| 116 | + t_var = nc.createVariable("T", "f4", ("time", "lev", "lat", "lon")) |
| 117 | + t_var.units = "K" |
| 118 | + t_var[:] = np.full((1, 5, 5, 5), 300.0) |
| 119 | + |
| 120 | + u_var = nc.createVariable("U", "f4", ("time", "lev", "lat", "lon")) |
| 121 | + u_var.units = "m s-1" |
| 122 | + u_var[:] = np.full((1, 5, 5, 5), 10.0) |
| 123 | + |
| 124 | + v_var = nc.createVariable("V", "f4", ("time", "lev", "lat", "lon")) |
| 125 | + v_var.units = "m s-1" |
| 126 | + v_var[:] = np.full((1, 5, 5, 5), 5.0) |
| 127 | + |
| 128 | + h_var = nc.createVariable("H", "f4", ("time", "lev", "lat", "lon")) |
| 129 | + h_var.units = "m" |
| 130 | + h_var[:] = np.linspace(0, 10000, 5).reshape(1, 5, 1, 1) * np.ones((1, 5, 5, 5)) |
| 131 | + |
| 132 | + # PHIS: Surface Geopotential Height [m2 s-2] |
| 133 | + phis = nc.createVariable("PHIS", "f4", ("time", "lat", "lon")) |
| 134 | + phis.units = "m2 s-2" |
| 135 | + |
| 136 | + # We set PHIS to 9806.65 (Energy). |
| 137 | + # We expect the code to divide by ~9.8 and get ~1000.0 (Height). |
| 138 | + phis[:] = np.full((1, 5, 5), 9806.65) |
| 139 | + |
| 140 | + return str(file_path) |
0 commit comments