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

Skip to content

Commit 5bbda48

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 a922901 commit 5bbda48

File tree

3 files changed

+79
-50
lines changed

3 files changed

+79
-50
lines changed

lib/mpl_toolkits/axisartist/angle_helper.py

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

333333

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

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

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

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

lib/mpl_toolkits/axisartist/floating_axes.py

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

152152

153153
class ExtremeFinderFixed(ExtremeFinderSimple):
154-
def __init__(self, extremes):
155-
self._extremes = extremes
154+
# docstring inherited
156155

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

166171

lib/mpl_toolkits/axisartist/grid_finder.py

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

1717

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

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

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

5263

5364
class GridFinder:

0 commit comments

Comments
 (0)