Skip to content

Commit 0f57800

Browse files
Merge pull request #81 from sadielbartholomew/update-unstructured-examples
Update unstructured grid page examples, add them to test suite
2 parents bcd6329 + 841f5e1 commit 0f57800

File tree

2 files changed

+175
-32
lines changed

2 files changed

+175
-32
lines changed

cfplot/test/test_examples.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
import matplotlib.testing.compare as mpl_compare
2323

24+
import cartopy.crs as ccrs
25+
2426
import cfplot as cfp
2527
import cf
2628

@@ -1323,6 +1325,141 @@ def test_example_43(self):
13231325
# https://ncas-cms.github.io/cf-plot/build/unstructured.html#unstructured)
13241326

13251327

1328+
class UnnumberedExamplesTest(unittest.TestCase):
1329+
"""Run all other documentation examples and compare to reference plots."""
1330+
1331+
data_dir = DATA_DIR
1332+
save_gen_dir = TEST_GEN_DIR
1333+
ref_dir = TEST_REF_DIR
1334+
test_id = None
1335+
1336+
def setUp(self):
1337+
"""Preparations called immediately before each test method."""
1338+
# Get a filename fname with the ID of test_example_X component X
1339+
test_method_name = unittest.TestCase.id(self).split(".")[-1]
1340+
self.test_id = test_method_name.rsplit("test_example_")[1]
1341+
fname = f"{self.save_gen_dir}/" f"gen_fig_{self.test_id}.png"
1342+
cfp.setvars(
1343+
file=fname,
1344+
viewer="matplotlib",
1345+
)
1346+
1347+
def tearDown(self):
1348+
"""Preparations called immediately after each test method."""
1349+
cfp.reset()
1350+
1351+
# @compare_plot_results # SLB TODO add expected plot
1352+
def test_example_unstructured_lfric_1(self):
1353+
"""Test example for unstructured grids: LFRic example 1."""
1354+
f = cf.read("cfplot_data/lfric_initial.nc")
1355+
1356+
# Select the relevant fields for the objects required for the plot,
1357+
# taking the air potential temperature as a variable to choose to view.
1358+
pot = f.select_by_identity("air_potential_temperature")[0]
1359+
lats = f.select_by_identity("latitude")[0]
1360+
lons = f.select_by_identity("longitude")[0]
1361+
faces = f.select_by_identity("cf_role=face_edge_connectivity")[0]
1362+
1363+
# Reduce the variable to match the shapes
1364+
pot = pot[4,:]
1365+
1366+
cfp.levs(240, 310, 5)
1367+
1368+
cfp.con(
1369+
f=pot, face_lons=lons, face_lats=lats,
1370+
face_connectivity=faces, lines=False
1371+
)
1372+
1373+
# @compare_plot_results # SLB TODO add expected plot
1374+
def test_example_unstructured_lfric_2(self):
1375+
"""Test example for unstructured grids: LFRic example 2."""
1376+
f = cf.read("cfplot_data/lfric_initial.nc")
1377+
1378+
# Select the relevant fields for the objects required for the plot,
1379+
# taking the air potential temperature as a variable to choose to view.
1380+
pot = f.select_by_identity("air_potential_temperature")[0]
1381+
lats = f.select_by_identity("latitude")[0]
1382+
lons = f.select_by_identity("longitude")[0]
1383+
faces = f.select_by_identity("cf_role=face_edge_connectivity")[0]
1384+
1385+
# Reduce the variable to match the shapes
1386+
pot = pot[4,:]
1387+
1388+
cfp.levs(240, 310, 5)
1389+
1390+
# This time set the projection to a polar one for a different view
1391+
cfp.mapset(proj="npstere")
1392+
cfp.con(
1393+
f=pot, face_lons=lons,
1394+
face_lats=lats, face_connectivity=faces, lines=False
1395+
)
1396+
1397+
# @compare_plot_results # SLB TODO add expected plot
1398+
def test_example_unstructured_lfric_3(self):
1399+
"""Test example for unstructured grids: LFRic example 3."""
1400+
f = cf.read("cfplot_data/lfric_initial.nc")
1401+
pot = f.select_by_identity("air_potential_temperature")[0]
1402+
1403+
g = pot[0, :]
1404+
cfp.con(g, lines=False)
1405+
1406+
@unittest.expectedFailure # suspected cf-plot bug, needs investigating
1407+
def test_example_unstructured_orca_1(self):
1408+
"""Test example for unstructured grids: ORCA grid example 1."""
1409+
# NOTE: this is taken from the 'unstructured.rst/html' page, but
1410+
# is very similar to 'test_example_26', so coordinate with that.
1411+
f = cf.read("cfplot_data/orca2.nc")
1412+
1413+
# Get an Orca grid and flatten the arrays
1414+
lons = f.select_by_identity("ncvar%longitude")[0]
1415+
lats = f.select_by_identity("ncvar%latitude")[0]
1416+
temp = f.select_by_identity("ncvar%sst")[0]
1417+
1418+
lons.flatten(inplace=True)
1419+
lats.flatten(inplace=True)
1420+
temp.flatten(inplace=True)
1421+
1422+
cfp.con(x=lons, y=lats, f=temp, ptype=1)
1423+
1424+
@unittest.expectedFailure # text input based, needs investigating
1425+
def test_example_unstructured_station_data_1(self):
1426+
"""Test example for unstructured grids: station data example 1."""
1427+
# NOTE: this is taken from the 'unstructured.rst/html' page, but
1428+
# is very similar to 'test_example_24/25', so coordinate with that.
1429+
1430+
# Part 1: docs title 'Station data'
1431+
1432+
# Arrays for data
1433+
lons=[]
1434+
lats=[]
1435+
pressure=[]
1436+
temp=[]
1437+
1438+
# Read data and make the contour plot
1439+
f = open('cfplot_data/synop_data.txt')
1440+
lines = f.readlines()
1441+
for line in lines:
1442+
mysplit=line.split()
1443+
lons=np.append(lons, float(mysplit[1]))
1444+
lats=np.append(lats, float(mysplit[2]))
1445+
pressure=np.append(pressure, float(mysplit[3]))
1446+
temp=np.append(temp, float(mysplit[4]))
1447+
1448+
cfp.con(
1449+
x=lons, y=lats, f=temp, ptype=1, colorbar_orientation='vertical')
1450+
1451+
# Part 2: docs title 'Station data - check of data values'
1452+
cfp.gopen()
1453+
for i in np.arange(len(lines)):
1454+
cfp.plotvars.mymap.text(
1455+
float(lons[i]), float(lats[i]), str(temp[i]),
1456+
horizontalalignment='center',verticalalignment='center',
1457+
transform=ccrs.PlateCarree()
1458+
)
1459+
1460+
cfp.gclose()
1461+
1462+
13261463
if __name__ == "__main__":
13271464
print("==================\n" "Regression testing\n" "==================\n")
13281465
cov = coverage.Coverage()

