def test_polygon_interiors():

    ax = plt.subplot(211, projection=ccrs.PlateCarree())
    ax.coastlines()
    ax.set_global()

    pth = Path([[0, -45], [60, -45], [60, 45], [0, 45], [0, 45],
                [10, -20], [10, 20], [40, 20], [40, -20], [10, 20]],
               [1, 2, 2, 2, 79, 1, 2, 2, 2, 79])

    patches_native = []
    patches = []
    for geos in cpatch.path_to_geos(pth):
        for pth in cpatch.geos_to_path(geos):
            patches.append(mpatches.PathPatch(pth))

        # buffer by 10 degrees (leaves a small hole in the middle)
        geos_buffered = geos.buffer(10)
        for pth in cpatch.geos_to_path(geos_buffered):
            patches_native.append(mpatches.PathPatch(pth))

    # Set high zorder to ensure the polygons are drawn on top of coastlines.
    collection = PatchCollection(patches_native, facecolor='red', alpha=0.4,
                                 transform=ax.projection, zorder=10)
    ax.add_collection(collection)

    collection = PatchCollection(patches, facecolor='yellow', alpha=0.4,
                                 transform=ccrs.Geodetic(), zorder=10)

    ax.add_collection(collection)

    # test multiple interior polygons
    ax = plt.subplot(212, projection=ccrs.PlateCarree(),
                     xlim=[-5, 15], ylim=[-5, 15])
    ax.coastlines()

    exterior = np.array(sgeom.box(0, 0, 12, 12).exterior.coords)
    interiors = [np.array(sgeom.box(1, 1, 2, 2, ccw=False).exterior.coords),
                 np.array(sgeom.box(1, 8, 2, 9, ccw=False).exterior.coords)]
    poly = sgeom.Polygon(exterior, interiors)

    patches = []
    for pth in cpatch.geos_to_path(poly):
        patches.append(mpatches.PathPatch(pth))

    collection = PatchCollection(patches, facecolor='yellow', alpha=0.4,
                                 transform=ccrs.Geodetic(), zorder=10)
    ax.add_collection(collection)
Example #2
0
def test_polygon_interiors():

    ax = plt.subplot(211, projection=ccrs.PlateCarree())
    ax.coastlines()
    ax.set_global()  # XXX could be the default???

    pth = Path([[0, -45], [60, -45], [60, 45], [0, 45], [0, 45],
                [10, -20], [10, 20], [40, 20], [40, -20], [10, 20]],
               [1, 2, 2, 2, 79, 1, 2, 2, 2, 79])

    patches_native = []
    patches = []
    for geos in cpatch.path_to_geos(pth):
        for pth in cpatch.geos_to_path(geos):
            patches.append(mpatches.PathPatch(pth))

        # buffer by 10 degrees (leaves a small hole in the middle)
        geos_buffered = geos.buffer(10)
        for pth in cpatch.geos_to_path(geos_buffered):
            patches_native.append(mpatches.PathPatch(pth))

    # Set high zorder to ensure the polygons are drawn on top of coastlines.
    collection = PatchCollection(patches_native, facecolor='red', alpha=0.4,
                                 transform=ax.projection, zorder=10)
    ax.add_collection(collection)

    collection = PatchCollection(patches, facecolor='yellow', alpha=0.4,
                                 transform=ccrs.Geodetic(), zorder=10)

    ax.add_collection(collection)

    # test multiple interior polygons
    ax = plt.subplot(212, projection=ccrs.PlateCarree(),
                     xlim=[-5, 15], ylim=[-5, 15])
    ax.coastlines()

    exterior = np.array(sgeom.box(0, 0, 12, 12).exterior.coords)
    interiors = [np.array(sgeom.box(1, 1, 2, 2, ccw=False).exterior.coords),
                 np.array(sgeom.box(1, 8, 2, 9, ccw=False).exterior.coords)]
    poly = sgeom.Polygon(exterior, interiors)

    patches = []
    for pth in cpatch.geos_to_path(poly):
        patches.append(mpatches.PathPatch(pth))

    collection = PatchCollection(patches, facecolor='yellow', alpha=0.4,
                                 transform=ccrs.Geodetic(), zorder=10)
    ax.add_collection(collection)
Example #3
0
 def set_subplot_map(self, highlights, cgeorange):
     ###SUBPLOT: SET MAP
     self.oldax = self.p.ax
     self.p.ax = self.p.fig.add_axes([0.02, -0.39, 1.04, 0.44])
     self.p.setmap(projection='cyl', georange=cgeorange, resolution='i')
     self.p.draw('country coastline province city')
     ###SUBPLOT: HIGHLIGHT COASTLINES & PLOT LEGEND
     colors = ['#AAFFAA', '#FFFF44', '#FF3333', '#BB0044']
     descr = ['10~25%', '25~50%', '50~75%', '>75%']
     handles = []
     for i, clr in enumerate(colors, 0):
         patch = PathCollection(geos_to_path(
             MultiLineString(highlights[i]).buffer(self.buffersize)),
                                facecolor=clr)
         self.p.ax.add_collection(patch)
         handles.append(Patch(color=clr, label=descr[i]))
     self.p.ax.text(0.98,
                    0.27,
                    '中心经过1经纬度\n范围内的几率',
                    transform=self.p.ax.transAxes,
                    va='bottom',
                    ha='right',
                    fontsize=6,
                    family='Source Han Sans CN')
     self.p.legend(handles=handles, loc='lower right', framealpha=0.8)
