<?xml version="1.0" encoding="UTF-8"?>

<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <atom:link href="http://kitchingroup.cheme.cmu.edu/blog/feed/index.xml" rel="self" type="application/rss+xml" />
    <title>The Kitchin Research Group</title>
    <link>https://kitchingroup.cheme.cmu.edu/blog</link>
    <description>Chemical Engineering at Carnegie Mellon University</description>
    <pubDate>Sat, 01 Nov 2025 13:47:46 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    
    <item>
      <title>Interpolation with splines</title>
      <link>https://kitchingroup.cheme.cmu.edu/blog/2013/02/27/Interpolation-with-splines</link>
      <pubDate>Wed, 27 Feb 2013 14:43:07 EST</pubDate>
      <category><![CDATA[interpolation]]></category>
      <guid isPermaLink="false">hItvaygDfX5o1eBFfC1msqBhpEw=</guid>
      <description>Interpolation with splines</description>
      <content:encoded><![CDATA[


&lt;p&gt;
When you do not know the functional form of data to fit an equation, you can still fit/interpolate with splines.
&lt;/p&gt;
&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #ff0000; font-weight: bold;"&gt;# use splines to fit and interpolate data&lt;/span&gt;
&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.interpolate &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; interp1d
&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.optimize &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; fmin
&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; numpy &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; np
&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; plt

x = np.array([ 0,      1,      2,      3,      4    ])
y = np.array([ 0.,     0.308,  0.55,   0.546,  0.44 ])

&lt;span style="color: #ff0000; font-weight: bold;"&gt;# create the interpolating function&lt;/span&gt;
f = interp1d(x, y, kind=&lt;span style="color: #228b22;"&gt;'cubic'&lt;/span&gt;, bounds_error=&lt;span style="color: #8b0000;"&gt;False&lt;/span&gt;)

&lt;span style="color: #ff0000; font-weight: bold;"&gt;# to find the maximum, we minimize the negative of the function. We&lt;/span&gt;
&lt;span style="color: #ff0000; font-weight: bold;"&gt;# cannot just multiply f by -1, so we create a new function here.&lt;/span&gt;
f2 = interp1d(x, -y, kind=&lt;span style="color: #228b22;"&gt;'cubic'&lt;/span&gt;)
xmax = fmin(f2, 2.5)

xfit = np.linspace(0,4)

plt.plot(x,y,&lt;span style="color: #228b22;"&gt;'bo'&lt;/span&gt;)
plt.plot(xfit, f(xfit),&lt;span style="color: #228b22;"&gt;'r-'&lt;/span&gt;)
plt.plot(xmax, f(xmax),&lt;span style="color: #228b22;"&gt;'g*'&lt;/span&gt;)
plt.legend([&lt;span style="color: #228b22;"&gt;'data'&lt;/span&gt;,&lt;span style="color: #228b22;"&gt;'fit'&lt;/span&gt;,&lt;span style="color: #228b22;"&gt;'max'&lt;/span&gt;], loc=&lt;span style="color: #228b22;"&gt;'best'&lt;/span&gt;, numpoints=1)
plt.xlabel(&lt;span style="color: #228b22;"&gt;'x data'&lt;/span&gt;)
plt.ylabel(&lt;span style="color: #228b22;"&gt;'y data'&lt;/span&gt;)
plt.title(&lt;span style="color: #228b22;"&gt;'Max point = ({0:1.2f}, {1:1.2f})'&lt;/span&gt;.format(&lt;span style="color: #8b0000;"&gt;float&lt;/span&gt;(xmax),
                                                    &lt;span style="color: #8b0000;"&gt;float&lt;/span&gt;(f(xmax))))
plt.savefig(&lt;span style="color: #228b22;"&gt;'images/splinefit.png'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
Optimization terminated successfully.
         Current function value: -0.575712
         Iterations: 12
         Function evaluations: 24
&lt;/pre&gt;

&lt;p&gt;&lt;img src="/img/./images/splinefit.png"&gt;&lt;p&gt;

&lt;p&gt;
There are other good examples at &lt;a href="http://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html" &gt;http://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Copyright (C) 2013 by John Kitchin. See the &lt;a href="/copying.html"&gt;License&lt;/a&gt; for information about copying.&lt;p&gt;&lt;p&gt;&lt;a href="/org/2013/02/27/Interpolation-with-splines.org"&gt;org-mode source&lt;/a&gt;&lt;p&gt;]]></content:encoded>
    </item>
    <item>
      <title>Interpolation of data</title>
      <link>https://kitchingroup.cheme.cmu.edu/blog/2013/02/27/Interpolation-of-data</link>
      <pubDate>Wed, 27 Feb 2013 14:42:57 EST</pubDate>
      <category><![CDATA[interpolation]]></category>
      <guid isPermaLink="false">7xoWswdcjJsWclaIEER-RpwaX08=</guid>
      <description>Interpolation of data</description>
      <content:encoded><![CDATA[


&lt;p&gt;
&lt;a href="http://matlab.cheme.cmu.edu/2011/08/01/interpolation-of-data/" &gt;Matlab post&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
When we have data at two points but we need data in between them we use interpolation. Suppose we have the points (4,3) and (6,2) and we want to know the value of y at x=4.65, assuming y varies linearly between these points. we use the interp1d command to achieve this. The syntax in python is slightly different than in matlab.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.interpolate &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; interp1d

x = [4, 6]
y = [3, 2]

ifunc = interp1d(x, y)

&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; ifunc(4.65)


ifunc = interp1d(x, y, bounds_error=&lt;span style="color: #8b0000;"&gt;False&lt;/span&gt;) &lt;span style="color: #ff0000; font-weight: bold;"&gt;# do not raise error on out of bounds&lt;/span&gt;
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; ifunc([4.65, 5.01, 4.2, 9])
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
2.675
[ 2.675  2.495  2.9      nan]
&lt;/pre&gt;

&lt;p&gt;
The default interpolation method is simple linear interpolation between points. Other methods exist too, such as fitting a cubic spline to the data and using the spline representation to interpolate from.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.interpolate &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; interp1d

x = [1, 2, 3, 4];
y = [1, 4, 9, 16]; &lt;span style="color: #ff0000; font-weight: bold;"&gt;# y = x^2&lt;/span&gt;

xi = [ 1.5, 2.5, 3.5]; &lt;span style="color: #ff0000; font-weight: bold;"&gt;# we want to interpolate on these values&lt;/span&gt;
y1 = interp1d(x,y)

&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; y1(xi)

y2 = interp1d(x,y,&lt;span style="color: #228b22;"&gt;'cubic'&lt;/span&gt;)
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; y2(xi)

&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; numpy &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; np
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; np.array(xi)**2
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
[  2.5   6.5  12.5]
[  2.25   6.25  12.25]
[  2.25   6.25  12.25]
&lt;/pre&gt;

&lt;p&gt;
In this case the cubic spline interpolation is  more accurate than the linear interpolation. That is because the underlying data was polynomial in nature, and a spline is like a polynomial. That may not always be the case, and you need some engineering judgement to know which method is best.
&lt;/p&gt;
&lt;p&gt;Copyright (C) 2013 by John Kitchin. See the &lt;a href="/copying.html"&gt;License&lt;/a&gt; for information about copying.&lt;p&gt;&lt;p&gt;&lt;a href="/org/2013/02/27/Interpolation-of-data.org"&gt;org-mode source&lt;/a&gt;&lt;p&gt;]]></content:encoded>
    </item>
    <item>
      <title>Numerical solution to a simple ode</title>
      <link>https://kitchingroup.cheme.cmu.edu/blog/2013/02/26/Numerical-solution-to-a-simple-ode</link>
      <pubDate>Tue, 26 Feb 2013 21:17:44 EST</pubDate>
      <category><![CDATA[interpolation]]></category>
      <category><![CDATA[ode]]></category>
      <guid isPermaLink="false">se4wOj2tNpFT8f6A6HiRkUABg1I=</guid>
      <description>Numerical solution to a simple ode</description>
      <content:encoded><![CDATA[


&lt;p&gt;
&lt;a href="http://matlab.cheme.cmu.edu/2011/08/03/numerical-solution-to-a-simple-ode/" &gt;Matlab post&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Integrate this ordinary differential equation (ode):
&lt;/p&gt;

&lt;p&gt;
$$\frac{dy}{dt} = y(t)$$
&lt;/p&gt;

&lt;p&gt;
over the time span of 0 to 2. The initial condition is y(0) = 1.
&lt;/p&gt;

&lt;p&gt;
to solve this equation, you need to create a function of the form: dydt = f(y, t) and then use one of the odesolvers, e.g. odeint.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; numpy &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; np
&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.integrate &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; odeint
&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; plt

&lt;span style="color: #8b0000;"&gt;def&lt;/span&gt; &lt;span style="color: #8b2323;"&gt;fprime&lt;/span&gt;(y,t):
    &lt;span style="color: #8b0000;"&gt;return&lt;/span&gt; y

tspan = np.linspace(0, 2)
y0 = 1
ysol = odeint(fprime, y0, tspan)

plt.plot(tspan, ysol, label=&lt;span style="color: #228b22;"&gt;'numerical solution'&lt;/span&gt;)
plt.plot(tspan, np.exp(tspan), &lt;span style="color: #228b22;"&gt;'r--'&lt;/span&gt;, label=&lt;span style="color: #228b22;"&gt;'analytical solution'&lt;/span&gt;)
plt.xlabel(&lt;span style="color: #228b22;"&gt;'time'&lt;/span&gt;)
plt.ylabel(&lt;span style="color: #228b22;"&gt;'y(t)'&lt;/span&gt;)
plt.legend(loc=&lt;span style="color: #228b22;"&gt;'best'&lt;/span&gt;)
plt.savefig(&lt;span style="color: #228b22;"&gt;'images/simple-ode.png'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;img src="/img/./images/simple-ode.png"&gt;&lt;p&gt;

&lt;p&gt;
The numerical and analytical solutions agree.
&lt;/p&gt;

&lt;p&gt;
Now, suppose you want to know at what time is the solution equal to 3? There are several approaches to this, including setting up a solver, or using an event like approach to stop integration at y=3. A simple approach is to use reverse interpolation. We simply reverse the x and y vectors so that y is the independent variable, and we interpolate the corresponding x-value.

&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; numpy &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; np
&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.integrate &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; odeint
&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; plt

&lt;span style="color: #8b0000;"&gt;def&lt;/span&gt; &lt;span style="color: #8b2323;"&gt;fprime&lt;/span&gt;(y,t):
    &lt;span style="color: #8b0000;"&gt;return&lt;/span&gt; y

tspan = np.linspace(0, 2)
y0 = 1
ysol = odeint(fprime, y0, tspan)

&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.interpolate &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; interp1d

ip = interp1d(ysol[:,0], tspan) &lt;span style="color: #ff0000; font-weight: bold;"&gt;# reverse interpolation&lt;/span&gt;
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; &lt;span style="color: #228b22;"&gt;'y = 3 at x = {0}'&lt;/span&gt;.format(ip(3))
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
y = 3 at x = 1.09854780564
&lt;/pre&gt;
&lt;p&gt;Copyright (C) 2013 by John Kitchin. See the &lt;a href="/copying.html"&gt;License&lt;/a&gt; for information about copying.&lt;p&gt;&lt;p&gt;&lt;a href="/org/2013/02/26/Numerical-solution-to-a-simple-ode.org"&gt;org-mode source&lt;/a&gt;&lt;p&gt;]]></content:encoded>
    </item>
    <item>
      <title>Better interpolate than never</title>
      <link>https://kitchingroup.cheme.cmu.edu/blog/2013/02/02/Better-interpolate-than-never</link>
      <pubDate>Sat, 02 Feb 2013 09:00:00 EST</pubDate>
      <category><![CDATA[interpolation]]></category>
      <guid isPermaLink="false">n-Va67s9hkjCVJ3FzH-TbfzRbe8=</guid>
      <description>Better interpolate than never</description>
      <content:encoded><![CDATA[


&lt;p&gt;

&lt;a href="http://matlab.cheme.cmu.edu/2012/02/02/better-interpolate-than-never/" &gt;Matlab post&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
We often have some data that we have obtained in the lab, and we want to solve some problem using the data. For example, suppose we have this data that describes the value of f at time t.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; plt

t = [0.5, 1, 3, 6]
f = [0.6065,    0.3679,    0.0498,    0.0025]
plt.plot(t,f)
plt.xlabel(&lt;span style="color: #228b22;"&gt;'t'&lt;/span&gt;)
plt.ylabel(&lt;span style="color: #228b22;"&gt;'f(t)'&lt;/span&gt;)
plt.savefig(&lt;span style="color: #228b22;"&gt;'images/interpolate-1.png'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
&amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; [&amp;lt;matplotlib.lines.Line2D object at 0x04D18730&amp;gt;]
&amp;lt;matplotlib.text.Text object at 0x04BEE8B0&amp;gt;
&amp;lt;matplotlib.text.Text object at 0x04C03970&amp;gt;
&lt;/pre&gt;

&lt;p&gt;&lt;img src="/img/./images/interpolate-1.png"&gt;&lt;p&gt;

&lt;div id="outline-container-1" class="outline-2"&gt;
&lt;h2 id="sec-1"&gt;&lt;span class="section-number-2"&gt;1&lt;/span&gt; Estimate the value of f at t=2.&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-1"&gt;
&lt;p&gt;
This is a simple interpolation problem.
&lt;/p&gt;
&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.interpolate &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; interp1d

g = interp1d(t, f) &lt;span style="color: #ff0000; font-weight: bold;"&gt;# default is linear interpolation&lt;/span&gt;

&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; g(2)
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; g([2, 3, 4])
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
&amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; 0.20885
[ 0.20885     0.0498      0.03403333]
&lt;/pre&gt;

&lt;p&gt;
The function we sample above is actually f(t) = exp(-t). The linearly interpolated example is not too accurate.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; numpy &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; np
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; np.exp(-2)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
0.135335283237
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-2" class="outline-2"&gt;
&lt;h2 id="sec-2"&gt;&lt;span class="section-number-2"&gt;2&lt;/span&gt; improved interpolation?&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-2"&gt;
&lt;p&gt;

we can tell interp1d to use a different interpolation scheme such as cubic polynomial splines like this. For nonlinear functions, this may improve the accuracy of the interpolation, as it implicitly includes information about the curvature by fitting a cubic polynomial over neighboring points. 
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;g2 = interp1d(t, f, &lt;span style="color: #228b22;"&gt;'cubic'&lt;/span&gt;)
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; g2(2)
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; g2([2, 3, 4])
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
0.108481818182
[ 0.10848182  0.0498      0.08428727]
&lt;/pre&gt;

&lt;p&gt;
Interestingly, this is a different value than Matlab's cubic interpolation. Let us show the cubic spline fit.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;plt.figure()
plt.plot(t,f)
plt.xlabel(&lt;span style="color: #228b22;"&gt;'t'&lt;/span&gt;)
plt.ylabel(&lt;span style="color: #228b22;"&gt;'f(t)'&lt;/span&gt;)

x = np.linspace(0.5, 6)
fit = g2(x)
plt.plot(x, fit, label=&lt;span style="color: #228b22;"&gt;'fit'&lt;/span&gt;)
plt.savefig(&lt;span style="color: #228b22;"&gt;'images/interpolation-2.png'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
&amp;lt;matplotlib.figure.Figure object at 0x04EF2430&amp;gt;
[&amp;lt;matplotlib.lines.Line2D object at 0x04F20ED0&amp;gt;]
&amp;lt;matplotlib.text.Text object at 0x04EF2FF0&amp;gt;
&amp;lt;matplotlib.text.Text object at 0x04F060D0&amp;gt;
&amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; [&amp;lt;matplotlib.lines.Line2D object at 0x04F17570&amp;gt;]
&lt;/pre&gt;

&lt;p&gt;&lt;img src="/img/./images/interpolation-2.png"&gt;&lt;p&gt;

&lt;p&gt;
Wow. That is a weird looking fit. Very different from what Matlab &lt;a href="http://matlab.cheme.cmu.edu/wp-content/uploads/2012/02/interp_methods_02.png" &gt;produces&lt;/a&gt;. This is a good teaching moment not to rely blindly on interpolation! We will rely on the linear interpolation from here out which behaves predictably.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-3" class="outline-2"&gt;
&lt;h2 id="sec-3"&gt;&lt;span class="section-number-2"&gt;3&lt;/span&gt; The inverse question&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-3"&gt;
&lt;p&gt;
It is easy to interpolate a new value of f given a value of t. What if we want to know the time that f=0.2? We can approach this a few ways.
&lt;/p&gt;
&lt;/div&gt;

&lt;div id="outline-container-3-1" class="outline-3"&gt;
&lt;h3 id="sec-3-1"&gt;&lt;span class="section-number-3"&gt;3.1&lt;/span&gt; method 1&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-3-1"&gt;
&lt;p&gt;
We setup a function that we can use fsolve on. The function will be equal to zero at the time. The second function will look like 0 = 0.2 - f(t). The answer for 0.2=exp(-t) is t = 1.6094. Since we use interpolation here, we will get an approximate answer. 
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.optimize &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; fsolve

&lt;span style="color: #8b0000;"&gt;def&lt;/span&gt; &lt;span style="color: #8b2323;"&gt;func&lt;/span&gt;(t):
    &lt;span style="color: #8b0000;"&gt;return&lt;/span&gt; 0.2 - g(t)

initial_guess = 2
ans, = fsolve(func, initial_guess)
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; ans
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
&amp;gt;&amp;gt;&amp;gt; ... ... &amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; 2.0556428796
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-3-2" class="outline-3"&gt;
&lt;h3 id="sec-3-2"&gt;&lt;span class="section-number-3"&gt;3.2&lt;/span&gt; method 2: switch the interpolation order&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-3-2"&gt;
&lt;p&gt;
We can switch the order of the interpolation to solve this problem. An issue we have to address in this method is that the &amp;ldquo;x&amp;rdquo; values must be monotonically &lt;i&gt;increasing&lt;/i&gt;. It is somewhat subtle to reverse a list in python. I will use the cryptic syntax of [::-1] instead of the list.reverse() function or reversed() function. list.reverse() actually reverses the list &amp;ldquo;in place&amp;rdquo;, which changes the contents of the variable. That is not what I want. reversed() returns an iterator which is also not what I want. [::-1] is a fancy indexing trick that returns a reversed list.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;g3 = interp1d(f[::-1], t[::-1])

&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; g3(0.2)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
&amp;gt;&amp;gt;&amp;gt; 2.0556428796
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-4" class="outline-2"&gt;
&lt;h2 id="sec-4"&gt;&lt;span class="section-number-2"&gt;4&lt;/span&gt; A harder problem&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-4"&gt;
&lt;p&gt;
Suppose we want to know at what time is 1/f = 100? Now we have to decide what do we interpolate: f(t) or 1/f(t). Let us look at both ways and decide what is best. The answer to \(1/exp(-t) = 100\) is 4.6052
&lt;/p&gt;
&lt;/div&gt;

&lt;div id="outline-container-4-1" class="outline-3"&gt;
&lt;h3 id="sec-4-1"&gt;&lt;span class="section-number-3"&gt;4.1&lt;/span&gt; interpolate on f(t) then invert the interpolated number&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-4-1"&gt;
&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;def&lt;/span&gt; &lt;span style="color: #8b2323;"&gt;func&lt;/span&gt;(t):
    &lt;span style="color: #228b22;"&gt;'objective function. we do some error bounds because we cannot interpolate out of the range.'&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;if&lt;/span&gt; t &amp;lt; 0.5: t=0.5
    &lt;span style="color: #8b0000;"&gt;if&lt;/span&gt; t &amp;gt; 6: t = 6
    &lt;span style="color: #8b0000;"&gt;return&lt;/span&gt; 100 - 1.0 / g(t)   

initial_guess = 4.5
a1, = fsolve(func, initial_guess)
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; a1
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; &lt;span style="color: #228b22;"&gt;'The %error is {0:%}'&lt;/span&gt;.format((a1 - 4.6052)/4.6052)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
... ... ... ... &amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; 5.52431289641
The %error is 19.958154%
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-4-2" class="outline-3"&gt;
&lt;h3 id="sec-4-2"&gt;&lt;span class="section-number-3"&gt;4.2&lt;/span&gt; invert f(t) then interpolate on 1/f&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-4-2"&gt;
&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;ig = interp1d(t, 1.0 / np.array(f))

&lt;span style="color: #8b0000;"&gt;def&lt;/span&gt; &lt;span style="color: #8b2323;"&gt;ifunc&lt;/span&gt;(t):
    &lt;span style="color: #8b0000;"&gt;if&lt;/span&gt; t &amp;lt; 0.5: t=0.5
    &lt;span style="color: #8b0000;"&gt;if&lt;/span&gt; t &amp;gt; 6: t = 6
    &lt;span style="color: #8b0000;"&gt;return&lt;/span&gt; 100 - ig(t)   

initial_guess = 4.5
a2, = fsolve(ifunc, initial_guess)
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; a2
&lt;span style="color: #8b0000;"&gt;print&lt;/span&gt; &lt;span style="color: #228b22;"&gt;'The %error is {0:%}'&lt;/span&gt;.format((a2 - 4.6052)/4.6052)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
&amp;gt;&amp;gt;&amp;gt; ... ... ... ... &amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; &amp;gt;&amp;gt;&amp;gt; 3.6310782241
The %error is -21.152649%
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-5" class="outline-2"&gt;
&lt;h2 id="sec-5"&gt;&lt;span class="section-number-2"&gt;5&lt;/span&gt; Discussion&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-5"&gt;
&lt;p&gt;
In this case you get different errors, one overestimates and one underestimates the answer, and by a lot: &amp;plusmn; 20%. Let us look at what is happening.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;

&lt;pre class="src src-python"&gt;&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; plt
&lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; numpy &lt;span style="color: #8b0000;"&gt;as&lt;/span&gt; np
&lt;span style="color: #8b0000;"&gt;from&lt;/span&gt; scipy.interpolate &lt;span style="color: #8b0000;"&gt;import&lt;/span&gt; interp1d

t = [0.5, 1, 3, 6]
f = [0.6065,    0.3679,    0.0498,    0.0025]

x = np.linspace(0.5, 6)


g = interp1d(t, f) &lt;span style="color: #ff0000; font-weight: bold;"&gt;# default is linear interpolation&lt;/span&gt;
ig = interp1d(t, 1.0 / np.array(f))

plt.figure()
plt.plot(t, 1 / np.array(f), &lt;span style="color: #228b22;"&gt;'ko '&lt;/span&gt;, label=&lt;span style="color: #228b22;"&gt;'data'&lt;/span&gt;)
plt.plot(x, 1 / g(x), label=&lt;span style="color: #228b22;"&gt;'1/interpolated f(x)'&lt;/span&gt;)
plt.plot(x, ig(x), label=&lt;span style="color: #228b22;"&gt;'interpolate on 1/f(x)'&lt;/span&gt;)
plt.plot(x, 1 / np.exp(-x), &lt;span style="color: #228b22;"&gt;'k--'&lt;/span&gt;, label=&lt;span style="color: #228b22;"&gt;'1/exp(-x)'&lt;/span&gt;)
plt.xlabel(&lt;span style="color: #228b22;"&gt;'t'&lt;/span&gt;)
plt.ylabel(&lt;span style="color: #228b22;"&gt;'1/f(t)'&lt;/span&gt;)
plt.legend(loc=&lt;span style="color: #228b22;"&gt;'best'&lt;/span&gt;)
plt.savefig(&lt;span style="color: #228b22;"&gt;'images/interpolation-3.png'&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;img src="/img/./images/interpolation-3.png"&gt;&lt;p&gt;

&lt;p&gt;
You can see that the 1/interpolated f(x) underestimates the value, while interpolated (1/f(x)) overestimates the value. This is an example of where you clearly need more data in that range to make good estimates. Neither interpolation method is doing a great job. The trouble in reality is that you often do not know the real function to do this analysis. Here you can say the time is probably between 3.6 and 5.5 where 1/f(t) = 100, but you can not read much more than that into it. If you need a more precise answer, you need better data, or you need to use an approach other than interpolation. For example, you could fit an exponential function to the data and use that to estimate values at other times.
&lt;/p&gt;

&lt;p&gt;
So which is the best to interpolate? I think you should interpolate the quantity that is linear in the problem you want to solve, so in this case I think interpolating 1/f(x) is better. When you use an interpolated function in a nonlinear function, strange, unintuitive things can happen. That is why the blue curve looks odd. Between data points are linear segments in the original interpolation, but when you invert them, you cause the curvature to form.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Copyright (C) 2013 by John Kitchin. See the &lt;a href="/copying.html"&gt;License&lt;/a&gt; for information about copying.&lt;p&gt;&lt;p&gt;&lt;a href="/org/2013/02/02/Better-interpolate-than-never.org"&gt;org-mode source&lt;/a&gt;&lt;p&gt;]]></content:encoded>
    </item>
  </channel>
</rss>
