Ejemplo n.º 1
0
def naive_compute_distance_similarity_matrix(sorted_detections, ground_truths):
    """Computes a similarity based on euclidean distance between all pairs of geometries in a naive fashion.

    Args:
        sorted_detections (ndarray, list) : A ndarray of detections stored as:

                * Bounding boxes for a given class where each row is a detection stored as:
                  ``[BoundingBox, confidence]``
                * Polygons for a given class where each row is a detection stored as:
                  ``[Polygon, confidence]``
                * Points for a given class where each row is a detection stored as:
                  ``[Point, confidence]``

        ground_truths (ndarray,list) : A ndarray of ground truth stored as:

            * Bounding boxes for a given class where each row is a ground truth stored as:
              ``[BoundingBox]``
            * Polygons for a given class where each row is a ground truth stored as:
              ``[Polygon]``
            * Points for a given class where each row is a ground truth stored as:
              ``[Point]``

    Returns:
        ndarray : An similarity matrix (#detections, #ground truth)
    """

    # We prepare the distance matrix (#detection, #gt)
    distance_matrix = np.zeros((sorted_detections.shape[0], len(ground_truths)))

    # Naive iterative distance matrix construction (Note: we iterate over the sorted detections)
    for k, ground_truth in enumerate(ground_truths):
        for m, detection in enumerate(sorted_detections):
            distance_matrix[m, k] = distance(centroid(detection[0]), centroid(ground_truth[0]))
    return 1 - distance_matrix
Ejemplo n.º 2
0
def convert_crs(gdf, current_crs="epsg:4326"):
    """[summary]

    Args:
        gdf ([type]): [description]

    Returns:
        [type]: [description]
    """
    if current_crs == "epsg:4326":
        lat = pygeos.geometry.get_y(pygeos.centroid(gdf['geometry'].iloc[0]))
        lon = pygeos.geometry.get_x(pygeos.centroid(gdf['geometry'].iloc[0]))
        # formula below based on :https://gis.stackexchange.com/a/190209/80697
        approximate_crs = "epsg:" + str(
            int(32700 - np.round((45 + lat) / 90, 0) * 100 +
                np.round((183 + lon) / 6, 0)))
    else:
        approximate_crs = "epsg:4326"

    #from pygeos/issues/95
    geometries = gdf['geometry']
    coords = pygeos.get_coordinates(geometries)
    transformer = pyproj.Transformer.from_crs(current_crs,
                                              approximate_crs,
                                              always_xy=True)
    new_coords = transformer.transform(coords[:, 0], coords[:, 1])
    result = pygeos.set_coordinates(geometries.copy(), np.array(new_coords).T)
    return result, approximate_crs
Ejemplo n.º 3
0
def moment_of_inertia(collection):
    """
    Computes the moment of inertia of the polygon.

    This treats each boundary point as a point-mass of 1.

    Thus, for constant unit mass at each boundary point,
    the MoI of this pointcloud is

    \sum_i d_{i,c}^2

    where c is the centroid of the polygon

    Altman's OS_1 measure, cited in Boyce and Clark (1964), also used in Weaver
    and Hess (1963).
    """
    ga = _cast(collection)
    coords = pygeos.get_coordinates(ga)
    geom_ixs = numpy.repeat(numpy.arange(len(ga)),
                            pygeos.get_num_coordinates(ga))
    centroids = pygeos.get_coordinates(pygeos.centroid(ga))[geom_ixs]
    squared_euclidean = numpy.sum((coords - centroids)**2, axis=1)
    dists = (pandas.DataFrame.from_dict(
        dict(d2=squared_euclidean,
             geom_ix=geom_ixs)).groupby("geom_ix").d2.sum()).values
    return pygeos.area(ga) / numpy.sqrt(2 * dists)
