2

I have made a plot for the basic SIR model. I am satisfied with my plot, however, I would like to be able to have an interactive slider that tweaks my parameters beta and gamma. I would like both of them to range from 0 to 1 and for the user to be able to increment them by 0.01.

Can someone help me implement this in my code? Thank you for your time in advance.

Here is my code:

# # Solving SIR Model in Python (INTERACTIVE)

# \
# Importing packages:

# In[10]:


# Display in LaTeX style.
from sympy.interactive import printing
printing.init_printing(use_latex = True)

# For integration.
import scipy.integrate 

# For arrays (Python does not have native arrays).
import numpy as np

# For graphing.
import matplotlib.pyplot as plt 

# Prevents the pop-up graphs in a separate window.
get_ipython().run_line_magic('matplotlib', 'inline')

# Allows for an interactive widget bar.
from ipywidgets import interactive 


# \
# Defining differential equations:

# In[11]:


def SIR_model(y, t, beta, gamma):
    S, I, R = y
    
    dS_dt = -beta*S*I
    dI_dt = beta*S*I - gamma*I
    dR_dt = gamma*I
    
    return([dS_dt, dI_dt, dR_dt,])


# \
# Defining initial conditions:

# In[12]:


S0 = 0.95
I0 = 0.05
R0 = 0.0

beta = 0.35
gamma = 0.1


# \
# Defining time vector:

# In[13]:


# Graph from 0 to 100, include 10000 points.
t = np.linspace(0, 100, 10000) 


# \
# Defining solution:

# In[14]:


# Result
solution = scipy.integrate.odeint(SIR_model, [S0, I0, R0], t, args=(beta, gamma))
solution = np.array(solution)


# \
# Plotting the result:

# In[20]:


plt.figure(figsize=[8, 5])

plt.plot(t, solution[:, 0], label="S(t)")
plt.plot(t, solution[:, 1], label="I(t)")
plt.plot(t, solution[:, 2], label="R(t)")

plt.grid()
plt.legend()

plt.title("SIR Model")
plt.xlabel("Time")
plt.ylabel("Proportions of Populations")

# THIS DOES NOT WORK !!!
#interactive_plot = interactive(SIR_model, betta=(0.35,1,0.01), gamma=(0.1,1,0.01))
#interactive_plot

plt.show()

Here is the output.

enter image description here

1
  • In Jupyter, the easiest thing to do would be to use ipywidgets.interact() (see e.g. ipywidgets.readthedocs.io/en/latest/examples/…). Or you can switch from matplotlib to another visualisation libraries with more interactive capabilities, such as bokeh or holoviz. Commented Jul 6, 2020 at 15:11

1 Answer 1

1

You need to create a function which handles the inputs, integration AND plotting all in one go (sir_interactive_func), see below:


# For integration.
import scipy.integrate 

# For arrays (Python does not have native arrays).
import numpy as np

# For graphing.
import matplotlib.pyplot as plt 

# Prevents the pop-up graphs in a separate window.
get_ipython().run_line_magic('matplotlib', 'inline')

# Allows for an interactive widget bar.
from ipywidgets import interactive 

S0 = 0.95
I0 = 0.05
R0 = 0.0



def SIR_model(y, t, beta, gamma):

    S, I, R = y
    
    dS_dt = -beta*S*I
    dI_dt = beta*S*I - gamma*I
    dR_dt = gamma*I
    
    return([dS_dt, dI_dt, dR_dt,])
    
def sir_interactive_func(beta, gamma):
    
    # Graph from 0 to 100, include 10000 points.
    t = np.linspace(0, 100, 10000) 
    
    solution = scipy.integrate.odeint(SIR_model, [S0, I0, R0], t, args=(beta, gamma))
    solution = np.array(solution)

    plt.figure(figsize=[8, 5])

    plt.plot(t, solution[:, 0], label="S(t)")
    plt.plot(t, solution[:, 1], label="I(t)")
    plt.plot(t, solution[:, 2], label="R(t)")

    plt.grid()
    plt.legend()

    plt.title("SIR Model")
    plt.xlabel("Time")
    plt.ylabel("Proportions of Populations")
    

interactive_plot = interactive(sir_interactive_func, beta=(0.35,1,0.01), gamma=(0.1,1,0.01))
interactive_plot
Sign up to request clarification or add additional context in comments.

1 Comment

I have one question. How do I make beta and gamma start at 0.35 and 0.1 respectively, but still allow the slider to start at 0 ???

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.