Example #4
0
def tissot(rads_km=None, lons=None, lats=None, n_samples=80, globe=None, ax=None, draw=False, **kwargs):
    import numpy as np
    import cartopy.crs as ccrs
    import cartopy.feature as feature
    import shapely.geometry as sgeom
    from cartopy import geodesic
    import cartopy.mpl.patch as cpatch

    geod = geodesic.Geodesic(radius=globe.semimajor_axis, flattening=globe.flattening)
    geoms = []

    rads_km = np.asarray(rads_km)
    lons = np.asarray(lons)
    lats = np.asarray(lats)

    for i in range(len(lons)):
        circle = geod.circle(lons[i], lats[i], rads_km[i],
                             n_samples=n_samples)
        geoms.append(sgeom.Polygon(circle))

    polys = cpatch.geos_to_path(geoms)

    if draw:
        if ax==None: ax = plt.gca()
        f = feature.ShapelyFeature(geoms, ccrs.Geodetic(globe=globe),
                                       **kwargs)
        ax.add_feature(f)

    return polys
Example #5
0
def show(projection, geometry):
    orig_backend = mpl.get_backend()
    plt.switch_backend('tkagg')

    if geometry.type == 'MultiPolygon' and 1:
        multi_polygon = geometry
        for polygon in multi_polygon:
            import cartopy.mpl.patch as patch
            paths = patch.geos_to_path(polygon)
            for pth in paths:
                patch = mpatches.PathPatch(pth,
                                           edgecolor='none',
                                           lw=0,
                                           alpha=0.2)
                plt.gca().add_patch(patch)
            line_string = polygon.exterior
            plt.plot(*zip(*line_string.coords), marker='+', linestyle='-')
    elif geometry.type == 'MultiPolygon':
        multi_polygon = geometry
        for polygon in multi_polygon:
            line_string = polygon.exterior
            plt.plot(*zip(*line_string.coords), marker='+', linestyle='-')

    elif geometry.type == 'MultiLineString':
        multi_line_string = geometry
        for line_string in multi_line_string:
            plt.plot(*zip(*line_string.coords), marker='+', linestyle='-')

    elif geometry.type == 'LinearRing':
        plt.plot(*zip(*geometry.coords), marker='+', linestyle='-')

    if 1:
        # Whole map domain
        plt.autoscale()
    elif 0:
        # The left-hand triangle
        plt.xlim(-1.65e7, -1.2e7)
        plt.ylim(0.3e7, 0.65e7)
    elif 0:
        # The tip of the left-hand triangle
        plt.xlim(-1.65e7, -1.55e7)
        plt.ylim(0.3e7, 0.4e7)
    elif 1:
        # The very tip of the left-hand triangle
        plt.xlim(-1.632e7, -1.622e7)
        plt.ylim(0.327e7, 0.337e7)
    elif 1:
        # The tip of the right-hand triangle
        plt.xlim(1.55e7, 1.65e7)
        plt.ylim(0.3e7, 0.4e7)

    plt.plot(*zip(*projection.boundary.coords),
             marker='o',
             scalex=False,
             scaley=False,
             zorder=-1)

    plt.show()
    plt.switch_backend(orig_backend)
Example #6
0
def show(projection, geometry):
    orig_backend = mpl.get_backend()
    plt.switch_backend('tkagg')

    if geometry.type == 'MultiPolygon' and 1:
        multi_polygon = geometry
        for polygon in multi_polygon:
            import cartopy.mpl.patch as patch
            paths = patch.geos_to_path(polygon)
            for pth in paths:
                patch = mpatches.PathPatch(pth, edgecolor='none',
                                           lw=0, alpha=0.2)
                plt.gca().add_patch(patch)
            line_string = polygon.exterior
            plt.plot(*zip(*line_string.coords),
                     marker='+', linestyle='-')
    elif geometry.type == 'MultiPolygon':
        multi_polygon = geometry
        for polygon in multi_polygon:
            line_string = polygon.exterior
            plt.plot(*zip(*line_string.coords),
                     marker='+', linestyle='-')

    elif geometry.type == 'MultiLineString':
        multi_line_string = geometry
        for line_string in multi_line_string:
            plt.plot(*zip(*line_string.coords),
                     marker='+', linestyle='-')

    elif geometry.type == 'LinearRing':
        plt.plot(*zip(*geometry.coords), marker='+', linestyle='-')

    if 1:
        # Whole map domain
        plt.autoscale()
    elif 0:
        # The left-hand triangle
        plt.xlim(-1.65e7, -1.2e7)
        plt.ylim(0.3e7, 0.65e7)
    elif 0:
        # The tip of the left-hand triangle
        plt.xlim(-1.65e7, -1.55e7)
        plt.ylim(0.3e7, 0.4e7)
    elif 1:
        # The very tip of the left-hand triangle
        plt.xlim(-1.632e7, -1.622e7)
        plt.ylim(0.327e7, 0.337e7)
    elif 1:
        # The tip of the right-hand triangle
        plt.xlim(1.55e7, 1.65e7)
        plt.ylim(0.3e7, 0.4e7)

    plt.plot(*zip(*projection.boundary.coords), marker='o',
             scalex=False, scaley=False, zorder=-1)

    plt.show()
    plt.switch_backend(orig_backend)
Example #7
0
def draw_polygon(projection, polygon, color=None):
    multi_polygon = projection.project_geometry(polygon)
    for polygon in multi_polygon:
        #plt.plot(*zip(*polygon.exterior.coords), marker='+', color=color)
        #_arrows(projection, polygon.exterior)
        #continue
        import cartopy.mpl.patch as patch
        paths = patch.geos_to_path(polygon)
        for pth in paths:
            patch = mpatches.PathPatch(pth, edgecolor='none',
                                       alpha=0.5, facecolor=color, lw=0)
            plt.gca().add_patch(patch)
