Beispiel #1
0
def summarize_by_huc12(geometries):
    """Calculate current and projected urbanization for each decade from 2020 to
    2100.

    Parameters
    ----------
    geometries : Series of pygeos geometries, indexed by HUC12 id
    """

    index = []
    results = []
    for huc12, geometry in Bar(
        "Calculating Urbanization counts for HUC12", max=len(geometries)
    ).iter(geometries.iteritems()):
        zone_results = extract_by_geometry(
            [to_dict(geometry)], bounds=pg.total_bounds(geometry)
        )
        if zone_results is None:
            continue

        index.append(huc12)
        results.append(zone_results)

    cols = ["shape_mask", "urban"] + URBAN_YEARS
    df = pd.DataFrame(results, index=index)[cols]
    df = df.reset_index().rename(columns={"index": "id"}).round()
    df.columns = [str(c) for c in df.columns]

    df.to_feather(results_filename)
Beispiel #2
0
def summarize_raster_by_geometry(geometries,
                                 extract_func,
                                 outfilename,
                                 progress_label="",
                                 bounds=None,
                                 **kwargs):
    """Summarize values of input dataset by geometry and writes results to
    a feather file, with one column for shape_mask and one for each raster value.

    Parameters
    ----------
    geometries : Series of pygeos geometries, indexed by HUC12 / marine block
    extract_func : function that extracts results for each geometry
    outfilename : str
    progress_label : str
    """

    if bounds is not None:
        # select only those areas that overlap input area
        tree = pg.STRtree(geometries)
        ix = tree.query(pg.box(*bounds))
        geometries = geometries.iloc[ix].copy()

    if not len(geometries):
        return

    index = []
    results = []
    for ix, geometry in Bar(progress_label,
                            max=len(geometries)).iter(geometries.iteritems()):
        zone_results = extract_func([to_dict(geometry)],
                                    bounds=pg.total_bounds(geometry),
                                    **kwargs)
        if zone_results is None:
            continue

        index.append(ix)
        results.append(zone_results)

    if not len(results):
        return

    df = pd.DataFrame(results, index=index)

    results = df[["shape_mask"]].copy()
    results.index.name = "id"

    avg_cols = [c for c in df.columns if c.endswith("_avg")]

    # each column is an array of counts for each
    for col in df.columns.difference(["shape_mask"] + avg_cols):
        s = df[col].apply(pd.Series).fillna(0)
        s.columns = [f"{col}_{c}" for c in s.columns]
        results = results.join(s)

    if len(avg_cols) > 0:
        results = results.join(df[avg_cols]).round()

    results.reset_index().to_feather(outfilename)
    def __init__(self, geometry, crs, name):
        """Initialize a custom area from a pygeos geometry.

        Parameters
        ----------
        geometry : pygeos Geometry
        crs : pyproj CRS object
        name : string
            name of custom area
        """

        self.geometry = to_crs(geometry, crs, DATA_CRS)
        self.bounds = pg.total_bounds(self.geometry)
        # wrap geometry as a dict for rasterio
        self.shapes = np.asarray([to_dict(self.geometry[0])])
        self.name = name
Beispiel #4
0
def summarize_by_huc12(geometries):
    """Summarize by HUC12

    Parameters
    ----------
    geometries : Series of pygeos geometries, indexed by HUC12 id
    """

    # find the indexes of the geometries that overlap with SLR bounds; these are the only
    # ones that need to be analyzed for SLR impacts
    slr_bounds = gp.read_feather(slr_bounds_filename).geometry
    tree = pg.STRtree(geometries)
    ix = tree.query(slr_bounds.geometry.values.data[0], predicate="intersects")
    geometries = geometries.iloc[ix].copy()

    if not len(geometries):
        return

    results = []
    index = []
    for huc12, geometry in Bar(
        "Calculating SLR counts for HUC12", max=len(geometries)
    ).iter(geometries.iteritems()):
        zone_results = extract_by_geometry(
            [to_dict(geometry)], bounds=pg.total_bounds(geometry)
        )
        if zone_results is None:
            continue

        index.append(huc12)
        results.append(zone_results)

    df = pd.DataFrame(results, index=index)

    # reorder columns
    df = df[["shape_mask"] + list(df.columns.difference(["shape_mask"]))]
    # extract only areas that actually had SLR pixels
    df = df[df[df.columns[1:]].sum(axis=1) > 0]
    df.columns = [str(c) for c in df.columns]
    df = df.reset_index().rename(columns={"index": "id"}).round()
    df.to_feather(results_filename)
def summarize_blueprint_by_geometry(geometries, outfilename, marine=False):
    counts = []
    means = []
    index = []

    for ix, geometry in Bar(
        "Calculating overlap with Blueprint, Corridors, and Indicators",
        max=len(geometries),
    ).iter(geometries.iteritems()):
        zone_results = extract_by_geometry(
            [to_dict(geometry)],
            bounds=pg.total_bounds(geometry),
            marine=marine,
            zonal_means=True,
        )

        if zone_results is None:
            continue

        index.append(ix)
        counts.append(zone_results["counts"])
        means.append(zone_results["means"])

    count_df = pd.DataFrame(counts, index=index)
    mean_df = pd.DataFrame(means, index=index).round()
    mean_df.columns = [f"{c}_avg" for c in mean_df.columns]

    results = count_df[["shape_mask"]].copy()
    results.index.name = "id"

    ### Export the Blueprint, corridors, and indicators
    # each column is an array of counts for each
    for col in count_df.columns.difference(["shape_mask"]):
        s = count_df[col].apply(pd.Series).fillna(0)
        s.columns = [f"{col}_{c}" for c in s.columns]
        results = results.join(s)

    results = results.join(mean_df)

    results.reset_index().to_feather(outfilename)
