Skip to content

Commit 331c427

Browse files
authored
Merge pull request #1100 from UXARRAY/rajeeja/issue_1098
Convert unittest to pytest
2 parents 7760ab6 + 41a4386 commit 331c427

29 files changed

+4368
-6041
lines changed

test/test_api.py

Lines changed: 81 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import os
2-
from unittest import TestCase
32
from pathlib import Path
43
import numpy.testing as nt
5-
64
import uxarray as ux
7-
import xarray as xr
85
import numpy as np
6+
import pytest
97

108
try:
119
import constants
@@ -14,126 +12,111 @@
1412

1513
current_path = Path(os.path.dirname(os.path.realpath(__file__)))
1614

15+
geoflow_data_path = current_path / "meshfiles" / "ugrid" / "geoflow-small"
16+
gridfile_geoflow = current_path / "meshfiles" / "ugrid" / "geoflow-small" / "grid.nc"
17+
geoflow_data_v1 = geoflow_data_path / "v1.nc"
18+
geoflow_data_v2 = geoflow_data_path / "v2.nc"
19+
geoflow_data_v3 = geoflow_data_path / "v3.nc"
1720

18-
class TestAPI(TestCase):
19-
geoflow_data_path = current_path / "meshfiles" / "ugrid" / "geoflow-small"
20-
gridfile_geoflow = current_path / "meshfiles" / "ugrid" / "geoflow-small" / "grid.nc"
21-
geoflow_data_v1 = geoflow_data_path / "v1.nc"
22-
geoflow_data_v2 = geoflow_data_path / "v2.nc"
23-
geoflow_data_v3 = geoflow_data_path / "v3.nc"
24-
25-
gridfile_ne30 = current_path / "meshfiles" / "ugrid" / "outCSne30" / "outCSne30.ug"
26-
dsfile_var2_ne30 = current_path / "meshfiles" / "ugrid" / "outCSne30" / "outCSne30_var2.nc"
27-
dsfiles_mf_ne30 = str(
28-
current_path) + "/meshfiles/ugrid/outCSne30/outCSne30_*.nc"
29-
30-
def test_open_geoflow_dataset(self):
31-
"""Loads a single dataset with its grid topology file using uxarray's
32-
open_dataset call."""
21+
gridfile_ne30 = current_path / "meshfiles" / "ugrid" / "outCSne30" / "outCSne30.ug"
22+
dsfile_var2_ne30 = current_path / "meshfiles" / "ugrid" / "outCSne30" / "outCSne30_var2.nc"
23+
dsfiles_mf_ne30 = str(current_path) + "/meshfiles/ugrid/outCSne30/outCSne30_*.nc"
3324

34-
# Paths to Data Variable files
35-
data_paths = [
36-
self.geoflow_data_v1, self.geoflow_data_v2, self.geoflow_data_v3
37-
]
25+
def test_open_geoflow_dataset():
26+
"""Loads a single dataset with its grid topology file using uxarray's
27+
open_dataset call."""
3828

39-
uxds_v1 = ux.open_dataset(self.gridfile_geoflow, data_paths[0])
29+
# Paths to Data Variable files
30+
data_paths = [
31+
geoflow_data_v1, geoflow_data_v2, geoflow_data_v3
32+
]
4033

41-
# Ideally uxds_v1.uxgrid should NOT be None
42-
with self.assertRaises(AssertionError):
43-
nt.assert_equal(uxds_v1.uxgrid, None)
34+
uxds_v1 = ux.open_dataset(gridfile_geoflow, data_paths[0])
4435

45-
def test_open_dataset(self):
46-
"""Loads a single dataset with its grid topology file using uxarray's
47-
open_dataset call."""
36+
# Ideally uxds_v1.uxgrid should NOT be None
37+
nt.assert_equal(uxds_v1.uxgrid is not None, True)
4838

49-
uxds_var2_ne30 = ux.open_dataset(self.gridfile_ne30,
50-
self.dsfile_var2_ne30)
39+
def test_open_dataset():
40+
"""Loads a single dataset with its grid topology file using uxarray's
41+
open_dataset call."""
5142

52-
nt.assert_equal(uxds_var2_ne30.uxgrid.node_lon.size,
53-
constants.NNODES_outCSne30)
54-
nt.assert_equal(len(uxds_var2_ne30.uxgrid._ds.data_vars),
55-
constants.DATAVARS_outCSne30)
56-
nt.assert_equal(uxds_var2_ne30.source_datasets,
57-
str(self.dsfile_var2_ne30))
43+
uxds_var2_ne30 = ux.open_dataset(gridfile_ne30, dsfile_var2_ne30)
5844

