コード例 #1
0
def createMap(proj, **kwargs):
    '''
    Define a basemap object given the projection parameters from setProj
    Input  : Projection class
    Output : basemap object
    '''

    if proj.projection == 'stere':
        bmap = _Basemap(projection=proj.projection, **kwargs)

    elif (proj.projection in ['npstere', 'spstere']):
        bmap = _Basemap(projection=proj.projection,
                        resolution=proj.resolution,
                        lon_0=proj.cenlon,
                        boundinglat=proj.boundinglat,
                        **kwargs)

    elif (proj.projection in ['mill', 'miller', 'merc', 'mercator']):
        bmap = _Basemap(projection=proj.projection,
                        resolution=proj.resolution,
                        llcrnrlon=proj.llcrnrlon,
                        llcrnrlat=proj.llcrnrlat,
                        urcrnrlon=proj.urcrnrlon,
                        urcrnrlat=proj.urcrnrlat,
                        **kwargs)

    elif (proj.projection in ['lcc', 'lambert']):
        bmap = _Basemap(projection=proj.projection,
                        resolution=proj.resolution,
                        width=proj.width,
                        height=proj.height,
                        lat_0=proj.cenlat,
                        lon_0=proj.cenlon,
                        lat_1=proj.stdlat1,
                        lat_2=proj.stdlat2,
                        **kwargs)

    elif proj.projection == 'ortho':
        bmap = _Basemap(projection=proj.projection,
                        resolution=proj.resolution,
                        **kwargs)

    elif proj.projection == 'robin':
        bmap = _Basemap(projection=proj.projection,
                        resolution=proj.resolution,
                        **kwargs)

    else:
        msg = 'Error message from : createMap(proj)\n' + \
              '   projection %s has not been implemented yet\n' % (proj.projection) + \
              '   valid options for projection are:\n' + \
              '   "stere" | "npstere" | "spstere" | "mill" | "merc" | "lcc" | "ortho" | "robin"'
        print msg
        raise

    return bmap
コード例 #2
0
ファイル: plot.py プロジェクト: suchyta1/suchyta_utils
def _BasePlot(ax=None, fig=None, nside=512, cat=None, ra=None, dec=None, nest=False, parallels=_np.arange(-75.,0.,5.), meridians=_np.arange(0.,360.,5.), dims=[20,20], center=[75,-52.5], vmin=None, vmax=None, clabel='$n_s\ [\mathrm{arcmin}^{-2}]$', rafmt='d', raflip=True, xoffset=0, yoffset=0, size=9, f=_getCountLocation, noplot=False, cmap=_cm.YlOrRd, cside='right', extrakwargs={} ):
    if fig is None:
        fig, ax = plt.subplots(1,1, figsize=(6.5*nside/512,6*nside/512))
    if ax is None:
        fig, ax = _plt.subplots(1,1)

    r = 6.371e6
    h = r * _np.radians(dims[1])
    w = r * _np.cos(_np.radians(center[1])) * _np.radians(dims[0])

    m = _Basemap(projection='aea', width=w, height=h, lat_0=center[1], lon_0=center[0], ax=ax)
    #m = _Basemap(projection='aea', llcrnrlon=110, llcrnrlat=-80, urcrnrlon=-70, urcrnrlat=20, lon_0=50, lat_0=-5, ax=ax)
    #m = _Basemap(projection='eqdc', width=w, height=h, lat_0=center[1], lon_0=center[0], ax=ax)
    #m = _Basemap(projection='spstere',boundinglat=10,lon_0=270,resolution='l')

    if rafmt=='h':
        m.drawmeridians(meridians,labels=[0,0,0,1], fmt=_Lon2RA, linewidth=0.5, yoffset=(r*_np.radians(yoffset)))
    elif rafmt=='d':
        m.drawmeridians(meridians,labels=[0,0,1,0], linewidth=0.5, yoffset=(r*_np.radians(yoffset)))

    if raflip:
        m.drawparallels(parallels,labels=[0,1,0,0], labelstyle="+/-", linewidth=0.5, xoffset=(r*_np.radians(xoffset)))
        ax.invert_xaxis()
    else:
        m.drawparallels(parallels,labels=[0,1,0,0], labelstyle="+/-", linewidth=0.5, xoffset=(r*_np.radians(xoffset)))


    if noplot:
        return m
    bc, lat, lon = f(cat=cat, ra=ra, dec=dec, nside=nside, nest=nest, **extrakwargs)
    x,y  = m(lon, lat)

    if vmin is None:
        vmin = _np.amin(bc)
    if vmax is None:
        vmax = _np.amax(bc)

    sc = m.scatter(x,y,c=bc, linewidths=0, s=size, marker='s', vmin=vmin, vmax=vmax, rasterized=True, cmap=cmap, ax=ax)
    cb = m.colorbar(sc,cside, size="3%", pad='0%')
    if clabel is not None:
        cb.set_label(clabel)
    #cb.set_ticklabels(_np.linspace(vmin, vmax, (vmax - vmin)/1 + 1, dtype='int32'))
    cb.solids.set_edgecolor("face")
