def route_analysis_map(route_num, shapefile, rasterfile): """ input the number of route, then output an interactive map showing the route and road grade. Also will save the route as shapefile named 'route_shp'. Parameters ---------- route_num: desired route number (integer) shapefile: route geospatial data (.shp file) rasterfile: elevation data file (.tif) Returns ------- map_display: interactive map for desired route """ route_shp = base.read_shape(shapefile, route_num) linestring_route_df = base.extract_point_df(route_shp) elevation, elevation_gradient, route_cum_distance, distance = base.gradient(route_shp, rasterfile) gdf_route = base.make_multi_lines( linestring_route_df, elevation_gradient) map_display = base.route_map(gdf_route) return map_display
def route_analysis_df(route_num, shapefile, rasterfile): """ input the number of route, then output a GeoDataFrame with gradient and geometry information of that route, and elevation_gradient for each line segment. Also will save the route as shapefile named 'route_shp'. Parameters ---------- route_num: desired route number (integer) shapefile: route geospatial data (.shp file) rasterfile: elevation data file (.tif) Returns ------- gdf_route: geodataframe with columns ['gradient', 'geometry'] """ route_shp = base.read_shape(shapefile, route_num) linestring_route_df = base.extract_point_df(route_shp) elevation, elevation_gradient, route_cum_distance, distance = base.gradient(route_shp, rasterfile) gdf_route = base.make_multi_lines( linestring_route_df, elevation_gradient) return gdf_route
def route_analysis_all(route_num, shapefile, rasterfile): """ input the number of route, then output an interactive map of the route, elevation and road grade profiles, and metrics calculated for the route. Also will save the route as shapefile named 'route_shp'. Parameters ---------- route_num: Desired route number (integer) shapefile: route geospatial data (.shp file) rasterfile: elevation data file (.tif) Returns ------- map_display: interactive map for desired route route_plot: elevation and grade profiles for desired route display_metrics: results of metrics calculations """ route_shp = base.read_shape(shapefile, route_num) linestring_route_df = base.extract_point_df(route_shp) elevation, elevation_gradient, route_cum_distance, distance = base.gradient(route_shp, rasterfile) gdf_route = base.make_multi_lines( linestring_route_df, elevation_gradient) map_display = base.route_map(gdf_route) route_plot = base.profile_plot(elevation, elevation_gradient, route_cum_distance, route_num) display_metrics, _ = base.route_metrics(elevation, elevation_gradient, route_cum_distance, distance, route_num) return map_display, route_plot, display_metrics
def route_analysis_profile(route_num, shapefile, rasterfile): """ input the number of route, then output elevation and road grade profiles. Also will save the route as shapefile named 'route_shp'. Parameters ---------- route_num: desired route number (integer) shapefile: route geospatial data (.shp file) rasterfile: elevation data file (.tif) Returns ------- route_plot: elevation and grade profiles for desired route """ route_shp = base.read_shape(shapefile, route_num) linestring_route_df = base.extract_point_df(route_shp) elevation, elevation_gradient, route_cum_distance, distance = base.gradient(route_shp, rasterfile) gdf_route = base.make_multi_lines( linestring_route_df, elevation_gradient) route_plot = base.profile_plot(elevation, elevation_gradient, route_cum_distance, route_num) return route_plot
def test_make_multi_lines(): """Test if all gradient data are float64 type.""" linestring_route_df = base.extract_point_df(route_shp) _, elevation_gradient, _, _ = base.gradient(route_shp, rasterfile) gdf_route = base.make_multi_lines(linestring_route_df, elevation_gradient) assert gdf_route[ 'gradient'].dtype == 'float64', 'Gradient columns should only contain number with float64 dtype.' return
def test_gradient(): """Test if the elevation data convert to meter metric and gradient data have the right length.""" elevation_meters, route_gradient, route_cum_distance, route_distance = base.gradient( route_shp, rasterfile) assert elevation_meters.max( ) < 104, 'elevation should convert to meter metric.' assert len( route_gradient) == 208, 'length of gradient values should be 208.' return
def test_route_metrics(): """Test values of metrics are whether valid.""" elevation_meters, route_gradient, route_cum_distance, route_distance = base.gradient( route_shp, rasterfile) _, metrics = base.route_metrics(elevation_meters, route_gradient, route_cum_distance, route_distance, 45) for idx in range(len(metrics)): assert metrics[idx] >= 0, 'Values of ranking should greater than 0.' return
def test_profile_plot(): """Test if input data contain nan values.""" _, route_gradient, route_cum_distance, _ = base.gradient( route_shp, rasterfile) if np.isnan(route_cum_distance).any() or np.isnan( route_gradient).any() or np.isnan(route_cum_distance).any(): raise ValueError( 'Check the source. Array should not contain nan value.') else: pass return
def test_route_map(): """Test if geodataframe contain null values.""" linestring_route_df = base.extract_point_df(route_shp) _, elevation_gradient, _, _ = base.gradient(route_shp, rasterfile) gdf_route = base.make_multi_lines(linestring_route_df, elevation_gradient) if gdf_route.isnull().values.all(): raise ValueError( 'GeoDataFrame has some null value, check the sources.') else: pass return
def routes_analysis_ranking(route_list, shapefile, rasterfile): """ Computes the four chosen metrics values for each bus routes in route_list and display them on a bar plot for ease of comparison Parameters ---------- route_list: A list of bus routes to be compared (Integers) shapefile: route geospatial data (.shp file) rasterfile: elevation data file (.tif) Returns ------- bar plot: showing results comparison between bus routes according to the four metrics chosen """ num_route = len(route_list) metrics_1 = [0] * num_route metrics_2 = [0] * num_route metrics_3 = [0] * num_route metrics_4 = [0] * num_route for idx, route_num in enumerate(route_list): route_shp = base.read_shape(shapefile, route_num) elevation, elevation_gradient, route_cum_distance, distance = base.gradient( route_shp, rasterfile) _, metrics = base.route_metrics(elevation, elevation_gradient, route_cum_distance, distance, route_num) metrics_1[idx], metrics_2[idx], metrics_3[idx], metrics_4[ idx] = metrics data = pd.DataFrame({ 'Bus Num': route_list, 'M1': metrics_1, 'M2': metrics_2, 'M3': metrics_3, 'M4': metrics_4 }) ax = data.plot.bar('Bus Num', figsize=[14, 5], fontsize=20) ax.set_ylabel('Metrics', size=20) ax.set_xlabel('Bus Number', size=20) return ax
def route_analysis_metrics(route_num, shapefile, rasterfile): """ input the number of route, then output the metrics calculated for that route. Also will save the route as shapefile named 'route_shp'. Parameters ---------- route_num: Desired route number (integer) shapefile: route geospatial data (.shp file) rasterfile: elevation data file (.tif) Returns ------- display_metrics: results of metrics calculations """ route_shp = base.read_shape(shapefile, route_num) linestring_route_df = base.extract_point_df(route_shp) elevation, elevation_gradient, route_cum_distance, distance = base.gradient(route_shp, rasterfile) display_metrics, _ = base.route_metrics(elevation, elevation_gradient, route_cum_distance, distance, route_num) return display_metrics
def __init__(self, f, x0, ranges=None, df=None, h=0.1, emax=1e-5, imax=1000): ''' Initializes the optimizer. To create an optimizer of this type, instantiate the class with the parameters given below: :Parameters: f A multivariable function to be optimized. The function should have only one parameter, a multidimensional line-vector, and return the function value, a scalar. x0 First estimate of the minimum. Estimates can be given in any format, but internally they are converted to a one-dimension vector, where each component corresponds to the estimate of that particular variable. The vector is computed by flattening the array. ranges A range of values might be passed to the algorithm, but it is not necessary. If supplied, this parameter should be a list of ranges for each variable of the objective function. It is specified as a list of tuples of two values, ``(x0, x1)``, where ``x0`` is the start of the interval, and ``x1`` its end. Obviously, ``x0`` should be smaller than ``x1``. It can also be given as a list with a simple tuple in the same format. In that case, the same range will be applied for every variable in the optimization. df A function to calculate the gradient vector of the cost function ``f``. Defaults to ``None``, if no gradient is supplied, then it is estimated from the cost function using Euler equations. h Convergence step. This method does not takes into consideration the possibility of varying the convergence step, to avoid Stiefel cages. emax Maximum allowed error. The algorithm stops as soon as the error is below this level. The error is absolute. imax Maximum number of iterations, the algorithm stops as soon this number of iterations are executed, no matter what the error is at the moment. ''' Optimizer.__init__(self) self.__f = f self.__x = array(x0).ravel() if df is None: self.__df = gradient(f) else: self.__df = df self.__B = inv(hessian(self.__f)(self.x)) self.__h = h # Determine ranges of the variables if ranges is not None: ranges = list(ranges) if len(ranges) == 1: ranges = array(ranges * len(x0[0])) else: ranges = array(ranges) self.ranges = ranges '''Holds the ranges for every variable. Although it is a writable property, care should be taken in changing parameters before ending the convergence.''' self.__emax = float(emax) self.__imax = int(imax)