Ejemplo n.º 1
0
    def test_shape(self):
        """Is the transformation doing well?"""

        from salem import read_shapefile

        so = read_shapefile(get_demo_file('Hintereisferner.shp'))
        sref = read_shapefile(get_demo_file('Hintereisferner_UTM.shp'))
        st = gis.transform_geopandas(so, to_crs=sref.crs)
        self.assertFalse(st is so)
        assert_allclose(st.geometry[0].exterior.coords,
                        sref.geometry[0].exterior.coords)

        sti = gis.transform_geopandas(so, to_crs=sref.crs, inplace=True)
        self.assertTrue(sti is so)
        assert_allclose(so.geometry[0].exterior.coords,
                        sref.geometry[0].exterior.coords)
        assert_allclose(sti.geometry[0].exterior.coords,
                        sref.geometry[0].exterior.coords)

        g = Grid(nxny=(1, 1), dxdy=(1, 1), x0y0=(10., 46.), proj=wgs84)
        so = read_shapefile(get_demo_file('Hintereisferner.shp'))
        st = gis.transform_geopandas(so, to_crs=g)

        ref = np.array(so.geometry[0].exterior.coords)
        ref = ref - np.floor(ref)
        assert_allclose(ref, st.geometry[0].exterior.coords)

        # round trip
        so_back = gis.transform_geopandas(st, to_crs=so.crs)
        assert_allclose(so_back.geometry[0].exterior.coords,
                        so.geometry[0].exterior.coords)
Ejemplo n.º 2
0
    def set_roi(self, shape=None, geometry=None, crs=wgs84, grid=None,
                corners=None, noerase=False):
        """Set a region of interest for the dataset.
        If set succesfully, a ROI is simply a mask of the same size as the
        dataset's grid, obtained with the .roi attribute.
        I haven't decided yet if the data should be masekd out when a ROI
        has been set.
        Parameters
        ----------
        shape: path to a shapefile
        geometry: a shapely geometry
        crs: the crs of the geometry
        grid: a Grid object
        corners: a ((x0, y0), (x1, y1)) tuple of the corners of the square
        to subset the dataset to. The coordinates are not expressed in
        wgs84, set the crs keyword
        noerase: set to true in order to add the new ROI to the previous one
        """

        # The rois are always defined on the original grids, but of course
        # we take that into account when a subset is set (see roi
        # decorator below)
        ogrid = self._ogrid

        # Initial mask
        if noerase and (self.roi is not None):
            mask = self.roi
        else:
            mask = np.zeros((ogrid.ny, ogrid.nx), dtype=np.int16)

        # Several cases
        if shape is not None:
            gdf = sio.read_shapefile(shape)
            gis.transform_geopandas(gdf, to_crs=ogrid.corner_grid,
                                    inplace=True)
            if rasterio is None:
                raise ImportError('This feature needs rasterio')
            from rasterio.features import rasterize
            with rasterio.Env():
                mask = rasterize(gdf.geometry, out=mask)
        if geometry is not None:
            geom = gis.transform_geometry(geometry, crs=crs,
                                          to_crs=ogrid.corner_grid)
            if rasterio is None:
                raise ImportError('This feature needs rasterio')
            from rasterio.features import rasterize
            with rasterio.Env():
                mask = rasterize(np.atleast_1d(geom), out=mask)
        if grid is not None:
            _tmp = np.ones((grid.ny, grid.nx), dtype=np.int16)
            mask = ogrid.map_gridded_data(_tmp, grid, out=mask).filled(0)
        if corners is not None:
            cgrid = self._ogrid.center_grid
            xy0, xy1 = corners
            x0, y0 = cgrid.transform(*xy0, crs=crs, nearest=True)
            x1, y1 = cgrid.transform(*xy1, crs=crs, nearest=True)
            mask[np.min([y0, y1]):np.max([y0, y1])+1,
                 np.min([x0, x1]):np.max([x0, x1])+1] = 1

        self.roi = mask
Ejemplo n.º 3
0
    def test_shape(self):
        """Is the transformation doing well?"""

        from salem import read_shapefile

        so = read_shapefile(get_demo_file('Hintereisferner.shp'))
        sref = read_shapefile(get_demo_file('Hintereisferner_UTM.shp'))
        st = gis.transform_geopandas(so, to_crs=sref.crs)
        self.assertFalse(st is so)
        assert_allclose(st.geometry[0].exterior.coords,
                                   sref.geometry[0].exterior.coords)

        sti = gis.transform_geopandas(so, to_crs=sref.crs, inplace=True)
        self.assertTrue(sti is so)
        assert_allclose(so.geometry[0].exterior.coords,
                                   sref.geometry[0].exterior.coords)
        assert_allclose(sti.geometry[0].exterior.coords,
                                   sref.geometry[0].exterior.coords)

        g = Grid(nxny=(1, 1), dxdy=(1, 1), ll_corner=(10., 46.), proj=wgs84)
        so = read_shapefile(get_demo_file('Hintereisferner.shp'))
        st = gis.transform_geopandas(so, to_crs=g)

        ref = np.array(so.geometry[0].exterior.coords)
        ref = ref - np.floor(ref)
        assert_allclose(ref, st.geometry[0].exterior.coords)
