Note: This notebook works with IPython 4.2.0, matplotlib 1.5.1, and ipywidgets 5.1.3


In [ ]:
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
import polo
import demo

Let's generate some demonstration data from a set of PyClaw runs:


In [ ]:
data = demo.generate_data()
print data.head()

Here data is a Pandas DataFrame; each row corresponds to one output time from a PyClaw simulation. The simulations have been run with a variety of algorithms and grid sizes.

Let's examine the data from the 5th-order WENO and the 2nd-order TVD runs. We'll use different plots for each value of nx (the number of grid cells)


In [ ]:
facets = {'subplot' : 'nx',
          'line' : 'solver_type',
          'slider' : 'time'}

# Select only rows for WENO5 and TVD runs
tvd_weno5 = data[(data['weno_order']==5) | np.isnan(data['weno_order'])]
fig = plt.figure(figsize=(8,6))
polo.comparison_plot(tvd_weno5,fig,facets);

Play with the slider above to see the difference between the two method solutions at various times.

Multiple sliders

We can include sliders to adjust two or more parameters separately.


In [ ]:
facets = {'subplot' : None,
        'line' : 'solver_type',
        'slider' : ['time','nx']}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(tvd_weno5,fig,facets)

In [ ]:
facets = {'subplot' : None,
        'line' : None,
        'slider' : ['time','nx','solver_type']}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(tvd_weno5,fig,facets);

Restrict to a subset of the data

In the examples above, the facets dictionary values correspond to column headings in the dataframe. We can further filter by setting one of the facets dictionary values to a tuple, whose first value is the column heading and whose second value is a tuple containing all the values for the rows we want to include. So we can get just the solutions computed with the Classic algorithm, for example:


In [ ]:
facets = {'subplot' : 'nx',
          'line' : ('solver_type',('classic',)),
          'slider' : 'time'}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(data,fig,facets);

Mixing it up

Any property can be varied over subplots, line plots within a subplot, or via a slider. Here are some combinations for the current dataset.


In [ ]:
facets = {'subplot' : 'nx',
          'line' : 'time',
          'slider' : 'solver_type'}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(tvd_weno5,fig,facets);

In [ ]:
facets = {'subplot' : 'solver_type',
          'line' : 'time',
          'slider' : 'nx'}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(tvd_weno5,fig,facets);

In [ ]:
facets = {'subplot' : 'time',
          'line' : 'solver_type',
          'slider' : 'nx'}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(tvd_weno5,fig,facets);

In [ ]:
facets = {'subplot' : 'time',
          'line' : 'nx',
          'slider' : 'solver_type'}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(tvd_weno5,fig,facets);

In [ ]:
facets = {'subplot' : 'nx',
          'line' : 'time',
          'slider' : 'solver_type'}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(tvd_weno5,fig,facets);

Comparing over fewer dimensions

We can filter to get solutions only at time $t=0.5$:


In [ ]:
t05 = tvd_weno5[tvd_weno5['time']==0.5]
t05.head()

In [ ]:
facets = {'subplot' : 'nx',
          'line' : 'solver_type'}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(t05,fig,facets);

In [ ]:
facets = {'line' : 'solver_type',
          'slider' : 'nx'}

fig = plt.figure(figsize=(10,6))
polo.comparison_plot(t05,fig,facets);

In [ ]:
facets = {'subplot' : 'solver_type',
          'slider' : 'nx'}

fig = plt.figure(figsize=(10,6))

polo.comparison_plot(t05,fig,facets);

The same can be achieved via:


In [ ]:
facets = {'subplot' : 'solver_type',
          'line' : ('time',(0.5,)),
          'slider' : 'nx'}

fig = plt.figure(figsize=(10,6))

polo.comparison_plot(tvd_weno5,fig,facets);

Manipulating the data

What if we want to plot some function of the data, instead of the data itself? We just define the function we want; as a simple example let's subtract 1 from the solution values:


In [ ]:
def q_minus_one(row):
    r"""Subtract 1 from q."""
    sol = row.data[row.index[0]]
    xc = sol.state.grid.p_centers[0] + 0
    q = sol.state.q[0,:] - 1
    return xc, q

In [ ]:
facets = {'subplot' : 'nx',
          'line' : 'solver_type',
          'slider' : 'time'}

fig = plt.figure(figsize=(8,6))

polo.comparison_plot(tvd_weno5,fig,facets,data_fun = q_minus_one,ylim=(-1.1,0.1));

Plotting scalar functionals

Sometimes we are interested in a functional of the data, such as the total mass, the total energy, or the average of some quantity. This should work similarly, but is not implemented correctly yet.


In [ ]:
def total_mass(row):
    r"""Get data for 1D PyClaw results."""
    sol = row.data[row.index[0]]
    time = row['time']
    xc = sol.state.grid.p_centers[0] + 0
    q = sol.state.q[0,:]
    dx = sol.state.grid.delta[0]
    mass = np.sum(q)*dx
    return time, mass

In [ ]:
facets = {'subplot' : 'nx',
          'line' : 'solver_type',
          'slider' : 'time'}

fig = plt.figure(figsize=(8,6))

polo.comparison_plot(tvd_weno5,fig,facets,data_fun = total_mass);