Пример #1
0
def test_linearrings_invalid_shape(shape):
    coords = np.ones(shape)
    with pytest.raises(ValueError):
        pygeos.linearrings(coords)

    # make sure the first coordinate != second coordinate
    coords[..., 1] += 1
    with pytest.raises(ValueError):
        pygeos.linearrings(coords)
Пример #2
0
def test_polygon_with_none_hole():
    actual = pygeos.polygons(
        pygeos.linearrings(box_tpl(0, 0, 10, 10)),
        [
            pygeos.linearrings(box_tpl(1, 1, 2, 2)),
            None,
            pygeos.linearrings(box_tpl(3, 3, 4, 4)),
        ],
    )
    assert pygeos.area(actual) == 98.0
Пример #3
0
import numpy as np
import pygeos

point_polygon_testdata = (
    pygeos.points(np.arange(6), np.arange(6)),
    pygeos.box(2, 2, 4, 4),
)
point = pygeos.points(2, 3)
line_string = pygeos.linestrings([(0, 0), (1, 0), (1, 1)])
linear_ring = pygeos.linearrings([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)])
polygon = pygeos.polygons([(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)])
multi_point = pygeos.multipoints([(0, 0), (1, 2)])
multi_line_string = pygeos.multilinestrings([[(0, 0), (1, 2)]])
multi_polygon = pygeos.multipolygons([
    [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)],
    [(2.1, 2.1), (2.2, 2.1), (2.2, 2.2), (2.1, 2.2), (2.1, 2.1)],
])
geometry_collection = pygeos.geometrycollections(
    [pygeos.points(51, -1),
     pygeos.linestrings([(52, -1), (49, 2)])])
point_z = pygeos.points(1.0, 1.0, 1.0)
polygon_with_hole = pygeos.Geometry(
    "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 4, 4 4, 4 2, 2 2))")