Ejemplo n.º 4
0
    def set_roi(self, shape=None, geometry=None, crs=wgs84, grid=None,
                corners=None, noerase=False):
        """Set a region of interest for the dataset.
        If set succesfully, a ROI is simply a mask of the same size as the
        dataset's grid, obtained with the .roi attribute.
        I haven't decided yet if the data should be masekd out when a ROI
        has been set.
        Parameters
        ----------
        shape: path to a shapefile
        geometry: a shapely geometry
        crs: the crs of the geometry
        grid: a Grid object
        corners: a ((x0, y0), (x1, y1)) tuple of the corners of the square
        to subset the dataset to. The coordinates are not expressed in
        wgs84, set the crs keyword
        noerase: set to true in order to add the new ROI to the previous one
        """

        # The rois are always defined on the original grids, but of course
        # we take that into account when a subset is set (see roi
        # decorator below)
        ogrid = self._ogrid

        # Initial mask
        if noerase and (self.roi is not None):
            mask = self.roi
        else:
            mask = np.zeros((ogrid.ny, ogrid.nx), dtype=np.int16)

        # Several cases
        if shape is not None:
            gdf = sio.read_shapefile(shape)
            gis.transform_geopandas(gdf, to_crs=ogrid.corner_grid,
                                    inplace=True)
            with rasterio.Env():
                mask = features.rasterize(gdf.geometry, out=mask)
        if geometry is not None:
            geom = gis.transform_geometry(geometry, crs=crs,
                                          to_crs=ogrid.corner_grid)
            with rasterio.Env():
                mask = features.rasterize(np.atleast_1d(geom), out=mask)
        if grid is not None:
            _tmp = np.ones((grid.ny, grid.nx), dtype=np.int16)
            mask = ogrid.map_gridded_data(_tmp, grid, out=mask).filled(0)
        if corners is not None:
            cgrid = self._ogrid.center_grid
            xy0, xy1 = corners
            x0, y0 = cgrid.transform(*xy0, crs=crs, nearest=True)
            x1, y1 = cgrid.transform(*xy1, crs=crs, nearest=True)
            mask[np.min([y0, y1]):np.max([y0, y1])+1,
                 np.min([x0, x1]):np.max([x0, x1])+1] = 1

        self.roi = mask
Ejemplo n.º 5
0
def _memory_transform(shape_cpath, grid=None, grid_str=None):
    """Quick solution using joblib in order to not transform many times the
    same shape (useful for maps).

    Since grid is a complex object joblib seemed to have trouble with it,
    so joblib is checking its cache according to grid_str while the job is
    done with grid.
    """

    shape = read_shapefile(shape_cpath, cached=True)
    e = grid.extent_in_crs(crs=shape.crs)
    p = np.nonzero(~((shape['min_x'] > e[1]) |
                     (shape['max_x'] < e[0]) |
                     (shape['min_y'] > e[3]) |
                     (shape['max_y'] < e[2])))
    shape = shape.iloc[p]
    shape = gis.transform_geopandas(shape, to_crs=grid, inplace=True)
    return shape
Ejemplo n.º 6
0
def _memory_shapefile_to_grid(shape_cpath,
                              grid=None,
                              nxny=None,
                              pixel_ref=None,
                              x0y0=None,
                              dxdy=None,
                              proj=None):
    """Quick solution using joblib in order to not transform many times the
    same shape (useful for maps).

    Since grid is a complex object, joblib seems to have trouble with it.
    So joblib is checking its cache according to the grid params while the job
    is done with grid.
    """

    shape = read_shapefile(shape_cpath, cached=True)
    e = grid.extent_in_crs(crs=shape.crs)
    p = np.nonzero(~(
        (shape['min_x'].to_numpy() > e[1]) | (shape['max_x'].to_numpy() < e[0])
        | (shape['min_y'].to_numpy() > e[3])
        | (shape['max_y'].to_numpy() < e[2])))
    shape = shape.iloc[p]
    shape = gis.transform_geopandas(shape, to_crs=grid, inplace=True)
    return shape