Example #8
0
    def maskcountries(self,
                      conf,
                      ax=None,
                      regions=["China"],
                      pathkw=dict(facecolor='none',
                                  edgecolor='black',
                                  linewidth=1.5)):
        """
        在cartopy中, 对选定的国家进行白化.
        refer to https://cloud.tencent.com/developer/article/1618341

        Args:
            conf (matplotlib object): matplotlib的contour或contourf绘图返回值.
            ax (object, optional): Axes instance, if not None then overrides the default axes instance.
            regions (list, optional): 指定无需白化的国家. Defaults to ["China"].
            pathkw (dict, optional): PathPatch关键字参数. Defaults to dict(facecolor='none',edgecolor='black', linewidth=1.0).

        Returns:
            clipping path, matplotlib.patches.PathPatch
        """

        #Get current axes if not specified
        ax = ax or self._check_ax()

        #Convert region name to upper
        regions = list(regions)
        regions = [region.upper() for region in regions]

        # get shape file
        shpfile = pkg_resources.resource_filename(
            'nmc_met_graphics', "resources/maps/country1.shp")

        # retrive region geometry
        reader = Reader(shpfile)
        countries = reader.records()
        multipoly, = [
            country.geometry for country in countries
            if country.attributes['CNTRY_NAME'].upper() in regions
        ]

        main_geom = sorted(multipoly.geoms, key=lambda geom: geom.area)[-1]

        path, = geos_to_path(main_geom)

        plate_carre_data_transform = ccrs.PlateCarree()._as_mpl_transform(ax)

        for collection in conf.collections:
            collection.set_clip_path(path, plate_carre_data_transform)

        # Draw the path of interest.
        path = PathPatch(path, transform=ccrs.PlateCarree(), **pathkw)
        return path
Example #9
0
    def draw(self, renderer, *args, **kwargs):
        """
        Draws the geometries of the feature that intersect with the extent of
        the :class:`cartopy.mpl.GeoAxes` instance to which this
        object has been added.

        """
        if not self.get_visible():
            return

        ax = self.get_axes()
        feature_crs = self._feature.crs

        # Get geometries that we need to draw.
        extent = None
        try:
            extent = ax.get_extent(feature_crs)
        except ValueError:
            warnings.warn('Unable to determine extent. Defaulting to global.')
        geoms = self._feature.intersecting_geometries(extent)

        # Project (if necessary) and convert geometries to matplotlib paths.
        paths = []
        key = ax.projection
        for geom in geoms:
            mapping = FeatureArtist._geometry_to_path_cache.setdefault(geom,
                                                                       {})
            geom_paths = mapping.get(key)
            if geom_paths is None:
                if ax.projection != feature_crs:
                    projected_geom = ax.projection.project_geometry(
                        geom, feature_crs)
                else:
                    projected_geom = geom
                geom_paths = cpatch.geos_to_path(projected_geom)
                mapping[key] = geom_paths
            paths.extend(geom_paths)

        # Build path collection and draw it.
        transform = ax.projection._as_mpl_transform(ax)
        # Combine all the keyword args in priority order
        final_kwargs = dict(self._feature.kwargs)
        final_kwargs.update(self._kwargs)
        final_kwargs.update(kwargs)
        c = matplotlib.collections.PathCollection(paths,
                                                  transform=transform,
                                                  **final_kwargs)
        c.set_clip_path(ax.patch)
        c.set_figure(ax.figure)
        return c.draw(renderer)
Example #10
0
    def draw(self, renderer, *args, **kwargs):
        """
        Draws the geometries of the feature that intersect with the extent of
        the :class:`cartopy.mpl.GeoAxes` instance to which this
        object has been added.

        """
        if not self.get_visible():
            return

        ax = self.get_axes()
        feature_crs = self._feature.crs

        # Get geometries that we need to draw.
        extent = None
        try:
            extent = ax.get_extent(feature_crs)
        except ValueError:
            warnings.warn('Unable to determine extent. Defaulting to global.')
        geoms = self._feature.intersecting_geometries(extent)

        # Project (if necessary) and convert geometries to matplotlib paths.
        paths = []
        key = ax.projection
        for geom in geoms:
            mapping = FeatureArtist._geometry_to_path_cache.setdefault(
                geom, {})
            geom_paths = mapping.get(key)
            if geom_paths is None:
                if ax.projection != feature_crs:
                    projected_geom = ax.projection.project_geometry(
                        geom, feature_crs)
                else:
                    projected_geom = geom
                geom_paths = cpatch.geos_to_path(projected_geom)
                mapping[key] = geom_paths
            paths.extend(geom_paths)

        # Build path collection and draw it.
        transform = ax.projection._as_mpl_transform(ax)
        # Combine all the keyword args in priority order
        final_kwargs = dict(self._feature.kwargs)
        final_kwargs.update(self._kwargs)
        final_kwargs.update(kwargs)
        c = matplotlib.collections.PathCollection(paths,
                                                  transform=transform,
                                                  **final_kwargs)
        c.set_clip_path(ax.patch)
        c.set_figure(ax.figure)
        return c.draw(renderer)
