Пример #1
0
def animate_interactive(data,
                        t=None,
                        dim_order=(0, 1, 2),
                        fps=10.0,
                        title=None,
                        xlabel='x',
                        ylabel='y',
                        font_size=24,
                        color_bar=0,
                        colorbar_label=None,
                        sloppy=True,
                        fancy=False,
                        range_min=None,
                        range_max=None,
                        extent=[-1, 1, -1, 1],
                        shade=False,
                        azdeg=0,
                        altdeg=65,
                        arrowsX=None,
                        arrowsY=None,
                        arrows_resX=10,
                        arrows_resY=10,
                        arrows_pivot='mid',
                        arrows_width=0.002,
                        arrows_scale=5,
                        arrows_color='black',
                        plot_arrows_grid=False,
                        movie_file=None,
                        bitrate=1800,
                        keep_images=False,
                        figsize=(8, 7),
                        dpi=300,
                        **kwimshow):
    """
    Assemble a 2D animation from a 3D array.

    call signature::

    animate_interactive(data, t=None, dim_order=(0, 1, 2),
                        fps=10.0, title=None, xlabel='x', ylabel='y',
                        font_size=24, color_bar=0, colorbar_label=None,
                        sloppy=True, fancy=False,
                        range_min=None, range_max=None, extent=[-1, 1, -1, 1],
                        shade=False, azdeg=0, altdeg=65,
                        arrowsX=None, arrowsY=None, arrows_resX=10, arrows_resY=10,
                        arrows_pivot='mid', arrows_width=0.002, arrows_scale=5,
                        arrows_color='black', plot_arrows_grid=False,
                        movie_file=None, bitrate=1800, keep_images=False,
                        figsize=(8, 7), dpi=300,
                        **kwimshow)

    Assemble a 2D animation from a 3D array. *data* has to be a 3D array of
    shape [nt, nx, ny] and who's time index has the same dimension as *t*.
    The time index of *data* as well as its x and y indices can be changed
    via *dim_order*.

    Keyword arguments:

    *dim_order*:
      Ordering of the dimensions in the data array (t, x, y).

    *fps*:
      Frames per second of the animation.

    *title*:
      Title of the plot.

    *xlabel*:
      Label of the x-axis.

    *ylabel*:
      Label of the y-axis.

    *font_size*:
      Font size of the title, x and y label.
      The size of the x- and y-ticks is 0.5*font_size and the colorbar ticks'
      font size is 0.5*font_size.

    *color_bar*: [ 0 | 1 ]
      Determines how the colorbar changes:
      (0 - no cahnge; 1 - adapt extreme values).

    *colorbar_label*:
      Label of the color bar.

    *sloppy*: [ True | False ]
      If True the update of the plot lags one frame behind. This speeds up the
      plotting.

    *fancy*: [ True | False ]
      Use fancy font style.

    *range_min*, *range_max*:
      Range of the colortable.

    *extent*: [ None | (left, right, bottom, top) ]
      Limits for the axes (domain).

    *shade*: [ False | True ]
      If True plot a shaded relief instead of the usual colormap.
      Note that with this option cmap has to be specified like
      cmap = plt.cm.hot instead of cmap = 'hot'. Shading cannot
      be used with the color_bar = 0 option.

    *azdeg*, *altdeg*:
      Azimuth and altitude of the light source for the shading.

    *arrowsX*:
      Data containing the x-component of the arrows.

    *arrowsY*:
      Data containing the y-component of the arrows.

    *arrows_resXY*:
      Plot every arrows_resXY arrow in x and y.

    *arrows_pivot*: [ 'tail' | 'middle' | 'tip' ]
      The part of the arrow that is used as pivot point.

    *arrows_width*:
      Width of the arrows.

    *arrows_scale*:
      Scaling of the arrows.

    *arrows_color*:
      Color of the arrows.

    *plot_arrows_grid*: [ False | True ]
      If 'True' the grid where the arrows are aligned to is shown.

    *movie_file*: [ None | string ]
      The movie file where the animation should be saved to.
      If 'None' no movie file is written. Requires 'ffmpeg' to be installed.

    *bitrate*:
      Bitrate of the movie file. Set to higher value for higher quality.

    *keep_images*: [ False | True ]
      If 'True' the images for the movie creation are not deleted.

    *figsize*:
      Size of the figure in inches.

    *dpi*:
      Dots per inch of the frame.

    **kwimshow:
      Remaining arguments are identical to those of pylab.imshow. Refer to that help.
    """

    try:
        import thread
    except:
        import _thread as thread

    # We need to define these variables as globals, as they are being used
    # by various functions.

    global time_step, time_slider, pause
    global fig, axes, image, colorbar, arrows, manager, n_times, movie_files
    global rgb, plot_arrows

    if title is None:
        title = ''

    def plot_frame():
        """
        Plot the current frame.
        """

        global time_step, axes, colorbar, arrows, manager, rgb

        # Define the plot title.
        if not movie_file is None:
            axes.set_title(title + r'$\quad$' +
                           r'$t={0:.4e}$'.format(t[time_step]),
                           fontsize=font_size)

        # Update the image data.
        if not shade:
            image.set_data(data[time_step, :, :])
        else:
            image.set_data(rgb[time_step, :, :, :])

        # Update the colorbar.
        if color_bar == 0:
            pass
        if color_bar == 1:
            colorbar.set_clim(vmin=data[time_step, :, :].min(),
                              vmax=data[time_step, :, :].max())
            colorbar.draw_all()

        # Update the arrows data.
        if plot_arrows:
            arrows.set_UVC(U=arrowsX[time_step, ::arrows_resX, ::arrows_resY],
                           V=arrowsY[time_step, ::arrows_resX, ::arrows_resY])

        if not sloppy or (not movie_file is None):
            manager.canvas.draw()

    def play(thread_name):
        """
        Play the movie.
        """

        import time
        global time_step, time_slider, pause, fig, axes, n_times, movie_files

        pause = False
        while (time_step < n_times) and (not pause):
            # Write the image files for the movie.
            if not movie_file is None:
                plot_frame()
                frame_name = '{0}{1:06}.png'.format(movie_file, time_step)
                fig.savefig(frame_name, dpi=dpi)
                movie_files.append(frame_name)
            else:
                time_start = time.clock()
                time_slider.set_val(t[time_step])
                # Wait for the next frame (fps).
                while (time.clock() - time_start < 1.0 / fps):
                    pass
            time_step += 1
        time_step -= 1

    def play_thread(event):
        """
        Call the play function as a separate thread (for GUI).
        """

        global pause

        if pause:
            try:
                thread.start_new_thread(play, ("play_thread", ))
            except:
                print("Error: unable to start play thread.")

    def pausing(event):
        global pause

        pause = True

    def reverse(event):
        global time_step, time_slider

        time_step -= 1
        if time_step < 0:
            time_step = 0
        # Plot the frame and update the time slider.
        time_slider.set_val(t[time_step])

    def forward(event):
        global time_step, time_slider

        time_step += 1
        if time_step > len(t) - 1:
            time_step = len(t) - 1
        # Plot the frame and update the time slider.
        time_slider.set_val(t[time_step])

    import numpy as np
    import pylab as plt

    pause = True
    plot_arrows = False

    # Check if the data has the right dimensions.
    if (data.ndim != 3 and data.ndim != 4):
        print("Error: data dimensions are invalid: {0} instead of 3.".format(
            data.ndim))
        return -1

    # Transpose the data according to dim_order.
    unordered_data = data
    data = np.transpose(unordered_data, dim_order)
    del (unordered_data)

    # Check if arrows should be plotted.
    if not (arrowsX is None) and not (arrowsY is None):
        if (isinstance(arrowsX, np.ndarray)
                and isinstance(arrowsY, np.ndarray)):
            if arrowsX.ndim == 3:
                # Transpose the data according to dim_order.
                unordered_data = arrowsX
                arrowsX = np.transpose(unordered_data, dim_order)
                del (unordered_data)
            if arrowsY.ndim == 3:
                # Transpose the data according to dim_order.
                unordered_data = arrowsY
                arrowsY = np.transpose(unordered_data, dim_order)
                unordered_data = []

                # Check if the dimensions of the arrow arrays match each other.
                if arrowsX.shape != arrowsY.shape:
                    print(
                        "Error: dimensions of arrowX do not match with dimensions of arrowY."
                    )
                    return -1
                else:
                    plot_arrows = True
        else:
            print("Warning: arrowsX and/or arrowsY are of invalid type.")

    # Check if time array has the right length.
    n_times = len(t)
    if n_times != data.shape[0]:
        print(
            "Error: length of time array does not match length of data array.")
        return -1
    if plot_arrows:
        if (n_times != arrowsX.shape[0]) or (n_times != arrowsY.shape[0]):
            print(
                "error: length of time array does not match length of arrows array."
            )
            return -1

    # Check if fps is positive.
    if fps < 0:
        print("Error: fps is not positive, fps = {0}.".format(fps))
        return -1

    # Determine the size of the data array.
    nX = data.shape[1]
    nY = data.shape[2]

    # Determine the minimum and maximum values of the data set.
    if not range_min:
        range_min = np.min(data)
    if not range_max:
        range_max = np.max(data)

    # Setup the plot.
    if fancy:
        plt.rc('text', usetex=True)
        plt.rc('font', family='arial')
    else:
        plt.rc('text', usetex=False)
        plt.rc('font', family='sans')
    if not movie_file is None:
        fig = plt.figure(figsize=figsize)
        axes = plt.axes([0.15, 0.1, .70, .85])
    else:
        fig = plt.figure(figsize=figsize)
        axes = plt.axes([0.1, 0.3, .80, .65])

    # Set up canvas of the plot.
    axes.set_title(title, fontsize=font_size)
    axes.set_xlabel(xlabel, fontsize=font_size)
    axes.set_ylabel(ylabel, fontsize=font_size)
    plt.xticks(fontsize=0.5 * font_size)
    plt.yticks(fontsize=0.5 * font_size)
    if shade:
        plane = np.zeros([nX, nY, 3])
    else:
        plane = np.zeros([nX, nY])

    # Apply shading.
    if shade:
        from matplotlib.colors import LightSource

        ls = LightSource(azdeg=azdeg, altdeg=altdeg)
        rgb = []
        # Shading can be only used with color_bar=1 or color_bar=2 at the moment.
        if color_bar == 0:
            color_bar = 1
        # Check if colormap is set, if not set it to 'copper'.
        if 'cmap' not in kwimshow.keys():
            kwimshow['cmap'] = plt.cm.copper
        for i in range(data.shape[0]):
            tmp = ls.shade(data[i, :, :], kwimshow['cmap'])
            rgb.append(tmp.tolist())
        rgb = np.array(rgb)
        del (tmp)

    # Calibrate the displayed colors for the data range.
    image = axes.imshow(plane,
                        vmin=range_min,
                        vmax=range_max,
                        origin='lower',
                        extent=extent,
                        **kwimshow)
    colorbar = fig.colorbar(image)
    colorbar.set_label(colorbar_label, fontsize=font_size, labelpad=10)

    # Change the font size of the colorbar's ytickslabels.
    cbytick_obj = plt.getp(colorbar.ax.axes, 'yticklabels')
    plt.setp(cbytick_obj, fontsize=0.5 * font_size)

    # Plot the arrows.
    if plot_arrows:
        # Prepare the mesh grid where the arrows will be drawn.
        arrow_grid = np.meshgrid(
            np.arange(
                extent[0], extent[1],
                float(extent[1] - extent[0]) * arrows_resX /
                (data.shape[2] - 1)),
            np.arange(
                extent[2], extent[3],
                float(extent[3] - extent[2]) * arrows_resY /
                (data.shape[1] - 1)))
        arrows = axes.quiver(arrow_grid[0],
                             arrow_grid[1],
                             arrowsX[0, ::arrows_resX, ::arrows_resY],
                             arrowsY[0, ::arrows_resX, ::arrows_resY],
                             units='width',
                             pivot=arrows_pivot,
                             width=arrows_width,
                             scale=arrows_scale,
                             color=arrows_color)
        # Plot the grid for the arrows.
        if plot_arrows_grid:
            axes.plot(arrow_grid[0], arrow_grid[1], 'k.')

    # For real-time image display.
    if (not sloppy) or (not movie_file is None):
        manager = plt.get_current_fig_manager()
        manager.show()

    time_step = 0
    if not movie_file is None:
        import os

        movie_files = []

        # Start the animation.
        play('no_thread')

        # Write the movie file.
        ffmpeg_command = "ffmpeg -r {0} -i {1}%6d.png -vcodec mpeg4 -b:v {2} -q:v 0 {3}.avi".format(
            fps, movie_file, bitrate, movie_file)
        os.system(ffmpeg_command)
        # Clean up the image files.
        if not keep_images:
            print("Cleaning up files.")
            for fname in movie_files:
                os.remove(fname)
    else:
        # Set up the gui.
        plt.ion()
        plt.subplots_adjust(bottom=0.2)

        #        axes_play = plt.axes([0.1, 0.05, 0.15, 0.05])
        #        button_play = plt.Button(axes_play, 'play', color='lightgoldenrodyellow',
        #                                 hovercolor='0.975')
        #        button_play.on_clicked(play_thread)

        #        axes_pause = plt.axes([0.3, 0.05, 0.15, 0.05])
        #        button_pause = plt.Button(axes_pause, 'pause', color='lightgoldenrodyellow',
        #                                  hovercolor='0.975')
        #        button_pause.on_clicked(pausing)

        #        axes_reverse = plt.axes([0.5, 0.05, 0.15, 0.05])
        axes_reverse = plt.axes([0.1, 0.05, 0.3, 0.05])
        button_reverse = plt.Button(axes_reverse,
                                    'reverse',
                                    color='lightgoldenrodyellow',
                                    hovercolor='0.975')
        button_reverse.on_clicked(reverse)

        #        axes_forward = plt.axes([0.7, 0.05, 0.15, 0.05])
        axes_forward = plt.axes([0.5, 0.05, 0.3, 0.05])
        button_forward = plt.Button(axes_forward,
                                    'forward',
                                    color='lightgoldenrodyellow',
                                    hovercolor='0.975')
        button_forward.on_clicked(forward)

        # Create the time slider.
        time_slider_axes = plt.axes([0.2, 0.12, 0.6, 0.03],
                                    facecolor='lightgoldenrodyellow')
        time_slider = plt.Slider(time_slider_axes,
                                 'time',
                                 t[0],
                                 t[-1],
                                 valinit=t[0])

        def update(val):
            global time_step
            # Find the closest time step to the slider time value.
            for i in range(len(t)):
                if t[i] < time_slider.val:
                    time_step = i
            if (time_step != len(t) - 1):
                if (t[time_step + 1] - time_slider.val) < (time_slider.val -
                                                           t[time_step]):
                    time_step += 1
            plot_frame()

        time_slider.on_changed(update)

        plt.show()

    print("done")

    #    return button_play, button_pause, button_reverse, button_forward
    return button_reverse, button_forward