コード例 #3
0
ファイル: plot.py プロジェクト: suchyta1/suchyta_utils
def _BasePlot(ax=None,
              fig=None,
              nside=512,
              cat=None,
              ra=None,
              dec=None,
              nest=False,
              parallels=_np.arange(-75., 0., 5.),
              meridians=_np.arange(0., 360., 5.),
              dims=[20, 20],
              center=[75, -52.5],
              vmin=None,
              vmax=None,
              clabel='$n_s\ [\mathrm{arcmin}^{-2}]$',
              rafmt='d',
              raflip=True,
              xoffset=0,
              yoffset=0,
              size=9,
              f=_getCountLocation,
              noplot=False,
              cmap=_cm.YlOrRd,
              cside='right',
              extrakwargs={}):
    if fig is None:
        fig, ax = plt.subplots(1,
                               1,
                               figsize=(6.5 * nside / 512, 6 * nside / 512))
    if ax is None:
        fig, ax = _plt.subplots(1, 1)

    r = 6.371e6
    h = r * _np.radians(dims[1])
    w = r * _np.cos(_np.radians(center[1])) * _np.radians(dims[0])

    m = _Basemap(projection='aea',
                 width=w,
                 height=h,
                 lat_0=center[1],
                 lon_0=center[0],
                 ax=ax)
    #m = _Basemap(projection='aea', llcrnrlon=110, llcrnrlat=-80, urcrnrlon=-70, urcrnrlat=20, lon_0=50, lat_0=-5, ax=ax)
    #m = _Basemap(projection='eqdc', width=w, height=h, lat_0=center[1], lon_0=center[0], ax=ax)
    #m = _Basemap(projection='spstere',boundinglat=10,lon_0=270,resolution='l')

    if rafmt == 'h':
        m.drawmeridians(meridians,
                        labels=[0, 0, 0, 1],
                        fmt=_Lon2RA,
                        linewidth=0.5,
                        yoffset=(r * _np.radians(yoffset)))
    elif rafmt == 'd':
        m.drawmeridians(meridians,
                        labels=[0, 0, 1, 0],
                        linewidth=0.5,
                        yoffset=(r * _np.radians(yoffset)))

    if raflip:
        m.drawparallels(parallels,
                        labels=[0, 1, 0, 0],
                        labelstyle="+/-",
                        linewidth=0.5,
                        xoffset=(r * _np.radians(xoffset)))
        ax.invert_xaxis()
    else:
        m.drawparallels(parallels,
                        labels=[0, 1, 0, 0],
                        labelstyle="+/-",
                        linewidth=0.5,
                        xoffset=(r * _np.radians(xoffset)))

    if noplot:
        return m
    bc, lat, lon = f(cat=cat,
                     ra=ra,
                     dec=dec,
                     nside=nside,
                     nest=nest,
                     **extrakwargs)
    x, y = m(lon, lat)

    if vmin is None:
        vmin = _np.amin(bc)
    if vmax is None:
        vmax = _np.amax(bc)

    sc = m.scatter(x,
                   y,
                   c=bc,
                   linewidths=0,
                   s=size,
                   marker='s',
                   vmin=vmin,
                   vmax=vmax,
                   rasterized=True,
                   cmap=cmap,
                   ax=ax)
    cb = m.colorbar(sc, cside, size="3%", pad='0%')
    if clabel is not None:
        cb.set_label(clabel)
    #cb.set_ticklabels(_np.linspace(vmin, vmax, (vmax - vmin)/1 + 1, dtype='int32'))
    cb.solids.set_edgecolor("face")
