Exemplo n.º 1
0
def plot_pmlf(pml_data, title='', output_file=None, grid=True,
             show_graph=False, annotate=[]):
    """Plot the PML fatality data.  Optionally save a file or show the graph (or both).

    Inputs:
    pml_data       (nx2) array containing the PMLf curve. The first column
                   contains the probability of exceedance (in one year) values,
                   the second column contains the direct fatality losses
                   for each of the probabilities of exceedance. 
    title          if supplied, the graph title string
    output_file    path of file to save plot picture in
    grid           draw a grid on graph if True
    show_graph     show graph on screen if True
    annotate       an iterable like [(x, y, ann, dict), ...] where
                       x    is X screen coordinate
                       y    is Y screen coordinate
                       ann  is the annotation string to display at (x, y)
                       dict is a dictionary of key/value pairs as documented at
                            http://matplotlib.sourceforge.net/api/pyplot_api.html
                            (this is optional)
                   NOTE: if annotate=None is used, no automatic annotation occurs.
                         if annotate=[] is used, auto annotation is generated:
                             timestamp
                             clipping
                             max input data value


    """

    # decide if we have a 'gui-less' plot or not.
    import matplotlib
    if output_file and not show_graph:
        # no plot to be shown - no gui
        matplotlib.use('Agg', warn=False)
    elif show_graph:
        # decide if we *can* show the plot - error if not
        if sys.platform != 'win32':
            try:
                display = os.environ['DISPLAY']
            except KeyError:
                msg = ("No DISPLAY variable set.  "
                       "Did you do 'ssh -X <machine>'?")
                raise RuntimeError(msg)

    # go ahead with the plot
    import matplotlib.pyplot as plt
    import matplotlib.colors as mcolors

    # create a plot of annualised loss versus return period if requested
    if output_file or show_graph:
        # unpack pml_data
        [ProbExceedSmall, trghzd_agg] = pml_data
                 
        fig = plt.figure()
        ax = fig.add_subplot(111)
        
        plt.semilogy(trghzd_agg, ProbExceedSmall, color='b')
        
        plt.xlabel('Direct fatality loss')
        plt.ylabel('Probability of exceedance in one year')

        # add graph 'furniture'
        if title:
            plt.title(title)
        plt.grid(grid)

        # add system annotations: time generated, etc
        if isinstance(annotate, list):
            pts.plot_timestamp(fig)

        # add user annotations, if any
        pua.plot_user_annotation(fig, annotate)

        # show or save graph (or both?)
        if output_file:
            plt.savefig(output_file)
        if show_graph:
            plt.show()

        plt.close()
