Skip to content

Commit

Permalink
Tidy L3 CAMEL reader and add tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
simonrp84 committed Dec 28, 2024
1 parent b2765d4 commit ef634a7
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 3 deletions.
2 changes: 1 addition & 1 deletion satpy/etc/readers/camel_l3_nc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ file_types:
camel_emis_file:
file_reader: !!python/name:satpy.readers.camel_l3_nc.CAMELL3NCFileHandler
file_patterns:
- 'CAM5K30EM_emis_{start_time:%Y%m}_V{version:3s}.nc'
- 'CAM5K30EM_emis_{start_period:%Y%m}_V{version:3s}.nc'


datasets:
Expand Down
4 changes: 2 additions & 2 deletions satpy/readers/camel_l3_nc.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ def __init__(self, filename, filename_info, filetype_info):
raise ValueError("Only 0.05 degree grid data is supported.")
if self.nc.attrs["geospatial_lat_resolution"] != "0.05 degree grid ":
raise ValueError("Only 0.05 degree grid data is supported.")
if self.nc.sizes["spectra"] != 13:
raise ValueError("Only CAMEL files with 13 spectral bands are supported.")

self.nlines = self.nc.sizes["latitude"]
self.ncols = self.nc.sizes["longitude"]
Expand Down Expand Up @@ -82,6 +80,8 @@ def get_dataset(self, key, info):

# For the emissivity there are multiple bands, so we need to select the correct one
if var == "camel_emis":
if info["band_id"] >= variable.shape[2]:
raise ValueError("Band id requested is larger than dataset.")
variable = variable[:, :, info["band_id"]]

# Rename the latitude and longitude dimensions to x and y
Expand Down
133 changes: 133 additions & 0 deletions satpy/tests/reader_tests/test_camel_l3_nc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"""Tests for the CAMEL L3 netCDF reader."""

import datetime as dt

import numpy as np
import pytest
import xarray as xr

from satpy.readers.camel_l3_nc import CAMELL3NCFileHandler
from satpy.tests.utils import make_dataid

rng = np.random.default_rng()
ndvi_data = rng.integers(0, 1000, (3600, 7200), dtype=np.int16)
emis_data = rng.integers(0, 1000, (3600, 7200, 5), dtype=np.int16)

lon_data = np.arange(-180, 180, 0.05)
lat_data = np.arange(-90, 90, 0.05)

start_time = dt.datetime(2023, 8, 1, 0, 0, 0)
end_time = dt.datetime(2023, 9, 1, 0, 0, 0)

fill_val = -999
scale_val = 0.001

dimensions = {"longitude": 7200, "latitude": 3600, "spectra": 13}

exp_ext = (-180.0, -90.0, 180.0, 90.0)

global_attrs = {"time_coverage_start": start_time.strftime("%Y-%m-%d %H:%M:%SZ"),
"time_coverage_end": end_time.strftime("%Y-%m-%d %H:%M:%SZ"),
"geospatial_lon_resolution": "0.05 degree grid ",
"geospatial_lat_resolution": "0.05 degree grid ",
}

bad_attrs1 = global_attrs.copy()
bad_attrs1["geospatial_lon_resolution"] = "0.1 degree grid "
bad_attrs2 = global_attrs.copy()
bad_attrs2["geospatial_lat_resolution"] = "0.1 degree grid "


def _make_ds(the_attrs, tmp_factory):
"""Make a dataset for use in tests."""
fname = f'{tmp_factory.mktemp("data")}/CAM5K30EM_emis_202308_V003.nc'
ds = xr.Dataset({"aster_ndvi": (["Rows", "Columns"], ndvi_data),
"camel_emis": (["latitude", "longitude", "spectra"], emis_data)},
coords={"latitude": (["Rows"], lat_data),
"longitude": (["Columns"], lon_data)},
attrs=the_attrs)
ds.to_netcdf(fname)
return fname


def camel_l3_filehandler(fname):
"""Instantiate a Filehandler."""
fileinfo = {"start_period": "202308",
"version": "003"}
filetype = None
fh = CAMELL3NCFileHandler(fname, fileinfo, filetype)
return fh


@pytest.fixture(scope="session")
def camel_filename(tmp_path_factory):
"""Create a fake camel l3 file."""
return _make_ds(global_attrs, tmp_path_factory)


@pytest.fixture(scope="session")
def camel_filename_bad1(tmp_path_factory):
"""Create a fake camel l3 file."""
return _make_ds(bad_attrs1, tmp_path_factory)


@pytest.fixture(scope="session")
def camel_filename_bad2(tmp_path_factory):
"""Create a fake camel l3 file."""
return _make_ds(bad_attrs2, tmp_path_factory)


def test_startend(camel_filename):
"""Test start and end times are set correctly."""
fh = camel_l3_filehandler(camel_filename)
assert fh.start_time == start_time
assert fh.end_time == end_time


def test_camel_l3_area_def(camel_filename, caplog):
"""Test reader handles area definition correctly."""
ps = "+proj=longlat +datum=WGS84 +no_defs +type=crs"

# Check case where input data is correct size.
fh = camel_l3_filehandler(camel_filename)
ndvi_id = make_dataid(name="aster_ndvi")
area_def = fh.get_area_def(ndvi_id)
assert area_def.width == dimensions["longitude"]
assert area_def.height == dimensions["latitude"]
assert np.allclose(area_def.area_extent, exp_ext)

assert area_def.proj4_string == ps


def test_bad_longitude(camel_filename_bad1):
"""Check case where longitude grid is not correct."""
with pytest.raises(ValueError, match="Only 0.05 degree grid data is supported."):
camel_l3_filehandler(camel_filename_bad1)


def test_bad_latitude(camel_filename_bad2):
"""Check case where latitude grid is not correct."""
with pytest.raises(ValueError, match="Only 0.05 degree grid data is supported."):
camel_l3_filehandler(camel_filename_bad2)


def test_load_ndvi_data(camel_filename):
"""Test that data is loaded successfully."""
fh = camel_l3_filehandler(camel_filename)
ndvi_id = make_dataid(name="aster_ndvi")
ndvi = fh.get_dataset(ndvi_id, {"file_key": "aster_ndvi"})
assert np.allclose(ndvi.data, ndvi_data)


def test_load_emis_data(camel_filename):
"""Test that data is loaded successfully."""
fh = camel_l3_filehandler(camel_filename)
emis_id = make_dataid(name="camel_emis")

# This is correct data
emis = fh.get_dataset(emis_id, {"file_key": "camel_emis", "band_id": 2})
assert np.allclose(emis.data, emis_data[:, :, 2])

# This will fail as we are requesting a band too high data
with pytest.raises(ValueError, match="Band id requested is larger than dataset."):
fh.get_dataset(emis_id, {"file_key": "camel_emis", "band_id": 12})

0 comments on commit ef634a7

Please sign in to comment.