Ask Your Question
1

Plot 3d data

asked 2022-05-09 23:58:10 +0100

BenBoggart gravatar image

updated 2022-06-03 22:24:56 +0100

I've been unable to find any viable solution although I'm quite sure there's an easy one.

I'd like to plot a surface from a matrix with some hundred rows that specify a point each, i.e. x y z. The point3d function does the ranges right but lacks the surface option; list_plot3d provides the surface, but does plot by the row/colum indeces instead of the x,y values.

Which function would do the trick?

Ben


(Edit) Thank you both, Frédéric and Emmanuel! Unfortunately, I cannot apply your answers to my problem properly, mainly because I dont fully understand them.

  • In Frédéric's answer, M seem's to be a 2x2x3 array and I'm unable to transfer the approach to my Nx3 matrix.
  • Emmanuel's list(zip(X,Y,Z)) looks very much like list(myMatrix), but with list_plot3d I still don't get anything like the anticipated result.

I'll try to provide my example here:

myMatrix=[(0.5, 0.0, 29.0),
 (1.5, 0.0, 29.0),
 (2.5, 0.0, 30.0),
 (3.5, 0.0, 38.0),
 (5.0, 0.0, 45.0),
 (5.01, 0.0, 0.0),
 (6.0, 0.0, 0.0),
 (0.0, 0.8, 26.0),
 (0.5, 0.8, 25.0),
 (1.5, 0.8, 24.0),
 (2.5, 0.8, 25.0),
 (3.5, 0.8, 35.0),
 (5.0, 0.8, 39.0),
 (5.01, 0.8, 0.0),
 (6.0, 0.8, 0.0),
 (0.0, 1.8, 27.0),
 (0.5, 1.8, 25.0),
 (1.5, 1.8, 22.0),
 (2.5, 1.8, 22.0),
 (3.5, 1.8, 27.0),
 (5.0, 1.8, 38.0),
 (5.01, 1.8, 0.0),
 (6.0, 1.8, 0.0),
 (0.0, 2.8, 22.0),
 (0.5, 2.8, 20.0),
 (1.5, 2.8, 19.0),
 (2.5, 2.8, 22.0),
 (3.5, 2.8, 28.0),
 (5.0, 2.8, 42.0),
 (5.01, 2.8, 0.0),
 (6.0, 2.8, 0.0),
 (0.0, 3.8, 14.0),
 (0.5, 3.8, 12.0),
 (1.5, 3.8, 10.0),
 (2.5, 3.8, 13.0),
 (3.5, 3.8, 21.0),
 (5.0, 3.8, 39.0),
 (5.01, 3.8, 0.0)]
myLiPlo3d=list_plot3d(myMatrix,aspect_ratio=[1,1,0.02])
myLiPlo3dLi=list_plot3d(list(myMatrix),aspect_ratio=[1,1,0.02])
myPlo3d=point3d(myMatrix,size=20,aspect_ratio=[1,1,0.02])

Now

show(myPlo3d)

does result in the plot I'm looking for, except for the fact that it's just points and not a connected surface. However, both,

show(myLiPlo3dLi)
show(myLiPlo3d)

result in a totally different z-scale and shape.


Thinking as I'm editing: May this strange scaling be an artifact of perfect polynomial fitting? That's not what I'm looking for, I don't want any overswings (is that an English word?); I'd even be ok with bilinear interpolation.

edit retag flag offensive close merge delete

Comments

give us a toy minimal example of the data you want to plot

FrédéricC gravatar imageFrédéricC ( 2022-05-13 15:48:16 +0100 )edit

@BenBoggart : your data may be questionable :

sage: list_plot3d(myMatrix, interpolation_type='linear', aspect_ratio=[8, 8, 1])
/usr/local/sage-9/local/var/lib/sage/venv-python3.10/lib/python3.10/site-packages/sage/repl/rich_output/display_manager.py:605: UserWarning: Warning: converting a masked element to nan.
  return obj._rich_repr_(self)
Launched html viewer for Graphics3d Object
Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2022-06-03 23:46:33 +0100 )edit

Your problem can be visualized.

Res ipsa loquitur...

Playing with parametric_plot3d and more suitable interpolation functions may be a better idea...

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2022-06-04 00:00:41 +0100 )edit

Awesome, your answer solves my problem as well as it teaches me two or three things about sagemath! Thanks a lot.

I've re-checked the data and don't see any two point having the same x,y-coordinates. The gradient from 5.00 to 5.01 could be a bit steep, but with linear interpolation, I don't really see a numerical issue. Anyway, the plot looks fine for me, so I won't dig into that.

Btw, it may entertain you to know that this is to visualize my floor and get an impression of where to apply some floating screed.

BenBoggart gravatar imageBenBoggart ( 2022-06-04 18:30:46 +0100 )edit

2 Answers

Sort by » oldest newest most voted
0

answered 2022-05-13 22:51:09 +0100

Emmanuel Charpentier gravatar image

updated 2022-05-13 22:56:11 +0100

WorksForMe(TM) in Sagecell and in Sage 9.6.rc3. Let's assess the density of a bivariate standard normal by plotting 1000 random points (I use R's functions by pure laziness...) :

set_random_seed(0)
X=r.rnorm(1000,0,1)._sage_()
Y=r.rnorm(1000,0,1)._sage_()
Z=r.dnorm(list(map(lambda u,v:sqrt(u^2+v^2), X, Y)),0,1)._sage_()
P=list_plot3d(list(zip(X,Y,Z)))
show(P, aspect_ratio=[1,1,5])

See for yourself !

HTH,

edit flag offensive delete link more

Comments

The final solution is in Emmanuel's 3rd comment and the link there.

BenBoggart gravatar imageBenBoggart ( 2022-06-04 18:33:39 +0100 )edit
0

answered 2022-05-13 18:12:04 +0100

FrédéricC gravatar image

Shooting in the dark, here is a tentative

def plot_cloud_matrix(M):
    m = len(M)
    n = len(M[0])
    P = point3d(M[0][0])
    for i in range(m-1):
        for j in range(n-1):
            pta = M[i][j]
            ptb = M[i+1][j]
            ptc = M[i+1][j+1]
            ptd = M[i][j+1]
            P += polygon3d([pta,ptb,ptc,ptd])
    return P

plot_cloud_matrix([[(0,1,2),(0,1,1.2)],[(0.5,1,2),(0.1,1,1.1)]])
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2022-05-09 23:58:10 +0100

Seen: 674 times

Last updated: Jun 03 '22