2

I'm using the yt-Project library to visualize data and create plots. Now, I want to create a plot containing of two subplots. It seems this is not directly possible with yt and you have to use matplotlib for further customization (described here). Being not used to matplotlib (and python in general) I tried something like this:

slc = yt.SlicePlot(ds, 'x', 'density')
dens_plot = slc.plots['density']

fig = dens_plot.figure
ax = dens_plot.axes
#colorbar_axes = dens_plot.cax

new_ax2 = fig.add_subplot(212)

slc.save()

But instead of adding another subplot beneath the first one, it adds it in it. enter image description here

What I'd like to achieve would be another plot from a different data set with the same color bar and the same x and y axes right beneath the first one.

Thank you for your help.

asmeurer
  • 86,894
  • 26
  • 169
  • 240
rtime
  • 349
  • 6
  • 23
  • Thanks for using yt! If you run into further issues you'll get more yt developer's attention if you send a message to our mailing list. That said, I'll definitely keep an eye out here on StackOverflow for yt questions in the future. – ngoldbaum Oct 13 '15 at 05:40

1 Answers1

3

Right now the easiest way to do this is to use an AxesGrid, as in this yt cookbook example as well as this one.

Here's an example that plots the gas density at two times in a time series, using yt 3.2.1. The example data I'm using can be downloaded from http://yt-project.org/data.

import yt
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import AxesGrid

fns = ['enzo_tiny_cosmology/DD0005/DD0005', 'enzo_tiny_cosmology/DD0040/DD0040']

fig = plt.figure()

# See http://matplotlib.org/mpl_toolkits/axes_grid/api/axes_grid_api.html
# These choices of keyword arguments produce a four panel plot with a single
# shared narrow colorbar on the right hand side of the multipanel plot. Axes
# labels are drawn for all plots since we're slicing along different directions
# for each plot.
grid = AxesGrid(fig, (0.075,0.075,0.85,0.85),
                nrows_ncols = (2, 1),
                axes_pad = 0.05,
                label_mode = "L",
                share_all = True,
                cbar_location="right",
                cbar_mode="single",
                cbar_size="3%",
                cbar_pad="0%")

for i, fn in enumerate(fns):
    # Load the data and create a single plot
    ds = yt.load(fn) # load data

    # Make a ProjectionPlot with a width of 34 comoving megaparsecs
    p = yt.ProjectionPlot(ds, 'z', 'density', width=(34, 'Mpccm'))

    # Ensure the colorbar limits match for all plots
    p.set_zlim('density', 1e-4, 1e-2)

    # This forces the ProjectionPlot to redraw itself on the AxesGrid axes.
    plot = p.plots['density']
    plot.figure = fig
    plot.axes = grid[i].axes
    plot.cax = grid.cbar_axes[i]

    # Finally, this actually redraws the plot.
    p._setup_plots()

plt.savefig('multiplot_1x2_time_series.png', bbox_inches='tight')

yt multiplot

You can do it your way too (using fig.add_subplots instead of AxesGrid), but you'll need to manually position the axes and also resize the figure.

Finally, if you want the figure to be smaller, you can control the size of the figure by passing a figure size in inches when you create the figure via plt.figure(). If you do that, you might want to adjust the font size as well by calling p.set_font_size() on the ProjectionPlot.

ngoldbaum
  • 5,430
  • 3
  • 28
  • 35
  • okay, this works just fine, BUT now I encountered a different problem. I'm using yt to visualize a eulerian grid code simulation with adaptive mesh refinement. What I wanted to show in those plots was the grid structure at a specific time. I discovred yt mainly for its .annotate_grid() function, which worked pretty convient in a code like `yt.SlicePlot(ds, 'x', "density").annotate_grids().save()`. In your solution however, `p = yt.ProjectionPlot(ds, 'z', 'density').annotate_grids()` doesn't have any effect on the plot. Any ideas? – rtime Oct 14 '15 at 13:00
  • I will try to look at this today. – ngoldbaum Oct 14 '15 at 15:31