docs/source/unstructured.rst

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,17 @@ netCDF and NumPy arrays of unstructured data.
2222

2323
::
2424

25-
import cf
26-
import cfplot as cfp
27-
f=cf.read('cfplot_data/lfric_initial.nc')
25+
f = cf.read("cfplot_data/lfric_initial.nc")
2826

29-
pot=f[33][4,:]
30-
lons = f[12]
31-
lats = f[13]
32-
faces = f[11]
27+
# Select the relevant fields for the objects required for the plot,
28+
# taking the air potential temperature as a variable to choose to view.
29+
pot = f.select_by_identity("air_potential_temperature")[0]
30+
lats = f.select_by_identity("latitude")[0]
31+
lons = f.select_by_identity("longitude")[0]
32+
faces = f.select_by_identity("cf_role=face_edge_connectivity")[0]
33+
34+
# Reduce the variable to match the shapes
35+
pot = pot[4,:]
3336

3437
cfp.levs(240, 310, 5)
3538

@@ -45,17 +48,22 @@ Here we identify the fields in the data that have the longitudes and latitudes f
4548

4649
::
4750

48-
import cf
49-
import cfplot as cfp
50-
f=cf.read('cfplot_data/lfric_initial.nc')
51+
f = cf.read("cfplot_data/lfric_initial.nc")
52+
53+
# Select the relevant fields for the objects required for the plot,
54+
# taking the air potential temperature as a variable to choose to view.
55+
pot = f.select_by_identity("air_potential_temperature")[0]
56+
lats = f.select_by_identity("latitude")[0]
57+
lons = f.select_by_identity("longitude")[0]
58+
faces = f.select_by_identity("cf_role=face_edge_connectivity")[0]
5159

52-
pot=f[33][4,:]
53-
lons = f[12]
54-
lats = f[13]
55-
faces = f[11]
60+
# Reduce the variable to match the shapes
61+
pot = pot[4,:]
5662

5763
cfp.levs(240, 310, 5)
58-
cfp.mapset(proj='npstere')
64+
65+
# This time set the projection to a polar one for a different view
66+
cfp.mapset(proj="npstere")
5967
cfp.con(f=pot, face_lons=lons, face_lats=lats, face_connectivity=faces, lines=False)
6068

6169

@@ -67,12 +75,12 @@ Here the projection is changed to show the north pole.
6775

6876
::
6977

70-
import cf
71-
import cfplot as cfp
72-
f=cf.read('cfplot_data/lfric_initial.nc')[33]
73-
g=f[0,:]
78+
f = cf.read("cfplot_data/lfric_initial.nc")
79+
pot = f.select_by_identity("air_potential_temperature")[0]
80+
81+
g = pot[0, :]
82+
cfp.con(g, lines=False)
7483

75-
cfp.con(g, lines=False )
7684

7785
The data in the field has auxiliary longitudes and latitudes that can be contoured as normal. Internally in cf-plot this is made using the Matplotlib tricontourf command as the data points are spatially irregular.
7886

@@ -85,23 +93,21 @@ Orca2 grid
8593

8694
::
8795

88-
import cf
89-
import cfplot as cfp
90-
import numpy as np
91-
from netCDF4 import Dataset as ncfile
96+
f = cf.read("cfplot_data/orca2.nc")
9297

93-
#Get an Orca grid and flatten the arrays
94-
nc = ncfile('cfplot_data/orca2.nc')
95-
lons=np.array(nc.variables['longitude'])
96-
lats=np.array(nc.variables['latitude'])
97-
temp=np.array(nc.variables['sst'])
98-
lons=lons.flatten()
99-
lats=lats.flatten()
100-
temp=temp.flatten()
98+
# Get an Orca grid and flatten the arrays
99+
lons = f.select_by_identity("ncvar%longitude")[0]
100+
lats = f.select_by_identity("ncvar%latitude")[0]
101+
temp = f.select_by_identity("ncvar%sst")[0]
101102

103+
lons.flatten(inplace=True)
104+
lats.flatten(inplace=True)
105+
temp.flatten(inplace=True)
106+
102107
cfp.con(x=lons, y=lats, f=temp, ptype=1)
103108

104109

110+
105111
The ORCA2 grid is an ocean grid with missing values over the land points. The data in this file is from before the UGRID convention was started and has no face connectivity or corner coordinates. In this case we can only plot a normal contour plot.
106112

107113

0 commit comments

Comments
 (0)