Example #11
0
def add_feature3d(ax, feature, clip_geom=None, zs=None):
    """
    Add the given feature to the given axes.
    """
    concat = lambda iterable: list(itertools.chain.from_iterable(iterable))

    target_projection = ax.projection

    if hasattr(feature, 'geometries'):
        # cartopy.feature.Feature
        feature_hook = feature
    elif hasattr(feature._feature, 'geometries'):
        # cartopy.feature_artist.FeatureArtist ?
        feature_hook = feature._feature
    else:
        raise RuntimeError('problem with feature: %s' % type(feature))

    geoms = list(feature_hook.geometries())

    if target_projection != feature_hook.crs:
        # Transform the geometries from the feature's CRS into the
        # desired projection.
        geoms = [
            target_projection.project_geometry(geom, feature_hook.crs)
            for geom in geoms
        ]

    if clip_geom:
        # Clip the geometries based on the extent of the map (because mpl3d
        # can't do it for us)
        geoms = [geom.intersection(clip_geom) for geom in geoms]

    # Convert the geometries to paths so we can use them in matplotlib.
    paths = concat(geos_to_path(geom) for geom in geoms)

    # Bug: mpl3d can't handle edgecolor='face'
    kwargs = feature_hook.kwargs
    if kwargs.get('edgecolor') == 'face':
        kwargs['edgecolor'] = kwargs['facecolor']

    polys = concat(path.to_polygons(closed_only=False) for path in paths)

    if kwargs.get('facecolor', 'none') == 'none':
        lc = mcoll.LineCollection(polys, **kwargs)
    else:
        lc = mcoll.PolyCollection(polys, closed=False, **kwargs)

    #ax.add_collection3d(lc, zs=zs)
    add_fixzordercollection3d(ax, lc, zs=zs)
Example #12
0
    def _boundary(self):
        """
        Adds the map's boundary.

        Note:

            The boundary is not the axes.patch, which provides rectilinear
            clipping for all of the map's artists.

        The axes.patch will have its visibility set to False inside
        GeoAxes.gca()
        """
        import cartopy.mpl.patch as p
        path, = p.geos_to_path(self.projection.boundary)

#        from matplotlib.collections import PatchCollection

        sct = SimpleClippedTransform(self.transScale + self.transLimits,
                                     self.transAxes)

        # XXX Should be exactly one path...
        collection = mpatches.PathPatch(path,
                                        facecolor='none', edgecolor='k',
                                        zorder=1000,
                                        # transform=self.transData,
                                        transform=sct, clip_on=False,
                                        )
        self.outline_patch = collection
        # XXX autolim = False
        self.add_patch(collection)

        # put a color patch for background color
        # XXX Should be exactly one path...
        collection = mpatches.PathPatch(path,
                                        facecolor='w', edgecolor='none',
                                        zorder=-1, transform=sct,
                                        clip_on=False,
                                        )
        self.background_patch = collection
        # XXX autolim = False
        self.add_patch(collection)

        self.patch.set_facecolor((1, 1, 1, 0))
        self.patch.set_edgecolor((0.5, 0.5, 0.5))
        self.patch.set_linewidth(0.0)
Example #13
0
def crsmask(ax, conf, crs, shpfile=None, region='China', 
            attribute_name='CNTRY_NAME', pathkw=None):
    """
    在cartopy中, 对选定的区域进行白化.
    refer to https://cloud.tencent.com/developer/article/1618341
    TODO: 如果Cartopy设置set_extent, 显示的图像不会剪裁外部等值线, 还未找到有效解决办法.

    Args:
        shpfile (string): 用于白化区域的shapefile文件名.
        region (string): shpfile中包含的区域名.
        ax (GeoAxes instance): cartopy的坐标轴实例
        crs (cartopy.crs): cartopy坐标投影
        conf (matplotlib): matplotlib的contour或contourf绘图返回值
        pathkw (dict, optional): PathPatch关键字参数. Defaults to None.

    Return:
        clipping path, matplotlib.patches.PathPatch
    """

    # get shape file
    if shpfile is None:
        shpfile = pkg_resources.resource_filename(
            'nmc_met_graphics', "resources/maps/country1.shp")
    
    # retrive region geometry
    reader = shapereader.Reader(shpfile)
    countries = reader.records()
    multipoly, = [country.geometry for country in countries
                    if country.attributes['CNTRY_NAME'] == region]
                        
    main_geom = sorted(multipoly.geoms, key=lambda geom: geom.area)[-1]

    path, = geos_to_path(main_geom)

    plate_carre_data_transform = crs._as_mpl_transform(ax)

    for collection in conf.collections:
        collection.set_clip_path(path, plate_carre_data_transform)
    
    # Draw the path of interest.
    path = PathPatch(path, transform = crs, **pathkw)
    
    return path
