Henrique
Henrique

Reputation: 35

Julia - MethodError: objects of type Float64 are not callable

I'm currently learning Julia and i'm trying to translate a Fortran77 code, but i got this error message and i can't see from where the issue is coming from.

using DelimitedFiles, DataFrames

function diprcbk(iii,x,r)

    if iii==0
        df = DataFrame(readdlm("dipgbw800hp.dat"), [:ya,:xa, :ra, :da])
        ya1=[]
        xa1=[]
        for ix in 1:801:370863
            YA1 = df.ya[ix]
            XA1 = df.xa[ix]
            append!(ya1, YA1)
            append!(xa1, XA1)
        end


        ya=[]
        xa=[]
        da=[]
        ra=[]
        ral=[]
        for ix in 1:1:463
            XA=xa1[ix]
            YA=ya1[ix]
            append!(ya, YA)
            append!(xa, XA)
            DA=df[df.ya .== ya[ix], :da]
            push!(da, DA)

            for ir in 1:1:801
                RA = df.ra[ir]
                RAL=log(RA)
                append!(ra, RA)
                append!(ral, RAL)
            end
        end  
    end
    if iii==1
        df = DataFrame(readdlm("dipmv800hp.dat"), [:ya,:xa, :ra, :da])
        ya1=[]
        xa1=[]
        for ix in 1:801:370863
            YA1 = df.ya[ix]
            XA1 = df.xa[ix]
            append!(ya1, YA1)
            append!(xa1, XA1)
        end
    end

        ya=[]
        xa=[]
        da=[]
        ra=[]
        ral=[]
        for ix in 1:1:463
            XA=xa1[ix]
            YA=ya1[ix]
            append!(ya, YA)
            append!(xa, XA)
            DA=df[df.ya .== ya[ix], :da]
            push!(da, DA)

            for ir in 1:1:801
                RA = df.ra[ir]
                RAL=log(RA)
                append!(ra, RA)
                append!(ral, RAL)
            end
        end   

    if r < ra[1]
        return 0

    #####Maybe the error is somewhere here?#####
    elseif r>= ra[1] && r<=ra[801]

        y = float(log((xa[1])/x))

        for ix in 1:1:(length(ya)-1)

            if y>ya[ix] && y<ya[ix+1]

                indx=ix

                for ir in 1:1:(802-1)
                    if r>ra[ir] && r<ra[ir + 1]
                        indr=ir

                        rl = log(r)

                        function xlinter(x1,x2,y1,y2,x)
                            xlinter = float((y2-y1)*(x-x1)/(x2-x1)+y1)
                            return xlinter
                        end

                        dindr=xlinter(ya[indx],ya[indx+1],da[indx][indr],da[indx+1][indr],y)
                        dindrp1=xlinter(ya[indx],ya[indx+1],da[indx][indr+1],da[indx+1][indr+1],y)
                        diprcbk=xlinter(ral[indr],ral[indr+1],dindr,dindrp1,rl)

                        return diprcbk


                    end
                end
            end
        end  
    ############################################

    elseif r>ra[801]
        return 1

    end

end

MV=[]
GBW=[]
R=[]
for i in -90:1:20
    r=10^((0.1)*i)
    aaa=diprcbk(0, 10^(-4), r)
    bbb=diprcbk(1, 10^(-4), r)
    append!(R, r)
    append!(GBW, aaa)
    append!(MV, bbb)
end

MethodError: objects of type Float64 are not callable

Maybe you forgot to use an operator such as *, ^, %, / etc. ?

Stacktrace:

[1] diprcbk(iii::Int64, x::Float64, r::Float64)

@ Main .\In[25]:94

[2] top-level scope

@ .\In[26]:6

[3] eval

@ .\boot.jl:368 [inlined]

[4] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)

@ Base .\loading.jl:1428

Upvotes: 1

Views: 836

Answers (2)

daycaster
daycaster

Reputation: 2697

The error message suggests that, at some point, your code has changed the value of a symbol that was originally defined as a function to have a value of a Float64. Then, when your code tries to apply the symbol as a function, it discovers too late that the symbol is a numeric value instead. Originally I thought your redefinition of diprcbk was the problem, but I'm not sure now.

But a problem I did notice is that at one point this line:

bbb=diprcbk(1, 10^(-4), r)

returns nothing. I think this is because you have this syntax:

if x
...
elseif
...
elseif
...
end

which returns nothing if none of the conditions are met. You should probably have a final "else" to catch all the conditions, so that the function always returns a number to the caller.

Upvotes: 2

Shayan
Shayan

Reputation: 6295

Some initial hints for writing efficient Julia code:

  • Don't define a function inside another function if it's not necessary!
  • Don't define a vector like foo = []. Pre-define it and change its content! like: Array{Float64, 1}(undef, 50) this is a pre-defined vector since I wrote Array{..., 1} with length of 50. Also, this prevents pushing and appending iteratively, which have high computation costs.
  • Don't read the data twice (or even more)! You are reading the *.dat files up to 111 times!! This is a disaster and slows down your code too much!