Exemplo n.º 2
0
def plot_hexbin_map(map_data, bins=100, title='', output_file=None, cblabel='',
                    cbformat='%.1f', show_graph=False, grid=True, colormap=None,
                    annotate=[], scale=None, np_posn=None,
                    hexbin_args=None, map_extent=None):
    """Plot data into a hexgrid  with an underlay map.

    Inputs:
    map_data       (nx3) array containing the data to plot. The first column
                   contains the latitude of a point, the second column contains
                   the longitude and the third column is the value to bin&plot.
    bins           Either a scalar (# bins in X and Y directions) or (nx, ny).
    title          the graph title string
    output_file    path of file to save plot picture in
    cblabel        label to display on the colorbar
    cbformat       format string used to show colormap values
    show_graph     show graph on screen if True
    grid           draw a grid on graph if True
    colormap       if supplied, the colormap name to use (string)
    annotate       an iterable like [(x, y, ann, dict), ...] where
                       x    is X screen coordinate
                       y    is Y screen coordinate
                       ann  is the annotation string to display at (x, y)
                       dict is a dictionary of key/value pairs as documented at
                            http://matplotlib.sourceforge.net/api/pyplot_api.html
                            (this is optional)
                   NOTE: if annotate=None is used, no automatic annotation occurs.
                         if annotate=[] is used, auto annotation is generated:
                             timestamp
    scale          a tuple containing data used to draw a scale:
                   (posn, length, scale_args)
                   where 'posn'       is where to place scale, one of:
                                          'NW', 'NE', 'SW', 'SE'
                                          (case-insensitive)
                     and 'scale_args' is an optional kwargs dictionary
                   see drawmapscale() function at 
                   http://matplotlib.sourceforge.net/basemap/doc/html/api/basemap_api.html#mpl_toolkits.basemap.Basemap.drawmapscale
                   to see values in scale_args
    np_posn        position tuple or a string describing pointer position:
                       'NW', 'NE', 'SW' or 'SE'
                       (case-insensitive)
    hexbin_args    is a dictionary of hexbin() parameters
                   if not supplied, assume {'gridsize': 100,
                                            'reduce_C_function': scipy.sum
                                           }
                   Note: if hexbin_args is supplied but key 'reduce_C_function'
                   isn't supplied in dictionary, insert 'scipy.sum' function
                   Note: allowed values are documented at:
                         http://matplotlib.sourceforge.net/api/pyplot_api.html
    map_extent     sets the extent of the displayed map if supplied
                   (get extent from the data if not supplied)

    """

    # decide if we have a 'gui-less' plot or not.
    import matplotlib
    if output_file and not show_graph:
        # no plot to be shown - no gui
        matplotlib.use('Agg', warn=False)
    elif show_graph:
        # decide if we *can* show the plot - error if not
        if sys.platform != 'win32':
            try:
                display = os.environ['DISPLAY']
            except KeyError:
                msg = ("No DISPLAY variable set.  "
                       "Did you do 'ssh -X <machine>'?")
                raise RuntimeError(msg)

    # go ahead with the plot
    import matplotlib.pyplot as plt
    import matplotlib.colors as mcolors
    from mpl_toolkits.basemap import Basemap
    from matplotlib.mlab import griddata

    # create a 'binned' plot on a map
    if output_file or show_graph:
        # decide on the colormap to use
        (cmap_name, my_cmap) = uc.get_colormap(colormap)

        # set the hexbin params
        if hexbin_args is None:
            hexbin_args = {'gridsize': 100,
                           'reduce_C_function': scipy.sum,
                           'linewidth': DEFAULT_LINEWIDTH}

        try:
            _ = hexbin_args['reduce_C_function']
        except KeyError:
            hexbin_args['reduce_C_function'] = scipy.sum

        # here we fiddle with 'linewidth' to get around a bug in plotting
        # if linewidth not set, hex bins overlap each other
        # force linewidth to a small value if not specified
        try:
            _ = hexbin_args['linewidth']
        except KeyError:
            hexbin_args['linewidth'] = DEFAULT_LINEWIDTH


        # if user doesn't define 'edgecolors' at all, use default
        hexbin_args['edgecolors'] = hexbin_args.get('edgecolors', FILL_COLOUR)

        # get extent of point data
        if map_extent:
            extent = map_extent
        else:
            extent = gxe.get_extent(map_data, margin=5)
        (ll_lat, ll_lon, ur_lat, ur_lon) = extent

        # start the plot
        fig = plt.figure()
        ax = fig.add_subplot(111)
            
        # draw the map
        m = Basemap(projection='cyl', llcrnrlat=ll_lat, urcrnrlat=ur_lat,
                    llcrnrlon=ll_lon, urcrnrlon=ur_lon, resolution='h',
                    suppress_ticks=False, area_thresh=0.5)

#        m = Basemap(projection='cass', llcrnrlat=ll_lat, urcrnrlat=ur_lat,
#                    llcrnrlon=ll_lon, urcrnrlon=ur_lon, resolution='h',
#                    lat_0=(ll_lat+ur_lat)/2.0, lon_0=(ll_lon+ur_lon)/2.0,
#                    suppress_ticks=False) #, area_thresh=0.5)

        # draw hexbin data on map
        plt.hexbin(map_data[:,0], map_data[:,1], map_data[:,2],
                   cmap=my_cmap, zorder=4, **hexbin_args)

        # draw the other minor stuff
        m.fillcontinents(color=FILL_COLOUR, zorder=2)
        m.drawcoastlines(linewidth=0.25, color='k', zorder=5)
        m.drawmapboundary()

        cb = plt.colorbar(cmap=my_cmap, format=cbformat)
        cb.set_label(cblabel)
        
        plt.xlabel('longitude', fontsize=8)
        plt.ylabel('latitude', fontsize=8)

        # if user asked for a NORTH pointer
        if np_posn:
            unp.plot_northpointer(m, (ll_lat, ll_lon, ur_lat, ur_lon),
                                  np_posn)

        # add graph 'furniture'
        plt.title(title)
        plt.grid(grid, color='#C0C0C0', linestyle='-', linewidth=0.25)

        # add system annotations: time generated, etc
        if isinstance(annotate, list):
            pts.plot_timestamp(fig)

        # add user annotations, if any
        pua.plot_user_annotation(fig, annotate)

        # show or save graph (or both?)
        if output_file:
            plt.savefig(output_file, dpi=300)
        if show_graph:
            plt.show()

        plt.close()