Ejemplo n.º 4
0
def close_gaps(df, tolerance):
    """Close gaps in LineString geometry where it should be contiguous.

    Snaps both lines to a centroid of a gap in between.

    """
    geom = df.geometry.values.data
    coords = pygeos.get_coordinates(geom)
    indices = pygeos.get_num_coordinates(geom)

    # generate a list of start and end coordinates and create point geometries
    edges = [0]
    i = 0
    for ind in indices:
        ix = i + ind
        edges.append(ix - 1)
        edges.append(ix)
        i = ix
    edges = edges[:-1]
    points = pygeos.points(np.unique(coords[edges], axis=0))

    buffered = pygeos.buffer(points, tolerance)

    dissolved = pygeos.union_all(buffered)

    exploded = [
        pygeos.get_geometry(dissolved, i)
        for i in range(pygeos.get_num_geometries(dissolved))
    ]

    centroids = pygeos.centroid(exploded)

    snapped = pygeos.snap(geom, pygeos.union_all(centroids), tolerance)

    return snapped
Ejemplo n.º 5
0
def export_csv(gdf,
               path,
               latlon=False,
               geom=True,
               lat_name='lat',
               lon_name='lot',
               geom_name='geometry',
               column_names=None,
               selection=False,
               virtual=True,
               chunksize=1000000,
               **kwargs):
    """ Writes GeoDataFrame to a CSV spatial file.
    """
    import pandas as pd

    sep = kwargs.pop('delimiter', ',')

    column_names = column_names or gdf.get_column_names(virtual=virtual,
                                                        strings=True)
    dtypes = gdf[column_names].dtypes
    fields = column_names[:]
    if latlon:
        fields.append(lat_name)
        fields.append(lon_name)
    if geom:
        fields.append(geom_name)

    geom_arr = gdf.geometry._geometry
    if selection not in [None, False] or gdf.filtered:
        mask = gdf.evaluate_selection_mask(selection)
        geom_arr = geom_arr.filter(mask)

    for i1, i2, chunks in gdf.evaluate_iterator(column_names,
                                                chunk_size=chunksize,
                                                selection=selection):
        if latlon:
            coordinates = pg.get_coordinates(
                pg.centroid(pg.from_wkb(geom_arr[i1:i2]))).T
            chunks.append(coordinates[0])
            chunks.append(coordinates[1])
        if geom:
            chunks.append(pg.to_wkt(pg.from_wkb(geom_arr[i1:i2])))
        chunk_dict = {col: values for col, values in zip(fields, chunks)}
        chunk_pdf = pd.DataFrame(chunk_dict)

        if i1 == 0:  # Only the 1st chunk should have a header and the rest will be appended
            mode = 'w'
            header = True
        else:
            mode = 'a'
            header = False

        chunk_pdf.to_csv(path_or_buf=path,
                         mode=mode,
                         header=header,
                         sep=sep,
                         index=False,
                         **kwargs)
Ejemplo n.º 6
0
def convert_point_to_constant_box(input_array, box_size):
    input_array = np.copy(input_array)
    for i in range(input_array.shape[0]):
        x, y = get_coordinates(centroid(input_array[i, 0]))[0]
        input_array[i, 0] = box(x - (box_size / 2),
                                y - (box_size / 2),
                                x + (box_size / 2),
                                y + (box_size / 2))

    return input_array
Ejemplo n.º 7
0
def as_points(x):
    """Convert an array of geometries to an array of centroid points.

    Args:
        x (numpy.ndarray): An array of geometries.

    Returns:
        numpy.ndarray: An array of points.

    """
    return centroid(x)
Ejemplo n.º 8
0
def close_gaps(gdf, tolerance):
    """Close gaps in LineString geometry where it should be contiguous.

    Snaps both lines to a centroid of a gap in between.

    Parameters
    ----------
    gdf : GeoDataFrame, GeoSeries
        GeoDataFrame  or GeoSeries containing LineString representation of a network.
    tolerance : float
        nodes within a tolerance will be snapped together

    Returns
    -------
    GeoSeries
    
    See also
    --------
    momepy.extend_lines
    momepy.remove_false_nodes

    """
    geom = gdf.geometry.values.data
    coords = pygeos.get_coordinates(geom)
    indices = pygeos.get_num_coordinates(geom)

    # generate a list of start and end coordinates and create point geometries
    edges = [0]
    i = 0
    for ind in indices:
        ix = i + ind
        edges.append(ix - 1)
        edges.append(ix)
        i = ix
    edges = edges[:-1]
    points = pygeos.points(np.unique(coords[edges], axis=0))

    buffered = pygeos.buffer(points, tolerance / 2)

    dissolved = pygeos.union_all(buffered)

    exploded = [
        pygeos.get_geometry(dissolved, i)
        for i in range(pygeos.get_num_geometries(dissolved))
    ]

    centroids = pygeos.centroid(exploded)

    snapped = pygeos.snap(geom, pygeos.union_all(centroids), tolerance)

    return gpd.GeoSeries(snapped, crs=gdf.crs)
