8000 Fillbetween by rmlopes · Pull Request #6560 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Fillbetween #6560

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/users/whats_new/updated_fill_betweenx.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Interpolation in fill_betweenx
------------------------------

The ``interpolate`` parameter now exists for the method :func:`fill_betweenx`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a method on a class, not a function, so will this cross-reference work?

This allows a user to interpolate the data and fill the areas in the crossover
points, similarly to :func:`fill_between`.
45 changes: 38 additions & 7 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4853,10 +4853,11 @@ def get_interp_point(ind):
label_namer=None)
@docstring.dedent_interpd
def fill_betweenx(self, y, x1, x2=0, where=None,
step=None, **kwargs):
step=None, interpolate=False, **kwargs):
"""
Make filled polygons between two horizontal curves.


Create a :class:`~matplotlib.collections.PolyCollection`
filling the regions between *x1* and *x2* where
``where==True``
Expand All @@ -4880,6 +4881,12 @@ def fill_betweenx(self, y, x1, x2=0, where=None,
step : {'pre', 'post', 'mid'}, optional
If not None, fill with step logic.

interpolate : bool, optional
If `True`, interpolate between the two lines to find the
precise point of intersection. Otherwise, the start and
end points of the filled region will only occur on explicit
values in the *x* array.

Notes
-----

Expand Down Expand Up @@ -4948,13 +4955,37 @@ def fill_betweenx(self, y, x1, x2=0, where=None,
continue

N = len(yslice)
Y = np.zeros((2 * N + 2, 2), float)
Y = np.zeros((2 * N + 2, 2), np.float)
if interpolate:
def get_interp_point(ind):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the exact same function as in fill_between?
If so, I think it should be factored out and moved to the cbook module as a private function.

Copy link
Contributor Author
@rmlopes rmlopes Nov 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. I thought about that but also about using some interpolation function maintained and alerady available in scipy (would this be a bad idea perhaps?). I'll have a look at it as soon as I can.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scipy isn't a dependency, so using their functions isn't an option unless you copy paste them in a module of ours.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two methods differ on the axes of interpolation only. Could be a single function indeed. I can make this in a new branch but I need to know where to add the interpolate function.
This solution is actually very slow for my use case since I am displaying a few thousand seismic traces, so I would like to keep working on this.

im1 = max(ind - 1, 0)
y_values = y[im1:ind + 1]
diff_values = x1[im1:ind + 1] - x2[im1:ind + 1]
x1_values = x1[im1:ind + 1]

if len(diff_values) == 2:
if np.ma.is_masked(diff_values[1]):
return x1[im1], y[im1]
elif np.ma.is_masked(diff_values[0]):
return x1[ind], y[ind]

diff_order = diff_values.argsort()
diff_root_y = np.interp(
0, diff_values[diff_order], y_values[diff_order])
diff_root_x = np.interp(diff_root_y, y_values, x1_values)
return diff_root_x, diff_root_y

start = get_interp_point(ind0)
end = get_interp_point(ind1)
else:
# the purpose of the next two lines is for when x2 is a
# scalar like 0 and we want the fill to go all the way
# down to 0 even if none of the x1 sample points do
start = x2slice[0], yslice[0]
end = x2slice[-1], yslice[-1]

# the purpose of the next two lines is for when x2 is a
# scalar like 0 and we want the fill to go all the way
# down to 0 even if none of the x1 sample points do
Y[0] = x2slice[0], yslice[0]
Y[N + 1] = x2slice[-1], yslice[-1]
Y[0] = start
Y[N + 1] = end

Y[1:N + 1, 0] = x1slice
Y[1:N + 1, 1] = yslice
Expand Down
0