def plot_annloss_deagg_distmag(data, momag_labels, range_bins, pct_limits=None,
                               output_file=None, title=None,
                               show_graph=False, grid=False, colormap=None,
                               annotate=[]):
    """Plot annualised loss deaggregated distance/magnitude data.

    Inputs:
    data         an MxN array containing % annualised loss values with axes
                 of moment/magnitude data (M) versus distance (N)
    momag_labels an iterable containing the y-axis labels for each row of 'data'
    range_bins   an iterable of range values for each column of 'data'
    pct_limits   a tuple (min_pct, max_pct) for % range to plot
    output_file  path to required output plot file
    title        string used to title graph
    show_graph   if True shows graph in window on screen
    grid         if True puts a grid in the graph
    colormap     name of the colormap to use
    annotate     an iterable like [(x, y, str, dict), ...] where
                     x    is X screen coordinate
                     y    is Y screen coordinate
                     str  is the annotation string to display at (x, y)
                     dict is a dictionary of key/value pairs as documented at
                          http://matplotlib.sourceforge.net/api/pyplot_api.html
                          (this is optional)
                 NOTE: if annotate=None is used, no automatic annotation occurs.
                       if annotate=[] is used, auto annotation is generated:
                           timestamp
                           clipping
                           max input data value

    """

    # decide if we have a 'gui-less' plot or not.
    import matplotlib
    if output_file and not show_graph:
        # no plot to be shown - no gui
        matplotlib.use('Agg', warn=False)
    elif show_graph:
        # decide if we *can* show the plot - error if not
        if sys.platform != 'win32':
            try:
                display = os.environ['DISPLAY']
            except KeyError:
                msg = ("No DISPLAY variable set.  "
                       "Did you do 'ssh -X <machine>'?")
                raise RuntimeError(msg)

    # go ahead with the plot
    import matplotlib.pyplot as plt
    import matplotlib.colors as mcolors

    # decide if we are going to plot
    if output_file or show_graph:
        # get colormap to use
        (cmap_name, my_cmap) = uc.get_colormap(colormap)

        # get maximum data value
        #max_pct = scipy.max(data)
        max_pct = num.max(data)
        
        # limit values to within pct_limits here
        if pct_limits:
            (floor, ceil) = pct_limits
            plot_data = scipy.clip(data, floor, ceil)
        else:
            plot_data = data

        # drop last range bin row from data
        plot_data = plot_data[:,:-1]
        
        # Get data X and Y limits
        max_x = range_bins[-1]
        min_x = range_bins[0]
        max_y = momag_labels[-1]
        min_y = momag_labels[0]
        max_z = num.max(plot_data)
        min_z = num.min(plot_data)

        # calculate required aspect ration (the *2 is a fudge)
        (y_size, x_size) = scipy.shape(plot_data)
        ratio = float(x_size/y_size) * 2

        # start plot
        fig = plt.figure()
        ax = fig.add_subplot(111)

        im = plt.imshow(plot_data, interpolation='nearest', cmap=my_cmap,
                        origin='lower', extent=[min_x,max_x,min_y,max_y])

        # add color bar
        for step in (1, 2, 5, 10, 20, 50, 100):
            cb_ticks = [x for x in range(int(min_z), int(max_z+1), step)]
            if len(cb_ticks) <= 12:
                break
        cb = plt.colorbar(orientation='horizontal', ticks=cb_ticks)
        cb.set_label('% of annual loss')
        
        # label axes
        plt.xlabel('Distance (km)')
        plt.ylabel('Moment Magnitude')

        # set main plot aspect ratio
        plt.axes().set_aspect(ratio)

        # add graph 'furniture'
        if title:
            plt.title(title)
        plt.grid(grid) 
                
        # add system annotations: the clipping in effect, time generated, etc
        if isinstance(annotate, list):
            pts.plot_timestamp(fig)

            if pct_limits:
                clip_str = 'Data values clipped to [%.1f,%.1f]' % (floor, ceil)
                plt.text(0.98, 0.02, clip_str, fontsize=6,
                         transform=fig.transFigure, horizontalalignment='right')
            pct_str = '%.2f%%' % max_pct
            plt.text(0.91, 0.185, pct_str, horizontalalignment='left',
                     fontsize=8, transform=fig.transFigure, )

        # add user annotations, if any
        pua.plot_user_annotation(fig, annotate)

        # show or save graph (or both?)
        if output_file:
            plt.savefig(output_file)
        if show_graph:
            plt.show()

        plt.close()
