Skip to content

Commit f62218d

Browse files
authored
Move non-plotting modules to separate files in src directory (#832)
* Move blockmedian to src * Move grdtrack to src * Move surface to src * Move makecpt to src * Move grdfilter to src * Move grdcut to src * Move info to src * Move which to src
1 parent 920a614 commit f62218d

13 files changed

+297
-250
lines changed

pygmt/__init__.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,19 @@
1414
# Import modules to make the high-level GMT Python API
1515
from pygmt import datasets
1616
from pygmt.figure import Figure
17-
from pygmt.filtering import blockmedian
18-
from pygmt.gridding import surface
19-
from pygmt.gridops import grdcut, grdfilter
20-
from pygmt.mathops import makecpt
21-
from pygmt.modules import GMTDataArrayAccessor, config, grdinfo, info, which
22-
from pygmt.sampling import grdtrack
17+
from pygmt.modules import GMTDataArrayAccessor, config, grdinfo
2318
from pygmt.session_management import begin as _begin
2419
from pygmt.session_management import end as _end
20+
from pygmt.src import (
21+
blockmedian,
22+
grdcut,
23+
grdfilter,
24+
grdtrack,
25+
info,
26+
makecpt,
27+
surface,
28+
which,
29+
)
2530
from pygmt.x2sys import x2sys_cross, x2sys_init
2631

2732
# Get semantic version through setuptools-scm

pygmt/datasets/earth_relief.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
"""
77
import xarray as xr
88
from pygmt.exceptions import GMTInvalidInput
9-
from pygmt.gridops import grdcut
109
from pygmt.helpers import kwargs_to_strings
11-
from pygmt.modules import which
10+
from pygmt.src import grdcut, which
1211

1312

1413
@kwargs_to_strings(region="sequence")

pygmt/datasets/tutorial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Functions to load sample data from the GMT tutorials.
33
"""
44
import pandas as pd
5-
from pygmt.modules import which
5+
from pygmt.src import which
66

77

88
def load_japan_quakes():

pygmt/modules.py

Lines changed: 0 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""
22
Non-plot GMT modules.
33
"""
4-
import numpy as np
54
import xarray as xr
65
from pygmt.clib import Session
76
from pygmt.exceptions import GMTInvalidInput
@@ -55,141 +54,6 @@ def grdinfo(grid, **kwargs):
5554
return result
5655

5756

58-
@fmt_docstring
59-
@use_alias(C="per_column", I="spacing", T="nearest_multiple", V="verbose")
60-
def info(table, **kwargs):
61-
"""
62-
Get information about data tables.
63-
64-
Reads from files and finds the extreme values in each of the columns
65-
reported as min/max pairs. It recognizes NaNs and will print warnings if
66-
the number of columns vary from record to record. As an option, it will
67-
find the extent of the first two columns rounded up and down to the nearest
68-
multiple of the supplied increments given by *spacing*. Such output will be
69-
in a numpy.ndarray form ``[w, e, s, n]``, which can be used directly as the
70-
*region* argument for other modules (hence only dx and dy are needed). If
71-
the *per_column* option is combined with *spacing*, then the numpy.ndarray
72-
output will be rounded up/down for as many columns as there are increments
73-
provided in *spacing*. A similar option *nearest_multiple* option will
74-
provide a numpy.ndarray in the form of ``[zmin, zmax, dz]`` for makecpt.
75-
76-
Full option list at :gmt-docs:`gmtinfo.html`
77-
78-
{aliases}
79-
80-
Parameters
81-
----------
82-
table : str or np.ndarray or pandas.DataFrame or xarray.Dataset
83-
Pass in either a file name to an ASCII data table, a 1D/2D numpy array,
84-
a pandas dataframe, or an xarray dataset made up of 1D xarray.DataArray
85-
data variables.
86-
per_column : bool
87-
Report the min/max values per column in separate columns.
88-
spacing : str
89-
``'[b|p|f|s]dx[/dy[/dz...]]'``.
90-
Report the min/max of the first n columns to the nearest multiple of
91-
the provided increments and output results in the form
92-
``[w, e, s, n]``.
93-
nearest_multiple : str
94-
``'dz[+ccol]'``
95-
Report the min/max of the first (0'th) column to the nearest multiple
96-
of dz and output this in the form ``[zmin, zmax, dz]``.
97-
98-
{V}
99-
100-
Returns
101-
-------
102-
output : np.ndarray or str
103-
Return type depends on whether any of the 'per_column', 'spacing', or
104-
'nearest_multiple' parameters are set.
105-
106-
- np.ndarray if either of the above parameters are used.
107-
- str if none of the above parameters are used.
108-
"""
109-
kind = data_kind(table)
110-
with Session() as lib:
111-
if kind == "file":
112-
file_context = dummy_context(table)
113-
elif kind == "matrix":
114-
try:
115-
# pandas.DataFrame and xarray.Dataset types
116-
arrays = [array for _, array in table.items()]
117-
except AttributeError:
118-
# Python lists, tuples, and numpy ndarray types
119-
arrays = np.atleast_2d(np.asanyarray(table).T)
120-
file_context = lib.virtualfile_from_vectors(*arrays)
121-
else:
122-
raise GMTInvalidInput(f"Unrecognized data type: {type(table)}")
123-
124-
with GMTTempFile() as tmpfile:
125-
with file_context as fname:
126-
arg_str = " ".join(
127-
[fname, build_arg_string(kwargs), "->" + tmpfile.name]
128-
)
129-
lib.call_module("info", arg_str)
130-
result = tmpfile.read()
131-
132-
if any(arg in kwargs for arg in ["C", "I", "T"]):
133-
# Converts certain output types into a numpy array
134-
# instead of a raw string that is less useful.
135-
if result.startswith(("-R", "-T")): # e.g. -R0/1/2/3 or -T0/9/1
136-
result = result[2:].replace("/", " ")
137-
result = np.loadtxt(result.splitlines())
138-
139-
return result
140-
141-
142-
@fmt_docstring
143-
@use_alias(G="download", V="verbose")
144-
def which(fname, **kwargs):
145-
"""
146-
Find the full path to specified files.
147-
148-
Reports the full paths to the files given through *fname*. We look for
149-
the file in (1) the current directory, (2) in $GMT_USERDIR (if defined),
150-
(3) in $GMT_DATADIR (if defined), or (4) in $GMT_CACHEDIR (if defined).
151-
152-
*fname* can also be a downloadable file (either a full URL, a
153-
`@file` special file for downloading from the GMT Site Cache, or
154-
`@earth_relief_*` topography grids). In these cases, use option *download*
155-
to set the desired behavior. If *download* is not used (or False), the file
156-
will not be found.
157-
158-
Full option list at :gmt-docs:`gmtwhich.html`
159-
160-
{aliases}
161-
162-
Parameters
163-
----------
164-
fname : str
165-
The file name that you want to check.
166-
download : bool or str
167-
If the file is downloadable and not found, we will try to download the
168-
it. Use True or 'l' (default) to download to the current directory. Use
169-
'c' to place in the user cache directory or 'u' user data directory
170-
instead.
171-
{V}
172-
173-
Returns
174-
-------
175-
path : str
176-
The path of the file, depending on the options used.
177-
178-
Raises
179-
------
180-
FileNotFoundError
181-
If the file is not found.
182-
"""
183-
with GMTTempFile() as tmpfile:
184-
arg_str = " ".join([fname, build_arg_string(kwargs), "->" + tmpfile.name])
185-
with Session() as lib:
186-
lib.call_module("which", arg_str)
187-
path = tmpfile.read().strip()
188-
if not path:
189-
raise FileNotFoundError("File '{}' not found.".format(fname))
190-
return path
191-
192-
19357
class config: # pylint: disable=invalid-name
19458
"""
19559
Set GMT defaults globally or locally.

pygmt/src/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,13 @@
22
Source code for PyGMT modules.
33
"""
44
# pylint: disable=import-outside-toplevel
5+
from pygmt.src.blockmedian import blockmedian
6+
from pygmt.src.grdcut import grdcut
7+
from pygmt.src.grdfilter import grdfilter
8+
from pygmt.src.grdtrack import grdtrack
9+
from pygmt.src.info import info
510
from pygmt.src.inset import inset
11+
from pygmt.src.makecpt import makecpt
612
from pygmt.src.meca import meca
13+
from pygmt.src.surface import surface
14+
from pygmt.src.which import which

pygmt/filtering.py renamed to pygmt/src/blockmedian.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
GMT modules for Filtering of 1-D and 2-D Data.
2+
blockmedian - Block average (x,y,z) data tables by median estimation.
33
"""
44
import pandas as pd
55
from pygmt.clib import Session

pygmt/src/grdcut.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
"""
2+
grdcut - Extract subregion from a grid.
3+
"""
4+
5+
import xarray as xr
6+
from pygmt.clib import Session
7+
from pygmt.exceptions import GMTInvalidInput
8+
from pygmt.helpers import (
9+
GMTTempFile,
10+
build_arg_string,
11+
data_kind,
12+
dummy_context,
13+
fmt_docstring,
14+
kwargs_to_strings,
15+
use_alias,
16+
)
17+
18+
19+
@fmt_docstring
20+
@use_alias(
21+
G="outgrid",
22+
R="region",
23+
J="projection",
24+
N="extend",
25+
S="circ_subregion",
26+
V="verbose",
27+
Z="z_subregion",
28+
)
29+
@kwargs_to_strings(R="sequence")
30+
def grdcut(grid, **kwargs):
31+
"""
32+
Extract subregion from a grid.
33+
34+
Produce a new *outgrid* file which is a subregion of *grid*. The
35+
subregion is specified with *region*; the specified range must not exceed
36+
the range of *grid* (but see *extend*). If in doubt, run
37+
:meth:`pygmt.grdinfo` to check range. Alternatively, define the subregion
38+
indirectly via a range check on the node values or via distances from a
39+
given point. Finally, you can give *projection* for oblique projections to
40+
determine the corresponding rectangular *region* setting that will give a
41+
grid that fully covers the oblique domain.
42+
43+
Full option list at :gmt-docs:`grdcut.html`
44+
45+
{aliases}
46+
47+
Parameters
48+
----------
49+
grid : str or xarray.DataArray
50+
The file name of the input grid or the grid loaded as a DataArray.
51+
outgrid : str or None
52+
The name of the output netCDF file with extension .nc to store the grid
53+
in.
54+
{J}
55+
{R}
56+
extend : bool or int or float
57+
Allow grid to be extended if new *region* exceeds existing boundaries.
58+
Give a value to initialize nodes outside current region.
59+
circ_subregion : str
60+
``'lon/lat/radius[unit][+n]'``.
61+
Specify an origin (*lon* and *lat*) and *radius*; append a distance
62+
*unit* and we determine the corresponding rectangular region so that
63+
all grid nodes on or inside the circle are contained in the subset.
64+
If **+n** is appended we set all nodes outside the circle to NaN.
65+
z_subregion : str
66+
``'[min/max][+n|N|r]'``.
67+
Determine a new rectangular region so that all nodes outside this
68+
region are also outside the given z-range [-inf/+inf]. To indicate no
69+
limit on *min* or *max* only, specify a hyphen (-). Normally, any NaNs
70+
encountered are simply skipped and not considered in the
71+
range-decision. Append **+n** to consider a NaN to be outside the given
72+
z-range. This means the new subset will be NaN-free. Alternatively,
73+
append **+r** to consider NaNs to be within the data range. In this
74+
case we stop shrinking the boundaries once a NaN is found [Default
75+
simply skips NaNs when making the range decision]. Finally, if your
76+
core subset grid is surrounded by rows and/or columns that are all
77+
NaNs, append **+N** to strip off such columns before (optionally)
78+
considering the range of the core subset for further reduction of the
79+
area.
80+
81+
{V}
82+
83+
Returns
84+
-------
85+
ret: xarray.DataArray or None
86+
Return type depends on whether the *outgrid* parameter is set:
87+
88+
- xarray.DataArray if *outgrid* is not set
89+
- None if *outgrid* is set (grid output will be stored in *outgrid*)
90+
"""
91+
kind = data_kind(grid)
92+
93+
with GMTTempFile(suffix=".nc") as tmpfile:
94+
with Session() as lib:
95+
if kind == "file":
96+
file_context = dummy_context(grid)
97+
elif kind == "grid":
98+
file_context = lib.virtualfile_from_grid(grid)
99+
else:
100+
raise GMTInvalidInput("Unrecognized data type: {}".format(type(grid)))
101+
102+
with file_context as infile:
103+
if "G" not in kwargs.keys(): # if outgrid is unset, output to tempfile
104+
kwargs.update({"G": tmpfile.name})
105+
outgrid = kwargs["G"]
106+
arg_str = " ".join([infile, build_arg_string(kwargs)])
107+
lib.call_module("grdcut", arg_str)
108+
109+
if outgrid == tmpfile.name: # if user did not set outgrid, return DataArray
110+
with xr.open_dataarray(outgrid) as dataarray:
111+
result = dataarray.load()
112+
_ = result.gmt # load GMTDataArray accessor information
113+
else:
114+
result = None # if user sets an outgrid, return None
115+
116+
return result

0 commit comments

Comments
 (0)