Skip to content

Commit f3cf528

Browse files
committed
Technical review corrections
1 parent 1ce9765 commit f3cf528

File tree

4 files changed

+57
-22
lines changed

4 files changed

+57
-22
lines changed

src/CSET/operators/plot.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,17 +1408,31 @@ def _calculate_CFAD(
14081408
bin_edges: list[float]
14091409
The bin edges for the histogram. The bins need to be specified to
14101410
ensure consistency across the CFAD, otherwise it cannot be interpreted.
1411+
1412+
Notes
1413+
-----
1414+
Contour Frequency by Altitude Diagrams (CFADs) were first designed by
1415+
Yuter and Houze (1995)[YuterandHouze95]. They are calculated by binning the
1416+
data by altitude and then by variable bins (e.g. temperature). The variable
1417+
bins are then normalised by each altitude. This essenitally creates a
1418+
normalised frequency distribution for each altitude. These are then stacked
1419+
and combined in a single plot.
1420+
1421+
References
1422+
----------
1423+
.. [YuterandHouze95] Yuter S.E., and Houze, R.A. (1995) "Three-Dimensional
1424+
Kinematic and Microphysical Evolution of Florida Cumulonimbus. Part II:
1425+
Frequency Distributions of Vertical Velocity, Reflectivity, and
1426+
Differential Reflectivity" Monthly Weather Review, vol. 123, 1941-1963,
1427+
doi: 10.1175/1520-0493(1995)123<1941:TDKAME>2.0.CO;2
14111428
"""
14121429
# Setup empty array for containing the CFAD data.
14131430
CFAD_values = np.zeros(
14141431
(len(cube.coord(vertical_coordinate).points), len(bin_edges) - 1)
14151432
)
14161433

1417-
# Set iterator for CFAD values.
1418-
i = 0
1419-
14201434
# Calculate the CFAD as a histogram summing to one for each level.
1421-
for level_cube in cube.slices_over(vertical_coordinate):
1435+
for i, level_cube in enumerate(cube.slices_over(vertical_coordinate)):
14221436
# Note setting density to True does not produce the correct
14231437
# normalization for a CFAD, where each row must sum to one.
14241438
CFAD_values[i, :] = (
@@ -1427,8 +1441,7 @@ def _calculate_CFAD(
14271441
]
14281442
/ level_cube.data.size
14291443
)
1430-
i += 1
1431-
# calculate central points for bins
1444+
# Calculate central points for bins.
14321445
bins = (np.array(bin_edges[:-1]) + np.array(bin_edges[1:])) / 2.0
14331446
bin_bounds = np.array((bin_edges[:-1], bin_edges[1:])).T
14341447
# Now construct the coordinates for the cube.
@@ -1440,10 +1453,11 @@ def _calculate_CFAD(
14401453
CFAD = iris.cube.Cube(
14411454
CFAD_values,
14421455
dim_coords_and_dims=[(vert_coord, 0), (bin_coord, 1)],
1456+
long_name=f"{cube.name()}_cfad",
14431457
standard_name=cube.standard_name,
14441458
units="1",
14451459
)
1446-
CFAD.attributes["type"] = "Contour Frequency by Altitude Diagram (CFAD)"
1460+
CFAD.rename(f"{cube.name()}_cfad")
14471461
return CFAD
14481462

14491463

tests/conftest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,15 @@ def ensemble_cube_read_only():
231231
def ensemble_cube(ensemble_cube_read_only):
232232
"""Get ensemble cube to run tests on. It is safe to modify."""
233233
return ensemble_cube_read_only.copy()
234+
235+
236+
@pytest.fixture(scope="session")
237+
def xwind_read_only():
238+
"""Get regridded xwind to run tests on. It is NOT safe to modify."""
239+
return read.read_cube("tests/test_data/ageofair/aoa_in_rgd.nc", "x_wind")
240+
241+
242+
@pytest.fixture()
243+
def xwind(xwind_read_only):
244+
"""Get regridded xwind to run tests on. It is safe to modify."""
245+
return xwind_read_only.copy()

tests/operators/test_ageofair.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@
2222
from CSET.operators import ageofair, read
2323

2424

25-
@pytest.fixture()
26-
def xwind() -> iris.cube.Cube:
27-
"""Get regridded xwind to run tests on."""
28-
return read.read_cube("tests/test_data/ageofair/aoa_in_rgd.nc", "x_wind")
29-
30-
3125
@pytest.fixture()
3226
def ywind() -> iris.cube.Cube:
3327
"""Get regridded ywind to run tests on."""

tests/operators/test_plots.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import logging
1919
from pathlib import Path
2020

21+
import cf_units
2122
import iris.coords
2223
import iris.cube
2324
import matplotlib as mpl
@@ -27,12 +28,6 @@
2728
from CSET.operators import collapse, plot
2829

2930

30-
@pytest.fixture()
31-
def xwind() -> iris.cube.Cube:
32-
"""Get regridded xwind to run tests on."""
33-
return iris.load_cube("tests/test_data/ageofair/aoa_in_rgd.nc", "x_wind")
34-
35-
3631
def test_check_single_cube():
3732
"""Conversion to a single cube, and rejection where not possible."""
3833
cube = iris.cube.Cube([0.0])
@@ -791,13 +786,11 @@ def test_calculate_CFAD(xwind):
791786
"""Test calculating a CFAD."""
792787
bins = np.array([-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50])
793788
calculated_CFAD = np.zeros((len(xwind.coord("pressure").points), len(bins) - 1))
794-
j = 0
795-
for level_cube in xwind.slices_over("pressure"):
789+
for j, level_cube in enumerate(xwind.slices_over("pressure")):
796790
calculated_CFAD[j, :] = (
797791
np.histogram(level_cube.data.reshape(level_cube.data.size), bins=bins)[0]
798792
/ level_cube.data.size
799793
)
800-
j += 1
801794
assert np.allclose(
802795
plot._calculate_CFAD(
803796
xwind, "pressure", [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50]
@@ -806,3 +799,25 @@ def test_calculate_CFAD(xwind):
806799
rtol=1e-06,
807800
atol=1e-02,
808801
)
802+
803+
804+
def test_name_CFAD(xwind):
805+
"""Test naming of CFAD cube."""
806+
expected_name = f"{xwind.name()}_cfad"
807+
assert (
808+
plot._calculate_CFAD(
809+
xwind, "pressure", [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50]
810+
).name()
811+
== expected_name
812+
)
813+
814+
815+
def test_units_CFAD(xwind):
816+
"""Test units of CFAD cube."""
817+
expected_units = cf_units.Unit("1")
818+
assert (
819+
plot._calculate_CFAD(
820+
xwind, "pressure", [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50]
821+
).units
822+
== expected_units
823+
)

0 commit comments

Comments
 (0)