コード例 #4
0
    def plot(self,
             projection='lcc',
             center = 'auto',
             width=400000 * 7,
             height=500000 * 3,
             station_label_format ='{abbr}',
             station_label_kwargs = None,
             resolution='c',
             background='blue_marble',
             station_symbol_kwargs = None,
             # site_label_marker_size = 8,
             # site_label_font_size = 18,
             # site_label_color='auto',
             bmap = None,
             plot_only_if_on_map = False,
             ax = None,
             verbose = False):
        """

        Parameters
        ----------
        projection
        center: 'auto' or (lat, lon)
        width
        height
        station_label_format: format str ('abbr', 'name', 'state')
            This takes a fromat string with the given optional arguments. E.g. '{name}, {state}'.
        station_label_kwargs: dict or bool
            This defines the position, size ... of the label. If False no label will
            be shown. See doc of plt.annotate() for details.
            defaults = dict(xytext = (10, -10),
                            size = 18,
                            ha = "left",
                            va = 'top',
                            textcoords = 'offset points',
                            bbox = dict(boxstyle="round", fc=[1, 1, 1, 0.5], ec='black'),
                             )
        resolution: str ('c','i','h'....
        background: str
            blue_marble: use the blue_marble provided by basemap
            "path_to_file_name": This will use the warpimage function to use the image in the filename ... works with the blue marble stuff (https://visibleearth.nasa.gov/view_cat.php?categoryID=1484)
        plot_only_if_on_map: bool
            as the name says
        ax

        Returns
        -------

        """
        if isinstance(station_symbol_kwargs, type(None)):
            station_symbol_kwargs = {}
        if 'marker' not in station_symbol_kwargs:
            station_symbol_kwargs['marker'] = 'o'
        if 'markersize' not in station_symbol_kwargs:
            station_symbol_kwargs['markersize'] = 4
        if 'color' not in station_symbol_kwargs:
            station_symbol_kwargs['color'] = default_colors[1]
        if 'zorder' not in station_symbol_kwargs:
            station_symbol_kwargs['zorder'] = 100
            

        if bmap:
            # a = bmap.ax
            a = _plt.gca()
        else:
            if ax:
                a = ax
            else:
                f ,a = _plt.subplots()

            #         self.lat = 36.605700
            #         self.lon = -97.487846
            # self.lat = 78.5
            # self.lon = 18
            # width = 34000
            # height = 22000

            #         width = 400000 * 7
            #         height = 500000 * 3

            if center == 'auto':
                lat = self.lat
                lon = self.lon
            else:
                lat, lon = center

            bmap = _Basemap  (  # projection='laea',
                projection=projection,
                lat_0=lat,
                lon_0=lon,
                width=width,
                height=height,
                resolution=resolution,
                ax = a
            )
            # bmap.drawcoastlines()
            if background == 'blue_marble':
                bmap.bluemarble()
            elif isinstance(background, type(None)):
                pass
            else:
                assert(_os.path.isfile(background))
                bmap.warpimage(image=background)

            bmap.drawcountries(linewidth=2)
            bmap.drawstates()

        # out = bmap.fillcontinents()
        # wcal = np.array([161., 190., 255.]) / 255.
        # boundary = bmap.drawmapboundary(fill_color=wcal)

        lon, lat = self.lon, self.lat # Location Ny-Alesund 78°13′N 15°33′E
        # convert to map projection coords.
        # Note that lon,lat can be scalars, lists or numpy arrays.

        if plot_only_if_on_map:
            map_bound_path = _path.Path(_np.array([bmap.boundarylons, bmap.boundarylats]).transpose())
            if not map_bound_path.contains_point((lon, lat)):
                if verbose:
                    txt = 'Station {} was not plot, since it is not on the map.'.format(self.name)
                    print(txt)
                return a,bmap

        xpt ,ypt = bmap(lon ,lat)
        p, = bmap.plot(xpt ,ypt ,linestyle = '',**station_symbol_kwargs)
        # if site_label_color == 'auto':
        #     col = colors[1]
        # else:
        #     col = site_label_color

        # p.set_color(station_symbol_kwargs['color'])
        # p.set_markersize()

        # if station_label == 'abbr':
        #     label = self.abb
        # elif station_label == 'name':
        #     label = self.name
        # elif station_label == 'label':
        #     label = self.label
        # else:
        #     raise ValueError('{} is not an option for station_label'.format(station_label))


    # Station Label
        if station_label_kwargs != False:
            annodefaults = dict(xytext = (10, -10),
                                size = 10,
                                ha = "left",
                                va = 'top',
                                textcoords = 'offset points',
                                bbox = dict(boxstyle="round", fc=[1, 1, 1, 0.5], ec='black'),
                                zorder = 100
                                 )
            if isinstance(station_label_kwargs, type(None)):
                station_label_kwargs = {}

            for ak in annodefaults:
                if ak not in station_label_kwargs:
                    station_label_kwargs[ak] = annodefaults[ak]

            label = station_label_format.format(abbr=self.abb, name=self.name, state=self.state, country=self.country)


            a.annotate(label, xy=(xpt, ypt), **station_label_kwargs
                           #                 xycoords='data',
                           # xytext=(10 ,-10),
                           # size = station_annotation_kwargs['size'],
                           # ha="left",
                           # va = 'top',
                           # textcoords='offset points',
                           # bbox=dict(boxstyle="round", fc=[1 ,1 ,1 ,0.5], ec='black'),
                           )

    # return
        self._bmap = bmap
        self._xpt, self._ypt = xpt, ypt
        return a,bmap
