Source code for dhd.modify

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from shapely.geometry import Point
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt

from dhd.logs import log


[docs]def get_streets_selection(streets, p, R): """ Select the streets from the dataframe *streets* within the distance *R* from the given point *p*. Parameters ---------- streets: DataFrame Dataframe of the streets network. p: Point or tuple Coordinates of the given point. R: float, optional Maximal distance from the point so that a street is selected. Returns ------- DataFrame Dataframe of the selected streets with indices from the dataframe *streets*. """ index = list() for idx, street in streets.iterrows(): line = street["geometry"] d = line.distance(p) if d < R: index.append(idx) streets_selection = streets.loc[index] return streets_selection
[docs]def plot_streets(streets_selection, plot): """ Plot the selected streets on the axes of the *plot* instance together with a legend. Parameters ---------- streets_selection: DataFrame Dataframe of the streets close enough to the considered point. plot: dhd.plot.Plot Plot instance associated to the considered city. """ i = 0 labels = list() colors = list() for idx, street_selection in streets_selection.iterrows(): color = plt.cm.Dark2(i) labels.append("index: {}".format(idx)) colors.append(color) kwargs = {"color": color, "linewidth": 2} i += 1 gdf = gpd.GeoDataFrame([street_selection]) plot.add_geodataframe(gdf, kwargs) plot.add_legend(colors, labels, "line", loc="upper left")
[docs]def find_streets_mutiple_points(streets, points, R=1, plot=None): """ Find the streets within the distance *R* from the given list of points *points*. Plot the selection of streets on the axes of the *dhd.plot.Plot* instance *plot* if provided. Parameters ---------- streets: DataFrame Dataframe of the streets network. points: list of Point or tuple Coordinates of the given points. R: float, optional Maximal distance from the point so that a street is selected. Default is 1 meter. plot: dhd.plot.Plot, optional Plot instance associated to the considered city. Default is None. Returns ------- DataFrame Dataframe of the selected streets with indices from the dataframe *streets*. """ streets_selection = [] for p in points: streets_selection.append(find_streets(streets, p, R=R)) # plot points if plot is not None: plot_point(p, plot) streets_selection = gpd.GeoDataFrame(pd.concat(streets_selection)) # plot streets if plot is not None: plot_streets(streets_selection, plot) return streets_selection
[docs]def find_streets(streets, p, R=1, plot=None): """ Find the streets within the distance *R* from the given point *p*. Plot the selection of streets on the axes of the *dhd.plot.Plot* instance *plot* if provided. Parameters ---------- streets: DataFrame Dataframe of the streets network. p: Point or tuple Coordinates of the given point. R: float, optional Maximal distance from the point so that a street is selected. Default is 1 meter. plot: dhd.plot.Plot, optional Plot instance associated to the considered city. Default is None. Returns ------- DataFrame Dataframe of the selected streets with indices from the dataframe *streets*. """ try: x, y = p p = Point(x, y) except TypeError: text = "'point' must either be x/y coordinates or Point geometry." assert type(p) == Point, text streets_selection = get_streets_selection(streets, p, R) text = "{} streets found within {} meters of the point {}." log.info(text.format(len(streets_selection), R, p)) if plot is not None: plot_point(p, plot) plot_streets(streets_selection, plot) return streets_selection
[docs]def multiply_streets_weight(streets, indices, ratios): """ Multiply the weights of the rows of the dataframe *streets* with the given indices by the given ratios ; in-place. *indices* and *ratios* may either be singlets of lists. Parameters ---------- streets: DataFrame Dataframe of the streets network. indices: int or list Index (or indices) of the street(s) which weight shall be changed. ratios: float or list Number(s) by which the associated street weight is multiplied and then replaced. """ if type(indices) == list: text = "The lists 'indices' and 'ratios' must have the same length." assert len(indices) == len(ratios), text for index, ratio in zip(indices, ratios): streets.loc[index, "weight"] *= ratio elif type(indices) == int: streets.loc[indices, "weight"] *= ratios else: text = ( "'indices' and 'ratios' must either be numbers or lists of " "numbers (int respectively float)." ) raise TypeError(text)
[docs]def replace_streets_weight(streets, indices, weights): """ Replace the weights of the rows of the dataframe *streets* with the given indices by the given weights ; in-place. *indices* and *weights* may either be singlets of lists. Parameters ---------- streets: DataFrame Dataframe of the streets network. indices: int or list Index (or indices) of the street(s) which weight shall be changed. weights: float or list Number(s) by which the associated street weight are replaced. """ if type(indices) == list: text = "The lists 'indices' and 'weights' must have the same length." assert len(indices) == len(weights), text for index, weight in zip(indices, weights): streets.loc[index, "weight"] = weight elif type(indices) == int: streets.loc[indices, "weight"] = weights else: text = ( "'indices' and 'weights' must either be numbers or lists of " "numbers (int respectively float)." ) raise TypeError(text)
[docs]def get_sinks_selection(sinks, p, R): """ Select the sinks from the dataframe *sinks* within the distance *R* from the given point *p*. Parameters ---------- sinks: DataFrame Dataframe of the sinks. p: Point or tuple Coordinates of the given point. R: float, optional Maximal distance from the point so that a street is selected. Returns ------- DataFrame Dataframe of the selected sinks with indices from the dataframe *sinks*. """ index = list() for idx, sink in sinks.iterrows(): object = sink["geometry"] d = object.distance(p) if d < R: index.append(idx) sinks_selection = sinks.loc[index] return sinks_selection
[docs]def plot_sinks(sinks_selection, plot): """ Plot the selected sinks centroids on the axes of the *plot* instance together with a legend. Parameters ---------- sinks_selection: DataFrame Dataframe of the sinks close enough to the considered point. plot: dhd.plot.Plot Plot instance associated to the considered city. """ i = 0 labels = list() colors = list() for idx, sink_selection in sinks_selection.iterrows(): color = plt.cm.Dark2(i) labels.append("index: {}".format(idx)) colors.append(color) kwargs = {"color": color, "markersize": 20} i += 1 gdf = gpd.GeoDataFrame([sink_selection]) plot.add_geodataframe(gdf, kwargs, centroid=True) plot.add_legend(colors, labels, "point", loc="upper left")
[docs]def plot_point(p, plot): """ """ # TODO: add doc kwargs = {'color': 'black', 'marker': '+', 'markersize': 20} gdf = gpd.GeoDataFrame([[p]], columns=['geometry']) plot.add_geodataframe(gdf, kwargs)
[docs]def find_sinks(sinks, p, R=1, plot=None): """ Find the sinks within the distance *R* from the given point *p*. Plot the selection of sinks on the axes of the *dhd.plot.Plot* instance *plot* if provided. Parameters ---------- sinks: DataFrame Dataframe of the sinks. p: Point or tuple Coordinates of the given point. R: float, optional Maximal distance from the point so that a street is selected. Default is 1 meter. plot: dhd.plot.Plot, optional Plot instance associated to the considered city. Default is None. Returns ------- DataFrame Dataframe of the selected sinks with indices from the dataframe *sinks*. """ try: x, y = p p = Point(x, y) except TypeError: text = "'point' must either be x/y coordinates or Point geometry." assert type(p) == Point, text sinks_selection = get_sinks_selection(sinks, p, R) text = "{} sinks found within {} meters of the point {}." log.info(text.format(len(sinks_selection), R, p)) if plot is not None: plot_point(p, plot) plot_sinks(sinks_selection, plot) return sinks_selection
[docs]def multiply_sinks_load(sinks, indices, ratios): """ Multiply the loads of the rows of the dataframe *sinks* with the given indices by the given ratios ; in-place. *indices* and *ratios* may either be singlets of lists. Parameters ---------- sinks: DataFrame Dataframe of the sinks. indices: int or list Index (or indices) of the sink(s) which load shall be changed. ratios: float or list Number(s) by which the associated sinks load is multiplied and then replaced. """ # TODO: add case where indices are list but ratios are int (numpy ?) if type(indices) == list: text = "The lists 'indices' and 'ratios' must have the same length." assert len(indices) == len(ratios), text for index, ratio in zip(indices, ratios): sinks.loc[index, "load"] *= ratio elif type(indices) == int: sinks.loc[indices, "load"] *= ratios else: text = ( "'indices' and 'ratios' must either be numbers or lists of " "numbers (int respectively float)." ) raise TypeError(text)
[docs]def replace_sinks_load(sinks, indices, loads): """ Replace the loads of the rows of the dataframe *sinks* with the given indices by the given loads ; in-place. *indices* and *loads* may either be singlets of lists. Parameters ---------- sinks: DataFrame Dataframe of the sinks. indices: int or list Index (or indices) of the sink(s) which load shall be changed. loads: float or list Number(s) by which the associated sinks load are replaced. """ if type(indices) == list: text = "The lists 'indices' and 'loads' must have the same length." assert len(indices) == len(loads), text for index, load in zip(indices, loads): sinks.loc[index, "load"] = load elif type(indices) == int: sinks.loc[indices, "load"] = loads else: text = ( "'indices' and 'loads' must either be numbers or lists of " "numbers (int respectively float)." ) raise TypeError(text)
[docs]def add_streets(): """TODO"""
[docs]def add_sinks(sinks, sinks_to_add, ignore_index=True): """ Add new sinks to the dataframe *sinks*. Parameters ---------- sinks: DataFrame Dataframe of the sinks. sinks_to_add: DataFrame Dataframe of the sinks to add. ignore_index: bool, optional If True, reset the indices to integers, else use the indices provided. Default is True. Returns ------- DataFrame Appended dataframe of the sinks. """ sinks_ = sinks.append(sinks_to_add, ignore_index=ignore_index) return sinks_
[docs]def remove_streets(streets, index): """ Remove streets to the dataframe *streets*. Parameters ---------- streets: DataFrame Dataframe of the streets. index: list List of indices of the streets to remove. Returns ------- DataFrame Updated dataframe of the streets. """ streets_ = streets.drop(index=index, inplace=False) streets_.reset_index(inplace=True) return streets_
[docs]def remove_sinks(sinks, index, ignore_index=True): """ Remove sinks to the dataframe *sinks*. Parameters ---------- sinks: DataFrame Dataframe of the sinks. index: list List of indices of the sinks to remove. ignore_index: bool, optional If True, reset the indices to integers, else use the indices provided. Default is True. Returns ------- DataFrame Updated dataframe of the sinks. """ sinks_ = sinks.drop(index=index, inplace=False) if ignore_index is True: sinks_.reset_index(inplace=True) return sinks_