Implicit plot with plots

How do I make an implicit plot with the plots package?

pyplot has a contour function which admits a fourth argument to plot a single level line.
But it does not seem to be implemented in plots.

1 Like

There is a contour function in Plots. It’s called contour IIRC.

Yes but it does not plot a single level line. Or am I missing something?

There’s lots of stuff in matplotlib that isn’t implemented in Plots yet. To know if your use case is, could you describe (or screenshot) what an implicit contour is?

The following works:

contour(-3:0.01:3, -3:0.01:3, (x,y) -> x^2 + 2y^2, levels=[2.0, 3.0])

But specifying only one level throws an InexactError.
That seems to be a bug.

As @mkborregaard said, we need to know exactly what you want to do. Could you please give the PyPlot command and output?

Hmm, that works in GR but Plotly ignores the level attribute.

So for example if I want to plot the curve given by the implicit equation x^2+y^2 = 1, I can use the following python code.

   import numpy as np
   import matplotlib.pyplot as plt
   y,x=np.ogrid[-5:5:100j,-5:5:100j]
   plt.contour(x.ravel(),y.ravel(),x^2+y^2,[1])
   plt.show()

The result is a circle of radius 1 centered at the origin. Now using the contour function for an implicit plot is as far as I understand a hack.

I can see that sympy has now a proper plot_implicit function that is documented (and live demonstrated) together with its source code here.

Thanks for your help!

1 Like

One can use https://github.com/JuliaIntervals/IntervalConstraintProgramming.jl or https://github.com/jverzani/ImplicitEquations.jl for this task. The latter is a bit slower, but has a slightly easier to use syntax:

using ImplicitEquations, Plots
f(x,y) = x^2 + y^2
plot(f ⩵ 1)  # \Equal[tab]

The SymPy solution can be called from within SymPy.jl, but that would be PyPlot specific.

4 Likes

Here are two new examples that may be useful for some (tested in Julia v1.5):

Using ImplicitPlots.jl

using ImplicitPlots, Plots

f(x,y) = (x^4 + y^4 - 1) * (x^2 + y^2 - 2) + x^5 * y

implicit_plot(f; xlims=(-2,2), ylims=(-2,2), lab="f(x) = 0")

Using IntervalConstraintProgramming.jl:

using IntervalConstraintProgramming, IntervalArithmetic, Plots

dom = IntervalBox(-2 .. 2, -2 .. 2)
@function f(x, y) = (x^4 + y^4 - 1) * (x^2 + y^2 - 2) + x^5 * y
C = @constraint f(x, y) <= 0
p = pave(C, dom, 0.01)

plot(p.inner, lw=1, ratio=1, lab="f(x, y) ≤ 0", title="")
plot!(p.boundary, lw=1, ratio=1, lab="boundary")

Using ModelingToolkit and a standard Julia function also works:

using IntervalConstraintProgramming, IntervalArithmetic, ModelingToolkit, Plots

dom = IntervalBox(-2..2, -2..2)
	
gg(x, y) = (x^4 + y^4 - 1) * (x^2 + y^2 - 2) + x^5 * y
	
vars = @variables x, y
	
C = Separator(vars, gg(x, y) < 0)
p = pave(C, dom, 0.05)
	
plot(p.inner, lw=0, ratio=1, lab="f(x, y) ≤ 0", title="")
plot!(p.boundary, lw=0, ratio=1, lab="boundary")
5 Likes

For completeness, there is also now the MDBM package, illustrated below with Plots:

f(x,y) = (x^4 + y^4 - 1) * (x^2 + y^2 - 2) + x^5 * y
xs, ys = -2:.25:2, -2:.25:2

using MDBM
m = MDBM_Problem(f, [xs, ys])
solve!(m, 4)
p = plot(xlim=extrema(xs), ylim=extrema(ys), legend=false)
mdt=MDBM.connect(m)
for i in 1:length(mdt)
    dt=mdt[i]
    P1=getinterpolatedsolution(m.ncubes[dt[1]], m)
    P2=getinterpolatedsolution(m.ncubes[dt[2]], m)
    plot!(p, [P1[1],P2[1]],[P1[2],P2[2]])
end
p
3 Likes

I have tried both ImplicitPlots.jl and ImplicitEquations.jl. There is one point that I am missing: how can I change the color of the lines? Apparently, the latter only accepts “black” (by default), while the former only accepts blue (by default). Sometimes, if we want to plot two implicit functions, it makes sense to have the possibility to change colors.

You should just be able to use Plots.jl’s contour function.

1 Like

@dpsanders thanks a lot. It works, it’s fast and versatile.

1 Like