Ejemplo n.º 9
0
def heatmap(pois,
            basemap_provider='OpenStreetMap',
            basemap_name='Mapnik',
            width='100%',
            height='100%',
            radius=10):
    """Generates a heatmap of the input POIs.

    Parameters:
        pois (GeoDataFrame): A POIs GeoDataFrame.
        basemap_provider (string): The basemap provider.
        basemap_name: The basemap itself as named by the provider.
            List and preview of available providers and their basemaps can be found in https://leaflet-extras.github.io/leaflet-providers/preview/
        width (integer or percentage): Width of the map in pixels or percentage (default: 100%).
        height (integer or percentage): Height of the map in pixels or percentage (default: 100%).
        radius (float): Radius of each point of the heatmap (default: 10).

    Returns:
        A Folium Map object displaying the heatmap generated from the POIs.
    """

    # Set the crs to WGS84
    if pois.geometry.crs == 'EPSG:4326':
        pass
    else:
        pois.geometry.to_crs('EPSG:4326')

    # Automatically center the map at the center of the gdf's bounding box
    bb = pois.geometry.total_bounds()
    map_center = pg.get_coordinates(pg.centroid(bb))[0].tolist()

    tiles, attribution, max_zoom = get_provider_info(basemap_provider,
                                                     basemap_name)
    heat_map = folium.Map(location=map_center,
                          tiles=tiles,
                          attr=attribution,
                          max_zoom=max_zoom,
                          width=width,
                          height=height)

    # Automatically set zoom level
    bounds = pg.total_bounds(bb)
    heat_map.fit_bounds(([bounds[1], bounds[0]], [bounds[3], bounds[2]]))

    # List comprehension to make list of lists
    heat_data = pois.geometry.get_coordinates(invert=True)
    # Plot it on the map
    HeatMap(heat_data, radius=radius).add_to(heat_map)

    return heat_map
Ejemplo n.º 10
0
def country_grid_gdp_filled(trans_network,
                            country,
                            data_path,
                            rough_grid_split=100,
                            from_main_graph=False):
    """[summary]

    Args:
        trans_network ([type]): [description]
        rough_grid_split (int, optional): [description]. Defaults to 100.

    Returns:
        [type]: [description]
    """
    if from_main_graph == True:
        node_df = trans_network.copy()
        envelop = pygeos.envelope(
            pygeos.multilinestrings(node_df.geometry.values))
        height = np.sqrt(pygeos.area(envelop) / rough_grid_split)
    else:
        node_df = trans_network.nodes.copy()
        node_df.geometry, approximate_crs = convert_crs(node_df)
        envelop = pygeos.envelope(
            pygeos.multilinestrings(node_df.geometry.values))
        height = np.sqrt(pygeos.area(envelop) / rough_grid_split)

    gdf_admin = pd.DataFrame(create_grid(create_bbox(node_df), height),
                             columns=['geometry'])

    #load data and convert to pygeos
    country_shape = gpd.read_file(os.path.join(data_path, 'GADM',
                                               'gadm36_levels.gpkg'),
                                  layer=0)
    country_shape = pd.DataFrame(
        country_shape.loc[country_shape.GID_0 == country])
    country_shape.geometry = pygeos.from_shapely(country_shape.geometry)

    gdf_admin = pygeos.intersection(gdf_admin, country_shape.geometry)
    gdf_admin = gdf_admin.loc[~pygeos.is_empty(gdf_admin.geometry)]

    gdf_admin['centroid'] = pygeos.centroid(gdf_admin.geometry)
    gdf_admin['km2'] = area(gdf_admin)
    gdf_admin['gdp'] = get_gdp_values(gdf_admin, data_path)
    gdf_admin = gdf_admin.loc[gdf_admin.gdp > 0].reset_index()
    gdf_admin['gdp_area'] = gdf_admin.gdp / gdf_admin['km2']

    return gdf_admin
