<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 <img src="img/csdms_logo.jpg">
Visualization with ipywidgets
Let's visualize the evolution of the 2D temperature field as heat diffuses across the plate. We can do this interactively with the ipywidgets package.
Note
Step1:  Define a function that runs the Diffusion model through its BMI for a fixed number of time steps. Store the temperture field from each time step in a list. Return the list.
Step2:  Run the model for awhile.
Step3:  Define a function to visualize the temperature field at a time step (defined by an index into the list of temperature fields).
Step4:  Make an interactive plot of temperature over time.
Step5:  Update the model interactively
Define a function to plot a 2D array of temperatures.
Step6:  We're going to use this a little later to interactively run and plot our model.
Create an object that runs the BmiHeat model until a given time and then plots the temperature field at that time. Notice that this would work with any BMI model - you would just have to change the name of the variable to plot. Since our model cannot run backward in time, we cache the temperature at each time step.
Step7:  Instantiate the heat model and initialize it.
Step8:  Set the initial temperature.
Step9:  Run the model interactively over time. Note that as you move the slider, the model runs to the updated time.
<ASSISTANT_TASK:>
Python Code:
%matplotlib auto
import matplotlib.pyplot as plt
from ipywidgets import interact
from bmi_live.bmi_diffusion import BmiDiffusion
Explanation: <img src="img/csdms_logo.jpg">
Visualization with ipywidgets
Let's visualize the evolution of the 2D temperature field as heat diffuses across the plate. We can do this interactively with the ipywidgets package.
Note: Depending on the current state of your Python installation, you may have to install the ipywidgets package, have notebook&gt;=4.2.0, and enable widgets.
bash
$ pip install ipywidgets
$ jupyter nbextension enable --py --sys-prefix widgetsnbextension
Start with the necessary imports.
End of explanation
def run_model(n_steps=10):
    model = BmiDiffusion()
    model.initialize('../data/diffusion.yaml')
    grid_shape = model.get_grid_shape(0)
    
    initial_temp = model.get_value('plate_surface__temperature')
    initial_temp[20] = 100.
    model.set_value('plate_surface__temperature', initial_temp)
    
    temp = [initial_temp.reshape(grid_shape)]
    for _ in range(n_steps):
        model.update()
        new_temp = model.get_value('plate_surface__temperature')
        temp.append(new_temp.reshape(grid_shape))
    
    model.finalize()
    return temp
Explanation: Define a function that runs the Diffusion model through its BMI for a fixed number of time steps. Store the temperture field from each time step in a list. Return the list.
End of explanation
temperature = run_model(50)
Explanation: Run the model for awhile.
End of explanation
xmin, xmax = 0., temperature[0].shape[1]
ymin, ymax = 0., temperature[0].shape[0]
im = plt.imshow(temperature[0], vmax=100, extent=[xmin, xmax, ymin, ymax], origin='upper', cmap='gist_stern')
plt.title('Plate Temperature')
plt.colorbar().ax.set_ylabel('Temperature (K)')
def plot_temperature(time_index=0):
    im.set_data(temperature[time_index])
Explanation: Define a function to visualize the temperature field at a time step (defined by an index into the list of temperature fields).
End of explanation
interact(plot_temperature, time_index=(0, 50, 1))
Explanation: Make an interactive plot of temperature over time.
End of explanation
def plot_temperature(temperature):
    plt.clf()
    xmin, xmax = 0., temperature.shape[1]
    ymin, ymax = 0., temperature.shape[0]
    plt.imshow(temperature, vmin=0., vmax=10., extent=[xmin, xmax, ymin, ymax], origin='upper', cmap='Reds')
    plt.title('Plate Temperature')
    # plt.colorbar().ax.set_ylabel('Temperature (K)')
Explanation: Update the model interactively
Define a function to plot a 2D array of temperatures.
End of explanation
class HeatRunner(object):
    def __init__(self, heat):
        self._heat = heat
        self._cache = []
    def run_and_plot(self, time_index):
        for _ in range(len(self._cache), time_index):
            self._heat.update()
            self._cache.append(
                heat.get_value('plate_surface__temperature').reshape(self._heat.get_grid_shape(0)))
        plot_temperature(self._cache[time_index - 1])
Explanation: We're going to use this a little later to interactively run and plot our model.
Create an object that runs the BmiHeat model until a given time and then plots the temperature field at that time. Notice that this would work with any BMI model - you would just have to change the name of the variable to plot. Since our model cannot run backward in time, we cache the temperature at each time step.
End of explanation
heat = BmiDiffusion()
heat.initialize('../data/diffusion.yaml')
Explanation: Instantiate the heat model and initialize it.
End of explanation
init_temperature = heat.get_value('plate_surface__temperature')
init_temperature.shape = heat.get_grid_shape(0)
init_temperature[2, 2] = 100.
heat.set_value('plate_surface__temperature', init_temperature)
Explanation: Set the initial temperature.
End of explanation
runner = HeatRunner(heat)
interact(runner.run_and_plot, time_index=(0, 100, 1))
current_temperature = heat.get_value('plate_surface__temperature')
current_temperature.shape = heat.get_grid_shape(0)
current_temperature[5, 7] = 100.
heat.set_value('plate_surface__temperature', current_temperature)
Explanation: Run the model interactively over time. Note that as you move the slider, the model runs to the updated time.
End of explanation
<END_TASK>