@@ -78,6 +78,41 @@ def processor():
7878 yield wl_processor
7979
8080
81+ @pytest .fixture
82+ def edge_case_processor ():
83+ """Fixture for a WarmingLevel processor with edge case warming level time DataFrames."""
84+ wl_processor = WarmingLevel (value = {"warming_levels" : [0.5 , 4.5 ]})
85+ wl_time_data = [
86+ [
87+ "GCM" ,
88+ "run" ,
89+ "scenario" ,
90+ "0.5" ,
91+ "4.5" ,
92+ ],
93+ [
94+ "ACCESS-CM2" ,
95+ "r1i1p1f1" ,
96+ "ssp585" ,
97+ "1955-01-01 00:00:00" ,
98+ "2095-01-01 00:00:00" ,
99+ ],
100+ ]
101+ wl_processor .warming_level_times = pd .DataFrame (
102+ wl_time_data [1 :], columns = wl_time_data [0 ]
103+ ).set_index (["GCM" , "run" , "scenario" ])
104+
105+ wl_time_idx_data = [
106+ ["time" , "ACCESS-CM2_r3i1p1f1_ssp585" ],
107+ ["2005-1" , 1.0 ],
108+ ]
109+ wl_processor .warming_level_times_idx = pd .DataFrame (
110+ wl_time_idx_data [1 :], columns = wl_time_idx_data [0 ]
111+ ).set_index ("time" )
112+
113+ yield wl_processor
114+
115+
81116@pytest .fixture
82117def full_processor ():
83118 """Fixture for a full WarmingLevel processor with default warming level time DataFrames."""
@@ -343,7 +378,7 @@ def test_empty_warming_level_times_error(self, mock_read_csv_file, processor):
343378 def test_execute_updates_context (self , request , full_processor ):
344379 """Test that execute updates context with warming level information."""
345380 test_result = request .getfixturevalue ("test_dataarray_dict" )
346- context = {}
381+ context = {"activity_id" : "WRF" }
347382 _ = full_processor .execute (result = test_result , context = context )
348383 assert full_processor .name in context [_NEW_ATTRS_KEY ][full_processor .name ]
349384 assert str (full_processor .value ) in context [_NEW_ATTRS_KEY ][full_processor .name ]
@@ -378,15 +413,15 @@ def test_execute_skips_warming_level(self, request, full_processor):
378413 match = f"No warming level data found" ,
379414 ),
380415 ):
381- ret = full_processor .execute (data , context = {})
416+ ret = full_processor .execute (data , context = {"activity_id" : "WRF" })
382417 for key in ret :
383418 assert len (ret [key ].warming_level ) == 2
384419 assert 5.8 not in ret [key ].warming_level .values
385420
386421 def test_execute_dims_correct (self , request , full_processor ):
387422 """Test that execute returns a dict with expected keys and types."""
388423 test_result = request .getfixturevalue ("test_dataarray_dict" )
389- ret = full_processor .execute (result = test_result , context = {})
424+ ret = full_processor .execute (result = test_result , context = {"activity_id" : "WRF" })
390425 for key in ret :
391426 assert isinstance (ret [key ], xr .Dataset )
392427 assert "warming_level" in ret [key ].dims
@@ -397,7 +432,7 @@ def test_execute_years_correct(self, request, full_processor):
397432 """Test that execute manipulates the data to have correct dims and years."""
398433 test_result = request .getfixturevalue ("test_dataarray_dict" )
399434 test_key = "WRF.UCLA.EC-Earth3.ssp370.day.d03"
400- ret = full_processor .execute (result = test_result , context = {})
435+ ret = full_processor .execute (result = test_result , context = {"activity_id" : "WRF" })
401436 ret_key = "WRF.UCLA.EC-Earth3.ssp370.day.d03.r1i1p1f1"
402437
403438 # Check that the warming_level coordinate matches the processor's warming_levels
@@ -417,3 +452,50 @@ def test_execute_years_correct(self, request, full_processor):
417452 assert isinstance (ret [ret_key ].centered_year .item (), int )
418453 # Check that the centered_year is within expected range
419454 assert 1981 <= ret [ret_key ].centered_year .item () <= 2100
455+
456+ def test_execute_loca_correct (self , request , full_processor ):
457+ """Test that execute works correctly for LOCA data."""
458+ test_result = request .getfixturevalue ("test_dataarray_dict_loca" )
459+ # The test fixture creates data for ACCESS-CM2 model
460+ test_key = "LOCA2.UCLA.ACCESS-CM2.ssp585.day.d03"
461+ ret = full_processor .execute (
462+ result = test_result , context = {"activity_id" : "LOCA2" }
463+ )
464+ ret_key = "LOCA2.UCLA.ACCESS-CM2.ssp585.day.d03.r1i1p1f1"
465+
466+ # Check that the warming_level coordinate matches the processor's warming_levels
467+ assert (
468+ ret [ret_key ].warming_level .values == full_processor .warming_levels
469+ ).all ()
470+ # Check the length of the time_delta dimension
471+ first_year = str (test_result [test_key ].isel (time = 0 ).time .dt .year .item ())
472+ # Find the number of elements in the first year of `ret[key]`
473+ timesteps_per_year = (
474+ test_result [test_key ].sel (time = slice (first_year , first_year )).time .size
475+ )
476+ assert (
477+ len (ret [ret_key ].time_delta )
478+ == timesteps_per_year * full_processor .warming_level_window * 2
479+ )
480+ assert isinstance (ret [ret_key ].centered_year .item (), int )
481+ # Check that the centered_year is within expected range
482+ assert 1981 <= ret [ret_key ].centered_year .item () <= 2100
483+
484+ def test_execute_edge_case_years (self , request , edge_case_processor ):
485+ """Test that execute handles edge case warming levels and years correctly."""
486+ test_result = request .getfixturevalue ("test_dataarray_dict_loca" )
487+ with pytest .warns (
488+ UserWarning ,
489+ ) as record :
490+ ret = edge_case_processor .execute (
491+ result = test_result , context = {"activity_id" : "LOCA2" }
492+ )
493+ assert len (record ) == 5
494+ assert ret == {}
495+ messages = [str (w .message ) for w in record ]
496+ expected_substrings = [
497+ "Incomplete warming level for LOCA2.UCLA.ACCESS-CM2.ssp585.day.d03.r1i1p1f1 at 0.5C" ,
498+ "Incomplete warming level for LOCA2.UCLA.ACCESS-CM2.ssp585.day.d03.r1i1p1f1 at 4.5C" ,
499+ ]
500+ for substr in expected_substrings :
501+ assert any (substr in msg for msg in messages ), f"Missing: { substr } "
0 commit comments