# Find intersection between curves in julia

**URL:** <https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494>\
**Category:** New to Julia\
**Tags:** roots, interpolations, splines\
**Created:** [October 27, 2021, 3:47pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494 "2021-10-27T15:47:41Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Luigi\_Marongiu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/luigi_marongiu/32/7909_2.png) [@Luigi\_Marongiu](https://discourse.julialang.org/u/Luigi_Marongiu)\
**Post date:** [October 27, 2021, 3:47pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/1 "2021-10-27T15:47:41Z")

</div>

Hello,  
I have two curves with the values:

```julia
col_y = [8.02511788606e7, 9.98481296252e7, 2.328332483329e8, 6.148181496526e8, 9.453171952624e8, 1.2331292887706e9, 1.4394296796998e9, 1.460066157955e9, 1.3570403824485e9, 1.4269447174002e9]

vin_y = [1.434628836798e8, 1.318375623746e8, 1.108524843855e8, 6.91176196241e7, 4.19137382458e7, 1.48676444645e7, 1.00659726053e7, 7.8734512643e6]

```

Is it possible to find the intersection x between these two curves? what is the approach in julia?  
Thank you

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [October 27, 2021, 4:28pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/2 "2021-10-27T16:28:11Z")

</div>

Do you have a model for what kind of curves these are (they look sigmoid, do you know what process generated them)? And is the `x`-scale the same or do they for instance span between the same limits (which is not the same thing since the number of elements is different)? Linear `x`-scale?

The reason you need to know is the answer will vary wildly depending on which way you interpret the question. A vector of values isn’t a function, in fact there is an uncountable infinity of functions which fit exactly.

The way I would do this is

- Find an analytic function `f_col`, `f_vin` that fits each of the sample vectors (for instance using `LsqFit.jl`)
- Form the function `g(x) = f_col(x) - f_vin(x)`
- Find the zero(s) of `g(x)` (for instance using `Roots.jl`)

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [October 27, 2021, 4:30pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/3 "2021-10-27T16:30:47Z")

</div>

You have points, not curves. The names suggest they are y-values, but it’s not clear what the corresponding x-values are for each.

Plotting these by assuming x=1:10 for the first and x=1:8 for the second gives:

![image](https://global.discourse-cdn.com/julialang/original/3X/d/7/d7de39daeee4d5a47893236c8d9edd2be4a8106e.png)

So there is an intersection just after x=2, but this is based on a linear interpolation between points which Plots does automatically. As Gustaphe says you might have some other function in mind to interpolate between the points, which will result in a different point of intersection.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [October 27, 2021, 4:45pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/4 "2021-10-27T16:45:27Z")

</div>

For this problem, Dierckx is just fine:

```julia
using Dierckx
n = length(vin_y)
spl = Spline1D(1:n, col_y[1:n] - vin_y)
x0 = roots(spl) # 2.4181
y0 = Spline1D(1:n, vin_y)(x0) # 1.2583e8

```

 ![Dierckx_curve_intersection](https://global.discourse-cdn.com/julialang/original/3X/5/a/5a0684a75f93443b39e39fbf4dc954be03c2b327.png)

---

<div class="post-metadata">

**Author:** ![Luigi\_Marongiu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/luigi_marongiu/32/7909_2.png) [@Luigi\_Marongiu](https://discourse.julialang.org/u/Luigi_Marongiu)\
**Post date:** [October 27, 2021, 5:06pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/5 "2021-10-27T17:06:21Z")

</div>

Thanks for the answers. I made a model, but it does not exactly fit the data:

 ![CASE2](https://global.discourse-cdn.com/julialang/original/3X/b/e/be2c849732293a42992c044bee2bbc3a632b8649.png)

Thus, I wanted to check the time difference of intersection between the actual data and the model…  
I’ll check the suggestions.

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [October 27, 2021, 5:10pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/6 "2021-10-27T17:10:29Z")

</div>

Here’s my way. I have an experimental version of `LsqFit` installed, so there will be a slight difference in syntax, but I just realized I’m in a bit of a hurry so I won’t fix that.

```julia
using Plots, LsqFit, Roots
default(;fontfamily="Computer Modern", label=nothing, seriestype=:scatter) # Better plot defaults
x_1 = 1:10
x_2 = 1:8
y_1 = [8.02511788606e7, 9.98481296252e7, 2.328332483329e8, 6.148181496526e8, 9.453171952624e8, 1.2331292887706e9, 1.4394296796998e9, 1.460066157955e9, 1.3570403824485e9, 1.4269447174002e9]
y_2 = [1.434628836798e8, 1.318375623746e8, 1.108524843855e8, 6.91176196241e7, 4.19137382458e7, 1.48676444645e7, 1.00659726053e7, 7.8734512643e6]
model(x, p) = 1e9*p[1]/(1+exp(-(x-p[2])/p[3])) # logistic function
f_1 = curve_fit(model, x_1, y_1, [1.0, 1.0, 1.0])
f_2 = curve_fit(model, x_2, y_2, [1e-1, 1.0, -1.0])
x_long = range(0.5,10.5;length=200)
pl_1 = plot(x_1, y_1)
plot!(pl_1, x_2, y_2)
plot!(pl_1, x_long, model.(x_long,Ref(f_1.param)); st=:line)
plot!(pl_1, x_long, model.(x_long,Ref(f_2.param)); st=:line)
g(x) = model(x, f_1.param) - model(x, f_2.param)
pl_2 = plot(g, x_long, st=:line)
plot(pl_1, pl_2; layout=(2,1)
find_zero(g, 2.0) # returns ~ 2.27

```

![image](https://global.discourse-cdn.com/julialang/original/3X/3/d/3d7cb2c643374cd43ecc0fefb31289436a6b11f6.png)

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [October 27, 2021, 5:12pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/7 "2021-10-27T17:12:28Z")

</div>

If you want the intersection between the actual data series, the answer is there is none. None of your sample points measure the same amount of bacteria of the two species.

---

<div class="post-metadata">

**Author:** ![Luigi\_Marongiu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/luigi_marongiu/32/7909_2.png) [@Luigi\_Marongiu](https://discourse.julialang.org/u/Luigi_Marongiu)\
**Post date:** [October 27, 2021, 7:30pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/8 "2021-10-27T19:30:51Z")

</div>

Thank you!  
the Dierckx solution worked out of the box. By using the actual x values (sorry, I forgot to add them originally)

```julia
x = [0.0, 6.465599999999999, 12.544800000000002, 24.0, 29.107200000000002, 45.772800000000004, 53.392799999999994, 68.0616]

```

I got the exact intersection:

 ![CASE2](https://global.discourse-cdn.com/julialang/original/3X/9/1/91b75203435c5e8a3f5c1d75ca3dbbab5a17f7ea.png)

The more canonical solution by gustaphe is giving me troubles. The definition of the model is very similar to the model I have set:

```julia
model = true_logistic(x, p) = p[1] ./ (1 .+ exp.(-p[2].*(x.-p[3])))

```

that is a logistic regression but I set 1 instead of 1e9. When I define g and find\_zero:

```julia
julia> g(x) = model(col_x[1:8], P_col) - model(col_x[1:8], P_vin)
g (generic function with 1 method)

julia> find_zero(g, col_x[2])
ERROR: Roots.ConvergenceFailed("Stopped")
Stacktrace:
 [1] find_zero(fs::Function, x0::Float64, M::Secant, N::AlefeldPotraShi; p::Nothing, tracks::Roots.NullTracks, verbose::Bool, kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Roots ~/.julia/packages/Roots/H7pXT/src/order0.jl:57
 [2] #find_zero#52
   @ ~/.julia/packages/Roots/H7pXT/src/order0.jl:37 [inlined]
 [3] find_zero
   @ ~/.julia/packages/Roots/H7pXT/src/order0.jl:35 [inlined]
 [4] #find_zero#16
   @ ~/.julia/packages/Roots/H7pXT/src/find_zero.jl:704 [inlined]
 [5] find_zero(f::Function, x0::Float64)
   @ Roots ~/.julia/packages/Roots/H7pXT/src/find_zero.jl:704
 [6] top-level scope
   @ none:1

julia> find_zero(g, 2.0)
ERROR: Roots.ConvergenceFailed("Stopped")
Stacktrace:
 [1] find_zero(fs::Function, x0::Float64, M::Secant, N::AlefeldPotraShi; p::Nothing, tracks::Roots.NullTracks, verbose::Bool, kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Roots ~/.julia/packages/Roots/H7pXT/src/order0.jl:57
 [2] #find_zero#52
   @ ~/.julia/packages/Roots/H7pXT/src/order0.jl:37 [inlined]
 [3] find_zero
   @ ~/.julia/packages/Roots/H7pXT/src/order0.jl:35 [inlined]
 [4] #find_zero#16
   @ ~/.julia/packages/Roots/H7pXT/src/find_zero.jl:704 [inlined]
 [5] find_zero(f::Function, x0::Float64)
   @ Roots ~/.julia/packages/Roots/H7pXT/src/find_zero.jl:704
 [6] top-level scope
   @ none:1

```

What am I getting wrong?

---

<div class="post-metadata">

**Author:** ![j\_verzani](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/j_verzani/32/8551_2.png) [@j\_verzani](https://discourse.julialang.org/u/j_verzani)\
**Post date:** [October 27, 2021, 8:37pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/10 "2021-10-27T20:37:56Z")

</div>

> [@Luigi\_Marongiu](#):
>
> ```julia
> col_y = [8.02511788606e7, 9.98481296252e7, 2.328332483329e8, 6.148181496526e8, 9.453171952624e8, 1.2331292887706e9, 1.4394296796998e9, 1.460066157955e9, 1.3570403824485e9, 1.4269447174002e9]
> 
> vin_y = [1.434628836798e8, 1.318375623746e8, 1.108524843855e8, 6.91176196241e7, 4.19137382458e7, 1.48676444645e7, 1.00659726053e7, 7.8734512643e6]
> 
> ```

Likely you have a bad starting point. With only 1 intersection you should be able to use a bracketing method: `find_zero(g, 1, 50)`

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [October 27, 2021, 9:19pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/11 "2021-10-27T21:19:11Z")

</div>

The reason I multiplied by 1e9 is that LsqFit (and any fitting method) is better at finding similarly sized parameters, so I scaled up the model so we can expect `p.≈1.0`.

Your problem is in the definition of `g`. It needs to depend on `x`, not `col_x`.

---

<div class="post-metadata">

**Author:** ![Luigi\_Marongiu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/luigi_marongiu/32/7909_2.png) [@Luigi\_Marongiu](https://discourse.julialang.org/u/Luigi_Marongiu)\
**Post date:** [October 27, 2021, 9:20pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/12 "2021-10-27T21:20:55Z")

</div>

Ah, so simple. It worked!

```julia
julia> g(x) = model(x, P_col) - model(x, P_vin)
g (generic function with 1 method)

julia> find_zero(g, col_x[2])
10.018996507513226

```

 ![CASE2](https://global.discourse-cdn.com/julialang/original/3X/c/3/c3dcbe01b30e1729271ec41d9dc76d6400ad760d.png)

Thank you

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [October 27, 2021, 9:35pm UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/13 "2021-10-27T21:35:45Z")

</div>

Glad it worked out!

Can I ask what function you’re fitting to in the figure? Because the logistic function seems like a better fit, and from the little I know of microbiology it’s not an unreasonable model, so it seems a little strange to only use the better fit to verify the worse.

---

<div class="post-metadata">

**Author:** ![Luigi\_Marongiu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/luigi_marongiu/32/7909_2.png) [@Luigi\_Marongiu](https://discourse.julialang.org/u/Luigi_Marongiu)\
**Post date:** [October 28, 2021, 7:08am UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/14 "2021-10-28T07:08:23Z")

</div>

> [@Luigi\_Marongiu](#):
>
> `true_logistic`

Hi, it is the `true_logistic`; I see that does not fit the data completely but it is the same model that I used for another group of bacteria (where it was more fitting). For consistency, I am sticking to this…

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [October 28, 2021, 7:20am UTC](https://discourse.julialang.org/t/find-intersection-between-curves-in-julia/70494/15 "2021-10-28T07:20:56Z")

</div>

Ah okay, I missed the log axis. The fit is decent 🙂
