Exemple #1
0
# Comentar si se usa CPU
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
config.gpu_options.per_process_gpu_memory_fraction = 0.9
tf.keras.backend.set_session(tf.Session(config=config))
# comentar hasta aquí

region_name = "20015"

fp = 'C:/Users/ASUS/Desktop/ARAUCO/arauco/shapeFiles/20015/20015.shp'

data = gpd.read_file(fp)
caminos = data[data.TIPOUSO == "FCAM"]
caminos = caminos["geometry"]
caminos = gpd.GeoSeries(caminos)

start = time.time()

lengthComp = 0

parametros = {
    "1.1": 3,
    #"1.52": 9,
    #"1.8": 15
}

canchasList = []
caminitos = []
sensProp = 1.1
lengthComp = 3
Exemple #2
0
class TestDataFrameOps(TestCase):
    df = pd.DataFrame({
        'A': [1, 2, 3, 4, 5, 6],
        'B': ['a', 'b', 'c', 'x', 'y', 'z'],
        'C': [False, False, True, False, True, True],
        'D': [0.4, 0.5, 0.3, 0.3, 0.1, 0.4]
    })

    gdf = gpd.GeoDataFrame({
        'A': [1, 2, 3, 4, 5, 6],
        'B': ['a', 'b', 'c', 'x', 'y', 'z'],
        'C': [False, False, True, False, True, True],
        'D': [0.4, 0.5, 0.3, 0.3, 0.1, 0.4],
        'geometry':
        gpd.GeoSeries([
            shapely.wkt.loads('POINT(10 10)'),
            shapely.wkt.loads('POINT(10 20)'),
            shapely.wkt.loads('POINT(10 30)'),
            shapely.wkt.loads('POINT(20 30)'),
            shapely.wkt.loads('POINT(20 20)'),
            shapely.wkt.loads('POINT(20 10)'),
        ])
    })

    def test_data_frame_min(self):
        df2 = data_frame_min(TestDataFrameOps.df, 'D')
        self.assertIsInstance(df2, pd.DataFrame)
        self.assertEqual(len(df2), 1)
        self.assertEqual(list(df2.columns), ['A', 'B', 'C', 'D'])
        self.assertEqual(df2.iloc[0, 0], 5)
        self.assertEqual(df2.iloc[0, 1], 'y')
        self.assertEqual(df2.iloc[0, 2], True)
        self.assertEqual(df2.iloc[0, 3], 0.1)

    def test_data_frame_max(self):
        df2 = data_frame_max(TestDataFrameOps.df, 'D')
        self.assertIsInstance(df2, pd.DataFrame)
        self.assertEqual(len(df2), 1)
        self.assertEqual(list(df2.columns), ['A', 'B', 'C', 'D'])
        self.assertEqual(df2.iloc[0, 0], 2)
        self.assertEqual(df2.iloc[0, 1], 'b')
        self.assertEqual(df2.iloc[0, 2], False)
        self.assertEqual(df2.iloc[0, 3], 0.5)

    def test_data_frame_query(self):
        df2 = data_frame_query(TestDataFrameOps.df, "D >= 0.4 and B != 'b'")
        self.assertIsInstance(df2, pd.DataFrame)
        self.assertEqual(len(df2), 2)
        self.assertEqual(list(df2.columns), ['A', 'B', 'C', 'D'])
        self.assertEqual(df2.iloc[0, 0], 1)
        self.assertEqual(df2.iloc[0, 1], 'a')
        self.assertEqual(df2.iloc[0, 2], False)
        self.assertEqual(df2.iloc[0, 3], 0.4)
        self.assertEqual(df2.iloc[1, 0], 6)
        self.assertEqual(df2.iloc[1, 1], 'z')
        self.assertEqual(df2.iloc[1, 2], True)
        self.assertEqual(df2.iloc[1, 3], 0.4)

    def test_data_frame_query_with_geom(self):

        df2 = data_frame_query(TestDataFrameOps.gdf,
                               "not C and @almost_equals('10,10')")
        self.assertIsInstance(df2, gpd.GeoDataFrame)
        self.assertEqual(len(df2), 1)

        df2 = data_frame_query(TestDataFrameOps.gdf,
                               "not C and @contains('10,10')")
        self.assertIsInstance(df2, gpd.GeoDataFrame)
        self.assertEqual(len(df2), 1)

        df2 = data_frame_query(TestDataFrameOps.gdf,
                               "not C and @crosses('10,10')")
        self.assertIsInstance(df2, gpd.GeoDataFrame)
        self.assertEqual(len(df2), 0)

        df2 = data_frame_query(TestDataFrameOps.gdf,
                               "not C and @disjoint('10,10')")
        self.assertIsInstance(df2, gpd.GeoDataFrame)
        self.assertEqual(len(df2), 2)

        df2 = data_frame_query(TestDataFrameOps.gdf,
                               "not C and @intersects('19, 9, 21, 31')")
        self.assertIsInstance(df2, gpd.GeoDataFrame)
        self.assertEqual(len(df2), 1)

        df2 = data_frame_query(TestDataFrameOps.gdf,
                               "not C and @touches('10, 10, 20, 30')")
        self.assertIsInstance(df2, gpd.GeoDataFrame)
        self.assertEqual(len(df2), 3)

        df2 = data_frame_query(TestDataFrameOps.gdf,
                               "@within('19, 9, 21, 31')")
        self.assertIsInstance(df2, gpd.GeoDataFrame)
        self.assertEqual(len(df2), 3)
        self.assertEqual(list(df2.columns), ['A', 'B', 'C', 'D', 'geometry'])
        self.assertEqual(df2.iloc[0, 0], 4)
        self.assertEqual(df2.iloc[1, 0], 5)
        self.assertEqual(df2.iloc[2, 0], 6)
        self.assertEqual(df2.iloc[0, 1], 'x')
        self.assertEqual(df2.iloc[1, 1], 'y')
        self.assertEqual(df2.iloc[2, 1], 'z')
        self.assertEqual(df2.iloc[0, 2], False)
        self.assertEqual(df2.iloc[1, 2], True)
        self.assertEqual(df2.iloc[2, 2], True)
        self.assertEqual(df2.iloc[0, 3], 0.3)
        self.assertEqual(df2.iloc[1, 3], 0.1)
        self.assertEqual(df2.iloc[2, 3], 0.4)

        df2 = data_frame_query(TestDataFrameOps.gdf,
                               "not C and @within('19, 9, 21, 31')")
        self.assertIsInstance(df2, gpd.GeoDataFrame)
        self.assertEqual(len(df2), 1)
        self.assertEqual(list(df2.columns), ['A', 'B', 'C', 'D', 'geometry'])
        self.assertEqual(df2.iloc[0, 0], 4)
        self.assertEqual(df2.iloc[0, 1], 'x')
        self.assertEqual(df2.iloc[0, 2], False)
        self.assertEqual(df2.iloc[0, 3], 0.3)

        df2 = data_frame_query(
            TestDataFrameOps.gdf,
            "not C and geometry.within(@from_wkt('19, 9, 21, 31'))")
        self.assertIsInstance(df2, gpd.GeoDataFrame)
        self.assertEqual(len(df2), 1)
        self.assertEqual(list(df2.columns), ['A', 'B', 'C', 'D', 'geometry'])
        self.assertEqual(df2.iloc[0, 0], 4)
        self.assertEqual(df2.iloc[0, 1], 'x')
        self.assertEqual(df2.iloc[0, 2], False)
        self.assertEqual(df2.iloc[0, 3], 0.3)
    pts_in_this_poly = []

    # Now loop over all points with index j.
    for j, pt in pts.iterrows():
        if poly.geometry.contains(pt.geometry):
            # Then it's a hit! Add it to the list,
            # and drop it so we have less hunting.
            pts_in_this_poly.append(pt.geometry)
            pts = pts.drop([j])

    # We could do all sorts, like grab a property of the
    # points, but let's just append the number of them.
    pts_in_polys.append(len(pts_in_this_poly))

# Add the number of points for each poly to the dataframe.
polygons['number of points'] = gpd.GeoSeries(pts_in_polys)

#############
import geopandas as gpd
import pandas as pd

polys = grid.copy()
polys['PolyID'] = polys.index
points2 = points.copy()

dfsjoin = gpd.sjoin(polys, points2)  #Spatial join Points to polygons
dfpivot = pd.pivot_table(dfsjoin,
                         index='PolyID',
                         columns='Food',
                         aggfunc={'Food': len})
dfpivot.columns = dfpivot.columns.droplevel()
Exemple #4
0
def compute_screen_line_counts(feed: "Feed", screen_lines: gpd.GeoDataFrame,
                               dates: List[str]) -> pd.DataFrame:
    """
    Find all the Feed trips active on the given YYYYMMDD dates whose shapes
    intersect the given GeoDataFrame of screen lines, that is, of straight WGS84
    LineStrings.
    Compute the intersection times and directions for each trip.

    Return a DataFrame with the columns

    - ``'date'``
    - ``'trip_id'``
    - ``'route_id'``
    - ``'route_short_name'``
    - ``'shape_id'``: shape ID of the trip
    - ``'screen_line_id'``: ID of the screen line as specified in ``screen_lines`` or as
      assigned after the fact.
    - ``'crossing_distance'``: distance along the trip shape of the screen line
      intersection
      ``'crossing_time'``: time that the trip's vehicle crosses
      the scren line; one trip could cross multiple times
    - ``'crossing_direction'``: 1 or -1; 1 indicates trip travel from the
      left side to the right side of the screen line;
      -1 indicates trip travel in the  opposite direction

    Notes:

    - Assume the Feed's stop times DataFrame has an accurate ``shape_dist_traveled`` column.
    - Assume that trips travel in the same direction as their shapes, an assumption
      that is part of the GTFS.
    - Assume that the screen line is straight and simple.
    - Probably does not give correct results for trips with self-intersecting shapes.
    - The algorithm works as follows

        1. Find the trip shapes that intersect the screen lines.
        2. For each such shape and screen line, compute the intersection points, the distance
           of the point along the shape, and the orientation of the screen line relative to
           the shape.
        3. For each given date, restrict to trips active on the
           date and interpolate a stop time for the intersection point using
           the ``shape_dist_traveled`` column.
        4. Use that interpolated time as the crossing time of the trip vehicle.

    """
    dates = feed.subset_dates(dates)
    if not dates:
        return pd.DataFrame()

    # Get shapes as GeoDataFrame
    shapes_g = feed.geometrize_shapes(use_utm=True)

    # Convert screen lines to UTM
    crs = shapes_g.crs
    screen_lines = screen_lines.to_crs(crs)

    # Create screen line IDs if necessary
    n = screen_lines.shape[0]
    if "screen_line_id" not in screen_lines.columns:
        screen_lines["screen_line_id"] = hp.make_ids(n, "sl")

    # Make a vector in the direction of each screen line to calculate crossing orientation.
    # Does not work in case of a bent screen line.
    p1 = screen_lines.geometry.map(lambda x: np.array(x.coords[0]))
    p2 = screen_lines.geometry.map(lambda x: np.array(x.coords[-1]))
    screen_lines["screen_line_vector"] = p2 - p1

    # Get intersection points of shapes and screen lines
    g0 = (
        # Only keep shapes that intersect screen lines to reduce computations
        gpd.sjoin(shapes_g, screen_lines.filter(
            ["screen_line_id",
             "geometry"])).merge(screen_lines, on="screen_line_id").assign(
                 geometry_x=lambda x: gpd.GeoSeries(x.geometry_x, crs=crs)
             ).set_geometry("geometry_x")
        # Compute intersection points
        .assign(int_point=lambda x: x.geometry_x.intersection(
            gpd.GeoSeries(x.geometry_y, crs=crs))))

    # Unpack multipoint intersections to yield a new GeoDataFrame
    records = []
    for row in g0.itertuples(index=False):
        if isinstance(row.int_point, sg.Point):
            intersections = [row.int_point]
        else:
            intersections = row.int_point
        for int_point in intersections:
            record = {
                "shape_id": row.shape_id,
                "screen_line_id": row.screen_line_id,
                "geometry": row.geometry_x,
                "int_point": int_point,
                "screen_line_vector": row.screen_line_vector,
            }
            records.append(record)

    g = gpd.GeoDataFrame.from_records(records)
    g.crs = crs

    # Get distance (in meters) of each intersection point along shape
    g["crossing_dist"] = g.apply(lambda x: x.geometry.project(x.int_point),
                                 axis=1)

    # Build a tiny vector along each shape
    p2 = g.apply(lambda x: x.geometry.interpolate(x.crossing_dist + 1),
                 axis=1).map(lambda x: np.array(x.coords[0]))
    p1 = g.int_point.map(lambda x: np.array(x.coords[0]))
    g["shape_vector"] = p2 - p1

    # Compute crossing direction by taking the vector cross product of
    # the shape vector and the screen line vector
    det = g.apply(
        lambda x: np.linalg.det(
            np.array([x.shape_vector, x.screen_line_vector])),
        axis=1,
    )
    g["crossing_direction"] = det.map(lambda x: 1 if x >= 0 else -1)

    # Convert to feed distance units
    converter = hp.get_convert_dist("m", feed.dist_units)
    g["crossing_dist"] = g["crossing_dist"].map(converter)

    # Summarize work so far into a lookup table
    h = (
        g.filter([
            "shape_id", "screen_line_id", "crossing_direction", "crossing_dist"
        ]).set_index("shape_id").sort_values(
            ["shape_id",
             "crossing_dist"])  # Need this sorting for interpolation to work
    )

    # Get stop times of trips whose shapes lie in h
    st = (
        feed.trips.loc[lambda x: x.shape_id.isin(h.index)]
        # Merge in route short names and stop times
        .merge(feed.routes[["route_id",
                            "route_short_name"]]).merge(feed.stop_times)
        # Keep only non-NaN departure times
        .loc[lambda x: x.departure_time.notna()]
        # Convert to seconds past midnight
        .assign(departure_time=lambda x: x.departure_time.map(
            hp.timestr_to_seconds)))

    # Compute crossing times by date
    records = []
    ta = feed.compute_trip_activity(dates)
    for date in dates:
        # Subset to trips active on date and merge with g
        ids = ta.loc[lambda x: x[date] == 1, "trip_id"]
        f = st.loc[lambda x: x.trip_id.isin(ids)].sort_values([
            "trip_id", "shape_dist_traveled"
        ])  # Need this sorting for interpolation to work

        # Get crossing time for each trip
        for tid, group in f.groupby("trip_id"):
            sid = group["shape_id"].iat[0]
            rid = group["route_id"].iat[0]
            rsn = group["route_short_name"].iat[0]
            dists = group["shape_dist_traveled"].values
            times = group["departure_time"].values
            crossing_dists = h.loc[[sid], "crossing_dist"].values
            crossing_times = np.interp(crossing_dists, dists, times)
            for i, row in enumerate(h.loc[[sid]].itertuples(index=False)):
                record = {
                    "date": date,
                    "trip_id": tid,
                    "route_id": group.route_id.iat[0],
                    "route_short_name": group.route_short_name.iat[0],
                    "shape_id": group.shape_id.iat[0],
                    "screen_line_id": row.screen_line_id,
                    "crossing_direction": row.crossing_direction,
                    "crossing_distance": row.crossing_dist,
                    "crossing_time": crossing_times[i],
                }
                records.append(record)

    result = pd.DataFrame.from_records(records).assign(
        crossing_time=lambda x: x.crossing_time.map(
            lambda x: hp.timestr_to_seconds(x, inverse=True)))
    return result
