def calculate_green_spaces(division_dir, green_spaces_dir): division_path = find_shp_path(division_dir) if type(green_spaces_dir) != list: green_spaces_dir = [green_spaces_dir] green_spaces_paths = [find_shp_path(i) for i in green_spaces_dir] # create spatial index for green spaces green_spaces = [] for green_spaces_path in green_spaces_paths: green_spaces.extend(list(iter_shp_as_shapely(green_spaces_path))) green_spaces_idx = create_spatial_index(green_spaces) divisions = list(iter_shp_as_shapely(division_path)) total_divisions = len(divisions) green_relevance = {} for index, (id_division, division_shp) in enumerate(divisions): area = division_shp.area area_without_green = calc_area(division_shp, green_spaces, green_spaces_idx) area_green = area - area_without_green green_relevance[id_division] = area_green / area progress_msg = unicode(index) + " of " + unicode(total_divisions) print(progress_msg, end="\r" * len(progress_msg)) return green_relevance
def intersect_data_with_shps(df, shp_path, lat_field="LAT", lon_field="LON"): """Asign an id from shp_path based on lat-lon intersection.""" sf = shapefile.Reader(shp_path) id_field_name = sf.fields[1][0] # def wrapper(fn, shapes, shp_idx, shp_path): # @wraps(fn) # def inner(*args, **kwargs): # kwargs["shapes"] = shapes # kwargs["shp_idx"] = shp_idx # kwargs["shp_path"] = shp_path # fn(*args, **kwargs) # return inner shapes = list(geo_utils.iter_shp_as_shapely(shp_path)) # shp_idx = create_spatial_index(shapes) # func_get_id = wrapper( # find_id_intersecting_shape, shapes, shp_idx, shp_path) # df[id_field_name] = map(func_get_id, df[lat_field], df[lon_field]) def func(x): return find_id_intersecting_shape(x["LAT"], x["LON"], shapes, shp_path) df[id_field_name] = df.apply(func, axis=1) return df
def create_context_polygon(context_shp_or_polygon): if not context_shp_or_polygon: return None elif (type(context_shp_or_polygon) != str and type(context_shp_or_polygon) != unicode): return context_shp_or_polygon else: return cascaded_union( [i[1].buffer(0) for i in iter_shp_as_shapely(context_shp_or_polygon)])
def create_context_polygon(context_shp_or_polygon): if not context_shp_or_polygon: return None elif (type(context_shp_or_polygon) != str and type(context_shp_or_polygon) != unicode): return context_shp_or_polygon else: return cascaded_union([ i[1].buffer(0) for i in iter_shp_as_shapely(context_shp_or_polygon) ])
def count_points(points_shp_path, polygons_shp_path): points_shp_path = pf.find_shp_path(points_shp_path) polygons_shp_path = pf.find_shp_path(polygons_shp_path) points = dict(iter_shp_as_shapely(points_shp_path)) polygons = dict(iter_shp_as_shapely(polygons_shp_path)) count = {id_polygon: 0 for id_polygon in polygons.iterkeys()} for id_polygon, polygon in polygons.iteritems(): remove_points = [] for id_point, point in points.iteritems(): if polygon.contains(point): count[id_polygon] += 1 remove_points.append(id_point) for remove_point in remove_points: del points[remove_point] return count
def calculate_intersect_weights(division_dir, buffer_dir, weights_path, empty_dirs=None, force_buffer_sum=True): """Calculate perecentage of division_dir shapes intersecting buffer_dir. Find which shapes in the division shapefile intersect with each shape in buffer, and how much surface of the division shape is intersecting as well as how much of the buffer shape is being intersected by that division shape. If a list with "empty shapefiles" is provided, the surfaces from those shps that intersect with the buffer will not be taken into account for the calculation of weights. They will be subtracted both from divisions and buffers. Args: division_dir (str): Directory where shapefile with "inner shapes" is in this case the polygons used to divide the greater shape. buffer_dir (str): Directory where shapefile with "container shapes" is, in this case the buffers calculated over points or lines. empty_dirs (list): Paths to shapefiles with surfaces that shouldn't be taken into account in the calculation. Returns: dict: The perecentage of intersected surface is returned as calculated over total division area and total buffer area in a dictionary like this dict[id_buffer][id_division][division] >>> { "id_buffer1": {"id_division1": {"division": %_intersect_division_surface, "buffer": %_intersect_buffer_surface}, "id_division2": {"division": %_intersect_division_surface, "buffer": %_intersect_buffer_surface} }, } """ division_path = find_shp_path(division_dir) buffer_path = find_shp_path(buffer_dir) if empty_dirs: empty_paths = [find_shp_path(shp) for shp in empty_dirs] # create spatial index for divisions divisions = list(geo_utils.iter_shp_as_shapely(division_path)) divisions_idx = create_spatial_index(divisions) # create spatial index for empty shapes if empty_dirs: empty_shps = [] for empty_path in empty_paths: empty_shps.extend(list(geo_utils.iter_shp_as_shapely(empty_path))) empty_idx = create_spatial_index(empty_shps) weighted_intersections = {} for id_buffer, buffer_shp in geo_utils.iter_shp_as_shapely(buffer_path): buffer_shp = buffer_shp.buffer(0) weighted_intersections[id_buffer] = {} if empty_dirs: buffer_area = calc_area(buffer_shp, empty_shps, empty_idx) else: buffer_area = buffer_shp.area assert buffer_area > 0, "Buffer area can't be 0 " + unicode(id_buffer) intersect_generator = find_intersections(buffer_shp, divisions, divisions_idx) for id_division, division_shp in intersect_generator: division_shp = division_shp.buffer(0) if empty_dirs: division_area = calc_area(division_shp, empty_shps, empty_idx) else: division_area = division_shp.area try: intersect = buffer_shp.intersection(division_shp) if empty_dirs: intersect_area = calc_area(intersect, empty_shps, empty_idx) else: intersect_area = intersect.area except Exception as inst: print("id_divison:", id_division, "couldn't be intersected with id_buffer:", id_buffer) print(inst, "\n") weighted_intersections[id_buffer][id_division] = { "division": round(intersect_area / division_area, 30), "buffer": round(intersect_area / buffer_area, 30) } if force_buffer_sum: total_w = sum([ i["buffer"] for i in weighted_intersections[id_buffer].itervalues() ]) for id_division in weighted_intersections[id_buffer]: weighted_intersections[id_buffer][id_division][ "buffer"] /= total_w save_to_json(weighted_intersections, weights_path) return weighted_intersections
def calculate_intersect_weights(division_dir, buffer_dir, weights_path, empty_dirs=None, force_buffer_sum=True): """Calculate perecentage of division_dir shapes intersecting buffer_dir. Find which shapes in the division shapefile intersect with each shape in buffer, and how much surface of the division shape is intersecting as well as how much of the buffer shape is being intersected by that division shape. If a list with "empty shapefiles" is provided, the surfaces from those shps that intersect with the buffer will not be taken into account for the calculation of weights. They will be subtracted both from divisions and buffers. Args: division_dir (str): Directory where shapefile with "inner shapes" is in this case the polygons used to divide the greater shape. buffer_dir (str): Directory where shapefile with "container shapes" is, in this case the buffers calculated over points or lines. weights_path (str): Json path where calculated weights will be saved. empty_dirs (list): Paths to shapefiles with surfaces that shouldn't be taken into account in the calculation. force_buffer_sum (bool): Recalculate weights of a buffer so they always sum 1.0. Returns: dict: The perecentage of intersected surface is returned as calculated over total division area and total buffer area in a dictionary like this dict[id_buffer][id_division][division] >>> { "id_buffer1": {"id_division1": {"division": %_intersect_division_surface, "buffer": %_intersect_buffer_surface}, "id_division2": {"division": %_intersect_division_surface, "buffer": %_intersect_buffer_surface} }, } """ division_path = pf.find_shp_path(division_dir) buffer_path = pf.find_shp_path(buffer_dir) if empty_dirs: empty_paths = [pf.find_shp_path(shp) for shp in empty_dirs] # create spatial index for divisions divisions = list(geo_utils.iter_shp_as_shapely(division_path)) divisions_idx = create_spatial_index(divisions) # create spatial index for empty shapes if empty_dirs: empty_shps = [] for empty_path in empty_paths: empty_shps.extend(list(geo_utils.iter_shp_as_shapely(empty_path))) empty_idx = create_spatial_index(empty_shps) weighted_intersections = {} for id_buffer, buffer_shp in geo_utils.iter_shp_as_shapely(buffer_path): buffer_shp = buffer_shp.buffer(0) weighted_intersections[id_buffer] = {} if empty_dirs: buffer_area = calc_area(buffer_shp, empty_shps, empty_idx) else: buffer_area = buffer_shp.area assert buffer_area > 0, "Buffer area can't be 0 " + unicode(id_buffer) intersect_generator = find_intersections(buffer_shp, divisions, divisions_idx) for id_division, division_shp in intersect_generator: division_shp = division_shp.buffer(0) if empty_dirs: division_area = calc_area(division_shp, empty_shps, empty_idx) else: division_area = division_shp.area try: intersect = buffer_shp.intersection(division_shp) if empty_dirs: intersect_area = calc_area(intersect, empty_shps, empty_idx) else: intersect_area = intersect.area except Exception as inst: print("id_divison:", id_division, "couldn't be intersected with id_buffer:", id_buffer) print(inst, "\n") weighted_intersections[id_buffer][id_division] = { "division": round(intersect_area / division_area, 30), "buffer": round(intersect_area / buffer_area, 30), } if force_buffer_sum: total_w = sum([i["buffer"] for i in weighted_intersections[id_buffer].itervalues()]) for id_division in weighted_intersections[id_buffer]: weighted_intersections[id_buffer][id_division]["buffer"] /= total_w save_to_json(weighted_intersections, weights_path) return weighted_intersections