Beispiel #1
0
def hovmoller(lon, tm, z, zo=None, zz=None, title=None, label=None,
              labels=dict(), crange=None, cmap=cm.GMT_no_green,
              orientation='landscape', show=False, save='', ftype='png',
              adjustprops=None, bottom=None, right=None, loc=[], std=None,
              xunits='deg', draft=False, hookx=None, hooky=None):
    """Hovmoller plots.

    PARAMETERS
        lon (array like) :
            Longitude axis.
        tm (array like) :
            Time axis.
        z (array like) :
            Filled contour variable.
        zo (array like) :
            Overlapping contour variable (e.g. relative significance of
            wavelet analysis) to be ploted with a thick solid black line.
        zz (array like) :
            Another overlapping contour variagle (e.g. original data) to be
            ploted with a thin solid white line.
        title (string, array like, optional) :
            Sets the contour plot title. If array like, each element of
            the array becomes the title for plot.
        label (string, array like, optional) :
            Sets the label for each plot. If array like, each element
            of the array becomes the label for each plot.
        labels (dictionary, optional) :
            Sets the labels for the plot axis.
        units (string, array like, optional) :
            Determines the units for all the contours together or
            sepparatelly.
        crange (array like, optional) :
            Sets the color range of the maps. If not given then the
            range is calculated from the input data.
        cmap (colormap, optional) :
            Sets the colormap to be used in the plots. The default is
            the Generic Mapping Tools (GMT) no green.
        orientation (string, optional) :
            Sets the orientation of the figure. Allowed options are
            'landscape' (default), 'portrait', 'squared'.
        show (boolean, optional) :
            If set to true the the resulting maps are explicitly shown
            on screen.
        save (string, optional) :
            The path in which the resulting plots are to be saved. If
            not set, then no images will be saved.
        ftype (string, optional) :
            The image file type. Most backends support png, pdf, ps,
            eps and svg.
        adjustprops (dict, optional) :
            Dictionary containing the subplot parameters.
        bottom (string, optional) :
            If set to ether 'std' or 'avg' plots respectively the
            standard deviation or mean of the signal at the bottom.
        loc (list, optional) :
            Lists the longitude of locations to be marked in plot.
        xunit (string, optional) :
            Determines the x-axis unit. Valid options are either 'deg'
            for degrees (default) or 'km' for kilometers.
        draft (boolean, optional) :
            If set to true, then reduces the size of the colorbar to
            approximatelly two colors to save time. Default is false.
        hookx, hooky (function, optional) :
            Executes a hook function after the plot in the x and y
            axes, respectivelly.

    OUTPUT
        Hovmoller contour plots plots either on screen and or on file
        according to the specified parameters.

    RETURNS
        Nothing.

    """
    t1 = time()
    __init__()

    # Setting undefined label strings.
    if 'units' not in labels.keys():
        labels['units'] = ''
    if 'Year' not in labels.keys():
        labels['Year'] = 'Year'
    if 'std' not in labels.keys():
        labels['std'] = 'Std'
    if 'avg' not in labels.keys():
            labels['avg'] = 'Avg'

    # Transforms input arrays in numpy arrays and numpy masked arrays.
    lon = numpy.asarray(lon)
    tm = numpy.asarray(tm)
    if type(z).__name__ != 'MaskedArray':
        z = numpy.ma.asarray(z)
        z.mask = numpy.isnan(z)
    else:
        z.mask = z.mask | numpy.isnan(z.data)

    # Determines the number of dimensions of the variable to be plotted and
    # the sizes of each dimension.
    dim = len(z.shape)
    if dim == 3:
        c, b, a = z.shape
    elif dim == 2:
        b, a = z.shape
        c = 1
        z = z.reshape(c, b, a)
    else:
        raise Warning, ('Hovmoller plots require either bi-dimensional or tri-'
                        'dimensional data.')
    if lon.size != a:
        raise Warning, 'Longitude and data lengths do not match.'
    if tm.size != b:
        raise Warning, 'Time and data lengths do not match.'

    if type(zo).__name__ != 'NoneType':
        dimo = len(zo.shape)
        if dimo == 2:
            co, ao = zo.shape
            bo = b
            zo = zo * numpy.ones([bo, co, ao])
        if (co != c) | (ao != a):
                raise Warning ('Overlapping array dimensions do not match')
        overlap = True
    else:
        overlap = False
    if type(zz).__name__ != 'NoneType':
        dimz = len(zz.shape)
        if dimz == 2:
            bz, az = zz.shape
            cz = 0
        elif dimz == 3:
            cz, bz, az = zz.shape
        else:
            cz = bz = az = 0
        if (bz != b) | (az != a):
                raise Warning ('Overlapping array dimensions do not match')
        zero = True
    else:
        zero = False

    # Verifies if title, label, unit and std parameters have the same number
    # of items as the number of plots to be drawn.
    if type(title).__name__ == 'str':
        title = [title] * c
    elif type(title).__name__ in ['list', 'tuple', 'ndarray']:
        C = len(title)
        if c > C:
            title = list(title) * int(numpy.ceil(float(c) / C))
    if type(label).__name__ == 'str':
        label = [label] * c
    elif type(label).__name__ in ['list', 'tuple', 'ndarray']:
        C = len(label)
        if c > C:
            label = list(label) * int(numpy.ceil(float(c) / C))

    # If the edges contain only NaN's, then slice them out.
    sel = pylab.find(~numpy.isnan(z.data).all(axis=0).all(axis=0))
    if len(sel) != a:
        a = len(sel)
        if a == 0:
            return
        lon = lon[sel[0]:sel[-1]]
        z = z[:, :, sel[0]:sel[-1]]
        if overlap:
            zo = zo[:, :, sel[0]:sel[-1]]
        if zero:
            if dimz == 2:
                zz = zz[:, sel[0]:sel[-1]]
            elif dimz == 3:
                zz = zz[:, :, sel[0]:sel[-1]]

    # Setting the color ranges
    bbox = dict(edgecolor='w', facecolor='w', alpha=0.9)
    if crange == None:
        cmajor, cminor, crange, cticks, extend = common.step(z,
            returnrange=True)
    else:
        crange = numpy.asarray(crange)
        cminor = numpy.diff(crange).mean()
        if crange.size > 11:
            cmajor = 2 * cminor
        if len(crange) < 15 :
            cticks = crange[::2]
        else:
            cticks = crange[::5]

        xmin, xmax = z.min(), z.max()
        rmin, rmax = crange.min(), crange.max()
        if (xmin < rmin) & (xmax > rmax):
            extend = 'both'
        elif (xmin < rmin) & (xmax <= rmax):
            extend = 'min'
        elif (xmin >= rmin) & (xmax > rmax):
            extend = 'max'
        elif (xmin >= rmin) & (xmax <= rmax):
            extend = 'neither'
        else:
            raise Warning, 'Unable to determine extend'
    if draft:
        crange = [min(crange), crange[len(crange) / 2], max(crange)]

    # Turning interactive mode on or off according to show parameter.
    if show == False:
        pylab.ioff()
    elif show == True:
        pylab.ion()
    else:
        raise Warning, 'Invalid show option.'

    # Sets the figure properties according to the orientation parameter and to
    # the data dimensions including the subplot number of rows and columns.
    if orientation == 'landscape':
        #figprops = dict(figsize=(7.33, 5.33), dpi=96)
        plcols = c
        plrows = 1
    elif orientation == 'portrait':
        #figprops = dict(figsize=(5.33, 7.33), dpi=96)
        plcols = 1
        plrows = c
    elif orientation == 'squared':
        #figprops = dict(figsize=(5.33, 5.33), dpi=96)
        plrows = plcols = numpy.ceil(c ** 0.5)
    else:
        raise Warning, 'Orientation \'%s\' not allowed.' % (orientation, )
    if adjustprops == None:
        adjustprops = dict(left=0.1, bottom=0.15, right=0.99, top=0.9,
                           wspace=0.05, hspace=0.02)
    
    fig = graphics.figure(ap=adjustprops, orientation=orientation)

    # Some figure parameters definitions and initializations
    if bottom:
        bottommin, bottommax = [0, -65535]
        baxes = []
    if right:
        rightmin, rightmax = [0, -65535]
        grey = [0.66, 0.66, 0.66]
        lfmt = ['-', '-', '-', '-']
        lclr = ['k', 'k', grey, grey]
        lwth = [2., 1., 2., 1.]
        c += 1 # Adds one more sub-plot for size calculations only.

    # Subplot width and height parameters
    w = ((adjustprops['right'] - adjustprops['left']) / c -
        adjustprops['hspace'])
    if bottom:
        y = 0.25 + adjustprops['bottom'] - adjustprops['wspace']
    else:
        y = adjustprops['bottom']
    if bottom:
        h = 0.75 - adjustprops['bottom']
    else:
        h = adjustprops['top'] - y + adjustprops['wspace']

    if right:
        c -= 1 # Adjusts to original number of Hovmoller sub-plots.

    for k in range(c):
        x = (w + adjustprops['hspace']) * k + adjustprops['left']

        if k == 0:
            ax = pylab.axes([x, y, w, h])
            bx = ax
            if right:
                xx = ((w + adjustprops['hspace']) * c + adjustprops['left'])
                rx = pylab.axes([xx, y, w, h], sharey=ax)
                pylab.setp(rx.get_yticklabels(), visible=False)
                pylab.axes(bx)
        else:
            bx = pylab.axes([x, y, w, h], sharex=ax, sharey=ax)

        if zero:
            if dimz == 2:
                oz = zz
            elif dimz == 3:
                oz = zz[k, :, :]
            pylab.contour(lon, tm, oz, [-1e10, 0, 1e10],
                colors=[[0.9, 0.9, 0.9]], linestyles='-', linewidths=0.5,
                alpha=0.9)

        if overlap:
            if dimo == 2:
                o = (z[k, :, :].data >= zo[:, k, :])
            elif dimo == 3:
                o = (z[k, :, :].data >= zo[k, :, :])
            pylab.contour(lon, tm, o, [0, 1],
                colors='k', linestyles='-', linewidths=1.)

        # Plots the contour. Uses assigned data for power hovmollers.
        pylab.contourf(lon, tm, z[k, :, :].data, crange, cmap=cmap,
            extend=extend)

        # Running x and y hooks on current axis.
        try:
            hookx(bx)
        except:
            pass
        try:
            hooky(bx)
        except:
            pass

        if right:
            if right == 'std':
                rz = nanstd(z[k, :, :].data, axis=1)
            elif right == 'avg':
                rz = nanmean(z[k, :, :].data, axis=1)
            rx.plot(rz, tm, lfmt[k], color=lclr[k], linewidth=lwth[k])

            # Running y hook on right axis.
            try:
                hooky(rx)
            except:
                pass

            rightmin = min([numpy.nanmin(rz), rightmin])
            rightmax = max([numpy.nanmax(rz), rightmax])

        for i in loc:
            pylab.plot([i, i], [tm.min(), tm.max()], 'D', markersize=14,
                color='w', alpha=1)

        if bottom:
            yb, hb = adjustprops['bottom'], 0.175
            if k == 0:
                cx = pylab.axes([x, yb, w, hb], sharex=ax)
                dx = cx
            else:
                dx = pylab.axes([x, yb, w, hb], sharex=ax, sharey=cx)
            baxes.append(dx)
            if bottom == 'avg':
                bz = nanmean(z[k, :, :].data, axis=0)
            elif bottom == 'std':
                bz = nanstd(z[k, :, :].data, axis=0)
            pylab.plot(lon, bz, 'k-')
            
            # Running x hook on bottom axis.
            try:
                hookx(dx)
            except:
                pass

            bottommin = min([numpy.nanmin(bz), bottommin])
            bottommax = max([numpy.nanmax(bz), bottommax])
            #
            pylab.setp(bx.get_xticklabels(), visible=False)
            if k > 0:
                pylab.setp(dx.get_yticklabels(), visible=False)

        if k == 0:
            if orientation == 'landscape':
                corientation = 'horizontal'
                cax = pylab.axes([adjustprops['left'] + 0.15, 0.05,
                    adjustprops['right'] - adjustprops['left'] - 0.3, 0.03])
                ci, cj, ha, va = 1.05, 0.5, 'left', 'center'
            elif orientation == 'portrait':
                corientation = 'vertical'
                cax = pylab.axes([adjustprops['right'] + 0.02, y + 0.05, 
                    0.03, h - 0.1])
                ci, cj, ha, va = 0.5, -0.05, 'center', 'baseline'
            pylab.colorbar(cax=cax, ax=ax, orientation=corientation,
                extend=extend, ticks=cticks)
            if labels['units']:
                cax.text(ci, cj, r'$\left[%s\right]$' % (labels['units']),
                         ha=ha, va=va, transform=cax.transAxes)
        else:
            pylab.setp(bx.get_yticklabels(), visible=False)

        if title:
            bx.set_title('%s' % (title[k]), va='baseline', fontsize='medium')
        if label:
            bx.text(0.07, 0.97, '%s' % (label[k]), ha='left', va='top',
                transform=bx.transAxes, bbox=bbox)

    # Formatting the plot axis.
    if bottom:
        ystep, ystep1 = common.step([bottommin, bottommax], 1.5)
        bottommax = pylab.ceil(bottommax / ystep) * ystep

        for dx in baxes:
            for i in loc:
                dx.plot([i, i], [bottommin, bottommax], 'D', markersize=10,
                    color='w', alpha=1)

        cx.set_ylim([bottommin, bottommax])
        ymajor = pylab.matplotlib.ticker.MultipleLocator(ystep)
        yminor = pylab.matplotlib.ticker.MultipleLocator(ystep1)
        cx.yaxis.set_major_locator(ymajor)
        cx.yaxis.set_minor_locator(yminor)
        if labels['units']:
            cx.set_ylabel(r'\textbf{%s} $\left[%s\right]$' % (labels[bottom],
                labels['units']))
        else:
            cx.set_ylabel(r'\textbf{%s}' % (labels[bottom]))
        if xunits == 'km':
            cx.set_xlabel(r'\textbf{%s}' % (xunits))
    else:
        if xunits == 'km':
            ax.set_xlabel(r'\textbf{%s}' % (xunits))
    if right:
        xstep, xstep1 = common.step([rightmin, rightmax], 1.5)
        rightmax = pylab.ceil(rightmax / xstep) * xstep

        rx.set_xlim([rightmin, rightmax])
        xmajor = pylab.matplotlib.ticker.MultipleLocator(xstep)
        xminor = pylab.matplotlib.ticker.MultipleLocator(xstep1)
        rx.xaxis.set_major_locator(xmajor)
        rx.xaxis.set_minor_locator(xminor)
        if labels['units']:
            rx.set_title(r'%s $\left[%s\right]$' % (labels[right],
                labels['units']))
        else:
            rx.set_title(r'%s' % (labels[right]))

    ax.set_xlim([lon.min(), lon.max()])
    ax.set_ylim([tm.min(),  tm.max()])
    if xunits == 'deg':
        xstep, xstep1 = common.step(lon, 2)
    elif xunits == 'km':
        xstep, xstep1 = common.step(lon, 5)
    xmajor = pylab.matplotlib.ticker.MultipleLocator(xstep)
    xminor = pylab.matplotlib.ticker.MultipleLocator(xstep1)
    ax.xaxis.set_major_locator(xmajor)
    ax.xaxis.set_minor_locator(xminor)
    graphics.timeformat(ax, dt=tm[-1]-tm[0], axis='y')
    if xunits == 'deg':
        ax.set_xticklabels([common.num2latlon(i, 0, mode='each', x180=False,
            dtype='label')[1] for i in ax.get_xticks()])
    ax.set_ylabel(r'\textbf{%s}' % (labels['Year']))

    # Drawing and saving the figure if appropriate.
    pylab.draw()
    if save:
        pylab.savefig('%s.%s' % (save, ftype), dpi=150)
    if show == False:
        pylab.close(fig)