Example #14
0
 def add_storm(self, storm):
     count = self.grid.copy()
     length = NUM_OF_MEMS
     name = storm.get_fullname()
     i = 0
     for code in storm.iter_members():
         linestring = list(zip(storm.lons, storm.lats))
         if len(linestring) < 2:
             continue
         path = geos_to_path(LineString(linestring).buffer(RADIUS))[0]
         boolarr = path.contains_points(self.xy).reshape(
             (self.yshape, self.xshape)).astype(np.uint8)
         count += boolarr
         i += 1
         print('\r{:s}: [{: <10s}] {:.0%}'.format(name,
                                                  '#' * (i * 10 // length),
                                                  i / length),
               end='')
     print()
     return count
Example #15
0
lon_formatter = LongitudeFormatter(zero_direction_label=True)
lat_formatter = LatitudeFormatter()
ax.xaxis.set_major_formatter(lon_formatter)
ax.yaxis.set_major_formatter(lat_formatter)
#刻度字体大小
ax.tick_params(labelsize=15)

contourf = ax.contourf(lon,lat,u1_avg,lev,cmap='Blues',transform=proj,extend='both')

countries = shp.records()
cn_multipoly, = [country.geometry for country in countries
                 if country.attributes['CNTRY_NAME'] == 'China']  # 选择地图属性下'NAME'属性里名字是'China'的一条多边形

paths = []
for i in range(len(cn_multipoly)):
    cn_geom, = geos_to_path(cn_multipoly.geoms[i])
    paths.append(cn_geom)

path = Path.make_compound_path(*paths)
for collection in contourf.collections:
    collection.set_clip_path(path, proj._as_mpl_transform(ax))

# 白化刻度
# contour = ax.contour(lon,lat,u1_avg,lev,cmap='Blues',transform=proj,extend='both')
# cn_label = plt.clabel(contour,inline=1,fontsize=10,fmt="%.fr")
# if cn_label:
#     clip_map_shapely = Polygon(path.vertices)
#     for text_object in cn_label:
#         if not clip_map_shapely.contains(Point(text_object.get_position())):
#             text_object.set_visible(False)
Example #16
0
    def draw(self, renderer, *args, **kwargs):
        """
        Draws the geometries of the feature that intersect with the extent of
        the :class:`cartopy.mpl.GeoAxes` instance to which this
        object has been added.

        """
        if not self.get_visible():
            return

        ax = self.axes
        feature_crs = self._feature.crs

        # Get geometries that we need to draw.
        extent = None
        try:
            extent = ax.get_extent(feature_crs)
        except ValueError:
            warnings.warn('Unable to determine extent. Defaulting to global.')
        geoms = self._feature.intersecting_geometries(extent)

        # Project (if necessary) and convert geometries to matplotlib paths.
        paths = []
        key = ax.projection
        for geom in geoms:
            # As Shapely geometries cannot be relied upon to be
            # hashable, we have to use a WeakValueDictionary to manage
            # their weak references. The key can then be a simple,
            # "disposable", hashable geom-key object that just uses the
            # id() of a geometry to determine equality and hash value.
            # The only persistent, strong reference to the geom-key is
            # in the WeakValueDictionary, so when the geometry is
            # garbage collected so is the geom-key.
            # The geom-key is also used to access the WeakKeyDictionary
            # cache of transformed geometries. So when the geom-key is
            # garbage collected so are the transformed geometries.
            geom_key = _GeomKey(geom)
            FeatureArtist._geom_key_to_geometry_cache.setdefault(
                geom_key, geom)
            mapping = FeatureArtist._geom_key_to_path_cache.setdefault(
                geom_key, {})
            geom_paths = mapping.get(key)
            if geom_paths is None:
                if ax.projection != feature_crs:
                    projected_geom = ax.projection.project_geometry(
                        geom, feature_crs)
                else:
                    projected_geom = geom
                geom_paths = cpatch.geos_to_path(projected_geom)
                mapping[key] = geom_paths
            paths.extend(geom_paths)

        # Build path collection and draw it.
        transform = ax.projection._as_mpl_transform(ax)
        # Combine all the keyword args in priority order
        final_kwargs = dict(self._feature.kwargs)
        final_kwargs.update(self._kwargs)
        final_kwargs.update(kwargs)
        c = matplotlib.collections.PathCollection(paths,
                                                  transform=transform,
                                                  **final_kwargs)
        c.set_clip_path(ax.patch)
        c.set_figure(ax.figure)
        return c.draw(renderer)
Example #17
0
    def draw(self, renderer, *args, **kwargs):
        """
        Draw the geometries of the feature that intersect with the extent of
        the :class:`cartopy.mpl.GeoAxes` instance to which this
        object has been added.

        """
        if not self.get_visible():
            return

        ax = self.axes
        feature_crs = self._feature.crs

        # Get geometries that we need to draw.
        extent = None
        try:
            extent = ax.get_extent(feature_crs)
        except ValueError:
            warnings.warn('Unable to determine extent. Defaulting to global.')
        geoms = self._feature.intersecting_geometries(extent)

        # Project (if necessary) and convert geometries to matplotlib paths.
        paths = []
        key = ax.projection
        for geom in geoms:
            # As Shapely geometries cannot be relied upon to be
            # hashable, we have to use a WeakValueDictionary to manage
            # their weak references. The key can then be a simple,
            # "disposable", hashable geom-key object that just uses the
            # id() of a geometry to determine equality and hash value.
            # The only persistent, strong reference to the geom-key is
            # in the WeakValueDictionary, so when the geometry is
            # garbage collected so is the geom-key.
            # The geom-key is also used to access the WeakKeyDictionary
            # cache of transformed geometries. So when the geom-key is
            # garbage collected so are the transformed geometries.
            geom_key = _GeomKey(geom)
            FeatureArtist._geom_key_to_geometry_cache.setdefault(
                geom_key, geom)
            mapping = FeatureArtist._geom_key_to_path_cache.setdefault(
                geom_key, {})
            geom_paths = mapping.get(key)
            if geom_paths is None:
                if ax.projection != feature_crs:
                    projected_geom = ax.projection.project_geometry(
                        geom, feature_crs)
                else:
                    projected_geom = geom
                geom_paths = cpatch.geos_to_path(projected_geom)
                mapping[key] = geom_paths
            paths.extend(geom_paths)

        # Build path collection and draw it.
        transform = ax.projection._as_mpl_transform(ax)
        # Combine all the keyword args in priority order
        final_kwargs = dict(self._feature.kwargs)
        final_kwargs.update(self._kwargs)
        final_kwargs.update(kwargs)
        c = matplotlib.collections.PathCollection(paths,
                                                  transform=transform,
                                                  **final_kwargs)
        c.set_clip_path(ax.patch)
        c.set_figure(ax.figure)
        return c.draw(renderer)
Example #18
0
    def transform_path_non_affine(self, src_path):
        """
        Transforms from source to target coordinates.

        Caches results, so subsequent calls with the same *src_path* argument
        (and the same source and target projections) are faster.

        Args:

            * src_path - A matplotlib :class:`~matplotlib.path.Path` object
                         with vertices in source coordinates.

        Returns

            * A matplotlib :class:`~matplotlib.path.Path` with vertices
              in target coordinates.

        """
        mapping = _PATH_TRANSFORM_CACHE.get(src_path)
        if mapping is not None:
            key = (self.source_projection, self.target_projection)
            result = mapping.get(key)
            if result is not None:
                return result

        # Allow the vertices to be quickly transformed, if
        # quick_vertices_transform allows it.
        new_vertices = self.target_projection.quick_vertices_transform(
            src_path.vertices, self.source_projection)
        if new_vertices is not None:
            if new_vertices is src_path.vertices:
                return src_path
            else:
                return mpath.Path(new_vertices, src_path.codes)

        if src_path.vertices.shape == (1, 2):
            return mpath.Path(self.transform(src_path.vertices))

        transformed_geoms = []
        for geom in patch.path_to_geos(src_path):
            transformed_geoms.append(
                self.target_projection.project_geometry(geom,
                                                        self.source_projection)
            )

        if not transformed_geoms:
            result = mpath.Path(np.empty([0, 2]))
        else:
            paths = patch.geos_to_path(transformed_geoms)
            if not paths:
                return mpath.Path(np.empty([0, 2]))
            points, codes = zip(*[patch.path_segments(path, curves=False,
                                                      simplify=False)
                                  for path in paths])
            result = mpath.Path(np.concatenate(points, 0),
                                np.concatenate(codes))

        # store the result in the cache for future performance boosts
        key = (self.source_projection, self.target_projection)
        if mapping is None:
            _PATH_TRANSFORM_CACHE[src_path] = {key: result}
        else:
            mapping[key] = result

        return result
# Define the contour levels (T)
clevs = np.arange(228, 273, 4, dtype=float)

# Import an NCL colormap, truncating it by using geocat.viz.util convenience function
newcmp = gvutil.truncate_colormap(gvcmaps.BkBlAqGrYeOrReViWh200,
                                  minval=0.1,
                                  maxval=0.6,
                                  n=len(clevs))

# Draw the contour plot, "clipped" to the country boundaries
# (NOTE: There are multiple closed polygons representing the boundaries of the
#        countries.  This is both because there are 2 country borders being used
#        to clip the contour plot, but also because China consists of many islands.
#        As a result, we have to loop over *all closed paths* and construct a
#        matplotlib patch object that we can use the clip the contour plot.)
for path in geos_to_path(country_geos):
    patch = PathPatch(path,
                      transform=ax.transData,
                      facecolor='none',
                      edgecolor='black',
                      lw=1.5)

    # Draw the patch on the plot
    ax.add_patch(patch)

    # Draw the contour plot
    # (NOTE: Because this line is in the loop over closed paths, the contour plot
    #        is being drawn for each closed path.  This has to be done because
    #        matplotlib cannot apply *multiple* closed paths at the same time to
    #        to the same plot.  Hence, for each closed path, we need to generate
    #        another contour plot and clip that contour plot with the patch.  In
Example #20
0
    def plot_3D(self, event=None):
        '''Plot observation QC values on a global 2D map

        Keyword arguments:
        event -- an argument passed by any tkiner menu event. Has no influence on output but
        tkinter requires it to be passed to any method called by a menu event

        '''

        qc = [
            np.int64(self.qc_menu.get(val).split(": ", 1)[1][0])
            for val in self.qc_menu.curselection()
        ]

        #make figure and canvas to draw on
        fig = Figure(figsize=(12, 8))
        #ax = fig.add_axes([0.01, 0.01, 0.98, 0.98], projection = ccrs.PlateCarree())
        canvas = FigureCanvasTkAgg(fig, master=self.main_frame)
        canvas.get_tk_widget().grid(column=1,
                                    row=1,
                                    rowspan=4,
                                    sticky="N, S, E, W")

        #have to set up a separate toolbar frame because toolbar doesn't like gridding with others
        self.toolbar_frame = ttk.Frame(self.main_frame)
        self.toolbar = NavigationToolbar2TkAgg(canvas, self.toolbar_frame)
        self.toolbar_frame.grid(column=1, row=5, sticky="N, S, E, W")
        self.toolbar.grid(column=1, row=1, sticky="N, S, E, W")
        #resizing
        self.toolbar_frame.grid_columnconfigure(1, weight=1)
        self.toolbar_frame.grid_rowconfigure(1, weight=1)

        #disable part of the coordinate display functionality, else everything flickers (may need for smaller window)
        #ax.format_coord = lambda x, y: ''

        data = self.plotter.filter(self.data_qc, ('qc_DART', qc))

        target_projection = ccrs.PlateCarree()

        #weird redundant line that works for transformation
        transform = target_projection.transform_points(target_projection,
                                                       data.lons.values,
                                                       data.lats.values)

        lons, lats = transform[:, 0], transform[:, 1]

        concat = lambda iterable: list(itertools.chain.from_iterable(iterable))

        feature = cartopy.feature.NaturalEarthFeature('Physical', 'land',
                                                      '110m')

        geoms = feature.geometries()

        geoms = [
            target_projection.project_geometry(geom, feature.crs)
            for geom in geoms
        ]

        paths = concat(geos_to_path(geom) for geom in geoms)

        polys = concat(path.to_polygons() for path in paths)

        ax = Axes3D(fig, [0.02, 0.02, 0.97, 0.97],
                    xlim=[-180, 180],
                    ylim=[-90, 90])

        z_max = max(data.z.values)

        #deal with orientation of graph for different vert types
        if data.vert_types.values[0] < 0 or data.vert_types.values[0] == 3:
            #surface, heights, or unknown units where up is positive direction
            #don't need to do 3D polygons since it will plot 2D polygons at z = 0 by default
            lc = PolyCollection(polys,
                                edgecolor='black',
                                facecolor='green',
                                closed=False)
            ax.set_zlim(bottom=0, top=z_max)
            ax.add_collection3d(lc)
        else:
            #level or pressure units where down is positive direction
            polys = [[(point[0], point[1], z_max) for point in shape]
                     for shape in polys]
            lc = Poly3DCollection(polys,
                                  edgecolor='black',
                                  facecolor='green',
                                  closed=False)
            ax.set_zlim(bottom=z_max, top=0)
            ax.add_collection3d(lc)

        plot_values = None
        cmap = None
        max_value = None
        min_value = None

        #colormap for QC values
        if self.val_type.get() == 'QC':
            cmap = plt.get_cmap('gist_ncar', 9)
            plot_values = data.qc_DART
            max_value = 8
            min_value = 0
        elif self.val_type.get() == 'Observation value':
            cmap = plt.get_cmap('jet', np.unique(data.values).size)
            plot_values = data.values.ravel()
            max_value = max(plot_values)
            min_value = min(plot_values)

        #plot each observation type separately to get differing edge colors and markers

        ax.scatter(lons,
                   lats,
                   data.z,
                   c=plot_values,
                   cmap=cmap,
                   vmin=min_value,
                   vmax=max_value,
                   s=35,
                   alpha=0.5)

        #make color bar
        sm = plt.cm.ScalarMappable(cmap=cmap,
                                   norm=plt.Normalize(0, max_value + 1))
        sm._A = []
        cbar = plt.colorbar(sm, ax=ax, orientation='horizontal', pad=0.04)

        #set up color bar title according to plot type
        if self.val_type.get() == 'QC':

            cbar.ax.set_xlabel('DART QC Value')
            #also center colorbar ticks and labels
            labels = np.arange(0, max_value + 1, 1)
            loc = labels + 0.5
            cbar.set_ticks(loc)
            cbar.set_ticklabels(labels)

        elif self.val_type.get() == 'Observation value':

            #get observation name
            cbar.ax.set_xlabel(
                self.obs_menu.get(self.obs_menu.curselection()).split(
                    " : ", 1)[1])

        ax.set_aspect('auto')
        #ax.margins(0.5, tight = False)
        s = ttk.Style()
        s.theme_use('clam')
Example #21
0
    def draw(self, renderer, *args, **kwargs):
        """
        Draw the geometries of the feature that intersect with the extent of
        the :class:`cartopy.mpl.GeoAxes` instance to which this
        object has been added.

        """
        if not self.get_visible():
            return

        ax = self.axes
        feature_crs = self._feature.crs

        # Get geometries that we need to draw.
        extent = None
        try:
            extent = ax.get_extent(feature_crs)
        except ValueError:
            warnings.warn('Unable to determine extent. Defaulting to global.')
        geoms = self._feature.intersecting_geometries(extent)

        # Combine all the keyword args in priority order.
        prepared_kwargs = style_merge(self._feature.kwargs, self._kwargs,
                                      kwargs)

        # Freeze the kwargs so that we can use them as a dict key. We will
        # need to unfreeze this with dict(frozen) before passing to mpl.
        prepared_kwargs = _freeze(prepared_kwargs)

        # Project (if necessary) and convert geometries to matplotlib paths.
        stylised_paths = OrderedDict()
        key = ax.projection
        for geom in geoms:
            # As Shapely geometries cannot be relied upon to be
            # hashable, we have to use a WeakValueDictionary to manage
            # their weak references. The key can then be a simple,
            # "disposable", hashable geom-key object that just uses the
            # id() of a geometry to determine equality and hash value.
            # The only persistent, strong reference to the geom-key is
            # in the WeakValueDictionary, so when the geometry is
            # garbage collected so is the geom-key.
            # The geom-key is also used to access the WeakKeyDictionary
            # cache of transformed geometries. So when the geom-key is
            # garbage collected so are the transformed geometries.
            geom_key = _GeomKey(geom)
            FeatureArtist._geom_key_to_geometry_cache.setdefault(
                geom_key, geom)
            mapping = FeatureArtist._geom_key_to_path_cache.setdefault(
                geom_key, {})
            geom_paths = mapping.get(key)
            if geom_paths is None:
                if ax.projection != feature_crs:
                    projected_geom = ax.projection.project_geometry(
                        geom, feature_crs)
                else:
                    projected_geom = geom
                geom_paths = cpatch.geos_to_path(projected_geom)
                mapping[key] = geom_paths

            if not self._styler:
                style = prepared_kwargs
            else:
                # Unfreeze, then add the computed style, and then re-freeze.
                style = style_merge(dict(prepared_kwargs), self._styler(geom))
                style = _freeze(style)

            stylised_paths.setdefault(style, []).extend(geom_paths)

        transform = ax.projection._as_mpl_transform(ax)

        # Draw one PathCollection per style. We could instead pass an array
        # of style items through to a single PathCollection, but that
        # complexity does not yet justify the effort.
        for style, paths in stylised_paths.items():
            style = style_finalize(dict(style))
            # Build path collection and draw it.
            c = matplotlib.collections.PathCollection(paths,
                                                      transform=transform,
                                                      **style)
            c.set_clip_path(ax.patch)
            c.set_figure(ax.figure)
            c.draw(renderer)

        # n.b. matplotlib.collection.Collection.draw returns None
        return None
Example #22
0
    def draw(self, renderer, *args, **kwargs):
        """
        Draw the geometries of the feature that intersect with the extent of
        the :class:`cartopy.mpl.GeoAxes` instance to which this
        object has been added.

        """
        if not self.get_visible():
            return

        ax = self.axes
        feature_crs = self._feature.crs

        # Get geometries that we need to draw.
        extent = None
        try:
            extent = ax.get_extent(feature_crs)
        except ValueError:
            warnings.warn('Unable to determine extent. Defaulting to global.')
        geoms = self._feature.intersecting_geometries(extent)

        # Combine all the keyword args in priority order.
        prepared_kwargs = style_merge(
                self._feature.kwargs, self._kwargs, kwargs)

        # Freeze the kwargs so that we can use them as a dict key. We will
        # need to unfreeze this with dict(frozen) before passing to mpl.
        prepared_kwargs = _freeze(prepared_kwargs)

        # Project (if necessary) and convert geometries to matplotlib paths.
        stylised_paths = OrderedDict()
        key = ax.projection
        for geom in geoms:
            # As Shapely geometries cannot be relied upon to be
            # hashable, we have to use a WeakValueDictionary to manage
            # their weak references. The key can then be a simple,
            # "disposable", hashable geom-key object that just uses the
            # id() of a geometry to determine equality and hash value.
            # The only persistent, strong reference to the geom-key is
            # in the WeakValueDictionary, so when the geometry is
            # garbage collected so is the geom-key.
            # The geom-key is also used to access the WeakKeyDictionary
            # cache of transformed geometries. So when the geom-key is
            # garbage collected so are the transformed geometries.
            geom_key = _GeomKey(geom)
            FeatureArtist._geom_key_to_geometry_cache.setdefault(
                geom_key, geom)
            mapping = FeatureArtist._geom_key_to_path_cache.setdefault(
                geom_key, {})
            geom_paths = mapping.get(key)
            if geom_paths is None:
                if ax.projection != feature_crs:
                    projected_geom = ax.projection.project_geometry(
                        geom, feature_crs)
                else:
                    projected_geom = geom
                geom_paths = cpatch.geos_to_path(projected_geom)
                mapping[key] = geom_paths

            if not self._styler:
                style = prepared_kwargs
            else:
                # Unfreeze, then add the computed style, and then re-freeze.
                style = style_merge(dict(prepared_kwargs), self._styler(geom))
                style = _freeze(style)

            stylised_paths.setdefault(style, []).extend(geom_paths)

        transform = ax.projection._as_mpl_transform(ax)

        # Draw one PathCollection per style. We could instead pass an array
        # of style items through to a single PathCollection, but that
        # complexity does not yet justify the effort.
        for style, paths in stylised_paths.items():
            style = style_finalize(dict(style))
            # Build path collection and draw it.
            c = matplotlib.collections.PathCollection(
                    paths, transform=transform, **style)
            c.set_clip_path(ax.patch)
            c.set_figure(ax.figure)
            c.draw(renderer)

        # n.b. matplotlib.collection.Collection.draw returns None
        return None
Example #23
0
a = ccrs.PlateCarree().transform_points(ccrs.PlateCarree(), plotter.data.lons[1:10000].values, plotter.data.lats[1:10000].values)
lons, lats = a[:, 0], a[:, 1]
ax = Axes3D(fig, xlim = [-180, 180], ylim = [-90, 90])
zmax = max(plotter.data.z.values)

concat = lambda iterable: list(itertools.chain.from_iterable(iterable))

target_projection = ccrs.PlateCarree()

feature = cartopy.feature.NaturalEarthFeature('Physical', 'land', '110m')

geoms = feature.geometries()

geoms = [target_projection.project_geometry(geom, feature.crs) for geom in geoms]

paths = concat(geos_to_path(geom) for geom in geoms)

polys = concat(path.to_polygons() for path in paths)
print(type(polys[0][0]))
#print(polys)
#print([[[point] for point in shape] for shape in polys])
polys = [[(point[0], point[1], zmax) for point in shape] for shape in polys]
#print(polys.shape)
#polys = [x, y, zmax for x,y 

lc = Poly3DCollection(polys, edgecolor = 'black', facecolor = 'green', closed = False)

ax.add_collection3d(lc)
print(plotter.data.qc_DART.values[:].shape)
ax.scatter(lons, lats,
           plotter.data.z[1:10000], c = plotter.data.values[1:10000].ravel(), cmap = plt.get_cmap('gist_ncar'))
def pcolor_mask_geoms(cube, geoms, transform):
    path = Path.make_compound_path(*geos_to_path(geoms))
    im = iplt.pcolor(cube)
    im.set_clip_path(path, transform=transform)
Example #25
0
fig = plt.figure()
ax = Axes3D(fig, xlim=[-180, 180], ylim=[-90, 90])
ax.set_zlim(bottom=0)

target_projection = ccrs.PlateCarree()

feature = cartopy.feature.NaturalEarthFeature('physical', 'land', '110m')
geoms = feature.geometries()

geoms = [
    target_projection.project_geometry(geom, feature.crs) for geom in geoms
]

paths = list(
    itertools.chain.from_iterable(geos_to_path(geom) for geom in geoms))

# At this point, we start working around mpl3d's slightly broken interfaces.
# So we produce a LineCollection rather than a PathCollection.
segments = []
for path in paths:
    vertices = [vertex for vertex, _ in path.iter_segments()]
    vertices = np.asarray(vertices)
    segments.append(vertices)

lc = LineCollection(segments, color='black')

ax.add_collection3d(lc)

ax.set_xlabel('X')
ax.set_ylabel('Y')