59-
def test_open_mf_dataset(self):
60-
"""Loads multiple datasets with their grid topology file using
61-
uxarray's open_dataset call."""
45+
nt.assert_equal(uxds_var2_ne30.uxgrid.node_lon.size, constants.NNODES_outCSne30)
46+
nt.assert_equal(len(uxds_var2_ne30.uxgrid._ds.data_vars), constants.DATAVARS_outCSne30)
47+
nt.assert_equal(uxds_var2_ne30.source_datasets, str(dsfile_var2_ne30))
6248

63-
uxds_mf_ne30 = ux.open_mfdataset(self.gridfile_ne30,
64-
self.dsfiles_mf_ne30)
49+
def test_open_mf_dataset():
50+
"""Loads multiple datasets with their grid topology file using
51+
uxarray's open_dataset call."""
6552

66-
nt.assert_equal(uxds_mf_ne30.uxgrid.node_lon.size,
67-
constants.NNODES_outCSne30)
68-
nt.assert_equal(len(uxds_mf_ne30.uxgrid._ds.data_vars),
69-
constants.DATAVARS_outCSne30)
53+
uxds_mf_ne30 = ux.open_mfdataset(gridfile_ne30, dsfiles_mf_ne30)
7054

71-
nt.assert_equal(uxds_mf_ne30.source_datasets, self.dsfiles_mf_ne30)
55+
nt.assert_equal(uxds_mf_ne30.uxgrid.node_lon.size, constants.NNODES_outCSne30)
56+
nt.assert_equal(len(uxds_mf_ne30.uxgrid._ds.data_vars), constants.DATAVARS_outCSne30)
57+
nt.assert_equal(uxds_mf_ne30.source_datasets, dsfiles_mf_ne30)
7258

73-
def test_open_grid(self):
74-
"""Loads only a grid topology file using uxarray's open_grid call."""
75-
uxgrid = ux.open_grid(self.gridfile_geoflow)
59+
def test_open_grid():
60+
"""Loads only a grid topology file using uxarray's open_grid call."""
61+
uxgrid = ux.open_grid(gridfile_geoflow)
7662

77-
nt.assert_almost_equal(uxgrid.calculate_total_face_area(),
78-
constants.MESH30_AREA,
79-
decimal=3)
63+
nt.assert_almost_equal(uxgrid.calculate_total_face_area(), constants.MESH30_AREA, decimal=3)
8064

81-
def test_copy_dataset(self):
82-
"""Loads a single dataset with its grid topology file using uxarray's
83-
open_dataset call and make a copy of the object."""
65+
def test_copy_dataset():
66+
"""Loads a single dataset with its grid topology file using uxarray's
67+
open_dataset call and make a copy of the object."""
8468

85-
uxds_var2_ne30 = ux.open_dataset(self.gridfile_ne30,
86-
self.dsfile_var2_ne30)
69+
uxds_var2_ne30 = ux.open_dataset(gridfile_ne30, dsfile_var2_ne30)
8770

88-
# make a shallow and deep copy of the dataset object
89-
uxds_var2_ne30_copy_deep = uxds_var2_ne30.copy(deep=True)
90-
uxds_var2_ne30_copy = uxds_var2_ne30.copy(deep=False)
71+
# make a shallow and deep copy of the dataset object
72+
uxds_var2_ne30_copy_deep = uxds_var2_ne30.copy(deep=True)
73+
uxds_var2_ne30_copy = uxds_var2_ne30.copy(deep=False)
9174

92-
# Ideally uxds_var2_ne30_copy.uxgrid should NOT be None
93-
with self.assertRaises(AssertionError):
94-
nt.assert_equal(uxds_var2_ne30_copy.uxgrid, None)
75+
# Ideally uxds_var2_ne30_copy.uxgrid should NOT be None
76+
nt.assert_equal(uxds_var2_ne30_copy.uxgrid is not None, True)
9577

96-
# Check that the copy is a shallow copy
97-
assert (uxds_var2_ne30_copy.uxgrid is uxds_var2_ne30.uxgrid)
98-
assert (uxds_var2_ne30_copy.uxgrid == uxds_var2_ne30.uxgrid)
78+
# Check that the copy is a shallow copy
79+
assert uxds_var2_ne30_copy.uxgrid is uxds_var2_ne30.uxgrid
80+
assert uxds_var2_ne30_copy.uxgrid == uxds_var2_ne30.uxgrid
9981