Here is what you can begin with (I'm sure that you can write much better than this, but it's beyond the scope of this answer, and it's up to your effort):

const df1 = DataFrame(readdlm("dipgbw800hp.dat"), [:ya,:xa, :ra, :da])
const df2 = DataFrame(readdlm("dipmv800hp.dat"), [:ya,:xa, :ra, :da])

function xlinter(x1,x2,y1,y2,x)
    xlinter = float((y2-y1)*(x-x1)/(x2-x1)+y1)
    return xlinter
end

function diprcbk(iii,x,r)

    if iii==0
        # df = DataFrame(readdlm("dipgbw800hp.dat"), [:ya,:xa, :ra, :da])
        df = df1
        ya1= Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        xa1= Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        for (iter,ix) in enumerate(1:801:370863)
            YA1 = df.ya[ix]
            XA1 = df.xa[ix]
            ya1[iter] = YA1
            xa1[iter] = XA1
        end


        ya=Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        xa=Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        da=Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        ra=Array{Union{Float64, Vector{Float64}}, 1}(undef, 801)
        ral=Array{Union{Float64, Vector{Float64}}, 1}(undef, 801)
        for (iter, ix) in enumerate(1:463)
            XA=xa1[ix]
            YA=ya1[ix]
            ya[iter] = YA
            xa[iter] = XA
            DA=df[df.ya .== ya[ix], :da]
            da[iter] = DA

            for (iter1,ir) in enumerate(1:801)
                RA = df.ra[ir]
                RAL=log(RA)
                ra[iter1] = RA
                ral[iter1] = RAL
            end
        end
    end
    if iii==1
        # df = DataFrame(readdlm("dipmv800hp.dat"), [:ya,:xa, :ra, :da])
        df = df2
        ya1=Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        xa1=Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        for (iter, ix) in enumerate(1:801:370863)
            YA1 = df.ya[ix]
            XA1 = df.xa[ix]
            ya1[iter] = YA1
            xa1[iter] = XA1
        end

        ya=Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        xa=Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        da=Array{Union{Float64, Vector{Float64}}, 1}(undef, 463)
        ra=Array{Union{Float64, Vector{Float64}}, 1}(undef, 801)
        ral=Array{Union{Float64, Vector{Float64}}, 1}(undef, 801)
        for (iter, ix) in enumerate(1:463)
            XA=xa1[ix]
            YA=ya1[ix]
            ya[iter] = YA
            xa[iter] = XA
            DA=df[df.ya .== ya[ix], :da]
            da[iter] = DA

            for (iter1, ir) in enumerate(1:801)
                RA = df.ra[ir]
                RAL=log(RA)
                ra[iter1] = RA
                ral[iter1] = RAL
            end
        end
    end

    if r < ra[1]
        return 0

    #####Maybe the error is somewhere here?#####
    elseif r>= ra[1] && r<=ra[801]

        y = float(log((xa[1])/x))

        for ix in 1:(length(ya)-1)

            if y>ya[ix] && y<ya[ix+1]

                indx=ix

                for ir in 1:801
                    if r>ra[ir] && r<ra[ir + 1]
                        indr=ir

                        rl = log(r)

                        dindr=xlinter(ya[indx],ya[indx+1],da[indx][indr],da[indx+1][indr],y)
                        dindrp1=xlinter(ya[indx],ya[indx+1],da[indx][indr+1],da[indx+1][indr+1],y)
                        diprcbk=xlinter(ral[indr],ral[indr+1],dindr,dindrp1,rl)

                        return diprcbk


                    end
                end
            end
        end
    ############################################

    elseif r>ra[801]
        return 1

    end
end

MV=Array{Float64, 1}(undef, 111)
GBW=Array{Float64, 1}(undef, 111)
R=Array{Float64, 1}(undef, 111)
for (iter, i) in enumerate(-90:20)
    @show i
    r=10^((0.1)*i)
    aaa=diprcbk(0, 10^(-4), r)
    bbb=diprcbk(1, 10^(-4), r)
    R[iter] = r
    GBW[iter] = aaa
    MV[iter] = bbb
    @show R[1:iter]
end

Please check if the output is what it has to be.
I used the @show macro to monitor the result of R iteratively. So you can remove them if you're done with the code.

What I have changed in your source code:

  1. Moving the xlinter function definition outside of the diprcbk function.
  2. Changing all *=[] definitions into Array{*, 1}(undef, *) with suitable length and element type.
  3. Using an iterator in for loops to replace the calculated values with the pre-defined ones through utilizing the enumerate function.
  4. Some unnecessary step lengths in a:*:b were removed. Example: a:1:b has a step equal to 1, and we can omit the 1. So a:b would be enough. Please check for further ones that might have been forgotten.
  5. Two variables, named df1 and df2 as two constant global variables created outside of the diprcbk definition. This highly improves runtime. Accordingly, df = DataFrame(readdlm("*.dat"), [:ya,:xa, :ra, :da]) was replaced with df = df1 or df = df2.

Upvotes: 2

Related Questions