Beispiel #2
0
def map(lon, lat, z, z2=None, tm=None, projection='cyl', save='', ftype='png',
        crange=None, crange2=None, cmap=cm.GMT_no_green, show=False,
        shiftgrd=0., orientation='landscape', title='', label='', units='',
        subplot=None, adjustprops=None, loc=[], xlim=None, ylim=None,
        xstep=None, ystep=None, etopo=False, profile=True, hook=None, 
        **kwargs):
    """Generates maps.

    The maps can be either saved as image files or simply showed on
    screen.

    PARAMETERS
        lon, lat (array like) :
            Longitude and latitude arrays.
        z (array like) :
            Variable data array. For bi-dimensional MxN arrays, then a
            single map is plotted where M and N should have the same
            lengths as the latitude and the longitude respectively.

            For tri-dimensional TxMxN arrays, eather a sequence of maps
            is generated if T has the same length as tm or, in case tm
            is not set, T maps are plotted on the save figure.
        z2 (array like, optional) :
            Second variable to be plotted using simple line contours.
        t (array like, optional) :
            Time array. It should contain values in matplotlib date
            format (i.e. number of days since 0001-01-01 UTC).
        projection (text, optional) :
            Sets the map projection. Implemented projections are:
                cyl -- Equidistant cylindrical
                ortho -- Orthographic
                robin -- Robinson
                moll -- Mollweide
                eqdc -- Equidistant conic
                poly -- Polyconic
                omerc -- Oblique mercator
            Default is the equidistant cylindrical projection (cyl).
        save (string, optional) :
            The path in which the resulting plots are to be saved. If
            not set, then no images will be saved.
        ftype (string, optional) :
            The image file type. Most backends support png, pdf, ps,
            eps and svg.
        crange (array like, optional) :
            Sets the color range of the maps. If not given then the
            range is calculated from the input data.
        crange2 (array like, optional) :
            Sets the contour line interval.
        cmap (colormap, optional) :
            Sets the colormap to be used in the plots. The default is
            the Generic Mapping Tools (GMT) no green.
        show (boolean, optional) :
            If set to true the the resulting maps are explicitly shown
            on screen.
        shiftgrd (float, optional) :
            Shifts the longitude and variable data arrays east or west.
            Its value determines the starting longitude for the shifted
            grid.
            TODO: update functionality
        orientation (string, optional) :
            Sets the orientation of the figure. Allowed options are
            'landscape' (default), 'portrait', 'squared'.
        title (string, array like, optional) :
            Sets the map title. If array like, each element of the
            array becomes the title for each map. If the title is set
            to '%date%' then the ISO formated date is written.
        label (string, array like, optional) :
            Sets the label for each plot. If array like, each element
            of the array becomes the label for each plot.
        units (string, array like, optional) :
            Determines the units for all the maps of for each map
            sepparetely if a text array is given.
        subplot (array like, optional) :
            Two item list containing the number of rows and columns for
            subplots.
        adjustprops (dict, optional) :
            Dictionary containing the subplot parameters.
        loc (list, optional) :
            Lists the longitude of locations to be marked in map.
        xlim, ylim (array like, optional) :
            List containing the upper and lower zonal and meridional
            limits, respectivelly.
        xstep, ystep (float, optional) :
            Determines the parallel and meridian spacing.
        etopo (boolean, optional) :
            If true, overlays ETOPO contour lines on map.
        profile (boolean, optional) :
            Turns profiler on/off. If set to true (default) outputs the
            ETA and other information on screen.
        hook (function, optional) :
            Executes a hook function after the plot. The map instance
            is passed along as parameter.

    OUTPUT
        Map plots either on screen and or on file according to the
        specified parameters.

    RETURNS
        Nothing.

    """
    t1 = time()
    __init__()

    # Transforms input arrays in numpy arrays and numpy masked arrays.
    lat = numpy.asarray(lat)
    lon = numpy.asarray(lon)
    if type(tm).__name__ != 'NoneType':
        tm = numpy.asarray(tm)
    if type(z).__name__ != 'MaskedArray':
        z = numpy.ma.asarray(z)
        z.mask = numpy.isnan(z)

    # Determines the number of dimensions of the variable to be plotted and
    # the sizes of each dimension.
    dim = len(z.shape)
    if dim == 3:
        c, b, a = z.shape
    elif dim == 2:
        b, a = z.shape
        c = 1
        z = z.reshape(c, b, a)
    else:
        raise Warning, ('Map plots require either bi-dimensional or tri-'
                        'dimensional data.')
    if lon.size != a:
        raise Warning, 'Longitude and data lengths do not match.'
    if lat.size != b:
        raise Warning, 'Latitude and data lengths do not match.'
    #if type(tm).__name__ != 'NoneType':
    #    if tm.size != c:
    #        raise Warning, 'Time and data lengths do not match.'

    # Shifts the longitude and data grid if applicable and determines central
    # latitude and longitude for the map.
    lon180 = common.lon180(lon)
    if xlim == None:
        try:
            mask = ~z.mask.all(axis=0).all(axis=0)
            xlim = [lon180[mask].min(), lon180[mask].max()]
        except:
            xlim = [lon.min(), lon.max()]
    if ylim == None:
        try:
            mask = ~z.mask.all(axis=0).all(axis=1)
            ylim = [lat[mask].min(), lat[mask].max()]
        except:
            ylim = [lat.min(), lat.max()]
    lon0 = numpy.mean(xlim)
    lat0 = numpy.mean(ylim)
    if (shiftgrd != 0): # | (projection in ['ortho', 'robin', 'moll']):
        dx, dy = lon[1] - lon[0], lat[1] - lat[0]
        lon = lon180
        shift = pylab.find(pylab.diff(lon) < 0) + 1
        try:
          lon = numpy.roll(lon, -shift)
          z = numpy.roll(z, -shift)
        except:
          pass
        #z, lon = shiftgrid(shiftgrd, z, lon0)
        
        # Pad borders with NaN's to avoid distorsions
        #lon = numpy.concatenate([[lon[0] - dx], lon, [lon[-1] + dx]])
        #lat = numpy.concatenate([[lat[0] - dy], lat, [lat[-1] + dy]])
        #nan = numpy.ma.empty((c, 1, a)) * numpy.nan
        #nan.mask = True
        #z = numpy.ma.concatenate([nan, z, nan], axis=1)
        #nan = numpy.ma.empty((c, b+2, 1)) * numpy.nan
        #nan.mask = True
        #z = numpy.ma.concatenate([nan, z, nan], axis=2)
    
    # Loads topographic data, if appropriate.
    if etopo:
        ez = common.etopo.z
        ex = common.etopo.x
        ey = common.etopo.y
        er = -numpy.arange(1000, 12000, 1000)

    # Setting the color ranges
    if crange == None:
        cmajor, cminor, crange, cticks, extend = common.step(z,
            returnrange=True)
    else:
        crange = numpy.asarray(crange)
        cminor = numpy.diff(crange).mean()
        if crange.size > 11:
            cmajor = 2 * cminor
        if len(crange) < 15 :
            cticks = crange[::2]
        else:
            cticks = crange[::5]

        xmin, xmax = z.min(), z.max()
        rmin, rmax = crange.min(), crange.max()
        
        if (xmin < rmin) & (xmax > rmax):
            extend = 'both'
        elif (xmin < rmin) & (xmax <= rmax):
            extend = 'min'
        elif (xmin >= rmin) & (xmax > rmax):
            extend = 'max'
        elif (xmin >= rmin) & (xmax <= rmax):
            extend = 'neither'
        else:
            raise Warning, 'Unable to determine extend'
    if type(z2).__name__ != 'NoneType' and crange2 == None:
        cmajor2, cminor2, crange2, cticks2, extend2 = common.step(z2,
            returnrange=True)

    # Turning interactive mode on or off according to show parameter.
    if show == False:
        pylab.ioff()
    elif show == True:
        pylab.ion()
    else:
        raise Warning, 'Invalid show option.'

    # Sets the figure properties according to the orientation parameter and to
    # the data dimensions.
    if adjustprops == None:
        if projection in ['cyl', 'eqdc', 'poly', 'omerc', 'vandg', 'nsper']:
            adjustprops = dict(left=0.1, bottom=0.15, right=0.95, top=0.9,
                               wspace=0.05, hspace=0.5)
        else:
            adjustprops = dict(left=0.05, bottom=0.15, right=0.95, top=0.9,
                               wspace=0.05, hspace=0.2)

    # Sets the meridian and the parallel coordinates and necessary parameters
    # depending on the chosen projection.
    if xstep == None:
        xstep = int(common.step(xlim, 5, kind='polar')[0])
    if ystep == None:
        ystep = int(common.step(ylim, 3, kind='polar')[0])
    merid = numpy.arange(10 * int(min(xlim) / 10 - 2),
                         10 * int(max(xlim) / 10 + 3), xstep)
    if (max(ylim) - min(ylim)) > 130 | (projection in ['ortho', 'robin', 
        'moll']):
        #paral = numpy.array([-(66. + 33. / 60. + 38. / (60. * 60.)),
        #                     -(23. + 26. / 60. + 22. / (60. * 60.)), 0.,
        #                      (23. + 26. / 60. + 22. / (60. * 60.)),
        #                      (66. + 33. / 60. + 38. / (60. * 60.))])
        #paral = numpy.round(paral)
        paral = numpy.array([-60, -30, 0, 30, 60])
    else:
        paral = numpy.arange(numpy.floor(min(ylim) / ystep) * ystep,
                             numpy.ceil(max(ylim) / ystep) * ystep + ystep,
                             ystep)
    if projection == 'eqdc':
        if not (('lat_0' in kwargs.keys()) and ('lat_1' in kwargs.keys())):
            kwargs['lat_0'] = min(ylim) + (max(ylim) - min(ylim)) / 3.
            kwargs['lat_1'] = min(ylim) + 2 * (max(ylim) - min(ylim)) / 3.
        if not ('lon_0' in kwargs.keys()):
            kwargs['lon_0'] = lon0
    elif projection == 'poly':
        if not ('lat_0' in kwargs.keys()):
            kwargs['lat_0'] = (max(ylim) - min(ylim)) / 2.
        if not ('lon_0' in kwargs.keys()):
            kwargs['lon_0'] = lon0
    elif projection == 'omerc':
        if not (('lat_0' in kwargs.keys()) and ('lat_1' in kwargs.keys())):
            kwargs['lat_1'] = min(ylim) + (max(ylim) - min(ylim)) / 4.
            kwargs['lat_2'] = min(ylim) + 3 * (max(ylim) - min(ylim)) / 4.
        if not (('lon_0' in kwargs.keys()) and ('lon_1' in kwargs.keys())):
            kwargs['lon_1'] = min(xlim) + (max(ylim) - min(ylim)) / 4.
            kwargs['lon_2'] = min(xlim) + 3 * (max(ylim) - min(ylim)) / 4.
        kwargs['no_rot'] = False
    elif projection == 'vandg':
        kwargs['lon_0'] = lon0
    elif projection == 'nsper':
        kwargs['lon_0'] = lon0
        kwargs['lat_0'] = lat0
    elif projection in ['aea', 'lcc']:
        kwargs['lon_0'] = lon0
        kwargs['lat_0'] = (min(ylim) + max(ylim)) / 2.
        kwargs['lat_1'] = max(ylim) - (max(ylim) - min(ylim)) / 4.
        kwargs['lat_2'] = min(ylim) + (max(ylim) - min(ylim)) / 4.

    # Setting the subplot parameters in case multiple maps per figure.
    try:
        plrows, plcols = subplot
    except:
        if type(tm).__name__ in ['NoneType', 'float']:
            if orientation in ['landscape', 'worldmap']:
                plcols = min(3, c)
                plrows = numpy.ceil(float(c) / plcols)
            elif orientation == 'portrait':
                plrows = min(3, c)
                plcols = numpy.ceil(float(c) / plrows)
            elif orientation == 'squared':
                plrows = plcols = numpy.ceil(float(c) ** 0.5)
        else:
            plcols = plrows = 1

    bbox = dict(edgecolor='w', facecolor='w', alpha=0.9)

    # Starts the plotting routines
    if profile:
        if c == 1:
            plural = ''
        else:
            plural = 's'
        s = 'Plotting %d map%s... ' % (c, plural)
        stdout.write(s)
        stdout.flush()

    fig = graphics.figure(fp=dict(), ap=adjustprops, orientation=orientation)
    for n in range(c):
        t2 = time()
        if plcols * plrows > 1:
            ax = pylab.subplot(plrows, plcols, n + 1)
        else:
            fig.clear()
            ax = pylab.subplot(plcols, plrows, 1)
        
        if (projection in ['ortho', 'robin', 'moll']):
            m = Basemap(projection=projection, lat_0=lat0, lon_0=lon0, *kwargs)
            xoffset = (m.urcrnrx - m.llcrnrx) / 50.
        elif projection in ['aea', 'cyl', 'eqdc', 'poly', 'omerc', 'vandg', 
                            'nsper', 'lcc']:
            m = Basemap(projection=projection, llcrnrlat=min(ylim),
                        urcrnrlat=max(ylim), llcrnrlon=min(xlim),
                        urcrnrlon=max(xlim), **kwargs)
            xoffset = None
        else:
            raise Warning, 'Projection \'%s\' not implemented.' % (projection)

        x, y = m(*numpy.meshgrid(lon, lat))
        dat = z[n, :, :]
        
        # Set the merdians' and parallels' labels
        if plcols * plrows > 1:
            if (n % plcols) == 0:
                plabels =  [1, 0, 0, 0]
            else:
                plabels = [0, 0, 0, 0]
            if (n >= c - plcols):
                mlabels = [0, 0, 0, 1]
            else:
                mlabels = [0, 0, 0, 0]
        else:
            mlabels = [0, 0, 0, 1]
            plabels = [1, 0, 0, 0]
        if projection in ['ortho']:
            plabels = [0, 0, 0, 0]
        if projection in ['geos', 'ortho', 'aeqd', 'moll']:
            mlabels = [0, 0, 0, 0]

        # Plots locations
        for item in loc:
            m.scatter(item[0], item[1], s=24, c='w', marker='o', alpha=1, 
                      zorder=99)

        # Plot contour
        im = m.contourf(x, y, dat, crange, cmap=cmap, extend=extend, hold='on')

        if type(z2).__name__ != 'NoneType':
            dat2 = z2[n, :, :]
            im2 = m.contour(x, y, dat2, crange2, colors='k', hatch='x',
                hold='on', linewidths=numpy.linspace(0.25, 2., len(crange2)),
                alpha=0.6)
            #pylab.clabel(im2, fmt='%.1f')

        # Plot topography, if appropriate
        if etopo:
            xe, ye = m(*numpy.meshgrid(ex, ey))
            cs = m.contour(xe, ye, ez, er, colors='k', linestyles='-',
                alpha=0.3, hold='on')

        # Run hook function, if appropriate
        try:
            hook(m)
        except:
            pass

        m.drawcoastlines()
        m.fillcontinents()
        m.drawcountries()
        if projection != 'nsper':
            m.drawmapboundary(fill_color='white')
        m.drawmeridians(merid, linewidth=0.5, labels=mlabels)
        m.drawparallels(paral, linewidth=0.5, labels=plabels, xoffset=xoffset)
        
        # Draws colorbar
        if orientation == 'squared':
            cx = pylab.axes([0.25, 0.07, 0.5, 0.03])
        elif orientation  in ['landscape', 'worldmap']:
            cx = pylab.axes([0.2, 0.05, 0.6, 0.03])
        elif orientation == 'portrait':
            cx = pylab.axes([0.25, 0.05, 0.5, 0.02])
        pylab.colorbar(im, cax=cx, orientation='horizontal', ticks=cticks,
                       extend=extend)

        # Titles, units and other things
        ttl = None
        if title.__class__ == str:
            ttl = title
        else:
            try:
                ttl = title[n]
            except:
                pass
        if ttl:
            if ttl == '%date%':
                try:
                    ttl = dates.num2date(tm[n]).isoformat()[:10]
                except:
                    try:
                        ttl = dates.num2date(tm).isoformat()[:10]
                    except:
                        ttl = ''
                        pass
            ax.text(0.5, 1.05, ttl, ha='center', va='baseline',
                transform=ax.transAxes)
        
        lbl = None
        if label.__class__ == str:
            lbl = label
        else:
            try:
                lbl = label[n]
            except:
                pass
        if lbl:
            if lbl == '%date%':
                try: 
                    ttl = dates.num2date(tm[n]).isoformat()[:10]
                except:
                    try:
                        ttl = dates.num2date(tm).isoformat()[:10]
                    except:
                        ttl = ''
                        pass
            ax.text(0.04, 0.83, lbl, ha='left', va='bottom', 
                transform=ax.transAxes, bbox=bbox)

        unt = None
        if units.__class__ == str:
            unt = units
        else:
            try:
                unt = units[n]
            except:
                pass
        if unt:
            cx.text(1.05, 0.5, r'$\left[%s\right]$' % (unt), ha='left',
                va='center', transform=cx.transAxes)

        # Drawing and saving the figure if appropriate.
        pylab.draw()
        if save:
            if (c == 1) | (plcols * plrows > 1):
                pylab.savefig('%s.%s' % (save, ftype), dpi=150)
            else:
                pylab.savefig('%s%06d.%s' % (save, n+1, ftype), dpi=150)

        if profile:
            stdout.write(len(s) * '\b')
            s = 'Plotting %d map%s... %s ' % (c, plural, common.profiler(c, 
                n + 1, 0, t1, t2),)
            stdout.write(s)
            stdout.flush()

    #
    if profile:
        stdout.write('\n')
    if show == False:
        pylab.close(fig)
    else:
        return fig