Skip to content

Commit 3616f8f

Browse files
authored
Add private function _validate_data_input to validate input data (#2595)
1 parent cca17c7 commit 3616f8f

File tree

1 file changed

+69
-15
lines changed

1 file changed

+69
-15
lines changed

pygmt/helpers/utils.py

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,74 @@
1414
from pygmt.exceptions import GMTInvalidInput
1515

1616

17-
def data_kind(data, x=None, y=None, z=None, required_z=False):
17+
def _validate_data_input(
18+
data=None, x=None, y=None, z=None, required_z=False, kind=None
19+
):
20+
"""
21+
Check if the combination of data/x/y/z is valid.
22+
23+
Examples
24+
--------
25+
>>> _validate_data_input(data="infile")
26+
>>> _validate_data_input(x=[1, 2, 3], y=[4, 5, 6])
27+
>>> _validate_data_input(x=[1, 2, 3], y=[4, 5, 6], z=[7, 8, 9])
28+
>>> _validate_data_input()
29+
Traceback (most recent call last):
30+
...
31+
pygmt.exceptions.GMTInvalidInput: No input data provided.
32+
>>> _validate_data_input(x=[1, 2, 3])
33+
Traceback (most recent call last):
34+
...
35+
pygmt.exceptions.GMTInvalidInput: Must provide both x and y.
36+
>>> _validate_data_input(y=[4, 5, 6])
37+
Traceback (most recent call last):
38+
...
39+
pygmt.exceptions.GMTInvalidInput: Must provide both x and y.
40+
>>> _validate_data_input(x=[1, 2, 3], y=[4, 5, 6], required_z=True)
41+
Traceback (most recent call last):
42+
...
43+
pygmt.exceptions.GMTInvalidInput: Must provide x, y, and z.
44+
>>> _validate_data_input(data="infile", x=[1, 2, 3])
45+
Traceback (most recent call last):
46+
...
47+
pygmt.exceptions.GMTInvalidInput: Too much data. Use either data or x/y/z.
48+
>>> _validate_data_input(data="infile", y=[4, 5, 6])
49+
Traceback (most recent call last):
50+
...
51+
pygmt.exceptions.GMTInvalidInput: Too much data. Use either data or x/y/z.
52+
>>> _validate_data_input(data="infile", z=[7, 8, 9])
53+
Traceback (most recent call last):
54+
...
55+
pygmt.exceptions.GMTInvalidInput: Too much data. Use either data or x/y/z.
56+
57+
Raises
58+
------
59+
GMTInvalidInput
60+
If the data input is not valid.
61+
"""
62+
if data is None: # data is None
63+
if x is None and y is None: # both x and y are None
64+
raise GMTInvalidInput("No input data provided.")
65+
if x is None or y is None: # either x or y is None
66+
raise GMTInvalidInput("Must provide both x and y.")
67+
# both x and y are not None, now check z
68+
if required_z and z is None:
69+
raise GMTInvalidInput("Must provide x, y, and z.")
70+
else: # data is not None
71+
if x is not None or y is not None or z is not None:
72+
raise GMTInvalidInput("Too much data. Use either data or x/y/z.")
73+
# For 'matrix' kind, check if data has the required z column
74+
if kind == "matrix" and required_z:
75+
if hasattr(data, "shape"): # np.ndarray or pd.DataFrame
76+
if len(data.shape) == 1 and data.shape[0] < 3:
77+
raise GMTInvalidInput("data must provide x, y, and z columns.")
78+
if len(data.shape) > 1 and data.shape[1] < 3:
79+
raise GMTInvalidInput("data must provide x, y, and z columns.")
80+
if hasattr(data, "data_vars") and len(data.data_vars) < 3: # xr.Dataset
81+
raise GMTInvalidInput("data must provide x, y, and z columns.")
82+
83+
84+
def data_kind(data=None, x=None, y=None, z=None, required_z=False):
1885
"""
1986
Check what kind of data is provided to a module.
2087
@@ -64,30 +131,17 @@ def data_kind(data, x=None, y=None, z=None, required_z=False):
64131
>>> data_kind(data=xr.DataArray(np.random.rand(4, 3)))
65132
'grid'
66133
"""
67-
if data is None and x is None and y is None:
68-
raise GMTInvalidInput("No input data provided.")
69-
if data is not None and (x is not None or y is not None or z is not None):
70-
raise GMTInvalidInput("Too much data. Use either data or x and y.")
71-
if data is None and (x is None or y is None):
72-
raise GMTInvalidInput("Must provide both x and y.")
73-
if data is None and required_z and z is None:
74-
raise GMTInvalidInput("Must provide x, y, and z.")
75-
76134
if isinstance(data, (str, pathlib.PurePath)):
77135
kind = "file"
78136
elif isinstance(data, xr.DataArray):
79137
kind = "grid"
80138
elif hasattr(data, "__geo_interface__"):
81139
kind = "geojson"
82140
elif data is not None:
83-
if required_z and (
84-
getattr(data, "shape", (3, 3))[1] < 3 # np.array, pd.DataFrame
85-
or len(getattr(data, "data_vars", (0, 1, 2))) < 3 # xr.Dataset
86-
):
87-
raise GMTInvalidInput("data must provide x, y, and z columns.")
88141
kind = "matrix"
89142
else:
90143
kind = "vectors"
144+
_validate_data_input(data=data, x=x, y=y, z=z, required_z=required_z, kind=kind)
91145
return kind
92146

93147

0 commit comments

Comments
 (0)