From 7d5eb4ff9473d8678aefb2743340940fccb9b17f Mon Sep 17 00:00:00 2001 From: mloubout Date: Sun, 27 Oct 2024 22:36:28 -0400 Subject: [PATCH] switch to pythoncall --- .github/workflows/ci-joli.yaml | 19 ++----------------- CondaPkg.toml | 3 +++ Project.toml | 8 ++++---- README.md | 2 +- src/JOLI.jl | 2 +- src/joLinearFunctionConstructors/joSWT.jl | 21 +++++++++++++++------ src/joMixedConstructors/joGaussian.jl | 15 +++++++++------ test/runtests.jl | 2 +- test/test_joSWT.jl | 4 ++-- 9 files changed, 38 insertions(+), 38 deletions(-) create mode 100644 CondaPkg.toml diff --git a/.github/workflows/ci-joli.yaml b/.github/workflows/ci-joli.yaml index e6c35df..24513a9 100644 --- a/.github/workflows/ci-joli.yaml +++ b/.github/workflows/ci-joli.yaml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: - version: ['1.6', '1.7', '1'] + version: ['lts', '1.10', '1'] os: - ubuntu-latest - macos-latest @@ -31,29 +31,14 @@ jobs: uses: actions/checkout@v2 - name: Setup julia - uses: julia-actions/setup-julia@v1 + uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - - name: Set up Python 3.7 - uses: actions/setup-python@v1 - with: - python-version: 3.7 - - - name: Install wavelets - run: | - python -m pip install --upgrade pip - pip install PyWavelets - name: Build JOLI uses: julia-actions/julia-buildpkg@latest - - name: Rebuild PyCall with system python - run: | - export PYTHON=$(which python) - julia --color=yes --check-bounds=yes --project -e 'using Pkg; Pkg.build("PyCall")' - - name: Run tests uses: julia-actions/julia-runtest@latest diff --git a/CondaPkg.toml b/CondaPkg.toml new file mode 100644 index 0000000..bf657dc --- /dev/null +++ b/CondaPkg.toml @@ -0,0 +1,3 @@ +[deps] +python = "" +pywavelets = "" diff --git a/Project.toml b/Project.toml index 0edbd57..53a7206 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "JOLI" uuid = "bb331ad6-a1cf-11e9-23da-9bcb53c69f6f" authors = ["Henryk Modzelewski "] -version = "0.8.5" +version = "0.9.0" [deps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" @@ -16,7 +16,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" NFFT = "efe261a4-0d2b-5849-be55-fc731d526b0d" Nullables = "4d1e1d77-625e-5b40-9113-a560ec7a8ecd" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" -PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" +PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" @@ -27,12 +27,12 @@ Wavelets = "29a6e085-ba6d-5f35-a997-948ac2efa89a" ChainRulesCore = "1" DistributedArrays = "0.5, 0.6" FFTW = "1" -Flux = "0.12, 0.13" +Flux = "0.12, 0.13, 0.14" InplaceOps = "0.3.0" IterativeSolvers = "0.8, 0.9" NFFT = "0.6 - 0.13" Nullables = "1" -PyCall = "1.18, 1.90, 1.91, 1.62" +PythonCall = "0.9" SpecialFunctions = "1.2, 2" Wavelets = "0.8, 0.9" julia = "1" diff --git a/README.md b/README.md index f9a909a..b42a838 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ JOLI is registered and can be added like any standard julia package with the com - **CurveLab**: In order to use `joCurvelet2D` or `joCurvelet2DnoFFT` operators, you need to obtain *CurveLab-2.1.2-SLIM*, a SLIM extension to *CurveLab-2.1.2*. The tarball of this extension is available from [curvelet.org](http://www.curvelet.org) under [Software](http://www.curvelet.org/software.html) tab. The installation instructions are included in the tarball of *CurveLab-2.1.2-SLIM*. Note, that CurveLab is free only for academic use and requires registration. -- **PyWavelets**: In order to use `joSWT` that implements 1D stationary/shift invariant wavelet transform, the [PyWavelets](https://github.com/PyWavelets/pywt) package needs to be installed within the python environement used by [PyCall.jl](https://github.com/JuliaPy/PyCall.jl). By default, it will use [Conda.jl](https://github.com/JuliaPy/Conda.jl) and you should follow its directiv to install a package within it. If you have configured `PyCall` with your own python environment you can install `PyWavelets` via `pip install --upgrade PyWavelets`. +- **PyWavelets**: In order to use `joSWT` that implements 1D stationary/shift invariant wavelet transform, the [PyWavelets](https://github.com/PyWavelets/pywt) package needs to be installed within the python environment used by [PythonCall.jl](https://github.com/JuliaPy/PythonCall.jl). By default, it will use [CondaPkg.jl](https://github.com/JuliaPy/CondaPkg.jl) and you should follow its directiv to install a package within it. If you have configured `PythonCall` with your own python environment you can install `PyWavelets` via `pip install --upgrade PyWavelets`. ## Documentation (more to come) diff --git a/src/JOLI.jl b/src/JOLI.jl index 5ff841a..d04cd0d 100644 --- a/src/JOLI.jl +++ b/src/JOLI.jl @@ -51,10 +51,10 @@ using DistributedArrays.SPMD using LinearAlgebra using InplaceOps using IterativeSolvers +using PythonCall using FFTW using NFFT using Wavelets -using PyCall using SpecialFunctions using ChainRulesCore diff --git a/src/joLinearFunctionConstructors/joSWT.jl b/src/joLinearFunctionConstructors/joSWT.jl index 9d962da..0772454 100644 --- a/src/joLinearFunctionConstructors/joSWT.jl +++ b/src/joLinearFunctionConstructors/joSWT.jl @@ -3,25 +3,32 @@ ## helper module module joSWT_etc using JOLI: jo_convert - using PyCall + using PythonCall + + const pywt = PythonCall.pynew() + + function __init__() + PythonCall.pycopy!(pywt, pyimport("pywt")) + end + # 1D function apply_swt(v::Vector{vdt}, wt::String, L::Integer,rdt::DataType,pad::Integer) where vdt<:Union{AbstractFloat,Complex} - pywt = pyimport("pywt") v = [v;zeros(vdt, pad)] rv = pywt.swt(v, wt, level=L, start_level=0, norm=true, trim_approx=true) - rv = vcat(rv...) + rv = vcat([PyArray(r) for r in rv]...) rv = jo_convert(rdt, rv, false) return rv end + function apply_iswt(v::Vector{vdt},wt::String,L::Integer,rdt::DataType,pad::Integer) where vdt<:Union{AbstractFloat,Complex} - pywt = pyimport("pywt") v = reshape(v, :, L+1) v = [v[:, i] for i=1:L+1] - rv = pywt.iswt(v, wt, norm=true) + rv = PyArray(pywt.iswt(v, wt, norm=true)) # Convert and remove pad rv = jo_convert(rdt, rv[1:end-pad], false) return rv end + end using .joSWT_etc @@ -68,7 +75,7 @@ examples with DDT/RDT joDWT(m,"sym5"; DDT=Float32,RDT=Float64) """ -function joSWT(m::Integer,wt::String="db20"; +function joSWT(m::Integer, wt::String="db20"; L::Integer=maxtransformlevels(m + m%2), DDT::DataType=joFloat,RDT::DataType=DDT, name::String="joSWT") @@ -84,3 +91,5 @@ function joSWT(m::Integer,wt::String="db20"; DDT,RDT; name=name) end + +joSWT(m::Integer, wt::Py; kwargs...) = joSWT(m, string(wt); kwargs...) diff --git a/src/joMixedConstructors/joGaussian.jl b/src/joMixedConstructors/joGaussian.jl index 7e05674..2d69dcd 100644 --- a/src/joMixedConstructors/joGaussian.jl +++ b/src/joMixedConstructors/joGaussian.jl @@ -5,7 +5,10 @@ module joGaussian_etc using JOLI: jo_convert, LocalVector using Random using LinearAlgebra - function fI(v::LocalVector{vdt},m::Integer,n::Integer,rng::AbstractRNG,rns::Array{UInt32,1},rdt::DataType) where vdt<:Number + + const rngT = Union{Vector{UInt32}, UInt128} + + function fI(v::LocalVector{vdt},m::Integer,n::Integer,rng::AbstractRNG,rns::rngT,rdt::DataType) where vdt<:Number rv = zeros(rdt,m) lrng=Random.seed!(rng,rns) for i=1:n @@ -15,7 +18,7 @@ module joGaussian_etc rv = jo_convert(rdt,rv,false) return rv end - function aI(v::LocalVector{vdt},m::Integer,n::Integer,rng::AbstractRNG,rns::Array{UInt32,1},rdt::DataType) where vdt<:Number + function aI(v::LocalVector{vdt},m::Integer,n::Integer,rng::AbstractRNG,rns::rngT,rdt::DataType) where vdt<:Number rv = Vector{rdt}(undef,n) lrng=Random.seed!(rng,rns) for i=1:n @@ -25,7 +28,7 @@ module joGaussian_etc rv = jo_convert(rdt,rv,false) return rv end - function scale(m::Integer,n::Integer,rng::AbstractRNG,rns::Array{UInt32,1},rdt::DataType) + function scale(m::Integer,n::Integer,rng::AbstractRNG,rns::rngT,rdt::DataType) rv = Vector{rdt}(undef,n) lrng=Random.seed!(rng,rns) for i=1:n @@ -37,7 +40,7 @@ module joGaussian_etc rv = jo_convert(rdt,rv,false) return rv end - function fIN(v::LocalVector{vdt},m::Integer,n::Integer,scale::LocalVector{<:Number},rng::AbstractRNG,rns::Array{UInt32,1},rdt::DataType) where vdt<:Number + function fIN(v::LocalVector{vdt},m::Integer,n::Integer,scale::LocalVector{<:Number},rng::AbstractRNG,rns::rngT,rdt::DataType) where vdt<:Number rv = zeros(rdt,m) lrng=Random.seed!(rng,rns) for i=1:n @@ -47,7 +50,7 @@ module joGaussian_etc rv = jo_convert(rdt,rv,false) return rv end - function aIN(v::LocalVector{vdt},m::Integer,n::Integer,scale::LocalVector{<:Number},rng::AbstractRNG,rns::Array{UInt32,1},rdt::DataType) where vdt<:Number + function aIN(v::LocalVector{vdt},m::Integer,n::Integer,scale::LocalVector{<:Number},rng::AbstractRNG,rns::rngT,rdt::DataType) where vdt<:Number rv = Vector{rdt}(undef,n) lrng=Random.seed!(rng,rns) for i=1:n @@ -134,7 +137,7 @@ function joGaussian(M::Integer,N::Integer=M; return joMatrix(a;DDT=DDT,RDT=RDT,name=name*"_o") else if implicit - rngs=copy(RNG.seed) + rngs = copy(RNG.seed) if normalized fscale = joGaussian_etc.scale(M,N,RNG,rngs,DDT) ascale = joGaussian_etc.scale(M,N,RNG,rngs,RDT) diff --git a/test/runtests.jl b/test/runtests.jl index 0d381f2..8823a68 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,7 +5,7 @@ using SparseArrays using InplaceOps using FFTW using Wavelets -using PyCall +using PythonCall using JOLI jo_type_mismatch_error_set(false) diff --git a/test/test_joSWT.jl b/test/test_joSWT.jl index 148ba11..dc6936b 100644 --- a/test/test_joSWT.jl +++ b/test/test_joSWT.jl @@ -4,11 +4,11 @@ try global swt = pywt.swt global pywavelet = true catch - @warn "Skipping joSWTtests - PyCall clouldn't import PyWavelets" + @warn "Skipping joSWTtests - PythonCall clouldn't import PyWavelets" end families = ("haar", "db", "sym", "coif") -pywavelet ? wavelets = vcat([pywt.wavelist(name) for name in families]...) : wavelets = [] +pywavelet ? wavelets = vcat([pyconvert(Vector{String}, pywt.wavelist(name)) for name in families]...) : wavelets = [] tsname="joSWT" @testset "$tsname" begin