コード例 #5
0
ファイル: burpfile.py プロジェクト: meteokid/python-rpn
def plot_burp(bf, code=None, cval=None, ax=None, level=0, mask=None, projection='cyl', cbar_opt={}, vals_opt={}, dparallel=30., dmeridian=60., fontsize=20, **kwargs):
    """
    Plots a BURP file. Will plot BUFR code if specified. Only plots a single level, 
    which can be specified by the optional argument. Additional arguments not listed
    below will be passes to Basemap.scatter.

    Parameters
    ----------
      bf           BurpFile instance
      code         code to be plotted, if not set the observation locations will be plotted
      level        level to be plotted
      mask         mask to apply to data
      cval         directly supply plotted values instead of using code argument
      ax           subplot object
      projection   projection used by Basemap for plotting
      cbar_opt     dictionary for colorbar options
      vals_opt     dictionary for get_rval options if code is supplied
      dparallel    spacing of parallels, if None will not plot parallels
      dmeridian    spacing of meridians, if None will not plot meridians
      fontsize     font size for labels of parallels and meridians

    Returns
    -------
      dictionary with keys:
        m          Basemap.scatter object used for plotting
        cbar       colorbar object if used
    """
    assert isinstance(bf, BurpFile), "First argument must be an instance of BurpFile"
    assert code is None or cval is None, "Only one of code, cval should be supplied as an argument"

    if ax is None:
        fig = _plt.figure(figsize=(18, 11))
        ax = fig.add_subplot(111)
    else:
        fig = ax.get_figure()

    if bf.nrep==0:
        return

    opt = kwargs.copy()
    if not 's' in opt.keys():
        opt['s'] = 10
    if not 'edgecolors' in opt.keys():
        opt['edgecolors'] = 'None'
    if not 'cmap' in opt.keys() and (code is not None or cval is not None):
        opt['cmap'] = _plt.cm.jet

    if code is not None:
        vals = bf.get_rval(code, **vals_opt)
        if len(vals.shape)>1:
            vals = vals[:, level]
        opt['c'] = vals
    elif cval is not None:
        opt['c'] = cval

    msk = _np.array([ stn[:2] for stn in bf.stnids ]) != '>>'  # don't plot resumes

    if not mask is None:
        msk = _np.logical_and(msk, mask)

    lon = bf.lon[msk]
    lat = bf.lat[msk]
    if code is not None or cval is not None:
        opt['c'] = opt['c'][msk]

    basemap_opt = {'projection':projection, 'resolution':'c'}

    if projection=='cyl':
        basemap_opt.update({'llcrnrlat':-90, 'urcrnrlat':90, 'llcrnrlon':-180, 'urcrnrlon':180})
    elif projection=='npstere':
        basemap_opt.update({'boundinglat':10., 'lon_0':0.})
    elif projection=='spstere':
        basemap_opt.update({'boundinglat':-10., 'lon_0':270.})

    m = _Basemap(ax=ax, **basemap_opt)

    m.drawcoastlines()

    xpt, ypt = m(lon, lat)

    sctr = m.scatter(xpt, ypt, **opt)

    if dparallel is not None:
        m.drawparallels(_np.arange(-90, 91, dparallel), labels=[1, 0, 0, 0], color='grey', fontsize=fontsize)
    if dmeridian is not None:
        m.drawmeridians(_np.arange(-180, 180, dmeridian), labels=[0, 0, 0, 1], color='grey', fontsize=fontsize)

    output = {'m':m}

    if code is not None or cval is not None:
        divider = _make_axes_locatable(ax)
        cax = divider.append_axes("right", size="2%", pad=0.5)
        cbar = fig.colorbar(sctr, ax=ax, cax=cax, **cbar_opt)
        output['cbar'] = cbar

    return output