Пример #2
0
def animate_interactive(data,
                        t=[],
                        dimOrder=(0, 1, 2),
                        fps=10.0,
                        title='',
                        xlabel='x',
                        ylabel='y',
                        fontsize=24,
                        cBar=0,
                        sloppy=True,
                        rangeMin=[],
                        rangeMax=[],
                        extent=[-1, 1, -1, 1],
                        shade=False,
                        azdeg=0,
                        altdeg=65,
                        arrowsX=np.array(0),
                        arrowsY=np.array(0),
                        arrowsRes=10,
                        arrowsPivot='mid',
                        arrowsWidth=0.002,
                        arrowsScale=5,
                        arrowsColor='black',
                        plotArrowsGrid=False,
                        movieFile='',
                        bitrate=1800,
                        keepImages=False,
                        figsize=(8, 7),
                        dpi=None,
                        **kwimshow):
    """
    Assemble a 2D animation from a 3D array.

    call signature::
    
      animate_interactive(data, t = [], dimOrder = (0,1,2),
                        fps = 10.0, title = '', xlabel = 'x', ylabel = 'y',
                        fontsize = 24, cBar = 0, sloppy = True,
                        rangeMin = [], rangeMax = [], extent = [-1,1,-1,1],
                        shade = False, azdeg = 0, altdeg = 65,
                        arrowsX = np.array(0), arrowsY = np.array(0), arrowsRes = 10,
                        arrowsPivot = 'mid', arrowsWidth = 0.002, arrowsScale = 5,
                        arrowsColor = 'black', plotArrowsGrid = False,
                        movieFile = '', bitrate = 1800, keepImages = False,
                        figsize = (8, 7), dpi = None,
                        **kwimshow)
    
    Assemble a 2D animation from a 3D array. *data* has to be a 3D array who's
    time index has the same dimension as *t*. The time index of *data* as well
    as its x and y indices can be changed via *dimOrder*.
    
    Keyword arguments:
    
      *dimOrder*: [ (i,j,k) ]
        Ordering of the dimensions in the data array (t,x,y).
        
     *fps*:
       Frames per second of the animation.
       
     *title*:
       Title of the plot.
       
     *xlabel*:
       Label of the x-axis.
       
     *ylabel*:
       Label of the y-axis.
       
     *fontsize*:
       Font size of the title, x and y label.
       The size of the x- and y-ticks is 0.7*fontsize and the colorbar ticks's
       font size is 0.5*fontsize.
       
     *cBar*: [ 0 | 1 | 2 ]
       Determines how the colorbar changes:
       (0 - no cahnge; 1 - keep extreme values constant; 2 - change extreme values).
     
     *sloppy*: [ True | False ]
       If True the update of the plot lags one frame behind. This speeds up the
       plotting.
     
     *rangeMin*, *rangeMax*:
       Range of the colortable.
       
     *extent*: [ None | scalars (left, right, bottom, top) ]
       Data limits for the axes. The default assigns zero-based row,
       column indices to the *x*, *y* centers of the pixels.
       
     *shade*: [ False | True ]
       If True plot a shaded relief plot instead of the usual colormap.
       Note that with this option cmap has to be specified like
       cmap = plt.cm.hot instead of cmap = 'hot'. Shading cannot
       be used with the cBar = 0 option.
     
     *azdeg*, *altdeg*:
       Azimuth and altitude of the light source for the shading.
       
     *arrowsX*:
       Data containing the x-component of the arrows.
       
     *arrowsy*:
       Data containing the y-component of the arrows.
       
     *arrowsRes*:
       Plot every arrowRes arrow.
       
     *arrowsPivot*: [ 'tail' | 'middle' | 'tip' ]
       The part of the arrow that is at the grid point; the arrow rotates
       about this point.
       
     *arrowsWidth*:
       Width of the arrows.
       
     *arrowsScale*:
       Scaling of the arrows.
       
     *arrowsColor*:
       Color of the arrows.
       
     *plotArrowsGrid*: [ False | True ]
       If 'True' the grid where the arrows are aligned to is shown.
     
     *movieFile*: [ None | string ]
       The movie file where the animation should be saved to.
       If 'None' no movie file is written. Requires 'mencoder' to be installed.
     
     *bitrate*:
       Bitrate of the movie file. Set to higher value for higher quality.
       
     *keepImages*: [ False | True ]
       If 'True' the images for the movie creation are not deleted.
     
     *figsize*:
       Size of the figure in inches.
      
     *dpi*:
       Dots per inch of the frame.
     
     **kwimshow:
       Remaining arguments are identical to those of pylab.imshow. Refer to that help.
    """

    global tStep, sliderTime, pause

    # plot the current frame
    def plotFrame():
        global tStep, sliderTime

        if movieFile:
            ax.set_title(title + r'$\quad$' + r'$t={0}$'.format(t[tStep]),
                         fontsize=fontsize)

        if shade == False:
            image.set_data(data[tStep, :, :])
        else:
            image.set_data(rgb[tStep, :, :, :])

        if (cBar == 0):
            pass
        if (cBar == 1):
            colorbar.set_clim(vmin=data[tStep, :, :].min(),
                              vmax=data[tStep, :, :].max())
        if (cBar == 2):
            colorbar.set_clim(vmin=data[tStep, :, :].min(),
                              vmax=data[tStep, :, :].max())
            colorbar.update_bruteforce(data[tStep, :, :])

        if plotArrows:
            arrows.set_UVC(U=arrowsX[tStep, ::arrowsRes, ::arrowsRes],
                           V=arrowsY[tStep, ::arrowsRes, ::arrowsRes])

        if (sloppy == False) or (movieFile):
            manager.canvas.draw()

    # play the movie
    def play(threadName):
        global tStep, sliderTime, pause

        pause = False
        while (tStep < nT) & (pause == False):
            # write the image files for the movie
            if movieFile:
                plotFrame()
                frameName = movieFile + '%06d.png' % tStep
                fig.savefig(frameName, dpi=dpi)
                movieFiles.append(frameName)
            else:
                start = time.clock()
                # time slider
                sliderTime.set_val(t[tStep])
                # wait for the next frame (fps)
                while (time.clock() - start < 1.0 / fps):
                    pass  # do nothing
            tStep += 1
        tStep -= 1

    # call the play function as a separate thread (for GUI)
    def play_thread(event):
        global pause

        if pause == True:
            try:
                thread.start_new_thread(play, ("playThread", ))
            except:
                print "Error: unable to start play thread"

    def pausing(event):
        global pause

        pause = True

    def reverse(event):
        global tStep, sliderTime

        tStep -= 1
        if tStep < 0:
            tStep = 0
        # plot the frame and update the time slider
        sliderTime.set_val(t[tStep])

    def forward(event):
        global tStep, sliderTime

        tStep += 1
        if tStep > len(t) - 1:
            tStep = len(t) - 1
        # plot the frame and update the time slider
        sliderTime.set_val(t[tStep])

    pause = True
    plotArrows = False

    # check if the data has the right dimensions
    if (len(data.shape) != 3 and len(data.shape) != 4):
        print 'error: data dimensions are invalid: {0} instead of 3'.format(
            len(data.shape))
        return -1

    # transpose the data according to dimOrder
    unOrdered = data
    data = np.transpose(unOrdered, dimOrder)
    unOrdered = []

    # check if arrows should be plotted
    if len(arrowsX.shape) == 3:
        # transpose the data according to dimOrder
        unOrdered = arrowsX
        arrowsX = np.transpose(unOrdered, dimOrder)
        unOrdered = []
        if len(arrowsY.shape) == 3:
            # transpose the data according to dimOrder
            unOrdered = arrowsY
            arrowsY = np.transpose(unOrdered, dimOrder)
            unOrdered = []

            # check if the dimensions of the arrow arrays match each other
            if ((len(arrowsX[:, 0, 0]) != len(arrowsY[:, 0, 0]))
                    or (len(arrowsX[0, :, 0]) != len(arrowsY[0, :, 0]))
                    or (len(arrowsX[0, 0, :]) != len(arrowsY[0, 0, :]))):
                print 'error: dimensions of arrowX do not match with dimensions of arrowY'
                return -1
            else:
                plotArrows = True

    # check if time array has the right length
    nT = len(t)
    if (nT != len(data[:, 0, 0])):
        print 'error: length of time array doesn\'t match length of data array'
        return -1
        if plotArrows:
            if (nT != len(arrowX[:, 0, 0]) or nT != len(arrowX[:, 0, 0])):
                print 'error: length of time array doesn\'t match length of arrows array'
                return -1

    # check if fps is positive
    if (fps < 0.0):
        print 'error: fps is not positive, fps = {0}'.format(fps)
        return -1

    # determine the size of the array
    nX = len(data[0, :, 0])
    nY = len(data[0, 0, :])

    # determine the minimum and maximum values of the data set
    if not (rangeMin):
        rangeMin = np.min(data)
    if not (rangeMax):
        rangeMax = np.max(data)

    # setup the plot
    if movieFile:
        width = figsize[0]
        height = figsize[1]
        plt.rc("figure.subplot", bottom=0.15)
        plt.rc("figure.subplot", top=0.95)
        plt.rc("figure.subplot", right=0.95)
        plt.rc("figure.subplot", left=0.15)
        fig = plt.figure(figsize=figsize)
        ax = plt.axes([0.1, 0.1, .90, .85])
    else:
        width = figsize[0]
        height = figsize[1]
        plt.rc("figure.subplot", bottom=0.05)
        plt.rc("figure.subplot", top=0.95)
        plt.rc("figure.subplot", right=0.95)
        plt.rc("figure.subplot", left=0.15)
        fig = plt.figure(figsize=figsize)
        ax = plt.axes([0.1, 0.25, .85, .70])

    ax.set_title(title, fontsize=fontsize)
    ax.set_xlabel(xlabel, fontsize=fontsize)
    ax.set_ylabel(ylabel, fontsize=fontsize)
    plt.xticks(fontsize=0.7 * fontsize)
    plt.yticks(fontsize=0.7 * fontsize)
    if shade:
        plane = np.zeros((nX, nY, 3))
    else:
        plane = np.zeros((nX, nY))

    # apply shading if True
    if shade:
        ls = LightSource(azdeg=azdeg, altdeg=altdeg)
        rgb = []
        # shading can be only used with cBar = 1 or cBar = 2 at the moment
        if cBar == 0:
            cBar = 1
        # check if colormap is set, if not set it to 'copper'
        if kwimshow.has_key('cmap') == False:
            kwimshow['cmap'] = plt.cm.copper
        for i in range(len(data[:, 0, 0])):
            tmp = ls.shade(data[i, :, :], kwimshow['cmap'])
            rgb.append(tmp.tolist())
        rgb = np.array(rgb)
        tmp = []

    # calibrate the displayed colors for the data range
    image = ax.imshow(plane,
                      vmin=rangeMin,
                      vmax=rangeMax,
                      origin='lower',
                      extent=extent,
                      **kwimshow)
    colorbar = fig.colorbar(image)
    # change the font size of the colorbar's ytickslabels
    cbytick_obj = plt.getp(colorbar.ax.axes, 'yticklabels')
    plt.setp(cbytick_obj, fontsize=0.5 * fontsize)

    # plot the arrows
    # TODO: add some more options
    if plotArrows:
        # prepare the mash grid where the arrows will be drawn
        arrowGridX, arrowGridY = np.meshgrid(
            np.arange(
                extent[0], extent[1],
                float(extent[1] - extent[0]) * arrowsRes / len(data[0, :, 0])),
            np.arange(
                extent[2], extent[3],
                float(extent[3] - extent[2]) * arrowsRes / len(data[0, 0, :])))
        arrows = ax.quiver(arrowGridX,
                           arrowGridY,
                           arrowsX[0, ::arrowsRes, ::arrowsRes],
                           arrowsY[0, ::arrowsRes, ::arrowsRes],
                           units='width',
                           pivot=arrowsPivot,
                           width=arrowsWidth,
                           scale=arrowsScale,
                           color=arrowsColor)
        # plot the grid for the arrows
        if plotArrowsGrid == True:
            ax.plot(arrowGridX, arrowGridY, 'k.')

    # for real-time image display
    if (sloppy == False) or (movieFile):
        manager = plt.get_current_fig_manager()
        manager.show()

    tStep = 0
    if movieFile:
        movieFiles = []
        # start the animation
        play('noThread')

        # write the movie file
        mencodeCommand = "mencoder 'mf://" + movieFile + "*.png' -mf type=png:fps=" + np.str(
            fps) + " -ovc lavc -lavcopts vcodec=mpeg4:vhq:vbitrate=" + np.str(
                bitrate) + " -ffourcc MP4S -oac copy -o " + movieFile + ".mpg"
        os.system(mencodeCommand)
        # clean up the image files
        if (keepImages == False):
            print 'cleaning up files'
            for fname in movieFiles:
                os.remove(fname)

    else:
        # set up the gui
        plt.ion()

        axPlay = plt.axes([0.1, 0.05, 0.15, 0.05],
                          axisbg='lightgoldenrodyellow')
        buttonPlay = plt.Button(axPlay,
                                'play',
                                color='lightgoldenrodyellow',
                                hovercolor='0.975')
        buttonPlay.on_clicked(play_thread)
        axPause = plt.axes([0.3, 0.05, 0.15, 0.05],
                           axisbg='lightgoldenrodyellow')
        buttonPause = plt.Button(axPause,
                                 'pause',
                                 color='lightgoldenrodyellow',
                                 hovercolor='0.975')
        buttonPause.on_clicked(pausing)

        axReverse = plt.axes([0.5, 0.05, 0.15, 0.05],
                             axisbg='lightgoldenrodyellow')
        buttonReverse = plt.Button(axReverse,
                                   'reverse',
                                   color='lightgoldenrodyellow',
                                   hovercolor='0.975')
        buttonReverse.on_clicked(reverse)
        axForward = plt.axes([0.7, 0.05, 0.15, 0.05],
                             axisbg='lightgoldenrodyellow')
        buttonForward = plt.Button(axForward,
                                   'forward',
                                   color='lightgoldenrodyellow',
                                   hovercolor='0.975')
        buttonForward.on_clicked(forward)

        # create the time slider
        fig.subplots_adjust(bottom=0.2)
        sliderTimeAxes = plt.axes([0.2, 0.12, 0.6, 0.03],
                                  axisbg='lightgoldenrodyellow')
        sliderTime = plt.Slider(sliderTimeAxes,
                                'time',
                                t[0],
                                t[-1],
                                valinit=0.0)

        def update(val):
            global tStep
            # find the closest time step to the slider time value
            for i in range(len(t)):
                if t[i] < sliderTime.val:
                    tStep = i
            if (tStep != len(t) - 1):
                if (t[tStep + 1] - sliderTime.val) < (sliderTime.val -
                                                      t[tStep]):
                    tStep += 1
            plotFrame()

        sliderTime.on_changed(update)

        plt.show()

    print 'done'