pyvista icon indicating copy to clipboard operation
pyvista copied to clipboard

When drawing a scatter points spread over multiple areas, the coordinates of gird are incorrect.

Open Stewie055 opened this issue 1 year ago • 2 comments

Describe the bug, what's wrong, and what you expected.

I have some scatter points spread over multiple areas。When plotting them, the gird line in pyvista does not show correctly.

the plot result of pyvista, the 0 pos of X should in the minddle, but it doesn'timage

plot result of matplotlib image

Steps to reproduce the bug.

import pyvista as pv
import numpy as np
pl = pv.Plotter()

def generate_snape(center_x):
    """ generate scatters """
    x = np.linspace(center_x - 1.72364324078285, center_x + 1.72364324078285, 10)
    y = np.linspace(-3, 3, 10)
    z = np.zeros(len(x) * len(y))
    mesh = np.transpose([np.tile(x, len(y)), np.repeat(y, len(x)), z])
    _ = pl.add_mesh(mesh)
    return mesh

mesh = generate_snape(0)
mesh2 = generate_snape(-10)
mesh3 = generate_snape(10)
_ = pl.show_grid(all_edges=True)
pl.show()

## matplotlib part
#import pandas as pd
#import matplotlib.pyplot as plt
# fig = plt.figure()
# ax = fig.add_subplot()
# ax.scatter(mesh[:,0], mesh[:,1])
# ax.scatter(mesh2[:,0], mesh2[:,1])
# ax.scatter(mesh3[:,0], mesh3[:,1])
# ax.set_xlabel('X Label')
# ax.set_ylabel('Y Label')
# plt.show()

System Information

--------------------------------------------------------------------------------
  Date: Tue Jan 23 17:36:07 2024 中国标准时间

                OS : Windows
            CPU(s) : 12
           Machine : AMD64
      Architecture : 64bit
               RAM : 31.8 GiB
       Environment : Python
        GPU Vendor : Intel
      GPU Renderer : Intel(R) UHD Graphics 630
       GPU Version : 4.5.0 - Build 23.20.16.5017
  MathText Support : False

  Python 3.9.12 (tags/v3.9.12:b28265d, Mar 23 2022, 23:52:46) [MSC v.1929 64
  bit (AMD64)]

           pyvista : 0.43.0
               vtk : 9.2.6
             numpy : 1.24.4
        matplotlib : 3.5.2
            scooby : 0.7.2
             pooch : v1.7.0
            pillow : 10.0.0
         pyvistaqt : 0.11.0
           IPython : 8.14.0
        ipywidgets : 8.0.7
             scipy : 1.9.0
      nest_asyncio : 1.5.6
--------------------------------------------------------------------------------

Screenshots

image

Stewie055 avatar Jan 23 '24 09:01 Stewie055

Hi,

Short answer : you can change _ = pl.show_grid(all_edges=True) by _ = pl.show_grid(all_edges=True, n_xlabels=4) (or any value strictly smaller than 5, 5 being the default value). It seems that there is a bug here and the ticks are displayed as expected only for small values of n_xlabels.

Capture d’écran du 2024-01-24 11-33-26

Long answer the behavior of show_grid wrt to n_xlabels, n_ylabels and n_ylabels is surprising. It seems that above a certain threshold, the ticks of the CubeAxesActor are not displayed as expected. In the @Aaron1992's example, the same weird behavior for Y appears as soon as n_ylabels >= 8.

Changing the scene also changes the values of the threshold, as an example, if we change the way data is generated along the X axis, we can have 5 ticks:

mesh = generate_snape(0)
mesh2 = generate_snape(-5) # -10 in the previous example 
mesh3 = generate_snape(5) # 10 in the previous example
_ = pl.show_grid(all_edges=True, n_xlabels=5, n_ylabels=5)
pl.show()

Result: Capture d’écran du 2024-01-24 11-35-49

But here again, with higher values for n_xlabels and n_ylabels, we can see the same undesired behavior. The issue appears again as soon as n_xlabels >= 7.

It seems that the vtk CubeAxesActor wrapped by PyVista has the right list of labels along each axis, but the position of the ticks is not set accordingly. I wasn't able to find a way to reconfigure manually the position of the ticks reading the doc, but my experience with core vtk is limited, perhaps someone can help finding a solution.

I realized that it was possible to guess the maximum value of n_xlabels with the following trick: In pyvista.plotting.cube_axes_actor I removed all calls with self._update_x_labels(), self._update_y_labels() or self._update_z_labels(). Then I ran the example from this issue:

mesh = generate_snape(0)
mesh2 = generate_snape(-10)
mesh3 = generate_snape(10)
grid = pl.show_grid(all_edges=True)
pl.show()

and obtained Capture d’écran du 2024-01-24 14-26-15

My interpretation (I don't fully understand what is going on on the vtk side) is that by default the number of ticks is set to 5, it is possible to reduce it but not increase it afterward, and choosing n_xlabels=5 seems to lead to a translation of the ticks (initially centered) to the boundary of the box, letting on the other side a blank space smaller than intial offset between labels.

In the situation generate_snape(-5) and generate_snape(5), I obtained 7 ticks by default, and again, it was the threshold here: Capture d’écran du 2024-01-24 14-29-38

It seems that there is a maximal number of ticks than can be displayed along each axis, setting at initialization, and then only some reshaping are possible. I tried to fix it playing around with underlying VTK CubeAxesActor but I didn't manage to find a solution. Perhaps someone with more experience with this class will see what's going on here.

Louis-Pujol avatar Jan 24 '24 13:01 Louis-Pujol

unfortunatley, no solution from my side. I just stumbled accros the same bug. Plotting a pointcloud, adding the associated grid with .show_bounds and adjustung the n_xlabels > 7 led to the same issue.

For now we have to keep n_xlabels to default to avoid wrong labeling.

wrong: screenshot - Copy

correct labeling: screenshot

andysfd avatar Jan 30 '24 09:01 andysfd