100-
# Check that the deep copy is a deep copy
101-
assert (uxds_var2_ne30_copy_deep.uxgrid == uxds_var2_ne30.uxgrid)
102-
assert (uxds_var2_ne30_copy_deep.uxgrid is not uxds_var2_ne30.uxgrid)
82+
# Check that the deep copy is a deep copy
83+
assert uxds_var2_ne30_copy_deep.uxgrid == uxds_var2_ne30.uxgrid
84+
assert uxds_var2_ne30_copy_deep.uxgrid is not uxds_var2_ne30.uxgrid
10385

104-
def test_copy_dataarray(self):
105-
"""Loads an unstructured grid and data using uxarray's open_dataset
106-
call and make a copy of the dataarray object."""
86+
def test_copy_dataarray():
87+
"""Loads an unstructured grid and data using uxarray's open_dataset
88+
call and make a copy of the dataarray object."""
10789

108-
# Paths to Data Variable files
109-
data_paths = [
110-
self.geoflow_data_v1, self.geoflow_data_v2, self.geoflow_data_v3
111-
]
90+
# Paths to Data Variable files
91+
data_paths = [
92+
geoflow_data_v1, geoflow_data_v2, geoflow_data_v3
93+
]
11294

113-
uxds_v1 = ux.open_dataset(self.gridfile_geoflow, data_paths[0])
95+
uxds_v1 = ux.open_dataset(gridfile_geoflow, data_paths[0])
11496

115-
# get the uxdataarray object
116-
v1_uxdata_array = uxds_v1['v1']
97+
# get the uxdataarray object
98+
v1_uxdata_array = uxds_v1['v1']
11799

118-
# make a shallow and deep copy of the dataarray object
119-
v1_uxdata_array_copy_deep = v1_uxdata_array.copy(deep=True)
120-
v1_uxdata_array_copy = v1_uxdata_array.copy(deep=False)
100+
# make a shallow and deep copy of the dataarray object
101+
v1_uxdata_array_copy_deep = v1_uxdata_array.copy(deep=True)
102+
v1_uxdata_array_copy = v1_uxdata_array.copy(deep=False)
121103

122-
# Check that the copy is a shallow copy
123-
assert (v1_uxdata_array_copy.uxgrid is v1_uxdata_array.uxgrid)
124-
assert (v1_uxdata_array_copy.uxgrid == v1_uxdata_array.uxgrid)
104+
# Check that the copy is a shallow copy
105+
assert v1_uxdata_array_copy.uxgrid is v1_uxdata_array.uxgrid
106+
assert v1_uxdata_array_copy.uxgrid == v1_uxdata_array.uxgrid
125107

126-
# Check that the deep copy is a deep copy
127-
assert (v1_uxdata_array_copy_deep.uxgrid == v1_uxdata_array.uxgrid)
128-
assert (v1_uxdata_array_copy_deep.uxgrid is not v1_uxdata_array.uxgrid)
108+
# Check that the deep copy is a deep copy
109+
assert v1_uxdata_array_copy_deep.uxgrid == v1_uxdata_array.uxgrid
110+
assert v1_uxdata_array_copy_deep.uxgrid is not v1_uxdata_array.uxgrid
129111

130-
def test_open_dataset_grid_kwargs(self):
131-
"""Drops ``Mesh2_face_nodes`` from the inputted grid file using
132-
``grid_kwargs``"""
112+
def test_open_dataset_grid_kwargs():
113+
"""Drops ``Mesh2_face_nodes`` from the inputted grid file using
114+
``grid_kwargs``"""
133115

134-
with self.assertRaises(ValueError):
135-
# attempt to open a dataset after dropping face nodes should raise a KeyError
136-
uxds = ux.open_dataset(
137-
self.gridfile_ne30,
138-
self.dsfile_var2_ne30,
139-
grid_kwargs={"drop_variables": "Mesh2_face_nodes"})
116+
with pytest.raises(ValueError):
117+
# attempt to open a dataset after dropping face nodes should raise a KeyError
118+
uxds = ux.open_dataset(
119+
gridfile_ne30,
120+
dsfile_var2_ne30,
121+
grid_kwargs={"drop_variables": "Mesh2_face_nodes"}
122+
)

test/test_arcs.py