Beispiel #6
0
async def get_aoi_map_image(geometry, center, zoom, width, height):
    """Create a rendered map image of the area of interest.

    Parameters
    ----------
    geometry : pygeos Geometry object (singular)
    center : [longitude, latitude]
    zoom : float
    width : int
        map width
    height : int
        map height

    Returns
    -------
    Image object
    """

    style = deepcopy(STYLE)
    style["sources"]["aoi"]["data"] = to_dict(geometry)

    params = {
        "style": style,
        "center": center,
        "zoom": zoom,
        "width": width,
        "height": height,
    }

    try:
        map = await render_mbgl_map(params)

    except Exception as ex:
        return None, f"Error generating aoi image ({type(ex)}): {ex}"

    return map, None
async def get_locator_map_image(longitude, latitude, bounds, geometry=None):
    """
    Create a rendered locator map image.

    If the bounds cover a large area, `geometry` will be rendered if available,
    otherwise a box covering the bounds will be rendered.  Otherwise, a
    representative point will be displayed on the map.

    Parameters
    ----------
    latitude : float
        latitude of area of interest marker
    longitude : float
        longitude of area of interest marker
    bounds : list-like of xmin, ymin, xmax, ymax
        bounds of geometry to locate on map
    geometry : pygeos.Geometry, optional (default: None)
        If present, will be used to render the area of interest if the bounds
        are very large.

    Returns
    -------
    Image object
    """

    style = deepcopy(LOCATOR_STYLE)

    xmin, ymin, xmax, ymax = bounds

    # If boundary is a large extent (more than 0.5 degree on edge)
    # and has big enough area then render geometry or a box instead of a point
    # NOTE: some multipart features cover large extent and small area, so these
    # drop out if we do not use area threshold.
    if xmax - ymax >= 0.5 or ymax - ymin >= 0.5:
        if geometry and pg.area(geometry) > 0.1:
            geometry = to_dict(geometry)

        else:
            geometry = ({
                "type":
                "Polygon",
                "coordinates": [[
                    [xmin, ymin],
                    [xmin, ymax],
                    [xmax, ymax],
                    [xmax, ymin],
                    [xmin, ymin],
                ]],
            }, )

        style["sources"]["feature"] = {"type": "geojson", "data": geometry}

    else:
        style["sources"]["marker"] = {
            "type": "geojson",
            "data": {
                "type": "Point",
                "coordinates": [longitude, latitude]
            },
        }

    params = {
        "style": style,
        "center": CENTER,
        "zoom": ZOOM,
        "width": WIDTH,
        "height": HEIGHT,
    }

    try:
        map = await render_mbgl_map(params)

    except Exception as ex:
        return None, f"Error generating locator image ({type(ex)}): {ex}"

    return map, None
Beispiel #8
0
    inputs.reset_index().rename(columns={
        "index": "value"
    }).set_index("inputs"),
    on="inputs",
)

write_dataframe(df, bnd_dir / "input_areas.fgb")
df.to_feather(out_dir / "boundaries/input_areas.feather")

# Rasterize to match the blueprint

df = pd.DataFrame(df[["geometry", "value"]].copy())
df.geometry = df.geometry.values.data

# convert to pairs of GeoJSON , value
shapes = df.apply(lambda row: (to_dict(row.geometry), row.value), axis=1)

print("Rasterizing inputs...")
with rasterio.open(blueprint_filename) as src:
    data = rasterize(shapes.values,
                     src.shape,
                     transform=src.transform,
                     dtype="uint8",
                     fill=255)
    profile = src.profile

outfilename = out_dir / "input_areas.tif"

with rasterio.open(outfilename, "w", **profile) as out:
    out.write(data, 1)
Beispiel #9
0
huc12["acres"] = (pg.area(huc12.geometry.values.data) * M2_ACRES).round().astype("uint")

# for those that touch the edge of the region, drop any that are not >= 50% in
# raster input area.  We are not able to use polygon intersection because it
# takes too long.
tree = pg.STRtree(huc12.geometry.values.data)
ix = tree.query(bnd, predicate="contains")

edge_df = huc12.loc[~huc12.id.isin(huc12.iloc[ix].id)].copy()
geometries = pd.Series(edge_df.geometry.values.data, index=edge_df.id)
drop_ids = []
for id, geometry in Bar(
    "Calculating HUC12 overlap with input area", max=len(geometries)
).iter(geometries.iteritems()):
    percent_overlap = calculate_percent_overlap(
        input_area_mask, [to_dict(geometry)], bounds=pg.total_bounds(geometry)
    )
    if percent_overlap < 50:
        drop_ids.append(id)

print(f"Dropping {len(drop_ids)} HUC12s that do not sufficiently overlap input areas")
huc12 = huc12.loc[~huc12.id.isin(drop_ids)].copy()

# extract geographic bounds
huc12_wgs84 = huc12.to_crs(GEO_CRS)
huc12 = huc12.join(huc12_wgs84.bounds)

# Save in EPSG:5070 for analysis
huc12.to_feather(analysis_dir / "huc12.feather")
write_dataframe(huc12, bnd_dir / "huc12.gpkg")