Julia #eval world age missmatch - matplotlib

I'm trying to use the julia #eval functionality to only load the PyPlot package on demand. However I verry often run into world age missmatch.
Here is a minimal example where i try and plot on demand
function CreateMatrix(Ncount;Plot=true)
TheMatrix = fill(0.0,Ncount,Ncount)
if Plot
#eval using PyPlot
###"Plot the Matrix"
PyPlot.figure()
PyPlot.imshow(abs.(TheMatrix))
PyPlot.colorbar()
end
return TheMatrix
end
CreateMatrix(10;Plot=false)
CreateMatrix(10;Plot=true)
With the output
ERROR: LoadError: MethodError: no method matching figure()
The applicable method may be too new: running in world age 25063, while current world is 25079.
Closest candidates are:
figure(!Matched::Any...; kws...) at ~/.julia/packages/PyPlot/fZuOQ/src/PyPlot.jl:148 (method too new to be called from this world context.)
Stacktrace:
[1] #CreateMatrix#3(::Bool, ::Function, ::Int64) at myfile.jl:7
[2] (::getfield(Main, Symbol("#kw##CreateMatrix")))(::NamedTuple{(:Plot,),Tuple{Bool}}, ::typeof(CreateMatrix), ::Int64) at ./none:0
[3] top-level scope at none:0
[4] include at ./boot.jl:317 [inlined]
[5] include_relative(::Module, ::String) at ./loading.jl:1044
[6] include(::Module, ::String) at ./sysimg.jl:29
[7] exec_options(::Base.JLOptions) at ./client.jl:231
[8] _start() at ./client.jl:425
in expression starting at myfile.jl:16
Does anyone know how uses the #eval functionality properly?
EDIT
One of the comments suggested wrapping the plotting command and annotating with #noinline as below, but this does not work.
function CreateMatrix(Ncount;Plot=false)
TheMatrix = fill(0.0,Ncount,Ncount)
if Plot
#eval using PyPlot
###"Plot the Matrix"
ThePlotting(TheMatrix)
end
return TheMatrix
end
#noinline function ThePlotting(TheMatrix)
PyPlot.figure()
PyPlot.imshow(abs.(TheMatrix))
PyPlot.colorbar()
end
CreateMatrix(10;Plot=false)
CreateMatrix(10;Plot=true)
I'm running julia version 1.0.2

You can implement it like this:
function CreateMatrix(Ncount;Plot=true)
TheMatrix = fill(0.0,Ncount,Ncount)
if Plot
if isdefined(Main, :PyPlot)
println("PyPlot already loaded")
PyPlot.figure()
PyPlot.imshow(abs.(TheMatrix))
PyPlot.colorbar()
else
println("PyPlot loading PyPlot")
#eval using PyPlot
Base.invokelatest(PyPlot.figure)
Base.invokelatest(PyPlot.imshow, abs.(TheMatrix))
Base.invokelatest(PyPlot.colorbar)
end
end
return TheMatrix
end
I have used conditional to allow you to see which branch gets executed on repeated call to the function.
Initially I thought that when calling non-inlined function Julia allows world age change (but it turns out that it is strict).
Finally - in general it is probably safer not to write code like this but simply load the module in top-level scope (possibly conditionally).

Related

Turning off specgram auto-plotting in Jupyter notebook

I'm using Matplotlib's specgram function, which has a form like:
Pxx, freqs, bins, im = specgram(x, NFFT=NFFT, Fs=Fs, noverlap=900)
where Pxx, freqs, bins, and im represent the periodogram, frequency vector, center of time bins, and the image.AxesImage instance. Additionally, you can feed in arguments (**kwargs) that get passed onto imshow.
I cannot seem to use specgram in a Jupyter Notebook, without producing a plot automatically. What argument can I pass into specgram that will stop it from plotting automatically?
I am not calling any plt.show() command. I've tried adding a semi-colon at the end of the line, and I've tried setting the final argument (im) as nothing, like this:
Pxx, freqs, bins, _ = specgram(x, NFFT=NFFT, Fs=Fs, noverlap=900);
but nothing seems to work.
From the PyPlot.jl docs: https://github.com/JuliaPy/PyPlot.jl#non-interactive-plotting
If you use PyPlot from an interactive Julia prompt, such as the Julia command-line prompt or an IJulia notebook, then plots appear immediately after a plotting function (plot etc.) is evaluated.
However, if you use PyPlot from a Julia script that is run
non-interactively (e.g. julia myscript.jl), then Matplotlib is
executed in non-interactive mode: a plot window is not opened until
you run show() (equivalent to plt.show() in the Python examples).
See the docs linked above for further reference.

Syntax error when using imported Scipy functions in Julia

I have succesfully imported Scipy Optimize's function minimize to Julia, but when I try to use it so that I specify constraints to it:
julia> #pyimport scipy.optimize.minimize as so
julia> so.minimize(f, x0,
constraints={"type": "ineq", "fun": g},
options={"maxiter": 1000})
Julia throws an error about the curly braces:
ERROR: LoadError: syntax: { } vector syntax is discontinued
Anyone having an idea of how the minimize function could be used properly in Julia?
I now realized that the curly brackets present dicts in Python and the Julia-version should therefore look like:
julia> so.minimize(objective_function, coords,
constraints = Dict("type" => "ineq", "fun" => g),
options = Dict("maxiter" => 1000))
So my guess is now that even though the function comes from Scipy, the input arguments need to be Julia syntax.

