From f2d998e92c3dfccc355b68e638affb4d54340c3d Mon Sep 17 00:00:00 2001 From: James Gaboardi Date: Mon, 19 Sep 2022 11:58:56 -0400 Subject: [PATCH] Scour docs for consistency, grammar, etc. (#416) * review coins.py * review dimension.py * review weights.py * review utils.py * review distribution.py * review diversity.py * review elements.py * review graph.py * review shape.py * review intensity.py * revise & correct [1] --- momepy/coins.py | 154 +++++-------- momepy/dimension.py | 337 +++++++++++++--------------- momepy/distribution.py | 291 ++++++++++++------------ momepy/diversity.py | 305 ++++++++++++------------- momepy/elements.py | 311 ++++++++++++-------------- momepy/graph.py | 497 ++++++++++++++++++----------------------- momepy/intensity.py | 272 +++++++++++----------- momepy/shape.py | 322 +++++++++++++------------- momepy/utils.py | 115 +++++----- momepy/weights.py | 54 +++-- 10 files changed, 1247 insertions(+), 1411 deletions(-) diff --git a/momepy/coins.py b/momepy/coins.py index 1b66ef33..e5d0b72e 100644 --- a/momepy/coins.py +++ b/momepy/coins.py @@ -22,8 +22,8 @@ class COINS: """ - Calculates natural continuity and hierarchy of street networks in given - GeoDataFrame using COINS algorithm. + Calculates natural continuity and hierarchy of street networks in a given + GeoDataFrame using the COINS algorithm. For details on the algorithms refer to the original paper :cite:`tripathy2020open`. @@ -37,17 +37,16 @@ class COINS: Parameters ---------- edge_gdf : GeoDataFrame - GeoDataFrame containing edge geometry of street network. edge_gdf should - ideally not contain MultiLineStrings. + A GeoDataFrame containing edge geometry of a street network. + ``edge_gdf`` should ideally not contain MultiLineStrings. angle_threshold : int, float (default 0) - the angle threshold for the COINS algorithm. - Segments will only be considered a part of the same street if the - deflection angle is above the threshold. + The angle threshold for the COINS algorithm. Segments will only be considered + a part of the same street if the deflection angle is above the threshold. Examples -------- - Initialise COINS class. This step will already compute the topology. + Initialise a ``COINS`` class. This step will compute the topology. >>> coins = momepy.COINS(streets) @@ -74,36 +73,34 @@ def __init__(self, edge_gdf, angle_threshold=0): # split edges into line segments self._split_lines() - # # create unique_id for each individual line segment + # create unique_id for each individual line segment self._unique_id() - # # compute edge connectivity table + # compute edge connectivity table self._get_links() - # # find best link at every point for both lines + # find best link at every point for both lines self._best_link() - # # cross check best links and enter angle threshold for connectivity + # cross check best links and enter angle threshold for connectivity self._cross_check_links(angle_threshold) def _premerge(self): """ - Returns a GeoDataFrame containing the individual segments with all underlying + Return a GeoDataFrame containing the individual segments with all underlying information. The result is useful for debugging purposes. """ return self._create_gdf_premerge() def stroke_gdf(self): - """ - Returns a GeoDataFrame containing merged final stroke geometry. - """ + """Return a GeoDataFrame containing merged final stroke geometry.""" if not self.already_merged: self._merge_lines() return self._create_gdf_strokes() def stroke_attribute(self): """ - Returns a pandas Series encoding stroke groups onto the original input geometry. + Return a pandas Series encoding stroke groups onto the original input geometry. """ if not self.already_merged: self._merge_lines() @@ -130,8 +127,8 @@ def _split_lines(self): self.uv_index[idx], ] ) - # merge the coordinates as string, this will help in finding adjacent - # edges in the function below + # merge the coordinates as a string, this will help + # in finding adjacent edges in the function below self.temp_array.append( [n, f"{part[0][0]}_{part[0][1]}", f"{part[1][0]}_{part[1][1]}"] ) @@ -141,7 +138,7 @@ def _split_lines(self): self.split = out_line def _unique_id(self): - # Loop through split lines, assign unique ID and + # Loop through split lines, assign unique ID, and # store inside a list along with the connectivity dictionary self.unique = dict(enumerate(self.split)) @@ -182,12 +179,10 @@ def _best_link(self): p1_angle_set = [] p2_angle_set = [] - """ - Instead of computing the angle between the two segments twice, the method - calculates it once and stores in the dictionary for both the keys. So that - it does not calculate the second time because the key is already present in - the dictionary. - """ + # Instead of computing the angle between the two segments twice, + # this method calculates it once and stores in a dictionary for + # both the keys. The key is already present in the dictionary so + # it does not calculate a second time. for link1 in self.unique[edge][2]: self.angle_pairs["%d_%d" % (edge, link1)] = _angle_between_two_lines( self.unique[edge][0], self.unique[link1][0] @@ -200,12 +195,10 @@ def _best_link(self): ) p2_angle_set.append(self.angle_pairs["%d_%d" % (edge, link2)]) - """ - Among the adjacent segments deflection angle values, check for the maximum - value at both the ends. The segment with the maximum angle is stored in the - attributes to be cross-checked later for before finalising the segments at - both the ends. - """ + # Among the adjacent segments deflection angle values, check + # for the maximum value at both the ends. The segment with + # the maximum angle is stored in the attributes to be cross-checked + # later before finalising the segments at both the ends. if len(p1_angle_set) != 0: val1, idx1 = max((val, idx) for (idx, val) in enumerate(p1_angle_set)) self.unique[edge][4] = self.unique[edge][2][idx1], val1 @@ -267,7 +260,6 @@ def _merge_lines(self): # Export geodataframes, 3 options def _create_gdf_premerge(self): - # create empty list to fill out my_list = [] for parts in range(0, len(self.unique)): @@ -285,7 +277,6 @@ def _create_gdf_premerge(self): p1_final = self.unique[parts][6] p2_final = self.unique[parts][7] - # append list my_list.append( [ _unique_id, @@ -321,10 +312,8 @@ def _create_gdf_premerge(self): def _create_gdf_strokes(self): - # create empty list to fill my_list = [] - # loop through merged geometry for a in self.merged: # get all segment points and make line strings @@ -334,14 +323,12 @@ def _create_gdf_strokes(self): for b in linelist: list_lines_segments.append(LineString(b)) - # merge seperate segments geom_multi_line = ops.linemerge(MultiLineString(list_lines_segments)) # get other values for gdf id_value = a n_segments = len(self.merged[a]) - # append list my_list.append([id_value, n_segments, geom_multi_line]) edge_gdf = gpd.GeoDataFrame( @@ -355,29 +342,25 @@ def _create_gdf_strokes(self): def _add_gdf_stroke_attributes(self): - # Invert self.edge_idx to get a dictionary where the key is the original edge - # index and the value is the group + # Invert self.edge_idx to get a dictionary where the key is + # the original edge index and the value is the group inv_edges = { value: key for key in self.edge_idx for value in self.edge_idx[key] } - # create empty list that will contain attributes of stroke - stroke_group = list() + stroke_group_attributes = list() for edge in self.uv_index: - stroke_group.append(inv_edges[edge]) - - return pd.Series(stroke_group, index=self.edge_gdf.index) + stroke_group_attributes.append(inv_edges[edge]) - -""" -The imported shapefile lines comes as tuple, whereas -the export requires list, this finction converts tuple -inside lines to list -""" + return pd.Series(stroke_group_attributes, index=self.edge_gdf.index) def _tuple_to_list(line): + """ + The imported shapefile lines comes as tuple, whereas the export requires list, + this function converts tuples inside lines to lists. + """ for a in range(0, len(line)): line[a] = list(line[a]) return line @@ -389,13 +372,8 @@ def _list_to_tuple(line): return tuple(line) -""" -The below function takes a line as an input and splits -it at every point. -""" - - def _list_to_pairs(in_list): + """Split a line at every point.""" out_list = [] index = 0 for index in range(0, len(in_list) - 1): @@ -404,57 +382,48 @@ def _list_to_pairs(in_list): return out_list -""" -The function below calculates the angle between two points in space. -""" - - def _compute_angle(point1, point2): + """Calculates the angle between two points in space.""" height = abs(point2[1] - point1[1]) base = abs(point2[0] - point1[0]) angle = round(math.degrees(math.atan(height / base)), 3) return angle -""" -This function calculates the orientation of a line segment. -Point1 is the lower one on the y-axes and vice-cersa for -Point2. -""" - - def _compute_orientation(line): + """Calculates the orientation of a line segment. Point1 is + the lower one on the y-axes and vice versa for Point2. + """ point1 = line[1] point2 = line[0] - """ - If the latutide of a point is less and the longitude is more, or - If the latitude of a point is more and the longitude is less, then - the point is oriented leftward and wil have negative orientation. - """ + + # If the latutide of a point is less and the longitude is more, or + # If the latitude of a point is more and the longitude is less, then + # the point is oriented leftward and wil have negative orientation. if ((point2[0] > point1[0]) and (point2[1] < point1[1])) or ( (point2[0] < point1[0]) and (point2[1] > point1[1]) ): return -_compute_angle(point1, point2) + # if the latitudes are same, the line is horizontal elif point2[1] == point1[1]: return 0 + # if the longitudes are same, the line is vertical elif point2[0] == point1[0]: return 90 - return _compute_angle(point1, point2) - -""" -This below function calculates the acute joining angle between -two given set of points. -""" + return _compute_angle(point1, point2) def _points_set_angle(line1, line2): + """Calculate the acute joining angle between two given set of points.""" l1orien = _compute_orientation(line1) l2orien = _compute_orientation(line2) + if ((l1orien > 0) and (l2orien < 0)) or ((l1orien < 0) and (l2orien > 0)): return abs(l1orien) + abs(l2orien) + elif ((l1orien > 0) and (l2orien > 0)) or ((l1orien < 0) and (l2orien < 0)): theta1 = abs(l1orien) + 180 - abs(l2orien) theta2 = abs(l2orien) + 180 - abs(l1orien) @@ -462,6 +431,7 @@ def _points_set_angle(line1, line2): return theta1 else: return theta2 + elif (l1orien == 0) or (l2orien == 0): if l1orien < 0: return 180 - abs(l1orien) @@ -471,29 +441,25 @@ def _points_set_angle(line1, line2): return 180 - ( abs(_compute_orientation(line1)) + abs(_compute_orientation(line2)) ) + elif l1orien == l2orien: return 180 -""" -The below function calculates the joining angle between -two line segments. -""" - - def _angle_between_two_lines(line1, line2): + """Calculate the joining angle between two line segments.""" l1p1, l1p2 = line1 l2p1, l2p2 = line2 l1orien = _compute_orientation(line1) l2orien = _compute_orientation(line2) - """ - If both lines have same orientation, return 180 If one of the lines is zero, - exception for that If both the lines are on same side of the horizontal plane, - calculate 180-(sumOfOrientation) If both the lines are on same side of the vertical - plane, calculate pointSetAngle - """ + + # If both lines have same orientation, return 180 If one of the + # lines is zero, exception for that If both the lines are on same side + # of the horizontal plane, calculate 180-(sumOfOrientation) If both the + # lines are on same side of the vertical plane, calculate pointSetAngle. if l1orien == l2orien: angle = 180 + elif (l1orien == 0) or (l2orien == 0): angle = _points_set_angle(line1, line2) @@ -504,6 +470,7 @@ def _angle_between_two_lines(line1, line2): angle = 180 - (abs(l1orien) + abs(l2orien)) else: angle = _points_set_angle([l1p1, l1p2], [l2p1, l2p2]) + elif l1p1 == l2p2: if ((l1p1[1] > l2p1[1]) and (l1p1[1] > l1p2[1])) or ( (l1p1[1] < l2p1[1]) and (l1p1[1] < l1p2[1]) @@ -511,6 +478,7 @@ def _angle_between_two_lines(line1, line2): angle = 180 - (abs(l1orien) + abs(l2orien)) else: angle = _points_set_angle([l1p1, l1p2], [l2p2, l2p1]) + elif l1p2 == l2p1: if ((l1p2[1] > l1p1[1]) and (l1p2[1] > l2p2[1])) or ( (l1p2[1] < l1p1[1]) and (l1p2[1] < l2p2[1]) @@ -518,6 +486,7 @@ def _angle_between_two_lines(line1, line2): angle = 180 - (abs(l1orien) + abs(l2orien)) else: angle = _points_set_angle([l1p2, l1p1], [l2p1, l2p2]) + elif l1p2 == l2p2: if ((l1p2[1] > l1p1[1]) and (l1p2[1] > l2p1[1])) or ( (l1p2[1] < l1p1[1]) and (l1p2[1] < l2p1[1]) @@ -525,6 +494,7 @@ def _angle_between_two_lines(line1, line2): angle = 180 - (abs(l1orien) + abs(l2orien)) else: angle = _points_set_angle([l1p2, l1p1], [l2p2, l2p1]) + return angle diff --git a/momepy/dimension.py b/momepy/dimension.py index 65e2b303..90472c53 100644 --- a/momepy/dimension.py +++ b/momepy/dimension.py @@ -32,22 +32,21 @@ class Area: """ - Calculates area of each object in given GeoDataFrame. It can be used for any - suitable element (building footprint, plot, tessellation, block). - - It is a simple wrapper for GeoPandas ``.area`` for the consistency of momepy. + Calculates the area of each object in a given GeoDataFrame. It can be used for any + suitable element (building footprint, plot, tessellation, block). It is a simple + wrapper for GeoPandas ``.area`` for the consistency of momepy. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. Examples -------- @@ -66,23 +65,21 @@ def __init__(self, gdf): class Perimeter: """ - Calculates perimeter of each object in given GeoDataFrame. It can be used for any - suitable element (building footprint, plot, tessellation, block). - - It is a simple wrapper for GeoPandas ``.length`` for the consistency of momepy. + Calculates perimeter of each object in a given GeoDataFrame. It can be used for any + suitable element (building footprint, plot, tessellation, block). It is a simple + wrapper for GeoPandas ``.length`` for the consistency of momepy. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. Attributes ---------- series : Series - Series containing resulting values - + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. Examples -------- @@ -100,7 +97,8 @@ def __init__(self, gdf): class Volume: """ - Calculates volume of each object in given GeoDataFrame based on its height and area. + Calculates the volume of each object in a + given GeoDataFrame based on its height and area. .. math:: area * height @@ -108,28 +106,25 @@ class Volume: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. heights : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` - where is stored height value + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where height values are stored. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` - where is stored area value. If set to None, function will calculate areas - during the process without saving them separately. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where area values are stored. If set to ``None``, this will calculate + areas during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values - + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame - + The original GeoDataFrame. heights : Series - Series containing used heights values - + A Series containing used heights values. areas : GeoDataFrame - Series containing used areas values + A Series containing used areas values. Examples -------- @@ -170,10 +165,9 @@ def __init__(self, gdf, heights, areas=None): class FloorArea: """ - Calculates floor area of each object based on height and area. - - Number of floors is simplified into formula height / 3 - (it is assumed that on average one floor is approximately 3 metres) + Calculates floor area of each object based on height and area. The number of + floors is simplified into the formula: height / 3. It is assumed that on + average one floor is approximately 3 metres. .. math:: area * \\frac{height}{3} @@ -181,25 +175,25 @@ class FloorArea: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. heights : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where - is stored height value + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where height values are stored. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where - is stored area value. If set to None, function will calculate areas - during the process without saving them separately. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where area values are stored. If set to ``None``, this will calculate + areas during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. heights : Series - Series containing used heights values + A Series containing used heights values. areas : GeoDataFrame - Series containing used areas values + A Series containing used areas values. Examples -------- @@ -244,28 +238,25 @@ def __init__(self, gdf, heights, areas=None): class CourtyardArea: """ Calculates area of holes within geometry - area of courtyards. - Expects pygeos backend of geopandas. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to None, function will calculate areas - during the process without saving them separately. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where area values are stored. If set to ``None``, this will calculate + areas during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values - + Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame - + The original GeoDataFrame. areas : GeoDataFrame - Series containing used areas values + A Series containing used areas values. Examples -------- @@ -293,11 +284,9 @@ def __init__(self, gdf, areas=None): class LongestAxisLength: """ - Calculates the length of the longest axis of object. - - Axis is defined as a diameter of minimal circumscribed circle around the - convex hull. - It does not have to be fully inside an object. + Calculates the length of the longest axis of object. Axis is defined as a + diameter of minimal circumscribed circle around the convex hull. It does + not have to be fully inside an object. .. math:: \\max \\left\\{d_{1}, d_{2}, \\ldots, d_{n}\\right\\} @@ -305,15 +294,14 @@ class LongestAxisLength: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. Attributes ---------- series : Series - Series containing resulting values - + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. Examples -------- @@ -330,62 +318,58 @@ def __init__(self, gdf): class AverageCharacter: """ - Calculates the average of a character within a set neighbourhood - defined in ``spatial_weights`` - - Average value of the character within a set neighbourhood defined - in ``spatial_weights``. - Can be set to ``mean``, ``median`` or ``mode``. ``mean`` is defined as: + Calculates the average of a character within a set + neighbourhood defined in ``spatial_weights``. Can be + set to ``mean``, ``median`` or ``mode``. ``mean`` is defined as: .. math:: \\frac{1}{n}\\left(\\sum_{i=1}^{n} value_{i}\\right) Adapted from :cite:`hausleitner2017`. - Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing a morphological tessellation. values : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where - is stored character value. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where character values are stored. unique_id : str - name of the column with unique id used as ``spatial_weights`` index. + The name of the column with unique ID used as the ``spatial_weights`` index. spatial_weights : libpysal.weights - spatial weights matrix - rng : Two-element sequence containing floats in range of [0,100], optional - Percentiles over which to compute the range. Each must be - between 0 and 100, inclusive. The order of the elements is not important. + A spatial weights matrix. + rng : tuple, list, optional (default None) + A two-element sequence containing floats between 0 and 100 (inclusive) + that are the percentiles over which to compute the range. + The order of the elements is not important. mode : str (default 'all') - mode of average calculation. Can be set to `all`, `mean`, `median` or `mode` or - list of any of the options. + The mode of average calculation. It can be set to ``'all'``, ``'mean'``, + ``'median'``, or ``'mode'`` or a list of any of the options. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting mean values + A Series containing resulting mean values. mean : Series - Series containing resulting mean values + A Series containing resulting mean values. median : Series - Series containing resulting median values + A Series containing resulting median values. mode : Series - Series containing resulting mode values + A Series containing resulting mode values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : GeoDataFrame - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. rng : tuple - range + The range. modes : str - mode - + The mode. Examples -------- @@ -481,12 +465,11 @@ def __init__( class StreetProfile: """ - Calculates the street profile characters. - - Returns a dictionary with widths, standard deviation of width, openness, heights, - standard deviation of height and ratio height/width. Algorithm generates - perpendicular ines to ``right`` dataframe features every ``distance`` and - measures values on intersectionwith features of ``left``. If no feature is + Calculates the street profile characters. This functions + returns a dictionary with widths, standard deviation of width, openness, heights, + standard deviation of height and ratio height/width. The algorithm generates + perpendicular lines to the ``right`` dataframe features every ``distance`` and + measures values on intersections with features of ``left``. If no feature is reached within ``tick_length`` its value is set as width (being a theoretical maximum). @@ -495,46 +478,46 @@ class StreetProfile: Parameters ---------- left : GeoDataFrame - GeoDataFrame containing streets to analyse + A GeoDataFrame containing streets to analyse. right : GeoDataFrame - GeoDataFrame containing buildings along the streets (only Polygon geometry type - is supported) + A GeoDataFrame containing buildings along the streets. + Only Polygon geometries are currently supported. heights: str, list, np.array, pd.Series (default None) - the name of the buildings dataframe column, ``np.array``, or ``pd.Series`` - where is stored building height. If set to None, + The name of the buildings dataframe column, ``np.array``, or ``pd.Series`` + where building height are stored. If set to ``None``, height and ratio height/width will not be calculated. distance : int (default 10) - distance between perpendicular ticks + The distance between perpendicular ticks. tick_length : int (default 50) - length of ticks + The length of ticks. Attributes ---------- w : Series - Series containing street profile width values + A Series containing street profile width values. wd : Series - Series containing street profile standard deviation values + A Series containing street profile standard deviation values. o : Series - Series containing street profile openness values + A Series containing street profile openness values. h : Series - Series containing street profile heights values. - Returned only when heights is set. + A Series containing street profile heights + values that is returned only when ``heights`` is set. hd : Series - Series containing street profile heights standard deviation values. - Returned only when heights is set. + A Series containing street profile heights standard deviation + values that is returned only when ``heights`` is set. p : Series - Series containing street profile height/width ratio values. - Returned only when heights is set. + A Series containing street profile height/width ratio + values that is returned only when ``heights`` is set. left : GeoDataFrame - original left GeoDataFrame + The original left GeoDataFrame. right : GeoDataFrame - original right GeoDataFrame + The original right GeoDataFrame. distance : int - distance between perpendicular ticks + The distance between perpendicular ticks. tick_length : int - length of ticks + The length of ticks. heights : GeoDataFrame - Series containing used height values + A Series containing used height values. Examples -------- @@ -710,10 +693,8 @@ def _getPoint2(self, pt, bearing, dist): class WeightedCharacter: """ - Calculates the weighted character - - Character weighted by the area of the objects within neighbors defined - in ``spatial_weights``. + Calculates the weighted character. Character weighted by the area + of the objects within neighbors defined in ``spatial_weights``. .. math:: \\frac{\\sum_{i=1}^{n} {character_{i} * area_{i}}}{\\sum_{i=1}^{n} area_{i}} @@ -723,36 +704,36 @@ class WeightedCharacter: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + The GeoDataFrame containing objects to analyse. values : str, list, np.array, pd.Series - the name of the gdf dataframe column, ``np.array``, or ``pd.Series`` where - is stored character to be weighted + The name of the ``gdf`` dataframe column, ``np.array``, or + ``pd.Series`` where the characters to be weighted are stored. spatial_weights : libpysal.weights - spatial weights matrix - If None, Queen contiguity matrix of set order will - be calculated based on left. + A spatial weights matrix. If ``None``, Queen contiguity matrix + of set order will be calculated based on left. unique_id : str - name of the column with unique id used as ``spatial_weights`` index. + The name of the column with unique ID used as ``spatial_weights`` index. areas : str, list, np.array, pd.Series (default None) - the name of the left dataframe column, ``np.array``, or ``pd.Series`` - where is stored area value + The name of the left dataframe column, ``np.array``, or ``pd.Series`` + where the area values are stored. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + A original GeoDataFrame. values : GeoDataFrame - Series containing used values + A Series containing used values. areas : GeoDataFrame - Series containing used areas + Series containing used areas. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. Examples -------- @@ -807,34 +788,30 @@ def __init__( class CoveredArea: """ - Calculates the area covered by neighbours - - Total area covered by neighbours defined in ``spatial_weights`` and element itself. - - .. math:: - + Calculates the area covered by neighbours, which is total area covered + by neighbours defined in ``spatial_weights`` and the element itself. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing Polygon geometry + A GeoDataFrame containing Polygon geometries. spatial_weights : libpysal.weights - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index. + The name of the column with unique ID used as ``spatial_weights`` index. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. Examples -------- @@ -868,26 +845,26 @@ def __init__(self, gdf, spatial_weights, unique_id, verbose=True): class PerimeterWall: """ - Calculate the perimeter wall length the joined structure. + Calculate the perimeter wall length of the joined structure. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. spatial_weights : libpysal.weights, optional - spatial weights matrix - If None, Queen contiguity matrix will be calculated - based on gdf. It is to denote adjacent buildings (note: based on index, not ID). + A spatial weights matrix. If ``None``, Queen contiguity matrix will + be calculated based on ``gdf``. It is to denote adjacent buildings. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. Examples -------- @@ -898,6 +875,9 @@ class PerimeterWall: Notes ----- + The ``spatial_weights`` keyword argument should be + based on *position*, not unique ID. + It might take a while to compute this character. """ @@ -939,45 +919,46 @@ def __init__(self, gdf, spatial_weights=None, verbose=True): class SegmentsLength: """ - Calculate the cummulative and/or mean length of segments. - - Length of segments within set topological distance from each of them. - Reached topological distance should be captured by ``spatial_weights``. - If ``mean=False`` it will compute sum of length, if ``mean=True`` - it will compute sum and mean. + Calculate the cummulative and/or mean length of segments. Length of segments + within set topological distance from each of them. Reached topological distance + should be captured by ``spatial_weights``. If ``mean=False`` it will compute + sum of length, if ``mean=True`` it will compute sum and mean. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing streets (edges) to analyse + A GeoDataFrame containing streets (edges) to analyse. spatial_weights : libpysal.weights, optional - spatial weights matrix - If None, Queen contiguity matrix will be calculated - based on streets (note: spatial_weights should be based on index, - not unique ID). - mean : boolean, optional - If mean=False it will compute sum of length, if mean=True it will compute - sum and mean + A spatial weights matrix. If ``None``, Queen contiguity + matrix will be calculated based on streets. + mean : bool, optional + If ``mean=False`` it will compute sum of length, if ``mean=True`` + it will compute sum and mean. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting total lengths + A Series containing resulting total lengths. mean : Series - Series containing resulting total lengths + A Series containing resulting total lengths. sum : Series - Series containing resulting total lengths + A Series containing resulting total lengths. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. Examples -------- >>> streets_df['length_neighbours'] = mm.SegmentsLength(streets_df, mean=True).mean Calculating spatial weights... Spatial weights ready... + + Notes + ----- + The ``spatial_weights`` keyword argument should be based on *index*, not unique ID. """ def __init__(self, gdf, spatial_weights=None, mean=False, verbose=True): diff --git a/momepy/distribution.py b/momepy/distribution.py index ba6f5bb5..6eaf9334 100644 --- a/momepy/distribution.py +++ b/momepy/distribution.py @@ -30,28 +30,27 @@ class Orientation: """ - Calculate the orientation of object - - Captures the deviation of orientation from cardinal directions. - Defined as an orientation of the longext axis of bounding rectangle in range 0 - 45. - Orientation of LineStrings is represented by the orientation of line - connecting first and last point of the segment. + Calculate the orientation of object. The deviation of orientation from cardinal + directions are captured. Here 'orientation' is defined as an orientation of the + longest axis of bounding rectangle in range 0 - 45. The orientation of LineStrings + is represented by the orientation of the line connecting the first and the last + point of the segment. Adapted from :cite:`schirmer2015`. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. Examples -------- @@ -97,27 +96,27 @@ def _dist(a, b): class SharedWalls: """ - Calculate the length of shared walls of adjacent elements (typically buildings) + Calculate the length of shared walls of adjacent elements (typically buildings). .. math:: \\textit{length of shared walls} - Note that data needs to be topologically correct. Overlapping polygons will lead to - incorrect results. + Note that data needs to be topologically correct. + Overlapping polygons will lead to incorrect results. Adapted from :cite:`hamaina2012a`. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing gdf to analyse + A GeoDataFrame containing objects to analyse. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. Examples -------- @@ -145,32 +144,32 @@ def __init__(self, gdf): class SharedWallsRatio(SharedWalls): """ - Calculate shared walls ratio of adjacent elements (typically buildings) + Calculate shared walls ratio of adjacent elements (typically buildings). .. math:: \\textit{length of shared walls} \\over perimeter - Note that data needs to be topologically correct. Overlapping polygons will lead to - incorrect results. + Note that data needs to be topologically correct. + Overlapping polygons will lead to incorrect results. Adapted from :cite:`hamaina2012a`. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing gdf to analyse + A GeoDataFrame containing objects to analyse. perimeters : str, list, np.array, pd.Series (default None, optional) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored perimeter value + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where perimeter values are stored. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. perimeters : GeoDataFrame - Series containing used perimeters values + A Series containing used perimeters values. Examples -------- @@ -198,15 +197,12 @@ def __init__(self, gdf, perimeters=None): class StreetAlignment: """ - Calculate the difference between street orientation and orientation of object in - degrees - - Orientation of street segment is represented by the orientation of line - connecting first and last point of the segment. Network ID linking each object - to specific street segment is needed. Can be generated by - :func:`momepy.get_network_id`. - Either ``network_id`` or both ``left_network_id`` and ``right_network_id`` - are required. + Calculate the difference between street orientation and orientation of + another object in degrees. The orientation of a street segment is represented + by the orientation of line connecting the first and the last point of the + segment. A network ID linking each object to specific street segment is needed, + and can be generated by :func:`momepy.get_network_id`. Either ``network_id`` or + both ``left_network_id`` and ``right_network_id`` are required. .. math:: \\left|{\\textit{building orientation} - \\textit{street orientation}}\\right| @@ -214,37 +210,37 @@ class StreetAlignment: Parameters ---------- left : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. right : GeoDataFrame - GeoDataFrame containing street network + A GeoDataFrame containing a street network. orientations : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored object orientation value - (can be calculated using :class:`momepy.Orientation`) + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + object orientation values are stored. The object can be calculated + using :class:`momepy.Orientation`. network_id : str (default None) - the name of the column storing network ID in both left and right + The name of the column storing network ID in both left and right. left_network_id : str, list, np.array, pd.Series (default None) - the name of the left dataframe column, ``np.array``, or ``pd.Series`` where is - stored object network ID + The name of the left dataframe column, ``np.array``, or ``pd.Series`` where + object network IDs are stored. right_network_id : str, list, np.array, pd.Series (default None) - the name of the right dataframe column, ``np.array``, or ``pd.Series`` of - streets with unique network id (has to be defined beforehand) - (can be defined using :func:`momepy.unique_id`) + The name of the right dataframe column, ``np.array``, or ``pd.Series`` of + streets with unique network IDs. These IDs have to be defined beforehand and + can be defined using :func:`momepy.unique_id`. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. left : GeoDataFrame - original left GeoDataFrame + The original ``left`` GeoDataFrame. right : GeoDataFrame - original right GeoDataFrame + The original ``right`` GeoDataFrame. network_id : str - the name of the column storing network ID in both left and right + The name of the column storing network ID in both ``left`` and ``right``. left_network_id : Series - Series containing used left ID + A Series containing used ``left`` ID. right_network_id : Series - Series containing used right ID + A Series containing used ``right`` ID. Examples -------- @@ -316,7 +312,7 @@ def __init__( class CellAlignment: """ - Calculate the difference between cell orientation and orientation of object + Calculate the difference between cell orientation and the orientation of object. .. math:: \\left|{\\textit{building orientation} - \\textit{cell orientation}}\\right| @@ -324,40 +320,40 @@ class CellAlignment: Parameters ---------- left : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. right : GeoDataFrame - GeoDataFrame containing tessellation cells (or relevant spatial units) + A GeoDataFrame containing tessellation cells (or relevant spatial units). left_orientations : str, list, np.array, pd.Series - the name of the left dataframe column, ``np.array``, or ``pd.Series`` where is - stored object orientation value - (can be calculated using :class:`momepy.Orientation`) + The name of the ``left`` dataframe column, ``np.array``, or + `pd.Series`` where object orientation values are stored. This + can be calculated using :class:`momepy.Orientation`. right_orientations : str, list, np.array, pd.Series - the name of the right dataframe column, ``np.array``, or ``pd.Series`` where is - stored object orientation value - (can be calculated using :class:`momepy.Orientation`) + The name of the ``right`` dataframe column, ``np.array``, or ``pd.Series`` + where object orientation values are stored. This + can be calculated using :class:`momepy.Orientation`. left_unique_id : str - the name of the ``left`` dataframe column with unique id shared between ``left`` - and ``right`` gdf + The name of the ``left`` dataframe column with a unique + ID shared between the ``left`` and ``right`` GeoDataFrame objects. right_unique_id : str - the name of the ``right`` dataframe column with unique id shared between - ``left`` and ``right`` gdf + The name of the ``right`` dataframe column with a unique + ID shared between the ``left`` and ``right`` GeoDataFrame objects. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. left : GeoDataFrame - original left GeoDataFrame + The original ``left`` GeoDataFrame. right : GeoDataFrame - original right GeoDataFrame + The original ``right`` GeoDataFrame. left_orientations : Series - Series containing used left orientations + A Series containing used ``left`` orientations. right_orientations : Series - Series containing used right orientations + A Series containing used ``right`` orientations. left_unique_id : Series - Series containing used left ID + A Series containing used ``left`` ID. right_unique_id : Series - Series containing used right ID + A Series containing used ``right`` ID. Examples -------- @@ -414,7 +410,7 @@ class Alignment: """ Calculate the mean deviation of solar orientation of objects on adjacent cells - from an object + from an object. .. math:: \\frac{1}{n}\\sum_{i=1}^n dev_i=\\frac{dev_1+dev_2+\\cdots+dev_n}{n} @@ -422,30 +418,30 @@ class Alignment: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. spatial_weights : libpysal.weights, optional - spatial weights matrix + A spatial weights matrix. orientations : str, list, np.array, pd.Series - the name of the left dataframe column, ``np.array``, or ``pd.Series`` where is - stored object orientation value - (can be calculated using :class:`momepy.Orientation`) + The name of the left dataframe column, ``np.array``, or ``pd.Series`` + where object orientation values are stored. This + can be calculated using :class:`momepy.Orientation`. unique_id : str - name of the column with unique id used as ``spatial_weights`` index. + The name of the unique ID column used as the ``spatial_weights`` index. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. orientations : Series - Series containing used orientation values + A Series containing used orientation values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. Examples -------- @@ -492,8 +488,7 @@ def __init__(self, gdf, spatial_weights, unique_id, orientations, verbose=True): class NeighborDistance: """ - Calculate the mean distance to adjacent buildings (based on ``spatial_weights``) - + Calculate the mean distance to adjacent buildings (based on ``spatial_weights``). If no neighbours are found, return ``np.nan``. .. math:: @@ -504,24 +499,24 @@ class NeighborDistance: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. spatial_weights : libpysal.weights - spatial weights matrix based on unique_id + A spatial weights matrix based on ``unique_id``. unique_id : str - name of the column with unique id used as ``spatial_weights`` index. + The name of the unique ID column used as the ``spatial_weights`` index. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. Examples -------- @@ -563,39 +558,35 @@ def __init__(self, gdf, spatial_weights, unique_id, verbose=True): class MeanInterbuildingDistance: """ - Calculate the mean interbuilding distance - - Interbuilding distances are calculated between buildings on adjacent cells based on + Calculate the mean interbuilding distance. Interbuilding distances are + calculated between buildings on adjacent cells based on ``spatial_weights``, while the extent is defined as order of contiguity. - .. math:: - - Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. unique_id : str - name of the column with unique id used as ``spatial_weights`` index + The name of the unique ID column used as the ``spatial_weights`` index. spatial_weights : libpysal.weights - spatial weights matrix + A spatial weights matrix. order : int - Order of contiguity defining the extent + The order of contiguity defining the extent. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. sw_higher : libpysal.weights - Spatial weights matrix of higher order + The spatial weights matrix of higher order. order : int Order of contiguity. @@ -663,10 +654,9 @@ def __init__( class NeighboringStreetOrientationDeviation: """ - Calculate the mean deviation of solar orientation of adjacent streets - - Orientation of street segment is represented by the orientation of line - connecting first and last point of the segment. + Calculate the mean deviation of solar orientation of adjacent streets. The + orientation of a street segment is represented by the orientation of the line + connecting the first and last point of the segment. .. math:: \\frac{1}{n}\\sum_{i=1}^n dev_i=\\frac{dev_1+dev_2+\\cdots+dev_n}{n} @@ -674,16 +664,16 @@ class NeighboringStreetOrientationDeviation: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing street network to analyse + A GeoDataFrame containing objects to analyse. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. orientation : Series - Series containing used street orientation values + A Series containing used street orientation values. Examples -------- @@ -738,41 +728,40 @@ def _orient(self, geom): class BuildingAdjacency: """ - Calculate the level of building adjacency - - Building adjacency reflects how much buildings tend to join together into larger - structures. - It is calculated as a ratio of joined built-up structures and buildings within - the extent defined in ``spatial_weights_higher``. + Calculate the level of building adjacency. Building adjacency reflects how much + buildings tend to join together into larger structures. It is calculated as a + ratio of joined built-up structures and buildings within the extent defined + in ``spatial_weights_higher``. Adapted from :cite:`vanderhaegen2017`. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. spatial_weights_higher : libpysal.weights - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index + The name of the unique ID column used as the ``spatial_weights`` index. spatial_weights : libpysal.weights, optional - spatial weights matrix - If None, Queen contiguity matrix will be calculated - based on gdf. It is to denote adjacent buildings (note: based on unique ID). + A spatial weights matrix. If ``None``, a Queen contiguity matrix will + be calculated based on ``gdf``. It is to denote adjacent buildings + and is based on ``unique_id``. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. sw_higher : libpysal.weights - spatial weights matrix + A higher order spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique IDs. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. Examples -------- @@ -832,42 +821,40 @@ def __init__( class Neighbors: """ - Calculate the number of neighbours captured by ``spatial_weights`` - - If ``weighted=True``, number of neighbours will be divided by the perimeter of - object to return relative value. + Calculate the number of neighbours captured by ``spatial_weights``. If + ``weighted=True``, the number of neighbours will be divided by the perimeter of + the object to return relative value. Adapted from :cite:`hermosilla2012`. - Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. spatial_weights : libpysal.weights - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index + The name of the unique ID column used as the ``spatial_weights`` index. weighted : bool (default False) - if ``True``, number of neighbours will be divided by the perimeter of object, - to return relative value + If ``True``, the number of neighbours will be divided + by the perimeter of object, to return the relative value. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : Series - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. weighted : bool - used weighted value + Whether object is weighted or not. Examples -------- diff --git a/momepy/diversity.py b/momepy/diversity.py index 6defc9a5..279551ce 100644 --- a/momepy/diversity.py +++ b/momepy/diversity.py @@ -28,7 +28,6 @@ class Range: """ Calculates the range of values within neighbours defined in ``spatial_weights``. - Uses ``scipy.stats.iqr`` under the hood. Adapted from :cite:`dibble2017`. @@ -36,38 +35,41 @@ class Range: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing morphological tessellation. values : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored character value. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where character values are stored. spatial_weights : libpysal.weights - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index - rng : Two-element sequence containing floats in range of [0,100], optional - Percentiles over which to compute the range. Each must be - between 0 and 100, inclusive. The order of the elements is not important. - **kwargs : keyword arguments - optional arguments for ``scipy.stats.iqr`` + The name of the column with unique IDs used as the ``spatial_weights`` index. + rng : tuple, list, optional (default None) + A two-element sequence containing floats between 0 and 100 (inclusive) + that are the percentiles over which to compute the range. + The order of the elements is not important. + **kwargs : dict + Optional arguments for ``scipy.stats.iqr``. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : Series - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID - rng : tuple - range + A Series containing used unique ID. + rng : tuple, list, optional (default None) + A two-element sequence containing floats between 0 and 100 (inclusive) + that are the percentiles over which to compute the range. + The order of the elements is not important. kwargs : dict - kwargs + Optional arguments for ``scipy.stats.iqr``. Examples -------- @@ -78,8 +80,6 @@ class Range: ... 'uID', ... rng=(25, 75)).series 100%|██████████| 144/144 [00:00<00:00, 722.50it/s] - - """ def __init__( @@ -124,9 +124,8 @@ def __init__( class Theil: """ Calculates the Theil measure of inequality of values within neighbours defined in - ``spatial_weights``. - - Uses ``inequality.theil.Theil`` under the hood. Requires '`inequality`' package. + ``spatial_weights``. Uses ``inequality.theil.Theil`` under the hood. + Requires '`inequality`' package. .. math:: @@ -139,34 +138,37 @@ class Theil: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing morphological tessellation. values : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored character value. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where character values are stored. spatial_weights : libpysal.weights - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index - rng : Two-element sequence containing floats in range of [0,100], optional - Percentiles over which to compute the range. Each must be - between 0 and 100, inclusive. The order of the elements is not important. + The name of the column with unique IDs used as the ``spatial_weights`` index. + rng : tuple, list, optional (default None) + A two-element sequence containing floats between 0 and 100 (inclusive) + that are the percentiles over which to compute the range. + The order of the elements is not important. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : Series - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID - rng : tuple, optional - range + A Series containing used unique ID. + rng : tuple, list, optional (default None) + A two-element sequence containing floats between 0 and 100 (inclusive) + that are the percentiles over which to compute the range. + The order of the elements is not important. Examples -------- @@ -220,11 +222,9 @@ def __init__(self, gdf, values, spatial_weights, unique_id, rng=None, verbose=Tr class Simpson: """ - Calculates the Simpson\'s diversity index of values within neighbours defined in - ``spatial_weights``. - - Uses ``mapclassify.classifiers`` under the hood for binning. Requires - ``mapclassify>=.2.1.0`` dependency. + Calculates the Simpson's diversity index of values within neighbours defined in + ``spatial_weights``. Uses ``mapclassify.classifiers`` under the hood for binning. + Requires ``mapclassify>=.2.1.0`` dependency. .. math:: @@ -235,48 +235,49 @@ class Simpson: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing morphological tessellation. values : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored character value. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where character values are stored. spatial_weights : libpysal.weights, optional - spatial weights matrix - If None, Queen contiguity matrix of set order will be - calculated based on objects. + A spatial weights matrix. If ``None``, Queen contiguity + matrix of set order will be calculated based on objects. unique_id : str - name of the column with unique id used as ``spatial_weights`` index + The name of the column with unique IDs used as the ``spatial_weights`` index. binning : str (default 'HeadTailBreaks') One of mapclassify classification schemes. For details see `mapclassify API documentation `_. gini_simpson : bool (default False) - return Gini-Simpson index instead of Simpson index (``1 - λ``) + Return Gini-Simpson index instead of Simpson index (``1 - λ``). inverse : bool (default False) - return Inverse Simpson index instead of Simpson index (``1 / λ``) + Return Inverse Simpson index instead of Simpson index (``1 / λ``). categorical : bool (default False) - treat values as categories (will not use ``binning``) + Treat values as categories (will not use ``binning``). verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. **classification_kwds : dict - Keyword arguments for classification scheme + Keyword arguments for the classification scheme. For details see `mapclassify documentation `_. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : Series - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. binning : str - binning method + The binning method used. bins : mapclassify.classifiers.Classifier - generated bins + The generated bins. classification_kwds : dict - classification_kwds + Keyword arguments for the classification scheme. + For details see `mapclassify documentation `_. Examples -------- @@ -289,7 +290,7 @@ class Simpson: See also -------- - momepy.simpson_diversity : Calculates the Simpson\'s diversity index of data + momepy.simpson_diversity : Calculates the Simpson's diversity index of data. """ def __init__( @@ -362,32 +363,31 @@ def __init__( def simpson_diversity(values, bins=None, categorical=False): """ - Calculates the Simpson\'s diversity index of data. Helper function for + Calculates the Simpson's diversity index of data. Helper function for :py:class:`momepy.Simpson`. .. math:: \\lambda=\\sum_{i=1}^{R} p_{i}^{2} - Parameters ---------- values : pandas.Series - list of values + A list of values. bins : array, optional - array of top edges of classification bins. - Should be equalt to the result of binnng.bins. + An array of top edges of classification bins. + Should be equal to the result of ``binning.bins``. categorical : bool (default False) - treat values as categories (will not use ``bins``) + Treat values as categories (will not use ``bins``). Returns ------- float - Simpson's diversity index + Simpson's diversity index. See also -------- - momepy.Simpson : Calculates the Simpson\'s diversity index + momepy.Simpson : Calculates the Simpson's diversity index. """ if not categorical: try: @@ -410,43 +410,45 @@ def simpson_diversity(values, bins=None, categorical=False): class Gini: """ Calculates the Gini index of values within neighbours defined in - ``spatial_weights``. - - Uses ``inequality.gini.Gini`` under the hood. Requires '`inequality`' package. + ``spatial_weights``. Uses ``inequality.gini.Gini`` under the hood. + Requires '`inequality`' package. .. math:: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing morphological tessellation. values : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored character value. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where character values are stored. spatial_weights : libpysal.weights - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index - rng : Two-element sequence containing floats in range of [0,100], optional - Percentiles over which to compute the range. Each must be - between 0 and 100, inclusive. The order of the elements is not important. + The name of the column with unique IDs used as the ``spatial_weights`` index. + rng : tuple, list, optional (default None) + A two-element sequence containing floats between 0 and 100 (inclusive) + that are the percentiles over which to compute the range. + The order of the elements is not important. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : Series - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID - rng : tuple - range + A Series containing used unique ID. + rng : tuple, list, optional (default None) + A two-element sequence containing floats between 0 and 100 (inclusive) + that are the percentiles over which to compute the range. + The order of the elements is not important. Examples -------- @@ -510,10 +512,8 @@ def __init__(self, gdf, values, spatial_weights, unique_id, rng=None, verbose=Tr class Shannon: """ Calculates the Shannon index of values within neighbours defined in - ``spatial_weights``. - - Uses ``mapclassify.classifiers`` under the hood for binning. - Requires ``mapclassify>=.2.1.0`` dependency. + ``spatial_weights``. Uses ``mapclassify.classifiers`` under the hood + for binning. Requires ``mapclassify>=.2.1.0`` dependency. .. math:: @@ -522,24 +522,24 @@ class Shannon: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing morphological tessellation. values : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where - is stored character value. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where character values are stored. spatial_weights : libpysal.weights, optional - spatial weights matrix - If None, Queen contiguity matrix of set order - will be calculated based on objects. + A spatial weights matrix. If ``None``, Queen contiguity + matrix of set order will be calculated based on objects. unique_id : str - name of the column with unique id used as ``spatial_weights`` index + The name of the column with unique IDs used as the ``spatial_weights`` index. binning : str One of mapclassify classification schemes. For details see `mapclassify API documentation `_. categorical : bool (default False) - treat values as categories (will not use binning) + Treat values as categories (will not use binning). categories : list-like (default None) - list of categories. If None values.unique() is used. + A list of categories. If ``None``, ``values.unique()`` is used. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. **classification_kwds : dict Keyword arguments for classification scheme For details see `mapclassify documentation `_. @@ -547,21 +547,22 @@ class Shannon: Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : Series - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. binning : str - binning method + The binning method used. bins : mapclassify.classifiers.Classifier - generated bins + The generated bins. classification_kwds : dict - classification_kwds + Keyword arguments for classification scheme + For details see `mapclassify documentation `_. Examples -------- @@ -639,36 +640,36 @@ def __init__( def shannon_diversity(data, bins=None, categorical=False, categories=None): """ - Calculates the Shannon\'s diversity index of data. Helper function for + Calculates the Shannon's diversity index of data. Helper function for :py:class:`momepy.Shannon`. .. math:: \\lambda=\\sum_{i=1}^{R} p_{i}^{2} - Formula adapted from https://gist.github.com/audy/783125 + Formula adapted from https://gist.github.com/audy/783125. Parameters ---------- data : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing morphological tessellation. bins : array, optional - array of top edges of classification bins. Result of binnng.bins. + An array of top edges of classification bins. Result of ``binning.bins``. categorical : bool (default False) - treat values as categories (will not use ``bins``) + tTeat values as categories (will not use ``bins``). categories : list-like (default None) - list of categories + A list of categories. Returns ------- float - Shannon's diversity index + Shannon's diversity index. See also -------- - momepy.Shannon : Calculates the Shannon's diversity index - momepy.Simpson : Calculates the Simpson's diversity index - momepy.simpson_diversity : Calculates the Simpson's diversity index + momepy.Shannon : Calculates the Shannon's diversity index. + momepy.Simpson : Calculates the Simpson's diversity index. + momepy.simpson_diversity : Calculates the Simpson's diversity index. """ from math import log as ln @@ -709,31 +710,31 @@ class Unique: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing morphological tessellation. values : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where - is stored character value. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where character values are stored. spatial_weights : libpysal.weights - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index + The name of the column with unique IDs used as the ``spatial_weights`` index. dropna : bool (default True) - Don’t include NaN in the counts of unique values. + Don’t include ``NaN`` in the counts of unique values. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : Series - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. Examples -------- @@ -777,22 +778,22 @@ def __init__( class Percentiles: """ - Calculates the percentiles of values within neighbours defined in - ``spatial_weights``. + Calculates the percentiles of values within + neighbours defined in ``spatial_weights``. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing source geometry + A GeoDataFrame containing source geometry. values : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` - where is stored character value. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where character values are stored. spatial_weights : libpysal.weights - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index + The name of the column with unique IDs used as the ``spatial_weights`` index. percentiles : array-like (default [25, 50, 75]) - percentiles to return + The percentiles to return. interpolation : {'linear', 'lower', 'higher', 'midpoint', 'nearest'} This optional parameter specifies the interpolation method to use when the desired percentile lies between two data points @@ -807,25 +808,25 @@ class Percentiles: See the documentation of ``numpy.percentile`` for details. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. weighted : {'linear', None} (default None) - Distance decay weighting. If None, each neighbor within - `spatial_weights` has equal weight. If `linear`, linear + Distance decay weighting. If ``None``, each neighbor within + ``spatial_weights`` has equal weight. If ``'linear'``, linear inverse distance between centroids is used as a weight. Attributes ---------- frame : DataFrame - DataFrame containing resulting values + A DataFrame containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : Series - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. Examples -------- diff --git a/momepy/elements.py b/momepy/elements.py index b7983129..110f4ed1 100644 --- a/momepy/elements.py +++ b/momepy/elements.py @@ -38,34 +38,34 @@ def buffered_limit(gdf, buffer=100): Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing building footprints + A GeoDataFrame containing building footprints. buffer : float - buffer around buildings limiting the extend of tessellation + A buffer around buildings limiting the extend of tessellation. Returns ------- MultiPolygon - MultiPolygon or Polygon defining the study area + A MultiPolygon or Polygon defining the study area. Examples -------- >>> limit = mm.buffered_limit(buildings_df) >>> type(limit) shapely.geometry.polygon.Polygon - """ return gdf.buffer(buffer).unary_union class Tessellation: """ - Generates tessellation. - - Three versions of tessellation can be created: + Generates tessellation. Three versions of tessellation can be created: - 1. Morphological tessellation around given buildings ``gdf`` within set ``limit``. - 2. Proximity bands around given street network ``gdf`` within set ``limit``. - 3. Enclosed tessellation based on given buildings ``gdf`` within ``enclosures``. + 1. Morphological tessellation around given buildings + ``gdf`` within set ``limit``. + 2. Proximity bands around given street network ``gdf`` + within set ``limit``. + 3. Enclosed tessellation based on given buildings + ``gdf`` within ``enclosures``. Pass either ``limit`` to create morphological tessellation or proximity bands or ``enclosures`` to create enclosed tessellation. @@ -73,40 +73,44 @@ class Tessellation: See :cite:`fleischmann2020` for details of implementation of morphological tessellation and :cite:`araldi2019` for proximity bands. - Tessellation requires data of relatively high level of precision and there are three - particular patterns causing issues.\n - 1. Features will collapse into empty polygon - these do not have tessellation - cell in the end.\n - 2. Features will split into MultiPolygon - at some cases, features with narrow links - between parts split into two during 'shrinking'. In most cases that is not an issue - and resulting tessellation is correct anyway, but sometimes this result in a cell - being MultiPolygon, which is not correct.\n - 3. Overlapping features - features which overlap even after 'shrinking' cause - invalid tessellation geometry.\n + Tessellation requires data of relatively high level of precision + and there are three particular patterns causing issues: + + 1. Features will collapse into empty polygon - these + do not have tessellation cell in the end. + 2. Features will split into MultiPolygons - in some cases, + features with narrow links between parts split into two + during 'shrinking'. In most cases that is not an issue + and the resulting tessellation is correct anyway, but + sometimes this results in a cell being a MultiPolygon, + which is not correct. + 3. Overlapping features - features which overlap even + after 'shrinking' cause invalid tessellation geometry. + All three types can be tested prior :class:`momepy.Tessellation` using :class:`momepy.CheckTessellationInput`. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing building footprints or street network + A GeoDataFrame containing building footprints or street network. unique_id : str - name of the column with unique id + The name of the column with the unique ID. limit : MultiPolygon or Polygon (default None) - MultiPolygon or Polygon defining the study area limiting - morphological tessellation or proximity bands - (otherwise it could go to infinity). + MultiPolygon or Polygon defining the study area limiting morphological + tessellation or proximity bands (otherwise it could go to infinity). shrink : float (default 0.4) - distance for negative buffer to generate space between adjacent polygons + The distance for negative buffer to generate space between adjacent polygons (if geometry type of gdf is (Multi)Polygon). segment : float (default 0.5) - maximum distance between points after discretization + The maximum distance between points after discretization. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. enclosures : GeoDataFrame (default None) - Enclosures geometry. Can be generated using :func:`momepy.enclosures`. + The enclosures geometry, which can be generated + using :func:`momepy.enclosures`. enclosure_id : str (default 'eID') - name of the enclosure_id containing unique identifer for each row in + The name of the ``enclosure_id`` containing unique identifer for each row in ``enclosures``. Applies only if ``enclosures`` are passed. threshold : float (default 0.05) The minimum threshold for a building to be considered within an enclosure. @@ -117,35 +121,36 @@ class Tessellation: Use parallelised algorithm based on ``dask.dataframe``. Requires dask. Applies only if ``enclosures`` are passed. n_chunks : None - Number of chunks to be used in parallelization. Ideal is one chunk per thread. - Applies only if ``enclosures`` are passed. Defualt automatically uses - n == dask.system.cpu_count. + The number of chunks to be used in parallelization. Ideal is one chunk per + thread. Applies only if ``enclosures`` are passed. Default automatically + uses ``n == dask.system.cpu_count``. Attributes ---------- tessellation : GeoDataFrame - GeoDataFrame containing resulting tessellation - + A GeoDataFrame containing resulting tessellation. For enclosed tessellation, gdf contains three columns: + - ``geometry``, - ``unique_id`` matching with parental building, - ``enclosure_id`` matching with enclosure integer index gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. id : Series - Series containing used unique ID + A Series containing used unique ID. limit : MultiPolygon or Polygon - limit + MultiPolygon or Polygon defining the study area limiting morphological + tessellation or proximity bands. shrink : float - used shrink value + The distance for negative buffer to generate space between adjacent polygons. segment : float - used segment value + The maximum distance between points after discretization. collapsed : list - list of unique_id's of collapsed features (if there are some) + A list of ``unique_id``s of collapsed features (if there are any). Applies only if ``limit`` is passed. multipolygons : list - list of unique_id's of features causing MultiPolygons (if there are some) + A list of ``unique_id``s of features causing MultiPolygons (if there are any). Applies only if ``limit`` is passed. Examples @@ -177,7 +182,6 @@ class Tessellation: 2 111.0 POLYGON ((1603458.666 6464332.614, 1603458.332... 0 3 112.0 POLYGON ((1603462.235 6464285.609, 1603454.795... 0 4 113.0 POLYGON ((1603524.561 6464388.609, 1603532.241... 0 - """ def __init__( @@ -206,7 +210,7 @@ def __init__( raise ValueError( "Geometry is in a geographic CRS. " "Use 'GeoDataFrame.to_crs()' to re-project geometries to a " - "projected CRS before using Tessellation.\n", + "projected CRS before using Tessellation.", ) if limit is not None and enclosures is not None: @@ -322,7 +326,7 @@ def _morphological_tessellation( def _dense_point_array(self, geoms, distance, index): """ - geoms - array of pygeos lines + geoms : array of pygeos lines """ # interpolate lines to represent them as points for Voronoi points = [] @@ -350,9 +354,7 @@ def _dense_point_array(self, geoms, distance, index): # to get a higher precision on the corners def _regions(self, voronoi_diagram, unique_id, ids, crs): - """ - Generate GeoDataFrame of Voronoi regions from scipy.spatial.Voronoi. - """ + """Generate GeoDataFrame of Voronoi regions from scipy.spatial.Voronoi.""" vertices = pd.Series(voronoi_diagram.regions).take(voronoi_diagram.point_region) polygons = [] for region in vertices: @@ -371,9 +373,7 @@ def _regions(self, voronoi_diagram, unique_id, ids, crs): return regions_gdf def _check_result(self, tesselation, orig_gdf, unique_id): - """ - Check whether result matches buildings and contains only Polygons. - """ + """Check whether result matches buildings and contains only Polygons.""" # check against input layer ids_original = list(orig_gdf[unique_id]) ids_generated = list(tesselation[unique_id]) @@ -381,9 +381,9 @@ def _check_result(self, tesselation, orig_gdf, unique_id): self.collapsed = set(ids_original).difference(ids_generated) warnings.warn( - f"Tessellation does not fully match buildings. " + "Tessellation does not fully match buildings. " f"{len(self.collapsed)} element(s) collapsed " - f"during generation - unique_id: {self.collapsed}" + f"during generation - unique_id: {self.collapsed}." ) # check MultiPolygons - usually caused by error in input geometry @@ -392,8 +392,9 @@ def _check_result(self, tesselation, orig_gdf, unique_id): ] if len(self.multipolygons) > 0: warnings.warn( - "Tessellation contains MultiPolygon elements. Initial objects should " - f"be edited. unique_id of affected elements: {list(self.multipolygons)}" + "Tessellation contains MultiPolygon elements. Initial " + "objects should be edited. `unique_id` of affected " + f"elements: {list(self.multipolygons)}." ) def _enclosed_tessellation( @@ -407,47 +408,47 @@ def _enclosed_tessellation( n_chunks=None, **kwargs, ): - """Enclosed tessellation - Generate enclosed tessellation based on barriers defining enclosures and - building footprints. + """ + Generate enclosed tessellation based on barriers + defining enclosures and building footprints. Parameters ---------- buildings : GeoDataFrame - GeoDataFrame containing building footprints. Expects (Multi)Polygon - geometry. + A GeoDataFrame containing building footprints. + Expects (Multi)Polygon geometry. enclosures : GeoDataFrame Enclosures geometry. Can be generated using :func:`momepy.enclosures`. unique_id : str - name of the column with unique id of buildings gdf + The name of the column with the unique ID of ``buildings`` gdf. threshold : float (default 0.05) The minimum threshold for a building to be considered within an enclosure. Threshold is a ratio of building area which needs to be within an enclosure - to inlude it in the tessellation of that enclosure. Resolves sliver geometry - issues. + to inlude it in the tessellation of that enclosure. + Resolves sliver geometry issues. use_dask : bool (default True) Use parallelised algorithm based on ``dask.dataframe``. Requires dask. n_chunks : None - Number of chunks to be used in parallelization. Ideal is one chunk per - thread. Applies only if ``enclosures`` are passed. Defualt automatically - uses n == dask.system.cpu_count. - **kwargs - Keyword arguments passed to Tessellation algorithm (as ``shrink`` - or ``segment``). + The number of chunks to be used in parallelization. Ideal is one chunk per + thread. Applies only if ``enclosures`` are passed. Default automatically + uses ``n == dask.system.cpu_count``. + **kwargs : dict + Keyword arguments passed to Tessellation algorithm + (such as ``'shrink'`` or ``'segment'``). Returns ------- tessellation : GeoDataFrame - gdf contains three columns: - geometry, - unique_id matching with parental building, - enclosure_id matching with enclosure integer index + A GeoDataFrame containing three columns: + + - ``geometry``, + - ``unique_id`` matching with parent building, + - ``enclosure_id`` matching with enclosure integer index Examples -------- >>> enclosures = mm.enclosures(streets, admin_boundary, [railway, rivers]) >>> enclosed_tess = mm.enclosed_tessellation(buildings, enclosures) - """ enclosures = enclosures.reset_index(drop=True) enclosures["position"] = range(len(enclosures)) @@ -550,43 +551,42 @@ def _tess( class Blocks: """ Generate blocks based on buildings, tessellation, and street network. - Dissolves tessellation cells based on street-network based polygons. - Links resulting id to ``buildings`` and ``tessellation`` as attributes. + Links resulting ID to ``buildings`` and ``tessellation`` as attributes. Parameters ---------- tessellation : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing morphological tessellation. edges : GeoDataFrame - GeoDataFrame containing street network + A GeoDataFrame containing a street network. buildings : GeoDataFrame - GeoDataFrame containing buildings + A GeoDataFrame containing buildings. id_name : str - name of the unique blocks id column to be generated + The name of the unique blocks ID column to be generated. unique_id : str - name of the column with unique id. If there is none, it could be generated - by :func:`momepy.unique_id`. - This should be the same for cells and buildings, id's should match. + The name of the column with the unique ID. If there is none, it can be + generated with :func:`momepy.unique_id`. This should be the same for + cells and buildings; ID's should match. Attributes ---------- blocks : GeoDataFrame - GeoDataFrame containing generated blocks + A GeoDataFrame containing generated blocks. buildings_id : Series - Series derived from buildings with block ID + A Series derived from buildings with block ID. tessellation_id : Series - Series derived from morphological tessellation with block ID + A Series derived from morphological tessellation with block ID. tessellation : GeoDataFrame - GeoDataFrame containing original tessellation + A GeoDataFrame containing original tessellation. edges : GeoDataFrame - GeoDataFrame containing original edges + A GeoDataFrame containing original edges. buildings : GeoDataFrame - GeoDataFrame containing original buildings + A GeoDataFrame containing original buildings. id_name : str - name of the unique blocks id column + The name of the unique blocks ID column. unique_id : str - name of the column with unique id + The name of the column with unique ID. Examples -------- @@ -598,7 +598,6 @@ class Blocks: 2 3.0 POLYGON ((1603056.595487018 6464093.903488506,... 3 4.0 POLYGON ((1603260.943782872 6464141.327631323,... 4 5.0 POLYGON ((1603183.399594798 6463966.109982309,... - """ def __init__(self, tessellation, edges, buildings, id_name, unique_id, **kwargs): @@ -610,7 +609,7 @@ def __init__(self, tessellation, edges, buildings, id_name, unique_id, **kwargs) if id_name in buildings.columns: raise ValueError( - "'{}' column cannot be in the buildings GeoDataFrame".format(id_name) + f"'{id_name}' column cannot be in the buildings GeoDataFrame." ) cut = gpd.overlay( @@ -675,33 +674,30 @@ def __init__(self, tessellation, edges, buildings, id_name, unique_id, **kwargs) def get_network_id(left, right, network_id, min_size=100, verbose=True): """ - Snap each element (preferably building) to the closest street network segment, - saves its id. - - Adds network ID to elements. + Snap each element (preferably building) to the closest + street network segment and save its ID. Also, adds network ID to elements. Parameters ---------- left : GeoDataFrame - GeoDataFrame containing objects to snap + A GeoDataFrame containing objects to snap. right : GeoDataFrame - GeoDataFrame containing street network with unique network ID. - If there is none, it could be generated by :func:`momepy.unique_id`. + A GeoDataFrame containing a street network with unique network IDs. + If there is none, it can be generated with :func:`momepy.unique_id`. network_id : str, list, np.array, pd.Series (default None) - the name of the streets dataframe column, ``np.array``, or ``pd.Series`` - with network unique id. + The name of the streets dataframe column, ``np.array``, or ``pd.Series`` + with network unique IDs. min_size : int (default 100) - min_size should be a vaule such that if you build a box centered in each + A minimum size should be a valuee such that if you build a box centered in each building centroid with edges of size ``2*min_size``, you know a priori that at - least one - segment is intersected with the box. + least one segment is intersected with the box. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- elements_nID : Series - Series containing network ID for elements + A Series containing network ID for elements. Examples -------- @@ -757,8 +753,8 @@ def get_network_id(left, right, network_id, min_size=100, verbose=True): if series.isnull().any(): warnings.warn( - "Some objects were not attached to the network. " - "Set larger min_size. {} affected elements".format(sum(series.isnull())) + "Some objects were not attached to the network. Set larger " + f"`min_size``. {sum(series.isnull())} affected elements." ) return series @@ -774,46 +770,42 @@ def get_node_id( verbose=True, ): """ - Snap each building to closest street network node on the closest network edge. - + Snap each building to the closest street network node on the closest network edge. Adds node ID to objects (preferably buildings). Gets ID of edge - (:func:`momepy.get_network_id` or :func:`get_network_ratio`) - , and determines which of its end points is closer to building centroid. - - Pass either ``edge_id`` with a single value or ``edge_keys`` and ``edge_values`` - with ratios. + (:func:`momepy.get_network_id` or :func:`get_network_ratio`), and determines + which of its end points is closer to the building centroid. Pass either ``edge_id`` + with a single value or ``edge_keys`` and ``edge_values`` with ratios. Parameters ---------- objects : GeoDataFrame - GeoDataFrame containing objects to snap + A GeoDataFrame containing objects to snap. nodes : GeoDataFrame - GeoDataFrame containing street nodes with unique node ID. - If there is none, it could be generated by :func:`momepy.unique_id`. + A GeoDataFrame containing street nodes with unique node IDs. + If there is none, it can be generated by :func:`momepy.unique_id`. edges : GeoDataFrame - GeoDataFrame containing street edges with unique edge ID and IDs of start - and end points of each segment. Start and endpoints are default + A GeoDataFrame containing street edges with unique edge IDs and IDs + of start and end points of each segment. Start and endpoints are default outcome of :func:`momepy.nx_to_gdf`. node_id : str, list, np.array, pd.Series - the name of the nodes dataframe column, ``np.array``, or ``pd.Series`` - with unique id + The name of the ``nodes`` dataframe column, ``np.array``, + or ``pd.Series`` with a unique ID. edge_id : str (default None) - the name of the objects dataframe column - with unique edge id (like an outcome of :func:`momepy.get_network_id`) + The name of the objects dataframe column with unique edge IDs + (like an outcome of :func:`momepy.get_network_id`). edge_keys : str (default None) - name the name of the objects dataframe column with edgeID_keys - (like an outcome of :func:`momepy.get_network_ratio`) + The name of the objects dataframe column with ``edgeID_keys`` + (like an outcome of :func:`momepy.get_network_ratio`). edge_values : str (default None) - name the name of the objects dataframe column with edgeID_values - (like an outcome of :func:`momepy.get_network_ratio`) + The name of the objects dataframe column with ``edgeID_values`` + (like an outcome of :func:`momepy.get_network_ratio`). verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- node_ids : Series - Series containing node ID for objects - + A Series containing node the ID for objects. """ nodes = nodes.set_index(node_id) @@ -870,28 +862,24 @@ def get_node_id( def get_network_ratio(df, edges, initial_buffer=500): """ Link polygons to network edges based on the proportion of overlap (if a cell - intersects more than one edge) - - Useful if you need to link enclosed tessellation to street network. Ratios can - be used as weights when linking network-based values to cells. For a purely - distance-based link use :func:`momepy.get_network_id`. - + intersects more than one edge). Useful if you need to link enclosed tessellation to + street network. Ratios can be used as weights when linking network-based values + to cells. For a purely distance-based link use :func:`momepy.get_network_id`. Links are based on the integer position of edge (``iloc``). Parameters ---------- - df : GeoDataFrame - GeoDataFrame containing objects to snap (typically enclosed tessellation) + A GeoDataFrame containing objects to snap (typically enclosed tessellation). edges : GeoDataFrame - GeoDataFrame containing street network + A GeoDataFrame containing a street network. initial_buffer : float - Initial buffer used to link non-intersecting cells. + The initial buffer used to link non-intersecting cells. Returns ------- - - DataFrame + result : DataFrame + The resultant DataFrame. See also -------- @@ -908,7 +896,6 @@ def get_network_ratio(df, edges, initial_buffer=500): 2 [32] [1] 3 [0] [1.0] 4 [26] [1] - """ if not GPD_10: @@ -975,42 +962,38 @@ def enclosures( clip=False, ): """ - Generate enclosures based on passed barriers. - - Enclosures are areas enclosed from all sides by at least one type of - a barrier. Barriers are typically roads, railways, natural features - like rivers and other water bodies or coastline. Enclosures are a - result of polygonization of the ``primary_barrier`` and ``limit`` and its - subdivision based on additional_barriers. + Generate enclosures based on passed barriers. Enclosures are areas enclosed from + all sides by at least one type of a barrier. Barriers are typically roads, + railways, natural features like rivers and other water bodies or coastline. + Enclosures are a result of polygonization of the ``primary_barrier`` and ``limit`` + and its subdivision based on additional_barriers. Parameters ---------- primary_barriers : GeoDataFrame, GeoSeries - GeoDataFrame or GeoSeries containing primary barriers. + A GeoDataFrame or GeoSeries containing primary barriers. (Multi)LineString geometry is expected. limit : GeoDataFrame, GeoSeries, shapely geometry (default None) - GeoDataFrame, GeoSeries or shapely geometry containing external limit - of enclosures, - i.e. the area which gets partitioned. If None is passed, + A GeoDataFrame, GeoSeries or shapely geometry containing external limit + of enclosures, i.e. the area which gets partitioned. If ``None`` is passed, the internal area of ``primary_barriers`` will be used. additional_barriers : GeoDataFrame - GeoDataFrame or GeoSeries containing additional barriers. + A GeoDataFrame or GeoSeries containing additional barriers. (Multi)LineString geometry is expected. enclosure_id : str (default 'eID') - name of the enclosure_id (to be created). + The name of the ``enclosure_id`` (to be created). clip : bool (default False) - if True, returns enclosures with representative point within the limit + If ``True``, returns enclosures with representative point within the limit (if given). Requires ``limit`` composed of Polygon or MultiPolygon geometries. Returns ------- enclosures : GeoDataFrame - GeoDataFrame containing enclosure geometries and enclosure_id + A GeoDataFrame containing enclosure geometries and ``enclosure_id``. Examples -------- >>> enclosures = mm.enclosures(streets, admin_boundary, [railway, rivers]) - """ if limit is not None: if isinstance(limit, BaseGeometry): @@ -1029,8 +1012,8 @@ def enclosures( if additional_barriers is not None: if not isinstance(additional_barriers, list): raise TypeError( - "`additional_barriers` expects a list of GeoDataFrames or GeoSeries." - f"Got {type(additional_barriers)}." + "`additional_barriers` expects a list of GeoDataFrames " + f"or GeoSeries. Got {type(additional_barriers)}." ) additional = pd.concat([gdf.geometry for gdf in additional_barriers]) @@ -1076,7 +1059,7 @@ def enclosures( if not limit.geom_type.isin(["Polygon", "MultiPolygon"]).all(): raise TypeError( "`limit` requires a GeoDataFrame or GeoSeries with Polygon or " - "MultiPolygon geometry to be used with clip=True." + "MultiPolygon geometry to be used with `clip=True`." ) _, encl_index = final_enclosures.representative_point().sindex.query_bulk( limit.geometry, predicate="contains" diff --git a/momepy/graph.py b/momepy/graph.py index f6b8edeb..01a2be26 100644 --- a/momepy/graph.py +++ b/momepy/graph.py @@ -30,22 +30,20 @@ def node_degree(graph, name="degree"): """ - Calculates node degree for each node. - - Wrapper around ``networkx.degree()``. + Calculates node degree for each node. Wrapper around ``networkx.degree()``. Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. name : str (default 'degree') - calculated attribute name + The calculated attribute name. Returns ------- - Graph - networkx.Graph + netx : Graph + A networkx.Graph object . Examples -------- @@ -60,9 +58,7 @@ def node_degree(graph, name="degree"): def _meshedness(graph): - """ - Calculates meshedness of a graph. - """ + """Calculates meshedness of a graph.""" e = graph.number_of_edges() v = graph.number_of_nodes() return (e - v + 1) / (2 * v - 5) @@ -71,43 +67,40 @@ def _meshedness(graph): def meshedness(graph, radius=5, name="meshedness", distance=None, verbose=True): """ Calculates meshedness for subgraph around each node if radius is set, or for - whole graph, if ``radius=None``. - - Subgraph is generated around each node within set radius. If ``distance=None``, - radius will define topological distance, otherwise it uses values in distance - attribute. + whole graph, if ``radius=None``. A subgraph is generated around each node within + set radius. If ``distance=None``, radius will define topological distance, + otherwise it uses values in distance attribute. .. math:: \\alpha=\\frac{e-v+1}{2 v-5} - where :math:`e` is the number of edges in subgraph and :math:`v` is the number of - nodes in subgraph. + where :math:`e` is the number of edges in a subgraph and :math:`v` + is the number of nodes in a subgraph. Adapted from :cite:`feliciotti2018`. - Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. radius: int, optional - Include all neighbors of distance <= radius from n + Include all neighbors of distance <= radius from ``n``. name : str, optional - calculated attribute name + The calculated attribute name. distance : str, optional - Use specified edge data key as distance. - For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n. + Use specified edge data key as distance. For example, setting + ``distance=’weight’`` will use the edge ``weight`` to + measure the distance from the node ``n``. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph if radius is set + netx : Graph + A networkx.Graph object if ``radius`` is set. float - meshedness for graph if ``radius=None`` + The meshedness for the graph if ``radius=None``. Examples -------- @@ -132,30 +125,28 @@ def meshedness(graph, radius=5, name="meshedness", distance=None, verbose=True): def mean_node_dist(graph, name="meanlen", length="mm_len", verbose=True): """ Calculates mean distance to neighbouring nodes. - Mean of values in ``length`` attribute. Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. name : str, optional - calculated attribute name + The calculated attribute name. length : str, optional - name of attribute of segment length (geographical) + The name of the attribute of segment length (geographical). verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph + netx : Graph + A networkx.Graph object. Examples -------- >>> network_graph = mm.mean_node_dist(network_graph) - """ netx = graph.copy() @@ -170,9 +161,7 @@ def mean_node_dist(graph, name="meanlen", length="mm_len", verbose=True): def _cds_length(graph, mode, length): - """ - Calculates cul-de-sac length in a graph. - """ + """Calculates cul-de-sac length in a graph.""" lens = [] for u, v, k, cds in graph.edges.data("cdsbool", keys=True): if cds: @@ -181,7 +170,7 @@ def _cds_length(graph, mode, length): return sum(lens) if mode == "mean": return np.mean(lens) - raise ValueError("Mode {} is not supported. Use 'sum' or 'mean'.".format(mode)) + raise ValueError(f"Mode {mode} is not supported. Use 'sum' or 'mean'.") def cds_length( @@ -196,42 +185,39 @@ def cds_length( ): """ Calculates length of cul-de-sacs for subgraph around each node if radius is set, - or for whole graph, if ``radius=None``. - - Subgraph is generated around each node within set radius. If ``distance=None``, - radius will define topological distance, otherwise it uses values in distance - attribute. + or for whole graph, if ``radius=None``. A subgraph is generated around each node + within set radius. If ``distance=None``, radius will define topological distance, + otherwise it uses values in distance attribute. Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. radius : int - Include all neighbors of distance <= radius from n + Include all neighbors of distance <= radius from ``n``. mode : str (default 'sum') - if ``'sum'``, calculate total length, if ``'mean'`` calculate mean length + If ``'sum'``, calculate total length, if ``'mean'`` calculate mean length. name : str, optional - calculated attribute name + The calculated attribute name. degree : str - name of attribute of node degree (:py:func:`momepy.node_degree`) + The name of attribute of node degree (:py:func:`momepy.node_degree`). length : str, optional - name of attribute of segment length (geographical) + The name of the attribute of segment length (geographical). distance : str, optional - Use specified edge data key as distance. - For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n. + Use specified edge data key as distance. For example, setting + ``distance=’weight’`` will use the edge ``weight`` to + measure the distance from the node ``n``. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps - + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph if radius is set + netx : Graph + A networkx.Graph object if ``radius`` is set. float - length of cul-de-sacs for graph if ``radius=None`` + The length of cul-de-sacs for the graph if ``radius=None``. Examples -------- @@ -261,9 +247,7 @@ def cds_length( def _mean_node_degree(graph, degree): - """ - Calculates mean node degree in a graph. - """ + """Calculates mean node degree in a graph.""" return np.mean(list(dict(graph.nodes(degree)).values())) @@ -272,37 +256,34 @@ def mean_node_degree( ): """ Calculates mean node degree for subgraph around each node if radius is set, or for - whole graph, if ``radius=None``. - - Subgraph is generated around each node within set radius. If ``distance=None``, - radius will define topological distance, otherwise it uses values in ``distance`` - attribute. - + whole graph, if ``radius=None``. A subgraph is generated around each node within + set radius. If ``distance=None``, radius will define topological distance, + otherwise it uses values in ``distance`` attribute. Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. radius: int - radius defining the extent of subgraph + Include all neighbors of distance <= radius from ``n``. name : str, optional - calculated attribute name + The calculated attribute name. degree : str - name of attribute of node degree (:py:func:`momepy.node_degree`) + The name of attribute of node degree (:py:func:`momepy.node_degree`). distance : str, optional - Use specified edge data key as distance. - For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n. + Use specified edge data key as distance. For example, setting + ``distance=’weight’`` will use the edge ``weight`` to + measure the distance from the node ``n``. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph if radius is set + netx : Graph + A networkx.Graph object if ``radius`` is set. float - mean node degree for graph if ``radius=None`` + The mean node degree for the graph if ``radius=None``. Examples -------- @@ -323,9 +304,7 @@ def mean_node_degree( def _proportion(graph, degree): - """ - Calculates the proportion of intersection types in a graph. - """ + """Calculates the proportion of intersection types in a graph.""" import collections values = list(dict(graph.nodes(degree)).values()) @@ -345,49 +324,49 @@ def proportion( ): """ Calculates the proportion of intersection types for subgraph around each node if - radius is set, or for whole graph, if ``radius=None``. - - Subgraph is generated around each node within set radius. If ``distance=None``, - radius will define topological distance, otherwise it uses values in ``distance`` - attribute. + radius is set, or for whole graph, if ``radius=None``. A subgraph is generated + around each node within set radius. If ``distance=None``, the radius will define + topological distance, otherwise it uses values in ``distance`` attribute. Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. radius: int - Include all neighbors of distance <= radius from n + Include all neighbors of distance <= radius from ``n``. three : str, optional - attribute name for 3-way intersections proportion + The attribute name for 3-way intersections proportion. four : str, optional - attribute name for 4-way intersections proportion + The attribute name for 4-way intersections proportion. dead : str, optional - attribute name for deadends proportion + The attribute name for deadends proportion. degree : str - name of attribute of node degree (:py:func:`momepy.node_degree`) + The name of attribute of node degree (:py:func:`momepy.node_degree`). distance : str, optional - Use specified edge data key as distance. - For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n. + Use specified edge data key as distance. For example, setting + ``distance=’weight’`` will use the edge ``weight`` to + measure the distance from the node ``n``. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph if radius is set - dict - dict with proportions for graph if ``radius=None`` + netx : Graph + A networkx.Graph object if ``radius`` is set. + result : dict + A dict with proportions for the graph if ``radius=None``. Examples -------- - >>> network_graph = mm.proportion(network_graph, three='threeway', four='fourway', dead='deadends') # noqa + >>> network_graph = mm.proportion( + ... network_graph, three='threeway', four='fourway', dead='deadends' + ... ) # noqa """ if not three and not four and not dead: raise ValueError( - "Nothing to calculate. Define names for at least one proportion to be " - "calculated." + "Nothing to calculate. Define names for at least " + "one proportion to be calculated." ) netx = graph.copy() @@ -419,9 +398,7 @@ def proportion( def _cyclomatic(graph): - """ - Calculates the cyclomatic complexity of a graph. - """ + """Calculates the cyclomatic complexity of a graph.""" e = graph.number_of_edges() v = graph.number_of_nodes() return e - v + 1 @@ -430,11 +407,9 @@ def _cyclomatic(graph): def cyclomatic(graph, radius=5, name="cyclomatic", distance=None, verbose=True): """ Calculates cyclomatic complexity for subgraph around each node if radius is set, or - for whole graph, if ``radius=None``. - - Subgraph is generated around each node within set radius. If ``distance=None``, - radius will define topological distance, otherwise it uses values in ``distance`` - attribute. + for whole graph, if ``radius=None``. A subgraph is generated around each node + within set radius. If ``distance=None``, radius will define topological distance, + otherwise it uses values in ``distance`` attribute. .. math:: \\alpha=e-v+1 @@ -447,25 +422,25 @@ def cyclomatic(graph, radius=5, name="cyclomatic", distance=None, verbose=True): Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. radius: int - Include all neighbors of distance <= radius from n + Include all neighbors of distance <= radius from ``n``. name : str, optional - calculated attribute name + The calculated attribute name. distance : str, optional - Use specified edge data key as distance. - For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n. + Use specified edge data key as distance. For example, setting + ``distance=’weight’`` will use the edge ``weight`` to + measure the distance from the node ``n``. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph if radius is set + netx : Graph + A networkx.Graph object if ``radius`` is set. float - cyclomatic complexity for graph if ``radius=None`` + The cyclomatic complexity for the graph if ``radius=None``. Examples -------- @@ -488,9 +463,7 @@ def cyclomatic(graph, radius=5, name="cyclomatic", distance=None, verbose=True): def _edge_node_ratio(graph): - """ - Calculates edge / node ratio of a graph. - """ + """Calculates edge / node ratio of a graph.""" e = graph.number_of_edges() v = graph.number_of_nodes() return e / v @@ -501,11 +474,9 @@ def edge_node_ratio( ): """ Calculates edge / node ratio for subgraph around each node if radius is set, or for - whole graph, if ``radius=None``. - - Subgraph is generated around each node within set radius. If ``distance=None``, - radius will define topological distance, otherwise it uses values in ``distance`` - attribute. + whole graph, if ``radius=None``. A subgraph is generated around each node within + set radius. If ``distance=None``, radius will define topological distance, + otherwise it uses values in ``distance`` attribute. .. math:: \\alpha=e/v @@ -518,25 +489,25 @@ def edge_node_ratio( Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. radius: int - Include all neighbors of distance <= radius from n + Include all neighbors of distance <= radius from ``n``. name : str, optional - calculated attribute name + The calculated attribute name. distance : str, optional - Use specified edge data key as distance. - For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n. + Use specified edge data key as distance. For example, setting + ``distance=’weight’`` will use the edge ``weight`` to + measure the distance from the node ``n``. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph if radius is set + netx : Graph + A networkx.Graph object if ``radius`` is set. float - edge / node ratio for graph if ``radius=None`` + The edge / node ratio for the graph if ``radius=None``. Examples -------- @@ -559,9 +530,7 @@ def edge_node_ratio( def _gamma(graph): - """ - Calculates gamma index of a graph. - """ + """Calculates gamma index of a graph.""" e = graph.number_of_edges() v = graph.number_of_nodes() if v == 2: @@ -572,11 +541,9 @@ def _gamma(graph): def gamma(graph, radius=5, name="gamma", distance=None, verbose=True): """ Calculates connectivity gamma index for subgraph around each node if radius is set, - or for whole graph, if ``radius=None``. - - Subgraph is generated around each node within set radius. If ``distance=None``, - radius will define topological distance, otherwise it uses values in ``distance`` - attribute. + or for whole graph, if ``radius=None``. A subgraph is generated around each node + within set radius. If ``distance=None``, radius will define topological distance, + otherwise it uses values in ``distance`` attribute. .. math:: \\alpha=\\frac{e}{3(v-2)} @@ -589,30 +556,29 @@ def gamma(graph, radius=5, name="gamma", distance=None, verbose=True): Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. radius: int - Include all neighbors of distance <= radius from n + Include all neighbors of distance <= radius from ``n``. name : str, optional - calculated attribute name + The calculated attribute name. distance : str, optional - Use specified edge data key as distance. - For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n. + Use specified edge data key as distance. For example, setting + ``distance=’weight’`` will use the edge ``weight`` to + measure the distance from the node ``n``. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph if radius is set + netx : Graph + A networkx.Graph object if ``radius`` is set. float - gamma index for graph if ``radius=None`` + The gamma index for the graph if ``radius=None``. Examples -------- >>> network_graph = mm.gamma(network_graph, radius=3) - """ netx = graph.copy() @@ -631,22 +597,20 @@ def gamma(graph, radius=5, name="gamma", distance=None, verbose=True): def clustering(graph, name="cluster"): """ Calculates the squares clustering coefficient for nodes. - Wrapper around ``networkx.square_clustering``. - Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. name : str, optional - calculated attribute name + The calculated attribute name. Returns ------- - Graph - networkx.Graph + netx : Graph + A networkx.Graph object. Examples -------- @@ -663,10 +627,9 @@ def clustering(graph, name="cluster"): def _closeness_centrality(G, u=None, length=None, wf_improved=True, len_graph=None): r"""Compute closeness centrality for nodes. Slight adaptation of networkx `closeness_centrality` to allow normalisation for local closeness. - Adapted script used in networkx. - - Closeness centrality [1]_ of a node `u` is the reciprocal of the - average shortest path distance to `u` over all `n-1` reachable nodes. + Adapted script used in networkx. The closeness centrality [1]_ of a node `u` is + the reciprocal of the average shortest path distance to `u` over all + `n-1` reachable nodes. .. math:: @@ -694,22 +657,19 @@ def _closeness_centrality(G, u=None, length=None, wf_improved=True, len_graph=No Parameters ---------- G : graph - A NetworkX graph - + A NetworkX graph. u : node, optional - Return only the value for node u - + Return only the value for node ``u``. distance : edge attribute key, optional (default=None) - Use the specified edge attribute as the edge distance in shortest - path calculations - + Use the specified edge attribute as the edge + distance in shortest path calculations. len_graph : int - length of complete graph + The length of the complete graph. Returns ------- - nodes : dictionary - Dictionary of nodes with closeness centrality as the value. + nodes : dict + Dictionary of nodes with closeness centrality as the value. References ---------- @@ -754,13 +714,11 @@ def closeness_centrality( radius=None, distance=None, verbose=True, - **kwargs + **kwargs, ): """ Calculates the closeness centrality for nodes. - Wrapper around ``networkx.closeness_centrality``. - Closeness centrality of a node `u` is the reciprocal of the average shortest path distance to `u` over all `n-1` nodes within reachable nodes. @@ -768,34 +726,34 @@ def closeness_centrality( C(u) = \\frac{n - 1}{\\sum_{v=1}^{n-1} d(v, u)}, - where :math:`d(v, u)` is the shortest-path distance between :math:`v` and :math:`u`, - and :math:`n` is the number of nodes that can reach :math:`u`. + where :math:`d(v, u)` is the shortest-path distance between :math:`v` and + :math:`u`, and :math:`n` is the number of nodes that can reach :math:`u`. Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. name : str, optional - calculated attribute name + The calculated attribute name. weight : str (default 'mm_len') - attribute holding the weight of edge (e.g. length, angle) + The attribute holding the weight of edge (e.g. length, angle). radius: int - Include all neighbors of distance <= radius from n + Include all neighbors of distance <= radius from ``n``. distance : str, optional Use specified edge data key as distance. For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n during ego_graph generation. + measure the distance from the node ``n`` during ``ego_graph`` generation. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps - **kwargs - kwargs for ``networkx.closeness_centrality`` + If ``True``, shows progress bars in loops and indication of steps. + **kwargs : dict + Keyword arguments for ``networkx.closeness_centrality``. Returns ------- - Graph - networkx.Graph + netx : Graph + A networkx.Graph object. Examples -------- @@ -829,14 +787,12 @@ def betweenness_centrality( distance=None, normalized=False, verbose=True, - **kwargs + **kwargs, ): """ Calculates the shortest-path betweenness centrality for nodes. - Wrapper around ``networkx.betweenness_centrality`` or ``networkx.edge_betweenness_centrality``. - Betweenness centrality of a node `v` is the sum of the fraction of all-pairs shortest paths that pass through `v` @@ -849,7 +805,6 @@ def betweenness_centrality( those paths passing through some node `v` other than `s, t`. If `s = t`, :math:`\\sigma(s, t) = 1`, and if `v` in `{s, t}``, :math:`\\sigma(s, t|v) = 0`. - Betweenness centrality of an edge `e` is the sum of the fraction of all-pairs shortest paths that pass through `e` @@ -866,33 +821,34 @@ def betweenness_centrality( Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. name : str, optional - calculated attribute name + The calculated attribute name. mode : str, default 'nodes' - mode of betweenness calculation. 'node' for node-based, 'edges' for edge-based + The mode of betweenness calculation. ``'node'`` for node-based + or ``'edges'`` for edge-based. weight : str (default 'mm_len') - attribute holding the weight of edge (e.g. length, angle) + The attribute holding the weight of edge (e.g. length, angle). radius: int - Include all neighbors of distance <= radius from n + Include all neighbors of distance <= radius from ``n``. distance : str, optional Use specified edge data key as distance. For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n during ego_graph generation. + measure the distance from the node ``n`` during ``ego_graph`` generation. normalized : bool, optional - If True the betweenness values are normalized by `2/((n-1)(n-2))`, - where n is the number of nodes in subgraph. + If ``True`` the betweenness values are normalized by `2/((n-1)(n-2))`, + where ``n`` is the number of nodes in a subgraph. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps - **kwargs - kwargs for ``networkx.betweenness_centrality`` or - ``networkx.edge_betweenness_centrality`` + If ``True``, shows progress bars in loops and indication of steps. + **kwargs : dict + Keyword argument for ``networkx.betweenness_centrality`` or + ``networkx.edge_betweenness_centrality``. Returns ------- - Graph - networkx.Graph + netx : Graph + A networkx.Graph object. Examples -------- @@ -936,22 +892,18 @@ def betweenness_centrality( val = vals[v, u] netx[u][v][k][name] = val else: - raise ValueError( - "Mode {} is not supported. Use 'nodes' or 'edges'.".format(mode) - ) + raise ValueError(f"Mode {mode} is not supported. Use 'nodes' or 'edges'.") return netx def _euclidean(n, m): - """helper for straightness""" + """Helper for straightness.""" return math.sqrt((n[0] - m[0]) ** 2 + (n[1] - m[1]) ** 2) def _straightness_centrality(G, weight, normalized=True): - """ - Calculates straightness centrality. - """ + """Calculates straightness centrality.""" straightness_centrality = {} for n in G.nodes(): @@ -1001,28 +953,28 @@ def straightness_centrality( Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. weight : str (default 'mm_len') - attribute holding length of edge + The attribute holding length of edge. normalized : bool - normalize to number of nodes-1 in connected part (for local straightness - is recommended to set to normalized False) + Normalize to the number of ``nodes-1`` in the connected part + (for local straightness it is recommended to set to ``normalized=False``). name : str, optional - calculated attribute name + The calculated attribute name. radius: int - Include all neighbors of distance <= radius from n + Include all neighbors of distance <= radius from ``n``. distance : str, optional Use specified edge data key as distance. For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n during ego_graph generation. + measure the distance from the node ``n`` during ``ego_graph`` generation. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph + netx : Graph + A networkx.Graph object. Examples -------- @@ -1064,58 +1016,55 @@ def subgraph( verbose=True, ): """ - Calculates all subgraph-based characters. - - Generating subgraph might be a time consuming activity. If we want to use the same - subgraph for more characters, ``subgraph`` allows this by generating subgraph and - then analysing it using selected options. - + Calculates all subgraph-based characters. Generating subgraph might be a time + consuming activity. If we want to use the same subgraph for more characters, + ``subgraph`` allows this by generating subgraph and then analysing it using + selected options. Parameters ---------- graph : networkx.Graph - Graph representing street network. - Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx` + A Graph representing a street network. + Ideally generated from GeoDataFrame using :func:`momepy.gdf_to_nx`. radius: int - radius defining the extent of subgraph + Include all neighbors of distance <= radius from ``n``. distance : str, optional - Use specified edge data key as distance. - For example, setting ``distance=’weight’`` will use the edge ``weight`` to - measure the distance from the node n. + Use specified edge data key as distance. For example, setting + ``distance=’weight’`` will use the edge ``weight`` to + measure the distance from the node ``n``. meshedness : bool, default True - Calculate meshedness (True/False) + Calculate meshedness (``True or ``False``). cds_length : bool, default True - Calculate cul-de-sac length (True/False) + Calculate cul-de-sac length (``True or ``False``). mode : str (defualt 'sum') - if ``'sum'``, calculate total cds_length, if ``'mean'`` calculate mean - cds_length + If ``'sum'``, calculate total ``cds_length``, + if ``'mean'`` calculate mean ``cds_length``. degree : str - name of attribute of node degree (:py:func:`momepy.node_degree`) + The name of attribute of node degree (:py:func:`momepy.node_degree`). length : str, default `mm_len` - name of attribute of segment length (geographical) + The name of the attribute of segment length (geographical). mean_node_degree : bool, default True - Calculate mean node degree (True/False) + Calculate mean node degree (``True or ``False``). proportion : dict, default {3: True, 4: True, 0: True} - Calculate proportion {3: True/False, 4: True/False, 0: True/False} + Calculate proportion ``{3: True/False, 4: True/False, 0: True/False}``. cyclomatic : bool, default True - Calculate cyclomatic complexity (True/False) + Calculate cyclomatic complexity (``True or ``False``). edge_node_ratio : bool, default True - Calculate edge node ratio (True/False) + Calculate edge node ratio (``True or ``False``). gamma : bool, default True - Calculate gamma index (True/False) + Calculate gamma index (``True or ``False``). local_closeness : bool, default True - Calculate local closeness centrality (True/False) + Calculate local closeness centrality (``True or ``False``). closeness_weight : str, optional - Use the specified edge attribute as the edge distance in shortest - path calculations in closeness centrality algorithm + Use the specified edge attribute as the edge distance in shortest + path calculations in closeness centrality algorithm. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps - + If ``True``, shows progress bars in loops and indication of steps. Returns ------- - Graph - networkx.Graph + netx : Graph + A networkx.Graph object. Examples -------- @@ -1172,9 +1121,7 @@ def subgraph( def mean_nodes(G, attr): - """ - Calculates mean value of nodes attr for each edge. - """ + """Calculates mean value of nodes attr for each edge.""" for u, v, k in G.edges(keys=True): mean = (G.nodes[u][attr] + G.nodes[v][attr]) / 2 G[u][v][k][attr] = mean diff --git a/momepy/intensity.py b/momepy/intensity.py index f7d91346..e6b657d5 100644 --- a/momepy/intensity.py +++ b/momepy/intensity.py @@ -23,10 +23,8 @@ class AreaRatio: """ - Calculate covered area ratio or floor area ratio of objects. - - Either ``unique_id`` or both ``left_unique_id`` and ``right_unique_id`` - are required. + Calculate covered area ratio or floor area ratio of objects. Either ``unique_id`` + or both ``left_unique_id`` and ``right_unique_id`` are required. .. math:: \\textit{covering object area} \\over \\textit{covered object area} @@ -36,42 +34,42 @@ class AreaRatio: Parameters ---------- left : GeoDataFrame - GeoDataFrame containing objects being covered (e.g. land unit) + A GeoDataFrame containing objects being covered (e.g. land unit). right : GeoDataFrame - GeoDataFrame with covering objects (e.g. building) + A GeoDataFrame with covering objects (e.g. building). left_areas : str, list, np.array, pd.Series - the name of the left dataframe column, ``np.array``, or ``pd.Series`` where - area value is stored + The name of the left dataframe column, ``np.array``, or + ``pd.Series`` where area values are stored. right_areas : str, list, np.array, pd.Series - the name of the right dataframe column, ``np.array``, or ``pd.Series`` where - area value is stored + The name of the right dataframe column, ``np.array``, or + ``pd.Series`` where area values are stored. representing either projected or floor area. unique_id : str (default None) - name of the column with unique id shared amongst left and right gdfs. - If there is none, it could be generated by :py:func:'momepy.unique_id()'. + The name of the unique ID column shared amongst ``left`` and ``right`` gdfs. + If there is none, it can be generated by :py:func:`momepy.unique_id()`. left_unique_id : str, list, np.array, pd.Series (default None) - the name of the left dataframe column, ``np.array``, or ``pd.Series`` where - shared unique ID is stored + The name of the ``left`` dataframe column, ``np.array``, or + ``pd.Series`` where the shared unique IDs are stored. right_unique_id : str, list, np.array, pd.Series (default None) - the name of the left dataframe column, ``np.array``, or ``pd.Series`` where - shared unique ID is stored + The name of the ``right`` dataframe column, ``np.array``, or + ``pd.Series`` where the shared unique IDs are stored. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. left : GeoDataFrame - original left GeoDataFrame + The original left GeoDataFrame. right : GeoDataFrame - original right GeoDataFrame + The original right GeoDataFrame. left_areas : Series - Series containing used left areas + A Series containing the used left areas. right_areas : Series - Series containing used right areas + A Series containing the used right areas. left_unique_id : Series - Series containing used left ID + A Series containing the used left ID. right_unique_id : Series - Series containing used right ID + A Series containing used right ID. Examples -------- @@ -104,8 +102,8 @@ def __init__( else: if left_unique_id is None or right_unique_id is None: raise ValueError( - "Unique ID not correctly set. Use either network_id or both" - "left_unique_id and right_unique_id." + "Unique ID not correctly set. Use either ``network_id`` or both" + "``left_unique_id`` and ``right_unique_id``." ) self.left_unique_id = left_unique_id self.right_unique_id = right_unique_id @@ -134,49 +132,46 @@ def __init__( class Count: """ - Calculate the number of elements within an aggregated structure. - - Aggregated structure can be typically block, street segment or street node (their - snapepd objects). Right gdf has to have - unique id of aggregated structure assigned before hand (e.g. using - :py:func:`momepy.get_network_id`). - If ``weighted=True``, number of elements will be divided by the area of - length (based on geometry type) of aggregated - element, to return relative value. + Calculate the number of elements within an aggregated structure. Aggregated + structures can typically be blocks, street segments, or street nodes (their + snapepd objects). The right gdf has to have a unique ID of aggregated structures + assigned before hand (e.g. using :py:func:`momepy.get_network_id`). + If ``weighted=True``, the number of elements will be divided by the area of + length (based on geometry type) of aggregated elements, to return relative value. .. math:: \\sum_{i \\in aggr} (n_i);\\space \\frac{\\sum_{i \\in aggr} (n_i)}{area_{aggr}} Adapted from :cite:`hermosilla2012` and :cite:`feliciotti2018`. - Parameters ---------- left : GeoDataFrame - GeoDataFrame containing aggregation to analyse + A GeoDataFrame containing aggregation to analyse. right : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. left_id : str - name of the column where unique ID in left gdf is stored + The name of the column where unique ID in the ``left`` gdf is stored. right_id : str - name of the column where unique ID of aggregation in right gdf is stored + The name of the column where unique ID of + aggregation in the ``right`` gdf is stored. weighted : bool (default False) - if ``True``, count will be divided by the area or length + If ``True``, count will be divided by the area or length. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. left : GeoDataFrame - original left GeoDataFrame + The original ``left`` GeoDataFrame. right : GeoDataFrame - original right GeoDataFrame + The original ``right`` GeoDataFrame. left_id : Series - Series containing used left ID + A Series containing used ``left`` ID. right_id : Series - Series containing used right ID + A Series containing used ``right`` ID. weighted : bool - used weighted value + ``True`` if the weighted value was used. Examples -------- @@ -216,26 +211,25 @@ class Courtyards: Adapted from :cite:`schirmer2015`. - Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. spatial_weights : libpysal.weights, optional - spatial weights matrix - If None, Queen contiguity matrix will be calculated - based on objects. It is to denote adjacent buildings - (note: based on integer index). + A spatial weights matrix. If None, Queen contiguity matrix + will be calculated based on objects. It is to denote adjacent + buildings and is based on integer index. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. Examples -------- @@ -283,10 +277,8 @@ def __init__(self, gdf, spatial_weights=None, verbose=True): class BlocksCount: """ - Calculates the weighted number of blocks - - Number of blocks within neighbours defined in ``spatial_weights`` divided by - the area you have covered by the neighbours. + Calculates the weighted number of blocks. The number of blocks within neighbours + defined in ``spatial_weights`` divided by the area covered by the neighbours. .. math:: @@ -295,33 +287,33 @@ class BlocksCount: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing morphological tessellation + A GeoDataFrame containing morphological tessellation. block_id : str, list, np.array, pd.Series - the name of the objects dataframe column, ``np.array``, or ``pd.Series`` - where block ID is stored + The name of the objects dataframe column, ``np.array``, + or ``pd.Series`` where block IDs are stored. spatial_weights : libpysal.weights - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index + The name of the column with a unique ID used as the ``spatial_weights`` index. weigted : bool, default True - return value weighted by the analysed area (``True``) or pure count (``False``) + Return value weighted by the analysed area (``True``) or pure count (``False``). verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. block_id : Series - Series containing used block ID + A Series containing used block ID. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix id : Series - Series containing used unique ID + A Series containing used unique ID. weighted : bool - used weighted value + ``True`` if the weighted value was used. Examples -------- @@ -377,65 +369,58 @@ def __init__( class Reached: """ - Calculates the number of objects reached within neighbours on street network - - Number of elements within neighbourhood defined in ``spatial_weights``. If + Calculates the number of objects reached within neighbours on a street network. + The number of elements within neighbourhood defined in ``spatial_weights``. If ``spatial_weights`` are ``None``, it will assume topological distance ``0`` - (element itself). - If ``mode='area'``, returns sum of areas of reached elements. Requires unique_id - of network assigned beforehand (e.g. using :py:func:`momepy.get_network_id`). - - .. math:: - + (element itself). If ``mode='area'``, returns sum of areas of reached elements. + Requires a ``unique_id`` of network assigned beforehand + (e.g. using :py:func:`momepy.get_network_id`). Parameters ---------- left : GeoDataFrame - GeoDataFrame containing streets (either segments or nodes) + A GeoDataFrame containing streets (either segments or nodes). right : GeoDataFrame - GeoDataFrame containing elements to be counted + A GeoDataFrame containing elements to be counted. left_id : str, list, np.array, pd.Series (default None) - the name of the left dataframe column, ``np.array``, or ``pd.Series`` where is - stored ID of streets (segments or nodes). + The name of the ``left`` dataframe column, ``np.array``, or ``pd.Series`` + where the IDs of streets (segments or nodes) are stored. right_id : str, list, np.array, pd.Series (default None) - the name of the right dataframe column, ``np.array``, or ``pd.Series`` where is - stored ID of streets (segments or nodes). + The name of the ``right`` dataframe column, ``np.array``, or ``pd.Series`` + where the IDs of streets (segments or nodes) are stored. spatial_weights : libpysal.weights (default None) - spatial weights matrix + A spatial weights matrix. mode : str (default 'count') - mode of calculation. If ``'count'`` function will return - the count of reached elements. - If ``'sum'``, it will return sum of ``'values'``. If ``'mean'`` it will - return mean value - of ``'values'``. If ``'std'`` it will return standard deviation - of ``'values'``. If ``'values'`` not set it will use of areas - of reached elements. + Tode of calculation. If ``'count'`` function will return the count of reached + elements. If ``'sum'``, it will return sum of ``'values'``. If ``'mean'`` it + will return mean value of ``'values'``. If ``'std'`` it will return standard + deviation of ``'values'``. If ``'values'`` not set it will use of areas of + reached elements. values : str (default None) - the name of the objects dataframe column with values used for calculations + The name of the objects dataframe column with values used for calculations. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. left : GeoDataFrame - original left GeoDataFrame + The original left GeoDataFrame. right : GeoDataFrame - original right GeoDataFrame + The original right GeoDataFrame. left_id : Series - Series containing used left ID + A Series containing used left ID. right_id : Series - Series containing used right ID + A Series containing used right ID. mode : str - mode of calculation + The mode of calculation. sw : libpysal.weights - spatial weights matrix (if set) + The spatial weights matrix (if set). Examples -------- >>> streets_df['reached'] = mm.Reached(streets_df, buildings_df, 'uID').series - """ # TODO: allow all modes @@ -509,58 +494,56 @@ def __init__( class NodeDensity: """ - Calculate the density of nodes neighbours on street network - defined in ``spatial_weights``. - - Calculated as number of neighbouring nodes / cummulative length - of street network within neighbours. - node_start and node_end is standard output of :py:func:`momepy.nx_to_gdf` - and is compulsory. + Calculate the density of nodes neighbours on street network defined in + ``spatial_weights``. Calculated as the number of neighbouring + nodes / cummulative length of street network within neighbours. + ``node_start`` and ``node_end`` is standard output of + :py:func:`momepy.nx_to_gdf` and is compulsory. Adapted from :cite:`dibble2017`. Parameters ---------- left : GeoDataFrame - GeoDataFrame containing nodes of street network + A GeoDataFrame containing nodes of street network. right : GeoDataFrame - GeoDataFrame containing edges of street network + A GeoDataFrame containing edges of street network. spatial_weights : libpysal.weights - spatial weights matrix capturing relationship between nodes + A spatial weights matrix capturing relationship between nodes. weighted : bool (default False) - if True density will take into account node degree as ``k-1`` + If ``True``, density will take into account node degree as ``k-1``. node_degree : str (optional) - name of the column of left gdf containing node degree. Used if ``weighted=True`` + The name of the column of ``left`` containing node degree. + Used if ``weighted=True``. node_start : str (default 'node_start') - name of the column of right gdf containing id of starting node + The name of the column of ``right`` containing the ID of the starting nodes. node_end : str (default 'node_end') - name of the column of right gdf containing id of ending node + The name of the column of ``right`` containing the ID of the ending node. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. left : GeoDataFrame - original left GeoDataFrame + The original left GeoDataFrame. right : GeoDataFrame - original right GeoDataFrame + The original right GeoDataFrame. node_start : Series - Series containing used ids of starting node + A Series containing used ids of starting node. node_end : Series - Series containing used ids of ending node + A Series containing used ids of ending node. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. weighted : bool - used weighted value + The used weighted value. node_degree : Series - Series containing used node degree values + A Series containing used node degree values. Examples -------- >>> nodes['density'] = mm.NodeDensity(nodes, edges, sw).series - """ def __init__( @@ -613,7 +596,7 @@ def __init__( class Density: """ - Calculate the gross density + Calculate the gross density. .. math:: \\frac{\\sum \\text {values}}{\\sum \\text {areas}} @@ -623,35 +606,34 @@ class Density: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. values : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored character value. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where character values are stored. spatial_weights : libpysal.weight - spatial weights matrix + A spatial weights matrix. unique_id : str - name of the column with unique id used as ``spatial_weights`` index + The name of the column with unique ID used as ``spatial_weights`` index areas : str, list, np.array, pd.Series (optional) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If None, - gdf.geometry.area will be used. + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where area values are stored. If ``None``, gdf.geometry.area will be used. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. values : Series - Series containing used values + A Series containing used values. sw : libpysal.weights - spatial weights matrix + The spatial weights matrix. id : Series - Series containing used unique ID + A Series containing used unique ID. areas : Series - Series containing used area values + A Series containing used area values. Examples -------- diff --git a/momepy/shape.py b/momepy/shape.py index 90283136..9864a7a7 100644 --- a/momepy/shape.py +++ b/momepy/shape.py @@ -33,7 +33,7 @@ def _form_factor(height, geometry, area=None, perimeter=None, volume=None): - """helper for FormFactor""" + """Helper for FormFactor.""" if area is None: area = geometry.area if perimeter is None: @@ -51,7 +51,7 @@ def _form_factor(height, geometry, area=None, perimeter=None, volume=None): class FormFactor: """ - Calculates form factor of each object in given GeoDataFrame. + Calculates the form factor of each object in a given GeoDataFrame. .. math:: surface \\over {volume^{2 \\over 3}} @@ -66,29 +66,28 @@ class FormFactor: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. volumes : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored volume value. - (To calculate volume you can use :py:func:`momepy.volume`) + The name of the dataframe column, ``np.array``, or ``pd.Series`` where volume + values are stored. To calculate volume you can use :py:func:`momepy.volume`. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area values stored. If set to ``None``, this function will calculate areas during the process without saving them separately. heights : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where height + The name of the dataframe column, ``np.array``, or ``pd.Series`` where height values are stored. Note that it cannot be ``None``. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. volumes : Series - Series containing used volume values + A Series containing used volume values. areas : Series - Series containing used area values + A Series containing used area values. Examples -------- @@ -100,7 +99,6 @@ class FormFactor: >>> buildings_df['formfactor'] = momepy.FormFactor(buildings_df, volume).series >>> buildings_df.formfactor[0] 1.9385988170288635 - """ def __init__(self, gdf, volumes, areas=None, heights=None): @@ -148,26 +146,26 @@ class FractalDimension: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area values stored. If set to ``None``, this function will calculate areas during the process without saving them separately. perimeters : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored perimeter value. If set to ``None``, function will calculate perimeters - during the process without saving them separately. + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + perimeter values stored. If set to ``None``, this function will calculate + perimeters during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. perimeters : Series - Series containing used perimeter values + A Series containing used perimeter values. areas : Series - Series containing used area values + A Series containing used area values. Examples -------- @@ -204,7 +202,7 @@ def __init__(self, gdf, areas=None, perimeters=None): class VolumeFacadeRatio: """ - Calculates volume/facade ratio of each object in given GeoDataFrame. + Calculates the volume/facade ratio of each object in a given GeoDataFrame. .. math:: volume \\over perimeter * height @@ -214,28 +212,27 @@ class VolumeFacadeRatio: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. heights : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored height value + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where height values are stored. volumes : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored volume value + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where volume values are stored. perimeters : , list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored perimeter value - + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where perimeter values are stored. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. perimeters : Series - Series containing used perimeter values + A Series containing used perimeter values. volumes : Series - Series containing used volume values + A Series containing used volume values. Examples -------- @@ -269,6 +266,7 @@ def __init__(self, gdf, heights, volumes=None, perimeters=None): self.series = gdf[volumes] / (gdf[perimeters] * gdf[heights]) +####################################################################################### # Smallest enclosing circle - Library (Python) # Copyright (c) 2017 Project Nayuki @@ -315,8 +313,8 @@ def _make_circle(points): return c -# One boundary point known def _make_circle_one_point(points, p): + """One boundary point known.""" c = (p[0], p[1], 0.0) for (i, q) in enumerate(points): if not _is_in_circle(c, q): @@ -327,8 +325,8 @@ def _make_circle_one_point(points, p): return c -# Two boundary points known def _make_circle_two_points(points, p, q): + """Two boundary points known.""" circ = _make_diameter(p, q) left = None right = None @@ -371,7 +369,7 @@ def _make_circle_two_points(points, p, q): def _make_circumcircle(p0, p1, p2): - # Mathematical algorithm from Wikipedia: Circumscribed circle + """Mathematical algorithm from Wikipedia: Circumscribed circle.""" ax, ay = p0 bx, by = p1 cx, cy = p2 @@ -428,16 +426,20 @@ def _is_in_circle(c, p): ) -# Returns twice the signed area of the triangle defined by (x0, y0), (x1, y1), (x2, y2). def _cross_product(x0, y0, x1, y1, x2, y2): + """ + Returns twice the signed area of the + triangle defined by (x0, y0), (x1, y1), (x2, y2). + """ return (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0) # end of Nayuiki script to define the smallest enclosing circle +####################################################################################### -# calculate the area of circumcircle def _circle_area(points): + """calculate the area of circumcircle.""" if len(points[0]) == 3: points = [x[:2] for x in points] circ = _make_circle(points) @@ -453,7 +455,7 @@ def _circle_radius(points): class CircularCompactness: """ - Calculates compactness index of each object in given GeoDataFrame. + Calculates the compactness index of each object in a given GeoDataFrame. .. math:: area \\over \\textit{area of enclosing circle} @@ -463,20 +465,20 @@ class CircularCompactness: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area values stored. If set to ``None``, this function will calculate areas during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. areas : Series - Series containing used area values + A Series containing used area values. Examples -------- @@ -502,7 +504,7 @@ def __init__(self, gdf, areas=None): class SquareCompactness: """ - Calculates compactness index of each object in given GeoDataFrame. + Calculates the compactness index of each object in a given GeoDataFrame. .. math:: \\begin{equation*} @@ -514,33 +516,32 @@ class SquareCompactness: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas - during the process without saving them separately. - perimeters : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored perimeter value. If set to ``None``, function will calculate perimeters + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area values stored. If set to ``None``, this function will calculate areas during the process without saving them separately. + areas : str, list, np.array, pd.Series (default None) + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + perimeter values stored. If set to ``None``, this function will calculate + perimeters during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. areas : Series - Series containing used area values + A Series containing used area values. perimeters : Series - Series containing used perimeter values + A Series containing used perimeter values. Examples -------- >>> buildings_df['squ_comp'] = momepy.SquareCompactness(buildings_df).series >>> buildings_df['squ_comp'][0] 0.6193872538650996 - """ def __init__(self, gdf, areas=None, perimeters=None): @@ -567,7 +568,7 @@ def __init__(self, gdf, areas=None, perimeters=None): class Convexity: """ - Calculates Convexity index of each object in given GeoDataFrame. + Calculates the Convexity index of each object in a given GeoDataFrame. .. math:: area \\over \\textit{convex hull area} @@ -577,20 +578,20 @@ class Convexity: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area values stored. If set to ``None``, this function will calculate areas during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. areas : Series - Series containing used area values + A Series containing used area values. Examples -------- @@ -615,7 +616,7 @@ def __init__(self, gdf, areas=None): class CourtyardIndex: """ - Calculates courtyard index of each object in given GeoDataFrame. + Calculates the courtyard index of each object in a given GeoDataFrame. .. math:: \\textit{area of courtyards} \\over \\textit{total area} @@ -625,26 +626,26 @@ class CourtyardIndex: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. courtyard_areas : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value - (To calculate volume you can use :py:class:`momepy.CourtyardArea`) + the name of the dataframe column, ``np.array``, or ``pd.Series`` where + courtyard area values are stored. To calculate volume you can use + :py:class:`momepy.CourtyardArea`. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area values stored. If set to ``None``, this function will calculate areas during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. courtyard_areas : Series - Series containing used courtyard areas values + A Series containing used courtyard areas values. areas : Series - Series containing used area values + A Series containing used area values. Examples -------- @@ -674,7 +675,7 @@ def __init__(self, gdf, courtyard_areas, areas=None): class Rectangularity: """ - Calculates rectangularity of each object in given GeoDataFrame. + Calculates the rectangularity of each object in a given GeoDataFrame. .. math:: {area \\over \\textit{minimum bounding rotated rectangle area}} @@ -684,20 +685,20 @@ class Rectangularity: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area values stored. If set to ``None``, this function will calculate areas during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. areas : Series - Series containing used area values + A Series containing used area values. Examples -------- @@ -725,7 +726,7 @@ def __init__(self, gdf, areas=None): class ShapeIndex: """ - Calculates shape index of each object in given GeoDataFrame. + Calculates the shape index of each object in a given GeoDataFrame. .. math:: {\\sqrt{{area} \\over {\\pi}}} \\over {0.5 * \\textit{longest axis}} @@ -733,25 +734,25 @@ class ShapeIndex: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. longest_axis : str, list, np.array, pd.Series - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored longest axis value + The name of the dataframe column, ``np.array``, or ``pd.Series`` + where is longest axis values are stored. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area values stored. If set to ``None``, this function will calculate areas during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. longest_axis : Series - Series containing used longest axis values + A Series containing used longest axis values. areas : Series - Series containing used area values + A Series containing used area values. Examples -------- @@ -784,10 +785,8 @@ def __init__(self, gdf, longest_axis, areas=None): class Corners: """ - Calculates number of corners of each object in given GeoDataFrame. - - Uses only external shape (``shapely.geometry.exterior``), courtyards are not - included. + Calculates the number of corners of each object in a given GeoDataFrame. Uses only + external shape (``shapely.geometry.exterior``), courtyards are not included. .. math:: \\sum corner @@ -795,17 +794,16 @@ class Corners: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame - + The original GeoDataFrame. Examples -------- @@ -813,8 +811,6 @@ class Corners: 100%|██████████| 144/144 [00:00<00:00, 1042.15it/s] >>> buildings_df.corners[0] 24 - - """ def __init__(self, gdf, verbose=True): @@ -907,10 +903,9 @@ def _true_angle(a, b, c): class Squareness: """ - Calculates squareness of each object in given GeoDataFrame. - - Uses only external shape (``shapely.geometry.exterior``), courtyards are not - included. + Calculates the squareness of each object in a given GeoDataFrame. Uses only + external shape (``shapely.geometry.exterior``), courtyards are not included. + Returns ``np.nan`` for MultiPolygons. .. math:: \\mu=\\frac{\\sum_{i=1}^{N} d_{i}}{N} @@ -919,21 +914,19 @@ class Squareness: Adapted from :cite:`dibble2017`. - Returns ``np.nan`` for MultiPolygons. - Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. Examples -------- @@ -1004,7 +997,7 @@ def _angle(a, b, c): class EquivalentRectangularIndex: """ - Calculates equivalent rectangular index of each object in given GeoDataFrame. + Calculates the equivalent rectangular index of each object in a given GeoDataFrame. .. math:: \\sqrt{{area} \\over \\textit{area of bounding rectangle}} * @@ -1015,26 +1008,26 @@ class EquivalentRectangularIndex: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area values are stored. If set to ``None``, this function will calculate areas during the process without saving them separately. perimeters : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored perimeter value. If set to ``None``, function will calculate perimeters - during the process without saving them separately. + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + perimeter values are stored. If set to ``None``, the function will calculate + perimeters during the process without saving them separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. areas : Series - Series containing used area values + A Series containing used area values. perimeters : Series - Series containing used perimeter values + A Series containing used perimeter values. Examples -------- @@ -1073,8 +1066,8 @@ def __init__(self, gdf, areas=None, perimeters=None): class Elongation: """ - Calculates elongation of object seen as elongation of - its minimum bounding rectangle. + Calculates the elongation of each object seen as + elongation of its minimum bounding rectangle. .. math:: {{p - \\sqrt{p^2 - 16a}} \\over {4}} \\over @@ -1087,14 +1080,14 @@ class Elongation: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. Attributes ---------- e : Series - Series containing resulting values + A Series containing resulting values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. Examples -------- @@ -1131,7 +1124,8 @@ def __init__(self, gdf): class CentroidCorners: """ - Calculates mean distance centroid - corners and st. deviation. + Calculates the mean distance centroid - corners and standard deviation. + Returns ``np.nan`` for MultiPolygons. .. math:: \\overline{x}=\\frac{1}{n}\\left(\\sum_{i=1}^{n} dist_{i}\\right); @@ -1139,23 +1133,21 @@ class CentroidCorners: Adapted from :cite:`schirmer2015` and :cite:`cimburova2017`. - Returns ``np.nan`` for MultiPolygons. - Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- mean : Series - Series containing mean distance values. + A Series containing mean distance values. std : Series - Series containing standard deviation values. + A Series containing standard deviation values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. Examples -------- @@ -1248,28 +1240,29 @@ def true_angle(a, b, c): class Linearity: """ - Calculates linearity of each LineString object in given GeoDataFrame. + Calculates the linearity of each LineString object in a given GeoDataFrame. + MultiLineString returns ``np.nan``. .. math:: \\frac{l_{euclidean}}{l_{segment}} - where `l` is the length of the LineString. MultiLineString returns ``np.nan``. + where `l` is the length of the LineString. Adapted from :cite:`araldi2019`. Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. verbose : bool (default True) - if True, shows progress bars in loops and indication of steps + If ``True``, shows progress bars in loops and indication of steps. Attributes ---------- series : Series - Series containing mean distance values. + A Series containing mean distance values. gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. Examples -------- @@ -1294,8 +1287,7 @@ def _dist(self, a, b): class CompactnessWeightedAxis: """ - Calculates compactness-weighted axis of each object in given GeoDataFrame. - + Calculates the compactness-weighted axis of each object in a given GeoDataFrame. Initially designed for blocks. .. math:: @@ -1305,33 +1297,33 @@ class CompactnessWeightedAxis: Parameters ---------- gdf : GeoDataFrame - GeoDataFrame containing objects + A GeoDataFrame containing objects. areas : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored area value. If set to ``None``, function will calculate areas + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + area value are stored . If set to ``None``, this function will calculate areas during the process without saving them separately. perimeters : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored perimeter value. If set to ``None``, function will calculate perimeters - during the process without saving them separately. + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + perimeter values are stored. If set to ``None``, this function will calculate + perimeters during the process without saving them separately. longest_axis : str, list, np.array, pd.Series (default None) - the name of the dataframe column, ``np.array``, or ``pd.Series`` where is - stored longest axis length value. If set to ``None``, function will calculate it - during the process without saving them separately. + The name of the dataframe column, ``np.array``, or ``pd.Series`` where + longest axis length values are stored. If set to ``None``, this function will + calculate longest axis lengths during the process without saving them + separately. Attributes ---------- series : Series - Series containing resulting values + A Series containing resulting values gdf : GeoDataFrame - original GeoDataFrame + The original GeoDataFrame. areas : Series - Series containing used area values + A Series containing used area values. longest_axis : Series - Series containing used area values + A Series containing used area values. perimeters : Series - Series containing used area values - + A Series containing used area values. Examples -------- diff --git a/momepy/utils.py b/momepy/utils.py index 523dd744..9c8d6467 100644 --- a/momepy/utils.py +++ b/momepy/utils.py @@ -21,17 +21,17 @@ def unique_id(objects): """ - Add an attribute with unique ID to each row of GeoDataFrame. + Add an attribute with a unique ID to each row of a GeoDataFrame. Parameters ---------- objects : GeoDataFrame - GeoDataFrame containing objects to analyse + A GeoDataFrame containing objects to analyse. Returns ------- - Series - Series containing resulting values. + series : Series + A Series containing resulting values. """ series = range(len(objects)) @@ -40,8 +40,7 @@ def unique_id(objects): def _angle(a, b, c): """ - Measure angle between a-b, b-c. In degrees. - Helper for gdf_to_nx. + Measure the angle between a-b, b-c (in degrees). Helper for ``gdf_to_nx``. Adapted from cityseer's implementation. """ a1 = math.degrees(math.atan2(b[1] - a[1], b[0] - a[0])) @@ -50,7 +49,7 @@ def _angle(a, b, c): def _generate_primal(G, gdf_network, fields, multigraph, oneway_column=None): - """Generate primal graph. Helper for gdf_to_nx.""" + """Generate a primal graph. Helper for ``gdf_to_nx``.""" G.graph["approach"] = "primal" msg = ( @@ -93,7 +92,7 @@ def _generate_primal(G, gdf_network, fields, multigraph, oneway_column=None): def _generate_dual(G, gdf_network, fields, angles, multigraph, angle): - """Generate dual graph Helper for gdf_to_nx.""" + """Generate a dual graph. Helper for ``gdf_to_nx``.""" G.graph["approach"] = "dual" key = 0 @@ -151,51 +150,47 @@ def gdf_to_nx( oneway_column=None, ): """ - Convert LineString GeoDataFrame to networkx.MultiGraph or other Graph as per - specification. - - Preserves columns as edge or node attributes (depending on the ``approach``). - Index is not preserved. + Convert a LineString GeoDataFrame to a ``networkx.MultiGraph`` or other + Graph as per specification. Columns are preserved as edge or node + attributes (depending on the ``approach``). Index is not preserved. See the User Guide page :doc:`../../user_guide/graph/convert` for details. Parameters ---------- gdf_network : GeoDataFrame - GeoDataFrame containing objects to convert + A GeoDataFrame containing objects to convert. approach : str, default 'primal' - Allowed options are ``'primal'`` or ``'dual'``. Primal graph represents - endpoints as nodes and LineStrings as edges, dual graph represents + Allowed options are ``'primal'`` or ``'dual'``. Primal graphs represent + endpoints as nodes and LineStrings as edges. Dual graphs represent LineStrings as nodes and their topological relation as edges. In such a case, it can encode an angle between LineStrings as an edge attribute. length : str, default 'mm_len' - name of attribute of segment length (geographical) which will be saved to graph + The attribute name of segment length (geographical) + which will be saved to the graph. multigraph : bool, default True - create ``MultiGraph`` of ``Graph`` (potentially directed). ``MutliGraph`` - allows multiple - edges between any pair of nodes, which is a common case in street networks. + Create a ``MultiGraph`` of ``Graph`` (potentially directed). + ``MutliGraph`` allows multiple edges between any pair of nodes, + which is a common case in street networks. directed : bool, default False - create directed graph (``DiGraph`` or ``MultiDiGraph``). Directionality follows - the order of LineString coordinates. + Create a directed graph (``DiGraph`` or ``MultiDiGraph``). + Directionality follows the order of LineString coordinates. angles : bool, default True - capture angles between LineStrings as an attribute of a dual graph. Ignored if - ``approach="primal"``. + Capture the angles between LineStrings as an attribute of a dual graph. + Ignored if ``approach='primal'``. angle : str, default 'angle' - name of attribute of angle between LineStrings which will be saved to graph. - Ignored if ``approach="primal"``. + The attribute name of the angle between LineStrings which will + be saved to the graph. Ignored if ``approach='primal'``. oneway_column : str, default None - create an additional edge for each LineString which allows bidirectional + Create an additional edge for each LineString which allows bidirectional path traversal by specifying the boolean column in the GeoDataFrame. Note, that the reverse conversion ``nx_to_gdf(gdf_to_nx(gdf, directed=True, oneway_column="oneway"))`` will contain additional duplicated geometries. Returns ------- - networkx.Graph, - networkx.MultiGraph, - networkx.DiGraph, - networkx.MultiDiGraph - Graph as per specification + net : networkx.Graph, networkx.MultiGraph, networkx.DiGraph, networkx.MultiDiGraph + Graph as per specification. See also -------- @@ -237,7 +232,6 @@ def gdf_to_nx( >>> G_dual - """ gdf_network = gdf_network.copy() if "key" in gdf_network.columns: @@ -281,7 +275,7 @@ def gdf_to_nx( def _points_to_gdf(net): - """Generate point gdf from nodes. Helper for nx_to_gdf.""" + """Generate a point gdf from nodes. Helper for ``nx_to_gdf``.""" node_xy, node_data = zip(*net.nodes(data=True)) if isinstance(node_xy[0], int) and "x" in node_data[0].keys(): geometry = [Point(data["x"], data["y"]) for data in node_data] # osmnx graph @@ -294,7 +288,7 @@ def _points_to_gdf(net): def _lines_to_gdf(net, points, nodeID): - """Generate linestring gdf from edges. Helper for nx_to_gdf.""" + """Generate a linestring gdf from edges. Helper for ``nx_to_gdf``.""" starts, ends, edge_data = zip(*net.edges(data=True)) gdf_edges = gpd.GeoDataFrame(list(edge_data)) @@ -315,7 +309,7 @@ def _lines_to_gdf(net, points, nodeID): def _primal_to_gdf(net, points, lines, spatial_weights, nodeID): - """Generate gdf(s) from primal network. Helper for nx_to_gdf.""" + """Generate gdf(s) from a primal network. Helper for ``nx_to_gdf``.""" if points is True: gdf_nodes = _points_to_gdf(net) @@ -338,7 +332,7 @@ def _primal_to_gdf(net, points, lines, spatial_weights, nodeID): def _dual_to_gdf(net): - """Generate linestring gdf from dual network. Helper for nx_to_gdf.""" + """Generate a linestring gdf from a dual network. Helper for ``nx_to_gdf``.""" starts, edge_data = zip(*net.nodes(data=True)) gdf_edges = gpd.GeoDataFrame(list(edge_data)) gdf_edges.crs = net.graph["crs"] @@ -347,30 +341,31 @@ def _dual_to_gdf(net): def nx_to_gdf(net, points=True, lines=True, spatial_weights=False, nodeID="nodeID"): """ - Convert ``networkx.Graph`` to LineString GeoDataFrame and Point GeoDataFrame. + Convert a ``networkx.Graph`` to a LineString GeoDataFrame and Point GeoDataFrame. - Automatically detects an ``approach`` of the graph and assignes edges and nodes to - relevant geometry type. + Automatically detects an ``approach`` of the graph and assigns + edges and nodes to relevant geometry type. See the User Guide page :doc:`../../user_guide/graph/convert` for details. Parameters ---------- net : networkx.Graph - ``networkx.Graph`` - points : bool - export point-based gdf representing intersections - lines : bool - export line-based gdf representing streets - spatial_weights : bool - export libpysal spatial weights for nodes (only for primal graphs) + A ``networkx.Graph`` object. + points : bool (default is ``True``) + Export point-based gdf representing intersections. + lines : bool (default is ``True``) + Export line-based gdf representing streets. + spatial_weights : bool (default is ``False``) + Set to ``True`` to export a libpysal spatial weights + for nodes (only for primal graphs). nodeID : str - name of node ID column to be generated + The name of the node ID column to be generated. Returns ------- GeoDataFrame - Selected gdf or tuple of both gdfs or tuple of gdfs and weights + The Selected gdf or tuple of both gdfs or tuple of gdfs and weights. See also -------- @@ -386,7 +381,7 @@ def nx_to_gdf(net, points=True, lines=True, spatial_weights=False, nodeID="nodeI 1 LINESTRING (1603268.502 6464060.781, 1603296.8... >>> G = momepy.gdf_to_nx(df) - Converting primal Graph to points as intersections and lines as street segments: + Converting the primal Graph to points as intersections and lines as street segments: >>> points, lines = momepy.nx_to_gdf(G) >>> points.head(2) @@ -398,13 +393,13 @@ def nx_to_gdf(net, points=True, lines=True, spatial_weights=False, nodeID="nodeI 0 LINESTRING (1603585.640... 264.103950 1 2 1 LINESTRING (1603561.740... 70.020202 1 9 - Storing relationship between points/nodes as libpysal W object: + Storing the relationship between points/nodes as a libpysal W object: >>> points, lines, W = momepy.nx_to_gdf(G, spatial_weights=True) >>> W - Converting dual Graph to lines. Dual Graph does not export edges to GDF: + Converting the dual Graph to lines. The dual Graph does not export edges to GDF: >>> G = momepy.gdf_to_nx(df, approach="dual") >>> lines = momepy.nx_to_gdf(G) @@ -441,19 +436,21 @@ def nx_to_gdf(net, points=True, lines=True, spatial_weights=False, nodeID="nodeI def limit_range(vals, rng): """ - Extract values within selected range + Extract values within selected range. Parameters ---------- - vals : array + vals : numpy.array + Values over which to extract a range. + rng : tuple, list, optional (default None) + A two-element sequence containing floats between 0 and 100 (inclusive) + that are the percentiles over which to compute the range. + The order of the elements is not important. - rng : Two-element sequence containing floats in range of [0,100], optional - Percentiles over which to compute the range. Each must be - between 0 and 100, inclusive. The order of the elements is not important. Returns ------- - array - limited array + vals : numpy.array + The limited array. """ vals = np.asarray(vals) diff --git a/momepy/weights.py b/momepy/weights.py index c8950982..5551ea24 100644 --- a/momepy/weights.py +++ b/momepy/weights.py @@ -12,32 +12,32 @@ class DistanceBand: On demand distance-based spatial weights-like class. Mimic the behavior of ``libpysal.weights.DistanceBand`` but do not compute all - neighbors at once but only on demand. Only ``DistanceBand.neighbors[key]`` is - implemented. Once user asks for ``DistanceBand.neighbors[key]``, neighbors for - specified key will be computed using rtree. The algorithm is significantly - slower than ``libpysal.weights.DistanceBand`` but allows for large number of + neighbors at once; only on demand. Only ``DistanceBand.neighbors[key]`` is + implemented. Once a user asks for ``DistanceBand.neighbors[key]``, neighbors for + specified key will be computed using ``rtree``. The algorithm is significantly + slower than ``libpysal.weights.DistanceBand`` but allows for a large number of neighbors which may cause memory issues in libpysal. Use ``libpysal.weights.DistanceBand`` if possible. ``momepy.weights.DistanceBand`` - only when necessary. ``DistanceBand.neighbors[key]`` should yield same results as - :class:`momepy.DistanceBand`. + only when necessary. ``DistanceBand.neighbors[key]`` should yield the same results + as :class:`momepy.DistanceBand`. Parameters ---------- gdf : GeoDataFrame or GeoSeries - GeoDataFrame containing objects to be used + The GeoDataFrame containing objects to be used. threshold : float - distance band to be used as buffer + The distance band to be used as buffer. centroid : bool (default True) - use centroid of geometry (as in ``libpysal.weights.DistanceBand``). - If ``False``, works with the geometry as it is. + Use the centroid of geometries (as in ``libpysal.weights.DistanceBand``). + If ``False``, this works with the geometry as it is. ids : str - column to be used as geometry ids. If not set, integer position is used. + The column to be used as geometry IDs. If not set, integer position is used. Attributes ---------- neighbors[key] : list - list of ids of neighboring features + A list of IDs of neighboring features. """ @@ -56,9 +56,7 @@ def fetch_items(self, key): class _Neighbors(dict, DistanceBand): - """ - Helper class for DistanceBand. - """ + """Helper class for DistanceBand.""" def __init__(self, geoms, buffer, ids): self.geoms = geoms @@ -85,32 +83,30 @@ def keys(self): def sw_high(k, gdf=None, weights=None, ids=None, contiguity="queen", silent=True): """ - Generate spatial weights based on Queen or Rook contiguity of order k. - - Adjacent are all features within <= k steps. Pass either ``gdf`` or ``weights``. - If both are passed, ``weights`` is used. - If ``weights`` are passed, ``contiguity`` is - ignored and high order spatial weights based on ``weights`` are computed. + Generate spatial weights based on Queen or Rook contiguity of order ``k``. + All features within <= ``k`` steps are adjacent. Pass in either ``gdf`` or + ``weights``. If both are passed, ``weights`` is used. If ``weights`` are + passed, ``contiguity`` is ignored and high order spatial weights based on + ``weights`` are computed. Parameters ---------- k : int - order of contiguity + The order of contiguity. gdf : GeoDataFrame - GeoDataFrame containing objects to analyse. Index has to be - consecutive range ``0:x``. - Otherwise, spatial weights will not match objects. + A GeoDataFrame containing objects to analyse. Index has to be a consecutive + range ``0:x``. Otherwise, spatial weights will not match objects. weights : libpysal.weights - libpysal.weights of order 1 + A libpysal.weights of order 1. contiguity : str (default 'queen') - type of contiguity weights. Can be ``'queen'`` or ``'rook'``. + The type of contiguity weights. Can be ``'queen'`` or ``'rook'``. silent : bool (default True) - silence libpysal islands warnings + Silence libpysal islands warnings (``True``). Returns ------- libpysal.weights - libpysal.weights object + The libpysal.weights object. Examples --------