def plot_pmlf(pml_data,
              title='',
              output_file=None,
              grid=True,
              show_graph=False,
              annotate=[]):
    """Plot the PML fatality data.  Optionally save a file or show the graph (or both).

    Inputs:
    pml_data       (nx2) array containing the PMLf curve. The first column
                   contains the probability of exceedance (in one year) values,
                   the second column contains the direct fatality losses
                   for each of the probabilities of exceedance. 
    title          if supplied, the graph title string
    output_file    path of file to save plot picture in
    grid           draw a grid on graph if True
    show_graph     show graph on screen if True
    annotate       an iterable like [(x, y, ann, dict), ...] where
                       x    is X screen coordinate
                       y    is Y screen coordinate
                       ann  is the annotation string to display at (x, y)
                       dict is a dictionary of key/value pairs as documented at
                            http://matplotlib.sourceforge.net/api/pyplot_api.html
                            (this is optional)
                   NOTE: if annotate=None is used, no automatic annotation occurs.
                         if annotate=[] is used, auto annotation is generated:
                             timestamp
                             clipping
                             max input data value


    """

    # decide if we have a 'gui-less' plot or not.
    import matplotlib
    if output_file and not show_graph:
        # no plot to be shown - no gui
        matplotlib.use('Agg', warn=False)
    elif show_graph:
        # decide if we *can* show the plot - error if not
        if sys.platform != 'win32':
            try:
                display = os.environ['DISPLAY']
            except KeyError:
                msg = ("No DISPLAY variable set.  "
                       "Did you do 'ssh -X <machine>'?")
                raise RuntimeError(msg)

    # go ahead with the plot
    import matplotlib.pyplot as plt
    import matplotlib.colors as mcolors

    # create a plot of annualised loss versus return period if requested
    if output_file or show_graph:
        # unpack pml_data
        [ProbExceedSmall, trghzd_agg] = pml_data

        fig = plt.figure()
        ax = fig.add_subplot(111)

        plt.semilogy(trghzd_agg, ProbExceedSmall, color='b')

        plt.xlabel('Direct fatality loss')
        plt.ylabel('Probability of exceedance in one year')

        # add graph 'furniture'
        if title:
            plt.title(title)
        plt.grid(grid)

        # add system annotations: time generated, etc
        if isinstance(annotate, list):
            pts.plot_timestamp(fig)

        # add user annotations, if any
        pua.plot_user_annotation(fig, annotate)

        # show or save graph (or both?)
        if output_file:
            plt.savefig(output_file)
        if show_graph:
            plt.show()

        plt.close()
