# Plotting a 3D Surface

**URL:** <https://discourse.julialang.org/t/plotting-a-3d-surface/17143>\
**Category:** New to Julia\
**Created:** [November 4, 2018, 7:23pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143 "2018-11-04T19:23:36Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![oliver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oliver/32/19264_2.png) [@oliver](https://discourse.julialang.org/u/oliver)\
**Post date:** [November 4, 2018, 7:23pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/1 "2018-11-04T19:23:36Z")

</div>

How would I plot the surface f(x,y)=xy-y-x+1 between \sqrt2\leq y\leq2

```julia
using PyPlot;
x = collect(Float16, range(-2,length=100,stop=2));
y = collect(Float16, range(sqrt(2),length=100, stop=2));
z = (x.*y).-y.-x.+1;
surf(x,y,z);

```

![Figure_1-1](https://global.discourse-cdn.com/julialang/original/3X/6/2/6209dac050003cf6bddead41d18a0ddb3794236f.png)

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [November 4, 2018, 8:07pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/2 "2018-11-04T20:07:25Z")

</div>

It is not quite clear to me what the question is. However, you can use `Plots` as follows:

```plaintext
using Plots; pyplot()
x=range(-2,stop=2,length=100)
y=range(sqrt(2),stop=2,length=100)
f(x,y) = x*y-x-y+1
plot(x,y,f,st=:surface,camera=(-30,30))

```

with result:  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/3/c/3c4bddb8ab8cffc2095ddc81d9c755d5d31b1e5e.jpeg)  
Here, `st` is short hand for `seriestype` (or something similar). Keyword `camera` sets the camera/viewing angles. I have used the default heatmap.  
If you want to plot contours, you can plot contour lines (`st=:contour`) or filled countours (`st=:contour`).

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [November 4, 2018, 8:16pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/3 "2018-11-04T20:16:57Z")

</div>

…if you want to use another heatmap, just set the `color` (or `c`) argument to some color gradient, e.g., a built in such as `:blues` or make your own, say:

```plaintext
my_cg = cgrad([:red,:blue])

```

thus

```plaintext
plot(x,y,f,st=:surface,c=my_cg,camera=(-30,30))

```

leading to:  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/4/8/489d684d81aa5866e17180835b23a5ef98378c9b.jpeg)

---

<div class="post-metadata">

**Author:** ![oliver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oliver/32/19264_2.png) [@oliver](https://discourse.julialang.org/u/oliver)\
**Post date:** [November 4, 2018, 8:18pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/4 "2018-11-04T20:18:19Z")

</div>

I think using `PyPlot.surf` was misguided since I had tried.

```julia
using PyPlot;
x = collect(Float16, range(-2,length=100,stop=2));
y = collect(Float16, range(sqrt(2),length=100, stop=2));
f(x,y) = x*y-x-y+1
surf(x,y,f);
ERROR: MethodError: no method matching 
surf(::Array{Float16,1}, ::Array{Float16,1}, ::typeof(f))

```

Clearly `PyPlot` \neq `{Plots,pyplot()}`

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [November 4, 2018, 11:08pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/5 "2018-11-04T23:08:41Z")

</div>

Well, it is possible that `Plots` with `pyplot()` sets some defaults for `PyPlot`, so that the `Plots` results are uniform for different backends such as `pyplot()`, `gr()`, etc. In any way, I’ve changed the `camera` angle — I think you often need to do that to get ok plots with 3D surface plots. Here is the default camera angle, with `c = :blues`:  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/8/0/804c140e3e8140963896e07f212893e896f254f8.jpeg)

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [November 4, 2018, 11:21pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/6 "2018-11-04T23:21:16Z")

</div>

I do notice that my way of plotting lets f(x,y) range from ca. -3 and upwards, while your plot seems to range from -1. Perhaps that is why it looks differently? I’ve checked the function plot in WolframAlpha, and the result I have looks very similar to that plot. I haven’t tried to use `PyPlot` directly from Julia.

---

<div class="post-metadata">