コード例 #6
0
def plot_burp(bf,
              code=None,
              cval=None,
              ax=None,
              level=0,
              mask=None,
              projection='cyl',
              cbar_opt={},
              vals_opt={},
              dparallel=30.,
              dmeridian=60.,
              fontsize=20,
              **kwargs):
    """
    Plots a BURP file. Will plot BUFR code if specified. Only plots a single level,
    which can be specified by the optional argument. Additional arguments not listed
    below will be passes to Basemap.scatter.

    Args:
        bf         : BurpFile instance
        code       : code to be plotted, if not set the observation locations will be plotted
        level      : level to be plotted
        mask       : mask to apply to data
        cval       : directly supply plotted values instead of using code argument
        ax         : subplot object
        projection : projection used by Basemap for plotting
        cbar_opt   : dictionary for colorbar options
        vals_opt   : dictionary for get_rval options if code is supplied
        dparallel  : spacing of parallels, if None will not plot parallels
        dmeridian  : spacing of meridians, if None will not plot meridians
        fontsize   : font size for labels of parallels and meridians

    Returns:
        {
            'm'    : Basemap.scatter object used for plotting
            'cbar' : colorbar object if used
        }
    """
    assert isinstance(
        bf, BurpFile), "First argument must be an instance of BurpFile"
    assert code is None or cval is None, "Only one of code, cval should be supplied as an argument"

    if ax is None:
        fig = _plt.figure(figsize=(18, 11))
        ax = fig.add_subplot(111)
    else:
        fig = ax.get_figure()

    if bf.nrep == 0:
        return

    opt = kwargs.copy()
    if not 's' in opt.keys():
        opt['s'] = 10
    if not 'edgecolors' in opt.keys():
        opt['edgecolors'] = 'None'
    if not 'cmap' in opt.keys() and (code is not None or cval is not None):
        opt['cmap'] = _plt.cm.jet

    if code is not None:
        vals = bf.get_rval(code, **vals_opt)
        if len(vals.shape) > 1:
            vals = vals[:, level]
        opt['c'] = vals
    elif cval is not None:
        opt['c'] = cval

    msk = _np.array([stn[:2]
                     for stn in bf.stnids]) != '>>'  # don't plot resumes

    if not mask is None:
        msk = _np.logical_and(msk, mask)

    lon = bf.lon[msk]
    lat = bf.lat[msk]
    if code is not None or cval is not None:
        opt['c'] = opt['c'][msk]

    basemap_opt = {'projection': projection, 'resolution': 'c'}

    if projection == 'cyl':
        basemap_opt.update({
            'llcrnrlat': -90,
            'urcrnrlat': 90,
            'llcrnrlon': -180,
            'urcrnrlon': 180
        })
    elif projection == 'npstere':
        basemap_opt.update({'boundinglat': 10., 'lon_0': 0.})
    elif projection == 'spstere':
        basemap_opt.update({'boundinglat': -10., 'lon_0': 270.})

    m = _Basemap(ax=ax, **basemap_opt)

    m.drawcoastlines()

    xpt, ypt = m(lon, lat)

    sctr = m.scatter(xpt, ypt, **opt)

    if dparallel is not None:
        m.drawparallels(_np.arange(-90, 91, dparallel),
                        labels=[1, 0, 0, 0],
                        color='grey',
                        fontsize=fontsize)
    if dmeridian is not None:
        m.drawmeridians(_np.arange(-180, 180, dmeridian),
                        labels=[0, 0, 0, 1],
                        color='grey',
                        fontsize=fontsize)

    output = {'m': m}

    if code is not None or cval is not None:
        divider = _make_axes_locatable(ax)
        cax = divider.append_axes("right", size="2%", pad=0.5)
        cbar = fig.colorbar(sctr, ax=ax, cax=cax, **cbar_opt)
        output['cbar'] = cbar

    return output