Exemplo n.º 5
0
def plot_barchart(data, output_file=None, title='', xlabel='', ylabel='',
                  xrange=None, yrange=None, grid=True, show_graph=False,
                  bin_width=None, bardict=None, annotate=[]):
    """Plot a barchart.  Optionally save a file or show the graph (or both).

    Inputs:
    data           (nx2) array containing the barchart data. The first column
                   contains the X ordinal and the second column contains the
                   height of the bar
    output_file    path of file to save plot picture in
    title          the graph title string, if supplied
    xlabel         label to put on the X axis
    ylabel         label to put on the Y axis
    xrange         a scalar or iterable indicating min[,max] X value to plot
    yrange         a scalar or iterable indicating min[,max] Y value to plot
    grid           draw a grid on graph if True
    show_graph     show graph on screen if True
    bin_width      width of the bins
    bardict        a dictionary containing extra parameters to the
                   matplotlib.pyplot.bar() routine.  Params are defined at
     http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.bar
    annotate       an iterable like [(x, y, ann, dict), ...] where
                       x    is X screen coordinate
                       y    is Y screen coordinate
                       ann  is the annotation string to display at (x, y)
                       dict is a dictionary of key/value pairs as documented at
                            matplotlib.sourceforge.net/api/pyplot_api.html
                            (this is optional)
                   NOTE: if annotate=None is used, no annotation occurs.
                         if annotate=[] is used, auto annotation is generated:
                             timestamp
                             X and Y range limits

    """

    # decide if we have a 'gui-less' plot or not.
    import matplotlib
    if output_file and not show_graph:
        # no plot to be shown - no gui
        matplotlib.use('Agg', warn=False)
    elif show_graph:
        # decide if we *can* show the plot - error if not
        if sys.platform != 'win32':
            try:
                display = os.environ['DISPLAY']
            except KeyError:
                msg = ("No DISPLAY variable set.  "
                       "Did you do 'ssh -X <machine>'?")
                raise RuntimeError(msg)

    # go ahead with the plot
    import matplotlib.pyplot as plt

    # create the plot if we want a file or must show it
    if output_file or show_graph:
        fig = plt.figure()
        ax = fig.add_subplot(111)
       
        # get bardict into correct form for bar() call below
        bar_kwargs = {}
        if bardict:
            bar_kwargs = bardict

        # plot the data
        if bin_width:
            plt.bar(data[:,0], data[:,1], width=bin_width, align='center',
                    **bar_kwargs)
        else:
            plt.bar(data[:,0], data[:,1], align='center', **bar_kwargs)

        # set X and Y range limits
        xrange = util.get_canonical_range(xrange)
        yrange = util.get_canonical_range(yrange)
        if xrange:
            plt.xlim(xrange)
        if yrange:
            plt.ylim(yrange)

        # do X and Y labels
        plt.xlabel(xlabel)
        plt.ylabel(ylabel)

        # add graph 'furniture'
        if title:
            plt.title(title)
        plt.grid(grid)

        # add system annotations: time generated, etc
        if isinstance(annotate, list):
            pts.plot_timestamp(fig)

        # add range limits annotations
        if annotate is None:
            annotate = []
        if xrange:
            annotate.append((0.02, 0.05,
                             'X range forced to (%.2f,%.2f)' % xrange))
        if yrange:
            annotate.append((0.02, 0.03,
                              'Y range forced to (%.2f,%.2f)' % yrange))

        # add user annotations, if any
        pua.plot_user_annotation(fig, annotate)

        # show or save graph (or both?)
        if output_file:
            plt.savefig(output_file)
        if show_graph:
            plt.show()

        plt.close()