**Author:** ![Brad\_Hines](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brad_hines/32/9885_2.png) [@Brad\_Hines](https://discourse.julialang.org/u/Brad_Hines)\
**Post date:** [August 26, 2019, 10:08pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/7 "2019-08-26T22:08:13Z")

</div>

I’m trying to figure out how to do the equivalent of Matlab fill3, which draws a filled 3D polygon, in Julia Plots.

I can do with PyPlot (although I don’t understand the diagonal stripe):

using PyPlot  
xc = [0;0;1;1]  
yc = [0;1;1;0]  
zc = [1;1;2;2]  
plt = PyPlot.surf(xc,yc,zc)

![image](https://global.discourse-cdn.com/julialang/original/3X/1/2/12e27695035ac3b0ca9dacffb6bd8986a21a4fe7.png)

When I try the same thing in Julia Plots, with plot type :surface, I get this.

import Plots  
Plots.plotlyjs()  
xc = [0;0;1;1]  
yc = [0;1;1;0]  
zc = [1;1;2;2]  
plt = Plots.plot(xc,yc,zc,st=:surface)

First, it’s zoomed out way too far. But it’s not just a limits thing – if I set the limits to zoom in on where the polygon is supposed to be, there’s nothing there:

plt = Plots.plot(xc,yc,zc,st=:surface,xlims=(-1,2),ylims=(-1,2),zlims=(0,3))

![image](https://global.discourse-cdn.com/julialang/original/3X/3/9/39ba13dc014a88c221679d114038f0dbabf1a630.png)

I’ve seen this example [Plotting a 3D Surface](https://discourse.julialang.org/t/plotting-a-3d-surface/17143), which includes a generator function for z, but I can’t figure out how to supply my own z coordinates.

I’ve tried supplying my own colormap, but that doesn’t help either.

Any tips on what I’m doing wrong?

Thanks,  
Brad

---

<div class="post-metadata">

**Author:** ![Brad\_Hines](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brad_hines/32/9885_2.png) [@Brad\_Hines](https://discourse.julialang.org/u/Brad_Hines)\
**Post date:** [August 26, 2019, 10:09pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/8 "2019-08-26T22:09:10Z")

</div>

Oops, I paste in the wrong image in the wrong place. Pyplot output looks like this:

![image](https://global.discourse-cdn.com/julialang/original/3X/b/1/b10ddc3fb9875940e0dc8b4ec90a02c5dea364c6.png)

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [August 28, 2019, 4:05pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/9 "2019-08-28T16:05:56Z")

</div>

A suggestion: when you insert code, it looks much better if you use mark-up. In-line code is typeset by enclosing it with single back-tic. Displayed code should be enclosed in triple back-tics, and the first triple back-tic allows to specify the language in case you want syntax high-lighting.

The following code uses `Plots` and `pyplot` as back-end:

```julia
using Plots; pyplot();

xc = [0,0,1,1]
yc = [0,1,1,0]
zc = [1,1,2,2];

plot(xc,yc,zc,st=:surface,camera=(-30,30))

```

The result is as follows:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/c/1/c1e116edaba62e9e21c15bfe0e573efe919239c8.png)

A few comments:

1. In your first case, you use raw `PyPlot`. An alternative is to use `pyplot` as a back-end to the `Plots` API – as I’ve done.
2. In your case of using `Plots`, you use the `plotlyjs` back-end. I used the `pyplot` back-end. There is also a `gr` back-end, etc. The `gr` back-end is the default for `Plots`. In my view, `gr` gives the purest/prettiest lines, etc. However, `pyplot` seems to have slightly better support of the `Plots` API, and also has the best \LaTeX support.
3. Your plot using `plotlyjs` back-end doesn’t really show any plot in my browser. I don’t know why; in any way, I use `pyplot` as back-end to `Plots`.
4. You import `Plots` using statement `import Plots`. That is fine; if you do so, you need to use the package name when issuing the command, i.e., `Plots.plot`. I import `Plots` by statement `using Plots` – the advantage is that then you don’t need to specify the package name. Such import is less “dangerous” in Julia than in, say, Python, because of Julia’s multiple dispatch idea.
5. Observe that I used the `camera` option in `plot` – sometimes it is necessary to do this to rotate the coordinate system to get a good view of the object.
6. Finally, I prefer to use comma (“,”) to separate vector elements; you have used semicolon (“;”). This is not a big thing here.

---

<div class="post-metadata">

**Author:** ![Brad\_Hines](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brad_hines/32/9885_2.png) [@Brad\_Hines](https://discourse.julialang.org/u/Brad_Hines)\
**Post date:** [August 28, 2019, 9:17pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/10 "2019-08-28T21:17:28Z")

</div>

Thanks so much! This works for me. Thanks also for the tips on composing messages.

Now I’m on to another question, which is “how do I see my plot”? The example (which I am running using Shift-Enter in Atom) pops up in my Atom Plots pane, but when I try to run my program, I get errors. The plot displays fine if I use plotly or plotlyjs.

* * *

Here’s the backdrop.

I went from my example program back to my real program, which I have changed to say

```julia
  import Plots
  Plots.pyplot()

```

But when I get to the end of my program, where I call

```julia
  Plots.gui()

```

to display the plot, I get

```julia
sys:1: UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.

```

In an earlier run - I thought everything was the same, I can’t quite figure out what was different - I got

```julia
Warning: _display is not defined for this backend.
└ @ Plots C:\Users\brad\.julia\packages\Plots\Ih71u\src\output.jl:186

```

When I was using straight PyPlot, if I recall correctly, I could say `pygui(:qt)` or the like to get a plot, but that doesn’t work.

I have tried all three of these, but I either get “UndefVarError” or “type #pyplot has no field”:

```julia
  pygui(:qt)
  Plots.pygui(:qt)
  Plots.pyplot.pygui(:qt)

```

This is the kind of thing that can drive a person crazy while trying to get up to speed on Julia. It seems like the system should just default to something that “works”, whatever that means.

I am running in the Atom/Juno environment. I’ve heard suggestions before to “just run Julia”. I hadn’t really groked what that meant, but I did just open a standalone Julia shell and was able to run my program.

When I do that, I get the

```julia
┌ Warning: _display is not defined for this backend.
└ @ Plots C:\Users\brad\.julia\packages\Plots\Ih71u\src\output.jl:186

```

error when I get to Plots.gui()

I’ve also seen suggestions to type `gcf()`. But both `Plots.gcf()` and `gcf()` give "UndefVarError`

I’ve also read that "when using PyPlot in Atom, you need to uncheck `Settings/Packages/Julia Client/UI Options/Enable Plot Pane`. Or, if you want to display your PyPlot plots in Atom with Juno (without changing the settings), you could also add `gcf()` at the end of your plotting code.

I seem to recall that at least the first of these worked with raw PyPlot. But when I just tried it now with Plots.pyplot, nothing happens at all.

* * *

Can anybody help me diagnose what these error messages mean or how to fix them? I could try to boil this down to a MWE, but in truth it will be faster for me to rip out Plots and go to raw PyPlot than to try to do that, and I’ve a got an end of week deadline for my client.

Thanks for taking the time to read through all this.

Brad

---

<div class="post-metadata">

**Author:** ![Brad\_Hines](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brad_hines/32/9885_2.png) [@Brad\_Hines](https://discourse.julialang.org/u/Brad_Hines)\
**Post date:** [August 28, 2019, 10:57pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/11 "2019-08-28T22:57:32Z")

</div>

Three more questions about 3D, for anyone that still has patience.

I wonder if some of these may devolve into a question of “how do I use the extra\_kwargs to pass args to the underlying engine?” Are there any examples of that that anyone knows of? Can you nest them - i.e., can I pass args to PyPlot, that it then passes on to matplotlib?

1. Does anybody know how to plot a 3D polygon with holes in it? (I am doing a solar tracking sim and using the Clipper library ([http://www.angusj.com/delphi/clipper.php](http://www.angusj.com/delphi/clipper.php)), which I’ve used before in Matlab.) Certain reflection patterns from my group of mirrors can lead to checkerboard illumination patterns (polygons with holes). Clipper can compute these complex shapes. I’d like to then plot the illumination pattern on the target.

(In 2D you could just draw the enclosing shape in, say, solid black, and then draw the “holes” as white. But in 3D you can’t do that because the polygons never quite lie in the same plane at the 10th decimal place, so the scene ends up changing depending on the viewpoint.)

1. I’d like more control over the camera than I get from just az/el. The engine seems to choose its own zoom regardless of what I set for xlims/ylims/zlims. (Although that might have only been for plotly - will have to check pyplot once I figure out how to see the plots.) I would make an animation of a full day, and the scale was constantly changing as my light rays changed position during the day. (It’s an animation of a full day of solar tracking.)

At least with plotly and plotlyjs, I had to resort to a trick to control the zoom. I draw invisible (white) lines at the extents of my scene, and that seems to prevent unwanted zooming.

1. Similarly, I’d like to control the amount of perspective applied. (This is more or less equivalent to setting a viewpoint and a zoom.) So I’d like to control the camera eyepoint, not just az/el, and also either zoom or perspective. (That is, to minimize perspective effects, I can look from a long way off and zoom in.) With my solar tracker sim, there are times during they day when rays that should be parallel turn into a cone (below). It’s a bit embarrassing to explain to my client that I don’t know how to fix that.

Here’s what happens when I look from a viewpoint too close to where the sun is in the sky:

![image](https://global.discourse-cdn.com/julialang/original/3X/d/a/da7ae50d4841911239940873100abaec011ed514.jpeg)

You can see that the perspective effect is rather severe - the two axes are well off from 90 degrees from each other.

Here’s what happens at a slightly different time of year when the sun is further from the viewpoint. You can see that the effect is still there, but not as bad. You can see how the rays tend to lean towards the axes on either side rather than running parallel to one another.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/6/3/6394fc4cd5b6d6e28bbb884734e3808a6962fc54.jpeg)

As always, thanks for your patience and interest in reading through all this.

Brad

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [August 29, 2019, 5:29am UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/12 "2019-08-29T05:29:23Z")

</div>

I normally use Jupyter/IJulia in my exploration. When I use Juno (Atom with addition), I do the same thing as in IJulia:

```julia
using Plots; pyplot();
plot(sin,range(-2pi,2pi,length=50))

```

produces a plot in Juno’s plot window. I don’t use `pygui`, etc.

I would guess that when you use the command `Plots.pyplot()` etc., you are essentially using “raw `PyPlot`”, and not the `plot()` API of `Plots`, but I’m not sure. I used Python and dug into `Matplotlib` some 7-8 years ago, but after I switched to Julia, I have mainly used the `Plots` API based on `Plots.plot()` with `pyplot()` backend, and have not really used `PyPlot` directly. Maybe someone else have better information on this.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [August 29, 2019, 5:30am UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/13 "2019-08-29T05:30:36Z")

</div>

Since I don’t use `PyPlot()` directly, someone else would need to answer this.

---

<div class="post-metadata">

**Author:** ![programista](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/programista/32/5372_2.png) [@programista](https://discourse.julialang.org/u/programista)\
**Post date:** [November 5, 2019, 7:40pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/14 "2019-11-05T19:40:28Z")

</div>

Hi, I am starting with ploting.  
My first plot 3d:  
using Plots  
pyplot()  
a=rand(10);b=rand(10),c=rand(10)  
scatter(a,b,c,size=(500,500))  
 ![a](https://global.discourse-cdn.com/julialang/original/3X/a/3/a36274a38b76ce11c9ba121c4d42c55f750534b0.png)

How to use diffrent colors (R,G,B ), for aeach ny series (a,b,c)  
Thx, Paul

---

<div class="post-metadata">

**Author:** ![natgeo-wong](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/natgeo-wong/32/10965_2.png) [@natgeo-wong](https://discourse.julialang.org/u/natgeo-wong)\
**Post date:** [November 5, 2019, 8:24pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/15 "2019-11-05T20:24:40Z")

</div>

add the call `zcolor=???` I think.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [November 5, 2019, 10:43pm UTC](https://discourse.julialang.org/t/plotting-a-3d-surface/17143/16 "2019-11-05T22:43:06Z")

</div>

Something like this? First (assuming 5 data sets) do:

```julia
using Plots
#
N=5
M = [:o,:v,:^,:x,:+]
seed=colorant"blue"
COL = distinguishable_colors(N,seed)

```

which leads to:  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/c/0/c078687da98a2397d1b445aa7a79c6bf2f4ab463.png)

and then (in IJulia):

```julia
plot()
for i in 1:N
    a = rand(10); b = rand(10); c = rand(10);
    plot!(a,b,c,seriestype=:scatter,markercolor=COL[i],markersize=8,markerstrokecolor=COL[i],marker=M[i],label="Data set $i")
end
plot!()

```

leading to:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/f/d/fd100a28dd0b288b283152eb76a21bcd32f88658.png)

[You can, e.g., use `ms` as short form for `markersize`, `mc` as short form for `markercolor`, `st` as short form of `seriestype`, etc. Your syntax `scatter` is just a short form of `plot(..., seriestype=:scatter)`).