Exemple #5
0
def do_your_thang(img_dir, out_path, path_t, saved_model, w, Ovr, f, timeline):

    truths = gpd.read_file(path_t)
    crs = truths.crs
    # print('\nCascading truths for analysis...')
    truths = gpd.GeoSeries(cascaded_union(truths['geometry']))
    truths = gpd.GeoDataFrame(geometry=truths, crs=crs)

    total = get_number(img_dir, '*tif')

    count = 1
    for pic in glob.glob(img_dir + '/*.tif'):

        if timeline:
            print('########## \
                  Timeline Image: %s / %s \
                      ##########' % (count, total))

        fn = get_name(pic)
        out_dir = out_path + '/' + fn

        ### Build subfolders
        if os.path.isdir(out_dir) is False:
            os.makedirs(out_dir)
            os.makedirs(out_dir + '/tiles')
            os.makedirs(out_dir + '/predictions')
            os.makedirs(out_dir + '/map')
            os.makedirs(out_dir + '/metrics')
        tiles_dir = out_dir + '/tiles'
        pred_dir = out_dir + '/predictions'
        map_dir = out_dir + '/map'
        met_dir = out_dir + '/metrics'

        ### Split mosic into tiles
        print('Splitting image: %s...' % fn)
        with suppress_stdout():  ### suppress the long output
            Split.split_image(input=pic,
                              output_dir=tiles_dir,
                              patch_w=w,
                              patch_h=w,
                              adj_overlay_x=Ovr,
                              adj_overlay_y=Ovr,
                              out_format=f)
        os.remove('split_image_info.txt')

        ### Remove tiles that don't intersect ground truths & Re-number
        Filter.remove(tiles_dir, truths, overlap_only=True)

        ### convert to .JPEG
        Convert.to_jpg(tiles_dir)

        ### create & save predictions
        UNet_Predict.deploy_model(saved_model, tiles_dir, pred_dir)

        ### create map from prediction tiles
        if Map.build_map(tiles_dir, pred_dir, map_dir, fn, truths):

            ### calculate performance metrics (and save True Posities for timeline)
            Metrics.run_metrics(truths, map_dir, pic, fn, met_dir, timeline)

        count += 1

    top_folder = out_path + '/Maps'
    ### create topfolder to consolidate prediction/timeline output
    if os.path.isdir(top_folder) is False:
        os.makedirs(top_folder)

        ### copy output maps to top folder
        for file in glob.glob(out_path + '/**/map/*cascaded_map*'):
            shutil.copy(file, top_folder)

    return
Exemple #6
0
 def get_perimeter():
     """Creates a perimeter polygon from points"""
     d_array = get_geometry_data('Perimeter')
     aoi = Polygon([tuple(p) for p in d_array])
     return gpd.GeoDataFrame(geometry=gpd.GeoSeries(aoi))
Exemple #7
0
def to_feature_collection(shape):
    """
    Create a GeoJSON FeatureCollection object for the given shapely.geometry :shape:.
    """
    collection = geopandas.GeoSeries([shape]).__geo_interface__
    return dict(collection)
