8000 Merge pull request #13884 from anntzer/docextreme · matplotlib/matplotlib@898bd5f · GitHub
[go: up one dir, main page]

Skip to content

Commit 898bd5f

Browse files
authored
Merge pull request #13884 from anntzer/docextreme
DOC: Add some documentation for axisartist's ExtremeFinder
2 parents 346f6f7 + bff5ce5 commit 898bd5f

File tree

3 files changed

+80
-38
lines changed

3 files changed

+80
-38
lines changed

lib/mpl_toolkits/axisartist/angle_helper.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -319,21 +319,49 @@ def __call__(self, direction, factor, values): # hour
319319

320320

321321
class ExtremeFinderCycle(ExtremeFinderSimple):
322-
"""
323-
When there is a cycle, e.g., longitude goes from 0-360.
324-
"""
322+
# docstring inherited
323+
325324
def __init__(self, nx, ny,
326325
lon_cycle=360., lat_cycle=None,
327326
lon_minmax=None, lat_minmax=(-90, 90)):
327+
"""
328+
This subclass handles the case where one or both coordinates should be
329+
taken modulo 360, or be restricted to not exceed a specific range.
330+
331+
Parameters
332+
----------
333+
nx, ny : int
334+
The number of samples in each direction.
335+
336+
lon_cycle, lat_cycle : 360 or None
337+
If not None, values in the corresponding direction are taken modulo
338+
*lon_cycle* or *lat_cycle*; in theory this can be any number but
339+
the implementation actually assumes that it is 360 (if not None);
340+
other values give nonsensical results.
341+
342+
This is done by "unwrapping" the transformed grid coordinates so
343+
that jumps are less than a half-cycle; then normalizing the span to
344+
no more than a full cycle.
345+
346+
For example, if values are in the union of the [0, 2] and
347+
[358, 360] intervals (typically, angles measured modulo 360), the
348+
values in the second interval are normalized to [-2, 0] instead so
349+
that the values now cover [-2, 2]. If values are in a range of
350+
[5, 1000], this gets normalized to [5, 365].
351+
352+
lon_minmax, lat_minmax : (float, float) or None
353+
If not None, the computed bounding box is clipped to the given
354+
range in the corresponding direction.
355+
"""
328356
self.nx, self.ny = nx, ny
329357
self.lon_cycle, self.lat_cycle = lon_cycle, lat_cycle
330358
self.lon_minmax = lon_minmax
331359
self.lat_minmax = lat_minmax
332360

333361
def __call__(self, transform_xy, x1, y1, x2, y2):
334362
# docstring inherited
335-
x_, y_ = np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny)
336-
x, y = np.meshgrid(x_, y_)
363+
x, y = np.meshgrid(
364+
np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny))
337365
lon, lat = transform_xy(np.ravel(x), np.ravel(y))
338366

339367
# iron out jumps, but algorithm should be improved.
@@ -353,13 +381,6 @@ def __call__(self, transform_xy, x1, y1, x2, y2):
353381
lon_min, lon_max = np.nanmin(lon), np.nanmax(lon)
354382
lat_min, lat_max = np.nanmin(lat), np.nanmax(lat)
355383

356-
lon_min, lon_max, lat_min, lat_max = \
357-
self._adjust_extremes(lon_min, lon_max, lat_min, lat_max)
358-
359-
return lon_min, lon_max, lat_min, lat_max
360-
361-
def _adjust_extremes(self, lon_min, lon_max, lat_min, lat_max):
362-
363384
lon_min, lon_max, lat_min, lat_max = \
364385
self._add_pad(lon_min, lon_max, lat_min, lat_max)
365386

lib/mpl_toolkits/axisartist/floating_axes.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,17 @@ def get_line(self, axes):
143143

144144

145145
class ExtremeFinderFixed(ExtremeFinderSimple):
146+
# docstring inherited
147+
146148
def __init__(self, extremes):
149+
"""
150+
This subclass always returns the same bounding box.
151+
152+
Parameters
153+
----------
154+
extremes : (float, float, float, float)
155+
The bounding box that this helper always returns.
156+
"""
147157
self._extremes = extremes
148158

149159
def __call__(self, transform_xy, x1, y1, x2, y2):

lib/mpl_toolkits/axisartist/grid_finder.py

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,50 @@ def _deprecate_factor_none(factor):
1616
return factor
1717

1818

19-
# extremes finder
2019
class ExtremeFinderSimple:
21-
def __init__(self, nx, ny):
22-
self.nx, self.ny = nx, ny
20+
"""
21+
A helper class to figure out the range of grid lines that need to be drawn.
22+
"""
2323

24-
def __call__(self, transform_xy, x1, y1, x2, y2):
24+
def __init__(self, nx, ny):
2525
"""
26-
Return extreme values.
27-
28-
x1, y1, x2, y2 in image coordinates (0-based)
29-
nx, ny : number of division in each axis
26+
Parameters
27+
----------
28+
nx, ny : int
29+
The number of samples in each direction.
3030
"""
31-
x_, y_ = np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny)
32-
x, y = np.meshgrid(x_, y_)
33-
lon, lat = transform_xy(np.ravel(x), np.ravel(y))
34-
35-
lon_min, lon_max = lon.min(), lon.max()
36-
lat_min, lat_max = lat.min(), lat.max()
31+
self.nx = nx
32+
self.ny = ny
3733

38-
return self._add_pad(lon_min, lon_max, lat_min, lat_max)
39-
40-
def _add_pad(self, lon_min, lon_max, lat_min, lat_max):
34+
def __call__(self, transform_xy, x1, y1, x2, y2):
4135
"""
42-
A small amount of padding is added because the current clipping
43-
algorithms seems to fail when the gridline ends at the bbox boundary.
36+
Compute an approximation of the bounding box obtained by applying
37+
*transform_xy* to the box delimited by ``(x1, y1, x2, y2)``.
38+
39+
The intended use is to have ``(x1, y1, x2, y2)`` in axes coordinates,
40+
and have *transform_xy* be the transform from axes coordinates to data
41+
coordinates; this method then returns the range of data coordinates
42+
that span the actual axes.
43+
44+
The computation is done by sampling ``nx * ny`` equispaced points in
45+
the ``(x1, y1, x2, y2)`` box and finding the resulting points with
46+
extremal coordinates; then adding some padding to take into account the
47+
finite sampling.
48+
49+
As each sampling step covers a relative range of *1/nx* or *1/ny*,
50+
the padding is computed by expanding the span D84E covered by the extremal
51+
coordinates by these fractions.
4452
"""
45-
dlon = (lon_max - lon_min) / self.nx
46-
dlat = (lat_max - lat_min) / self.ny
47-
48-
lon_min, lon_max = lon_min - dlon, lon_max + dlon
49-
lat_min, lat_max = lat_min - dlat, lat_max + dlat
50-
51-
return lon_min, lon_max, lat_min, lat_max
53+
x, y = np.meshgrid(
54+
np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny))
55+
xt, yt = transform_xy(np.ravel(x), np.ravel(y))
56+
return self._add_pad(xt.min(), xt.max(), yt.min(), yt.max())
57+
58+
def _add_pad(self, x_min, x_max, y_min, y_max):
59+
"""Perform the padding mentioned in `__call__`."""
60+
dx = (x_max - x_min) / self.nx
61+
dy = (y_max - y_min) / self.ny
62+
return x_min - dx, x_max + dx, y_min - dy, y_max + dy
5263

5364

5465
class GridFinder:

0 commit comments

Comments
 (0)
0