Lines changed: 63 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import os
22
import numpy as np
33
import numpy.testing as nt
4-
import random
5-
import xarray as xr
6-
7-
from unittest import TestCase
84
from pathlib import Path
9-
105
import uxarray as ux
11-
6+
import pytest
127
from uxarray.grid.coordinates import _lonlat_rad_to_xyz
138
from uxarray.grid.arcs import point_within_gca
149

@@ -25,72 +20,65 @@
2520
gridfile_geoflowsmall_grid = current_path / 'meshfiles' / "ugrid" / "geoflow-small" / 'grid.nc'
2621
gridfile_geoflowsmall_var = current_path / 'meshfiles' / "ugrid" / "geoflow-small" / 'v1.nc'
2722

28-
29-
class TestIntersectionPoint(TestCase):
30-
31-
def test_pt_within_gcr(self):
32-
# The GCR that's eexactly 180 degrees will have Value Error raised
33-
34-
gcr_180degree_cart = np.asarray([
35-
_lonlat_rad_to_xyz(0.0, np.pi / 2.0),
36-
_lonlat_rad_to_xyz(0.0, -np.pi / 2.0)
37-
])
38-
pt_same_lon_in = np.asarray(_lonlat_rad_to_xyz(0.0, 0.0))
39-
40-
with self.assertRaises(ValueError):
41-
point_within_gca(pt_same_lon_in, gcr_180degree_cart[0],gcr_180degree_cart[1] )
42-
#
43-
# Test when the point and the GCA all have the same longitude
44-
gcr_same_lon_cart = np.asarray([
45-
_lonlat_rad_to_xyz(0.0, 1.5),
46-
_lonlat_rad_to_xyz(0.0, -1.5)
47-
])
48-
pt_same_lon_in = np.asarray(_lonlat_rad_to_xyz(0.0, 0.0))
49-
self.assertTrue(point_within_gca(pt_same_lon_in, gcr_same_lon_cart[0], gcr_same_lon_cart[1]))
50-
51-
pt_same_lon_out = np.asarray(_lonlat_rad_to_xyz(0.0, 1.5000001))
52-
res = point_within_gca(pt_same_lon_out, gcr_same_lon_cart[0], gcr_same_lon_cart[1])
53-
self.assertFalse(res)
54-
55-
pt_same_lon_out_2 = np.asarray(_lonlat_rad_to_xyz(0.1, 1.0))
56-
res = point_within_gca(pt_same_lon_out_2, gcr_same_lon_cart[0], gcr_same_lon_cart[1])
57-
self.assertFalse(res)
58-
59-
def test_pt_within_gcr_antimeridian(self):
60-
# GCR vertex0 in radian : [5.163808182822441, 0.6351384888657234],
61-
# GCR vertex1 in radian : [0.8280410325693055, 0.42237025187091526]
62-
# Point in radian : [0.12574759138415173, 0.770098701904903]
63-
gcr_cart = np.array([[0.351, -0.724, 0.593], [0.617, 0.672, 0.410]])
64-
pt_cart = np.array(
65-
[0.9438777657502077, 0.1193199333436068, 0.922714737029319])
66-
self.assertTrue(
67-
point_within_gca(pt_cart, gcr_cart[0], gcr_cart[1]))
68-
69-
gcr_cart_flip = np.array([[0.617, 0.672, 0.410], [0.351, -0.724,
70-
0.593]])
71-
# If we flip the gcr in the undirected mode, it should still work
72-
self.assertTrue(
73-
point_within_gca(pt_cart, gcr_cart_flip[0], gcr_cart_flip[1]))
74-
75-
# 2nd anti-meridian case
76-
# GCR vertex0 in radian : [4.104711496596806, 0.5352983676533828],
77-
# GCR vertex1 in radian : [2.4269979227622533, -0.007003212877856825]
78-
# Point in radian : [0.43400375562899113, -0.49554509841586936]
79-
gcr_cart_1 = np.array([[-0.491, -0.706, 0.510], [-0.755, 0.655,
80-
-0.007]])
81-
pt_cart_within = np.array(
82-
[0.6136726305712109, 0.28442243941920053, -0.365605190899831])
83-
self.assertFalse(
84-
point_within_gca(pt_cart_within, gcr_cart_1[0], gcr_cart_1[1]))
85-
86-
87-
88-
def test_pt_within_gcr_cross_pole(self):
89-
gcr_cart = np.array([[0.351, 0.0, 0.3], [-0.351, 0.0, 0.3]])
90-
pt_cart = np.array(
91-
[0.10, 0.0, 0.8])
92-
93-
# Normalize the point abd the GCA
94-
pt_cart = pt_cart / np.linalg.norm(pt_cart)
95-
gcr_cart = np.array([x / np.linalg.norm(x) for x in gcr_cart])
96-
self.assertTrue(point_within_gca(pt_cart, gcr_cart[0], gcr_cart[1]))
23+
def test_pt_within_gcr():
24+
# The GCR that's exactly 180 degrees will raise a ValueError
25+
gcr_180degree_cart = np.asarray([
26+
_lonlat_rad_to_xyz(0.0, np.pi / 2.0),
27+
_lonlat_rad_to_xyz(0.0, -np.pi / 2.0)
28+
])
29+
pt_same_lon_in = np.asarray(_lonlat_rad_to_xyz(0.0, 0.0))
30+
31+
with pytest.raises(ValueError):
32+
point_within_gca(pt_same_lon_in, gcr_180degree_cart[0],gcr_180degree_cart[1] )
33+
#
34+
# Test when the point and the GCA all have the same longitude
35+
gcr_same_lon_cart = np.asarray([
36+
_lonlat_rad_to_xyz(0.0, 1.5),
37+
_lonlat_rad_to_xyz(0.0, -1.5)
38+
])
39+
pt_same_lon_in = np.asarray(_lonlat_rad_to_xyz(0.0, 0.0))
40+
assert(point_within_gca(pt_same_lon_in, gcr_same_lon_cart[0], gcr_same_lon_cart[1]))
41+
42+
pt_same_lon_out = np.asarray(_lonlat_rad_to_xyz(0.0, 1.5000001))
43+
res = point_within_gca(pt_same_lon_out, gcr_same_lon_cart[0], gcr_same_lon_cart[1])
44+
assert not res
45+
46+
pt_same_lon_out_2 = np.asarray(_lonlat_rad_to_xyz(0.1, 1.0))
47+
res = point_within_gca(pt_same_lon_out_2, gcr_same_lon_cart[0], gcr_same_lon_cart[1])
48+
assert not res
49+
50+
def test_pt_within_gcr_antimeridian():
51+
# GCR vertex0 in radian : [5.163808182822441, 0.6351384888657234],
52+
# GCR vertex1 in radian : [0.8280410325693055, 0.42237025187091526]
53+
# Point in radian : [0.12574759138415173, 0.770098701904903]
54+
gcr_cart = np.array([[0.351, -0.724, 0.593], [0.617, 0.672, 0.410]])
55+
pt_cart = np.array(
56+
[0.9438777657502077, 0.1193199333436068, 0.922714737029319])
57+
assert(
58+
point_within_gca(pt_cart, gcr_cart[0], gcr_cart[1]))
59+
60+
gcr_cart_flip = np.array([[0.617, 0.672, 0.410], [0.351, -0.724,
61+
0.593]])
62+
# If we flip the gcr in the undirected mode, it should still work
63+
assert(
64+
point_within_gca(pt_cart, gcr_cart_flip[0], gcr_cart_flip[1]))
65+
66+
# 2nd anti-meridian case
67+
# GCR vertex0 in radian : [4.104711496596806, 0.5352983676533828],
68+
# GCR vertex1 in radian : [2.4269979227622533, -0.007003212877856825]
69+
# Point in radian : [0.43400375562899113, -0.49554509841586936]
70+
gcr_cart_1 = np.array([[-0.491, -0.706, 0.510], [-0.755, 0.655,
71+
-0.007]])
72+
pt_cart_within = np.array(
73+
[0.6136726305712109, 0.28442243941920053, -0.365605190899831])
74+
assert( not
75+
point_within_gca(pt_cart_within, gcr_cart_1[0], gcr_cart_1[1]))
76+
77+
def test_pt_within_gcr_cross_pole():
78+
gcr_cart = np.array([[0.351, 0.0, 0.3], [-0.351, 0.0, 0.3]])
79+
pt_cart = np.array([0.10, 0.0, 0.8])
80+
81+
# Normalize the point abd the GCA
82+
pt_cart = pt_cart / np.linalg.norm(pt_cart)
83+
gcr_cart = np.array([x / np.linalg.norm(x) for x in gcr_cart])
84+
assert(point_within_gca(pt_cart, gcr_cart[0], gcr_cart[1]))

0 commit comments

Comments
 (0)