Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't "connect" to events, PyCall can't create weak references to Julia function #21

Closed
marcusps opened this issue Nov 12, 2013 · 9 comments

Comments

@marcusps
Copy link

I am trying to "connect" to PyPlot events so I can visually inspect some plots and extract peaks from 1D spectra.

I tried the following

julia> using PyPlot
'import sitecustomize' failed; use -v for traceback

julia> x = Float64[]; y = Float64[]
0-element Array{Float64,1}

julia> function mycall(event)
         append!(x,[event.xdata]); append!(y,[event.ydata])
       end
mycall (generic function with 1 method)

julia> connect("button_press_event", mycall)
ERROR: PyError (PyObject_Call) <type 'exceptions.TypeError'>
TypeError("cannot create weak reference to 'PyCall.jl_Function' object",)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/pyplot.py", line 395, in connect
    return get_current_fig_manager().canvas.mpl_connect(s, func)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 2195, in mpl_connect
    return self.callbacks.connect(s, func)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/cbook.py", line 308, in connect
    self._func_cid_map[s][func] = cid
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py", line 262, in __setitem__
    self.data[ref(key, self._remove)] = value

 in pyerr_check at /Users/msilva/.julia/PyCall/src/exception.jl:58
 in pycall at /Users/msilva/.julia/PyCall/src/PyCall.jl:85
 in connect at /Users/msilva/.julia/PyPlot/src/PyPlot.jl:235

Looking through the PyPlot code it seems like connect should work in this instance, but I have not been able to find any examples of people using this function, so I am not sure if it is functional.

@ronisbr
Copy link

ronisbr commented Jun 11, 2015

I do really need to connect a signal in fig[:canvas] using fig[:canvas][:mpl_connect]. However, I am getting this same error message. I am trying to get the position of a mouse click over a plot. Is there any way to solve the problem now?

Thanks,
Ronan

@stevengj
Copy link
Member

stevengj commented Jul 2, 2015

This is due to JuliaPy/PyCall.jl#158, and looks like it requires some implementation work in PyCall to support Python weak references to Julia objects.

@ronisbr
Copy link

ronisbr commented Jul 6, 2015

Ok, thanks @stevengj.

@ronisbr
Copy link

ronisbr commented Dec 3, 2017

@stevengj

Hi! Did something change? I was able to connect an event to a Julia function using the fig[:canvas][:mpl_connect] without problems. The weak reference error does not show anymore.

Here is an example:

using PyCall
pygui(:qt5)
using PyPlot

function test(event)
    println("Click: $(event[:xdata]), $(event[:ydata])")
end

fig = figure()
plot(0:1:10, 0:1:10)
fig[:canvas][:mpl_connect]("button_press_event", test)

Then, after clicking on the figure, I see:

julia> Click: 4.423387096774194, 4.476190476190478
Click: 5.820564516129033, 4.11904761904762
Click: 1.806451612903226, 7.2738095238095255
Click: 3.691532258064516, 7.690476190476192
Click: 6.286290322580645, 7.660714285714288
Click: 7.572580645161291, 5.30952380952381
Click: 5.997983870967743, 2.7202380952380962
Click: 1.5625, 3.7916666666666674
Click: 0.941532258064516, 6.708333333333336

@ronisbr
Copy link

ronisbr commented Dec 4, 2017

Here is a gif of my Control Toolbox package that I was developing. I was really wanting this feature to have an interactive plot:

rlocus

EDIT: I tested this with both Python 2 and 3 using Qt4, Qt5, and Tk as backend. Everything worked as expected!

@lukasfischer83
Copy link

What Julia/PyCall version were you using for that? Did you also test on linux?
I still get the same "weak reference" error in 0.6.2 and after a Pkg.update() on ubuntu.

@ronisbr
Copy link

ronisbr commented May 24, 2018

I was using Julia 0.6.2 and latest released version of PyCall in openSUSE linux. I tested it on macOS and Linux. In linux, I performed a test using different versions of Python and QT5. Everything worked. You can see this package here:

https://github.com/ronisbr/ControlToolbox.jl

@lukasfischer83
Copy link

Unfortunately in my setup (ubuntu 14.04, tried Python 3.4 and 2.7) it also doesn't work with your example.

rlocus(G)
ERROR: PyError (ccall(@pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, arg, C_NULL)) <class 'TypeError'>
TypeError("cannot create weak reference to 'PyCall.jlwrap' object",)
  File "/usr/lib/python3/dist-packages/matplotlib/backend_bases.py", line 2324, in mpl_connect
    return self.callbacks.connect(s, func)
  File "/usr/lib/python3/dist-packages/matplotlib/cbook.py", line 495, in connect
    self._func_cid_map[s][func] = cid
  File "/usr/lib/python3.4/weakref.py", line 365, in __setitem__
    self.data[ref(key, self._remove)] = value

Stacktrace:
 [1] pyerr_check at /home/lukas/.julia/v0.6/PyCall/src/exception.jl:58 [inlined]
 [2] pyerr_check at /home/lukas/.julia/v0.6/PyCall/src/exception.jl:62 [inlined]
 [3] macro expansion at /home/lukas/.julia/v0.6/PyCall/src/exception.jl:82 [inlined]
 [4] #_pycall#88(::Array{Any,1}, ::Function, ::PyCall.PyObject, ::String, ::Vararg{Any,N} where N) at /home/lukas/.julia/v0.6/PyCall/src/PyCall.jl:710
 [5] _pycall(::PyCall.PyObject, ::String, ::Vararg{Any,N} where N) at /home/lukas/.julia/v0.6/PyCall/src/PyCall.jl:698
 [6] #pycall#92(::Array{Any,1}, ::Function, ::PyCall.PyObject, ::Type{PyCall.PyAny}, ::String, ::Vararg{Any,N} where N) at /home/lukas/.julia/v0.6/PyCall/src/PyCall.jl:732
 [7] pycall(::PyCall.PyObject, ::Type{PyCall.PyAny}, ::String, ::Vararg{Any,N} where N) at /home/lukas/.julia/v0.6/PyCall/src/PyCall.jl:732
 [8] #call#93(::Array{Any,1}, ::PyCall.PyObject, ::String, ::Vararg{Any,N} where N) at /home/lukas/.julia/v0.6/PyCall/src/PyCall.jl:735
 [9] (::PyCall.PyObject)(::String, ::Vararg{Any,N} where N) at /home/lukas/.julia/v0.6/PyCall/src/PyCall.jl:735
 [10] plot_rlocus(::Array{Array{Complex{Float64},1},1}, ::Array{Float64,1}, ::Array{Complex{Float64},1}, ::Array{Complex{Float64},1}, ::Array{Complex{Float64},1}, ::Array{Complex{Float64},1}) at /home/lukas/.julia/v0.6/ControlToolbox/src/plots/plot_rlocus.jl:45
 [11] #rlocus#22(::Bool, ::Function, ::ControlToolbox.TransferFunction, ::Array{Any,1}) at /home/lukas/.julia/v0.6/ControlToolbox/src/analysis/rlocus.jl:222
 [12] rlocus(::ControlToolbox.TransferFunction) at /home/lukas/.julia/v0.6/ControlToolbox/src/analysis/rlocus.jl:27

@ronisbr
Copy link

ronisbr commented May 24, 2018

One question, did you install matplotlib from pip?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants