diff --git a/src/access_moppy/atmosphere.py b/src/access_moppy/atmosphere.py index 9686292e..1a21a7e6 100644 --- a/src/access_moppy/atmosphere.py +++ b/src/access_moppy/atmosphere.py @@ -230,6 +230,11 @@ def select_and_process_variables(self): if dim not in transpose_order and self.ds[self.cmor_name][dim].size == 1: self.ds[self.cmor_name] = self.ds[self.cmor_name].squeeze(dim) + if "time" in transpose_order: + transpose_order = ["time"] + [ + dim for dim in transpose_order if dim != "time" + ] + self.ds[self.cmor_name] = self.ds[self.cmor_name].transpose(*transpose_order) def update_attributes(self): diff --git a/tests/unit/test_sea_ice.py b/tests/unit/test_sea_ice.py new file mode 100644 index 00000000..1d015b3e --- /dev/null +++ b/tests/unit/test_sea_ice.py @@ -0,0 +1,75 @@ +from unittest.mock import Mock, patch + +import numpy as np +import pandas as pd +import pytest +import xarray as xr + +from access_moppy.sea_ice import SeaIce_CMORiser + + +class TestSeaIceCMORiser: + """Unit tests for sea-ice CMORisation.""" + + @pytest.fixture + def mock_vocab(self): + """Mock vocabulary for sea-ice tests.""" + vocab = Mock() + vocab.source_id = "ACCESS-ESM1.6" + vocab.variable = {"units": "1", "type": "real"} + vocab._get_nominal_resolution = Mock(return_value="1deg") + vocab._get_axes = Mock(return_value=({}, {})) + vocab._get_required_bounds_variables = Mock(return_value=({}, {})) + return vocab + + @pytest.fixture + def mock_mapping(self): + """Mock variable mapping for sea-ice tests.""" + return { + "siconc": { + "model_variables": ["ice_conc"], + "calculation": {"type": "direct"}, + } + } + + @pytest.fixture + def mock_seaice_dataset(self): + """Create a mock sea-ice dataset with time not in first position.""" + time = pd.date_range("2000-01-01", periods=3, freq="ME") + nj = np.arange(2) + ni = np.arange(4) + + return xr.Dataset( + data_vars={ + "ice_conc": ( + ["nj", "time", "ni"], + np.random.random((2, 3, 4)), + {"coordinates": "ULON ULAT", "units": "1"}, + ) + }, + coords={ + "time": ("time", time), + "nj": ("nj", nj), + "ni": ("ni", ni), + }, + ) + + @pytest.mark.unit + def test_select_and_process_variables_moves_time_to_first_dimension( + self, mock_vocab, mock_mapping, mock_seaice_dataset, temp_dir + ): + """Ensure the processed sea-ice variable has time as the leading dimension.""" + with patch("access_moppy.sea_ice.Supergrid"): + with patch("access_moppy.ocean.CMORiser.load_dataset", return_value=None): + cmoriser = SeaIce_CMORiser( + input_paths=["test.nc"], + output_path=str(temp_dir), + compound_name="SImon.siconc", + vocab=mock_vocab, + variable_mapping=mock_mapping, + ) + cmoriser.ds = mock_seaice_dataset + + cmoriser.select_and_process_variables() + + assert cmoriser.ds[cmoriser.cmor_name].dims == ("time", "j", "i")