Ejemplo n.º 11
0
def geojson(geojson,
            basemap_provider='OpenStreetMap',
            basemap_name='Mapnik',
            width='100%',
            height='100%',
            styled=False):
    """Plots into a Folium map.
    Parameters:
        geojson (dict): A geojson object.
        basemap_provider (string): The basemap provider.
        basemap_name: The basemap itself as named by the provider.
            List and preview of available providers and their basemaps can be found in https://leaflet-extras.github.io/leaflet-providers/preview/
         width (int|string): Width of the map in pixels or percentage (default: 100%).
         height (int|string): Height of the map in pixels or percentage (default: 100%).
         styled (bool): If True, follows the mapbox simple style, as proposed in https://github.com/mapbox/simplestyle-spec/tree/master/1.1.0.
    Returns:
        (object) A Folium Map object displaying the geoJSON.
    """
    df = gpd.GeoDataFrame.from_features(geojson['features'], crs="epsg:4326")

    bb = ymin, xmin, ymax, xmax = df.geometry.total_bounds
    map_center = pg.get_coordinates(pg.centroid(pg.box(xmin, ymin, xmax,
                                                       ymax)))[0]
    tiles, attribution, max_zoom = get_provider_info(basemap_provider,
                                                     basemap_name)
    m = folium.Map(location=map_center,
                   tiles=tiles,
                   attr=attribution,
                   max_zoom=max_zoom,
                   width=width,
                   height=height)
    m.fit_bounds([[xmin, ymin], [xmax, ymax]])

    if styled:
        folium.GeoJson(df,
                       name='geojson',
                       style_function=lambda x: dict(
                           color=x['properties']['stroke'],
                           fillColor=x['properties']['fill'],
                           fillOpacity=x['properties']['fill-opacity'],
                           opacity=0.1,
                           weight=x['properties']['stroke-width'])).add_to(m)
    else:
        folium.GeoJson(df, name='geojson').add_to(m)

    return m
    def _pandas(cls, column, **kwargs):

        shape = kwargs.get("shape")
        shape_format = kwargs.get("shape_format")
        column_shape_format = kwargs.get("column_shape_format")

        # Check that shape is given and given in the correct format
        if shape is not None:
            try:
                if shape_format == "wkt":
                    shape_ref = geos.from_wkt(shape)
                elif shape_format == "wkb":
                    shape_ref = geos.from_wkb(shape)
                elif shape_format == "geojson":
                    shape_ref = geos.from_geojson(shape)
                else:
                    raise NotImplementedError(
                        "Shape constructor method not implemented. Must be in WKT, WKB, or GeoJSON format."
                    )
            except:
                raise Exception("A valid reference shape was not given.")
        else:
            raise Exception("A shape must be provided for this method.")

        # Load the column into a pygeos Geometry vector from numpy array (Series not supported).
        if column_shape_format == "wkt":
            shape_test = geos.from_wkt(column.to_numpy(), on_invalid="ignore")
        elif column_shape_format == "wkb":
            shape_test = geos.from_wkb(column.to_numpy(), on_invalid="ignore")
        else:
            raise NotImplementedError(
                "Column values shape format not implemented.")

        # Allow for an array of reference shapes to be provided. Return a union of all the shapes in the array (Polygon or Multipolygon)
        shape_ref = geos.union_all(shape_ref)

        # Prepare the geometries
        geos.prepare(shape_ref)
        geos.prepare(shape_test)
        column_centroids = geos.centroid(shape_test)

        print(column_centroids)

        return pd.Series(geos.within(column_centroids, shape_ref))
