# How to find inflection point of curve?

**URL:** <https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892>\
**Category:** Numerics\
**Tags:** question, function\
**Created:** [November 28, 2020, 9:06am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892 "2020-11-28T09:06:10Z")\
**Posts on this page:** 20\
**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:** [November 28, 2020, 9:06am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/1 "2020-11-28T09:06:10Z")

</div>

Hello,  
I have the function

```julia
y = ϑ - ((1/ω) * log(x/ε)) - 1/μ

```

Is there a simple way in Julia to find the flection point of the function?  
if I set these paramaters:

```julia
mu = 0.72 # maximum growth rate resistant (E. coli)
omega = 0.05 # outflow
tmax = 4000.0 # time span 0-tmax
epsilon = 1 # concentration equivalent to 1 phage
Tp = 2.392731385751533
ε, ω, ϑ, μ = [epsilon, omega, Tp, mu, tmax]
Y = []
    X = 0.0:0.1:τ
    for x in X
        y = ϑ - ((1/ω) * log(x/ε)) - 1/μ
        push!(Y, y)
    end

```

I get the figure:

 ![find_Tf](https://global.discourse-cdn.com/julialang/original/3X/1/d/1dc2548b24da5a84605b3fc1f1e0557c05186b1f.png)  
Is it possible to find the inflection point of the curve, which should be at around t=500?  
Or it is all mathematics and I need to solve the point by mathematical analysis?  
Thank you

---

<div class="post-metadata">

**Author:** ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)\
**Post date:** [November 28, 2020, 9:19am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/2 "2020-11-28T09:19:58Z")

</div>

ApproxFun.jl Can do this

---

<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:** [November 28, 2020, 9:20am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/3 "2020-11-28T09:20:40Z")

</div>

