First time here? Check out the FAQ!

Ask Your Question
1

Plot 3d data

asked 2 years ago

BenBoggart gravatar image

updated 2 years ago

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.

Preview: (hide)

Comments

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

FrédéricC gravatar imageFrédéricC ( 2 years ago )

@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 ( 2 years ago )

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 ( 2 years ago )

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 ( 2 years ago )

2 Answers

Sort by » oldest newest most voted
0

answered 2 years ago

Emmanuel Charpentier gravatar image

updated 2 years ago

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,

Preview: (hide)
link

Comments

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

BenBoggart gravatar imageBenBoggart ( 2 years ago )
0

answered 2 years ago

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)]])
Preview: (hide)
link

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: 2 years ago

Seen: 747 times

Last updated: Jun 03 '22