8000 [Bug]: 3D plot_surface edge tearing with masked array · Issue #22918 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

[Bug]: 3D plot_surface edge tearing with masked array #22918

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

Closed
Jeffrey-Alec-Smith opened this issue Apr 27, 2022 · 2 comments
Closed

[Bug]: 3D plot_surface edge tearing with masked array #22918

Jeffrey-Alec-Smith opened this issue Apr 27, 2022 · 2 comments

Comments

@Jeffrey-Alec-Smith
Copy link

Bug summary

Using plot_surface with masked arrays can lead to tearing at the edges between the data and the mask.
I have created a question on StackOverflow with images of the tearing: Here's the link

Code for reproduction

# The code below is the closest I could get to artificially reproducing the effect,
# I am not sure if the tearing in this example is the same kind as the one I posted to StackOverflow.
%matplotlib notebook

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from mpl_toolkits.mplot3d import Axes3D
import math

def wave(x, y):
    return math.cos(x * 0.05) * math.sin(y * 0.05)

data = np.zeros(shape=(256, 256))
length, height = data.shape
for x in np.arange(length):
    for y in np.arange(height):
        data[x][y] = wave(x, y)
data[(data < 0.25) | (data > 0.75)] = 0
        
fig = plt.figure(figsize=(3, 3))
ax = fig.add_subplot(1, 1, 1)
ax.set_xticks([])
ax.set_yticks([])
ax.set_title("Data")
ax.imshow(data)
plt.show()

data_masked = np.ma.masked_where(data == 0, data)
fig = plt.figure(figsize=(3, 3))
ax = fig.add_subplot(1, 1, 1)
ax.set_xticks([])
ax.set_yticks([])
ax.set_title("Masked data")
ax.imshow(data_masked)
plt.show()
        
length, width = data.shape
X, Y = np.meshgrid(np.arange(length), np.arange(width))
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(1, 1, 1, projection='3d')
ax.plot_surface(
    X, 
    Y, 
    data, 
    cmap=plt.cm.viridis,
    cstride=1,
    rstride=1,
    linewidth=0,
    antialiased=False
)
ax.set_title("Surface plot of data")
plt.show()

length, width = data.shape
X, Y = np.meshgrid(np.arange(length), np.arange(width))
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(1, 1, 1, projection='3d')
ax.plot_surface(
    X, 
    Y, 
    data_masked, 
    cmap=plt.cm.viridis,
    cstride=1,
    rstride=1,
    linewidth=0,
    antialiased=False
)
ax.set_title("Surface plot of masked data")
plt.show()

Actual outcome

Tearing near the edges on the example code

Expected outcome

Smooth edges at the boundaries between data and mask.

Additional information

Tearing from my real heightmap data:
image
Note: unlike in the code above this example has antialising on and rstride & cstride set to 1.
If I run the heightmap plot with the same parameters as the above code I get similar (albeit more blocky) results:
image

In both the example code and with my actual heightmap the underlying masked values are already set to 0, so if you plot the unmasked data you get a steep cliff. Perhaps this effect still comes through even if the data is masked.

Operating system

Windows 10

Matplotlib Version

3.5.1

Matplotlib Backend

nbAgg

Python version

3.9.12

Jupyter version

Jupyter Notebook 6.4.8

Installation

conda

@scottshambaugh
Copy link
Contributor
scottshambaugh commented Nov 27, 2023

I believe this is related to and may be addressed by the fix for #25804, I'll run the example code when I get home later.

Note that partial clipping such that there is a smooth cutoff at your z=0.25 and z=0.75 boundaries is not possible with the current renderer.

@scottshambaugh
Copy link
Contributor
scottshambaugh commented Nov 28, 2023

Unfortunately the stackoverflow link seems to be broken, and while I can recreate your "actual outcome" plot, I can't recreate the jagged waterfall edges on your second two plots without that data available.

As I briefly noted in my previous comment and gone into more detail in that linked ticket, a smooth boundary at a certain z level would require a rewrite of the 3D renderer, and is the topic of this earlier ticket: #8902. Going to close this ticket for now as a duplicate but please feel free to reopen if you have the data available to share!

@scottshambaugh scottshambaugh closed this as not planned Won't fix, can't repro, duplicate, stale Nov 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants
0