Ejemplo n.º 7
0
    def set_shapefile(self,
                      shape=None,
                      countries=False,
                      oceans=False,
                      rivers=False,
                      lakes=False,
                      **kwargs):
        """Add a shapefile to the plot.

        Salem is shipped with a few default settings for country borders,
        oceans and rivers (set one at the time!)

        set_shapefile() without argument will reset the map to zero shapefiles.

        Parameters
        ----------
        shape: the path to the shapefile to read
        countries: if True, add country borders
        oceans: if True, add oceans
        rivers: if True, add rivers
        lakes: if True, add lakes
        kwargs: all keywords accepted by the corresponding collection.
        For LineStrings::
            linewidths, colors, linestyles, ...
        For Polygons::
            alpha, edgecolor, facecolor, fill, linestyle, linewidth, color, ...
        """

        # See if the user wanted defaults settings
        if oceans:
            kwargs.setdefault('facecolor', (0.36862745, 0.64313725, 0.8))
            kwargs.setdefault('edgecolor', 'none')
            kwargs.setdefault('alpha', 1)
            return self.set_shapefile(shapefiles['oceans'], **kwargs)
        if rivers:
            kwargs.setdefault('color', (0.08984375, 0.65625, 0.8515625))
            return self.set_shapefile(shapefiles['rivers'], **kwargs)
        if lakes:
            kwargs.setdefault('color', (0.08984375, 0.65625, 0.8515625))
            return self.set_shapefile(shapefiles['lakes'], **kwargs)
        if countries:
            kwargs.setdefault('zorder', 1.5)
            return self.set_shapefile(shapefiles['world_borders'], **kwargs)

        # Defaults
        if not all(k in kwargs for k in ('facecolor', 'edgecolor')):
            kwargs.setdefault('color', 'k')

        # Reset?
        if shape is None:
            self._collections = []
            return

        # Transform
        if isinstance(shape, pd.DataFrame):
            shape = gis.transform_geopandas(shape, to_crs=self.grid)
        else:
            shape = sio.read_shapefile_to_grid(shape, grid=self.grid)
        if len(shape) == 0:
            return

        # Different collection for each type
        geomtype = shape.iloc[0].geometry.type
        if 'Polygon' in geomtype:
            patches = []
            for g in shape.geometry:
                if 'Multi' in g.type:
                    for gg in g:
                        patches.append(PolygonPatch(gg))
                else:
                    patches.append(PolygonPatch(g))
            kwargs.setdefault('facecolor', 'none')
            if 'color' in kwargs:
                kwargs.setdefault('edgecolor', kwargs['color'])
                del kwargs['color']
            self._collections.append(PatchCollection(patches, **kwargs))
        elif 'LineString' in geomtype:
            lines = []
            for g in shape.geometry:
                if 'Multi' in g.type:
                    for gg in g:
                        lines.append(np.array(gg))
                else:
                    lines.append(np.array(g))
            self._collections.append(LineCollection(lines, **kwargs))
        else:
            raise NotImplementedError(geomtype)
Ejemplo n.º 8
0
    def set_shapefile(self, shape=None, countries=False, oceans=False,
                      rivers=False, **kwargs):
        """Add a shapefile to the plot.

        Salem is shipped with a few default settings for country borders,
        oceans and rivers (set one at the time!)

        set_shapefile() without argument will reset the map to zero shapefiles.

        Parameters
        ----------
        shape: the path to the shapefile to read
        countries: if True, add country borders
        oceans: if True, add oceans
        rivers: if True, add rivers
        kwargs: all keywords accepted by the corresponding collection.
        For LineStrings::
            linewidths, colors, linestyles, ...
        For Polygons::
            alpha, edgecolor, facecolor, fill, linestyle, linewidth, color, ...
        """

        # See if the user wanted defaults settings
        if oceans:
            kwargs.setdefault('facecolor', (0.36862745, 0.64313725, 0.8))
            kwargs.setdefault('edgecolor', 'none')
            kwargs.setdefault('alpha', 1)
            return self.set_shapefile(shapefiles['oceans'], **kwargs)
        if rivers:
            kwargs.setdefault('colors', (0.08984375, 0.65625, 0.8515625))
            return self.set_shapefile(shapefiles['rivers'], **kwargs)
        if countries:
            kwargs.setdefault('zorder', 50)
            return self.set_shapefile(shapefiles['world_borders'], **kwargs)

        # Reset?
        if shape is None:
            self._collections = []
            return

        # Transform
        if isinstance(shape, pd.DataFrame):
            shape = gis.transform_geopandas(shape, to_crs=self.grid)
        else:
            shape = sio.read_shapefile_to_grid(shape, grid=self.grid)
        if len(shape) == 0:
            return

        # Different collection for each type
        geomtype = shape.iloc[0].geometry.type
        if 'Polygon' in geomtype:
            patches = []
            for g in shape.geometry:
                if 'Multi' in g.type:
                    for gg in g:
                        patches.append(PolygonPatch(gg))
                else:
                    patches.append(PolygonPatch(g))
            kwargs.setdefault('facecolor', 'none')
            if 'color' in kwargs:
                kwargs.setdefault('edgecolor', kwargs['color'])
                del kwargs['color']
            self._collections.append(PatchCollection(patches, **kwargs))
        elif 'LineString' in geomtype:
            lines = []
            for g in shape.geometry:
                if 'Multi' in g.type:
                    for gg in g:
                        lines.append(np.array(gg))
                else:
                    lines.append(np.array(g))
            self._collections.append(LineCollection(lines, **kwargs))
        else:
            raise NotImplementedError(geomtype)