Converting python code into julia code

Hello everyone,
I’m new in Julia word and I would like to translate a code/function I have in python to julia language but I’m didn’t have success till this moment.

The function I have is:
def buffer(X, n, p=0, opt=None):

import numpy as np

if opt not in [None, 'nodelay']:
    raise ValueError('{} not implemented'.format(opt))

i = 0
first_iter = True
while i < len(X):
    if first_iter:
        if opt == 'nodelay':
            # No zeros at array start
            result = X[:n]
            i = n
        else:
            # Start with `p` zeros
            result = np.hstack([np.zeros(p), X[:n-p]])
            i = n-p
        # Make 2D array and pivot
        result = np.expand_dims(result, axis=0).T
        first_iter = False
        continue

    # Create next column, add `p` results from last col if given
    col = X[i:i+(n-p)]
    if p != 0:
        col = np.hstack([result[:,-1][-p:], col])
    i += n-p

    # Append zeros if last row and not length `n`
    if len(col) < n:
        col = np.hstack([col, np.zeros(n-len(col))])

    # Combine result with next row
    result = np.hstack([result, np.expand_dims(col, axis=0).T])

return result

Could anyone give me a hand in this?
Thank you in advance.

What have you tried so far? What problems did you run into?

The basic syntax is pretty similar, so loops and conditionals should hopefully not be too tricky. Here is a cheat-sheet for Julia that might be of help
https://cheatsheet.juliadocs.org/

One major difference is that julia is 1-indexed by default, and the numpy functionality you use here exists in the basic language.

2 Likes

I have this piece of code, but it doesn’t work at all

using LinearAlgebra

function buffer(X, n, p=0, opt=nothing)
if opt ∉ [nothing, “nodelay”]
error(“$opt not implemented”)
end

i = 1
first_iter = true
while i <= length(X)
    if first_iter
        if opt == "nodelay"
            result = X[1:n]
            i = n
        else
            result = hcat(zeros(p), X[1:n-p])
            i = n-p
        end
        
        result = reshape(result, (length(result), 1))
        first_iter = false
        continue
    end
    
    col = X[i:i+(n-p)-1]
    if p != 0
        col = hcat(result[:, end-p+1:end], col)
    end
    i += n-p
    
    if length(col) < n
        col = hcat(col, zeros(length(col), n-length(col)))
    end
    
    result = hcat(result, col)
end

return result

end

A couple of things seem to be happening here.

First I think you want to do vcat instead of hcat for the results = hcat(zeros(p), X[1:n-p]) line, otherwise it seems like it should error.

The variable result is first defined in the loop, I don’t think this will work, should define it beforehand.

The line col = X[i:i+(n-p)-1] will index out of bounds, so you probably need to put a check there to index only up to length of X.

And this seems strange also, that does not seem like what you are doing in python.

Is this a GPT translation?

I feel like if you understand the python code well enough it shouldn’t be too hard to translate it.

2 Likes

I’ve translated a decent amount of Python/MATLAB code into Julia, and what I’ve found helps is just going one line, or just a couple lines, at a time and make sure that 1) it runs and 2) the results are correct along the way. This is especially helpful if you’re not already familiar with Julia programming. If you try to translate 50 lines at a time it will just be harder to find the little mistakes. This also makes it easier to move from a Pythonic style to a more Julian style.

1 Like

I would focus on the desired output and try to achieve that as straightforwardly as possible, rather than trying to port some other implementation designed for a system with other performance characteristics. In this case it’s all a matter of filling an array with entries from a vector, so just do a double loop.

function buffer(X, n, p)
    0 <= p < n || error("You must have 0 <= p < n.")
    m = cld(length(X), n - p)
    out = zeros(eltype(X), n, m)
    for j = 1:m
        for i = 1:n
            k = (j - 1) * (n - p) + i - p
            if k in eachindex(X)
                out[i, j] = X[k]
            end
        end
    end
    return out
end
1 Like

The OP seems to be trying to re-implement the Matlab buffer function (see their other thread: Convert buffer function existing in matlab to julia language). (Apparently they found a Python implementation and are now trying to port that, rather than starting from the spec?) This really seems better to implement via an array or iterator of views rather than copies.

See my suggestion in the other thread, which boils down to the one-liner @views stack([X[i:i+n-1] for i in firstindex(X):n-p:lastindex(X)-n+1]).

2 Likes

I think this is close to what I need, however when applying it I obtained the following error message:

ERROR: MethodError: no method matching zeros(::Type{Float64}, ::Float64, ::Float64)
Closest candidates are:
zeros(::Type{T}, ::Union{Integer, AbstractUnitRange}…) where T at array.jl:584
zeros(::Type{T}, ::Tuple{}) where T at array.jl:592
zeros(::Type{T}, ::Tuple{Vararg{Integer, N}}) where {T, N} at array.jl:587

Stacktrace:
[1] bufferjulia(X::Matrix{Float64}, n::Float64, p::Float64)
@ Main .\REPL[60]:4
[2] top-level scope
@ c:\Users\R_Dua\Desktop\Packs\Julia Code\DataAnalysis.jl:52

Do you have any idea why this is happening?
Thank you in advance

Yes.

julia> zeros(Float64, 3, 2)
3×2 Matrix{Float64}:
 0.0  0.0
 0.0  0.0
 0.0  0.0

julia> zeros(Float64, 3.0, 2.0)
ERROR: MethodError: no method matching zeros(::Type{Float64}, ::Float64, ::Float64)

Closest candidates are:
  zeros(::Type{T}, ::Union{Integer, AbstractUnitRange}...) where T
   @ Base array.jl:580
  zeros(::Type{T}, ::Tuple{}) where T
   @ Base array.jl:588
  zeros(::Type{T}, ::Tuple{Vararg{Integer, N}}) where {T, N}
   @ Base array.jl:583
  ...

Stacktrace:
 [1] top-level scope
   @ REPL[6]:1

Call the function with n and p being integers, not integer-valued floating point numbers. Add an explicit cast to Int if necessary.