3
votes

I am plotting some data as a 3D surface plot using Matplotlib. The code I am using is pretty similar to this 3D surface plot example. It generates the plot shown below:

enter image description here

The problem with this plot is that the Z-axis is not vertical. How do I make the Z-axis vertical?

I examined the different API available and found view_init. By setting a low elevation (elev=1) of the plot using view_init, I can get the Z-axis to be vertical, as shown below:

enter image description here

However, the problem here is that at low elevation the Y axis tick labels are all overwritten and cannot be viewed correctly. So I need the plot to be at a high elevation and with the X-Y plane rotation angle as shown in Figure 1. How do I achieve a vertical Z-axis for this plot?

I do not know Matlab, but I know Matplotlib is derived from the Matlab API. So, I looked at surface plot examples in Matlab documentation and found that the Z-axis seems to be vertical in their examples. One figure for illustration with high elevation is shown below:

enter image description here

Update 1: Based on Bentoy13's suggestion, I set view_init(elev=30, azim=-37.5) and got the below result. It is better, but not yet vertical:

enter image description here

In comparison, Z-axis in Matlab plot is perfectly vertical. Also, as is visible from this angle, I cannot actually use this azim=-37.5 since some information is hidden. Any other solution? :-)

2
It looks like perpertive projection/ortographc proyection problem - Ander Biguri

2 Answers

3
votes

In MPL 2.1.01 they added the option to manually override the projection to generate your 3d graph with an orthographic projection; simply insert the following line into your script:

ax.set_proj_type('ortho')

[Example from MPL source 1]

1 https://matplotlib.org/users/prev_whats_new/whats_new_2.1.0.html

2
votes

In the examples given in the Matlab documentation, surface plots are often viewed in a special position which is given by the command view:

view(3)

The command view sets the viewpoint of the axes. According to the doc, view(3) sets the default three-dimensional view with azimutal = –37.5 and elevation = 30.

EDIT

The problem of having a vertical z-axis is not that the axis is vertical, but is a problem of perspective. By default, Matlab plots 3D surfaces with a orthographic projection, but matplotlib seems to draw with perspective projection. Sadly matplotlib doesn't provide an API for setting this...

EDIT 2

It appears that the following patch is very useful to draw 3D in orthographic projection:

import numpy
from mpl_toolkits.mplot3d import proj3d
def orthogonal_proj(zfront, zback):
    a = (zfront+zback)/(zfront-zback)
    b = -2*(zfront*zback)/(zfront-zback)
    return numpy.array([[1,0,0,0],
                        [0,1,0,0],
                        [0,0,a,b],
                        [0,0,0,zback]])
proj3d.persp_transformation = orthogonal_proj

I take no credit for this patch, you can find it here.