Пример #1
0
def lookup_map_feature(feature_name):
    """Get a Cartopy map feature based on a name."""
    import cartopy.feature as cfeature
    from . import cartopy_utils

    name = feature_name.upper()
    try:
        feat = getattr(cfeature, name)
        scaler = cfeature.AdaptiveScaler('110m', (('50m', 50), ('10m', 15)))
    except AttributeError:
        feat = getattr(cartopy_utils, name)
        scaler = cfeature.AdaptiveScaler('20m', (('5m', 5), ('500k', 1)))
    return feat.with_scale(scaler)
Пример #2
0
    def _layer_features(self):
        """Iterate over all map features and return as Cartopy objects.

        Handle converting names of maps to auto-scaling map features.

        """
        for item in self.layers:
            if is_string_like(item):
                item = item.upper()
                try:
                    scaler = cfeature.AdaptiveScaler('110m', (('50m', 50),
                                                              ('10m', 15)))
                    feat = getattr(cfeature, item).with_scale(scaler)
                except AttributeError:
                    scaler = cfeature.AdaptiveScaler('20m',
                                                     (('5m', 5), ('500k', 1)))
                    feat = getattr(cartopy_utils, item).with_scale(scaler)
            else:
                feat = item

            yield feat
Пример #3
0
    def plot(self, variable=None, vmin=None, vmax=None,
             filename=None, title=None, buffer=1, lscale='auto'):
        """Plot geographical coverage of reader."""

        fig = plt.figure()

        if self.global_coverage():
            lonmin=-180
            lonmax=180
            latmin=-89
            latmax=89
        else:
            corners = self.xy2lonlat([self.xmin, self.xmin, self.xmax, self.xmax],
                                     [self.ymax, self.ymin, self.ymax, self.ymin])
            lonmin = np.min(corners[0]) - buffer*2
            lonmax = np.max(corners[0]) + buffer*2
            latmin = np.min(corners[1]) - buffer
            latmax = np.max(corners[1]) + buffer

        # Initialise map
        if not self.global_coverage():
            # Stereographic projection centred on domain, if small domain
            x0 = (self.xmin + self.xmax) / 2
            y0 = (self.ymin + self.ymax) / 2
            lon0, lat0 = self.xy2lonlat(x0, y0)
            sp = ccrs.Stereographic(central_longitude=lon0, central_latitude=lat0)
            latmax = np.maximum(latmax, lat0)
            latmin = np.minimum(latmin, lat0)
        else:
            # Global map if reader domain is large
            sp = ccrs.Mercator()

        ax = fig.add_subplot(1, 1, 1, projection=sp)

        if lscale == 'auto':  # Custom lscale - this should be generalized to Basemodel also
            s = cfeature.AdaptiveScaler('coarse',
                (('low', 100), ('intermediate', 20), ('high', 5), ('full', 1)))
            lscale = s.scale_from_extent([lonmin, lonmax, latmin, latmax])

        # GSHHS coastlines
        f = cfeature.GSHHSFeature(scale=lscale, levels=[1])
        f._geometries_cache = {}
        ax.add_geometries(
            #f.intersecting_geometries([lonmin, lonmax, latmin, latmax]),
            f.geometries(),
            ccrs.PlateCarree(),
            facecolor=cfeature.COLORS['land'],
            edgecolor='black')

        gl = ax.gridlines(ccrs.PlateCarree())
        gl.top_labels = False

        # Get boundary
        if self.global_coverage():
            lon = np.array([-180, 180, 180, -180, -180])
            lat = np.array([-89, -89, 89, 89, -89])
        else:
            npoints = 10  # points per side
            x = np.array([])
            y = np.array([])
            x = np.concatenate((x, np.linspace(self.xmin, self.xmax, npoints)))
            y = np.concatenate((y, [self.ymin]*npoints))
            x = np.concatenate((x, [self.xmax]*npoints))
            y = np.concatenate((y, np.linspace(self.ymin, self.ymax, npoints)))
            x = np.concatenate((x, np.linspace(self.xmax, self.xmin, npoints)))
            y = np.concatenate((y, [self.ymax]*npoints))
            x = np.concatenate((x, [self.xmin]*npoints))
            y = np.concatenate((y, np.linspace(self.ymax, self.ymin, npoints)))
            # from x/y vectors create a Patch to be added to map
            lon, lat = self.xy2lonlat(x, y)
            lat[lat>89] = 89.
            lat[lat<-89] = -89.
        p = sp.transform_points(ccrs.PlateCarree(), lon, lat)
        xsp = p[:, 0]
        ysp = p[:, 1]

        if variable is None:
            boundary = Polygon(list(zip(xsp, ysp)), alpha=0.5, ec='k', fc='b',
                               zorder=100)
            ax.add_patch(boundary)
            if self.global_coverage():
                ax.set_global()
            else:
                buf = (xsp.max()-xsp.min())*.1  # Some whitespace around polygon
                ax.set_extent([xsp.min()-buf, xsp.max()+buf, ysp.min()-buf, ysp.max()+buf], crs=sp)
        if title is None:
            plt.title(self.name)
        else:
            plt.title(title)
        plt.xlabel('Time coverage: %s to %s' %
                   (self.start_time, self.end_time))

        if variable is not None:
            rx = np.array([self.xmin, self.xmax])
            ry = np.array([self.ymin, self.ymax])
            if variable in self.derived_variables:
                data = self.get_variables(self.derived_variables[variable], self.start_time, rx, ry)
                self.__calculate_derived_environment_variables__(data)
            else:
                data = self.get_variables(variable, self.start_time, rx, ry)
            rx, ry = np.meshgrid(data['x'], data['y'])
            rx = np.float32(rx)
            ry = np.float32(ry)
            rlon, rlat = self.xy2lonlat(rx, ry)
            data[variable] = np.ma.masked_invalid(data[variable])

            if data[variable].ndim > 2:
                logger.warning('Ensemble data, plotting only first member')
                data[variable] = data[variable][0,:,:]
            if self.global_coverage():
                mappable = ax.pcolormesh(rlon, rlat, data[variable], vmin=vmin, vmax=vmax,
                                         transform=ccrs.PlateCarree(), shading='nearest')
            else:
                p = sp.transform_points(ccrs.PlateCarree(), rlon, rlat)
                mapx = p[:,:,0]
                mapy = p[:,:,1]
                mappable = ax.pcolormesh(mapx, mapy, data[variable], vmin=vmin, vmax=vmax,
                                         shading='nearest')

            cbar = fig.colorbar(mappable, orientation='horizontal', pad=.05, aspect=30, shrink=.4)
            cbar.set_label(variable)

        try:  # Activate figure zooming
            mng = plt.get_current_fig_manager()
            mng.toolbar.zoom()
        except:
            pass

        if filename is not None:
            plt.savefig(filename)
            plt.close()
        else:
            plt.show()
Пример #4
0
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with cartopy.  If not, see <https://www.gnu.org/licenses/>.

from __future__ import (absolute_import, division, print_function)

import cartopy.feature as cfeature

small_extent = (-6, -8, 56, 59)
medium_extent = (-20, 20, 20, 60)
large_extent = (-40, 40, 0, 80)

auto_scaler = cfeature.AdaptiveScaler('110m', (('50m', 50), ('10m', 15)))

auto_land = cfeature.NaturalEarthFeature('physical', 'land', auto_scaler)


class TestFeatures(object):
    def test_change_scale(self):
        # Check that features can easily be retrieved with a different
        # scale.
        new_lakes = cfeature.LAKES.with_scale('10m')
        assert new_lakes.scale == '10m'
        assert new_lakes.kwargs == cfeature.LAKES.kwargs
        assert new_lakes.category == cfeature.LAKES.category
        assert new_lakes.name == cfeature.LAKES.name

    def test_scale_from_extent(self):