Plotting Method error using PyPlot in IJulia

I am trying to plot a function using PyPlot on an IJulia notebook, but I keep obtaining error messages.
When I ran this code:
function gtest2(x)
6.34*(log2(1+exp(10.0*(x+0.5))))^0.8
end
using PyPlot
x = -1.0:0.1:1.0;
plot(x, gtest2(x));
I got errors like these:
MethodError: no method matching ^(::Array{Float64,1}, ::Float64)
Closest candidates are: ^(::Float64, ::Float64) at math.jl:355 ...
I tried to defined a different type of variable while defining my function using gtest2(x::Number) or gtest2(x::Float64) but I have the same errors.
It does the same using linespace instead of -1.0:0.1:1.0. I understand that the format the function sees in input does not match the definition but I don't get what I'm doing wrong because simple functions work:
function f(x)
x
end
plot(x,f(x))
Why am I getting those errors in the first case?
I am using IJulia notebook 0.5.1 on safari.
Your code doesn't properly handle vectors thus you need to either change gtest
using the . vectorization syntax
function gtest2(x)
6.34*(log2.(1 + exp.(10.0*(x + 0.5)))).^0.8
end
or even easier use the dot vectorization as follows
plot(x, gtest2.(x));
To learn more about dot vectorization please see the following in the docs: https://docs.julialang.org/en/latest/manual/functions.html#man-vectorized-1
The first definition works also with:
map(gtest2, x)
or
gtest2.(x)

PyPlot Error in Julia: type PyObject has no field set_yscale

I am programming in Julia but using PyPloy library. I want to plot an histogram with log y-axis. But when I use the following code:
using PyPlot
List = [rand() for i = 1:100]
plt.hist(List)
plt.gca().set_yscale("log")
I get the following error:
type PyObject has no field set_yscale
while loading In[45], in expression starting on line 3
in getindex at /home/rm/.julia/v0.4/PyCall/src/PyCall.jl:642
in pysequence_query at /home/rm/.julia/v0.4/PyCall/src/conversions.jl:743
in pytype_query at /home/rm/.julia/v0.4/PyCall/src/conversions.jl:759
in convert at /home/rm/.julia/v0.4/PyCall/src/conversions.jl:808
in pycall at /home/rm/.julia/v0.4/PyCall/src/PyCall.jl:812
in fn at /home/rm/.julia/v0.4/PyCall/src/conversions.jl:181
in close_queued_figs at /home/rm/.julia/v0.4/PyPlot/src/PyPlot.jl:295
Is this a path error? If so, is there a simpler way to do a log-log plot with a different command?
Thanks in advance.
I feel like this should be more prominently explained in the documentation, but if you scroll down to the bottom of the Readme for PyCall (which PyPlot uses) it says:
Important: The biggest difference from Python is that object attributes/members are accessed with o[:attribute] rather than o.attribute, so that o.method(...) in Python is replaced by o[:method](...)
So, as #jverzani mentioned, after you call any module-level function from PyPlot that returns an object, that object is a PyObject and all of the attributes and methods have to be called using the bracket notation with a symbol.

PathPatch object in julia with PyPlot

I was trying to reproduce this example from the matplotlib website using the PyPlot package for Julia. As far as I know, the PyPlot is essentialy the matplotlib.pyplot module, so I imported the other modules of matplotlib that I needed (with the #pyimport macro):
using PyCall
#pyimport matplotlib.path as mpath
#pyimport matplotlib.patches as mpatches
Then I proceed to define the path object:
Path = mpath.Path
but then I get:
fn (generic function with 1 method) .
As if I had defined a function. Moreover, when I assign the path_data I get the following error:
ERROR: type Function has no field MOVETO
Of course, that's due to Path, which Julia tries as a function and not as a type or something like that. As you might guess the same happens when I try to define the variable patch .
So, there are incompatibilities of modules from matplotlib different to pyplot for Julia since the expected objects (types) are taken as functions. This behaviour can be expected if it were different the PyPlot.jl file wouldn't be needed.
My questions are:
-Am I doing something wrong?
-Is there a simple way to make it works?
-Do you know another package for Julia in which I can define patches and work in a similar way to matplotlib?
I have in mind to do this kind of animations.
Thanks for your ideas.
You need to get the "raw" Python object for Path. By default, PyCall converts Python type objects into functions (which call the corresponding constructor), but then you cannot access static members of the class.
Instead, do e.g. Path = mpath.pymember("Path") to get the "raw" PyObject, and then you can do Path["MOVETO"] or Path[:MOVETO] to access the MOVETO member.
(This difficulty will hopefully go away in Julia 0.4 once something like https://github.com/JuliaLang/julia/pull/8008 gets merged (so that we can make PyObjects callable directly.)