Skip to content

Commit 689d833

Browse files
committed
Technical review corrections
1 parent b63f80e commit 689d833

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
@@ -1614,17 +1614,31 @@ def _calculate_CFAD(
16141614
bin_edges: list[float]
16151615
The bin edges for the histogram. The bins need to be specified to
16161616
ensure consistency across the CFAD, otherwise it cannot be interpreted.
1617+
1618+
Notes
1619+
-----
1620+
Contour Frequency by Altitude Diagrams (CFADs) were first designed by
1621+
Yuter and Houze (1995)[YuterandHouze95]. They are calculated by binning the
1622+
data by altitude and then by variable bins (e.g. temperature). The variable
1623+
bins are then normalised by each altitude. This essenitally creates a
1624+
normalised frequency distribution for each altitude. These are then stacked
1625+
and combined in a single plot.
1626+
1627+
References
1628+
----------
1629+
.. [YuterandHouze95] Yuter S.E., and Houze, R.A. (1995) "Three-Dimensional
1630+
Kinematic and Microphysical Evolution of Florida Cumulonimbus. Part II:
1631+
Frequency Distributions of Vertical Velocity, Reflectivity, and
1632+
Differential Reflectivity" Monthly Weather Review, vol. 123, 1941-1963,
1633+
doi: 10.1175/1520-0493(1995)123<1941:TDKAME>2.0.CO;2
16171634
"""
16181635
# Setup empty array for containing the CFAD data.
16191636
CFAD_values = np.zeros(
16201637
(len(cube.coord(vertical_coordinate).points), len(bin_edges) - 1)
16211638
)
16221639

1623-
# Set iterator for CFAD values.
1624-
i = 0
1625-
16261640
# Calculate the CFAD as a histogram summing to one for each level.
1627-
for level_cube in cube.slices_over(vertical_coordinate):
1641+
for i, level_cube in enumerate(cube.slices_over(vertical_coordinate)):
16281642
# Note setting density to True does not produce the correct
16291643
# normalization for a CFAD, where each row must sum to one.
16301644
CFAD_values[i, :] = (
@@ -1633,8 +1647,7 @@ def _calculate_CFAD(
16331647
]
16341648
/ level_cube.data.size
16351649
)
1636-
i += 1
1637-
# calculate central points for bins
1650+
# Calculate central points for bins.
16381651
bins = (np.array(bin_edges[:-1]) + np.array(bin_edges[1:])) / 2.0
16391652
bin_bounds = np.array((bin_edges[:-1], bin_edges[1:])).T
16401653
# Now construct the coordinates for the cube.
@@ -1646,10 +1659,11 @@ def _calculate_CFAD(
16461659
CFAD = iris.cube.Cube(
16471660
CFAD_values,
16481661
dim_coords_and_dims=[(vert_coord, 0), (bin_coord, 1)],
1662+
long_name=f"{cube.name()}_cfad",
16491663
standard_name=cube.standard_name,
16501664
units="1",
16511665
)
1652-
CFAD.attributes["type"] = "Contour Frequency by Altitude Diagram (CFAD)"
1666+
CFAD.rename(f"{cube.name()}_cfad")
16531667
return CFAD
16541668

16551669

tests/conftest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,15 @@ def ensemble_cube_read_only():
233233
def ensemble_cube(ensemble_cube_read_only):
234234
"""Get ensemble cube to run tests on. It is safe to modify."""
235235
return ensemble_cube_read_only.copy()
236+
237+
238+
@pytest.fixture(scope="session")
239+
def xwind_read_only():
240+
"""Get regridded xwind to run tests on. It is NOT safe to modify."""
241+
return read.read_cube("tests/test_data/ageofair/aoa_in_rgd.nc", "x_wind")
242+
243+
244+
@pytest.fixture()
245+
def xwind(xwind_read_only):
246+
"""Get regridded xwind to run tests on. It is safe to modify."""
247+
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_plot.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
@@ -28,12 +29,6 @@
2829
from CSET.operators import collapse, plot, read
2930

3031

31-
@pytest.fixture()
32-
def xwind() -> iris.cube.Cube:
33-
"""Get regridded xwind to run tests on."""
34-
return iris.load_cube("tests/test_data/ageofair/aoa_in_rgd.nc", "x_wind")
35-
36-
3732
def test_check_single_cube():
3833
"""Conversion to a single cube, and rejection where not possible."""
3934
cube = iris.cube.Cube([0.0])
@@ -955,13 +950,11 @@ def test_calculate_CFAD(xwind):
955950
"""Test calculating a CFAD."""
956951
bins = np.array([-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50])
957952
calculated_CFAD = np.zeros((len(xwind.coord("pressure").points), len(bins) - 1))
958-
j = 0
959-
for level_cube in xwind.slices_over("pressure"):
953+
for j, level_cube in enumerate(xwind.slices_over("pressure")):
960954
calculated_CFAD[j, :] = (
961955
np.histogram(level_cube.data.reshape(level_cube.data.size), bins=bins)[0]
962956
/ level_cube.data.size
963957
)
964-
j += 1
965958
assert np.allclose(
966959
plot._calculate_CFAD(
967960
xwind, "pressure", [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50]
@@ -970,3 +963,25 @@ def test_calculate_CFAD(xwind):
970963
rtol=1e-06,
971964
atol=1e-02,
972965
)
966+
967+
968+
def test_name_CFAD(xwind):
969+
"""Test naming of CFAD cube."""
970+
expected_name = f"{xwind.name()}_cfad"
971+
assert (
972+
plot._calculate_CFAD(
973+
xwind, "pressure", [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50]
974+
).name()
975+
== expected_name
976+
)
977+
978+
979+
def test_units_CFAD(xwind):
980+
"""Test units of CFAD cube."""
981+
expected_units = cf_units.Unit("1")
982+
assert (
983+
plot._calculate_CFAD(
984+
xwind, "pressure", [-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50]
985+
).units
986+
== expected_units
987+
)

0 commit comments

Comments
 (0)