You may need to find the [point with minimum radius of curvature](https://en.wikipedia.org/wiki/Radius_of_curvature).

---

<div class="post-metadata">

**Author:** ![jonathanBieler](https://avatars.discourse-cdn.com/v4/letter/j/82dd89/32.png) [@jonathanBieler](https://discourse.julialang.org/u/jonathanBieler)\
**Post date:** [November 28, 2020, 9:49am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/4 "2020-11-28T09:49:33Z")

</div>

You can use automatic differentiation :

```julia
using ForwardDiff, Roots

f(x) = sin(x)
g = x->ForwardDiff.derivative(f,x)
find_zero(x->ForwardDiff.derivative(g,x), 3)

```

(you still need to check that the second derivative changes signs around the zero)

That said the second derivative of your function is `1/(ω*x^2)` and thus has not inflection point.

You can also use broadcasting (or an array comprehension) instead of a for loop to evaluate your function :

```julia
f(x, ϑ, ω, ε, μ) = ϑ - ((1/ω) * log(x/ε)) - 1/μ
x = 0.0:0.1:τ
y = f.(x, ϑ, ω, ε, μ)

```

---

<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:** [November 28, 2020, 11:22am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/5 "2020-11-28T11:22:34Z")

</div>

The maximum curvature (or minimum radius of curvature) occurs at time t = 14.14:

```julia
using ForwardDiff, Roots, Plots
function f(t)
    ε, ω, ϑ, μ = [1., 0.05 , 2.392731385751533, 0.72]
    return ϑ - (1/ω) * log(t/ε) - 1/μ
end
τ = 4000.0
t = 10 .^(-3:0.01:log10(τ))
y = f.(t)
plot(t,y)

df = t->ForwardDiff.derivative(f,t)
d2f = t->ForwardDiff.derivative(df,t)
rho(t) = (abs(1 + df(t)^2))^1.5 / abs(d2f(t)) # radius of curvature
drho = t->ForwardDiff.derivative(rho,t) # ... and its derivative
plot(t,rho, xaxis=:log, yaxis=:log)
savefig("max_curvature.png")

julia> fzero(drho, 500)
14.142135623730953

```

![max_curvature](https://global.discourse-cdn.com/julialang/original/3X/1/1/11af8df0a376536a54fe4c737b4e2f1b37793a5f.png)

To find something around t=500, the biologists definition of “inflection point” may be required.

---

<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:** [November 28, 2020, 1:59pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/6 "2020-11-28T13:59:02Z")

</div>

Thank you all. The latter looks very interesting but:

```julia
julia> f_Tf(x, ϑ, ω, ε, μ) = ϑ - ((1/ω) * log(x/ε)) - 1/μ
f_Tf (generic function with 1 method)
julia> ε, ω, ϑ, μ, τ = [epsilon, omega, Tp, nu, tmax]
5-element Array{Float64,1}:
    1.0
    0.05
    2.392731385751533
    0.72
 4000.0
julia> x = 0.0:0.1:τ
0.0:0.1:4000.0
julia> y = f_Tf.(x, ϑ, ω, ε, μ)
40001-element Array{Float64,1}:
julia> df = t->ForwardDiff.derivative(f_Tf,t)
#19 (generic function with 1 method)
julia> d2f = t->ForwardDiff.derivative(df,t)
#21 (generic function with 1 method)
julia> rho(t) = (abs(1 + df(t)^2))^1.5 / abs(d2f(t)) # radius of curvature
rho (generic function with 1 method)
julia> drho = t->ForwardDiff.derivative(rho,t) 
#23 (generic function with 1 method)

julia> fzero(drho, 500)
ERROR: MethodError: no method matching f_Tf(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(f_Tf),ForwardDiff.Dual{ForwardDiff.Tag{typeof(rho),Float64},Float64,1}},ForwardDiff.Dual{ForwardDiff.Tag{typeof(rho),Float64},Float64,1},1})
Closest candidates are:
  f_Tf(::Any, ::Any, ::Any, ::Any, ::Any) at none:1
Stacktrace:
 [1] derivative at /home/gigiux/.julia/packages/ForwardDiff/sdToQ/src/derivative.jl:14 [inlined]
 [2] (::var"#19#20")(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(rho),Float64},Float64,1}) at ./none:1
 [3] rho(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(rho),Float64},Float64,1}) at ./none:1
 [4] derivative at /home/gigiux/.julia/packages/ForwardDiff/sdToQ/src/derivative.jl:14 [inlined]
 [5] (::var"#23#24")(::Float64) at ./none:1
 [6] (::Roots.FnWrapper)(::Float64) at /home/gigiux/.julia/packages/Roots/Z5Mal/src/find_zero.jl:262
 [7] (::Roots.DerivativeFree{Roots.FnWrapper})(::Float64) at /home/gigiux/.julia/packages/Roots/Z5Mal/src/find_zero.jl:263 (repeats 2 times)
 [8] init_state(::Roots.Secant, ::Roots.DerivativeFree{Roots.DerivativeFree{Roots.FnWrapper}}, ::Tuple{Float64,Float64}) at /home/gigiux/.julia/packages/Roots/Z5Mal/src/derivative_free.jl:64
 [9] init_state(::Roots.Secant, ::Roots.DerivativeFree{Roots.DerivativeFree{Roots.FnWrapper}}, ::Float64) at /home/gigiux/.julia/packages/Roots/Z5Mal/src/derivative_free.jl:59
 [10] find_zero(::Roots.DerivativeFree{Roots.FnWrapper}, ::Float64, ::Roots.Secant, ::Roots.AlefeldPotraShi; tracks::Roots.NullTracks, verbose::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/gigiux/.julia/packages/Roots/Z5Mal/src/find_zero.jl:654
 [11] #find_zero#33 at /home/gigiux/.julia/packages/Roots/Z5Mal/src/derivative_free.jl:123 [inlined]
 [12] find_zero at /home/gigiux/.julia/packages/Roots/Z5Mal/src/derivative_free.jl:120 [inlined]
 [13] derivative_free(::Function, ::Float64; order::Int64, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/gigiux/.julia/packages/Roots/Z5Mal/src/fzero.jl:155
 [14] derivative_free(::Function, ::Float64) at /home/gigiux/.julia/packages/Roots/Z5Mal/src/fzero.jl:134
 [15] #fzero#48 at /home/gigiux/.julia/packages/Roots/Z5Mal/src/fzero.jl:65 [inlined]
 [16] fzero(::Function, ::Int64) at /home/gigiux/.julia/packages/Roots/Z5Mal/src/fzero.jl:63
 [17] top-level scope at none:1

```

Why the error?  
Is 500 based on my initial eye-ball assumption?  
Is the definition of rho universal (based on the curvature radius) or is specific to the equation f\_Tf?

---

<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:** [November 28, 2020, 2:10pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/7 "2020-11-28T14:10:45Z")

</div>

If you click on the link I have provided in the earlier post, you will see the wikipedia page with the definition of the radius of curvature. It is universal for a real function (R–\> R).

---

<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:** [November 28, 2020, 4:20pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/8 "2020-11-28T16:20:01Z")

</div>

@Luigi_Marongiu, the doc of [Roots.jl](https://juliahub.com/docs/Roots/o0Xsi/1.0.5/) says that it is a package for finding zeros of continuous scalar functions of a single real variable. If you follow the single variable syntax in my solution, there will be no such error.  
For the Roots workflow, you could define a single variable auxiliary function:

```julia
f(t) = f_Tf(t, ϑ, ω, ε, μ) 
df = t->ForwardDiff.derivative(f,t)
# etc...

```

---

<div class="post-metadata">

**Author:** ![Geoffrey](https://avatars.discourse-cdn.com/v4/letter/g/bc8723/32.png) [@Geoffrey](https://discourse.julialang.org/u/Geoffrey)\
**Post date:** [November 28, 2020, 7:37pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/9 "2020-11-28T19:37:35Z")

</div>

Hi,

I think what cause that the point of maximum curvature don’t fit on our intuition is that your function value is not bounded (it can give value from [-inf, inf]) so the plot we see and the impression that there is an elbow at 500 is biased by the fact that we only see a portion of the curve.

Another solution would be to find the best linear split, I mean the point that minimize the RMSE of the linear regression on the left and on the right of this point:

```julia
function f(t)
    ε, ω, ϑ, μ = (1.0, 0.05 , 2.392731385751533, 0.72)
    return ϑ - ((1 / ω) * log(t / ε)) - 1 / μ
end

# function to construct a Vandermonde matrix from a vector
function Vand(x, d)
    V = ones(length(x))
    for i in 1:d
        V = hcat(V, x .^ i)
    end
    return V
end

# function that given a test point compute the RMSE of the linear regression on the left and on the rigth of this point
function findchangepts(xi, f, xmin = eps(), xmax = 4000, n = 100)
    # take n sample of the function on the left
    l = range(xmin, xi - eps(); length = n)
    # perform the linear regression
    β = Vand(l, 1) \ f.(l)
    # compute the RMSE (using the n points)
    RMSE = sqrt(sum(t -> t * t, f.(l) .- Vand(l, 1) * β) / n)
    # do the same on the rigth
    r = range(xi + eps(), xmax; length = n)
    β = Vand(r, 1) \ f.(r)
    RMSE += sqrt(sum(t -> t * t, f.(r) .- Vand(r, 1) * β) / n)
    return RMSE
end

# look at the value for different change point
xi = range(100, 3000; length = 100)
rmse = [findchangepts(i, f) for i in xi]
plot(xi, rmse; legend = false)

```

Then we look for the minimum of the RMSE:

```julia
# use Optim to find the minimum of RMSE
using Optim
res = Optim.optimize(i -> findchangepts(i, f), 100, 3000)
k = Optim.minimizer(res) # 827.4879390290434

plot(x, y; legend = false)
vline!([k])
l = range(eps(), k - eps(); length = 100)
β1 = Vand(l, 1) \ f.(l)
r = range(k + eps(), τ; length = 100)
β2 = Vand(r, 1) \ f.(r)
plot!(l, Vand(l, 1) * β1)
plot!(r, Vand(r, 1) * β2)

```

![changepts](https://global.discourse-cdn.com/julialang/original/3X/9/7/97eeb7b435148ac87a3d4b50ba7731133a2b2012.png)

But as you can see this point is quiet far from 500… Actually the more sample you will add on the right the more the split point will be drag on the right, so this point is totally dependent on xmax. To illustrate this you get a split point at circa 517 if you use xmax = 2500.

---

<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:** [November 28, 2020, 10:28pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/10 "2020-11-28T22:28:02Z")

</div>

Knowing the context/physical meaning of the curve, should help selecting some sensible criteria for the departure point.  
With an arbitrary choice of setting the cut-off when the rate of change of the curve is 10 times above the minimum rate recorded at the end of the observation period, one gets **t = 398** :

```julia
dfmax = maximum(df.(t)) # maximum because all slopes are negative
dfcut(t) = df(t) - 10*dfmax # cutoff at curve change rate = 10x minimum in time range
fzero(dfcut, 1)

julia> fzero(dfcut, 1)
398.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:** [November 29, 2020, 9:02am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/11 "2020-11-29T09:02:43Z")

</div>

Thank you. The context is that of defining the optimal time Tf to administer a shot of phages in phage therapy, as defined by [Payne and Jansen 2001](https://pubmed.ncbi.nlm.nih.gov/11162051/). ϑ = Tp in the paper and corresponds to the time when the bacterial target reaches the optimal concentration. There are no limits indicated, but I guess it will go from 0 (start of the model) to a t max (end of the process), which in my case I set at 2500 (and extended to 4000 in the graph to see how it would change).

This time the definition of `fzero` worked, giving the value of 14.14 as reported. When using the values 517 and 398, I get models like these:

 ![Scenario_7 (another copy)](https://global.discourse-cdn.com/julialang/original/3X/d/8/d8cef59f7239c6c14661f817d7db0dfd3459e0a8.png)  
 ![Scenario_7 (3rd copy)](https://global.discourse-cdn.com/julialang/original/3X/b/7/b700453a99b19e73d32dccff58bfcbcc5216e331.png)  
The use of 14.14 gives the same type of graphs. Even if I use 10 or 100 fold phage input, the graph does not change.  
In theory, the red line should go to zero after the injection of the phage at t=398 or t=517  
Given the intricacy of the subject, is there a good manual that explains how to do numeric analysis in Julia?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 29, 2020, 9:59am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/12 "2020-11-29T09:59:41Z")

</div>

> [@Luigi\_Marongiu](#):
>
> is there a good manual that explains how to do numeric analysis in Julia?

Please note that numerical analysis is a very broad field; you may need to be more specific.

Incidentally, in the above graphs I don’t see the red lines crossing 0 at all. Are you sure that the problem is well-defined?

---

<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:** [November 29, 2020, 10:04am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/13 "2020-11-29T10:04:10Z")

</div>

Concerning documentation on numerical analysis in Julia, the following [course](http://homepages.math.uic.edu/~jan/mcs471/index.html) by Jan Verschelde from UIC seems to be a very good resource.  
As you are simulating dynamic processes, you should look also at the detailed documentation of [DifferentialEquations.jl](https://diffeq.sciml.ai/stable/).

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [November 29, 2020, 4:44pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/14 "2020-11-29T16:44:30Z")

</div>

@Luigi_Marongiu

1. I couldn’t find the definition of “flection point”. Do you mean “inflection point”, i.e. the point where the at which the curvature changes sign? In this case it looks like your curve doesn’t have one.
2. Your plots (multiple colors) at different injection times look the same. If they are indeed what you get, then it’s probably due to some bug.
3. If I were you, I’d try to simulate the whole dynamic process using [DifferentialEquations.jl](https://diffeq.sciml.ai/stable/) as @rafael.guerra suggested, define your objective function, which could be some concentration of bacteria at a definite time point, or some integral over a time span, or whatever, and then try to vary the injection point and look for the optimum. It looks like your problem is 1D (time being the independent variable) and involves only a few dependent variables, so it’s probably not excessively compute intensive.

---

<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:** [November 29, 2020, 5:09pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/15 "2020-11-29T17:09:16Z")

</div>

Yes “flection point” was a typo, sorry. It was correct the second time. The problem is indeed that the red line DOES NOT reach 0 (if I extend the y-axis to 1, the result does not change). The idea is that if the injection point is correct, the red lines should go to zero and stay there. Here there is no difference between 517, 398 or 14. The graphs are generated with DifferentialEquations.jl. I’ll see for the video course. Thanks

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [November 29, 2020, 5:18pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/16 "2020-11-29T17:18:53Z")

</div>

> [@Luigi\_Marongiu](#):
>
> Even if I use 10 or 100 fold phage input, the graph does not change.

And with 1000000000 fold phage input?

---

<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:** [November 29, 2020, 6:33pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/17 "2020-11-29T18:33:25Z")

</div>

@Luigi_Marongiu, the constants in your equation: `y = ϑ - (1/ω) * log(x/ε) - 1/μ`, do not have units defined. You should check the consistency of your units. Maybe some conversion factors are missing?

---

<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:** [November 29, 2020, 8:18pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/18 "2020-11-29T20:18:31Z")

</div>

Same thing:

 ![Scenario_7](https://global.discourse-cdn.com/julialang/original/3X/c/5/c538611c22042ddb0614fdbbf776079d43d52cef.png)  
The whole model is:

```julia
function multiInfect!(du, u, p, t)
    μ, ν, κ, φ, ψ, ω, β, Β, η, Η = p
    #=
    du[1] = resident susceptible
    du[2] = resident infected
    du[3] = resident phage
    du[4] = invader susceptible
    du[5] = invader infected
    du[6] = invader phage
    =#
    sumBact = u[1]+u[2]+u[4]+u[5]
    du[1] = (μ * u[1]) * (1 - sumBact/κ) - (φ * u[1] * u[3]) - (ω * u[1])
    du[2] = (φ * u[1] * u[3]) - (η * u[2]) - (ω * u[2])
    du[3] = (β * η * u[2]) - (φ * u[1] * u[3]) - (ω * u[3])

    du[4] = (ν * u[4]) * (1 - sumBact/κ) - (ψ * u[4] * u[6]) - (ω * u[4])
    du[5] = (ψ * u[4] * u[6]) - (Η * u[5]) - (ω * u[5])
    du[6] = (Β * Η * u[5]) - (ψ * u[4] * u[6]) - (ω * u[6])
end
#=
    From: Payne J Theor Biol 2001;208:37
    μ = growth rate (replication coef), a
    φ = adsorption rate (transmission coef), b
    η = lysis rate, k
    β = burst size, L
    ω = outflow (decay rate phage), m
    σ = initial bacterial concentratoin, S0
    τ = maximum running time
    ϑ = Tp
=#
function ϝ_Tp(p) # proliferation-onset time
    ω, η, μ, β, φ, σ = p
    x = (1/μ) * log( ((η-μ)*ω) / (φ*η*β*σ) )
    return x
end
function ϝ_Vf(p)
    ε, ω, ϑ, μ = p
    # solution by looping
    Y = []
    X = 0.0:0.1:2*ϑ
    for x in X
        y = ε * exp( ω * (ϑ-x) + (ω/μ) * (exp( -μ * (ϑ-x) ) - 1) )
        push!(Y, y)
    end
    return minimum(Y)
end
ϝ_Tf(x, ϑ, ω, ε, μ) = ϑ - ((1/ω) * log(x/ε)) - 1/μ

# parameters
X = 2500 # tmax for plot
mu = 0.47 # maximum growth rate susceptible (B. longum)
nu = 0.72 # maximum growth rate resistant (E. coli)
kappa = 2.2*10^7 # maximum population density
phi = 10.0^-9 # adsorption rate
omega = 0.05 # outflow
eta = 1.0 # lyse rate
beta = 50.0 # burst size
tau = 3.62 # latency time
tmax = 4000.0 # time span 0-tmax
s0 = 50000.0 # initial susceptible population
i0 = 0.0 # initial infected population
v0 = 80.0 # initial phage population
psi = 10.0^-9 # adsorption rate alternative
Eta = 1.0 # lyse rate alternative
Beta = 50.0 # burst size alternative
r_s0 = 50000.0 # initial resident susceptible population
r_i0 = 0.0 # initial resident infected population
r_v0 = 1000.0 # initial resident phage population
i_s0 = 0.0 # initial invader susceptible population
i_i0 = 0.0 # initial invader infected population
i_v0 = 0.0 # initial invader phage population
t_in = 1000 # time of inoculum
i_in = 500 # amount of invader
epsilon = 1 # concentration equivalent to 1 phage

# calculate critical parameters
Tp = ϝ_Tp([omega, Eta, nu, Beta, psi, r_s0])
Vf = ϝ_Vf([epsilon, omega, Tp, nu])
#=
 Tf (time of injection) from this post
=#
 
# implement
Tf = 398
tspan = (0.0, tmax)
u0 = [r_s0, r_i0, r_v0, i_s0, i_i0, i_v0]
parms = [mu, nu, kappa, phi, psi, omega, beta, Beta, eta, Eta]
condition_1(u, t, integrator) = t-t_in # time invader inoculum
condition_2(u, t, integrator) = t-(t_in+Tf) # time phage activation
affect_1!(integrator) = integrator.u[4] += i_in # amount invader inoculum
affect_2!(integrator) = integrator.u[6] += 1000000000 # amount phage
cb1 = ContinuousCallback(condition_1, affect_1!)
cb2 = ContinuousCallback(condition_2, affect_2!)
delay = CallbackSet(cb1, cb2)
prob = ODEProblem(multiInfect!, u0, tspan, parms)
soln = solve(prob, AutoVern7(Rodas5()), callback=delay, tstops=[1000])

```

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [November 29, 2020, 8:53pm UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/19 "2020-11-29T20:53:21Z")

</div>

> [@Luigi\_Marongiu](#):
>
> Same thing

As I understand it, physically (or, in your case rather “biologically”), very high phage dose at an arbitrary time point should eliminate **all** bacteria. If that doesn’t happen in your solution, then most probably due to some silly bug somewhere.

---

<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:** [November 30, 2020, 7:03am UTC](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892/20 "2020-11-30T07:03:23Z")

</div>

Yes, it is worrisome. To give more context, The graph reported in the original paper for the definition of Tf gives this profile:

 ![Tf](https://global.discourse-cdn.com/julialang/original/3X/0/9/090f20191cd6752291074120ffab4b2a4f30ae5f.jpeg)  
To note that the time t=20 is the end of the simulation (tmax) that in my case is 2500.  
and the formula for Tf (ϑ - ((1/ω) \* log(x/ε)) - 1/μ) [with ϑ = Tp = (1/μ) \* log( ((η-μ)_ω) / (φ_η_β_σ) )] gives a function that is similar to the hyperbolic or negative exponential:  
 ![hyper](https://global.discourse-cdn.com/julialang/original/3X/b/1/b1659d90b2f1695b91633020bf7a5f18f28a8f75.jpeg)

 ![neg](https://global.discourse-cdn.com/julialang/original/3X/0/0/00f284af63916273f8af3cd940607d87c77064ac.jpeg)

The manuals report `a/2b` or `a/e` as important points, which should be similar to the inflection point I was looking for. The problem is to convert Tf into the hyperbolic or exponential format to find `a` and `b`…  
Or perhaps it is just that the model reported in the paper is fundamentally different from the one I am studying.

[Next page](https://discourse.julialang.org/t/how-to-find-inflection-point-of-curve/50892.md?page=2)