all_types = (
    point,
    line_string,
    linear_ring,
    polygon,
    multi_point,
    multi_line_string,
Пример #4
0
def test_linearrings_unclosed():
    actual = pygeos.linearrings(box_tpl(0, 0, 1, 1)[:-1])
    assert str(actual) == "LINEARRING (1 0, 1 1, 0 1, 0 0, 1 0)"
Пример #5
0
def test_linearrings_from_xy():
    actual = pygeos.linearrings([0, 1, 2, 0], [3, 4, 5, 3])
    assert str(actual) == "LINEARRING (0 3, 1 4, 2 5, 0 3)"
Пример #6
0
def test_polygon_from_linearring():
    actual = pygeos.polygons(pygeos.linearrings(box_tpl(0, 0, 1, 1)))
    assert str(actual) == "POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))"
Пример #7
0
def test_linearrings(coordinates):
    actual = pygeos.linearrings(coordinates, indices=len(coordinates) * [0])
    assert_geometries_equal(actual, pygeos.linearrings(coordinates))
Пример #8
0
def test_linearrings_invalid(coordinates):
    # attempt to construct linestrings with 1 coordinate
    with pytest.raises(pygeos.GEOSException):
        pygeos.linearrings(coordinates, indices=np.zeros(len(coordinates)))
Пример #9
0

@pytest.mark.parametrize("holes",
                         [[1, 2], None, [linear_ring, point], "hello"])
def test_polygons_invalid_holes(holes):
    with pytest.raises((TypeError, ValueError, pygeos.GEOSException)):
        pygeos.polygons([linear_ring, linear_ring], holes, indices=[0, 1])


@pytest.mark.parametrize("indices", [[1, 2], [point], "hello", [1], [-1]])
def test_polygons_invalid_indices(indices):
    with pytest.raises((TypeError, ValueError)):
        pygeos.polygons([linear_ring], [linear_ring], indices=indices)


hole_1 = pygeos.linearrings([(0.2, 0.2), (0.2, 0.4), (0.4, 0.4)])
hole_2 = pygeos.linearrings([(0.6, 0.6), (0.6, 0.8), (0.8, 0.8)])
poly = pygeos.polygons(linear_ring)
poly_hole_1 = pygeos.polygons(linear_ring, holes=[hole_1])
poly_hole_2 = pygeos.polygons(linear_ring, holes=[hole_2])
poly_hole_1_2 = pygeos.polygons(linear_ring, holes=[hole_1, hole_2])


@pytest.mark.parametrize(
    "holes,indices,expected",
    [
        ([None], [1], [poly, poly]),
        ([hole_1], [0], [poly_hole_1, poly]),
        ([hole_1], [1], [poly, poly_hole_1]),
        ([hole_1, hole_2], [0, 0], [poly_hole_1_2, poly]),
        ([hole_1, hole_2], [0, 1], [poly_hole_1, poly_hole_2]),
Пример #10
0
def test_linearrings():
    actual = pygeos.linearrings(box_tpl(0, 0, 1, 1))
    assert actual.to_wkt() == "LINEARRING (1 0, 1 1, 0 1, 0 0, 1 0)"
Пример #11
0
def fix(dem, coastline, **kwargs):

    # ---------------------------------------------------------------------
    logger.info("adjust dem\n")
    # ---------------------------------------------------------------------

    # define coastline
    try:
        shp = gp.GeoDataFrame.from_file(coastline)
    except:
        shp = gp.GeoDataFrame(coastline)

    if "ival" in dem.data_vars:
        xp = dem.ilons.values
        yp = dem.ilats.values
    else:
        xp = dem.longitude.values
        yp = dem.latitude.values

    minlon = xp.min()
    maxlon = xp.max()
    minlat = yp.min()
    maxlat = yp.max()

    if xp.mean() < 0 and xp.min() < -180.0:
        flag = -1
    elif xp.mean() > 0 and xp.max() > 180.0:
        flag = 1
    else:
        flag = 0

    if flag == 1:
        block1 = shp.cx[minlon:180, minlat:maxlat].copy()
        block2 = shp.cx[-180:(maxlon - 360.0), minlat:maxlat].copy()

        for idx, poly in block2.iterrows():
            block2.loc[idx,
                       "geometry"] = shapely.ops.transform(lambda x, y, z=None:
                                                           (x + 360.0, y),
                                                           poly.geometry)

        block = pd.concat([block1, block2])

    elif flag == -1:

        block1 = shp.cx[minlon + 360:180, minlat:maxlat].copy()
        block2 = shp.cx[-180:maxlon, minlat:maxlat].copy()

        for idx, poly in block1.iterrows():
            block1.loc[idx,
                       "geometry"] = shapely.ops.transform(lambda x, y, z=None:
                                                           (x - 360.0, y),
                                                           poly.geometry)

        block = pd.concat([block1, block2])

    else:
        block = shp.cx[minlon:maxlon, minlat:maxlat]

    try:
        block = gp.GeoDataFrame(geometry=list(block.unary_union.geoms))
    except:
        pass

    # ---------------------------------------------------------------------
    logger.debug("compute water and land\n")
    # ---------------------------------------------------------------------

    # create a polygon of the lat/lon window
    grp = shapely.geometry.Polygon([(minlon, minlat), (minlon, maxlat),
                                    (maxlon, maxlat), (maxlon, minlat)])

    grp = grp.buffer(0.5)  # buffer it to get also the boundary points

    g = block.unary_union.symmetric_difference(grp)  # get the diff

    try:
        t = gp.GeoDataFrame({"geometry": g})
    except:
        t = gp.GeoDataFrame({"geometry": [g]})

    t["length"] = t["geometry"][:].length  # optional

    t = t.sort_values(by="length", ascending=0)  # use the length to list them
    t = t.reset_index(drop=True)

    t["in"] = gp.GeoDataFrame(geometry=[grp.buffer(0.001)] *
                              t.shape[0]).contains(
                                  t)  # find the largest of boundaries

    try:
        idx = np.where(
            t["in"] == True)[0][0]  # first(largest) boundary within lat/lon
        b = t.iloc[idx].geometry  # get the largest
    except:
        b = shapely.geometry.GeometryCollection()

    # define wet/dry
    water = b
    land = grp - b

    if (not land) | (not water):

        # ---------------------------------------------------------------------
        logger.debug("only water/land present...\n")
        # ---------------------------------------------------------------------

        if "ival" in dem.data_vars:

            dem = dem.assign(fval=dem.ival)

        else:

            dem = dem.assign(adjusted=dem.elevation)

        return dem

    if "ival" in dem.data_vars:
        df = pd.DataFrame({
            "longitude": dem.ilons.values.flatten(),
            "latitude": dem.ilats.values.flatten(),
            "elevation": dem.ival.values.flatten(),
        })
    else:
        df = dem.elevation.to_dataframe().reset_index()

    # ---------------------------------------------------------------------
    logger.debug("invoke pygeos\n")
    # ---------------------------------------------------------------------

    spoints_ = pygeos.points(list(df.loc[:, ["longitude", "latitude"]].values)
                             )  # create pygeos objects for the points

    # Add land boundaries to a pygeos object
    try:
        lbs = []
        for l in range(len(land.boundary.geoms)):
            z = pygeos.linearrings(land.boundary.geoms[l].coords[:])
            lbs.append(z)
    except:
        lbs = pygeos.linearrings(land.boundary.coords[:])

    bp = pygeos.polygons(lbs)

    # ---------------------------------------------------------------------
    logger.debug("find wet and dry masks\n")
    # ---------------------------------------------------------------------

    # find the points on land

    tree = pygeos.STRtree(spoints_)

    try:
        wl = []
        for l in range(len(land.boundary.geoms)):
            wl.append(tree.query(bp[l], predicate="contains").tolist())
        ns = [j for i in wl for j in i]
    except:
        wl = tree.query(bp, predicate="contains").tolist()
        ns = wl

    lmask = np.zeros(spoints_.shape, dtype=bool)
    lmask[ns] = True

    wmask = ~lmask  # invert for wet mask

    # ---------------------------------------------------------------------
    logger.debug("fix wet points\n")
    # ---------------------------------------------------------------------

    # Now see if the wet points have indeed negative values

    pw_mask = df.loc[wmask, "elevation"] > 0

    if pw_mask.sum() > 0:

        pw = df.loc[wmask][
            pw_mask]  # problematic points: bathymetry > 0 in wet area

        # Resample to fix that ...
        xw = pw.longitude.values
        yw = pw.latitude.values

        # Define points with positive bathymetry
        x, y = np.meshgrid(dem.longitude, dem.latitude)  #!!!!!!!!

        if flag == 1:
            xw = xw - 180.0
            x = x - 180.0
        elif flag == -1:
            xw = xw + 180.0
            x = x + 180.0

        # wet.fill_value = 0.
        mx = np.ma.masked_array(x, dem.elevation.values > 0)
        my = np.ma.masked_array(y, dem.elevation.values > 0)

        # fill the nan, if present, with values in order to compute values there if needed.
        dem.elevation.data[np.isnan(dem.elevation.values)] = 9999.0

        # mask positive bathymetry
        wet_dem = np.ma.masked_array(dem.elevation, dem.elevation.values > 0)

        orig = pyresample.geometry.SwathDefinition(
            lons=mx, lats=my)  # original bathymetry points
        targ = pyresample.geometry.SwathDefinition(lons=xw,
                                                   lats=yw)  # wet points

        bw = pyresample.kd_tree.resample_nearest(orig,
                                                 wet_dem,
                                                 targ,
                                                 radius_of_influence=100000,
                                                 fill_value=np.nan)

        df.loc[pw.index, "elevation"] = bw  # replace in original dataset

    # ---------------------------------------------------------------------
    logger.debug("fix dry points\n")
    # ---------------------------------------------------------------------

    # .. the same for dry points

    pl_mask = df.loc[lmask, "elevation"] < 0

    if pl_mask.sum() > 0:

        pl = df.loc[lmask][
            pl_mask]  # problematic points: bathymetry <0 in dry area

        ## Resample to fix that
        xl = pl.longitude.values
        yl = pl.latitude.values

        x, y = np.meshgrid(dem.longitude, dem.latitude)

        if flag == 1:
            xl = xl - 180.0
            x = x - 180.0
        elif flag == -1:
            xl = xl + 180.0
            x = x + 180.0

        # wet.fill_value = 0.
        dx = np.ma.masked_array(x, dem.elevation.values < 0)
        dy = np.ma.masked_array(y, dem.elevation.values < 0)

        # fill the nan, if present, with values in order to compute values there if needed.
        dem.elevation.data[np.isnan(dem.elevation.values)] = 9999.0

        # mask positive bathymetry
        dry_dem = np.ma.masked_array(dem.elevation, dem.elevation.values < 0)

        orig = pyresample.geometry.SwathDefinition(
            lons=dx, lats=dy)  # original bathymetry points
        targ = pyresample.geometry.SwathDefinition(lons=xl,
                                                   lats=yl)  # wet points

        bd = pyresample.kd_tree.resample_nearest(orig,
                                                 dry_dem,
                                                 targ,
                                                 radius_of_influence=100000,
                                                 fill_value=np.nan)

        df.loc[pl.index, "elevation"] = bd  # replace in original dataset

    # ---------------------------------------------------------------------
    logger.debug("assemble dataset \n")
    # ---------------------------------------------------------------------

    # reassemble dataset

    if "ival" in dem.data_vars:

        if len(dem.ival.shape) == 1:
            new_dem = df.elevation.to_xarray()
            new_dem = xr.merge([new_dem])
            new_dem = new_dem.rename({"elevation": "fval"})
            new_dem.fval.attrs = {"coastline": "based on coastline"}
            new_dem = new_dem.rename({"index": "k"}).drop_vars("k")
        else:
            new_dem = (df.set_index(["latitude",
                                     "longitude"]).to_xarray().rename({
                                         "longitude":
                                         "l",
                                         "latitude":
                                         "k",
                                         "elevation":
                                         "fval"
                                     }).drop_vars(["k", "l"]))

    else:

        df_new = df.set_index(["latitude", "longitude"])
        new_dem = df_new.to_xarray()
        new_dem = new_dem.rename({"elevation": "adjusted"})
        new_dem.attrs = {"coastline": "based on coastline"}

    cdem = xr.merge([dem, new_dem])

    return cdem
Пример #12
0
    def _create_mosaic(
        cls,
        features: Sequence[Dict],
        minzoom: int,
        maxzoom: int,
        quadkey_zoom: Optional[int] = None,
        accessor: Callable[[Dict], str] = default_accessor,
        asset_filter: Callable = default_filter,
        version: str = "0.0.2",
        quiet: bool = True,
        **kwargs,
    ):
        """Create mosaic definition content.

        Attributes:
            features (list): List of GeoJSON features.
            minzoom (int): Force mosaic min-zoom.
            maxzoom (int): Force mosaic max-zoom.
            quadkey_zoom (int): Force mosaic quadkey zoom (optional).
            accessor (callable): Function called on each feature to get its identifier (default is feature["properties"]["path"]).
            asset_filter (callable):  Function to filter features.
            version (str): mosaicJSON definition version (default: 0.0.2).
            quiet (bool): Mask processing steps (default is True).
            kwargs (any): Options forwarded to `asset_filter`

        Returns:
            mosaic_definition (MosaicJSON): Mosaic definition.

        Examples:
            >>> MosaicJSON._create_mosaic([], 12, 14)

        """
        quadkey_zoom = quadkey_zoom or minzoom

        if not quiet:
            click.echo(f"Get quadkey list for zoom: {quadkey_zoom}", err=True)

        dataset_geoms = polygons([
            linearrings(feat["geometry"]["coordinates"][0])
            for feat in features
        ])

        bounds = tuple(total_bounds(dataset_geoms))

        tiles = burntiles.burn(features, quadkey_zoom)
        tiles = [mercantile.Tile(*tile) for tile in tiles]

        mosaic_definition: Dict[str, Any] = dict(
            mosaicjson=version,
            minzoom=minzoom,
            maxzoom=maxzoom,
            quadkey_zoom=quadkey_zoom,
            bounds=bounds,
            center=((bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2,
                    minzoom),
            tiles={},
            version="1.0.0",
        )

        if not quiet:
            click.echo("Feed Quadkey index", err=True)

        # Create tree and find assets that overlap each tile
        tree = STRtree(dataset_geoms)

        with ExitStack() as ctx:
            fout = ctx.enter_context(open(os.devnull,
                                          "w")) if quiet else sys.stderr
            with click.progressbar(  # type: ignore
                    tiles,
                    file=fout,
                    show_percent=True,
                    label="Iterate over quadkeys") as bar:
                for tile in bar:
                    quadkey = mercantile.quadkey(tile)
                    tile_geom = polygons(
                        mercantile.feature(tile)["geometry"]["coordinates"][0])

                    # Find intersections from rtree
                    intersections_idx = sorted(
                        tree.query(tile_geom, predicate="intersects"))
                    if len(intersections_idx) == 0:
                        continue

                    intersect_dataset, intersect_geoms = zip(
                        *[(features[idx], dataset_geoms[idx])
                          for idx in intersections_idx])

                    dataset = asset_filter(tile, intersect_dataset,
                                           intersect_geoms, **kwargs)

                    if dataset:
                        mosaic_definition["tiles"][quadkey] = [
                            accessor(f) for f in dataset
                        ]

        return cls(**mosaic_definition)
Пример #13
0
def test_linearrings_all_nan():
    coords = np.full((4, 2), np.nan)
    with pytest.raises(pygeos.GEOSException):
        pygeos.linearrings(coords)
Пример #14
0
def test_linearrings_invalid_shape_scalar():
    with pytest.raises(ValueError):
        pygeos.linearrings((1, 1))
Пример #15
0
import numpy as np
import pygeos

point_polygon_testdata = (
    pygeos.points(np.arange(6), np.arange(6)),
    pygeos.box(2, 2, 4, 4),
)
point = pygeos.points(2, 2)
line_string = pygeos.linestrings([[0, 0], [1, 0], [1, 1]])
linear_ring = pygeos.linearrings(((0, 0), (0, 1), (1, 1), (1, 0), (0, 0)))
polygon = pygeos.polygons(
    ((0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)))
multi_point = pygeos.multipoints([[0.0, 0.0], [1.0, 2.0]])
multi_line_string = pygeos.multilinestrings([[[0.0, 0.0], [1.0, 2.0]]])
multi_polygon = pygeos.multipolygons([
    ((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)),
    ((0.1, 0.1), (0.1, 0.2), (0.2, 0.2), (0.2, 0.1)),
])
geometry_collection = pygeos.geometrycollections(
    [pygeos.points(51, -1),
     pygeos.linestrings([(52, -1), (49, 2)])])
point_z = pygeos.points(1.0, 1.0, 1.0)

all_types = (
    point,
    line_string,
    linear_ring,
    polygon,
    multi_point,
    multi_line_string,
    multi_polygon,
Пример #16
0
def test_linearrings(coordinates):
    actual = pygeos.linearrings(
        np.array(coordinates, dtype=np.float64),
        indices=np.zeros(len(coordinates), dtype=np.intp),
    )
    assert_geometries_equal(actual, pygeos.linearrings(coordinates))