DEV Community

Cover image for How I approximated a function f(x) using an image as input
Marcos Leal
Marcos Leal

Posted on

How I approximated a function f(x) using an image as input

Recently I was reading this scientific paper and came across this graph:

Image description

In a first glance it looked pretty much like a gamma distribution. Using scipy's gamma function I could create a similar curve using two parameters: the shape and scale. If the data in the graph was a truly gamma these would suffice but as they have other meanings in each scale I also needed a third parameter to take account for the y-axis range

As the data is not provided with the graph I was able to approximate it using PlotDigitalizer which is a web solution that allows to upload a graph and, given the axis scales, estimates the points on the graph.

With this data I was able to minimize my desired function using the curve_fit

from scipy.optimize import curve_fit
import numpy as np
from scipy.stats import gamma

def func(x, a, b, c):
    return gamma.pdf(x, a, scale=b)*c

popt, pcov = curve_fit(func, df['x'], df['y'])

popt, pcov

>> (array([2.38845754e+00, 4.14949111e+01, 1.65402740e+04]),
>> array([[ 3.66739537e-02, -9.02425608e-01, -7.11863037e+01],
        [-9.02425608e-01,  2.56723468e+01,  2.87599647e+03],
        [-7.11863037e+01,  2.87599647e+03,  9.93779351e+05]]))
Enter fullscreen mode Exit fullscreen mode

And then plot it using the plotly library

import plotly.graph_objects as go
import numpy as np
from scipy.stats import gamma

#1 ml of 1,4-butanediol is equivalent to 1.4 g of Na-GHB.

x = np.linspace(0, 600, 100)
y = gamma.pdf(x, a=popt[0], scale=popt[1])*popt[2]

fig = go.Figure(data=go.Scatter(x=x, y=y))

# Add data from the dataframe df
fig.add_trace(go.Scatter(x=df['x'], y=df['y'], mode='markers', name='original'))

# Edit the layout to add title, and change x and y axis labels
fig.update_layout(title='GHB Concentration in Blood', xaxis_title='Time (min)', yaxis_title='Concentration (mg/L)')


# Edit the layout make the width of the graph 600px
fig.update_layout(width=500)
fig.show()
fig.write_image("fig1.png")
Enter fullscreen mode Exit fullscreen mode

Image description

In this example I wanted to approximate my data as a gamma function but in reality it could be any given function with any set of parameters. The curve_fit uses non-linear least squares to fit a function f. If I didn't had a function in mind I could use other machine learning techniques to obtain generic approximations and have a better guess on which approximations to use.

Top comments (0)