def main(): config = load_config() regions = ['Lao Cai', 'Binh Dinh', 'Thanh Hoa'] # plot_set = [ # { # 'column': 'min_econ_l', # 'title': 'Min Economic impact', # 'legend_label': "Economic Loss('000 USD/day)", # 'divisor': 1000, # 'significance': 0 # }, # { # 'column': 'max_econ_l', # 'title': 'Max Economic impact', # 'legend_label': "Economic Loss('000 USD/day)", # 'divisor': 1000, # 'significance': 0 # }, # { # 'column': 'min_tons', # 'title': 'Min Daily Tons loss', # 'legend_label': "MT (tons/day)", # 'divisor': 1, # 'significance': 0 # }, # { # 'column': 'max_tons', # 'title': 'Max Daily Tons loss', # 'legend_label': "MT (tons/day)", # 'divisor': 1, # 'significance': 0 # }, # { # 'column': 'min_adapt_', # 'title': 'Min NPV of adaptation over time', # 'legend_label': "NPV(USD million)", # 'divisor': 1000000, # 'significance': 0 # }, # { # 'column': 'max_econ_l', # 'title': 'Max NPV of adaptation over time', # 'legend_label': "NPV(USD million)", # 'divisor': 1000000, # 'significance': 0 # }, # { # 'column': 'min_bc_rat', # 'title': 'Min BCR of adaptation over time', # 'legend_label': "BCR", # 'divisor': 1, # 'significance': 0 # }, # { # 'column': 'max_bc_rat', # 'title': 'Max BCR of adaptation over time', # 'legend_label': "BCR", # 'divisor': 1, # 'significance': 0 # } # ] plot_set = [ { 'column': 'min_adapt_', 'title': 'Min NPV of adaptation over time', 'legend_label': "NPV(USD million)", 'divisor': 1000000, 'significance': 0 }, { 'column': 'max_adapt_', 'title': 'Max NPV of adaptation over time', 'legend_label': "NPV(USD million)", 'divisor': 1000000, 'significance': 0 }, { 'column': 'min_bc_rat', 'title': 'Min BCR of adaptation over time', 'legend_label': "BCR", 'divisor': 1, 'significance': 0 }, { 'column': 'max_bc_rat', 'title': 'Max BCR of adaptation over time', 'legend_label': "BCR", 'divisor': 1, 'significance': 0 } ] # for region in regions: for re in range(0,1): region = regions[re] region_file = os.path.join(config['paths']['data'], 'Results', 'Failure_shapefiles', 'weighted_edges_commune_center_failures_' + region.lower().replace(' ', '') + '_5_tons.shp') plot_settings = get_region_plot_settings(region) for c in range(len(plot_set)): ax = get_axes(plot_settings['bbox'], figsize=plot_settings['figure_size']) if region == 'Binh Dinh': plot_basemap(ax, config['paths']['data'], country_border='none', plot_states=False, plot_districts=True, highlight_region=region) else: plot_basemap(ax, config['paths']['data'], country_border='none', plot_states=True, plot_districts=True, highlight_region=region) scale_bar(ax, location=(0.8, 0.05), length=plot_settings['scale_legend']) proj_lat_lon = ccrs.PlateCarree() # generate weight bins column = plot_set[c]['column'] if column in ('min_adapt_','max_adapt_'): weights = [ record.attributes[column] for record in shpreader.Reader(region_file).records() if record.attributes[column] > 0 and record.attributes['max_econ_l'] > 0 ] elif column in ('min_bc_rat','max_bc_rat'): weights = [ record.attributes[column] for record in shpreader.Reader(region_file).records() if record.attributes[column] > 1 and record.attributes['max_econ_l'] > 0 ] else: weights = [ record.attributes[column] for record in shpreader.Reader(region_file).records() ] max_weight = max(weights) if column in ('min_bc_rat','max_bc_rat') and region == 'Lao Cai': width_by_range = generate_weight_bins_with_colour_gradient(weights,n_steps = 6,width_step=0.001) else: width_by_range = generate_weight_bins_with_colour_gradient(weights, width_step=0.001) road_geoms_by_category = { region: [] } styles = OrderedDict([ (region, Style(color='#ba0f03', zindex=6, label=region)) ]) if column in ('min_adapt_','max_adapt_'): rec_set = [ record for record in shpreader.Reader(region_file).records() if record.attributes[column] > 0 and record.attributes['max_econ_l'] > 0 ] elif column in ('min_bc_rat','max_bc_rat'): rec_set = [ record for record in shpreader.Reader(region_file).records() if record.attributes[column] > 1 and record.attributes['max_econ_l'] > 0 ] else: rec_set = [ record for record in shpreader.Reader(region_file).records() ] for record in rec_set: cat = region geom = record.geometry val = record.attributes[column] buffered_geom = None for (nmin, nmax), line_style in width_by_range.items(): if nmin <= val and val < nmax: buffered_geom = geom.buffer(line_style[1]) if buffered_geom is not None: ax.add_geometries( [buffered_geom], crs=proj_lat_lon, linewidth=0, facecolor=str(line_style[2]), edgecolor='none', zorder=3 + line_style[0] ) else: print("Feature was outside range to plot", record.attributes) x_l = plot_settings['weight_legend']['x_l'] x_r = plot_settings['weight_legend']['x_r'] base_y = plot_settings['weight_legend']['base_y'] y_step = plot_settings['weight_legend']['y_step'] y_text_nudge = plot_settings['weight_legend']['y_text_nudge'] x_text_nudge = plot_settings['weight_legend']['x_text_nudge'] # text above weight legend ax.text( x_l, base_y + y_step - y_text_nudge, plot_set[c]['legend_label'], horizontalalignment='left', transform=proj_lat_lon, size=10) # weight legend divisor = plot_set[c]['divisor'] for (i, ((nmin, nmax), line_style)) in enumerate(width_by_range.items()): y = base_y - (i*y_step) line = LineString([(x_l, y), (x_r, y)]).buffer(line_style[1]) ax.add_geometries( [line], crs=proj_lat_lon, linewidth=0, edgecolor=str(line_style[2]), facecolor=str(line_style[2]), zorder=2) significance_ndigits = plot_set[c]['significance'] if nmin == max_weight: value_template = '>{:.' + str(significance_ndigits) + 'f}' label = value_template.format(round(max_weight/divisor, significance_ndigits)) else: value_template = '{:.' + str(significance_ndigits) + 'f}-{:.' + str(significance_ndigits) + 'f}' label = value_template.format(round(nmin/divisor, significance_ndigits), round(nmax/divisor, significance_ndigits)) ax.text( x_r + x_text_nudge, y - y_text_nudge, label, horizontalalignment='left', transform=proj_lat_lon, size=10) # district labels plot_district_labels(ax, config['paths']['data'], highlight_region=region) # plot title = '{} ({})'.format(region, plot_set[c]['title']) print(" * Plotting", title) plt.title(title, fontsize = 14) # output output_file = os.path.join(config['paths']['figures'], 'commune_center-{}-{}-failures_2.png'.format(region.lower().replace(' ', ''), column)) save_fig(output_file) plt.close()
def test_linestring_ctypes_deprecated(): line = LineString(((1.0, 2.0), (3.0, 4.0))) with pytest.warns(ShapelyDeprecationWarning, match="ctypes"): line.ctypes
def test_linestring_array_interface_numpy_deprecated(): import numpy as np line = LineString(((1.0, 2.0), (3.0, 4.0))) with pytest.warns(ShapelyDeprecationWarning, match="array interface"): np.array(line)
def test_linestring_empty(self): # Test Non-operability of Null geometry l_null = LineString() self.assertEqual(l_null.wkt, 'GEOMETRYCOLLECTION EMPTY') self.assertEqual(l_null.length, 0.0)
def test_linestring_empty_mutate(self): # Check that we can set coordinates of a null geometry l_null = LineString() l_null.coords = [(0, 0), (1, 1)] self.assertAlmostEqual(l_null.length, 1.4142135623730951)
def line_length(node1, node2): line = LineString((node1, node2)) return line.length
def __init__(self, velHub, streamline, wake, bounding_box, debug=False, debug_plot=False): #Bounding box, shapely polygon self._bounding_box = bounding_box #initialise top and bottom wake stream boundaries self.streamtop = [[0] * len(streamline[0]), [0] * len(streamline[1])] self.streambot = [[0] * len(streamline[0]), [0] * len(streamline[1])] L = len(streamline[0]) #Compute hypothenus hypo = np.zeros(L - 1) X = np.asarray(streamline[0]) Y = np.asarray(streamline[1]) hypo = np.sqrt(((X[:-1] - X[1:])**2.0) + ((Y[:-1] - Y[1:])**2.0)) #Compute the outer lines of the wake ##Flow signs deltaY = Y[1] - Y[0] sy = np.sign(deltaY) deltaX = X[1] - X[0] sx = np.sign(deltaX) ##Tilt first outer points l = wake.Diam / 2.0 #wake expansion gamma = np.arctan2(deltaY, deltaX) self.streamtop[0][0] = X[0] - (l * np.sin(gamma)) self.streamtop[1][0] = Y[0] + (l * np.cos(gamma)) self.streambot[0][0] = X[0] + (l * np.sin(gamma)) self.streambot[1][0] = Y[0] - (l * np.cos(gamma)) distance = 0.0 for i in range(L - 1): ##Flow signs deltaY = Y[i + 1] - Y[i] sy = np.sign(deltaY) deltaX = X[i + 1] - X[i] sx = np.sign(deltaX) distance += hypo[i] #cumulative distance along streamline l = (wake.Diam / 2.0) + (wake.l * distance) #wake expansion AB = np.sqrt((deltaY**2.0) + (deltaX**2.0)) AC = np.sqrt((AB**2.0) + (l**2.0)) gamma = np.arctan((Y[i + 1] - Y[i]) / (X[i + 1] - X[i])) alpha1 = np.arctan(l / AB) alpha2 = np.arctan(-l / AB) beta = gamma + alpha1 delta = gamma + alpha2 self.streamtop[0][i + 1] = X[i] + ((AC * np.cos(beta)) * sx) self.streamtop[1][i + 1] = Y[i] + ((AC * np.sin(beta)) * sx) self.streambot[0][i + 1] = X[i] + ((AC * np.cos(delta)) * sx) self.streambot[1][i + 1] = Y[i] + ((AC * np.sin(delta)) * sx) #Make sure that the last points are outside or on the bounding box pt1 = Point(self.streambot[0][-1], self.streambot[1][-1]) pt2 = Point(self.streamtop[0][-1], self.streamtop[1][-1]) ptEnd = [streamline[0][-1], streamline[1][-1]] pts = list(self._bounding_box.exterior.coords)[:-1] L0 = line(pts[0], pts[1]) L1 = line(pts[1], pts[2]) L2 = line(pts[2], pts[3]) L3 = line(pts[3], pts[0]) Ls = [L0, L1, L2, L3] #Need to find if one or the two last points outside of box if (self._bounding_box.contains(pt1) or self._bounding_box.contains(pt2)): if self._bounding_box.contains(pt1): Lref = line([self.streambot[0][-2], self.streambot[1][-2]], [self.streambot[0][-1], self.streambot[1][-1]]) Lbis = line([self.streamtop[0][-2], self.streamtop[1][-2]], [self.streamtop[0][-1], self.streamtop[1][-1]]) if self._bounding_box.contains(pt2): Lref = line([self.streamtop[0][-2], self.streamtop[1][-2]], [self.streamtop[0][-1], self.streamtop[1][-1]]) Lbis = line([self.streambot[0][-2], self.streambot[1][-2]], [self.streambot[0][-1], self.streambot[1][-1]]) #if one point: find intersection with bounding box Rs = [] Rbiss = [] for L in Ls: R = intersection(L, Lref) Rbis = intersection(L, Lbis) if not R == False: Rs.append(R) if not R == False: Rbiss.append(Rbis) clPt, ind, dist = closest_point(ptEnd, Rs, debug=debug) if self._bounding_box.contains(pt1): self.streambot[0].append(clPt[0]) self.streambot[1].append(clPt[1]) if not Rbiss[ind] == False: self.streamtop[0].append(Rbiss[ind][0]) self.streamtop[1].append(Rbiss[ind][1]) if self._bounding_box.contains(pt2): self.streamtop[0].append(clPt[0]) self.streamtop[1].append(clPt[1]) if not Rbiss[ind] == False: self.streambot[0].append(Rbiss[ind][0]) self.streambot[1].append(Rbiss[ind][1]) else: #if two points: add closest boundingbox corner to wake c1 = [self.streambot[0][-1], self.streambot[1][-1]] c2 = [self.streamtop[0][-1], self.streamtop[1][-1]] c3 = [self.streamtop[0][0], self.streamtop[1][0]] c4 = [self.streambot[0][0], self.streambot[1][0]] test_poly = Polygon([c1, c2, c3, c4]) test_line = LineString([c1, c2]) cPt = [] for pt in pts: if test_line.crosses(self._bounding_box): trgl = Polygon([c1, c2, pt]) test = trgl.intersection(test_poly) if (test.area == 0.0): self.streambot[0].append(pt[0]) self.streambot[1].append(pt[1]) if debug_plot: fig = plt.figure(figsize=(18, 10)) ax1 = fig.add_subplot(121) ax1.plot(streamline[0], streamline[1]) ax1.plot(self.streamtop[0], self.streamtop[1]) ax1.plot(self.streambot[0], self.streambot[1]) ax1.set_aspect('equal') #plt.show() #Define wake shapes with shapely extPt = [] for i, j in zip(self.streambot[0][:], self.streambot[1][:]): extPt.append((i, j)) for i, j in zip(self.streamtop[0][::-1], self.streamtop[1][::-1]): extPt.append((i, j)) self.polygon = Polygon(extPt) #Cut-out wake bits outside of bounding box try: self.polygon = self.polygon.intersection(self._bounding_box) #In case added points mess up the shapely polygon except TopologicalError: extPt.pop(len(extPt) // 2) self.polygon = Polygon(extPt) try: self.polygon = self.polygon.intersection(self._bounding_box) except TopologicalError: extPt.pop(len(extPt) // 2) self.polygon = Polygon(extPt) self.polygon = self.polygon.intersection(self._bounding_box) #Control plots if debug_plot: ax = fig.add_subplot(122) x, y = self.polygon.exterior.xy ax.plot(x, y, 'o', color='#999999', zorder=1) patch = PolygonPatch(self.polygon, alpha=0.5, zorder=2) ax.add_patch(patch) ax.set_aspect('equal')
def plot_road_network(net, subs, inset={}, path=None): """ """ fig = plt.figure(figsize=(40, 40), dpi=72) ax = fig.add_subplot(111) sub_x = [subs[s]['cord'][0] for s in subs] sub_y = [subs[s]['cord'][1] for s in subs] # Draw nodes ax.scatter(sub_x, sub_y, c='dodgerblue', s=2000) DrawNodes(net, ax, label='T', color='green', size=25) DrawNodes(net, ax, label='R', color='black', size=2.0) # Draw edges d = {'edges':list(net.edges()), 'geometry':[LineString((net.nodes[e[0]]['cord'],net.nodes[e[1]]['cord'])) \ for e in net.edges()]} df_edges = gpd.GeoDataFrame(d, crs="EPSG:4326") df_edges.plot(ax=ax, edgecolor="black", linewidth=2.0, linestyle="dashed") ax.tick_params(left=False, bottom=False, labelleft=False, labelbottom=False) # Inset figures for sub in inset: axins = zoomed_inset_axes(ax, inset[sub]['zoom'], loc=inset[sub]['loc']) axins.set_aspect(1.3) # Draw nodes ax.scatter([subs[sub]['cord'][0]], [subs[sub]['cord'][1]], c='dodgerblue', s=2000) DrawNodes(inset[sub]['graph'], axins, label='T', color='green', size=25) DrawNodes(inset[sub]['graph'], axins, label='R', color='black', size=2.0) # Draw edges d = {'edges':list(inset[sub]['graph'].edges()), 'geometry':[LineString((inset[sub]['graph'].nodes[e[0]]['cord'], inset[sub]['graph'].nodes[e[1]]['cord'])) \ for e in inset[sub]['graph'].edges()]} df_edges = gpd.GeoDataFrame(d, crs="EPSG:4326") df_edges.plot(ax=axins, edgecolor="black", linewidth=2.0, linestyle="dashed") axins.tick_params(bottom=False, left=False, labelleft=False, labelbottom=False) mark_inset(ax, axins, loc1=inset[sub]['loc1'], loc2=inset[sub]['loc2'], fc="none", ec="0.5") # Legend for the plot leghands = [ Line2D([0], [0], color='black', markerfacecolor='black', marker='o', markersize=0, label='road network'), Line2D([0], [0], color='white', markerfacecolor='green', marker='o', markersize=20, label='transformer'), Line2D([0], [0], color='white', markerfacecolor='black', marker='o', markersize=20, label='road node'), Line2D([0], [0], color='white', markerfacecolor='dodgerblue', marker='o', markersize=20, label='substation') ] ax.legend(handles=leghands, loc='best', ncol=1, prop={'size': 25}) if path != None: fig.savefig("{}{}.png".format(path, '-51121-road'), bbox_inches='tight') return
import math from shapely.geometry import LineString import copy # Measurements in inches l1 = 3.75 l2 = 2.5 start = (0, 0) #(t1, t2) degrees A = (3.75, 2.5) #(x, y) inches B = (-3.75, 2.5) #(x, y) inches obstacle = [ LineString([(-2.5, 8.5), (2.5, 8.5)]), LineString([(2.5, 8.5), (2.5, 5)]), LineString([(2.5, 5), (-2.5, 5)]), LineString([(-2.5, 5), (-2.5, 8.5)]), # Workspace boundaries: LineString([(-7.1, 8.1), (7.1, 8.1)]), LineString([(7.1, 8.1), (7.1, -0.1)]), LineString([(7.1, -0.1), (-7.1, -0.1)]), LineString([(-7.1, -0.1), (-7.1, 8.1)]) ] t1range, t2range = 180, 360 cspace = [[0 for y in range(0, t2range)] for x in range(0, t1range)] def t1_to_i(t): return round(t)
# select polygon facecolor RGB vals based on record value R = 0.81 G = 0.81 B = 0.81 nparts = 0 for mapg in map_geoms: if rec[field_names.index(mapg)] not in rec_vals: print rec[field_names.index(mapg)] rec_vals.append(rec[field_names.index(mapg)]) if rec[field_names.index(mapg)] in plot_these_rec_vals: nparts = len(shape.parts) # total parts Pts = Point(shape.points) Lin = LineString(shape.points) Bounds = Lin.bounds #(minx, miny, maxx, maxy) minx = Bounds[0] miny = Bounds[1] maxx = Bounds[2] maxy = Bounds[3] Xsub = x_o[x_o > minx - Dismin] Xsub = Xsub[Xsub < maxx + Dismin] Ysub = y_o[y_o > miny - Dismin] Ysub = Ysub[Ysub < maxy + Dismin] Xg1, Yg1 = np.meshgrid(Xsub, Ysub) GridPts = zip(Xg1.ravel(), Yg1.ravel()) for Pt in GridPts: Dis = 1.0 / (Lin.distance(Point(Pt)) + .01)
def gdlToGisFile(self, coords, folderpath, layername, fmt="ESRI Shapefile", epsg_cd=4326, prop=None, crtfld=True): """ Dump geodesic line coords to ESRI Shapefile and GeoJSON Linestring Feature coords: input coords returned by gcComp. folderpath: folder to store output file. layername: output filename. fmt: output format ("ESRI Shapefile" (default), "GeoJSON"). epsg_cd: Coordinate Reference System, EPSG code (default: 4326) prop: property crtfld: create folder if not exists (default: True). """ schema = {'geometry': 'LineString', 'properties': {'prop': 'str'}} try: if fmt in ["ESRI Shapefile", "GeoJSON"]: ext = ".shp" if fmt == "GeoJSON": ext = ".geojson" filepath = os.path.join(folderpath, "{0}{1}".format(layername, ext)) self.__dest_folder(folderpath, crtfld) if fmt == "GeoJSON" and os.path.isfile(filepath): os.remove(filepath) out_crs = from_epsg(epsg_cd) with collection(filepath, "w", fmt, schema, crs=out_crs) as output: line = LineString(coords) geom = mapping(line) if self.__antimeridian: line_t = self.__antiMeridianCut(geom) else: line_t = geom output.write({ 'properties': { 'prop': prop }, 'geometry': line_t }) self.__logger.info("{0} succesfully created!".format(fmt)) else: self.__logger.error("No format to store output...") return except Exception as e: self.__logger.error("Error: {0}".format(e)) raise ExportGeodesicLineError(e)
def test_boundary(self): l1 = LineString([(0, 0), (1, 0), (1, 1), (0, 0)]) l2 = LineString([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)]) expected = GeoSeries([l1, l2], index=self.g1.index, crs=self.g1.crs) self._test_unary_topological("boundary", expected, self.g1)
def setup_method(self): self.t1 = Polygon([(0, 0), (1, 0), (1, 1)]) self.t2 = Polygon([(0, 0), (1, 1), (0, 1)]) self.t3 = Polygon([(2, 0), (3, 0), (3, 1)]) self.sq = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]) self.t4 = Polygon([(0, 0), (3, 0), (3, 3), (0, 2)]) self.t5 = Polygon([(2, 0), (3, 0), (3, 3), (2, 3)]) self.inner_sq = Polygon([(0.25, 0.25), (0.75, 0.25), (0.75, 0.75), (0.25, 0.75)]) self.nested_squares = Polygon(self.sq.boundary, [self.inner_sq.boundary]) self.p0 = Point(5, 5) self.p3d = Point(5, 5, 5) self.g0 = GeoSeries([ self.t1, self.t2, self.sq, self.inner_sq, self.nested_squares, self.p0, None, ]) self.g1 = GeoSeries([self.t1, self.sq]) self.g2 = GeoSeries([self.sq, self.t1]) self.g3 = GeoSeries([self.t1, self.t2]) self.g3.crs = "epsg:4326" self.g4 = GeoSeries([self.t2, self.t1]) self.g4.crs = "epsg:4326" self.g_3d = GeoSeries([self.p0, self.p3d]) self.na = GeoSeries([self.t1, self.t2, Polygon()]) self.na_none = GeoSeries([self.t1, None]) self.a1 = self.g1.copy() self.a1.index = ["A", "B"] self.a2 = self.g2.copy() self.a2.index = ["B", "C"] self.esb = Point(-73.9847, 40.7484) self.sol = Point(-74.0446, 40.6893) self.landmarks = GeoSeries([self.esb, self.sol], crs="epsg:4326") self.l1 = LineString([(0, 0), (0, 1), (1, 1)]) self.l2 = LineString([(0, 0), (1, 0), (1, 1), (0, 1)]) self.g5 = GeoSeries([self.l1, self.l2]) self.g6 = GeoSeries([self.p0, self.t3]) self.g7 = GeoSeries([self.sq, self.t4]) self.g8 = GeoSeries([self.t1, self.t5]) self.empty = GeoSeries([]) self.all_none = GeoSeries([None, None]) self.empty_poly = Polygon() # Crossed lines self.l3 = LineString([(0, 0), (1, 1)]) self.l4 = LineString([(0, 1), (1, 0)]) self.crossed_lines = GeoSeries([self.l3, self.l4]) # Placeholder for testing, will just drop in different geometries # when needed self.gdf1 = GeoDataFrame({ "geometry": self.g1, "col0": [1.0, 2.0], "col1": ["geo", "pandas"] }) self.gdf2 = GeoDataFrame({ "geometry": self.g1, "col3": [4, 5], "col4": ["rand", "string"] }) self.gdf3 = GeoDataFrame({ "geometry": self.g3, "col3": [4, 5], "col4": ["rand", "string"] })
def setUp(self): self.point = Point(1, 1) self.line1 = LineString(([0, 0], [2, 0])) self.line2 = LineString(([3, 0], [3, 6], [4.5, 6]))
class TestLoaders: def test_build_input_rows(self): dt_microsecond_format = '%Y-%m-%d %H:%M:%S.%f' def get_dt_nanosecond(v): return np.datetime64('201{}-01-01 01:01:01.001001001'.format(v)) def get_dt_microsecond(v): return datetime.datetime.strptime( '201{}-01-01 01:01:01.001001'.format(v), dt_microsecond_format) data = [ (1, 'a', get_dt_nanosecond(1), get_dt_microsecond(1)), (2, 'b', get_dt_nanosecond(2), get_dt_microsecond(2)), ] result = _build_input_rows(data) # breakpoint expected = [ TStringRow(cols=[ TStringValue(str_val='1', is_null=None), TStringValue(str_val='a', is_null=None), TStringValue(str_val=get_dt_nanosecond(1).astype(str), is_null=None), TStringValue( str_val=get_dt_microsecond(1).strftime( dt_microsecond_format), is_null=None, ), ]), TStringRow(cols=[ TStringValue(str_val='2', is_null=None), TStringValue(str_val='b', is_null=None), TStringValue(str_val=get_dt_nanosecond(2).astype(str), is_null=None), TStringValue( str_val=get_dt_microsecond(2).strftime( dt_microsecond_format), is_null=None, ), ]), ] assert result == expected def test_build_input_rows_with_array(self): data = [(1, 'a'), (2, 'b'), (3, ['c', 'd', 'e'])] result = _build_input_rows(data) expected = [ TStringRow(cols=[ TStringValue(str_val='1', is_null=None), TStringValue(str_val='a', is_null=None), ]), TStringRow(cols=[ TStringValue(str_val='2', is_null=None), TStringValue(str_val='b', is_null=None), ]), TStringRow(cols=[ TStringValue(str_val='3', is_null=None), TStringValue(str_val='{c,d,e}', is_null=None), ]), ] assert result == expected @pytest.mark.parametrize( 'data, col_properties', [ pytest.param( pd.DataFrame({ 'a': [[1, 1], [2, 2], [3, 3]], 'b': [[1.1, 1.1], [2.2, 2.2], [3.3, 3.3]], 'c': [1, 2, 3], 'd': [ np.datetime64('2010-01-01 01:01:01.001001001'), np.datetime64('2011-01-01 01:01:01.001001001'), np.datetime64('2012-01-01 01:01:01.001001001'), ], 'e': [ datetime.datetime.strptime( '2010-01-01 01:01:01.001001', '%Y-%m-%d %H:%M:%S.%f', ), datetime.datetime.strptime( '2011-01-01 01:01:01.001001', '%Y-%m-%d %H:%M:%S.%f', ), datetime.datetime.strptime( '2012-01-01 01:01:01.001001', '%Y-%m-%d %H:%M:%S.%f', ), ], 'f': [ Decimal('1.1234'), Decimal('2.2345'), Decimal('3.3456'), ], }), [ { 'name': 'a', 'type': 'INT', 'is_array': True }, { 'name': 'b', 'type': 'DOUBLE', 'is_array': True }, { 'name': 'c', 'type': 'INT', 'is_array': False }, { 'name': 'd', 'type': 'TIMESTAMP', 'is_array': False, 'precision': 9, }, { 'name': 'e', 'type': 'TIMESTAMP', 'is_array': False, 'precision': 0, }, { 'name': 'f', 'type': 'DECIMAL', 'is_array': False, 'scale': 10, 'precision': 4, }, ], id='mult-cols-mix-array-not-null', ), pytest.param( pd.DataFrame({ 'a': [[1, 1], [2, 2], [3, 3]], 'b': [[1.1, 1.1], [2.2, 2.2], [3.3, 3.3]], }), [ { 'name': 'a', 'type': 'INT', 'is_array': True }, { 'name': 'b', 'type': 'DOUBLE', 'is_array': True }, ], id='mult-cols-array-not-null', ), pytest.param( pd.DataFrame({ 'a': [1, 2, 3], 'b': [1.1, 2.2, 3.3] }), [ { 'name': 'a', 'type': 'INT', 'is_array': False }, { 'name': 'b', 'type': 'DOUBLE', 'is_array': False }, ], id='mult-cols-not-null', ), pytest.param( pd.DataFrame([ { 'a': [2, 3, 4] }, { 'a': [4444] }, { 'a': [] }, { 'a': [] }, { 'a': [2, 3, 4] }, ]), [{ 'name': 'a', 'type': 'INT', 'is_array': True }], id='one-col-array-not-null', ), pytest.param( pd.DataFrame(data=[ { 'a': [2, 3, 4], 'b': 'teststr' }, { 'a': [2, 3], 'b': 'teststr' }, { 'a': [4444], 'b': 'teststr' }, { 'a': [], 'b': 'teststr' }, { 'a': [2, 3, 4], 'b': 'teststr' }, ]), [ { 'name': 'a', 'type': 'INT', 'is_array': True }, { 'name': 'b', 'type': 'STR', 'is_array': False }, ], id='mult-cols-mix-array-not-null', ), pytest.param( pd.DataFrame(data=[ { 'a': [2, 3, 4], 'b': 'teststr' }, { 'a': [2, 3], 'b': 'teststr' }, { 'a': [4444], 'b': 'teststr' }, { 'a': None, 'b': 'teststr' }, { 'a': [2, 3, 4], 'b': 'teststr' }, ]), [ { 'name': 'a', 'type': 'INT', 'is_array': True }, { 'name': 'b', 'type': 'STR', 'is_array': False }, ], id='mult-cols-mix-array-nullable', ), pytest.param( pd.DataFrame([ { 'a': [2, 3, 4] }, { 'a': [4444] }, { 'a': None }, { 'a': [] }, { 'a': [2, 3, 4] }, ]), [{ 'name': 'a', 'type': 'INT', 'is_array': True }], id='one-col-array-nullable-and-empty-list', ), pytest.param( gpd.GeoDataFrame({ 'a': [Point(0, 0), Point(1, 1)], 'b': [ LineString([(2, 0), (2, 4), (3, 4)]), LineString([(0, 0), (1, 1)]), ], 'c': [ Polygon([(0, 0), (1, 1), (1, 0)]), Polygon([[0, 0], [0, 4], [4, 4], [4, 0]]), ], 'd': [ MultiPolygon([Polygon([(0, 0), (1, 1), (1, 0)])]), MultiPolygon( [Polygon([[0, 0], [0, 4], [4, 4], [4, 0]])]), ], }), [ { 'name': 'a', 'type': 'POINT', 'is_array': False }, { 'name': 'b', 'type': 'LINESTRING', 'is_array': False }, { 'name': 'c', 'type': 'POLYGON', 'is_array': False }, { 'name': 'd', 'type': 'MULTIPOLYGON', 'is_array': False }, ], id='multi-col-geo-nullable', ), ], ) def test_build_table_columnar(self, data, col_properties): from pyomnisci._pandas_loaders import build_input_columnar col_types = get_col_types(col_properties) result = build_input_columnar( data, preserve_index=False, col_names=data.columns, col_types=col_types, ) expected = get_expected(data, col_properties) assert data.shape[1] == len(expected) assert_columnar_equal(result[0], expected) def test_build_table_columnar_pandas(self): common_col_params = dict( nullable=True, precision=0, scale=0, comp_param=0, encoding='NONE', is_array=False, ) col_types = [ ColumnDetails(name='boolean_', type='BOOL', **common_col_params), ColumnDetails(name='smallint_', type='SMALLINT', **common_col_params), ColumnDetails(name='int_', type='INT', **common_col_params), ColumnDetails(name='bigint_', type='BIGINT', **common_col_params), ColumnDetails(name='float_', type='FLOAT', **common_col_params), ColumnDetails(name='double_', type='DOUBLE', **common_col_params), ColumnDetails(name='varchar_', type='STR', **common_col_params), ColumnDetails(name='text_', type='STR', **common_col_params), ColumnDetails(name='time_', type='TIME', **common_col_params), ColumnDetails( name='timestamp_', type='TIMESTAMP', nullable=True, precision=0, scale=0, comp_param=0, encoding='NONE', is_array=False, ), ColumnDetails(name='date_', type='DATE', **common_col_params), ] data = pd.DataFrame({ 'boolean_': [True, False], 'smallint_': np.array([0, 1], dtype=np.int16), 'int_': np.array([0, 1], dtype=np.int32), 'bigint_': np.array([0, 1], dtype=np.int64), 'float_': np.array([0, 1], dtype=np.float32), 'double_': np.array([0, 1], dtype=np.float64), 'varchar_': ['a', 'b'], 'text_': ['a', 'b'], 'time_': [datetime.time(0, 11, 59), datetime.time(13)], 'timestamp_': [pd.Timestamp('2016'), pd.Timestamp('2017')], 'date_': [ datetime.date(2016, 1, 1), datetime.date(2017, 1, 1), ], }) result = _pandas_loaders.build_input_columnar( data, preserve_index=False, col_names=data.columns, col_types=col_types, ) nulls = [False, False] expected = [ TColumn(TColumnData(int_col=[True, False]), nulls=nulls), TColumn( TColumnData(int_col=np.array([0, 1], dtype=np.int16)), nulls=nulls, ), # noqa TColumn( TColumnData(int_col=np.array([0, 1], dtype=np.int32)), nulls=nulls, ), # noqa TColumn( TColumnData(int_col=np.array([0, 1], dtype=np.int64)), nulls=nulls, ), # noqa TColumn( TColumnData(real_col=np.array([0, 1], dtype=np.float32)), nulls=nulls, ), # noqa TColumn( TColumnData(real_col=np.array([0, 1], dtype=np.float64)), nulls=nulls, ), # noqa TColumn(TColumnData(str_col=['a', 'b']), nulls=nulls), TColumn(TColumnData(str_col=['a', 'b']), nulls=nulls), TColumn(TColumnData(int_col=[719, 46800]), nulls=nulls), TColumn(TColumnData(int_col=[1451606400, 1483228800]), nulls=nulls), # noqa TColumn(TColumnData(int_col=[1451606400, 1483228800]), nulls=nulls), ] assert_columnar_equal(result[0], expected) def test_build_table_columnar_nulls(self): common_col_params = dict( nullable=True, scale=0, comp_param=0, encoding='NONE', is_array=False, ) col_types = [ ColumnDetails(name='boolean_', type='BOOL', precision=0, **common_col_params), ColumnDetails(name='int_', type='INT', precision=0, **common_col_params), ColumnDetails(name='bigint_', type='BIGINT', precision=0, **common_col_params), ColumnDetails(name='double_', type='DOUBLE', precision=0, **common_col_params), ColumnDetails(name='varchar_', type='STR', precision=0, **common_col_params), ColumnDetails(name='text_', type='STR', precision=0, **common_col_params), ColumnDetails(name='time_', type='TIME', precision=0, **common_col_params), ColumnDetails( name='timestamp_', type='TIMESTAMP', **common_col_params, precision=0, ), ColumnDetails(name='date_', type='DATE', precision=0, **common_col_params), ] data = pd.DataFrame({ 'boolean_': [True, False, None], # Currently Pandas does not support storing None or NaN # in integer columns, so int cols with null # need to be objects. This means our type detection will be # unreliable since if there is no number outside the int32 # bounds in a column with nulls then we will be assuming int 'int_': np.array([0, 1, None], dtype=np.object), 'bigint_': np.array([0, 9223372036854775807, None], dtype=np.object), 'double_': np.array([0, 1, None], dtype=np.float64), 'varchar_': ['a', 'b', None], 'text_': ['a', 'b', None], 'time_': [datetime.time(0, 11, 59), datetime.time(13), None], 'timestamp_': [ pd.Timestamp('2016'), pd.Timestamp('2017'), None, ], 'date_': [ datetime.date(1001, 1, 1), datetime.date(2017, 1, 1), None, ], }) result = _pandas_loaders.build_input_columnar( data, preserve_index=False, col_names=data.columns, col_types=col_types, ) nulls = [False, False, True] bool_na = -128 int_na = -2147483648 bigint_na = -9223372036854775808 ns_na = -9223372037 double_na = 0 expected = [ TColumn(TColumnData(int_col=[1, 0, bool_na]), nulls=nulls), TColumn( TColumnData(int_col=np.array([0, 1, int_na], dtype=np.int32)), nulls=nulls, ), # noqa TColumn( TColumnData(int_col=np.array( [0, 9223372036854775807, bigint_na], dtype=np.int64)), nulls=nulls, ), # noqa TColumn( TColumnData( real_col=np.array([0, 1, double_na], dtype=np.float64)), nulls=nulls, ), # noqa TColumn(TColumnData(str_col=['a', 'b', '']), nulls=nulls), TColumn(TColumnData(str_col=['a', 'b', '']), nulls=nulls), TColumn(TColumnData(int_col=[719, 46800, bigint_na]), nulls=nulls), TColumn( TColumnData(int_col=[1451606400, 1483228800, ns_na]), nulls=nulls, ), # noqa TColumn( TColumnData(int_col=[-30578688000, 1483228800, bigint_na]), nulls=nulls, ), # noqa ] assert_columnar_equal(result[0], expected) def test_build_row_desc(self): data = pd.DataFrame( { 'boolean_': [True, False], 'smallint_': np.array([0, 1], dtype=np.int16), 'int_': np.array([0, 1], dtype=np.int32), 'bigint_': np.array([0, 1], dtype=np.int64), 'float_': np.array([0, 1], dtype=np.float32), 'double_': np.array([0, 1], dtype=np.float64), 'varchar_': ['a', 'b'], 'text_': ['a', 'b'], 'time_': [datetime.time(0, 11, 59), datetime.time(13)], 'timestamp1_': [pd.Timestamp('2016'), pd.Timestamp('2017')], 'timestamp2_': [ np.datetime64('2016-01-01 01:01:01.001001001'), np.datetime64('2017-01-01 01:01:01.001001001'), ], 'date_': [ datetime.date(2016, 1, 1), datetime.date(2017, 1, 1), ], }, columns=[ 'boolean_', 'smallint_', 'int_', 'bigint_', 'float_', 'double_', 'varchar_', 'text_', 'time_', 'timestamp1_', 'timestamp2_', 'date_', ], ) result = _pandas_loaders.build_row_desc(data) expected = [ TColumnType( col_name='boolean_', col_type=TTypeInfo(type=10), is_reserved_keyword=None, ), TColumnType( col_name='smallint_', col_type=TTypeInfo(type=0), is_reserved_keyword=None, ), TColumnType( col_name='int_', col_type=TTypeInfo(type=1), is_reserved_keyword=None, ), TColumnType(col_name='bigint_', col_type=TTypeInfo(type=2)), TColumnType(col_name='float_', col_type=TTypeInfo(type=3)), TColumnType(col_name='double_', col_type=TTypeInfo(type=5)), TColumnType(col_name='varchar_', col_type=TTypeInfo(type=6, encoding=4)), TColumnType(col_name='text_', col_type=TTypeInfo(type=6, encoding=4)), TColumnType(col_name='time_', col_type=TTypeInfo(type=7)), TColumnType(col_name='timestamp1_', col_type=TTypeInfo(type=8)), TColumnType(col_name='timestamp2_', col_type=TTypeInfo(type=8, precision=9)), TColumnType(col_name='date_', col_type=TTypeInfo(type=9)), ] assert result == expected data.index.name = 'idx' result = _pandas_loaders.build_row_desc(data, preserve_index=True) expected.insert( 0, TColumnType(col_name='idx', col_type=TTypeInfo(type=2))) assert result == expected def test_create_non_pandas_raises(self): with pytest.raises(TypeError) as m: _pandas_loaders.build_row_desc([(1, 'a'), (2, 'b')]) assert m.match('is not supported for type ')
def evaluate(orient_vector, first=False): global top_X, parameters invalid = False l = Limb() l.build(orient_vector) data = np.copy(l.XY) origin = np.array((0, 0)) point = np.array((data[0][-1], data[1][-1])) D = np.linalg.norm(point - origin) X = data[0][-1] Y = data[1][-1] if any(value == True for value in parameters.get('Curve fitting').values()): m = data[0][-1] / (2 * pi) amp = 20 if parameters.get('Curve fitting').get('Sin'): curve = amp * np.sin(data[0] / m) elif parameters.get('Curve fitting').get('Cos'): curve = amp * np.cos(data[0] / m) - 1 elif parameters.get('Curve fitting').get('Custom'): curve = [] func = parameters.get('Curve fitting').get('Custom func') for _ in data[0] / m: curve.append(eval(func)) curve_fit = cdist([data[1]], [curve], 'sqeuclidean') else: curve_fit = 0 Curvature = degrees(l.curvature[-1]) limb_res = [ round(X, 2), round(Y, 2), round(D, 2), round(Curvature, 2), orient_vector, curve_fit, ] lowest = min(np.array(top_X)[:, sort_by]) highest = max(np.array(top_X)[:, sort_by]) if (lowest < limb_res[sort_by] < highest) or first: lines = [] to_tuple = [(x, y) for x, y in zip(data[0], data[1])] lines.append(LineString(to_tuple)) try: lines.append(lines[0].parallel_offset(1.9, side='left')) except: pass try: lines.append(lines[0].parallel_offset(1.9, side='right')) except: pass for line in lines: if not line.is_simple or line.is_closed: invalid = True if invalid: if descending: D = 0 X = 0 Y = 0 Curvature = 0 else: D = 99999 X = 99999 Y = 99999 Curvature = 99999 limb_res = [ round(X, 2), round(Y, 2), round(D, 2), round(Curvature, 2), orient_vector ] return limb_res
def __init__(self, left, right, heights=None, distance=10, tick_length=50): self.left = left self.right = right self.distance = distance self.tick_length = tick_length if heights is not None: if not isinstance(heights, str): right = right.copy() right["mm_h"] = heights heights = "mm_h" self.heights = right[heights] sindex = right.sindex results_list = [] deviations_list = [] heights_list = [] heights_deviations_list = [] openness_list = [] for idx, row in tqdm(left.iterrows(), total=left.shape[0]): # list to hold all the point coords list_points = [] # set the current distance to place the point current_dist = distance # make shapely MultiLineString object shapely_line = row.geometry # get the total length of the line line_length = shapely_line.length # append the starting coordinate to the list list_points.append(Point(list(shapely_line.coords)[0])) # https://nathanw.net/2012/08/05/generating-chainage-distance-nodes-in-qgis/ # while the current cumulative distance is less than the total length of the line while current_dist < line_length: # use interpolate and increase the current distance list_points.append(shapely_line.interpolate(current_dist)) current_dist += distance # append end coordinate to the list list_points.append(Point(list(shapely_line.coords)[-1])) ticks = [] for num, pt in enumerate(list_points, 1): # start chainage 0 if num == 1: angle = self._getAngle(pt, list_points[num]) line_end_1 = self._getPoint1(pt, angle, tick_length / 2) angle = self._getAngle(line_end_1, pt) line_end_2 = self._getPoint2(line_end_1, angle, tick_length) tick1 = LineString([(line_end_1.x, line_end_1.y), (pt.x, pt.y)]) tick2 = LineString([(line_end_2.x, line_end_2.y), (pt.x, pt.y)]) ticks.append([tick1, tick2]) # everything in between if num < len(list_points) - 1: angle = self._getAngle(pt, list_points[num]) line_end_1 = self._getPoint1( list_points[num], angle, tick_length / 2 ) angle = self._getAngle(line_end_1, list_points[num]) line_end_2 = self._getPoint2(line_end_1, angle, tick_length) tick1 = LineString( [ (line_end_1.x, line_end_1.y), (list_points[num].x, list_points[num].y), ] ) tick2 = LineString( [ (line_end_2.x, line_end_2.y), (list_points[num].x, list_points[num].y), ] ) ticks.append([tick1, tick2]) # end chainage if num == len(list_points): angle = self._getAngle(list_points[num - 2], pt) line_end_1 = self._getPoint1(pt, angle, tick_length / 2) angle = self._getAngle(line_end_1, pt) line_end_2 = self._getPoint2(line_end_1, angle, tick_length) tick1 = LineString([(line_end_1.x, line_end_1.y), (pt.x, pt.y)]) tick2 = LineString([(line_end_2.x, line_end_2.y), (pt.x, pt.y)]) ticks.append([tick1, tick2]) # widths = [] m_heights = [] lefts = [] rights = [] for duo in ticks: for ix, tick in enumerate(duo): possible_intersections_index = list( sindex.intersection(tick.bounds) ) possible_intersections = right.iloc[possible_intersections_index] real_intersections = possible_intersections.intersects(tick) get_height = right.loc[list(real_intersections.index)] possible_int = get_height.exterior.intersection(tick) if not possible_int.is_empty.all(): true_int = [] for one in list(possible_int.index): if possible_int[one].type == "Point": true_int.append(possible_int[one]) elif possible_int[one].type == "MultiPoint": for p in possible_int[one]: true_int.append(p) if len(true_int) > 1: distances = [] ix = 0 for p in true_int: dist = p.distance(Point(tick.coords[-1])) distances.append(dist) ix = ix + 1 minimal = min(distances) if ix == 0: lefts.append(minimal) else: rights.append(minimal) else: if ix == 0: lefts.append( true_int[0].distance(Point(tick.coords[-1])) ) else: rights.append( true_int[0].distance(Point(tick.coords[-1])) ) if heights is not None: indices = {} for idx, row in get_height.iterrows(): dist = row.geometry.distance(Point(tick.coords[-1])) indices[idx] = dist minim = min(indices, key=indices.get) m_heights.append(right.loc[minim][heights]) openness = (len(lefts) + len(rights)) / len(ticks * 2) openness_list.append(1 - openness) if rights and lefts: results_list.append(2 * np.mean(lefts + rights)) deviations_list.append(np.std(lefts + rights)) elif not lefts and rights: results_list.append(2 * np.mean([np.mean(rights), tick_length / 2])) deviations_list.append(np.std(rights)) elif not rights and lefts: results_list.append(2 * np.mean([np.mean(lefts), tick_length / 2])) deviations_list.append(np.std(lefts)) else: results_list.append(tick_length) deviations_list.append(0) if heights is not None: if m_heights: heights_list.append(np.mean(m_heights)) heights_deviations_list.append(np.std(m_heights)) else: heights_list.append(0) heights_deviations_list.append(0) self.w = pd.Series(results_list, index=left.index) self.wd = pd.Series(deviations_list, index=left.index) self.o = pd.Series(openness_list, index=left.index) if heights is not None: self.h = pd.Series(heights_list, index=left.index) self.hd = pd.Series(heights_deviations_list, index=left.index) self.p = self.h / self.w
def plot_limb(limbs): def on_click(event): ax = event.inaxes if ax is None: return if event.button != 1: return if zoomed_axes[0] is None: zoomed_axes[0] = (ax, ax.get_position()) ax.set_position([0.1, 0.1, 0.8, 0.8]) ax.legend(loc='best') ax.get_xaxis().set_visible(True) ax.get_yaxis().set_visible(True) ax.xaxis.set_major_locator(MultipleLocator(5)) ax.grid(linestyle=':') ax.set_ylim(0) ax.margins(x=0, y=-0.25) for axis in event.canvas.figure.axes: if axis is not ax: axis.set_visible(False) else: zoomed_axes[0][0].set_position(zoomed_axes[0][1]) zoomed_axes[0] = None ax.get_legend().remove() ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) for axis in event.canvas.figure.axes: axis.set_visible(True) event.canvas.draw() zoomed_axes = [None] for i in range(len(limbs[0])): if isinstance(limbs[0][i], list): vec_ind = i limbs = np.array(limbs) if len(limbs.shape) > 1: num_plots = len(limbs) limbs = limbs[:, vec_ind] else: num_plots = len(limbs.shape) limbs = [limbs] specs = strategies.SquareStrategy('center').get_grid(num_plots) fig = plt.figure(1, constrained_layout=False) fig.canvas.set_window_title('Top ' + str(num_plots)) for vec, sub in zip(limbs, specs): ax = fig.add_subplot(sub) limb = Limb() limb.build(vec) segs = len(limb.orient) points = np.copy(limb.XY) rots = limb.curvature ax.plot([0, 0], [-2, 2], color='black') if settings.get('Rainbow'): colors = cm.rainbow(np.linspace(0, 1, segs)) """------NORMAL-------""" for i in range(0, segs - 1): ax.plot([i, i + 2], [0, 0], color=colors[i]) """------ACTUATED-------""" for i in range(0, segs - 1): ax.plot(points[0, i:i + 2], points[1, i:i + 2], color=colors[i]) else: """------NORMAL-------""" ''' PLOT UNACTUATED LINE HERE ''' # normal = np.zeros((segs+1)) # ax.plot(normal, color='grey', # label="Initial pressure (P=P" + r'$_i$' + ")") """------ACTUATED-------""" ax.plot(points[0, :], points[1, :], color='red', label="Reduced-order model") if any(value == True for value in parameters.get('Curve fitting').values()): m = points[0][-1] / (2 * pi) if parameters.get('Curve fitting').get('Sin'): curve = 20 * np.sin(points[0] / m) elif parameters.get('Curve fitting').get('Cos'): curve = 25 * np.cos(points[0] / m) - 25 elif parameters.get('Curve fitting').get('Custom'): curve = [] func = parameters.get('Curve fitting').get('Custom func') for _ in points[0] / m: curve.append(eval(func)) ax.plot(points[0], curve, color='black', alpha=0.85, linestyle='--', label='Desired profile') if settings.get('Plot boundaries'): to_tuple = [(x, y) for x, y in zip(limb.XY[0], limb.XY[1])] line_check = LineString(to_tuple) line_top = line_check.parallel_offset(1.9, side='left') line_bottom = line_check.parallel_offset(1.9, side='right') ax.plot(line_top.xy[0], line_top.xy[1]) ax.plot(line_bottom.xy[0], line_bottom.xy[1]) if settings.get('Overlay images'): overlay_images(ax, limb) diff = 20 x_min = min(points[0, :]) - diff x_max = max(points[0, :]) + diff y_min = min(points[1, :]) - diff y_max = max(points[1, :]) + diff ''' THIS SETTING ALLOWS TO FOCUS THE WINDOW ON THE SELECTED SUBPLOT IF Top > 1 ''' # fig.canvas.mpl_connect('button_press_event', on_click) plt.xlim(x_min, x_max) plt.ylim(y_min, y_max) plt.xlabel('X [mm]') plt.ylabel('Y [mm]') ax.xaxis.set_major_locator(MultipleLocator(20)) ax.grid(linestyle=':') figManager = plt.get_current_fig_manager() figManager.window.state('zoomed') ax.legend(loc='lower center', bbox_to_anchor=(0.5, 1)) plt.show()
def add_loops_to_network(G, mst_non_directed, new_mst_nodes, mst_edges, type_mat, pipe_dn): added_a_loop = False # Identify all NONE type nodes in the steiner tree for node_number, node_coords in zip(new_mst_nodes.index, new_mst_nodes['coordinates']): if new_mst_nodes['Type'][node_number] == 'NONE': # find neighbours of nodes in the potential network and steiner network potential_neighbours = G[node_coords] steiner_neighbours = mst_non_directed[node_coords] # check if there are differences, if yes, an edge was deleted here if not set(potential_neighbours.keys()) == set( steiner_neighbours.keys()): new_neighbour_list = [] for a in potential_neighbours.keys(): if a not in steiner_neighbours.keys(): new_neighbour_list.append(a) # check if the node that is additional in the potential network also exists in the steiner network for new_neighbour in new_neighbour_list: if new_neighbour in list( new_mst_nodes['coordinates'].values): # check if it is a none type # write out index of this node node_index = list( new_mst_nodes['coordinates'].values).index( new_neighbour) if new_mst_nodes['Type'][node_index] == 'NONE': # create new edge line = LineString((node_coords, new_neighbour)) if not line in mst_edges['geometry']: mst_edges = mst_edges.append( { "geometry": line, "Pipe_DN": pipe_dn, "Type_mat": type_mat, "Name": "PIPE" + str(mst_edges.Name.count()) }, ignore_index=True) added_a_loop = True mst_edges.reset_index(inplace=True, drop=True) if not added_a_loop: print('No first degree loop added. Trying two nodes apart.') # Identify all NONE type nodes in the steiner tree for node_number, node_coords in zip(new_mst_nodes.index, new_mst_nodes['coordinates']): if new_mst_nodes['Type'][node_number] == 'NONE': # find neighbours of nodes in the potential network and steiner network potential_neighbours = G[node_coords] steiner_neighbours = mst_non_directed[node_coords] # check if there are differences, if yes, an edge was deleted here if not set(potential_neighbours.keys()) == set( steiner_neighbours.keys()): new_neighbour_list = [] for a in potential_neighbours.keys(): if a not in steiner_neighbours.keys(): new_neighbour_list.append(a) # check if the node that is additional in the potential network does not exist in the steiner network for new_neighbour in new_neighbour_list: if new_neighbour not in list( new_mst_nodes['coordinates'].values): # find neighbours of that node second_degree_pot_neigh = list( G[new_neighbour].keys()) for potential_second_deg_neighbour in second_degree_pot_neigh: if potential_second_deg_neighbour in list( new_mst_nodes['coordinates'].values ) and potential_second_deg_neighbour != node_coords: # check if it is a none type # write out index of this node node_index = list( new_mst_nodes['coordinates'].values ).index(potential_second_deg_neighbour) if new_mst_nodes['Type'][ node_index] == 'NONE': # create new edge line = LineString( (node_coords, new_neighbour)) if line not in mst_edges['geometry']: mst_edges = mst_edges.append( { "geometry": line, "Pipe_DN": pipe_dn, "Type_mat": type_mat, "Name": "PIPE" + str(mst_edges.Name.count()) }, ignore_index=True) # Add new node from potential network to steiner tree # create copy of selected node and add to list of all nodes copy_of_new_mst_nodes = new_mst_nodes.copy( ) x_distance = new_neighbour[ 0] - node_coords[0] y_distance = new_neighbour[ 1] - node_coords[1] copy_of_new_mst_nodes.geometry = copy_of_new_mst_nodes.translate( xoff=x_distance, yoff=y_distance) selected_node = copy_of_new_mst_nodes[ copy_of_new_mst_nodes[ "coordinates"] == node_coords] selected_node.loc[:, "Name"] = "NODE" + str( new_mst_nodes. Name.count()) selected_node.loc[:, "Type"] = "NONE" selected_node[ "coordinates"] = selected_node.geometry.values[ 0].coords if selected_node[ "coordinates"].values not in new_mst_nodes[ "coordinates"].values: new_mst_nodes = new_mst_nodes.append( selected_node) new_mst_nodes.reset_index(inplace=True, drop=True) line2 = LineString( (new_neighbour, potential_second_deg_neighbour)) if line2 not in mst_edges['geometry']: mst_edges = mst_edges.append( { "geometry": line2, "Pipe_DN": pipe_dn, "Type_mat": type_mat, "Name": "PIPE" + str(mst_edges.Name.count()) }, ignore_index=True) added_a_loop = True mst_edges.reset_index(inplace=True, drop=True) if not added_a_loop: print('No loops added.') return mst_edges, new_mst_nodes
# to cross each road segment by dividing the length of the road segment with the speed limit and calculate the optimal routes by # taking into account the speed limits as well that might alter the result especially on longer trips than here. # Saving shortest paths to disk # ----------------------------- # Quite often you need to save the route e.g. as a Shapefile. # Hence, let's continue still a bit and see how we can make a Shapefile of our route with some information associated with it. # First we need to get the nodes that belong to the shortest path. route_nodes = nodes_proj.loc[route] print(route_nodes) # Now we can create a LineString out of the Point geometries of the nodes from shapely.geometry import LineString, Point route_line = LineString(list(route_nodes.geometry.values)) print(route_line) # Let's make a GeoDataFrame having some useful information about our route such as a list of the osmids that are part of the route and the length of the route. route_geom = gpd.GeoDataFrame(crs=edges_proj.crs) route_geom['geometry'] = None route_geom['osmids'] = None # Let's add the information: geometry, a list of osmids and the length of the route. route_geom.loc[0, 'geometry'] = route_line route_geom.loc[0, 'osmids'] = str(list(route_nodes['osmid'].values)) route_geom['length_m'] = route_geom.length # Now we have a GeoDataFrame that we can save to disk. Let's still confirm that everything is okey by plotting our route # on top of our street network, and plot also the origin and target points on top of our map.
def test_from_single_coordinate(): """Test for issue #486""" coords = [[-122.185933073564, 37.3629353839073]] with pytest.raises(ValueError): ls = LineString(coords) ls.geom_type # caused segfault before fix
def test_linestring(): g = LineString([(1, 2), (3, 4)]) assert hash(g) == hash(LineString([(1, 2), (3, 4)])) assert hash(g) != hash(LineString([(1, 2), (3, 3)]))
def test_from_coordinate_sequence_3D(): line = LineString(((1.0, 2.0, 3.0), (3.0, 4.0, 5.0))) assert line.has_z assert line.coords[:] == [(1.0, 2.0, 3.0), (3.0, 4.0, 5.0)]
def create(vehicle_id, start_date, end_date): csv.field_size_limit(1000000000) connection = pymysql.connect(host='000.000.000.00', user='******', password='******', db='database', charset='utf8mb4', cursorclass=pymysql.cursors.SSDictCursor) cur = connection.cursor() # execute a select query and return results as a generator def generator(stmt): # error handling code removed cur.execute(stmt) for row in cur: yield row sql = "select latitude, longitude from ngp.hist_trackrecords where device_id='%s' and reportstamp between '%s' and '%s'" % ( vehicle_id, start_date, end_date) pts = set() for l in generator(sql): pts.add(str(Point(l['longitude'], l['latitude']))) connection.close() point_list = list(pts) road = open('roads.csv') read = csv.reader(road) for j in read: m = loads(j[0]) line_list = [] c = 0 for r in point_list: if c != (len(point_list) - 1): line = LineString([ m.interpolate(m.project(loads(r))), m.interpolate(m.project(loads(point_list[c + 1]))) ]) line_list.append(line) c += 1 ml = MultiLineString(line_list) geom = ogr.CreateGeometryFromWkt(str(ml)) length = int(geom.Length()) bml_in = str(ml.buffer(.0001)) cut = re.split(r'[()]', bml_in) cut2 = re.split(r'[,]', cut[2]) nodes = [] if cut2 == [''] or len(cut2) < 3: pass else: for coords in cut2: cut3 = re.split(r'[ ]', coords) retype = float(cut3[1]), float(cut3[0]) nodes.append(tuple(retype)) bml_out = Polygon(nodes) return bml_out, length
def test_linestring_mutability_deprecated(): line = LineString(((1.0, 2.0), (3.0, 4.0))) with pytest.warns(ShapelyDeprecationWarning, match="Setting"): line.coords = ((-1.0, -1.0), (1.0, 1.0))
def main(): #-- Read the system arguments listed after the program long_options = [ 'subdir=', 'method=', 'step=', 'indir=', 'interval=', 'buffer=', 'manual' ] optlist, arglist = getopt.getopt(sys.argv[1:], '=D:M:S:I:V:B:m:', long_options) subdir = 'all_data2_test' method = '' step = 50 n_interval = 1000 buffer_size = 500 indir = '' set_manual = False for opt, arg in optlist: if opt in ('-D', '--subdir'): subdir = arg elif opt in ('-M', '--method'): method = arg elif opt in ('-S', '--step'): step = np.int(arg) elif opt in ('-V', '--interval'): n_interval = np.int(arg) elif opt in ('-B', '--buffer'): buffer_size = np.int(arg) elif opt in ('-I', '--indir'): indir = os.path.expanduser(arg) elif opt in ('-m', '--manual'): set_manual = True #-- directory setup #- current directory current_dir = os.path.dirname(os.path.realpath(__file__)) headDirectory = os.path.join(current_dir, '..', 'FrontLearning_data') glaciersFolder = os.path.join(headDirectory, 'Glaciers') results_dir = os.path.join(headDirectory, 'Results', subdir) #-- if user input not given, set label folder #-- else if input directory is given, then set the method based on that if indir == '': indir = os.path.join(results_dir, method, method) else: method = os.path.basename(indir) if method == '': sys.exit("Please do not put '/' at the end of indir.") print('input directory ONLY for NN output:%s' % indir) print('METHOD:%s' % method) #-- make histohtam filder if it doesn't exist histFolder = os.path.join(results_dir, 'Histograms') if (not os.path.isdir(histFolder)): os.mkdir(histFolder) outputFolder = os.path.join( histFolder, method + '_' + str(step) + '_%isegs' % n_interval + '_%ibuffer' % buffer_size) #-- make output folders if (not os.path.isdir(outputFolder)): os.mkdir(outputFolder) if set_manual: datasets = ['NN', 'Sobel', 'Manual'] else: datasets = ['NN', 'Sobel'] print(datasets) pixelFolder = {} frontFolder = {} pixelFolder['NN'] = os.path.join(results_dir, method, method + ' Pixel CSVs ' + str(step)) pixelFolder['Sobel'] = os.path.join(results_dir, 'Sobel/Sobel Pixel CSVs ' + str(step)) if 'Manual' in datasets: pixelFolder['Manual'] = os.path.join( results_dir, 'output_handrawn/output_handrawn Pixel CSVs ' + str(step)) frontFolder['NN'] = os.path.join(results_dir, method, method + ' Geo CSVs ' + str(step)) frontFolder['Sobel'] = os.path.join(results_dir, 'Sobel/Sobel Geo CSVs ' + str(step)) if 'Manual' in datasets: frontFolder['Manual'] = os.path.join( results_dir, 'output_handrawn/output_handrawn Geo CSVs ' + str(step)) def seriesToNPoints(series, N): #find the total length of the series totalDistance = 0 for s in range(len(series[:, 0]) - 1): totalDistance += ((series[s, 0] - series[s + 1, 0])**2 + (series[s, 1] - series[s + 1, 1])**2)**0.5 intervalDistance = totalDistance / (N - 1) #make the list of points newSeries = series[0, :] currentS = 0 currentPoint1 = series[currentS, :] currentPoint2 = series[currentS + 1, :] for p in range(N - 2): distanceAccrued = 0 while distanceAccrued < intervalDistance: currentLineDistance = ( (currentPoint1[0] - currentPoint2[0])**2 + (currentPoint1[1] - currentPoint2[1])**2)**0.5 if currentLineDistance < intervalDistance - distanceAccrued: distanceAccrued += currentLineDistance currentS += 1 currentPoint1 = series[currentS, :] currentPoint2 = series[currentS + 1, :] else: distance = intervalDistance - distanceAccrued newX = currentPoint1[0] + ( distance / currentLineDistance) * (currentPoint2[0] - currentPoint1[0]) newY = currentPoint1[1] + ( distance / currentLineDistance) * (currentPoint2[1] - currentPoint1[1]) distanceAccrued = intervalDistance + 1 newSeries = np.vstack([newSeries, np.array([newX, newY])]) currentPoint1 = np.array([newX, newY]) newSeries = np.vstack([newSeries, series[-1, :]]) return (newSeries) def frontComparisonErrors(front1, front2): errors = [] polygon_points = [ ] #creates a empty list where we will append the points to create the polygon for x, y in zip(front1[:, 0], front1[:, 1]): polygon_points.append([x, y]) for x, y in zip(front2[::-1, 0], front2[::-1, 1]): polygon_points.append([x, y]) #-- close the polygon polygon_points.append([front1[0, 0], front1[0, 1]]) polygon = Polygon(polygon_points) area = polygon.area #-- get length of true line length = 0 for ff in range(1, len(front1)): length += ((front1[ff,0]-front1[ff-1,0])**2+\ (front1[ff,1]-front1[ff-1,1])**2)**0.5 errors = area / length return ([errors]) def rmsError(error): return (np.sqrt(np.mean(np.square(error)))) def generateLabelList(labelFolder): labelList = [] for fil in os.listdir(labelFolder): # if fil[-6:] == 'B8.png' or fil[-6:] == 'B2.png': # labelList.append(fil[:-4]) if fil.endswith('_nothreshold.png'): labelList.append(fil.replace('_nothreshold.png', '')) return (labelList) # get glacier names def getGlacierList(labelList): f = open(os.path.join(glaciersFolder, 'Scene_Glacier_Dictionary.csv'), 'r') lines = f.read() f.close() lines = lines.split('\n') glacierList = [] for sceneID in labelList: for line in lines: line = line.split(',') if line[0] == sceneID: glacierList.append(line[1]) return (glacierList) #code to get the list of fronts and their images def getFrontList(glacierList, labelList): frontsList = [] for ind, label in enumerate(labelList): glacier = glacierList[ind] f = open( os.path.join(glaciersFolder, glacier, '%s Image Data.csv' % glacier), 'r') lines = f.read() f.close() lines = lines.split('\n') for line in lines: line = line.split(',') if line[1][:-4] == label: frontsList.append(line[0]) return (frontsList) def fjordBoundaryIndices(glacier): boundary1file = os.path.join(glaciersFolder, glacier, 'Fjord Boundaries', glacier + ' Boundary 1 V2.csv') boundary1 = np.genfromtxt(boundary1file, delimiter=',') boundary2file = os.path.join(glaciersFolder, glacier, 'Fjord Boundaries', glacier + ' Boundary 2 V2.csv') boundary2 = np.genfromtxt(boundary2file, delimiter=',') boundary1 = seriesToNPoints(boundary1, 1000) boundary2 = seriesToNPoints(boundary2, 1000) return (boundary1, boundary2) labelList = generateLabelList(indir) glacierList = getGlacierList(labelList) frontList = getFrontList(glacierList, labelList) allerrors = {} allerrors['NN'] = [] allerrors['Sobel'] = [] allerrors['Manual'] = [] N = 1 N = len(labelList) for ll in range(N): glacier = glacierList[ll] label = labelList[ll] trueFrontFile = frontList[ll] print(label) ############################################################################ # This section to get the front images trueImageFolder = os.path.join(headDirectory, 'Glaciers', glacier, 'Small Images') trueImage = Image.open( os.path.join(trueImageFolder, label + '_Subset.png')).transpose( Image.FLIP_LEFT_RIGHT).convert("L") frontImageFolder = {} frontImageFolder['NN'] = indir frontImageFolder['Sobel'] = os.path.join(results_dir, 'Sobel/Sobel') if 'Manual' in datasets: frontImageFolder['Manual'] = os.path.join(os.path.dirname(indir), 'output_handrawn') frontImage = {} pixels = {} for d, tl in zip(datasets, ['_nothreshold', '', '_nothreshold']): frontImage[d] = Image.open(os.path.join(frontImageFolder[d],label \ + '%s.png'%tl)).transpose(Image.FLIP_LEFT_RIGHT).convert("L") ############################################################################ # This section to get the front pixels # get the front pixelsFile = glacier + ' ' + label + ' Pixels.csv' pixels[d] = np.genfromtxt(os.path.join(pixelFolder[d], pixelsFile), delimiter=',') pixels[d] = seriesToNPoints(pixels[d], n_interval) ############################################################################ # Get the fjord boundaries for the current glacier bounds = {} bounds[1], bounds[2] = fjordBoundaryIndices(glacier) buff = {} for i in [1, 2]: # Form buffer around boundary lineStringSet = bounds[i] line = LineString(lineStringSet) buff[i] = line.buffer(buffer_size) ############################################################################ # This section to get the front data #get the true front trueFrontFolder = os.path.join(glaciersFolder, glacier, 'Front Locations', '3413') trueFront = np.genfromtxt(trueFrontFolder + '/' + trueFrontFile, delimiter=',') #-- make sure all fronts go in the same direction #-- if the x axis is not in increasng order, reverse if trueFront[0, 0] > trueFront[-1, 0] and glacier != 'Helheim': print('flipped true front.') trueFront = trueFront[::-1, :] trueFront = seriesToNPoints(trueFront, n_interval) #-- get rid of poitns too close to the edges l1 = LineString(trueFront) int1 = l1.difference(buff[1]) int2 = int1.difference(buff[2]) try: trueFront = np.array(shape(int2).coords) except: lengths = [ len(np.array(shape(int2)[i].coords)) for i in range(len(shape(int2))) ] max_ind = np.argmax(lengths) trueFront = np.array(shape(int2)[max_ind].coords) #-- testing print(lengths) print(lengths[max_ind]) #-- rebreak into n_interval segments trueFront = seriesToNPoints(trueFront, n_interval) front = {} errors = {} for d in datasets: #get the front frontFile = glacier + ' ' + label + ' Profile.csv' temp_front = np.genfromtxt(os.path.join(frontFolder[d], frontFile), delimiter=',') #-- make sure all fronts go in the same direction #-- if the x axis is not in increasng order, reverse #if temp_front[0,0] > temp_front[-1,0]: # print('flipped %s'%d) # temp_front = temp_front[::-1,:] front[d] = seriesToNPoints(temp_front, n_interval) #-- get rid of points to close to the edges #-- get rid of poitns too close to the edges l1 = LineString(front[d]) int1 = l1.difference(buff[1]) int2 = int1.difference(buff[2]) try: front[d] = np.array(shape(int2).coords) except: lengths = [ len(np.array(shape(int2)[i].coords)) for i in range(len(shape(int2))) ] max_ind = np.argmax(lengths) front[d] = np.array(shape(int2)[max_ind].coords) #-- testing print(lengths) print(lengths[max_ind]) #-- rebreak into n_interval segments front[d] = seriesToNPoints(front[d], n_interval) errors[d] = frontComparisonErrors(trueFront, front[d]) for error in errors[d]: allerrors[d].append(error) frontXmin = np.min( np.concatenate(([np.min(trueFront[:, 0])], [np.min(front[d][:, 0]) for d in datasets]))) frontXmax = np.max( np.concatenate(([np.max(trueFront[:, 0])], [np.max(front[d][:, 0]) for d in datasets]))) frontYmin = np.min( np.concatenate(([np.min(trueFront[:, 1])], [np.min(front[d][:, 1]) for d in datasets]))) frontYmax = np.max( np.concatenate(([np.max(trueFront[:, 1])], [np.max(front[d][:, 1]) for d in datasets]))) fig = plt.figure(figsize=(10, 8)) n_panels = len(front) + 1 plt.subplot(2, n_panels, 1) plt.imshow(trueImage, cmap='gray') plt.gca().set_xlim([0, 200]) plt.gca().set_ylim([300, 0]) plt.gca().axes.get_xaxis().set_ticks([]) plt.gca().axes.get_yaxis().set_ticks([]) plt.title('Original Image', fontsize=12) p = 2 for d in datasets: plt.subplot(2, n_panels, p) plt.imshow(frontImage[d], cmap='gray') plt.plot(pixels[d][:, 0], pixels[d][:, 1], 'y-', linewidth=3) plt.gca().set_xlim([0, 200]) plt.gca().set_ylim([300, 0]) plt.gca().axes.get_xaxis().set_ticks([]) plt.gca().axes.get_yaxis().set_ticks([]) plt.title('%s Solution' % d, fontsize=12) p += 1 plt.subplot(2, n_panels, p) plt.title('Geocoded Solutions', fontsize=12) plt.ylabel('Northing (km)', fontsize=12) plt.xlabel('Easting (km)', fontsize=12) plt.plot(trueFront[:, 0] / 1000, trueFront[:, 1] / 1000, 'k-', label='True') for d, c in zip(datasets, ['b-', 'g-', 'r-']): plt.plot(front[d][:, 0] / 1000, front[d][:, 1] / 1000, c, label=d) plt.gca().set_xlim([frontXmin / 1000, frontXmax / 1000]) plt.gca().set_ylim([frontYmin / 1000, frontYmax / 1000]) plt.gca().set_xticks([frontXmin / 1000, frontXmax / 1000]) plt.gca().set_yticks([frontYmin / 1000, frontYmax / 1000]) plt.legend(loc=0) p += 1 p_temp = copy.copy(p) x = {} y = {} for d, c in zip(datasets, ['b', 'g', 'r']): plt.subplot(2, n_panels, p) plt.title('%s Errors Histogram' % d, fontsize=12) bins = range(0, 5000, 100) y[d], x[d], _ = plt.hist(errors[d], alpha=0.5, color=c, bins=bins, label='NN') #plt.xlabel('RMS Error = '+'{0:.2f}'.format(rmsError(errors[d]))+' m',fontsize=12) plt.xlabel('Mean Diff. = ' + '{0:.2f}'.format(np.mean(np.abs(errors[d]))) + ' m', fontsize=12) p += 1 #-- set histogram bounds for d in datasets: plt.subplot(2, n_panels, p_temp) plt.gca().set_ylim([0, np.max([y[d] for d in datasets])]) plt.gca().set_xlim([0, np.max([x[d] for d in datasets])]) p_temp += 1 plt.savefig(os.path.join(outputFolder, label + '_AREA.png'), bbox_inches='tight') plt.close(fig) fig = plt.figure(figsize=(11, 4)) x = {} y = {} for i, d, c, lbl in zip(range(len(datasets)), datasets, ['b', 'g', 'r'], ['e', 'f', 'g']): plt.subplot(1, len(datasets), i + 1) plt.title(r"$\bf{%s)}$" % lbl + " %s Error Histogram" % d, fontsize=12) bins = range(0, 5000, 100) y[d], x[d], _ = plt.hist(allerrors[d], alpha=0.5, color=c, bins=bins, label=d) #plt.xlabel('RMS Error = '+'{0:.2f}'.format(rmsError(allerrors[d]))+' m',fontsize=12) plt.xlabel('Mean Difference = ' + '{0:.2f}'.format(np.mean(np.abs(allerrors[d]))) + ' m', fontsize=12) if i == 0: plt.ylabel('Count (100 m bins)', fontsize=12) for i in range(len(datasets)): plt.subplot(1, len(datasets), i + 1) plt.gca().set_ylim([0, np.max([y[d] for d in datasets])]) plt.gca().set_xlim([0, np.max([x[d] for d in datasets])]) plt.savefig(os.path.join(results_dir,\ 'Figure_4_AREA_'+'_'.join(method.split())+'_'+str(step)+'_%isegs'%n_interval+'_%ibuffer'%buffer_size+'.pdf'),bbox_inches='tight') plt.close()
def test_linestring_array_interface_deprecated(): line = LineString(((1.0, 2.0), (3.0, 4.0))) with pytest.warns(ShapelyDeprecationWarning, match="array_interface"): line.array_interface()
def nodes_to_linestring(path): coords_list = [(G.nodes[i]['x'], G.nodes[i]['y']) for i in path] line = LineString(coords_list) return (line)
def test_from_mix(): # From mix of tuples and Points line = LineString((Point(1.0, 2.0), (2.0, 3.0), Point(3.0, 4.0))) assert line.coords[:] == [(1.0, 2.0), (2.0, 3.0), (3.0, 4.0)]
def repair(self, network): try: l.warning('REPAIR: Join attempt a Repair') # Enable plotting with a flag # RepairTestSuiteGenerator.plot(network, 'broken') # We move the broken road around such that its starting point is on the border and we get largest map coverage # (note we use the bbox instead of the actual road polygons) # import matplotlib.pyplot as plt # plt.figure('x-ray') # plt.cla() # self.plot_network_segments_and_bounding_box(network) # First rank the edges and then explore the best one x, y = network.bounds.exterior.coords[0] x = math.fabs(x) y = math.fabs(y) edges = [ # N [(-x, +y), (+x, +y)], # E [(+x, -y), (+x, +y)], # S [(-x, -y), (+x, -y)], # W [(-x, -y), (-x, +y)] ] # In some occasions compute_overlap_area_at triggers an exception. We capture it and fail the repair # attempt instead of breaking AsFault max_area = -1 best_edge = None for edge in edges: edge_mid_point = Point((edge[0][0] + edge[1][0]) / 2.0, (edge[0][1] + edge[1][1]) / 2.0) area = self.compute_overlap_area_at(edge_mid_point, network) if area > max_area: max_area = area best_edge = edge # At this point we do a simple linear search over the edge to identify where we should place the road # starting point to maximize the area if best_edge[0][0] == best_edge[1][0]: # if X are the same, then we lin space over Y target_points = [ Point(best_edge[0][0], y) for y in np.linspace(best_edge[0][1], best_edge[1][1], 10) ] else: # if Y are the same, then we lin space over X target_points = [ Point(x, best_edge[0][1]) for x in np.linspace(best_edge[0][0], best_edge[1][0], 10) ] best_location = None max_area = -1 for target_point in target_points: area = self.compute_overlap_area_at(target_point, network) if area > max_area: max_area = area best_location = target_point # At this point the road starts from a boundary, we need to check whether the road must grow or shrink # First we move the road to the target point ensuring that the root is slightly outside the map so cars will # be completely inside the road when tests start # Assumption: Road has ONLY one street so there's only one root root_node = list(network.get_roots())[0] # 0 deg is (0,1) not (1,0) ! seg = LineString([(0, 0), (0, BOUNDARY_OVERLAP)]) # Rotate it by the angle (degree) defined by root but in the opposite direction +180 seg = rotate(seg, root_node.angle + 180, origin=Point(0, 0), use_radians=False) # Translate the segment in the best location seg = translate(seg, xoff=best_location.x, yoff=best_location.y) # Now move the root node into the new location root_node.x_off = seg.coords[1][0] root_node.y_off = seg.coords[1][1] # Recompute the polygons of the entire road network.update_abs(force=True) # TODO Enable with a flag # RepairTestSuiteGenerator.plot(network, 'half-repaired') # Check how many segments in the road touch the boundary boundary_crossing_segments = len( network.get_boundary_intersecting_nodes()) # This should never happen since we have just moved the road on the border... assert boundary_crossing_segments > 0, "Something wrong happened, the translated road does not touch " \ "any border ?!" if boundary_crossing_segments == 1: # We need to use a generator to grow and shrink the road as it has all the methods already available repair_generator = RepairRoadGenerator(network.bounds, randint(10000)) repair_generator.network = network # Assume we have only one road bestNode = list(network.get_roots())[0] repair_generator.root = bestNode counter = 0 while repair_generator.grow( ) != repair_generator.done and counter < 10: counter += 1 # Is this really necessay?! network = repair_generator.network else: repair_generator = RepairRoadGenerator(network.bounds, randint(10000)) repair_generator.network = network bestNode = list(network.get_roots())[0] repair_generator.root = bestNode repair_generator.trim() # Is this really necessay?! network = repair_generator.network # TODO Enable with a flag # This might be broken # RepairTestSuiteGenerator.plot(network, 'repaired') # # plt.figure('repaired-x-ray') # plt.cla() # self.plot_network_segments_and_bounding_box(network) # Check that all the other properties of valid networks hold network.update_abs(force=True) # Not sure if force makes a difference if network.complete_is_consistent(): l.warning("REPAIR: Join Repair worked") return network else: l.warning("REPAIR: Join Repair failed") return None except: # Catch-all clause l.warning("REPAIR: Join Repair failed with exception", sys.exc_info()[0]) return None