Ejemplo n.º 13
0
def constructive(arr, operation, *args, **kwargs):
    if operation == 'boundary':
        geometries = pg.boundary(pg.from_wkb(arr), **kwargs)
    elif operation == 'buffer':
        geometries = pg.buffer(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'build_area':
        geometries = pg.build_area(pg.from_wkb(arr), **kwargs)
    elif operation == 'centroid':
        geometries = pg.centroid(pg.from_wkb(arr), **kwargs)
    elif operation == 'clip_by_rect':
        geometries = pg.clip_by_rect(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'convex_hull':
        geometries = pg.convex_hull(pg.from_wkb(arr), **kwargs)
    elif operation == 'delaunay_triangles':
        geometries = pg.delaunay_triangles(pg.from_wkb(arr), **kwargs)
    elif operation == 'envelope':
        geometries = pg.envelope(pg.from_wkb(arr), **kwargs)
    elif operation == 'extract_unique_points':
        geometries = pg.extract_unique_points(pg.from_wkb(arr), **kwargs)
    elif operation == 'make_valid':
        geometries = pg.make_valid(pg.from_wkb(arr), **kwargs)
    elif operation == 'normalize':
        geometries = pg.normalize(pg.from_wkb(arr), **kwargs)
    elif operation == 'offset_curve':
        geometries = pg.offset_curve(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'point_on_surface':
        geometries = pg.point_on_surface(pg.from_wkb(arr), **kwargs)
    elif operation == 'reverse':
        geometries = pg.reverse(pg.from_wkb(arr), **kwargs)
    elif operation == 'simplify':
        geometries = pg.simplify(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'snap':
        geometries = pg.snap(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'voronoi_polygons':
        geometries = pg.voronoi_polygons(pg.from_wkb(arr), **kwargs)
    else:
        warnings.warn(f'Operation {operation} not supported.')
        return None
    return pg.to_wkb(geometries)
Ejemplo n.º 14
0
 def _(shape: pygeos.Geometry):
     """
     if we know we're working with a pygeos polygon,
     then use pygeos.centroid
     """
     return pygeos.coordinates.get_coordinates(pygeos.centroid(shape)).squeeze()
Ejemplo n.º 15
0
# Is in EPSG:5070 but not recognized as such
print("Reading CHAT data...")
df = (read_dataframe(src_dir /
                     "WAFWA_CHAT_Lower48.shp").set_crs(DATA_CRS).drop(
                         columns=["ls_cond"]).rename(columns=field_map).rename(
                             columns={"chat_rank": "chatrank"}))

for col in chat_fields:
    df[col] = df[col].astype("uint8")

df = df.drop(columns=["hexagon_id"])

### Find the CHAT units that intersect with OK / TX input areas
# Use centerpoints, since input area roughly follows edges of hexes
points = pg.centroid(df.geometry.values.data)
tree = pg.STRtree(points)

for state in ["ok", "tx"]:
    print(f"Processing {state} CHAT...")
    input_area = pg.union_all(
        inputs_df.loc[inputs_df.inputs == f"{state}chat"].geometry.values.data)
    ix = tree.query(input_area, predicate="intersects")
    state_df = df.iloc[ix].reset_index(drop=True)

    # lcon not present for TX
    if state == "tx":
        state_df = state_df.drop(columns=["lcon"])
        # Reclassify chatrank to match blueprint integration rules.
        # First shift other values up one
        ix = state_df.chatrank >= 2
Ejemplo n.º 16
0
def test_centroid():
    actual = pygeos.centroid(polygon)
    assert pygeos.equals(actual, pygeos.points(1, 1))
Ejemplo n.º 17
0
def centroid(data):
    if compat.USE_PYGEOS:
        return pygeos.centroid(data)
    else:
        return _unary_geo("centroid", data)
Ejemplo n.º 18
0
def bbox_to_point(bbox):
    if isinstance(bbox[0], Geometry):
        return centroid(bbox[0])
    elif isinstance(bbox, (list, tuple, np.ndarray)):
        return centroid(box(*bbox[:4]))