# Using LsqFit on complex data

**URL:** <https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620>\
**Category:** General Usage\
**Tags:** package, curve-fitting, complex-numbers\
**Created:** [April 18, 2022, 8:07am UTC](https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620 "2022-04-18T08:07:35Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![PazzyBoardman449](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pazzyboardman449/32/35495_2.png) [@PazzyBoardman449](https://discourse.julialang.org/u/PazzyBoardman449)\
**Post date:** [April 18, 2022, 8:07am UTC](https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620/1 "2022-04-18T08:07:35Z")

</div>

I’m trying to use LsqFit.jl to fit data that is complex (in the form x + im\*y). For purposes of showing the problem, I’m using the example provided on GitHub for LsqFit but I’m changing the model such that it has an imaginary term in the exponential, rather than a real one.

```julia
using LsqFit
@. model(x, p) = p[1] * exp(im*x * p[2])

xdata = range(0, stop=10, length=20)
ydata = model(xdata, [1.0 2.0]) + 0.01 * randn(length(xdata))

p0 = [0.5, 0.5]
fit = curve_fit(model, xdata, ydata, p0)

```

I get the error message:

```julia
LoadError: InexactError: Float64(-0.9292044089784778 + 3.141189448336519im)
Stacktrace:
  [1] Real
    @ ./complex.jl:44 [inlined]
  [2] convert
    @ ./number.jl:7 [inlined]

```

I’ve tried the same thing in Matlab (☹) using `lsqcurvefit()` with complex data and it works fine and extracts the correct parameters. I’m aware that a fitting procedure that involves complex data is going to be inherently different to simply fitting real data, but I cannot figure this out.

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 18, 2022, 8:18am UTC](https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620/2 "2022-04-18T08:18:15Z")

</div>

Even if I force all arguments to be of type (or `eltype`) `ComplexF64` like

```julia
using LsqFit
@. model(x, p) = p[1] * exp(im*x * p[2])

xdata = range(0+0im, stop=10, length=20)
ydata = model(xdata, ComplexF64[1.0 2.0]) + 0.01 * randn(length(xdata))

p0 = [0.5+0im, 0.5+0im]
fit = curve_fit(model, xdata, ydata, p0)

```

I get

```julia
ERROR: MethodError: no method matching isless(::Float64, ::ComplexF64)
Closest candidates are:
  isless(::T, ::T) where T<:Union{Float16, Float32, Float64} at float.jl:424
  isless(::AbstractFloat, ::AbstractFloat) at operators.jl:177
  isless(::Real, ::AbstractFloat) at operators.jl:178
  ...
Stacktrace:
  [1] max(x::ComplexF64, y::Float64)
    @ Base .\operators.jl:467
  [2] levenberg_marquardt(df::NLSolversBase.OnceDifferentiable{Vector{ComplexF64}, Matrix{ComplexF64}, Vector{ComplexF64}}, initial_x::Vector{ComplexF64}; x_tol::Float64, g_tol::Float64, maxIter::Int64, lambda::ComplexF64, tau::ComplexF64, lambda_increase::Float64, lambda_decrease::Float64, min_step_quality::Float64, good_step_quality::Float64, show_trace::Bool, lower::Vector{ComplexF64}, upper::Vector{ComplexF64}, avv!::Nothing)

```

This looks like a problem in `LsqFit` to me.

---

<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 18, 2022, 11:54am UTC](https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620/3 "2022-04-18T11:54:17Z")

</div>

> [@goerch](#):
>
> This looks like a problem in `LsqFit` to me.

Yes, it looks like its `levenberg_marquardt` function assumes that the model results have the same type as the parameters (see the array allocations [here](https://github.com/JuliaNLSolvers/LsqFit.jl/blob/0064c785a7c4969f0f6731a38a15732ea5411b4f/src/levenberg_marquardt.jl#L79-L86)), which is wrong in this case. They need to be a bit more careful in propagating the data types.

I would file an issue (and/or work on a PR).

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 18, 2022, 12:15pm UTC](https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620/4 "2022-04-18T12:15:10Z")

</div>

> [@stevengj](#):
>
> I would file an issue (and/or work on a PR).

@stevengj: I tried to [fix](https://github.com/goerch/LsqFit.jl/tree/complex-fit) the problem. Extended the original tests in `curve_fit.jl` and `curve_fit_inplace.jl` to check with `Float32`, `Float64`, `ComplexF32`, `ComplexF64`. Only open problem for now is I’m running into problems with complex AD in `ForwardDiff` here

```julia
        for ad in (T<:Complex ? (:finite,) : (:finite, :forward, :forwarddiff))
            fit = curve_fit(model, xdata, ydata, p0; autodiff = ad)
            @show fit.param
            @assert norm(fit.param - [1.0, 2.0]) < 0.05
            @test fit.converged

            # can also get error estimates on the fit parameters
            errors = margin_error(fit, 0.1)
            @assert norm(errors - [0.017, 0.075]) < 0.01
        end

```

What else to check?

---

<div class="post-metadata">

**Author:** ![PazzyBoardman449](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pazzyboardman449/32/35495_2.png) [@PazzyBoardman449](https://discourse.julialang.org/u/PazzyBoardman449)\
**Post date:** [April 18, 2022, 5:19pm UTC](https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620/6 "2022-04-18T17:19:49Z")

</div>

Thanks very much for your help, it’s super great to know that you guys are willing to help fix the problem! This has been my first question I’ve posted during my PhD after switching from Matlab to Julia, and it’s great to know there is help out there. I look forward to seeing the progress on the resolution of this issue!

---

<div class="post-metadata">

**Author:** ![PazzyBoardman449](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pazzyboardman449/32/35495_2.png) [@PazzyBoardman449](https://discourse.julialang.org/u/PazzyBoardman449)\
**Post date:** [April 18, 2022, 5:20pm UTC](https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620/7 "2022-04-18T17:20:48Z")

</div>

Ahh okay- I look forward to seeing the progress of the resolution of this issue! Many thanks for your help on this!

---

<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 18, 2022, 5:41pm UTC](https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620/8 "2022-04-18T17:41:16Z")

</div>

> [@goerch](#):
>
> Only open problem for now is I’m running into problems with complex AD in `ForwardDiff` here

I don’t think ForwardDiff supports this ([Support for real-valued function with complex arguments · Issue #498 · JuliaDiff/ForwardDiff.jl · GitHub](https://github.com/JuliaDiff/ForwardDiff.jl/issues/498)). I think Zygote [does](https://fluxml.ai/Zygote.jl/latest/complex/#Complex-Differentiation-1)?

(Or you can use finite differences here; that’s what Matlab’s `lsqcurvefit` does IIRC.)

---

<div class="post-metadata">

**Author:** ![Charlotte247](https://avatars.discourse-cdn.com/v4/letter/c/c37758/32.png) [@Charlotte247](https://discourse.julialang.org/u/Charlotte247)\
**Post date:** [December 15, 2022, 7:32am UTC](https://discourse.julialang.org/t/using-lsqfit-on-complex-data/79620/9 "2022-12-15T07:32:30Z")

</div>

Hi @PazzyBoardman449, you said you got it working in matlab? Could you explain how? I’m trying to do something similar but the output I get is always exactly the same as my starting point. Couldn’t find an answer on any matlab forum, so that’s why I asked it here…
