# PyCall.jl with SparseArrays

**URL:** <https://discourse.julialang.org/t/pycall-jl-with-sparsearrays/97316>\
**Category:** General Usage\
**Tags:** python, sparse\
**Created:** [April 10, 2023, 7:02pm UTC](https://discourse.julialang.org/t/pycall-jl-with-sparsearrays/97316 "2023-04-10T19:02:38Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [April 10, 2023, 7:02pm UTC](https://discourse.julialang.org/t/pycall-jl-with-sparsearrays/97316/1 "2023-04-10T19:02:38Z")

</div>

I am trying to diagonalize a huge sparse Hermitian matrix (original thread here: [Suggestions needed: diagonalizing large Hermitian sparse matrix](https://discourse.julialang.org/t/suggestions-needed-diagonalizing-large-hermitian-sparse-matrix/96580)) and am exploring the possibility of utilizing the PRIMME package. Since the Primme.jl ([GitHub - andreasnoack/Primme.jl: Julia wrapper for Primme: Preconditioned Iterative Multimethod Eigensolver](https://github.com/andreasnoack/Primme.jl)) is outdated and does not contain eigenvalue solver interface, I am trying to call PRIMME by PyCall.

It seems PyCall does not know how to translate SparseArrays to scipy sparse arrays:

```julia
julia> using PyCall, SparseArrays

julia> sp = pyimport("scipy")
PyObject <module 'scipy' from '/path/to/myhome/.julia/conda/3/lib/python3.9/site-packages/scipy/ __init__.py'>

julia> A = sprandn(1000, 1000, 0.0025);

julia> B = sprandn(1000, 1000, 0.0025);

julia> C = A + im * B;

julia> D = C' + C;

julia> sp.sparse.linalg.eigs(D)
ERROR: PyError ($(Expr(:escape, :(ccall(#= /path/to/myhome/.julia/packages/PyCall/twYvK/src/pyfncall.jl:43 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class 'AttributeError'>
AttributeError("'list' object has no attribute 'shape'")
  File "/path/to/myhome/.julia/conda/3/lib/python3.9/site-packages/scipy/sparse/linalg/_eigen/arpack/arpack.py", line 1256, in eigs
    if A.shape[0] != A.shape[1]:

Stacktrace:
  [1] pyerr_check
    @ ~/.julia/packages/PyCall/twYvK/src/exception.jl:75 [inlined]
  [2] pyerr_check
    @ ~/.julia/packages/PyCall/twYvK/src/exception.jl:79 [inlined]
  [3] _handle_error(msg::String)
    @ PyCall ~/.julia/packages/PyCall/twYvK/src/exception.jl:96
  [4] macro expansion
    @ ~/.julia/packages/PyCall/twYvK/src/exception.jl:110 [inlined]
  [5] #107
    @ ~/.julia/packages/PyCall/twYvK/src/pyfncall.jl:43 [inlined]
  [6] disable_sigint
    @ ./c.jl:473 [inlined]
  [7] __pycall!
    @ ~/.julia/packages/PyCall/twYvK/src/pyfncall.jl:42 [inlined]
  [8] _pycall!(ret::PyObject, o::PyObject, args::Tuple{SparseMatrixCSC{ComplexF64, Int64}}, nargs::Int64, kw::Ptr{Nothing})
    @ PyCall ~/.julia/packages/PyCall/twYvK/src/pyfncall.jl:29
  [9] _pycall!
    @ ~/.julia/packages/PyCall/twYvK/src/pyfncall.jl:11 [inlined]
 [10] #_#114
    @ ~/.julia/packages/PyCall/twYvK/src/pyfncall.jl:86 [inlined]
 [11] (::PyObject)(args::SparseMatrixCSC{ComplexF64, Int64})
    @ PyCall ~/.julia/packages/PyCall/twYvK/src/pyfncall.jl:86
 [12] top-level scope
    @ REPL[34]:1

```

Any ideas about how I can utilize sparse eigenvalue solvers from the Python ecosystem?

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [April 10, 2023, 7:22pm UTC](https://discourse.julialang.org/t/pycall-jl-with-sparsearrays/97316/2 "2023-04-10T19:22:40Z")

</div>

> [@Chong\_Wang](#):
>
> ```julia
> julia> C = A + im * B;
> 
> julia> D = C' + C;
> 
> ```

one of these step converted type, check the type of `im*B` and `A + im*B` and `C'`

---

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [April 10, 2023, 9:38pm UTC](https://discourse.julialang.org/t/pycall-jl-with-sparsearrays/97316/3 "2023-04-10T21:38:33Z")

</div>

> [@jling](#):
>
> one of these step converted type, check the type of `im*B` and `A + im*B` and `C'`

The types are exactly what I expected. What do you mean?

```julia
julia> typeof(A)
SparseMatrixCSC{Float64, Int64}

julia> typeof(B)
SparseMatrixCSC{Float64, Int64}

julia> typeof(C)
SparseMatrixCSC{ComplexF64, Int64}

julia> typeof(D)
SparseMatrixCSC{ComplexF64, Int64}

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 11, 2023, 12:14am UTC](https://discourse.julialang.org/t/pycall-jl-with-sparsearrays/97316/4 "2023-04-11T00:14:12Z")

</div>

> [@Chong\_Wang](#):
>
> It seems PyCall does not know how to translate SparseArrays to scipy sparse arrays:

See [Convert to sparse · Issue #204 · JuliaPy/PyCall.jl · GitHub](https://github.com/JuliaPy/PyCall.jl/issues/204) for conversion in the opposite direction. You should just be able to call the [`scipy.sparse.csc_array`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.csc_array.html#scipy.sparse.csc_array) constructor directly with the corresponding data from a Julia sparse arrray, e.g. something like:

```julia
pysparse = pyimport("scipy.sparse")
Apy = pysparse.csc_array((A.nzval, A.rowval .- 1, A.colptr .- 1), shape=size(A))

```

where `A` is a Julia `SparseMatrixCSC`. (The `.- 1` is to convert from 1-based to 0-based indices.)

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [April 11, 2023, 1:42am UTC](https://discourse.julialang.org/t/pycall-jl-with-sparsearrays/97316/5 "2023-04-11T01:42:08Z")

</div>

> [@Chong\_Wang](#):
>
> The types are exactly what I expected. What do you mean?

I would call that something I didn’t expect, because I called Scipy function, and got back Julia matrix. This is not what you want if the intention is to call Scipy function again.

Btw maybe `PythonCall.jl` with its no-conversion default would serve you better

---

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [April 11, 2023, 9:10pm UTC](https://discourse.julialang.org/t/pycall-jl-with-sparsearrays/97316/6 "2023-04-11T21:10:27Z")

</div>

> [@jling](#):
>
> I would call that something I didn’t expect, because I called Scipy function, and got back Julia matrix.

I think you probably misunderstood. `sprandn` is a Julia function from `SparseArrays`.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [April 11, 2023, 11:21pm UTC](https://discourse.julialang.org/t/pycall-jl-with-sparsearrays/97316/7 "2023-04-11T23:21:22Z")

</div>

Yep I totally got that backwards sorry