Exemplo n.º 6
0
def plot_hexbin_map(map_data,
                    bins=100,
                    title='',
                    output_file=None,
                    cblabel='',
                    cbformat='%.1f',
                    show_graph=False,
                    grid=True,
                    colormap=None,
                    annotate=[],
                    scale=None,
                    np_posn=None,
                    hexbin_args=None,
                    map_extent=None):
    """Plot data into a hexgrid  with an underlay map.

    Inputs:
    map_data       (nx3) array containing the data to plot. The first column
                   contains the latitude of a point, the second column contains
                   the longitude and the third column is the value to bin&plot.
    bins           Either a scalar (# bins in X and Y directions) or (nx, ny).
    title          the graph title string
    output_file    path of file to save plot picture in
    cblabel        label to display on the colorbar
    cbformat       format string used to show colormap values
    show_graph     show graph on screen if True
    grid           draw a grid on graph if True
    colormap       if supplied, the colormap name to use (string)
    annotate       an iterable like [(x, y, ann, dict), ...] where
                       x    is X screen coordinate
                       y    is Y screen coordinate
                       ann  is the annotation string to display at (x, y)
                       dict is a dictionary of key/value pairs as documented at
                            http://matplotlib.sourceforge.net/api/pyplot_api.html
                            (this is optional)
                   NOTE: if annotate=None is used, no automatic annotation occurs.
                         if annotate=[] is used, auto annotation is generated:
                             timestamp
    scale          a tuple containing data used to draw a scale:
                   (posn, length, scale_args)
                   where 'posn'       is where to place scale, one of:
                                          'NW', 'NE', 'SW', 'SE'
                                          (case-insensitive)
                     and 'scale_args' is an optional kwargs dictionary
                   see drawmapscale() function at 
                   http://matplotlib.sourceforge.net/basemap/doc/html/api/basemap_api.html#mpl_toolkits.basemap.Basemap.drawmapscale
                   to see values in scale_args
    np_posn        position tuple or a string describing pointer position:
                       'NW', 'NE', 'SW' or 'SE'
                       (case-insensitive)
    hexbin_args    is a dictionary of hexbin() parameters
                   if not supplied, assume {'gridsize': 100,
                                            'reduce_C_function': scipy.sum
                                           }
                   Note: if hexbin_args is supplied but key 'reduce_C_function'
                   isn't supplied in dictionary, insert 'scipy.sum' function
                   Note: allowed values are documented at:
                         http://matplotlib.sourceforge.net/api/pyplot_api.html
    map_extent     sets the extent of the displayed map if supplied
                   (get extent from the data if not supplied)

    """

    # decide if we have a 'gui-less' plot or not.
    import matplotlib
    if output_file and not show_graph:
        # no plot to be shown - no gui
        matplotlib.use('Agg', warn=False)
    elif show_graph:
        # decide if we *can* show the plot - error if not
        if sys.platform != 'win32':
            try:
                display = os.environ['DISPLAY']
            except KeyError:
                msg = ("No DISPLAY variable set.  "
                       "Did you do 'ssh -X <machine>'?")
                raise RuntimeError(msg)

    # go ahead with the plot
    import matplotlib.pyplot as plt
    import matplotlib.colors as mcolors
    from mpl_toolkits.basemap import Basemap
    from matplotlib.mlab import griddata

    # create a 'binned' plot on a map
    if output_file or show_graph:
        # decide on the colormap to use
        (cmap_name, my_cmap) = uc.get_colormap(colormap)

        # set the hexbin params
        if hexbin_args is None:
            hexbin_args = {
                'gridsize': 100,
                'reduce_C_function': scipy.sum,
                'linewidth': DEFAULT_LINEWIDTH
            }

        try:
            _ = hexbin_args['reduce_C_function']
        except KeyError:
            hexbin_args['reduce_C_function'] = scipy.sum

        # here we fiddle with 'linewidth' to get around a bug in plotting
        # if linewidth not set, hex bins overlap each other
        # force linewidth to a small value if not specified
        try:
            _ = hexbin_args['linewidth']
        except KeyError:
            hexbin_args['linewidth'] = DEFAULT_LINEWIDTH

        # if user doesn't define 'edgecolors' at all, use default
        hexbin_args['edgecolors'] = hexbin_args.get('edgecolors', FILL_COLOUR)

        # get extent of point data
        if map_extent:
            extent = map_extent
        else:
            extent = gxe.get_extent(map_data, margin=5)
        (ll_lat, ll_lon, ur_lat, ur_lon) = extent

        # start the plot
        fig = plt.figure()
        ax = fig.add_subplot(111)

        # draw the map
        m = Basemap(projection='cyl',
                    llcrnrlat=ll_lat,
                    urcrnrlat=ur_lat,
                    llcrnrlon=ll_lon,
                    urcrnrlon=ur_lon,
                    resolution='h',
                    suppress_ticks=False,
                    area_thresh=0.5)

        #        m = Basemap(projection='cass', llcrnrlat=ll_lat, urcrnrlat=ur_lat,
        #                    llcrnrlon=ll_lon, urcrnrlon=ur_lon, resolution='h',
        #                    lat_0=(ll_lat+ur_lat)/2.0, lon_0=(ll_lon+ur_lon)/2.0,
        #                    suppress_ticks=False) #, area_thresh=0.5)

        # draw hexbin data on map
        plt.hexbin(map_data[:, 0],
                   map_data[:, 1],
                   map_data[:, 2],
                   cmap=my_cmap,
                   zorder=4,
                   **hexbin_args)

        # draw the other minor stuff
        m.fillcontinents(color=FILL_COLOUR, zorder=2)
        m.drawcoastlines(linewidth=0.25, color='k', zorder=5)
        m.drawmapboundary()

        cb = plt.colorbar(cmap=my_cmap, format=cbformat)
        cb.set_label(cblabel)

        plt.xlabel('longitude', fontsize=8)
        plt.ylabel('latitude', fontsize=8)

        # if user asked for a NORTH pointer
        if np_posn:
            unp.plot_northpointer(m, (ll_lat, ll_lon, ur_lat, ur_lon), np_posn)

        # add graph 'furniture'
        plt.title(title)
        plt.grid(grid, color='#C0C0C0', linestyle='-', linewidth=0.25)

        # add system annotations: time generated, etc
        if isinstance(annotate, list):
            pts.plot_timestamp(fig)

        # add user annotations, if any
        pua.plot_user_annotation(fig, annotate)

        # show or save graph (or both?)
        if output_file:
            plt.savefig(output_file, dpi=300)
        if show_graph:
            plt.show()

        plt.close()