Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e957cda

Browse files
committed
Add some documentation for ExtremeFinder.
Let's try to figure out how this whole thing is constructed :) At least that's my understanding.
1 parent d864788 commit e957cda

File tree

3 files changed

+80
-51
lines changed

3 files changed

+80
-51
lines changed

lib/mpl_toolkits/axisartist/angle_helper.py

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -331,26 +331,46 @@ def __call__(self, direction, factor, values): # hour
331331

332332

333333
class ExtremeFinderCycle(ExtremeFinderSimple):
334-
"""
335-
When there is a cycle, e.g., longitude goes from 0-360.
336-
"""
334+
# docstring inherited
335+
337336
def __init__(self, nx, ny,
338337
lon_cycle=360., lat_cycle=None,
339338
lon_minmax=None, lat_minmax=(-90, 90)):
339+
"""
340+
This subclass handles the case where one or both coordinates should be
341+
taken modulo 360, or be restricted to not exceed a specific range.
342+
343+
Parameters
344+
----------
345+
nx, ny : int
346+
The number of samples in each direction.
347+
348+
lon_cycle, lat_cycle : 360 or None
349+
If not None, values in the corresponding direction are taken modulo
350+
*lon_cycle* or *lat_cycle*; in theory this can be any number but
351+
the implementation actually assumes that it is 360 (if not None);
352+
other values give nonsensical results.
353+
354+
This is done by "unwrapping" the transformed grid coordinates so
355+
that jumps are less than a half-cycle; then normalizing the span to
356+
no more than a full cycle.
357+
358+
For example, a range of (2, 358) is normalized to (-2, 2); a range
359+
of (5, 1000) is normalized to (5, 365).
360+
361+
lon_minmax, lat_minmax : (float, float) or None
362+
If not None, the computed bounding box is clipped to the given
363+
range in the corresponding direction.
364+
"""
340365
self.nx, self.ny = nx, ny
341366
self.lon_cycle, self.lat_cycle = lon_cycle, lat_cycle
342367
self.lon_minmax = lon_minmax
343368
self.lat_minmax = lat_minmax
344369

345370
def __call__(self, transform_xy, x1, y1, x2, y2):
346-
"""
347-
get extreme values.
348-
349-
x1, y1, x2, y2 in image coordinates (0-based)
350-
nx, ny : number of divisions in each axis
351-
"""
352-
x_, y_ = np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny)
353-
x, y = np.meshgrid(x_, y_)
371+
# docstring inherited
372+
x, y = np.meshgrid(
373+
np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny))
354374
lon, lat = transform_xy(np.ravel(x), np.ravel(y))
355375

356376
# iron out jumps, but algorithm should be improved.
@@ -370,13 +390,6 @@ def __call__(self, transform_xy, x1, y1, x2, y2):
370390
lon_min, lon_max = np.nanmin(lon), np.nanmax(lon)
371391
lat_min, lat_max = np.nanmin(lat), np.nanmax(lat)
372392

373-
lon_min, lon_max, lat_min, lat_max = \
374-
self._adjust_extremes(lon_min, lon_max, lat_min, lat_max)
375-
376-
return lon_min, lon_max, lat_min, lat_max
377-
378-
def _adjust_extremes(self, lon_min, lon_max, lat_min, lat_max):
379-
380393
lon_min, lon_max, lat_min, lat_max = \
381394
self._add_pad(lon_min, lon_max, lat_min, lat_max)
382395

lib/mpl_toolkits/axisartist/floating_axes.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,16 +153,21 @@ def get_line(self, axes):
153153

154154

155155
class ExtremeFinderFixed(ExtremeFinderSimple):
156-
def __init__(self, extremes):
157-
self._extremes = extremes
156+
# docstring inherited
158157

159-
def __call__(self, transform_xy, x1, y1, x2, y2):
158+
def __init__(self, extremes):
160159
"""
161-
get extreme values.
160+
This subclass always returns the same bounding box.
162161
163-
x1, y1, x2, y2 in image coordinates (0-based)
164-
nx, ny : number of division in each axis
162+
Parameters
163+
----------
164+
extremes : (float, float, float, float)
165+
The bounding box always returned by this helper.
165166
"""
167+
self._extremes = extremes
168+
169+
def __call__(self, transform_xy, x1, y1, x2, y2):
170+
# docstring inherited
166171
return self._extremes
167172

168173

lib/mpl_toolkits/axisartist/grid_finder.py

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,50 @@
55
from .clip_path import clip_line_to_rect
66

77

8-
# extremes finder
98
class ExtremeFinderSimple(object):
10-
def __init__(self, nx, ny):
11-
self.nx, self.ny = nx, ny
9+
"""
10+
A helper class to figure out the range of grid lines that need to be drawn.
11+
"""
1212

13-
def __call__(self, transform_xy, x1, y1, x2, y2):
13+
def __init__(self, nx, ny):
1414
"""
15-
get extreme values.
16-
17-
x1, y1, x2, y2 in image coordinates (0-based)
18-
nx, ny : number of division in each axis
15+
Parameters
16+
----------
17+
nx, ny : int
18+
The number of samples in each direction.
1919
"""
20-
x_, y_ = np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny)
21-
x, y = np.meshgrid(x_, y_)
22-
lon, lat = transform_xy(np.ravel(x), np.ravel(y))
23-
24-
lon_min, lon_max = lon.min(), lon.max()
25-
lat_min, lat_max = lat.min(), lat.max()
20+
self.nx = nx
21+
self.ny = ny
2622

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

4253

4354
class GridFinderBase(object):

0 commit comments

Comments
 (0)