コード例 #7
0
    def plot(
            self,
            projection='lcc',
            center='auto',
            width=400000 * 7,
            height=500000 * 3,
            abbriviate_name=True,
            resolution='c',
            background='blue_marble',
            station_symbol_kwargs=None,
            station_annotation_kwargs=None,
            # site_label_marker_size = 8,
            # site_label_font_size = 18,
            # site_label_color='auto',
            bmap=None,
            plot_only_if_on_map=False,
            ax=None,
            verbose=False):
        """

        Parameters
        ----------
        projection
        center: 'auto' or (lat, lon)
        width
        height
        abbriviate_name
        resolution
        background: str
            blue_marble: use the blue_marble provided by basemap
            "path_to_file_name": This will use the warpimage function to use the image in the filename ... works with the blue marble stuff (https://visibleearth.nasa.gov/view_cat.php?categoryID=1484)
        plot_only_if_on_map: bool
            as the name says
        ax

        Returns
        -------

        """
        if isinstance(station_symbol_kwargs, type(None)):
            station_symbol_kwargs = {}
        if 'marker' not in station_symbol_kwargs:
            station_symbol_kwargs['marker'] = 'o'
        if 'markersize' not in station_symbol_kwargs:
            station_symbol_kwargs['markersize'] = 8
        if 'color' not in station_symbol_kwargs:
            station_symbol_kwargs['color'] = default_colors[1]

        if isinstance(station_annotation_kwargs, type(None)):
            station_annotation_kwargs = {}
        if 'fontsize' not in station_annotation_kwargs:
            station_annotation_kwargs['size'] = 18

        if bmap:
            a = bmap.ax
        else:
            if ax:
                a = ax
            else:
                f, a = _plt.subplots()

            #         self.lat = 36.605700
            #         self.lon = -97.487846
            # self.lat = 78.5
            # self.lon = 18
            # width = 34000
            # height = 22000

            #         width = 400000 * 7
            #         height = 500000 * 3

            if center == 'auto':
                lat = self.lat
                lon = self.lon
            else:
                lat, lon = center

            bmap = _Basemap(  # projection='laea',
                projection=projection,
                lat_0=lat,
                lon_0=lon,
                width=width,
                height=height,
                resolution=resolution,
                ax=a)
            # bmap.drawcoastlines()
            if background == 'blue_marble':
                bmap.bluemarble()
            elif isinstance(background, type(None)):
                pass
            else:
                assert (_os.path.isfile(background))
                bmap.warpimage(image=background)

            bmap.drawcountries(linewidth=2)
            bmap.drawstates()

        # out = bmap.fillcontinents()
        # wcal = np.array([161., 190., 255.]) / 255.
        # boundary = bmap.drawmapboundary(fill_color=wcal)

        lon, lat = self.lon, self.lat  # Location Ny-Alesund 78°13′N 15°33′E
        # convert to map projection coords.
        # Note that lon,lat can be scalars, lists or numpy arrays.

        if plot_only_if_on_map:
            map_bound_path = _path.Path(
                _np.array([bmap.boundarylons, bmap.boundarylats]).transpose())
            if not map_bound_path.contains_point((lon, lat)):
                if verbose:
                    txt = 'Station {} was not plot, since it is not on the map.'.format(
                        self.name)
                    print(txt)
                return a, bmap

        xpt, ypt = bmap(lon, lat)
        p, = bmap.plot(xpt, ypt, linestyle='', **station_symbol_kwargs)
        # if site_label_color == 'auto':
        #     col = colors[1]
        # else:
        #     col = site_label_color

        # p.set_color(station_symbol_kwargs['color'])
        # p.set_markersize()

        if abbriviate_name:
            label = self.abb
        else:
            label = self.name
        a.annotate(
            label,
            xy=(xpt, ypt),
            #                 xycoords='data',
            xytext=(10, -10),
            size=station_annotation_kwargs['size'],
            ha="left",
            va='top',
            textcoords='offset points',
            bbox=dict(boxstyle="round", fc=[1, 1, 1, 0.5], ec='black'),
        )
        return a, bmap