Exemple #8
0
def plot_dataframe(df,
                   column=None,
                   cmap=None,
                   color=None,
                   ax=None,
                   cax=None,
                   categorical=False,
                   legend=False,
                   scheme=None,
                   k=5,
                   vmin=None,
                   vmax=None,
                   markersize=None,
                   figsize=None,
                   legend_kwds=None,
                   categories=None,
                   classification_kwds=None,
                   missing_kwds=None,
                   aspect="auto",
                   **style_kwds):
    """
    Plot a GeoDataFrame.

    Generate a plot of a GeoDataFrame with matplotlib.  If a
    column is specified, the plot coloring will be based on values
    in that column.

    Parameters
    ----------
    df : GeoDataFrame
        The GeoDataFrame to be plotted.  Currently Polygon,
        MultiPolygon, LineString, MultiLineString and Point
        geometries can be plotted.
    column : str, np.array, pd.Series (default None)
        The name of the dataframe column, np.array, or pd.Series to be plotted.
        If np.array or pd.Series are used then it must have same length as
        dataframe. Values are used to color the plot. Ignored if `color` is
        also set.
    cmap : str (default None)
        The name of a colormap recognized by matplotlib.
    color : str (default None)
        If specified, all objects will be colored uniformly.
    ax : matplotlib.pyplot.Artist (default None)
        axes on which to draw the plot
    cax : matplotlib.pyplot Artist (default None)
        axes on which to draw the legend in case of color map.
    categorical : bool (default False)
        If False, cmap will reflect numerical values of the
        column being plotted.  For non-numerical columns, this
        will be set to True.
    legend : bool (default False)
        Plot a legend. Ignored if no `column` is given, or if `color` is given.
    scheme : str (default None)
        Name of a choropleth classification scheme (requires mapclassify).
        A mapclassify.MapClassifier object will be used
        under the hood. Supported are all schemes provided by mapclassify (e.g.
        'BoxPlot', 'EqualInterval', 'FisherJenks', 'FisherJenksSampled',
        'HeadTailBreaks', 'JenksCaspall', 'JenksCaspallForced',
        'JenksCaspallSampled', 'MaxP', 'MaximumBreaks',
        'NaturalBreaks', 'Quantiles', 'Percentiles', 'StdMean',
        'UserDefined'). Arguments can be passed in classification_kwds.
    k : int (default 5)
        Number of classes (ignored if scheme is None)
    vmin : None or float (default None)
        Minimum value of cmap. If None, the minimum data value
        in the column to be plotted is used.
    vmax : None or float (default None)
        Maximum value of cmap. If None, the maximum data value
        in the column to be plotted is used.
    markersize : str or float or sequence (default None)
        Only applies to point geometries within a frame.
        If a str, will use the values in the column of the frame specified
        by markersize to set the size of markers. Otherwise can be a value
        to apply to all points, or a sequence of the same length as the
        number of points.
    figsize : tuple of integers (default None)
        Size of the resulting matplotlib.figure.Figure. If the argument
        axes is given explicitly, figsize is ignored.
    legend_kwds : dict (default None)
        Keyword arguments to pass to matplotlib.pyplot.legend() or
        matplotlib.pyplot.colorbar().
        Additional accepted keywords when `scheme` is specified:

        fmt : string
            A formatting specification for the bin edges of the classes in the
            legend. For example, to have no decimals: ``{"fmt": "{:.0f}"}``.
        labels : list-like
            A list of legend labels to override the auto-generated labels.
            Needs to have the same number of elements as the number of
            classes (`k`).
    categories : list-like
        Ordered list-like object of categories to be used for categorical plot.
    classification_kwds : dict (default None)
        Keyword arguments to pass to mapclassify
    missing_kwds : dict (default None)
        Keyword arguments specifying color options (as style_kwds)
        to be passed on to geometries with missing values in addition to
        or overwriting other style kwds. If None, geometries with missing
        values are not plotted.
    aspect : 'auto', 'equal', None or float (default 'auto')
        Set aspect of axis. If 'auto', the default aspect for map plots is 'equal'; if
        however data are not projected (coordinates are long/lat), the aspect is by
        default set to 1/cos(df_y * pi/180) with df_y the y coordinate of the middle of
        the GeoDataFrame (the mean of the y range of bounding box) so that a long/lat
        square appears square in the middle of the plot. This implies an
        Equirectangular projection. If None, the aspect of `ax` won't be changed. It can
        also be set manually (float) as the ratio of y-unit to x-unit.

    **style_kwds : dict
        Style options to be passed on to the actual plot function, such
        as ``edgecolor``, ``facecolor``, ``linewidth``, ``markersize``,
        ``alpha``.

    Returns
    -------
    ax : matplotlib axes instance

    """
    if "colormap" in style_kwds:
        warnings.warn(
            "'colormap' is deprecated, please use 'cmap' instead "
            "(for consistency with matplotlib)",
            FutureWarning,
        )
        cmap = style_kwds.pop("colormap")
    if "axes" in style_kwds:
        warnings.warn(
            "'axes' is deprecated, please use 'ax' instead "
            "(for consistency with pandas)",
            FutureWarning,
        )
        ax = style_kwds.pop("axes")
    if column is not None and color is not None:
        warnings.warn(
            "Only specify one of 'column' or 'color'. Using 'color'.",
            UserWarning)
        column = None

    try:
        import matplotlib.pyplot as plt
    except ImportError:
        raise ImportError(
            "The matplotlib package is required for plotting in geopandas. "
            "You can install it using 'conda install -c conda-forge matplotlib' or "
            "'pip install matplotlib'.")

    if ax is None:
        if cax is not None:
            raise ValueError("'ax' can not be None if 'cax' is not.")
        fig, ax = plt.subplots(figsize=figsize)

    if aspect == "auto":
        if df.crs and df.crs.is_geographic:
            bounds = df.total_bounds
            y_coord = np.mean([bounds[1], bounds[3]])
            ax.set_aspect(1 / np.cos(y_coord * np.pi / 180))
            # formula ported from R package sp
            # https://github.com/edzer/sp/blob/master/R/mapasp.R
        else:
            ax.set_aspect("equal")
    elif aspect is not None:
        ax.set_aspect(aspect)

    # GH 1555
    # if legend_kwds set, copy so we don't update it in place
    if legend_kwds is not None:
        legend_kwds = legend_kwds.copy()

    if df.empty:
        warnings.warn(
            "The GeoDataFrame you are attempting to plot is "
            "empty. Nothing has been displayed.",
            UserWarning,
        )
        return ax

    if isinstance(markersize, str):
        markersize = df[markersize].values

    if column is None:
        return plot_series(df.geometry,
                           cmap=cmap,
                           color=color,
                           ax=ax,
                           figsize=figsize,
                           markersize=markersize,
                           aspect=aspect,
                           **style_kwds)

    # To accept pd.Series and np.arrays as column
    if isinstance(column, (np.ndarray, pd.Series)):
        if column.shape[0] != df.shape[0]:
            raise ValueError(
                "The dataframe and given column have different number of rows."
            )
        else:
            values = column

            # Make sure index of a Series matches index of df
            if isinstance(values, pd.Series):
                values = values.reindex(df.index)
    else:
        values = df[column]

    if pd.api.types.is_categorical_dtype(values.dtype):
        if categories is not None:
            raise ValueError(
                "Cannot specify 'categories' when column has categorical dtype"
            )
        categorical = True
    elif values.dtype is np.dtype("O") or categories:
        categorical = True

    nan_idx = np.asarray(pd.isna(values), dtype="bool")

    # Define `values` as a Series
    if categorical:
        if cmap is None:
            cmap = "tab10"

        cat = pd.Categorical(values, categories=categories)
        categories = list(cat.categories)

        # values missing in the Categorical but not in original values
        missing = list(np.unique(values[~nan_idx & cat.isna()]))
        if missing:
            raise ValueError(
                "Column contains values not listed in categories. "
                "Missing categories: {}.".format(missing))

        values = cat.codes[~nan_idx]
        vmin = 0 if vmin is None else vmin
        vmax = len(categories) - 1 if vmax is None else vmax

    if scheme is not None:
        if classification_kwds is None:
            classification_kwds = {}
        if "k" not in classification_kwds:
            classification_kwds["k"] = k

        binning = _mapclassify_choro(values[~nan_idx], scheme,
                                     **classification_kwds)
        # set categorical to True for creating the legend
        categorical = True
        if legend_kwds is not None and "labels" in legend_kwds:
            if len(legend_kwds["labels"]) != binning.k:
                raise ValueError("Number of labels must match number of bins, "
                                 "received {} labels for {} bins".format(
                                     len(legend_kwds["labels"]), binning.k))
            else:
                categories = list(legend_kwds.pop("labels"))
        else:
            fmt = "{:.2f}"
            if legend_kwds is not None and "fmt" in legend_kwds:
                fmt = legend_kwds.pop("fmt")
            categories = binning.get_legend_classes(fmt)
        values = np.array(binning.yb)

    # fill values with placeholder where were NaNs originally to map them properly
    # (after removing them in categorical or scheme)
    if categorical:
        for n in np.where(nan_idx)[0]:
            values = np.insert(values, n, values[0])

    mn = values[~np.isnan(values)].min() if vmin is None else vmin
    mx = values[~np.isnan(values)].max() if vmax is None else vmax

    # decompose GeometryCollections
    geoms, multiindex = _flatten_multi_geoms(df.geometry, prefix="Geom")
    values = np.take(values, multiindex, axis=0)
    nan_idx = np.take(nan_idx, multiindex, axis=0)
    expl_series = geopandas.GeoSeries(geoms)

    geom_types = expl_series.type
    poly_idx = np.asarray((geom_types == "Polygon")
                          | (geom_types == "MultiPolygon"))
    line_idx = np.asarray((geom_types == "LineString")
                          | (geom_types == "MultiLineString")
                          | (geom_types == "LinearRing"))
    point_idx = np.asarray((geom_types == "Point")
                           | (geom_types == "MultiPoint"))

    # plot all Polygons and all MultiPolygon components in the same collection
    polys = expl_series[poly_idx & np.invert(nan_idx)]
    subset = values[poly_idx & np.invert(nan_idx)]
    if not polys.empty:
        _plot_polygon_collection(ax,
                                 polys,
                                 subset,
                                 vmin=mn,
                                 vmax=mx,
                                 cmap=cmap,
                                 **style_kwds)

    # plot all LineStrings and MultiLineString components in same collection
    lines = expl_series[line_idx & np.invert(nan_idx)]
    subset = values[line_idx & np.invert(nan_idx)]
    if not lines.empty:
        _plot_linestring_collection(ax,
                                    lines,
                                    subset,
                                    vmin=mn,
                                    vmax=mx,
                                    cmap=cmap,
                                    **style_kwds)

    # plot all Points in the same collection
    points = expl_series[point_idx & np.invert(nan_idx)]
    subset = values[point_idx & np.invert(nan_idx)]
    if not points.empty:
        if isinstance(markersize, np.ndarray):
            markersize = np.take(markersize, multiindex, axis=0)
            markersize = markersize[point_idx & np.invert(nan_idx)]
        _plot_point_collection(ax,
                               points,
                               subset,
                               vmin=mn,
                               vmax=mx,
                               markersize=markersize,
                               cmap=cmap,
                               **style_kwds)

    if missing_kwds is not None and not expl_series[nan_idx].empty:
        if color:
            if "color" not in missing_kwds:
                missing_kwds["color"] = color

        merged_kwds = style_kwds.copy()
        merged_kwds.update(missing_kwds)

        plot_series(expl_series[nan_idx], ax=ax, **merged_kwds)

    if legend and not color:

        if legend_kwds is None:
            legend_kwds = {}
        if "fmt" in legend_kwds:
            legend_kwds.pop("fmt")

        from matplotlib.lines import Line2D
        from matplotlib.colors import Normalize
        from matplotlib import cm

        norm = style_kwds.get("norm", None)
        if not norm:
            norm = Normalize(vmin=mn, vmax=mx)
        n_cmap = cm.ScalarMappable(norm=norm, cmap=cmap)
        if categorical:
            patches = []
            for value, cat in enumerate(categories):
                patches.append(
                    Line2D(
                        [0],
                        [0],
                        linestyle="none",
                        marker="o",
                        alpha=style_kwds.get("alpha", 1),
                        markersize=10,
                        markerfacecolor=n_cmap.to_rgba(value),
                        markeredgewidth=0,
                    ))
            if missing_kwds is not None:
                if "color" in merged_kwds:
                    merged_kwds["facecolor"] = merged_kwds["color"]
                patches.append(
                    Line2D(
                        [0],
                        [0],
                        linestyle="none",
                        marker="o",
                        alpha=merged_kwds.get("alpha", 1),
                        markersize=10,
                        markerfacecolor=merged_kwds.get("facecolor", None),
                        markeredgecolor=merged_kwds.get("edgecolor", None),
                        markeredgewidth=merged_kwds.get(
                            "linewidth",
                            1 if merged_kwds.get("edgecolor", False) else 0),
                    ))
                categories.append(merged_kwds.get("label", "NaN"))
            legend_kwds.setdefault("numpoints", 1)
            legend_kwds.setdefault("loc", "best")
            ax.legend(patches, categories, **legend_kwds)
        else:

            if cax is not None:
                legend_kwds.setdefault("cax", cax)
            else:
                legend_kwds.setdefault("ax", ax)

            n_cmap.set_array([])
            ax.get_figure().colorbar(n_cmap, **legend_kwds)

    plt.draw()
    return ax
Exemple #9
0
def complete_unique_geoms():
    # output unique geometries and sum of all
    # project locations associated with that geometry

    unique_geo_df = gpd.GeoDataFrame()

    if active_data.size > 0:

        unique_active_data = active_data.loc[
            active_data.geom_val != "None"].copy(deep=True)

    if active_data.size > 0 and unique_active_data.size > 0:

        # creating geodataframe
        geo_df = gpd.GeoDataFrame()
        # location id
        geo_df["project_location_id"] = unique_active_data["project_location_id"]
        geo_df["project_location_id"].fillna(unique_active_data["project_id"],
                                             inplace=True)
        geo_df["project_location_id"] = geo_df["project_location_id"].astype(str)

        # assuming even split of total project dollars is "max" dollars
        # that project location could receive
        geo_df["dollars"] = unique_active_data["adjusted_val"]
        # geometry for each project location
        geo_df["geometry"] = gpd.GeoSeries(unique_active_data["geom_val"])

        # # write full to geojson
        # full_geo_json = geo_df.to_json()
        # full_geo_file = open(dir_working + "/full.geojson", "w")
        # json.dump(json.loads(full_geo_json), full_geo_file, indent=4)
        # full_geo_file.close()


        # string version of geometry used to determine duplicates
        geo_df["str_geo_hash"] = geo_df["geometry"].astype(str).apply(
            lambda z: str_sha1_hash(z))

        # create and set unique index
        geo_df['index'] = range(0, len(geo_df))
        geo_df = geo_df.set_index('index')

        # group project locations by geometry using str_geo_hash field
        # and for each unique geometry get the sum of dollars for
        # all project locations with that geometry
        sum_unique = geo_df.groupby(by='str_geo_hash')['dollars'].sum()

        # get count of locations for each unique geom
        geo_df['ones'] = 1 #(pd.Series(np.ones(len(geo_df)))).values
        sum_count = geo_df.groupby(by='str_geo_hash')['ones'].sum()

        # create list of project location ids for unique geoms
        cat_plids = geo_df.groupby(by='str_geo_hash')['project_location_id'].apply(
            lambda z: '|'.join(list(z)))

        # temporary dataframe with
        #   unique geometry
        #   location_count
        #   dollar sums
        # which can be used to merge with original geo_df dataframe
        tmp_geo_df = gpd.GeoDataFrame()
        tmp_geo_df['unique_dollars'] = sum_unique
        tmp_geo_df['location_count'] = sum_count
        tmp_geo_df['project_location_ids'] = cat_plids

        tmp_geo_df['str_geo_hash'] = tmp_geo_df.index

        # merge geo_df with tmp_geo_df
        new_geo_df = geo_df.merge(tmp_geo_df, how='inner', on="str_geo_hash")
        # drops duplicate rows
        new_geo_df.drop_duplicates(subset="str_geo_hash", inplace=True)
        # gets rid of str_geo_hash column
        new_geo_df.drop('str_geo_hash', axis=1, inplace=True)

        # create final output geodataframe with index, unique_dollars
        # and unique geometry
        # unique_geo_df = gpd.GeoDataFrame()
        unique_geo_df["geometry"] = gpd.GeoSeries(new_geo_df["geometry"])
        unique_geo_df["unique_dollars"] = new_geo_df["unique_dollars"]
        unique_geo_df["location_count"] = new_geo_df["location_count"]
        unique_geo_df["project_location_ids"] = new_geo_df["project_location_ids"]

        # unique_geo_df['index'] = range(len(unique_geo_df))


    # write unique to geojson
    unique_geo_json = unique_geo_df.to_json()
    unique_geo_file = open(dir_working + "/unique.geojson", "w")
    json.dump(json.loads(unique_geo_json), unique_geo_file, indent=4)
    unique_geo_file.close()
Exemple #10
0
from rasterio.plot import show
from rasterio.mask import mask
from shapely.geometry import box
import geopandas as gpd
from fiona.crs import from_epsg
import os
import matplotlib.pyplot as plt
import gdal
import glob

# Openf file with the roofs for a single block
src = fiona.open("blockRoofs.shp")
pol = MultiPolygon([shape(building["geometry"]) for building in src])

