How would I plot the surface f(x,y)=xy-y-x+1 between \sqrt2\leq y\leq2
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);
How would I plot the surface f(x,y)=xy-y-x+1 between \sqrt2\leq y\leq2
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);
It is not quite clear to me what the question is. However, you can use Plots
as follows:
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:
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
).
…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:
my_cg = cgrad([:red,:blue])
thus
plot(x,y,f,st=:surface,c=my_cg,camera=(-30,30))
leading to:
I think using PyPlot.surf
was misguided since I had tried.
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()}
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
:
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.
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)
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))
I’ve seen this example Plotting a 3D Surface, 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
Oops, I paste in the wrong image in the wrong place. Pyplot output looks like this:
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:
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:
A few comments:
PyPlot
. An alternative is to use pyplot
as a back-end to the Plots
API – as I’ve done.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.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
.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.camera
option in plot
– sometimes it is necessary to do this to rotate the coordinate system to get a good view of the object.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
import Plots
Plots.pyplot()
But when I get to the end of my program, where I call
Plots.gui()
to display the plot, I get
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
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”:
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
┌ 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
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?
(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.)
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.
Here’s what happens when I look from a viewpoint too close to where the sun is in the sky:
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.
As always, thanks for your patience and interest in reading through all this.
Brad
I normally use Jupyter/IJulia in my exploration. When I use Juno (Atom with addition), I do the same thing as in IJulia:
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.
Since I don’t use PyPlot()
directly, someone else would need to answer this.
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))
How to use diffrent colors (R,G,B ), for aeach ny series (a,b,c)
Thx, Paul
add the call zcolor=???
I think.
Something like this? First (assuming 5 data sets) do:
using Plots
#
N=5
M = [:o,:v,:^,:x,:+]
seed=colorant"blue"
COL = distinguishable_colors(N,seed)
which leads to:
and then (in IJulia):
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:
[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)
).