-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Mplot3d masked surface #18114
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
Mplot3d masked surface #18114
Changes from all commits
cf8647c
682a767
f32c976
b9dc0b1
91d2f37
296a388
3eace1e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1624,8 +1624,8 @@ def plot_surface(self, X, Y, Z, *args, norm=None, vmin=None, | |
"Z contains NaN values. This may result in rendering " | ||
"artifacts.") | ||
|
||
# TODO: Support masked arrays | ||
X, Y, Z = np.broadcast_arrays(X, Y, Z) | ||
mask = np.ma.getmaskarray(Z) | ||
X, Y, Z, mask = np.broadcast_arrays(X, Y, Z, mask) | ||
rows, cols = Z.shape | ||
|
||
has_stride = 'rstride' in kwargs or 'cstride' in kwargs | ||
|
@@ -1680,6 +1680,10 @@ def plot_surface(self, X, Y, Z, *args, norm=None, vmin=None, | |
[cbook._array_patch_perimeters(a, rstride, cstride) | ||
for a in (X, Y, Z)], | ||
axis=-1) | ||
masked = np.any( | ||
cbook._array_patch_perimeters(mask, rstride, cstride), axis=1 | ||
) | ||
polys = polys[~masked] | ||
else: | ||
# evenly spaced, and including both endpoints | ||
row_inds = list(range(0, rows-1, rstride)) + [rows-1] | ||
|
@@ -1693,6 +1697,12 @@ def plot_surface(self, X, Y, Z, *args, norm=None, vmin=None, | |
cbook._array_perimeter(a[rs:rs_next+1, cs:cs_next+1]) | ||
for a in (X, Y, Z) | ||
] | ||
# If any of the perimeters are masked, then skip the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you test this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added another test for this based on the example above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this behavior desirable? If everything but the perimeter of the polygon is masked, do we really want to draw the polygon? Some other choices would be:
Whatever you decide on, I think it's important to describe the choice in the docstring. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a good question and I'm happy to have more input on this topic. My line of thought is that as long as the perimeters of the polygons don't contain masked data, then it is ok to draw the polygon. If some data inside of the polygon is masked but is strided over, then it is not used to make the plot anyway so we aren't "revealing" masked data in the plot. I understand this might cause a bit of confusion due to the nature of the
and
These seem like "advanced" use cases to me but happy to hear if others think differently. Though I still don't think anyone would want the perimeter of a polygon to contain masked data. As far as I can tell, no one has requested this kind of feature before.
Probably the ideal solution, if any one has suggestions how the can be accomplished then I'm happy to hear them! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I want input from @ianthomas23 about how he handled masked data for the contouring functions. I think it would make sense to be consistent with those rules. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Of course, the concepts don't perfectly overlap because the contouring algorithms don't have a concept of striding, but I am still interested in his input. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe striding does anything other than a simple decimation at the moment? If so I don't see why it would do something fancy for a mask. You could easily have the same complaint about a sharp spike that gets strided over. If folks want to properly decimate their data they can do so before passing to mpl. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It doesn't decimate the space fully, as the perimeter is still drawn at full precision. But looking closely, the colormap color is computed based only on the perimeter, so I guess the implemented behavior is consistent. |
||
# polygon | ||
if np.any(cbook._array_perimeter( | ||
mask[rs:rs_next+1, cs:cs_next+1] | ||
)): | ||
continue | ||
# ps = np.stack(ps, axis=-1) | ||
ps = np.array(ps).T | ||
polys.append(ps) | ||
|
@@ -1730,7 +1740,7 @@ def plot_surface(self, X, Y, Z, *args, norm=None, vmin=None, | |
polyc.set_facecolors(colset) | ||
|
||
self.add_collection(polyc) | ||
self.auto_scale_xyz(X, Y, Z, had_data) | ||
self.auto_scale_xyz(X, Y, Z[~mask], had_data) | ||
|
||
return polyc | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if X or Y have a mask? My guess is we should take the union of all the masks to compute an 'overall' mask here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question, I see that
pcolormesh
doesn't accept maskedX
andY
values (but it looks likepcolor
might). I've not testedcontour
but it looks like masks are ignored onX
andY
values?