rasterfiles = glob.glob('/media/HD/raster/*[!.aux.xml,!.dbf,!.py,!.csv,!.qpj]')
gdf = gpd.GeoSeries(pol)
basePath = '/media/HD/blockRaster/'

l = len(rasterfiles)

print("Start cropping")
i = 0
for raster in rasterfiles:
    i += 1
    print(f'Completed at {i*100/l:.2}%\r', end="")
    data = rasterio.open(raster)
    clippedImg, clippedTrans = mask(dataset=data, shapes=gdf, crop=True)
    out_meta = data.meta.copy()
    out_meta.update({
        "driver": "GTiff",
        "height": clippedImg.shape[1],
Exemple #11
0
def plot_series(s,
                cmap=None,
                color=None,
                ax=None,
                figsize=None,
                aspect="auto",
                **style_kwds):
    """
    Plot a GeoSeries.

    Generate a plot of a GeoSeries geometry with matplotlib.

    Parameters
    ----------
    s : Series
        The GeoSeries to be plotted. Currently Polygon,
        MultiPolygon, LineString, MultiLineString and Point
        geometries can be plotted.
    cmap : str (default None)
        The name of a colormap recognized by matplotlib. Any
        colormap will work, but categorical colormaps are
        generally recommended. Examples of useful discrete
        colormaps include:

            tab10, tab20, Accent, Dark2, Paired, Pastel1, Set1, Set2

    color : str (default None)
        If specified, all objects will be colored uniformly.
    ax : matplotlib.pyplot.Artist (default None)
        axes on which to draw the plot
    figsize : pair of floats (default None)
        Size of the resulting matplotlib.figure.Figure. If the argument
        ax is given explicitly, figsize is ignored.
    aspect : 'auto', 'equal', None or float (default 'auto')
        Set aspect of axis. If 'auto', the default aspect for map plots is 'equal'; if
        however data are not projected (coordinates are long/lat), the aspect is by
        default set to 1/cos(s_y * pi/180) with s_y the y coordinate of the middle of
        the GeoSeries (the mean of the y range of bounding box) so that a long/lat
        square appears square in the middle of the plot. This implies an
        Equirectangular projection. If None, the aspect of `ax` won't be changed. It can
        also be set manually (float) as the ratio of y-unit to x-unit.
    **style_kwds : dict
        Color options to be passed on to the actual plot function, such
        as ``edgecolor``, ``facecolor``, ``linewidth``, ``markersize``,
        ``alpha``.

    Returns
    -------
    ax : matplotlib axes instance
    """
    if "colormap" in style_kwds:
        warnings.warn(
            "'colormap' is deprecated, please use 'cmap' instead "
            "(for consistency with matplotlib)",
            FutureWarning,
        )
        cmap = style_kwds.pop("colormap")
    if "axes" in style_kwds:
        warnings.warn(
            "'axes' is deprecated, please use 'ax' instead "
            "(for consistency with pandas)",
            FutureWarning,
        )
        ax = style_kwds.pop("axes")

    try:
        import matplotlib.pyplot as plt
    except ImportError:
        raise ImportError(
            "The matplotlib package is required for plotting in geopandas. "
            "You can install it using 'conda install -c conda-forge matplotlib' or "
            "'pip install matplotlib'.")

    if ax is None:
        fig, ax = plt.subplots(figsize=figsize)

    if aspect == "auto":
        if s.crs and s.crs.is_geographic:
            bounds = s.total_bounds
            y_coord = np.mean([bounds[1], bounds[3]])
            ax.set_aspect(1 / np.cos(y_coord * np.pi / 180))
            # formula ported from R package sp
            # https://github.com/edzer/sp/blob/master/R/mapasp.R
        else:
            ax.set_aspect("equal")
    elif aspect is not None:
        ax.set_aspect(aspect)

    if s.empty:
        warnings.warn(
            "The GeoSeries you are attempting to plot is "
            "empty. Nothing has been displayed.",
            UserWarning,
        )
        return ax

    if s.is_empty.all():
        warnings.warn(
            "The GeoSeries you are attempting to plot is "
            "composed of empty geometries. Nothing has been displayed.",
            UserWarning,
        )
        return ax

    # if cmap is specified, create range of colors based on cmap
    values = None
    if cmap is not None:
        values = np.arange(len(s))
        if hasattr(cmap, "N"):
            values = values % cmap.N
        style_kwds["vmin"] = style_kwds.get("vmin", values.min())
        style_kwds["vmax"] = style_kwds.get("vmax", values.max())

    # decompose GeometryCollections
    geoms, multiindex = _flatten_multi_geoms(s.geometry, prefix="Geom")
    values = np.take(values, multiindex, axis=0) if cmap else None
    expl_series = geopandas.GeoSeries(geoms)

    geom_types = expl_series.type
    poly_idx = np.asarray((geom_types == "Polygon")
                          | (geom_types == "MultiPolygon"))
    line_idx = np.asarray((geom_types == "LineString")
                          | (geom_types == "MultiLineString")
                          | (geom_types == "LinearRing"))
    point_idx = np.asarray((geom_types == "Point")
                           | (geom_types == "MultiPoint"))

    # plot all Polygons and all MultiPolygon components in the same collection
    polys = expl_series[poly_idx]
    if not polys.empty:
        # color overrides both face and edgecolor. As we want people to be
        # able to use edgecolor as well, pass color to facecolor
        facecolor = style_kwds.pop("facecolor", None)
        if color is not None:
            facecolor = color

        values_ = values[poly_idx] if cmap else None
        _plot_polygon_collection(ax,
                                 polys,
                                 values_,
                                 facecolor=facecolor,
                                 cmap=cmap,
                                 **style_kwds)

    # plot all LineStrings and MultiLineString components in same collection
    lines = expl_series[line_idx]
    if not lines.empty:
        values_ = values[line_idx] if cmap else None
        _plot_linestring_collection(ax,
                                    lines,
                                    values_,
                                    color=color,
                                    cmap=cmap,
                                    **style_kwds)

    # plot all Points in the same collection
    points = expl_series[point_idx]
    if not points.empty:
        values_ = values[point_idx] if cmap else None
        _plot_point_collection(ax,
                               points,
                               values_,
                               color=color,
                               cmap=cmap,
                               **style_kwds)

    plt.draw()
    return ax
def decomposeSite(deims_site, admin_zones, zone_id, zone_name, debug=False):
    """Decompose a site by administrative zones.

    deims_site: site to decompose (gpd.GeoDataFrame)
    admin_zones: admin zones/regions to break deims_site into (gpd.GeoDataFrame)
    zone_id: column name of the zone ID in admin_zones (str)
    zone_name: column name of the zone name in admin_zones (str)
    debug: whether or not to plot the results for visual checking (bool)

    Returns the resulting GDF.
    """

    # convert CRS of dataset to match admin zones
    # this will be the CRS of the output GDF
    deims_site = deims_site.to_crs(admin_zones.crs)

    # check which zones intersect the LTSER site
    ltser_zones = gpd.overlay(deims_site,admin_zones,how='intersection')

    # add original zones for area comparison, setting correct geometry
    # this is necessary to align the comparison geometry correctly:
    # comparing straight away with admin_zones.geometry.area doesn't
    # align the rows correctly
    ltser_zones = pd.merge(ltser_zones,admin_zones,on=zone_id)
    ltser_zones = ltser_zones.set_geometry('geometry_x')

    # add intersection area/zone area as new column
    # full_areas definition necessary because pd.merge only allows for one geoseries
    full_areas = gpd.GeoSeries(ltser_zones['geometry_y'])
    ltser_zones['intersection_ratio'] = ltser_zones.geometry.area/full_areas.area

    # construct GDF of cropped zones + ratio of area intersection
    gdf_out = gpd.GeoDataFrame(
        {
            'zone_id': ltser_zones[zone_id].astype('string'),
            'zone_name': ltser_zones[zone_name+'_x'].astype('string'),
            'geometry': ltser_zones['geometry_x'],
            'area_ratio': ltser_zones['intersection_ratio']
        },
        crs = ltser_zones.crs
    )

    # optional visual check of intersection adds full geometry of zones
    if debug:
        # add and set full geometry
        gdf_out['debug_geometry'] = ltser_zones['geometry_y']
        gdf_out = gdf_out.set_geometry('debug_geometry')

        # plot overlap - no need to return object since plots directly to (presumably) stdout
        fig, ax = plt.subplots(figsize = (10,10))
        ax.set_axis_off()
        ax.set_title('Zones (blue) intersecting LTSER site (red)')
        gdf_out.plot(ax=ax)
        deims_site.boundary.plot(color='r',ax=ax)

        # drop debug_geometry column so output is identical to non-debug
        gdf_out.drop(columns='debug_geometry',inplace=True)
        gdf_out = gdf_out.set_geometry('geometry')
        return gdf_out
    else:
        return gdf_out
Exemple #13
0
def calculate_risk():
    shapefile = 'iho/iho.shp'
    oceans = gpd.read_file(shapefile)
    #list of webpages of the weather stations
    weather_stations = [
        'https://www.infoclimat.fr/observations-meteo/temps-reel/kemi/02864.html',
        'https://www.infoclimat.fr/observations-meteo/temps-reel/helsinki-malmi/02975.html',
        'https://www.infoclimat.fr/observations-meteo/temps-reel/bagaskar/02984.html',
        'https://www.infoclimat.fr/observations-meteo/temps-reel/market/02993.html',
        'https://www.infoclimat.fr/observations-meteo/temps-reel/nyhamn/02980.html',
        'https://www.infoclimat.fr/observations-meteo/temps-reel/oulu/02875.html',
        'https://www.infoclimat.fr/observations-meteo/temps-reel/pori/02952.html'
    ]
    #list of zone coordinates
    station_coordinates = gpd.GeoSeries([
        Polygon([(66, 24.58), (65.355, 24.58), (65.355, 25.37, 64.63, 25.37)]),
        Polygon([(64.63, 23.6), (64.025, 23.6), (64.025, 23.15),
                 (63.575, 23.15)]),
        Polygon([(63.575, 21.07), (63.24, 21.07),
                 (63.24, 21.77, 62.26, 21.77)]),
        Polygon([(62.26, 21.8), (50, 21.8), (60.13, 19), (60.13, 19.935)]),
        Polygon([(59.97, 19.935), (59.97, 21.12), (60.52, 21.12),
                 (60.52, 22.61)]),
        Polygon([(59.77, 22.61), (59.77, 23.485), (59.93, 23.485),
                 (59.93, 24.535)]),
        Polygon([(60.25, 24.535), (60.25, 26.01), (60.37, 26.01), (60.37, 27)])
    ])
    df1 = gpd.GeoDataFrame({'geometry': station_coordinates})
    results = []  #to put the zones coordinates
    item = 0
    res = {}
    ocean = gpd.read_file(shapefile)
    df2 = gpd.GeoDataFrame({'geometry': station_coordinates})
    for i in weather_stations:
        r = requests.get(i)
        try:
            soup = BeautifulSoup(r.text, 'html.parser')
            temp_max = soup.find_all(class_='displayer')[0].get_text()
            regex = re.search("[[\s]*([\S]*])", temp_max)
            if regex != None:
                temp_max = regex.group(1)
            else:
                temp_max = 0
            temp_min = soup.find_all(class_='displayer')[1].get_text()
            regex = re.search("[\s]*([\S]*)", temp_min)
            regex = re.search("([0-9])", regex.group(1))
            if regex != None:
                temp_min = regex.group(1)
            else:
                temp_min = 0
            temp_min = int(temp_min)
            try:
                rain = soup.find_all(class_='displayer')[2].get_text()
            except:
                rain = 0
            if (temp_min > 10) and (temp_max > 15):
                risk = 5.8 * temp_max + rain * 2
                if risk < 96:
                    color = "green"  #in more than 50% of cases, in those conditions there will be a bloom
                elif risk < 104:
                    color = "yellow"  #in more than 80% of cases, in those conditions there will be a bloom
                else:
                    color = "red"  #in more than 95%...
            else:
                color = "blue"
        except:
            color = "blue"
        res_intersection = gpd.overlay(df1, df2, how='intersection')
        results.append(res_intersection)
        ocean = gpd.GeoDataFrame({'geometry': results})
        item = item + 1
        risk = 0
        color = "blue"

    return ocean
Exemple #14
0
    def RequestData(self, request, inInfo, outInfo):
        import xarray as xr
        import numpy as np
        import geopandas as gpd
        import pandas as pd
        from shapely.geometry import box, Point, LineString
        from shapely.affinity import translate
        from vtk import vtkPolyData, vtkAppendPolyData, vtkCompositeDataSet, vtkMultiBlockDataSet
        import math
        import time

        # check mandatory fields
        if self._tablename is None or self._xcol is None or self._ycol is None or self._zcol is None:
            return 1

        t0 = time.time()
        #df = pd.read_csv(self._tablename, low_memory=False)

        df = pd.read_csv(self._tablename,
                         encoding=self._tableencoding,
                         low_memory=False)
        print("len(df)", len(df))
        if (len(df)) == 0:
            return

        # calculate coordinates
        xs = df[self._xcol]
        ys = df[self._ycol]
        zs = df[self._zcol]
        # create point
        geom = gpd.GeoSeries(map(Point, zip(xs, ys, zs)))

        # create line segment when possible
        if self._xcol2 is not None or self._ycol2 is not None or self._zcol2 is not None:
            # we can define only one (changed) column for 2nd point
            self._xcol2 = self._xcol2 if self._xcol2 is not None else self._xcol
            self._ycol2 = self._ycol2 if self._ycol2 is not None else self._ycol
            self._zcol2 = self._zcol2 if self._zcol2 is not None else self._zcol
            xs2 = df[self._xcol2]
            ys2 = df[self._ycol2]
            zs2 = df[self._zcol2]
            # create line segment
            geom2 = gpd.GeoSeries(map(Point, zip(xs2, ys2, zs2)))
            geom = gpd.GeoSeries(map(LineString, zip(geom, geom2)))

        # create geodataframe to build output
        df = gpd.GeoDataFrame(df, geometry=geom)

        # group to multiblock
        if self._tablecol is not None:
            df = df.sort_values(self._tablecol).set_index(self._tablecol)

        vtk_blocks = _NCubeGeometryOnTopography(df, None)
        if len(vtk_blocks) > 0:
            print("vtk_blocks", len(vtk_blocks))
            mb = vtkMultiBlockDataSet.GetData(outInfo, 0)
            mb.SetNumberOfBlocks(len(vtk_blocks))
            rowidx = 0
            for (label, polyData) in vtk_blocks:
                #print (rowidx, label)
                mb.SetBlock(rowidx, polyData)
                mb.GetMetaData(rowidx).Set(vtkCompositeDataSet.NAME(), label)
                rowidx += 1

        t1 = time.time()
        print("t1-t0", t1 - t0)

        return 1
census_us_county_gdf = census_us_county_gdf[census_us_county_gdf.STATEFP != "02"]
census_us_county_gdf = census_us_county_gdf[
    ["STATEFP", "COUNTYFP", "GEOID", "NAME", "geometry"]
]

# 15005, Kalawao County has 86 people is combined with 15009,
# Maui County population 167,417 in the eleciton results
# to match the election results, we combine them here under Maui
poly = shp.ops.cascaded_union(
    census_us_county_gdf[census_us_county_gdf.GEOID.isin(["15005", "15009"])][
        "geometry"
    ]
)
census_us_county_gdf.loc[
    (census_us_county_gdf.GEOID == "15009"), "geometry"
] = gpd.GeoSeries(poly)
census_us_county_gdf = census_us_county_gdf.drop(
    census_us_county_gdf[census_us_county_gdf.GEOID == "15005"].index
)

ak_shapefiles_path = pkg_resources.resource_filename('op_verification', "data/county_shapefiles/2013-HD-ProclamationPlan")
alaska_districts = gpd.read_file(ak_shapefiles_path)
alaska_districts["STATEFP"] = "02"
alaska_districts["COUNTYFP"] = alaska_districts["District_N"].apply(
    lambda x: x.zfill(3)
)
alaska_districts["GEOID"] = alaska_districts["STATEFP"].map(str) + alaska_districts[
    "COUNTYFP"
].map(str)
alaska_districts["NAME"] = alaska_districts["District_N"].apply(
    lambda x: "district " + x
Exemple #16
0
def network_false_nodes(gdf):
    """
    Check topology of street network and eliminate nodes of degree 2 by joining
    affected edges.

    Parameters
    ----------
    gdf : GeoDataFrame
        GeoDataFrame containg edge representation of street network.
    Returns
    -------
    gdf : GeoDataFrame
    """
    streets = gdf.copy().explode()
    streets.reset_index(inplace=True)
    sindex = streets.sindex

    false_points = []
    print("Identifying false points...")
    for idx, row in tqdm(streets.iterrows(), total=streets.shape[0]):
        line = row["geometry"]
        l_coords = list(line.coords)
        # network_w = network.drop(idx, axis=0)['geometry']  # ensure that it wont intersect itself
        start = Point(l_coords[0])
        end = Point(l_coords[-1])

        # find out whether ends of the line are connected or not
        possible_first_index = list(sindex.intersection(start.bounds))
        possible_first_matches = streets.iloc[possible_first_index]
        possible_first_matches_clean = possible_first_matches.drop(idx, axis=0)
        real_first_matches = possible_first_matches_clean[
            possible_first_matches_clean.intersects(start)]

        possible_second_index = list(sindex.intersection(end.bounds))
        possible_second_matches = streets.iloc[possible_second_index]
        possible_second_matches_clean = possible_second_matches.drop(idx,
                                                                     axis=0)
        real_second_matches = possible_second_matches_clean[
            possible_second_matches_clean.intersects(end)]

        if len(real_first_matches) == 1:
            false_points.append(start)
        if len(real_second_matches) == 1:
            false_points.append(end)

    false_xy = []
    for p in false_points:
        false_xy.append([p.x, p.y])

    false_xy_unique = [list(x) for x in set(tuple(x) for x in false_xy)]

    false_unique = []
    for p in false_xy_unique:
        false_unique.append(Point(p[0], p[1]))

    geoms = streets.geometry

    print("Merging segments...")
    for point in tqdm(false_unique):
        matches = list(geoms[geoms.intersects(point)].index)
        idx = max(geoms.index) + 1
        try:
            multiline = geoms[matches[0]].union(geoms[matches[1]])
            linestring = shapely.ops.linemerge(multiline)
            geoms = geoms.append(gpd.GeoSeries(linestring, index=[idx]))
            geoms = geoms.drop(matches)
        except IndexError:
            import warnings

            warnings.warn(
                "An exception during merging occured. Lines at point [{x}, {y}] were not merged."
                .format(x=point.x, y=point.y))

    geoms_gdf = gpd.GeoDataFrame(geometry=geoms)
    geoms_gdf.crs = streets.crs
    streets = geoms_gdf.explode().reset_index(drop=True)
    return streets
Exemple #17
0
def get_reference_sl(metadata, settings):
    """
    Allows the user to manually digitize a reference shoreline that is used seed
    the shoreline detection algorithm. The reference shoreline helps to detect 
    the outliers, making the shoreline detection more robust.

    KV WRL 2018

    Arguments:
    -----------
    metadata: dict
        contains all the information about the satellite images that were downloaded
    settings: dict with the following keys
        'inputs': dict
            input parameters (sitename, filepath, polygon, dates, sat_list)
        'cloud_thresh': float
            value between 0 and 1 indicating the maximum cloud fraction in 
            the cropped image that is accepted
        'cloud_mask_issue': boolean
            True if there is an issue with the cloud mask and sand pixels
            are erroneously being masked on the images
        'output_epsg': int
            output spatial reference system as EPSG code

    Returns:
    -----------
    reference_shoreline: np.array
        coordinates of the reference shoreline that was manually digitized. 
        This is also saved as a .pkl and .geojson file.

    """

    sitename = settings['inputs']['sitename']
    filepath_data = settings['inputs']['filepath']
    pts_coords = []
    # check if reference shoreline already exists in the corresponding folder
    filepath = os.path.join(filepath_data, sitename)
    filename = sitename + '_reference_shoreline.pkl'
    # if it exist, load it and return it
    if filename in os.listdir(filepath):
        print('Reference shoreline already exists and was loaded')
        with open(
                os.path.join(filepath, sitename + '_reference_shoreline.pkl'),
                'rb') as f:
            refsl = pickle.load(f)
        return refsl

    # otherwise get the user to manually digitise a shoreline on S2, L8 or L5 images (no L7 because of scan line error)
    else:
        # first try to use S2 images (10m res for manually digitizing the reference shoreline)
        if 'S2' in metadata.keys():
            satname = 'S2'
            filepath = SDS_tools.get_filepath(settings['inputs'], satname)
            filenames = metadata[satname]['filenames']
        # if no S2 images, try L8  (15m res in the RGB with pansharpening)
        elif not 'S2' in metadata.keys() and 'L8' in metadata.keys():
            satname = 'L8'
            filepath = SDS_tools.get_filepath(settings['inputs'], satname)
            filenames = metadata[satname]['filenames']
        # if no S2 images and no L8, use L5 images (L7 images have black diagonal bands making it
        # hard to manually digitize a shoreline)
        elif not 'S2' in metadata.keys() and not 'L8' in metadata.keys(
        ) and 'L5' in metadata.keys():
            satname = 'L5'
            filepath = SDS_tools.get_filepath(settings['inputs'], satname)
            filenames = metadata[satname]['filenames']
        else:
            raise Exception(
                'You cannot digitize the shoreline on L7 images (because of gaps in the images), add another L8, S2 or L5 to your dataset.'
            )

        # create figure
        fig, ax = plt.subplots(1, 1, figsize=[18, 9], tight_layout=True)
        mng = plt.get_current_fig_manager()
        mng.window.showMaximized()
        # loop trhough the images
        for i in range(len(filenames)):

            # read image
            fn = SDS_tools.get_filenames(filenames[i], filepath, satname)
            im_ms, georef, cloud_mask, im_extra, im_QA, im_nodata = preprocess_single(
                fn, satname, settings['cloud_mask_issue'])

            # calculate cloud cover
            cloud_cover = np.divide(
                sum(sum(cloud_mask.astype(int))),
                (cloud_mask.shape[0] * cloud_mask.shape[1]))

            # skip image if cloud cover is above threshold
            if cloud_cover > settings['cloud_thresh']:
                continue

            # rescale image intensity for display purposes
            im_RGB = rescale_image_intensity(im_ms[:, :, [2, 1, 0]],
                                             cloud_mask, 99.9)

            # plot the image RGB on a figure
            ax.axis('off')
            ax.imshow(im_RGB)

            # decide if the image if good enough for digitizing the shoreline
            ax.set_title(
                'Press <right arrow> if image is clear enough to digitize the shoreline.\n'
                +
                'If the image is cloudy press <left arrow> to get another image',
                fontsize=14)
            # set a key event to accept/reject the detections (see https://stackoverflow.com/a/15033071)
            # this variable needs to be immuatable so we can access it after the keypress event
            skip_image = False
            key_event = {}

            def press(event):
                # store what key was pressed in the dictionary
                key_event['pressed'] = event.key

            # let the user press a key, right arrow to keep the image, left arrow to skip it
            # to break the loop the user can press 'escape'
            while True:
                btn_keep = plt.text(1.1,
                                    0.9,
                                    'keep ⇨',
                                    size=12,
                                    ha="right",
                                    va="top",
                                    transform=ax.transAxes,
                                    bbox=dict(boxstyle="square",
                                              ec='k',
                                              fc='w'))
                btn_skip = plt.text(-0.1,
                                    0.9,
                                    '⇦ skip',
                                    size=12,
                                    ha="left",
                                    va="top",
                                    transform=ax.transAxes,
                                    bbox=dict(boxstyle="square",
                                              ec='k',
                                              fc='w'))
                btn_esc = plt.text(0.5,
                                   0,
                                   '<esc> to quit',
                                   size=12,
                                   ha="center",
                                   va="top",
                                   transform=ax.transAxes,
                                   bbox=dict(boxstyle="square", ec='k',
                                             fc='w'))
                plt.draw()
                fig.canvas.mpl_connect('key_press_event', press)
                plt.waitforbuttonpress()
                # after button is pressed, remove the buttons
                btn_skip.remove()
                btn_keep.remove()
                btn_esc.remove()
                # keep/skip image according to the pressed key, 'escape' to break the loop
                if key_event.get('pressed') == 'right':
                    skip_image = False
                    break
                elif key_event.get('pressed') == 'left':
                    skip_image = True
                    break
                elif key_event.get('pressed') == 'escape':
                    plt.close()
                    raise StopIteration(
                        'User cancelled checking shoreline detection')
                else:
                    plt.waitforbuttonpress()

            if skip_image:
                ax.clear()
                continue
            else:
                # create two new buttons
                add_button = plt.text(0,
                                      0.9,
                                      'add',
                                      size=16,
                                      ha="left",
                                      va="top",
                                      transform=plt.gca().transAxes,
                                      bbox=dict(boxstyle="square",
                                                ec='k',
                                                fc='w'))
                end_button = plt.text(1,
                                      0.9,
                                      'end',
                                      size=16,
                                      ha="right",
                                      va="top",
                                      transform=plt.gca().transAxes,
                                      bbox=dict(boxstyle="square",
                                                ec='k',
                                                fc='w'))
                # add multiple reference shorelines (until user clicks on <end> button)
                pts_sl = np.expand_dims(np.array([np.nan, np.nan]), axis=0)
                geoms = []
                while 1:
                    add_button.set_visible(False)
                    end_button.set_visible(False)
                    # update title (instructions)
                    ax.set_title(
                        'Click points along the shoreline (enough points to capture the beach curvature).\n'
                        + 'Start at one end of the beach.\n' +
                        'When finished digitizing, click <ENTER>',
                        fontsize=14)
                    plt.draw()

                    # let user click on the shoreline
                    pts = ginput(n=50000, timeout=1e9, show_clicks=True)
                    pts_pix = np.array(pts)
                    # convert pixel coordinates to world coordinates
                    pts_world = SDS_tools.convert_pix2world(
                        pts_pix[:, [1, 0]], georef)

                    # interpolate between points clicked by the user (1m resolution)
                    pts_world_interp = np.expand_dims(np.array(
                        [np.nan, np.nan]),
                                                      axis=0)
                    for k in range(len(pts_world) - 1):
                        pt_dist = np.linalg.norm(pts_world[k, :] -
                                                 pts_world[k + 1, :])
                        xvals = np.arange(0, pt_dist)
                        yvals = np.zeros(len(xvals))
                        pt_coords = np.zeros((len(xvals), 2))
                        pt_coords[:, 0] = xvals
                        pt_coords[:, 1] = yvals
                        phi = 0
                        deltax = pts_world[k + 1, 0] - pts_world[k, 0]
                        deltay = pts_world[k + 1, 1] - pts_world[k, 1]
                        phi = np.pi / 2 - np.math.atan2(deltax, deltay)
                        tf = transform.EuclideanTransform(
                            rotation=phi, translation=pts_world[k, :])
                        pts_world_interp = np.append(pts_world_interp,
                                                     tf(pt_coords),
                                                     axis=0)
                    pts_world_interp = np.delete(pts_world_interp, 0, axis=0)

                    # save as geometry (to create .geojson file later)
                    geoms.append(geometry.LineString(pts_world_interp))

                    # convert to pixel coordinates and plot
                    pts_pix_interp = SDS_tools.convert_world2pix(
                        pts_world_interp, georef)
                    pts_sl = np.append(pts_sl, pts_world_interp, axis=0)
                    ax.plot(pts_pix_interp[:, 0], pts_pix_interp[:, 1], 'r--')
                    ax.plot(pts_pix_interp[0, 0], pts_pix_interp[0, 1], 'ko')
                    ax.plot(pts_pix_interp[-1, 0], pts_pix_interp[-1, 1], 'ko')

                    # update title and buttons
                    add_button.set_visible(True)
                    end_button.set_visible(True)
                    ax.set_title(
                        'click on <add> to digitize another shoreline or on <end> to finish and save the shoreline(s)',
                        fontsize=14)
                    plt.draw()

                    # let the user click again (<add> another shoreline or <end>)
                    pt_input = ginput(n=1, timeout=1e9, show_clicks=False)
                    pt_input = np.array(pt_input)

                    # if user clicks on <end>, save the points and break the loop
                    if pt_input[0][0] > im_ms.shape[1] / 2:
                        add_button.set_visible(False)
                        end_button.set_visible(False)
                        plt.title('Reference shoreline saved as ' + sitename +
                                  '_reference_shoreline.pkl and ' + sitename +
                                  '_reference_shoreline.geojson')
                        plt.draw()
                        ginput(n=1, timeout=3, show_clicks=False)
                        plt.close()
                        break

                pts_sl = np.delete(pts_sl, 0, axis=0)
                # convert world image coordinates to user-defined coordinate system
                image_epsg = metadata[satname]['epsg'][i]
                pts_coords = SDS_tools.convert_epsg(pts_sl, image_epsg,
                                                    settings['output_epsg'])

                # save the reference shoreline as .pkl
                filepath = os.path.join(filepath_data, sitename)
                with open(
                        os.path.join(filepath,
                                     sitename + '_reference_shoreline.pkl'),
                        'wb') as f:
                    pickle.dump(pts_coords, f)

                # also store as .geojson in case user wants to drag-and-drop on GIS for verification
                for k, line in enumerate(geoms):
                    gdf = gpd.GeoDataFrame(geometry=gpd.GeoSeries(line))
                    gdf.index = [k]
                    gdf.loc[k, 'name'] = 'reference shoreline ' + str(k + 1)
                    # store into geodataframe
                    if k == 0:
                        gdf_all = gdf
                    else:
                        gdf_all = gdf_all.append(gdf)
                gdf_all.crs = {'init': 'epsg:' + str(image_epsg)}
                # convert from image_epsg to user-defined coordinate system
                gdf_all = gdf_all.to_crs(
                    {'init': 'epsg:' + str(settings['output_epsg'])})
                # save as geojson
                gdf_all.to_file(os.path.join(
                    filepath, sitename + '_reference_shoreline.geojson'),
                                driver='GeoJSON',
                                encoding='utf-8')

                print('Reference shoreline has been saved in ' + filepath)
                break

    # check if a shoreline was digitised
    if len(pts_coords) == 0:
        raise Exception(
            'No cloud free images are available to digitise the reference shoreline,'
            + 'download more images and try again')

    return pts_coords
Exemple #18
0
CHappyhill
"""
import os
if not os.path.exists('data'): os.makedirs('data')
if not os.path.exists('output'): os.makedirs('output')

import matplotlib.pyplot as plt
#
#import os
#os.getcwd()

from shapely.geometry import Point
import geopandas as gpd
wageningenCampus = Point([173994.1578792833, 444133.60329471016])
print(type(wageningenCampus))
gs = gpd.GeoSeries([wageningenCampus])
print(type(gs), len(gs))

from shapely.wkt import loads
WKTstring = 'POINT(173994.1578792833 444133.6032947102)'
gs = gpd.GeoSeries([loads(WKTstring)])
gs.crs = "EPSG:28992"  # specify manually the projection
gsBuffer = gs.buffer(100)
print(gs.geometry)
print(gsBuffer.geometry)

import pandas as pd
data = {
    'name': ['a', 'b', 'c'],
    'x': [173994.1578792833, 173974.1578792833, 173910.1578792833],
    'y': [444135.6032947102, 444186.6032947102, 444111.6032947102]
Exemple #19
0
Tests that raw data inputs function correctly.
"""

import sys
sys.path.insert(0, '../')
import geoplot as gplt
import unittest
import geopandas as gpd
import matplotlib.pyplot as plt
from shapely.geometry import Point, LineString
import numpy as np
import pandas as pd

# Point-type DataFrame input.
list_gaussian_points = gplt.utils.gaussian_points(n=4)
series_gaussian_points = gpd.GeoSeries(list_gaussian_points)
dataframe_gaussian_points = gpd.GeoDataFrame(
    geometry=series_gaussian_points).assign(hue_var=[1, 2, 3, 4])

# Polygon-type DataFrame input.
list_gaussian_polys = gplt.utils.gaussian_polygons(
    gplt.utils.gaussian_points(n=1000), n=2).append(
        gplt.utils.gaussian_multi_polygons(gplt.utils.gaussian_points(n=1000),
                                           n=2))
series_gaussian_polys = gpd.GeoSeries(list_gaussian_polys)
dataframe_gaussian_polys = gpd.GeoDataFrame(
    geometry=series_gaussian_polys).assign(hue_var=[1, 2, 3, 4])

# Hue input.
list_hue_values = [1, 2, 3, 4]
series_hue_values = pd.Series(list_hue_values)
Exemple #20
0
 def func(data, x, y, z):
     return geopandas.GeoSeries(
         geopandas.points_from_xy(data[x], data[y],
                                  data[z] if z in df.columns else None),
         index=data.index,
     )
def street_blocks_to_parking_spots():
    """
    Read in a shapefile containing the RPP blocks and save out a GeoJSON
    containing one point for every possible parking space on each block. 
    """

    rpp = gpd.read_file(
        'input/Residential_Parking_Permit_Blocks-shp/Residential_Parking_Permit_Blocks.shp'
    )
    rpp = drop_duplicate_geometries(rpp, print_counts=True)
    # rpp = rpp.to_crs(maryland_crs)

    # Rename block sides
    rpp['block_side'] = rpp['BLK_SIDE'].map({
        'AO': 'address only',
        'B': 'both sides',
        'V': 'even side',
        'O': 'odd side',
        'S': 'single building'
    })

    parking_dict = {}

    street_width = 10  # meters
    street_width_radians = 0.00003

    for idx, street in tqdm(rpp.iterrows(), total=len(rpp)):

        if street['OBJECTID'] == 1973107:
            # Multiple line segments on this street
            # rpp[rpp['OBJECTID'] == 1973107]
            continue

            # if idx > 10:
            #     break

            # if street['OBJECTID'] not in [
            #         1971375 # California
            #         , 1972138 # 19th
            #         , 1969724 # Mintwood Place
            #     ]:
            continue

        try:
            street_points = cut_street_into_points(street)
        except Exception as e:
            bad_objectid = street['OBJECTID']
            print(f'OBJECTID {bad_objectid} causes error: {e}')
            continue

        start_coord = street['geometry'].coords[0]
        start_lon = start_coord[0]
        start_lat = start_coord[1]
        end_coord = street['geometry'].coords[-1]
        end_lon = end_coord[0]
        end_lat = end_coord[1]

        geodesic = pyproj.Geod(ellps='WGS84')
        street_heading, _, _ = geodesic.inv(start_lon, start_lat, end_lon,
                                            end_lat)

        heading_right = (street_heading + 90)
        offset_right_x = math.sin(
            math.radians(heading_right)) * street_width_radians
        offset_right_y = math.cos(
            math.radians(heading_right)) * street_width_radians

        heading_left = (street_heading - 90)
        offset_left_x = math.sin(
            math.radians(heading_left)) * street_width_radians
        offset_left_y = math.cos(
            math.radians(heading_left)) * street_width_radians

        street_series = gpd.GeoSeries(street_points)
        # todo: determine which is side is even and odd based off of heading

        if street['block_side'] == 'both sides':
            street_series_odd = street_series.translate(xoff=offset_right_x,
                                                        yoff=offset_right_y)
            street_series_even = street_series.translate(xoff=offset_left_x,
                                                         yoff=offset_left_y)

            street_series_combined = pd.concat(
                [street_series_odd, street_series_even], ignore_index=True)

        elif street['block_side'] == 'even side':
            street_series_combined = street_series.translate(
                xoff=offset_left_x, yoff=offset_left_y)

        elif street['block_side'] == 'odd side':
            street_series_combined = street_series.translate(
                xoff=offset_right_x, yoff=offset_right_y)

        else:
            continue

        temp_df = pd.DataFrame()
        temp_df['geometry'] = street_series_combined
        temp_df['source_street_objectid'] = street['OBJECTID']
        temp_df['block_side'] = street['block_side']

        parking_dict[street['OBJECTID']] = temp_df

    df_dict = {}
    for d in parking_dict:
        df_dict[d] = pd.DataFrame(parking_dict[d], columns=['geometry'])

    parking_df = pd.concat(df_dict).reset_index()
    parking_df.rename(columns={'level_0': 'source_street_objectid'},
                      inplace=True)
    parking_df.drop('level_1', axis=1, inplace=True)
    parking_df = parking_df.reset_index()
    parking_df['parking_spot_id'] = parking_df['index'] + 1
    parking_df.drop('index', axis=1, inplace=True)

    parking_gdf = gpd.GeoDataFrame(parking_df)

    parking_gdf_output = parking_gdf  #.to_crs(output_crs)
    parking_gdf_output.to_file('output/parking_spots.geojson',
                               driver='GeoJSON')

    print('Number of parking spots: {:,}'.format(len(parking_gdf)))
match3=gpd.GeoDataFrame(match3, geometry='geometry')

match3=match3.to_crs('epsg:4326')
match3.plot()

os.chdir(r'D:\부동산 빅데이터 분석 스터디\상권 프로젝트 수정')

import folium

lat = 37.55
long = 127

m = folium.Map([lat,long],zoom_start=11, title='Competitive')

for _, r in match3.iterrows():
    
    # simplify를 쓰나 안쓰나 차이는 별로 없으나 geopandas 원문에서 쓰라고 하니 써주자
    
    sim_geo = gpd.GeoSeries(r['geometry']).simplify(tolerance=0.001)
    geo_j = sim_geo.to_json()
    geo_j = folium.GeoJson(data=geo_j,
                           style_function = lambda x: {'fillColor': 'blue'})
    # folium.Popup(r['법정동명']).add_to(geo_j)
    geo_j.add_to(m)

m.save('competitive.html')

# 최종 결과 파일 저장

match3.to_csv(r'D:\부동산 빅데이터 분석 스터디\상권 프로젝트 수정\최종 매칭.csv', encoding='cp949', sep = ',')
    def test_AreaTablesAreaInterpolate(self):
        polys1 = gpd.GeoSeries([
            Polygon([(0, 0), (10, 0), (10, 5), (0, 5)]),
            Polygon([(0, 5), (0, 10), (10, 10), (10, 5)])
        ])

        polys2 = gpd.GeoSeries([
            Polygon([(0, 0), (5, 0), (5, 7), (0, 7)]),
            Polygon([(5, 0), (5, 10), (10, 10), (10, 0)]),
            Polygon([(0, 7), (0, 10), (5, 10), (5, 7)])
        ])

        df1 = gpd.GeoDataFrame({'geometry': polys1})
        df2 = gpd.GeoDataFrame({'geometry': polys2})
        df1['population'] = [500, 200]
        df1['pci'] = [75, 100]
        df1['income'] = df1['population'] * df1['pci']

        res_union = gpd.overlay(df1, df2, how='union')

        result_area = area_tables(df1, res_union)
        result_area_binning = area_tables_binning(df1, res_union)

        np.testing.assert_almost_equal(result_area[0],
                                       np.array([[25., 25., 0., 0., 0.],
                                                 [0., 0., 10., 15., 25.]]),
                                       decimal=3)

        np.testing.assert_almost_equal(result_area[1],
                                       np.array([[1., 0., 0., 0., 0.],
                                                 [0., 0., 1., 0., 0.],
                                                 [0., 1., 0., 0., 0.],
                                                 [0., 0., 0., 0., 1.],
                                                 [0., 0., 0., 1., 0.]]),
                                       decimal=3)

        np.testing.assert_almost_equal(result_area_binning.toarray(),
                                       np.array([[25., 0., 25., 0., 0.],
                                                 [0., 10., 0., 25., 15.]]),
                                       decimal=3)

        result_inte = area_interpolate(
            df1,
            res_union,
            extensive_variables=['population', 'income'],
            intensive_variables=['pci'])
        result_inte_binning = area_interpolate_binning(
            df1,
            res_union,
            extensive_variables=['population', 'income'],
            intensive_variables=['pci'])

        np.testing.assert_almost_equal(result_inte[0],
                                       np.array([[250., 18750.], [40., 4000.],
                                                 [250.,
                                                  18750.], [100., 10000.],
                                                 [60., 6000.]]),
                                       decimal=3)

        np.testing.assert_almost_equal(result_inte[1],
                                       np.array([[75.], [100.], [75.], [100.],
                                                 [100.]]),
                                       decimal=3)

        np.testing.assert_almost_equal(result_inte_binning[0],
                                       np.array([[250., 18750.],
                                                 [39.99999762, 3999.99976158],
                                                 [250., 18750.],
                                                 [100., 10000.],
                                                 [59.99999642,
                                                  5999.99964237]]),
                                       decimal=3)

        np.testing.assert_almost_equal(result_inte_binning[1],
                                       np.array([[75.], [100.], [75.], [100.],
                                                 [100.]]),
                                       decimal=3)
Exemple #24
0
def consolidate_intersections(
    G, tolerance=10, rebuild_graph=True, dead_ends=False, update_edge_lengths=True
):
    """
    Consolidate intersections comprising clusters of nearby nodes.

    Merging nodes and return either their centroids or a rebuilt graph with
    consolidated intersections and reconnected edge geometries.

    The tolerance argument should be adjusted to approximately match street
    design standards in the specific street network, and you should always use
    a projected graph to work in meaningful and consistent units like meters.

    Divided roads are often represented by separate centerline edges. The
    intersection of two divided roads thus creates 4 nodes, representing where
    each edge intersects a perpendicular edge. These 4 nodes represent a single
    intersection in the real world. This function consolidates them up by
    buffering them to an arbitrary distance, merging overlapping buffers, and
    taking their centroid. For best results, the tolerance argument should be
    adjusted to approximately match street design standards in the specific
    street network.

    Parameters
    ----------
    G : networkx.MultiDiGraph
        a projected graph
    tolerance : float
        nodes within this distance (in graph's geometry's units) will be
        dissolved into a single intersection
    rebuild_graph : bool
        if True, use consolidate_intersections_rebuild_graph to consolidate
        the intersections and rebuild the graph, then return as
        networkx.MultiDiGraph. if False, just return the consolidated
        intersection points as a geopandas.GeoSeries (faster than rebuilding
        graph)
    dead_ends : bool
        if False, discard dead-end nodes to return only street-intersection
        points
    update_edge_lengths : bool
        just passed to consolidate_intersections_rebuild_graph.
        if True, update the length attribute of edges reconnected to a new
        merged node; if False, just retain the original edge length.

    Returns
    -------
    networkx.MultiDiGraph or geopandas.GeoSeries
        if rebuild_graph=True, returns MultiDiGraph with consolidated
        intersections and reconnected edge geometries. if rebuild_graph=False,
        returns GeoSeries of shapely Points representing the centroids of
        street intersections
    """
    # if dead_ends is False, discard dead-end nodes to retain only intersections
    if not dead_ends:
        if "streets_per_node" in G.graph:
            streets_per_node = G.graph["streets_per_node"]
        else:
            streets_per_node = utils_graph.count_streets_per_node(G)

        dead_end_nodes = [node for node, count in streets_per_node.items() if count <= 1]
        G = G.copy()
        G.remove_nodes_from(dead_end_nodes)

    if rebuild_graph:
        return _consolidate_intersections_rebuild_graph(
            G=G, tolerance=tolerance, update_edge_lengths=update_edge_lengths
        )

    else:
        # create a GeoDataFrame of nodes, buffer to passed-in distance, merge overlaps
        gdf_nodes = utils_graph.graph_to_gdfs(G, edges=False)
        buffered_nodes = gdf_nodes.buffer(tolerance).unary_union
        if isinstance(buffered_nodes, Polygon):
            # if only a single node results, make iterable to convert to GeoSeries
            buffered_nodes = [buffered_nodes]

        # get the centroids of the merged intersection polygons
        unified_intersections = gpd.GeoSeries(list(buffered_nodes))
        intersection_centroids = unified_intersections.centroid
        return intersection_centroids

rGrid = makePlotCube(
    iris.coord_systems.RotatedGeogCS(90.0, 180.0, 0),
    0.05,
    110 - 40 * 0.5,
    110 + 40 * 0.5,
    30 - 15 * 0.5,
    30 + 15 * 0.5,
)

# Convert the field to an in=1, out=0 mask
lats = rGrid.coord(axis='Y').points
lons = rGrid.coord(axis='X').points
[lon2d, lat2d] = numpy.meshgrid(lons, lats)
lon2 = lon2d.reshape(-1)  # to 1d for iteration
lat2 = lat2d.reshape(-1)
mask = []
for lat, lon in zip(lat2, lon2):
    this_point = geopandas.GeoSeries([Point(lon, lat)],
                                     crs=yangtze.crs,
                                     index=yangtze.index)
    res = yangtze.geometry.contains(this_point)
    mask.append(res.values[0])

mask = numpy.array(mask).reshape(lon2d.shape)
mask = mask * 1
rGrid.data = mask
iris.save(rGrid, "mask.plot.nc")
#pickle.dump(rGrid,open('mask.plot.pkl','wb'))
Exemple #26
0
data = [('Nevada', geometry_nevada), ('Colorado', geometry_colorado),
        ('Wyoming', geometry_wyoming)]
cursor.executemany('insert into TestStates values (:state, :obj)', data)

# We now have test geometries in Oracle Spatial (SDO_GEOMETRY) and will next
# bring them back into Python to analyze with GeoPandas. GeoPandas is able to
# consume geometries in the Well Known Text (WKT) and Well Known Binary (WKB)
# formats. Oracle database includes utility functions to return SDO_GEOMETRY as
# both WKT and WKB. Therefore we use that utility function in the query below
# to provide results in a format readily consumable by GeoPandas. These utility
# functions were introduced in Oracle 10g. We use WKB here; however the same
# process applies for WKT.
cursor.execute("""
        SELECT state, sdo_util.to_wkbgeometry(geometry)
        FROM TestStates""")
gdf = gpd.GeoDataFrame(cursor.fetchall(), columns=['state', 'wkbgeometry'])

# create GeoSeries to replace the WKB geometry column
gdf['geometry'] = gpd.GeoSeries(gdf['wkbgeometry'].apply(lambda x: loads(x)))
del gdf['wkbgeometry']

# display the GeoDataFrame
print()
print(gdf)

# perform a basic GeoPandas operation (unary_union)
# to combine the 3 adjacent states into 1 geometry
print()
print("GeoPandas combining the 3 geometries into a single geometry...")
print(gdf.unary_union)
Exemple #27
0
#Subset to bounding box of basin
demdata = rio.open('Mads_1.tif')
show((demdata, 1), cmap='terrain')
print(demdata.crs, basin.crs)
# print(basin.boundary.to_json())
basin_coords = getFeatures(basin)
minx, miny, maxx, maxy = basin.total_bounds
p1 = geometry.Point(minx, miny)
p2 = geometry.Point(minx, maxy)
p3 = geometry.Point(maxx, maxy)
p4 = geometry.Point(maxx, miny)

pointlist = [p1, p2, p3, p4, p1]
clipBnd = geometry.Polygon(pointlist)
clip = gpd.GeoSeries(clipBnd)

out_img, out_transform = mask(dataset=demdata, shapes=clip, crop=True)
out_meta = demdata.meta
out_meta.update({
    "driver": "GTiff",
    "height": out_img.shape[1],
    "width": out_img.shape[2],
    "transform": out_transform
})
out_raster = rio.open('Mads_clip_1.tif', "w", **out_meta)
out_raster.write(out_img)

out_raster.close()
demdata_clip = rio.open('Mads_clip_1.tif')
with rio.open('Mads_clip_1.tif') as dataset1:
def remove_false_nodes(gdf):
    """
    Clean topology of existing LineString geometry by removal of nodes of degree 2.

    Parameters
    ----------
    gdf : GeoDataFrame, GeoSeries, array of pygeos geometries
        (Multi)LineString data of street network

    Returns
    -------
    gdf : GeoDataFrame, GeoSeries

    See also
    --------
    momepy.extend_lines
    momepy.close_gaps
    """
    if isinstance(gdf, (gpd.GeoDataFrame, gpd.GeoSeries)):
        # explode to avoid MultiLineStrings
        # double reset index due to the bug in GeoPandas explode
        df = gdf.reset_index(drop=True).explode().reset_index(drop=True)

        # get underlying pygeos geometry
        geom = df.geometry.values.data
    else:
        geom = gdf

    # extract array of coordinates and number per geometry
    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))

    # query LineString geometry to identify points intersecting 2 geometries
    tree = pygeos.STRtree(geom)
    inp, res = tree.query_bulk(points, predicate="intersects")
    unique, counts = np.unique(inp, return_counts=True)
    merge = res[np.isin(inp, unique[counts == 2])]

    if len(merge) > 0:
        # filter duplications and create a dictionary with indication of components to
        # be merged together
        dups = [item for item, count in collections.Counter(merge).items() if count > 1]
        split = np.split(merge, len(merge) / 2)
        components = {}
        for i, a in enumerate(split):
            if a[0] in dups or a[1] in dups:
                if a[0] in components.keys():
                    i = components[a[0]]
                elif a[1] in components.keys():
                    i = components[a[1]]
            components[a[0]] = i
            components[a[1]] = i

        # iterate through components and create new geometries
        new = []
        for c in set(components.values()):
            keys = []
            for item in components.items():
                if item[1] == c:
                    keys.append(item[0])
            new.append(pygeos.line_merge(pygeos.union_all(geom[keys])))

        # remove incorrect geometries and append fixed versions
        df = df.drop(merge)
        final = gpd.GeoSeries(new).explode().reset_index(drop=True)
        if isinstance(gdf, gpd.GeoDataFrame):
            return df.append(
                gpd.GeoDataFrame({df.geometry.name: final}, geometry=df.geometry.name),
                ignore_index=True,
            )
        return df.append(final, ignore_index=True)
Exemple #29
0
def plot_local_autocorrelation(moran_loc, gdf, attribute, p=0.05,
                               region_column=None, mask=None,
                               mask_color='#636363', quadrant=None,
                               legend=True, scheme='Quantiles',
                               cmap='YlGnBu', figsize=(15, 4),
                               scatter_kwds=None, fitline_kwds=None):
    '''
    Produce three-plot visualisation of Moran Scatteprlot, LISA cluster
    and Choropleth maps, with Local Moran region and quadrant masking

    Parameters
    ----------
    moran_loc : esda.moran.Moran_Local instance
        Values of Moran's Local Autocorrelation Statistic
    gdf : geopandas dataframe
        The Dataframe containing information to plot the two maps.
    attribute : str
        Column name of attribute which should be depicted in Choropleth map.
    p : float, optional
        The p-value threshold for significance. Points and polygons will
        be colored by significance. Default = 0.05.
    region_column: string, optional
        Column name containing mask region of interest. Default = None
    mask: str, optional
        Identifier or name of the region to highlight. Default = None
    mask_color: str, optional
        Color of mask. Default = '#636363'
    quadrant : int, optional
        Quadrant 1-4 in scatterplot masking values in LISA cluster and
        Choropleth maps. Default = None
    figsize: tuple, optional
        W, h of figure. Default = (15,4)
    legend: boolean, optional
        If True, legend for maps will be depicted. Default = True
    scheme: str, optional
        Name of PySAL classifier to be used. Default = 'Quantiles'
    cmap: str, optional
        Name of matplotlib colormap used for plotting the Choropleth.
        Default = 'YlGnBU'
    scatter_kwds : keyword arguments, optional
        Keywords used for creating and designing the scatter points.
        Default =None.
    fitline_kwds : keyword arguments, optional
        Keywords used for creating and designing the moran fitline
        in the scatterplot. Default =None.

    Returns
    -------
    fig : Matplotlib figure instance
        Moran Scatterplot, LISA cluster map and Choropleth.
    axs : list of Matplotlib axes
        Lisat of Matplotlib axes plotted.

    Examples
    --------
    Imports
    
    >>> import matplotlib.pyplot as plt
    >>> import libpysal.api as lp
    >>> from libpysal import examples
    >>> import geopandas as gpd
    >>> from esda.moran import Moran_Local
    >>> from splot.esda import plot_local_autocorrelation

    Data preparation and analysis
    
    >>> link = examples.get_path('Guerry.shp')
    >>> gdf = gpd.read_file(link)
    >>> y = gdf['Donatns'].values
    >>> w = lp.Queen.from_dataframe(gdf)
    >>> w.transform = 'r'
    >>> moran_loc = Moran_Local(y, w)

    Plotting with quadrant mask and region mask
    
    >>> fig = plot_local_autocorrelation(moran_loc, gdf, 'HOVAL', p=0.05,
    ...                                  region_column='POLYID',
    ...                                  mask=['1', '2', '3'], quadrant=1)
    >>> plt.show()
    
    '''
    fig, axs = plt.subplots(1, 3, figsize=figsize,
                            subplot_kw={'aspect': 'equal'})
    # Moran Scatterplot
    if isinstance (moran_loc, Moran_Local):
        moran_loc_scatterplot(moran_loc, p=p, ax=axs[0],
                              scatter_kwds=scatter_kwds, fitline_kwds=fitline_kwds)
    else:
        moran_loc_bv_scatterplot(moran_loc, p=p, ax=axs[0],
                                 scatter_kwds=scatter_kwds, fitline_kwds=fitline_kwds)
    axs[0].set_aspect('auto')

    # Lisa cluster map
    # TODO: Fix legend_kwds: display boxes instead of points
    lisa_cluster(moran_loc, gdf, p=p, ax=axs[1], legend=legend,
                 legend_kwds={'loc': 'upper left',
                 'bbox_to_anchor': (0.92, 1.05)})
    axs[1].set_aspect('equal')

    # Choropleth for attribute
    gdf.plot(column=attribute, scheme=scheme, cmap=cmap,
             legend=legend, legend_kwds={'loc': 'upper left',
                                         'bbox_to_anchor': (0.92, 1.05)},
             ax=axs[2], alpha=1)
    axs[2].set_axis_off()
    axs[2].set_aspect('equal')

    # MASKING QUADRANT VALUES
    if quadrant is not None:
        # Quadrant masking in Scatterplot
        mask_angles = {1: 0, 2: 90, 3: 180, 4: 270}   # rectangle angles
        # We don't want to change the axis data limits, so use the current ones
        xmin, xmax = axs[0].get_xlim()
        ymin, ymax = axs[0].get_ylim()
        # We are rotating, so we start from 0 degrees and
        # figured out the right dimensions for the rectangles for other angles
        mask_width = {1: abs(xmax),
                      2: abs(ymax),
                      3: abs(xmin),
                      4: abs(ymin)}
        mask_height = {1: abs(ymax),
                       2: abs(xmin),
                       3: abs(ymin),
                       4: abs(xmax)}
        axs[0].add_patch(patches.Rectangle((0, 0), width=mask_width[quadrant],
                                           height=mask_height[quadrant],
                                           angle=mask_angles[quadrant],
                                           color='grey', zorder=-1, alpha=0.8))
        # quadrant selection in maps
        non_quadrant = ~(moran_loc.q == quadrant)
        mask_quadrant = gdf[non_quadrant]
        df_quadrant = gdf.iloc[~non_quadrant]
        union2 = df_quadrant.unary_union.boundary

        # LISA Cluster mask and cluster boundary
        mask_quadrant.plot(column=attribute, scheme=scheme, color='white',
                           ax=axs[1], alpha=0.7, zorder=1)
        gpd.GeoSeries([union2]).plot(linewidth=2, ax=axs[1], color='darkgrey')

        # CHOROPLETH MASK
        mask_quadrant.plot(column=attribute, scheme=scheme, color='white',
                           ax=axs[2], alpha=0.7, zorder=1)
        gpd.GeoSeries([union2]).plot(linewidth=2, ax=axs[2], color='darkgrey')

    # REGION MASKING
    if region_column is not None:
        # masking inside axs[0] or Moran Scatterplot
        ix = gdf[region_column].isin(mask)
        df_mask = gdf[ix]
        x_mask = moran_loc.z[ix]
        y_mask = lp.lag_spatial(moran_loc.w, moran_loc.z)[ix]
        axs[0].plot(x_mask, y_mask, color=mask_color, marker='o',
                    markersize=14, alpha=.8, linestyle="None", zorder=-1)

        # masking inside axs[1] or Lisa cluster map
        union = df_mask.unary_union.boundary
        gpd.GeoSeries([union]).plot(linewidth=2, ax=axs[1], color=mask_color)

        # masking inside axs[2] or Chloropleth
        gpd.GeoSeries([union]).plot(linewidth=2, ax=axs[2], color=mask_color)
    return fig, axs
Exemple #30
0
def extract_raster_features(gdf,
                            raster_path,
                            pixel_values=None,
                            nodata=255,
                            n_jobs=-1,
                            collapse_values=False):
    """Generate a geodataframe from raster data by polygonizing contiguous pixels with the same value using rasterio's features module.

    Parameters
    ----------
    gdf : geopandas.GeoDataFrame
        geodataframe  defining the area of interest. The input raster will be
        clipped to the extent of the geodataframe
    raster_path : str
        path to raster file, such as downloaded from <https://lcviewer.vito.be/download>
    pixel_values : list-like, optional
        subset of pixel values to extract, by default None. If None, this function
        may generate a very large geodataframe
    nodata : int, optional
        pixel value denoting "no data" in input raster
    n_jobs : int
        [Optional. Default=-1] Number of processes to run in parallel. If -1,
        this is set to the number of CPUs available
    collapse_values : bool, optional
        If True, multiple values passed to the pixel_values argument are treated
        as a single type. I.e. polygons will be generated from any contiguous collection
        of values from pixel_types, instead of unique polygons generated for each value
        This can dramatically reduce the complexity of the resulting geodataframe a
        fewer polygons are required to represent the study area.

    Returns
    -------
    geopandas.GeoDataFrame
        geodataframe whose rows are the zones extracted by the rasterio.features module.
        The geometry of each zone is the boundary of a contiguous group of pixels with
        the same value; the `value` column contains the pixel value of each zone.
    """
    if n_jobs == -1:
        n_jobs = multiprocessing.cpu_count()
    with rio.open(raster_path) as src:

        raster_crs = src.crs.data
        gdf = gdf.to_crs(raster_crs)
        geomask = [gdf.unary_union.__geo_interface__]

        out_image, out_transform = mask(
            src, geomask, nodata=nodata,
            crop=True)  # clip to AoI using a vector layer

        if pixel_values:
            if collapse_values:
                out_image = np.where(
                    np.isin(out_image, pixel_values), pixel_values[0],
                    out_image)  #  replace values to generate fewer polys
            pixel_values = np.isin(
                out_image, pixel_values)  # only include requested pixels

        shapes = list(
            features.shapes(
                out_image, mask=pixel_values,
                transform=out_transform))  # convert regions to polygons
    res = list(zip(*shapes))
    geoms = pd.Series(res[0], name="geometry").astype(str)
    pieces = _chunk_dfs(geoms, n_jobs)
    geoms = pd.concat(
        Parallel(n_jobs=n_jobs)(delayed(_apply_parser)(i) for i in pieces))
    geoms = gpd.GeoSeries(geoms).buffer(
        0)  # we sometimes get self-intersecting rings
    vals = pd.Series(res[1], name="value")
    gdf = gpd.GeoDataFrame(vals, geometry=geoms, crs=raster_crs)
    if collapse_values:
        gdf = gdf.drop(columns=["value"
                                ])  # values col is misleading in this case

    return gdf