From 3ac0d4c386e185852573209c5bf147a693ec7d87 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Wed, 4 Dec 2024 13:46:14 -0300 Subject: [PATCH 01/34] add new files --- .../add_links_from_layer.py | 179 ++++++++++++ .../add_matrix_from_layer.py | 196 ++++++++++++++ .../assign_pt_from_yaml.py | 167 ++++++++++++ ...om_yaml.py => assign_traffic_from_yaml.py} | 112 +++++--- ...m_layer.py => create_matrix_from_layer.py} | 16 +- .../processing_provider/create_pt_graph.py | 120 +++++++++ .../processing_provider/export_matrix.py | 36 ++- .../modules/processing_provider/group_i18n.py | 0 .../processing_provider/import_gtfs.py | 114 ++++++++ .../processing_provider/matrix_calculator.py | 254 ++++++++++++++++++ .../processing_provider/project_from_OSM.py | 80 ++++++ .../processing_provider/project_from_layer.py | 64 +++-- .../modules/processing_provider/provider.py | 26 +- .../renumber_nodes_from_layer.py | 6 +- 14 files changed, 1271 insertions(+), 99 deletions(-) create mode 100644 qaequilibrae/modules/processing_provider/add_links_from_layer.py create mode 100644 qaequilibrae/modules/processing_provider/add_matrix_from_layer.py create mode 100644 qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py rename qaequilibrae/modules/processing_provider/{assign_from_yaml.py => assign_traffic_from_yaml.py} (60%) rename qaequilibrae/modules/processing_provider/{matrix_from_layer.py => create_matrix_from_layer.py} (94%) create mode 100644 qaequilibrae/modules/processing_provider/create_pt_graph.py create mode 100644 qaequilibrae/modules/processing_provider/group_i18n.py create mode 100644 qaequilibrae/modules/processing_provider/import_gtfs.py create mode 100644 qaequilibrae/modules/processing_provider/matrix_calculator.py create mode 100644 qaequilibrae/modules/processing_provider/project_from_OSM.py diff --git a/qaequilibrae/modules/processing_provider/add_links_from_layer.py b/qaequilibrae/modules/processing_provider/add_links_from_layer.py new file mode 100644 index 00000000..1a960aa3 --- /dev/null +++ b/qaequilibrae/modules/processing_provider/add_links_from_layer.py @@ -0,0 +1,179 @@ +import importlib.util as iutil +import pandas as pd +import sys +from os.path import join +from string import ascii_lowercase + +from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProcessingAlgorithm +from qgis.core import QgsProcessing, QgsProcessingMultiStepFeedback, QgsProcessingParameterVectorLayer +from qgis.core import QgsProcessingParameterField, QgsProcessingParameterFile, QgsProcessingParameterString +from qgis.core import QgsProject, QgsFeature, QgsVectorLayer, QgsDataSourceUri + +from qaequilibrae.modules.common_tools import standard_path +from qaequilibrae.i18n.translate import trlt + + +class AddLinksFromLayer(QgsProcessingAlgorithm): + + def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterVectorLayer( + "links", self.tr("Links"), types=[QgsProcessing.TypeVectorLine], defaultValue=None + ) + ) + self.addParameter( + QgsProcessingParameterField( + "link_type", + self.tr("Link type"), + type=QgsProcessingParameterField.String, + parentLayerParameterName="links", + allowMultiple=False, + defaultValue="link_type", + ) + ) + self.addParameter( + QgsProcessingParameterField( + "direction", + self.tr("Direction"), + type=QgsProcessingParameterField.Numeric, + parentLayerParameterName="links", + allowMultiple=False, + defaultValue="direction", + ) + ) + self.addParameter( + QgsProcessingParameterField( + "modes", + self.tr("Modes"), + type=QgsProcessingParameterField.String, + parentLayerParameterName="links", + allowMultiple=False, + defaultValue="modes", + ) + ) + self.addParameter( + QgsProcessingParameterFile( + "project_path", + self.tr("Project path"), + behavior=QgsProcessingParameterFile.Folder, + defaultValue=standard_path(), + ) + ) + + def processAlgorithm(self, parameters, context, model_feedback): + feedback = QgsProcessingMultiStepFeedback(5, model_feedback) + + # Checks if we have access to aequilibrae library + if iutil.find_spec("aequilibrae") is None: + sys.exit(self.tr("AequilibraE module not found")) + + from aequilibrae import Project + + aeq_crs = QgsCoordinateReferenceSystem("EPSG:4326") + + feedback.pushInfo(self.tr("Opening project")) + project_path = parameters["project_path"] + + # Import links layer + uri = QgsDataSourceUri() + uri.setDatabase(join(project_path, "project_database.sqlite")) + uri.setDataSource("", "links", "geometry") + links_layer = QgsVectorLayer(uri.uri(), "links_layer", "spatialite") + + # Get current max link_id + cols = ["link_id", "ogc_fid"] + datagen = ([f[col] for col in cols] for f in links_layer.getFeatures()) + links_ids = pd.DataFrame.from_records(data=datagen, columns=cols) + ogc_id = links_ids["ogc_fid"].max() + 1 + link_id = links_ids["link_id"].max() + 1 + + # Import QGIS layer as a panda dataframe and storing features for future copy + layer = self.parameterAsVectorLayer(parameters, "links", context) + columns = [parameters["modes"], parameters["link_type"]] + feature_list = [] + row_list = [] + for f in layer.getFeatures(): + geom = f.geometry() + geom.transform(QgsCoordinateTransform(layer.crs(), aeq_crs, QgsProject.instance())) + nf = QgsFeature(links_layer.fields()) + nf.setGeometry(geom) + nf["ogc_fid"] = int(ogc_id) + nf["link_id"] = int(link_id) + nf["a_node"] = 0 + nf["b_node"] = 0 + nf["direction"] = f[parameters["direction"]] + nf["link_type"] = f[parameters["link_type"]] + nf["modes"] = f[parameters["modes"]] + ogc_id = ogc_id + 1 + link_id = link_id + 1 + feature_list.append(nf) + row_list.append([f[parameters["modes"]], f[parameters["link_type"]]]) + df = pd.DataFrame(row_list, columns=columns) + feedback.pushInfo(" ") + feedback.setCurrentStep(1) + + feedback.pushInfo(self.tr("Getting parameters from layer")) + + # Updating link types + link_types = df[parameters["link_type"]].unique() + lt = project.network.link_types + lt_dict = lt.all_types() + + existing_types = [ltype.link_type for ltype in lt_dict.values()] + types_to_add = [ltype for ltype in link_types if ltype not in existing_types] + for i, ltype in enumerate(types_to_add): + new_type = lt.new(ascii_lowercase[i]) + new_type.link_type = ltype + new_type.save() + + # Updating modes + md = project.network.modes + md_dict = md.all_modes() + existing_modes = {k: v.mode_name for k, v in md_dict.items()} + + all_modes = set("".join(df[parameters["modes"]].unique())) + modes_to_add = [mode for mode in all_modes if mode not in existing_modes] + for i, mode_id in enumerate(modes_to_add): + new_mode = md.new(mode_id) + new_mode.mode_name = f"Mode_from_original_data_{mode_id}" + project.network.modes.add(new_mode) + new_mode.save() + project.close() + feedback.pushInfo(" ") + feedback.setCurrentStep(2) + + feedback.pushInfo(self.tr("Adding links")) + + # Adding links all at once + links_layer.startEditing() + links_layer.addFeatures(feature_list) + links_layer.commitChanges() + + feedback.pushInfo(" ") + feedback.setCurrentStep(3) + + feedback.pushInfo(self.tr("Closing project")) + del df, row_list, feature_list + + return {"Output": project_path} + + def name(self): + return self.tr("Add links from layer to project") + + def displayName(self): + return self.tr("Add links from layer to project") + + def group(self): + return "01-" + self.tr("Model Building") + + def groupId(self): + return "01-" + self.tr("Model Building") + + def shortHelpString(self): + return self.tr("Take links from a layer and add them to an existing AequilibraE project") + + def createInstance(self): + return AddLinksFromLayer() + + def tr(self, message): + return trlt("AddLinksFromLayer", message) diff --git a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py new file mode 100644 index 00000000..e46043ec --- /dev/null +++ b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py @@ -0,0 +1,196 @@ +import importlib.util as iutil +import sys +import numpy as np +import pandas as pd +from os.path import join +import os +from scipy.sparse import coo_matrix + +from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessingParameterString, QgsProcessingParameterDefinition +from qgis.core import QgsProcessingParameterField, QgsProcessingParameterMapLayer, QgsProcessingParameterFile +from qgis.core import QgsProcessingAlgorithm + +from qaequilibrae.modules.common_tools import standard_path +from qaequilibrae.i18n.translate import trlt + + +class AddMatrixFromLayer(QgsProcessingAlgorithm): + + def initAlgorithm(self, config=None): + self.addParameter(QgsProcessingParameterMapLayer("matrix_layer", self.tr("Matrix Layer"))) + self.addParameter( + QgsProcessingParameterField( + "origin", + self.tr("Origin"), + type=QgsProcessingParameterField.Numeric, + parentLayerParameterName="matrix_layer", + allowMultiple=False, + defaultValue="origin", + ) + ) + self.addParameter( + QgsProcessingParameterField( + "destination", + self.tr("Destination"), + type=QgsProcessingParameterField.Numeric, + parentLayerParameterName="matrix_layer", + allowMultiple=False, + defaultValue="destination", + ) + ) + self.addParameter( + QgsProcessingParameterField( + "value", + self.tr("Value"), + type=QgsProcessingParameterField.Numeric, + parentLayerParameterName="matrix_layer", + allowMultiple=False, + defaultValue="value", + ) + ) + self.addParameter( + QgsProcessingParameterFile( + "matrix_file", + self.tr("Existing .aem file"), + behavior=QgsProcessingParameterFile.File, + fileFilter="", + defaultValue=None, + ) + ) + + self.addParameter( + QgsProcessingParameterString("matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="Value") + ) + + def processAlgorithm(self, parameters, context, model_feedback): + feedback = QgsProcessingMultiStepFeedback(3, model_feedback) + + # Checks if we have access to aequilibrae library + if iutil.find_spec("aequilibrae") is None: + sys.exit(self.tr("AequilibraE module not found")) + + from aequilibrae.matrix import AequilibraeMatrix + + origin = parameters["origin"] + destination = parameters["destination"] + value = parameters["value"] + + core_name = [parameters["matrix_core"]] + + matrix_file = parameters["matrix_file"] + + # Import layer as a pandas df + feedback.pushInfo(self.tr("Importing layer")) + layer = self.parameterAsVectorLayer(parameters, "matrix_layer", context) + cols = [origin, destination, value] + datagen = ([f[col] for col in cols] for f in layer.getFeatures()) + matrix = pd.DataFrame.from_records(data=datagen, columns=cols) + feedback.pushInfo("") + feedback.setCurrentStep(1) + + # Getting all zones + all_zones = np.array(sorted(list(set(list(matrix[origin].unique()) + list(matrix[destination].unique()))))) + num_zones = all_zones.shape[0] + idx = np.arange(num_zones) + + # Creates the indexing dataframes + origs = pd.DataFrame({"from_index": all_zones, "from": idx}) + dests = pd.DataFrame({"to_index": all_zones, "to": idx}) + + # adds the new index columns to the pandas dataframe + matrix = matrix.merge(origs, left_on=origin, right_on="from_index", how="left") + matrix = matrix.merge(dests, left_on=destination, right_on="to_index", how="left") + + agg_matrix = matrix.groupby(["from", "to"]).sum() + + # returns the indices + agg_matrix.reset_index(inplace=True) + + # Creating the aequilibrae matrix file + mat = AequilibraeMatrix() + mat.load(matrix_file) + + cores = mat.names + cores.append(core_name[0]) + + output = AequilibraeMatrix() + output.create_empty( + file_name=matrix_file[-4] + "_temp.aem", + zones=mat.zones, + matrix_names=cores, + memory_only=False, + ) + + m = ( + coo_matrix((agg_matrix[value], (agg_matrix["from"], agg_matrix["to"])), shape=(num_zones, num_zones)) + .toarray() + .astype(np.float64) + ) + + output.index[:] = mat.index[:] + + for core in cores: + if core == core_name[0]: + output.matrix[core][:, :] = m[:, :] + else: + output.matrix[core][:, :] = mat.matrix[core][:, :] + output.setName(mat.name) + output.setDescription(mat.description.decode("utf-8")) + + feedback.pushInfo(self.tr("{}x{} matrix imported ").format(num_zones, num_zones)) + feedback.pushInfo(" ") + feedback.setCurrentStep(2) + + output.save() + output.close() + mat.close() + + os.remove(matrix_file) + os.rename(matrix_file[-4] + "_temp.aem", matrix_file) + del agg_matrix, matrix, m + + feedback.pushInfo(" ") + feedback.setCurrentStep(3) + + return {"Output": f"{mat.name}, {mat.description} ({matrix_file})"} + + def name(self): + return self.tr("Add matrix from layer to aem file") + + def displayName(self): + return self.tr("Add matrix from layer to aem file") + + def group(self): + return "02-" + self.tr("Data") + + def groupId(self): + return "02-" + self.tr("Data") + + def shortHelpString(self): + return "\n".join( + [ + self.string_order(1), + self.string_order(2), + self.string_order(3), + self.string_order(4), + self.string_order(5), + ] + ) + + def createInstance(self): + return AddMatrixFromLayer() + + def string_order(self, order): + if order == 1: + return self.tr("Save a layer to an existing *.aem file. Notice that:") + elif order == 2: + return self.tr("- the original matrix stored in the layer needs to be in list format") + elif order == 3: + return self.tr("- origin and destination fields need to be integers") + elif order == 4: + return self.tr("- value field can be either integer or real") + elif order == 5: + return self.tr("- if matrix_core already exists, it will be updated and previous data will be lost") + + def tr(self, message): + return trlt("AddMatrixFromLayer", message) diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py new file mode 100644 index 00000000..4310a7aa --- /dev/null +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -0,0 +1,167 @@ +import importlib.util as iutil +import sys +import textwrap + +from datetime import datetime as dt + +from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile +from qgis.core import QgsProcessingParameterDefinition, QgsProcessingParameterBoolean + +from qaequilibrae.i18n.translate import trlt + + +class ptAssignYAML(QgsProcessingAlgorithm): + + def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterFile( + "conf_file", + self.tr("Configuration file (.yaml)"), + behavior=QgsProcessingParameterFile.File, + fileFilter="", + defaultValue=None, + ) + ) + + advparameters = [ + QgsProcessingParameterBoolean( + "datetime_to_resultname", self.tr("Include current datetime to result name"), defaultValue=True + ) + ] + + for param in advparameters: + param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) + self.addParameter(param) + + def processAlgorithm(self, parameters, context, model_feedback): + feedback = QgsProcessingMultiStepFeedback(5, model_feedback) + + # Checks if we have access to aequilibrae library + if iutil.find_spec("aequilibrae") is None: + sys.exit(self.tr("AequilibraE module not found")) + + from aequilibrae.paths import TransitAssignment, TransitClass + from aequilibrae.project import Project + from aequilibrae.matrix import AequilibraeMatrix + from aequilibrae.project.database_connection import database_connection + from aequilibrae.transit.transit_graph_builder import TransitGraphBuilder + import yaml + + feedback.pushInfo(self.tr("Getting parameters from YAML")) + + pathfile = parameters["conf_file"] + with open(pathfile, "r") as f: + params = yaml.safe_load(f) + + feedback.pushInfo(" ") + feedback.setCurrentStep(1) + + # Opening project + feedback.pushInfo(self.tr("Opening project")) + + project = Project() + project.open(params["project_path"]) + project.network.build_graphs() + + # Load PT Graph + pt_con = database_connection("transit") + params["graph"]["public_transport_conn"] = pt_con + + graph_db = TransitGraphBuilder.from_db(**params["graph"]) + graph_db.create_graph() + graph_db.create_line_geometry(method="connector project match", graph="c") + + graph = graph_db.to_transit_graph() + + # Load AequilibraE Matrix + mat = AequilibraeMatrix() + mat.load(params["matrix_path"]) + mat.computational_view() + + feedback.pushInfo(" ") + feedback.setCurrentStep(2) + + # Setting up assignment + feedback.pushInfo(self.tr("Setting up assignment")) + + # Create the assignment class + assigclass = TransitClass(name="pt", graph=graph, matrix=mat) + assigclass.set_demand_matrix_core(params["matrix_core"]) + + # Create PT Assignment object + assig = TransitAssignment() + assig.add_class(assigclass) + assig.set_time_field(params["assignment"]["time_field"]) + assig.set_frequency_field(params["assignment"]["frequency"]) + assig.set_algorithm(params["assignment"]["algorithm"]) + + feedback.pushInfo(" ") + feedback.setCurrentStep(3) + + # Running assignment + feedback.pushInfo(self.tr("Running assignment")) + assig.execute() + feedback.pushInfo(" ") + feedback.setCurrentStep(4) + + # Saving outputs + feedback.pushInfo(self.tr("Saving outputs")) + if str(parameters["datetime_to_resultname"]) == "True": + params["result_name"] = params["result_name"] + dt.now().strftime("_%Y-%m-%d_%Hh%M") + assig.save_results(params["result_name"]) + + feedback.pushInfo(" ") + feedback.setCurrentStep(5) + + project.close() + + return {"Output": "PT assignment successfully completed"} + + def name(self): + return self.tr("PT assignment from file") + + def displayName(self): + return self.tr("PT assignment from file") + + def group(self): + return "04-" + self.tr("Public transport") + + def groupId(self): + return "04-" + self.tr("Public transport") + + def shortHelpString(self): + return textwrap.dedent("\n".join([self.string_order(1), self.string_order(2), self.string_order(3)])) + + def createInstance(self): + return ptAssignYAML() + + def string_order(self, order): + if order == 1: + return self.tr("Run a pt assignment using a YAML configuration file.") + elif order == 2: + return self.tr("Example of valid configuration file:") + elif order == 3: + return textwrap.dedent( + """\ + project: D:/AequilibraE/Project/ + + result_name: sce_from_yaml + + transit_classes: + - student: + matrix_path: D:/AequilibraE/Project/matrices/demand.aem + matrix_core: student_pt + blocked_centroid_flows: True + skims: travel_time, distance + - worker: + matrix_path: D:/AequilibraE/Project/matrices/demand.aem + matrix_core: worker_pt + blocked_centroid_flows: True + + assignment: + period_id: 1 + """ + ) + + def tr(self, message): + return trlt("ptAssignYAML", message) diff --git a/qaequilibrae/modules/processing_provider/assign_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py similarity index 60% rename from qaequilibrae/modules/processing_provider/assign_from_yaml.py rename to qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py index 6dff42cc..5e896f8f 100644 --- a/qaequilibrae/modules/processing_provider/assign_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py @@ -1,7 +1,11 @@ import importlib.util as iutil import sys +import textwrap + +from datetime import datetime as dt from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile +from qgis.core import QgsProcessingParameterDefinition, QgsProcessingParameterBoolean from qaequilibrae.i18n.translate import trlt @@ -14,11 +18,21 @@ def initAlgorithm(self, config=None): "conf_file", self.tr("Configuration file (.yaml)"), behavior=QgsProcessingParameterFile.File, - fileFilter="*.yaml", + fileFilter="", defaultValue=None, ) ) + advparams = [ + QgsProcessingParameterBoolean( + "datetime_to_resultname", self.tr("Include current datetime to result name"), defaultValue=True + ) + ] + + for param in advparams: + param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) + self.addParameter(param) + def processAlgorithm(self, parameters, context, model_feedback): feedback = QgsProcessingMultiStepFeedback(5, model_feedback) @@ -49,6 +63,17 @@ def processAlgorithm(self, parameters, context, model_feedback): # Creating traffic classes traffic_classes = [] feedback.pushInfo(self.tr("{} traffic classes have been found").format(len(params["traffic_classes"]))) + select_links = "select_links" in params and params["select_links"] + if select_links: + selection_dict = {} + for selections in params["select_links"]: + for name in selections: + link_list = "" + for text in selections[name]: + link_list = link_list + "," + text + link_list = "[" + link_list[1:] + "]" + link_list = eval(link_list) + selection_dict[name] = link_list for classes in params["traffic_classes"]: for traffic in classes: @@ -61,7 +86,10 @@ def processAlgorithm(self, parameters, context, model_feedback): # Getting graph graph = project.network.graphs[classes[traffic]["network_mode"]] graph.set_graph(params["assignment"]["time_field"]) - graph.set_blocked_centroid_flows(False) + if str(classes[traffic]["blocked_centroid_flows"]) == "True": + graph.set_blocked_centroid_flows(True) + else: + graph.set_blocked_centroid_flows(False) if "skims" in classes[traffic] and classes[traffic]["skims"]: skims = [sk.strip() for sk in classes[traffic]["skims"].split(",")] @@ -78,6 +106,10 @@ def processAlgorithm(self, parameters, context, model_feedback): else: sys.exit("error: fixed_cost must come with a correct value of time") + # Adding select links analysis + if select_links: + assigclass.set_select_links(selection_dict) + # Adding class feedback.pushInfo(f"\t- {traffic} ' ' {str(classes[traffic])}") @@ -112,8 +144,13 @@ def processAlgorithm(self, parameters, context, model_feedback): # Saving outputs feedback.pushInfo(self.tr("Saving outputs")) feedback.pushInfo(str(assig.report())) + if str(parameters["datetime_to_resultname"]) == "True": + params["result_name"] = params["result_name"] + dt.now().strftime("_%Y-%m-%d_%Hh%M") assig.save_results(params["result_name"]) - assig.save_skims(params["result_name"], which_ones="all", format="omx") + assig.save_skims(params["result_name"], which_ones="all", format="aem") + if select_links: + assig.procedure_id = assig.procedure_id + "_S" + assig.save_select_link_results(params["result_name"]) feedback.pushInfo(" ") feedback.setCurrentStep(5) @@ -128,13 +165,13 @@ def displayName(self): return self.tr("Traffic assignment from file") def group(self): - return self.tr("Paths and assignment") + return "03-" + self.tr("Paths and assignment") def groupId(self): - return self.tr("Paths and assignment") + return "03-" + self.tr("Paths and assignment") def shortHelpString(self): - return "\n".join([self.string_order(1), self.string_order(2), self.string_order(3)]) + return textwrap.dedent("\n".join([self.string_order(1), self.string_order(2), self.string_order(3)])) def createInstance(self): return TrafficAssignYAML() @@ -145,35 +182,40 @@ def string_order(self, order): elif order == 2: return self.tr("Example of valid configuration file:") elif order == 3: - return """ - project: D:/AequilibraE/Project/ - result_name: sce_from_yaml - traffic_classes: - - car: - matrix_path: D:/AequilibraE/Project/matrices/demand.aem - matrix_core: car - network_mode: c - pce: 1 - blocked_centroid_flows: True - skims: travel_time, distance - - truck: - matrix_path: D:/AequilibraE/Project/matrices/demand.aem - matrix_core: truck - network_mode: c - pce: 2 - fixed_cost: toll - vot: 12 - blocked_centroid_flows: True - assignment: - algorithm: bfw - vdf: BPR2 - alpha: 0.15 - beta: power - capacity_field: capacity - time_field: travel_time - max_iter: 250 - rgap: 0.00001 - """ + return textwrap.dedent( + """\ + project: D:/AequilibraE/Project/ + result_name: sce_from_yaml + traffic_classes: + - car: + matrix_path: D:/AequilibraE/Project/matrices/demand.aem + matrix_core: car + network_mode: c + pce: 1 + blocked_centroid_flows: True + skims: travel_time, distance + - truck: + matrix_path: D:/AequilibraE/Project/matrices/demand.aem + matrix_core: truck + network_mode: c + pce: 2 + fixed_cost: toll + vot: 12 + blocked_centroid_flows: True + assignment: + algorithm: bfw + vdf: BPR2 + alpha: 0.15 + beta: power + capacity_field: capacity + time_field: travel_time + max_iter: 250 + rgap: 0.00001 + select_links: #optionnal, name with a list of tuples as [(link_id, link_direction)] + - survey_site_1: [(23,0)] + - est-west-transit: [(12, 1),(402, 1)] + """ + ) def tr(self, message): return trlt("TrafficAssignYAML", message) diff --git a/qaequilibrae/modules/processing_provider/matrix_from_layer.py b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py similarity index 94% rename from qaequilibrae/modules/processing_provider/matrix_from_layer.py rename to qaequilibrae/modules/processing_provider/create_matrix_from_layer.py index 0033501b..b5adcff6 100644 --- a/qaequilibrae/modules/processing_provider/matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py @@ -13,7 +13,7 @@ from qaequilibrae.i18n.translate import trlt -class MatrixFromLayer(QgsProcessingAlgorithm): +class CreateMatrixFromLayer(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): self.addParameter(QgsProcessingParameterMapLayer("matrix_layer", self.tr("Matrix Layer"))) @@ -144,7 +144,7 @@ def processAlgorithm(self, parameters, context, model_feedback): mat.save() mat.close() - del matrix + del agg_matrix, matrix, m feedback.pushInfo(" ") feedback.setCurrentStep(3) @@ -152,22 +152,22 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": f"{mat.name}, {mat.description} ({file_name})"} def name(self): - return self.tr("Import matrices") + return self.tr("Create aem matrix file from layer") def displayName(self): - return self.tr("Import matrices") + return self.tr("Create aem matrix file from layer") def group(self): - return self.tr("Data") + return "02-" + self.tr("Data") def groupId(self): - return self.tr("Data") + return "02-" + self.tr("Data") def shortHelpString(self): return "\n".join([self.string_order(1), self.string_order(2), self.string_order(3), self.string_order(4)]) def createInstance(self): - return MatrixFromLayer() + return CreateMatrixFromLayer() def string_order(self, order): if order == 1: @@ -180,4 +180,4 @@ def string_order(self, order): return self.tr("- value field can be either integer or real") def tr(self, message): - return trlt("MatrixFromLayer", message) + return trlt("CreateMatrixFromLayer", message) diff --git a/qaequilibrae/modules/processing_provider/create_pt_graph.py b/qaequilibrae/modules/processing_provider/create_pt_graph.py new file mode 100644 index 00000000..1167ad77 --- /dev/null +++ b/qaequilibrae/modules/processing_provider/create_pt_graph.py @@ -0,0 +1,120 @@ +import importlib.util as iutil +import sys +import textwrap + +from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile +from qgis.core import QgsProcessingParameterBoolean, QgsProcessingParameterString, QgsProcessingParameterNumber +from qgis.core import QgsProcessingParameterDefinition + +from qaequilibrae.modules.common_tools import standard_path +from qaequilibrae.i18n.translate import trlt + + +class create_pt_graph(QgsProcessingAlgorithm): + + def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterFile( + "project_path", + self.tr("Project path"), + behavior=QgsProcessingParameterFile.Folder, + defaultValue=standard_path(), + ) + ) + # This should load all mode_ids available. Could be a dict, e.g.: "w": walk, "c": car, etc + self.addParameter( + QgsProcessingParameterString("access_mode", self.tr("access mode"), multiLine=False, defaultValue="w") + ) + self.addParameter( + QgsProcessingParameterBoolean("block_flows", self.tr("Block flows through centroids"), defaultValue=True) + ) + self.addParameter( + QgsProcessingParameterBoolean("walking_edges", self.tr("Project with walking edges"), defaultValue=False) + ) + self.addParameter( + QgsProcessingParameterBoolean( + "outer_stops_transfers", self.tr("Project with outer stops transfers"), defaultValue=False + ) + ) + + advparams = [ + QgsProcessingParameterBoolean("has_zones", self.tr("Project has zoning information"), defaultValue=True), + QgsProcessingParameterNumber( + "period_id", self.tr("Period id"), type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=1 + ), + ] + + for param in advparams: + param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) + self.addParameter(param) + + def processAlgorithm(self, parameters, context, model_feedback): + feedback = QgsProcessingMultiStepFeedback(3, model_feedback) + + # Checks if we have access to aequilibrae library + if iutil.find_spec("aequilibrae") is None: + sys.exit(self.tr("AequilibraE module not found")) + + from aequilibrae.transit import Transit + from aequilibrae.project import Project + + feedback.pushInfo(self.tr("Opening project")) + # Opening project + project = Project() + project.open(parameters["project_path"]) + data = Transit(project) + + feedback.pushInfo(" ") + feedback.setCurrentStep(1) + + feedback.pushInfo(self.tr("Creating graph")) + # Creating graph + if not parameters["has_zones"]: + graph = data.create_graph( + with_outer_stop_transfers=parameters["outer_stops_transfers"], + with_walking_edges=parameters["walking_edges"], + blocking_centroid_flows=parameters["block_flows"], + connector_method="overlapping_regions", + ) + feedback.pushInfo(" ") + feedback.setCurrentStep(2) + + # Connector matching + project.network.build_graphs() + graph.create_line_geometry(method="connector project match", graph=parameters["access_mode"]) + + feedback.pushInfo(self.tr("Saving graph")) + # Saving graph + data.save_graphs() + + feedback.pushInfo(" ") + feedback.setCurrentStep(3) + + project.close() + + return {"Output": "PT graph successfully created"} + + def name(self): + return self.tr("Create PT graph before PT assignment") + + def displayName(self): + return self.tr("Create PT graph before PT assignment") + + def group(self): + return "04-" + self.tr("Public transport") + + def groupId(self): + return "04-" + self.tr("Public transport") + + def shortHelpString(self): + return textwrap.dedent("\n".join([self.string_order(1)])) + + def createInstance(self): + return create_pt_graph() + + def string_order(self, order): + if order == 1: + return self.tr("Create a PT graph.") + + def tr(self, message): + return trlt("create_pt_graph", message) diff --git a/qaequilibrae/modules/processing_provider/export_matrix.py b/qaequilibrae/modules/processing_provider/export_matrix.py index 45d86d75..2211f054 100644 --- a/qaequilibrae/modules/processing_provider/export_matrix.py +++ b/qaequilibrae/modules/processing_provider/export_matrix.py @@ -39,30 +39,28 @@ def initAlgorithm(self, config=None): ) def processAlgorithm(self, parameters, context, model_feedback): + + src_path = parameters["src"] + file_format = [".csv", ".omx", ".aem"] + format = file_format[parameters["output_format"]] + dst_path = join(parameters["dst"], f"{Path(src_path).stem}.{format}") + # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) from aequilibrae.matrix import AequilibraeMatrix - file_format = ["csv", "omx", "aem"] - format = file_format[parameters["output_format"]] - file_name, ext = parameters["src"].split("/")[-1].split(".") - dst_path = join(parameters["dst"], f"{file_name}.{format}") - - kwargs = {"file_path": dst_path, "memory_only": False} + if src_path[-3:] == "omx": + tmpmat = AequilibraeMatrix() + tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".aem").name + tmpmat.create_from_omx(tmp, src_path) + tmpmat.export(tmp) + src_path = tmp + tmpmat.close() mat = AequilibraeMatrix() - - if ext == "omx": - if format == "omx": - mat.create_from_omx(omx_path=parameters["src"], **kwargs) - elif format in ["csv", "aem"]: - mat.create_from_omx(parameters["src"]) - mat.export(dst_path) - elif ext == "aem": - mat.load(parameters["src"]) - mat.export(dst_path) - + mat.load(src_path) + mat.export(dst_path) mat.close() return {"Output": dst_path} @@ -74,10 +72,10 @@ def displayName(self): return self.tr("Export matrices") def group(self): - return self.tr("Data") + return "02-" + self.tr("Data") def groupId(self): - return self.tr("Data") + return "02-" + self.tr("Data") def shortHelpString(self): return self.tr("Export an existing *.omx or *.aem matrix file into *.csv, *.aem or *.omx") diff --git a/qaequilibrae/modules/processing_provider/group_i18n.py b/qaequilibrae/modules/processing_provider/group_i18n.py new file mode 100644 index 00000000..e69de29b diff --git a/qaequilibrae/modules/processing_provider/import_gtfs.py b/qaequilibrae/modules/processing_provider/import_gtfs.py new file mode 100644 index 00000000..0f5def34 --- /dev/null +++ b/qaequilibrae/modules/processing_provider/import_gtfs.py @@ -0,0 +1,114 @@ +import importlib.util as iutil +import sys + +from datetime import datetime as dt + +from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile +from qgis.core import QgsProcessingParameterString, QgsProcessingParameterBoolean + +from qaequilibrae.modules.common_tools import standard_path +from qaequilibrae.i18n.translate import trlt + + +class ImportGTFS(QgsProcessingAlgorithm): + + def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterFile( + "gtfs_file", + self.tr("GTFS file (.zip)"), + behavior=QgsProcessingParameterFile.File, + fileFilter="", + defaultValue=None, + ) + ) + self.addParameter(QgsProcessingParameterString("agency", self.tr("Agency to import"), multiLine=False)) + self.addParameter( + QgsProcessingParameterString( + "gtfs_date", self.tr("Date to import (YYYY-MM-DD)"), multiLine=False, defaultValue="2024-01-01" + ) + ) + self.addParameter( + QgsProcessingParameterBoolean( + "map_match", self.tr("map matching of PT lines on the aequilibrae project network"), defaultValue=True + ) + ) + self.addParameter( + QgsProcessingParameterFile( + "project", + self.tr("Project path"), + behavior=QgsProcessingParameterFile.Folder, + defaultValue=standard_path(), + ) + ) + + def processAlgorithm(self, parameters, context, model_feedback): + + if parameters["map_match"]: + i = 4 + else: + i = 3 + + feedback = QgsProcessingMultiStepFeedback(i, model_feedback) + + # Checks if we have access to aequilibrae library + if iutil.find_spec("aequilibrae") is None: + sys.exit(self.tr("AequilibraE module not found")) + + from aequilibrae.project import Project + from aequilibrae.transit import Transit + + feedback.pushInfo(self.tr("Opening project")) + + # Opening project + project = Project() + project.open(parameters["project"]) + feedback.setCurrentStep(1) + feedback.pushInfo(" ") + + # Importing GTFS + feedback.pushInfo(self.tr("Importing GTFS")) + data = Transit(project) + transit = data.new_gtfs_builder(agency=parameters["agency"], file_path=parameters["gtfs_file"]) + transit.load_date(parameters["gtfs_date"]) + feedback.setCurrentStep(2) + feedback.pushInfo(" ") + + # Map matching if selected + if str(parameters["map_match"]) == "True": + feedback.pushInfo(self.tr("Map matching of PT lines on available network, it may take a while...")) + transit.set_allow_map_match(True) + transit.map_match() + feedback.setCurrentStep(i - 1) + feedback.pushInfo(" ") + + # Saving results + feedback.pushInfo(self.tr("Saving results")) + transit.save_to_disk() + feedback.pushInfo(" ") + feedback.setCurrentStep(i) + + project.close() + + return {"Output": "Traffic assignment successfully completed"} + + def name(self): + return self.tr("Import GTFS") + + def displayName(self): + return self.tr("Import GTFS") + + def group(self): + return "04-" + self.tr("Public transport") + + def groupId(self): + return "04-" + self.tr("Public transport") + + def shortHelpString(self): + return self.tr("Add PT lines from a GTFS file to an existing aequilibrae project") + + def createInstance(self): + return ImportGTFS() + + def tr(self, message): + return trlt("ImportGTFS", message) diff --git a/qaequilibrae/modules/processing_provider/matrix_calculator.py b/qaequilibrae/modules/processing_provider/matrix_calculator.py new file mode 100644 index 00000000..0cbfe053 --- /dev/null +++ b/qaequilibrae/modules/processing_provider/matrix_calculator.py @@ -0,0 +1,254 @@ +import importlib.util as iutil +import sys +import textwrap + +from datetime import datetime as dt + +from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile +from qgis.core import QgsProcessingParameterDefinition, QgsProcessingParameterBoolean, QgsProcessingParameterString + +from qaequilibrae.i18n.translate import trlt + + +class MatrixCalculator(QgsProcessingAlgorithm): + + def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterFile( + "conf_file", + self.tr("Matrix configuration file (.yaml)"), + behavior=QgsProcessingParameterFile.File, + fileFilter="", + defaultValue=None, + ) + ) + self.addParameter( + QgsProcessingParameterString("request", self.tr("Request"), multiLine=False, defaultValue=None) + ) + self.addParameter( + QgsProcessingParameterFile( + "dest_path", + self.tr("Existing .aem file") + self.tr("(used to store computed matrix)"), + behavior=QgsProcessingParameterFile.File, + fileFilter="", + defaultValue=None, + ) + ) + self.addParameter( + QgsProcessingParameterString( + "matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="MatrixCalculator_Result" + ) + ) + + advparams = [ + QgsProcessingParameterString( + "filtering_matrix", self.tr("Filtering matrix"), multiLine=False, optional=True, defaultValue=None + ) + ] + + for param in advparams: + param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) + self.addParameter(param) + + def processAlgorithm(self, parameters, context, model_feedback): + feedback = QgsProcessingMultiStepFeedback(4, model_feedback) + + # Checks if we have access to aequilibrae library + if iutil.find_spec("aequilibrae") is None: + sys.exit(self.tr("AequilibraE module not found")) + + exec("from aequilibrae.matrix import AequilibraeMatrix", globals()) + exec("import numpy as np", globals()) + import yaml + + start = dt.now() + + # Import or create all needed matrices as numpy arrays + feedback.pushInfo(self.tr("Getting matrices from configuration file")) + conf_file = parameters["conf_file"] + dest_path = parameters["dest_path"] + dest_core = [parameters["matrix_core"]] + request = parameters["request"] + + destination = AequilibraeMatrix() + destination.load(dest_path) + global d + d = len(destination.get_matrix(dest_core[0])) + + feedback.pushInfo( + self.tr("Matrix total before calculation: ") + + "{:,.2f}".format(destination.get_matrix(dest_core[0]).sum()).replace(",", " ") + ) + feedback.pushInfo(self.tr("Expected dimensions of matrix based on destination file: ") + str(d) + "x" + str(d)) + feedback.pushInfo("") + + with open(conf_file, "r") as f: + params = yaml.safe_load(f) + m_list = [] + + for matrices in params["Matrices"]: + for matrix in matrices: + exec( + f""" +{matrix} = AequilibraeMatrix() +{matrix}.load("{matrices[matrix]["matrix_path"]}") +{matrix}={matrix}.get_matrix("{matrices[matrix]["matrix_core"]}") +""", + globals(), + ) + + m_list.append(matrix) + exec(f"dim=len({matrix})", globals()) + feedback.pushInfo(str(matrix)) + feedback.pushInfo(self.tr(f"Importation of {matrix}, matrix dimensions {dim}x{dim} and total is:")) + exec('feedback.pushInfo("{:,.2f}".format(' + matrix + '.sum()).replace(",", " "))') + assert d == dim, self.tr("Matrices must have the same dimensions as the desired result !") + feedback.pushInfo("") + + if "null_diag" in request: # If needed, prepare a matrix to set diagonal to 0 + exec( + """ +null_diag=np.ones((d, d), dtype=np.float64) +np.fill_diagonal(null_diag, 0)""", + globals(), + ) + + if "zeros" in request: # If needed, prepare a matrix full of zero + exec("zeros=np.zeros((d, d), dtype=np.float64)", globals()) + feedback.pushInfo(" ") + feedback.setCurrentStep(1) + + # Setting up request, Used grammar is close to R language, need to be translated for numpy + request = request.replace("max(", "np.maximum(") + request = request.replace("min(", "np.minimum(") + request = request.replace("ln(", "np.log(") + request = request.replace("exp(", "np.exp(") + request = request.replace("power(", "np.power(") + request = request.replace("abs(", "np.absolute(") + request = request.replace("null_diag(", "null_diag*(") + request = request.replace("t(", "np.transpose(") + + feedback.pushInfo(" ") + feedback.setCurrentStep(2) + + # Compute request: if a filtering matrix is used, update only a part of the destination matrix + filtering_matrix = parameters["filtering_matrix"] + if len(filtering_matrix) > 0: + global result + exec("filtering_matrix=np.nan_to_num(" + filtering_matrix + ")", globals()) + assert np.any((filtering_matrix == 0.0) | (filtering_matrix == 1.0)) + keep = np.absolute(filtering_matrix - np.ones(d)) * destination.get_matrix(dest_core[0]) + exec("new=filtering_matrix*(" + request + ")", globals()) + result = keep + new + del filtering_matrix + else: + exec("result=" + request, globals()) + feedback.pushInfo(self.tr("Result (total: ") + f"{'{:,.2f}'.format(result.sum()).replace(',', ' ')}): ") + feedback.pushInfo(str(result)) + + feedback.pushInfo(" ") + feedback.setCurrentStep(3) + + # Updating destination matrix file + destination.matrix[dest_core[0]][:, :] = result[:, :] + destination.save() + destination.close() + + for m in m_list: + exec("del " + m, globals()) + + feedback.pushInfo(" ") + feedback.setCurrentStep(4) + + return {"Output": self.tr("Calculation completed in: ") + str((dt.now() - start).total_seconds()) + "secs"} + + def name(self): + return self.tr("Matrix calculator") + + def displayName(self): + return self.tr("Matrix calculator") + + def group(self): + return "02-" + self.tr("Data") + + def groupId(self): + return "02-" + self.tr("Data") + + def shortHelpString(self): + return textwrap.dedent( + "\n".join( + [ + self.string_order(1), + self.string_order(2), + self.string_order(3), + self.string_order(4), + self.string_order(5), + self.string_order(6), + self.string_order(7), + self.string_order(8), + self.string_order(9), + ] + ) + ) + + def createInstance(self): + return MatrixCalculator() + + def string_order(self, order): + if order == 1: + return self.tr("Run a matrix calculation based on a request and a matrix config file (.yaml) :") + elif order == 2: + return self.tr("- Matrix configuration file (.yaml file)") + elif order == 3: + return ( + self.tr("- Request as a formula, example : ") + + "null_diag( abs( max( t(matA)-(matB*3), zeros ) + power(matC,2) ) )" + ) + elif order == 4: + return self.tr("- .aem file and matrix core to store calculated matrix") + elif order == 5: + return self.tr( + "- filtering matrix, a matrix of 0 and 1 defined in matrix config file that will be used to update only a part of the destination matrix " + ) + elif order == 6: + return self.tr("Example of valid matrix configuration file:") + elif order == 7: + return textwrap.dedent( + """\ + Matrices: + - generation: + matrix_path: D:/AequilibraE/Project/matrices/socioeconomic_2024.aem + matrix_core: generation + - pop2024: + matrix_path: D:/AequilibraE/Project/matrices/socioeconomic_2024.aem + matrix_core: pop_dest + - emp2024: + matrix_path: D:/AequilibraE/Project/matrices/socioeconomic_2024.aem + matrix_core: emp_dest + - gen_time: + matrix_path: D:/AequilibraE/Project/matrices/aon_skims.aem + matrix_core: gen_time + """ + ) + elif order == 8: + return self.tr("List of available functions :") + elif order == 9: + return textwrap.dedent( + """\ + + + - + / + * + min(matA, matB) + max(matA, matB) + abs(matA) + ln(matA) + exp(matA) + power(matA, n) + null_diag(matA) + t(matA) #transpose + """ + ) + + def tr(self, message): + return trlt("MatrixCalculator", message) diff --git a/qaequilibrae/modules/processing_provider/project_from_OSM.py b/qaequilibrae/modules/processing_provider/project_from_OSM.py new file mode 100644 index 00000000..a1231c68 --- /dev/null +++ b/qaequilibrae/modules/processing_provider/project_from_OSM.py @@ -0,0 +1,80 @@ +import importlib.util as iutil +import pandas as pd +import sys +from os.path import join +from string import ascii_lowercase +from shapely.wkt import loads as load_wkt + +from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile +from qgis.core import QgsProcessingParameterString + +from qaequilibrae.modules.common_tools import standard_path +from qaequilibrae.i18n.translate import trlt + + +class ProjectFromOSM(QgsProcessingAlgorithm): + + def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterString( + "OSM_place", self.tr("Place name (OSM search)"), multiLine=False, defaultValue="" + ) + ) + self.addParameter( + QgsProcessingParameterFile( + "dst", + self.tr("Output folder"), + behavior=QgsProcessingParameterFile.Folder, + defaultValue=standard_path(), + ) + ) + self.addParameter( + QgsProcessingParameterString( + "project_name", self.tr("Project name"), multiLine=False, defaultValue="new_project" + ) + ) + + def processAlgorithm(self, parameters, context, model_feedback): + feedback = QgsProcessingMultiStepFeedback(2, model_feedback) + + # Checks if we have access to aequilibrae library + if iutil.find_spec("aequilibrae") is None: + sys.exit(self.tr("AequilibraE module not found")) + + from aequilibrae import Project + + feedback.pushInfo(self.tr("Creating project")) + project_path = join(parameters["dst"], parameters["project_name"]) + project = Project() + project.new(project_path) + + project.network.create_from_osm(place_name=parameters["OSM_place"]) + + feedback.pushInfo(" ") + feedback.setCurrentStep(2) + + feedback.pushInfo(self.tr("Closing project")) + project.close() + + return {"Output": project_path} + + def name(self): + return self.tr("Create project from OSM") + + def displayName(self): + return self.tr("Create project from OSM") + + def group(self): + return "01-" + self.tr("Model Building") + + def groupId(self): + return "01-" + self.tr("Model Building") + + def shortHelpString(self): + return self.tr("Create an AequilibraE project from OpenStreetMap") + + def createInstance(self): + return ProjectFromOSM() + + def tr(self, message): + return trlt("ProjectFromOSM", message) diff --git a/qaequilibrae/modules/processing_provider/project_from_layer.py b/qaequilibrae/modules/processing_provider/project_from_layer.py index b272f54b..fc3ee65f 100644 --- a/qaequilibrae/modules/processing_provider/project_from_layer.py +++ b/qaequilibrae/modules/processing_provider/project_from_layer.py @@ -3,12 +3,11 @@ import sys from os.path import join from string import ascii_lowercase -from shapely.wkt import loads as load_wkt from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProcessingAlgorithm from qgis.core import QgsProcessing, QgsProcessingMultiStepFeedback, QgsProcessingParameterVectorLayer from qgis.core import QgsProcessingParameterField, QgsProcessingParameterFile, QgsProcessingParameterString -from qgis.core import QgsProject +from qgis.core import QgsProject, QgsFeature, QgsVectorLayer, QgsDataSourceUri from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt @@ -93,18 +92,37 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback.pushInfo(self.tr("Importing links layer")) aeq_crs = QgsCoordinateReferenceSystem("EPSG:4326") + # Adding source_id field early to have all fields available in links table + links = project.network.links + link_data = links.fields + link_data.add("source_id", "link_id from the data source") + links.refresh_fields() + uri = QgsDataSourceUri() + uri.setDatabase(join(project_path, "project_database.sqlite")) + uri.setDataSource("", "links", "geometry") + links_layer = QgsVectorLayer(uri.uri(), "links_layer", "spatialite") + # Import QGIS layer as a panda dataframe and storing features for future copy layer = self.parameterAsVectorLayer(parameters, "links", context) - columns = [f.name() for f in layer.fields()] + columns = [parameters["modes"], parameters["link_type"]] feature_list = [] - geometries = [] - for feat in layer.getFeatures(): - feature_list.append(feat.attributes()) - geom = feat.geometry() + row_list = [] + for f in layer.getFeatures(): + geom = f.geometry() geom.transform(QgsCoordinateTransform(layer.crs(), aeq_crs, QgsProject.instance())) - geometries.append(geom.asWkt().upper()) - df = pd.DataFrame(feature_list, columns=columns) - df["geom"] = geometries + nf = QgsFeature(links_layer.fields()) + nf.setGeometry(geom) + nf["ogc_fid"] = f[parameters["link_id"]] + nf["link_id"] = f[parameters["link_id"]] + nf["a_node"] = 0 + nf["b_node"] = 0 + nf["source_id"] = f[parameters["link_id"]] + nf["direction"] = f[parameters["direction"]] + nf["link_type"] = f[parameters["link_type"]] + nf["modes"] = f[parameters["modes"]] + feature_list.append(nf) + row_list.append([f[parameters["modes"]], f[parameters["link_type"]]]) + df = pd.DataFrame(row_list, columns=columns) feedback.pushInfo(" ") feedback.setCurrentStep(1) @@ -134,32 +152,22 @@ def processAlgorithm(self, parameters, context, model_feedback): new_mode.mode_name = f"Mode_from_original_data_{mode_id}" project.network.modes.add(new_mode) new_mode.save() + project.close() feedback.pushInfo(" ") feedback.setCurrentStep(2) feedback.pushInfo(self.tr("Adding links")) - # Adding source_id field early to have all fields available in links table - links = project.network.links - link_data = links.fields - link_data.add("source_id", "link_id from the data source") - links.refresh_fields() - - for _, record in df.iterrows(): - new_link = links.new() - new_link.source_id = record[parameters["link_id"]] - new_link.direction = record[parameters["direction"]] - new_link.modes = record[parameters["modes"]] - new_link.link_type = record[parameters["link_type"]] - new_link.geometry = load_wkt(record.geom.upper()) - new_link.save() + # Adding links all at once + links_layer.startEditing() + links_layer.addFeatures(feature_list) + links_layer.commitChanges() feedback.pushInfo(" ") feedback.setCurrentStep(3) feedback.pushInfo(self.tr("Closing project")) - project.close() - del df, feature_list, geometries + del df, row_list, feature_list return {"Output": project_path} @@ -170,10 +178,10 @@ def displayName(self): return self.tr("Create project from link layer") def group(self): - return self.tr("Model Building") + return "01-" + self.tr("Model Building") def groupId(self): - return self.tr("Model Building") + return "01-" + self.tr("Model Building") def shortHelpString(self): return self.tr("Create an AequilibraE project from a given link layer") diff --git a/qaequilibrae/modules/processing_provider/provider.py b/qaequilibrae/modules/processing_provider/provider.py index 2cb21dfe..85d5c652 100644 --- a/qaequilibrae/modules/processing_provider/provider.py +++ b/qaequilibrae/modules/processing_provider/provider.py @@ -15,19 +15,33 @@ class Provider(QgsProcessingProvider): def loadAlgorithms(self): - from .Add_connectors import AddConnectors - from .assign_from_yaml import TrafficAssignYAML - from .export_matrix import ExportMatrix - from .matrix_from_layer import MatrixFromLayer from .project_from_layer import ProjectFromLayer + from .project_from_OSM import ProjectFromOSM + from .add_connectors import AddConnectors + from .assign_traffic_from_yaml import TrafficAssignYAML + from .export_matrix import ExportMatrix + from .create_matrix_from_layer import CreateMatrixFromLayer + from .add_matrix_from_layer import AddMatrixFromLayer + from .add_links_from_layer import AddLinksFromLayer from .renumber_nodes_from_layer import RenumberNodesFromLayer + from .matrix_calculator import MatrixCalculator + from .import_gtfs import ImportGTFS + from .create_pt_graph import create_pt_graph + from .assign_pt_from_yaml import ptAssignYAML - self.addAlgorithm(MatrixFromLayer()) - self.addAlgorithm(ExportMatrix()) + self.addAlgorithm(ProjectFromOSM()) self.addAlgorithm(ProjectFromLayer()) + self.addAlgorithm(CreateMatrixFromLayer()) + self.addAlgorithm(AddMatrixFromLayer()) + self.addAlgorithm(MatrixCalculator()) + self.addAlgorithm(ExportMatrix()) + self.addAlgorithm(AddLinksFromLayer()) self.addAlgorithm(RenumberNodesFromLayer()) self.addAlgorithm(AddConnectors()) self.addAlgorithm(TrafficAssignYAML()) + self.addAlgorithm(ImportGTFS()) + self.addAlgorithm(create_pt_graph()) + self.addAlgorithm(ptAssignYAML()) def id(self): """The ID used for identifying the provider. diff --git a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py index ee442f05..2a8730fa 100644 --- a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py +++ b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py @@ -98,7 +98,7 @@ def processAlgorithm(self, parameters, context, model_feedback): elif matching.shape[0] == 0: create += 1 new = nodes.new_centroid(zone[parameters["node_id"]]) - new.geometry = loads(zone["geom"]) + new.geometry = loads(zone["geometry"]) new.save() elif matching.shape[0] > 1: fail += 1 @@ -128,10 +128,10 @@ def displayName(self): return self.tr("Add/Renumber nodes from layer") def group(self): - return self.tr("Model Building") + return "01-" + self.tr("Model Building") def groupId(self): - return self.tr("Model Building") + return "01-" + self.tr("Model Building") def shortHelpString(self): return f"{self.string_order(1)}\n{self.string_order(2)} {self.string_order(3)}" From 609445c6ac0ddf1c7d5ab92c214df27beb80d1cd Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Wed, 4 Dec 2024 13:54:18 -0300 Subject: [PATCH 02/34] remove unused imports --- .../modules/processing_provider/add_matrix_from_layer.py | 4 +--- qaequilibrae/modules/processing_provider/project_from_OSM.py | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py index e46043ec..17c3d25e 100644 --- a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py @@ -2,15 +2,13 @@ import sys import numpy as np import pandas as pd -from os.path import join import os from scipy.sparse import coo_matrix -from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessingParameterString, QgsProcessingParameterDefinition +from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessingParameterString from qgis.core import QgsProcessingParameterField, QgsProcessingParameterMapLayer, QgsProcessingParameterFile from qgis.core import QgsProcessingAlgorithm -from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt diff --git a/qaequilibrae/modules/processing_provider/project_from_OSM.py b/qaequilibrae/modules/processing_provider/project_from_OSM.py index a1231c68..e9db34bc 100644 --- a/qaequilibrae/modules/processing_provider/project_from_OSM.py +++ b/qaequilibrae/modules/processing_provider/project_from_OSM.py @@ -1,9 +1,6 @@ import importlib.util as iutil -import pandas as pd import sys from os.path import join -from string import ascii_lowercase -from shapely.wkt import loads as load_wkt from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile from qgis.core import QgsProcessingParameterString From c54d44f1c84d73b671eadd0f169887dfe0dec192 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Wed, 4 Dec 2024 14:34:32 -0300 Subject: [PATCH 03/34] rename files --- .../modules/processing_provider/group_i18n.py | 0 .../modules/processing_provider/provider.py | 2 +- test/test_processing_provider.py | 105 +++++++++--------- 3 files changed, 54 insertions(+), 53 deletions(-) delete mode 100644 qaequilibrae/modules/processing_provider/group_i18n.py diff --git a/qaequilibrae/modules/processing_provider/group_i18n.py b/qaequilibrae/modules/processing_provider/group_i18n.py deleted file mode 100644 index e69de29b..00000000 diff --git a/qaequilibrae/modules/processing_provider/provider.py b/qaequilibrae/modules/processing_provider/provider.py index 85d5c652..f0673bc2 100644 --- a/qaequilibrae/modules/processing_provider/provider.py +++ b/qaequilibrae/modules/processing_provider/provider.py @@ -16,7 +16,7 @@ class Provider(QgsProcessingProvider): def loadAlgorithms(self): from .project_from_layer import ProjectFromLayer - from .project_from_OSM import ProjectFromOSM + from .project_from_osm import ProjectFromOSM from .add_connectors import AddConnectors from .assign_traffic_from_yaml import TrafficAssignYAML from .export_matrix import ExportMatrix diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 553e38df..6a17c46b 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -16,10 +16,10 @@ from qaequilibrae.modules.processing_provider.provider import Provider from qaequilibrae.modules.processing_provider.export_matrix import ExportMatrix -from qaequilibrae.modules.processing_provider.matrix_from_layer import MatrixFromLayer +# from qaequilibrae.modules.processing_provider.matrix_from_layer import MatrixFromLayer from qaequilibrae.modules.processing_provider.project_from_layer import ProjectFromLayer from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors -from qaequilibrae.modules.processing_provider.assign_from_yaml import TrafficAssignYAML +# from qaequilibrae.modules.processing_provider.assign_from_yaml import TrafficAssignYAML from qaequilibrae.modules.processing_provider.renumber_nodes_from_layer import RenumberNodesFromLayer @@ -59,42 +59,43 @@ def test_export_matrix(folder_path, source_file, format): assert isfile(result["Output"]) -def test_matrix_from_layer(folder_path): - makedirs(folder_path) +# @pytest.mark.skip +# def test_matrix_from_layer(folder_path): +# makedirs(folder_path) - df = pd.read_csv("test/data/SiouxFalls_project/SiouxFalls_od.csv") - layer = layer_from_dataframe(df, "SiouxFalls_od") +# df = pd.read_csv("test/data/SiouxFalls_project/SiouxFalls_od.csv") +# layer = layer_from_dataframe(df, "SiouxFalls_od") - action = MatrixFromLayer() +# action = MatrixFromLayer() - parameters = { - "matrix_layer": layer, - "origin": "O", - "destination": "D", - "value": "Ton", - "file_name": "siouxfalls_od", - "output_folder": folder_path, - "matrix_name": "NAME_FOR_TEST", - "matrix_description": "this is a description", - "matrix_core": "MAT_CORE", - } +# parameters = { +# "matrix_layer": layer, +# "origin": "O", +# "destination": "D", +# "value": "Ton", +# "file_name": "siouxfalls_od", +# "output_folder": folder_path, +# "matrix_name": "NAME_FOR_TEST", +# "matrix_description": "this is a description", +# "matrix_core": "MAT_CORE", +# } - context = QgsProcessingContext() - feedback = QgsProcessingFeedback() +# context = QgsProcessingContext() +# feedback = QgsProcessingFeedback() - _ = action.run(parameters, context, feedback) +# _ = action.run(parameters, context, feedback) - assert isfile(join(folder_path, f"{parameters['file_name']}.aem")) +# assert isfile(join(folder_path, f"{parameters['file_name']}.aem")) - mat = AequilibraeMatrix() - mat.load(join(folder_path, f"{parameters['file_name']}.aem")) +# mat = AequilibraeMatrix() +# mat.load(join(folder_path, f"{parameters['file_name']}.aem")) - info = mat.__dict__ - assert info["names"] == [parameters["matrix_core"]] - assert parameters["matrix_name"].encode() in info["name"] - assert parameters["matrix_description"].encode() in info["description"] - assert info["zones"] == 24 - assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 +# info = mat.__dict__ +# assert info["names"] == [parameters["matrix_core"]] +# assert parameters["matrix_name"].encode() in info["name"] +# assert parameters["matrix_description"].encode() in info["description"] +# assert info["zones"] == 24 +# assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 @pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) @@ -202,38 +203,38 @@ def test_renumber_from_centroids(ae_with_project, load_sfalls_from_layer): assert node_count == list(range(1001, 1025)) -def test_assign_from_yaml(ae_with_project): - folder = ae_with_project.project.project_base_path - file_path = join(folder, "config.yml") +# def test_assign_from_yaml(ae_with_project): +# folder = ae_with_project.project.project_base_path +# file_path = join(folder, "config.yml") - assert isfile(file_path) +# assert isfile(file_path) - string_to_replace = "path_to_project" +# string_to_replace = "path_to_project" - with open(file_path, "r", encoding="utf-8") as file: - content = file.read() +# with open(file_path, "r", encoding="utf-8") as file: +# content = file.read() - updated_content = re.sub(re.escape(string_to_replace), folder, content) +# updated_content = re.sub(re.escape(string_to_replace), folder, content) - with open(file_path, "w", encoding="utf-8") as file: - file.write(updated_content) +# with open(file_path, "w", encoding="utf-8") as file: +# file.write(updated_content) - action = TrafficAssignYAML() +# action = TrafficAssignYAML() - parameters = {"conf_file": file_path} +# parameters = {"conf_file": file_path} - context = QgsProcessingContext() - feedback = QgsProcessingFeedback() +# context = QgsProcessingContext() +# feedback = QgsProcessingFeedback() - result = action.processAlgorithm(parameters, context, feedback) +# result = action.processAlgorithm(parameters, context, feedback) - assert result["Output"] == "Traffic assignment successfully completed" +# assert result["Output"] == "Traffic assignment successfully completed" - assert isfile(join(folder, "results_database.sqlite")) +# assert isfile(join(folder, "results_database.sqlite")) - conn = sqlite3.connect(join(folder, "results_database.sqlite")) - tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchone()[0] - assert tables == "test_from_yaml" +# conn = sqlite3.connect(join(folder, "results_database.sqlite")) +# tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchone()[0] +# assert tables == "test_from_yaml" - row = conn.execute("SELECT * FROM test_from_yaml;").fetchone() - assert row +# row = conn.execute("SELECT * FROM test_from_yaml;").fetchone() +# assert row From 0bd370a83dd1fe22901d6cd9891893e264c212be Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Wed, 4 Dec 2024 16:34:40 -0300 Subject: [PATCH 04/34] update test and files --- .../processing_provider/Add_connectors.py | 118 ++++++++++++--- .../processing_provider/create_pt_graph.py | 28 ++-- test/test_processing_provider.py | 135 +++++++++++------- 3 files changed, 190 insertions(+), 91 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/Add_connectors.py b/qaequilibrae/modules/processing_provider/Add_connectors.py index 58edac65..e3563166 100644 --- a/qaequilibrae/modules/processing_provider/Add_connectors.py +++ b/qaequilibrae/modules/processing_provider/Add_connectors.py @@ -1,8 +1,13 @@ import importlib.util as iutil import sys +from os.path import join +import pandas as pd -from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessingAlgorithm +from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessing, QgsProcessingAlgorithm from qgis.core import QgsProcessingParameterFile, QgsProcessingParameterNumber, QgsProcessingParameterString +from qgis.core import QgsFeature, QgsVectorLayer, QgsDataSourceUri + +import processing from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt @@ -36,37 +41,106 @@ def initAlgorithm(self, config=None): ) def processAlgorithm(self, parameters, context, model_feedback): - # Checks if we have access to aequilibrae library - if iutil.find_spec("aequilibrae") is None: - sys.exit(self.tr("AequilibraE module not found")) - - from aequilibrae import Project - feedback = QgsProcessingMultiStepFeedback(2, model_feedback) feedback.pushInfo(self.tr("Opening project")) - project = Project() - project.open(parameters["project_path"]) - - nodes = project.network.nodes - centroids = nodes.data[nodes.data["is_centroid"] == 1] + project_path = parameters["project_path"] + + # Import nodes layer + uri = QgsDataSourceUri() + uri.setDatabase(join(project_path, "project_database.sqlite")) + uri.setDataSource("", "nodes", "geometry") + nodes_layer = QgsVectorLayer(uri.uri(), "nodes_layer", "spatialite") + + # Import links layer + uri = QgsDataSourceUri() + uri.setDatabase(join(project_path, "project_database.sqlite")) + uri.setDataSource("", "links", "geometry") + links_layer = QgsVectorLayer(uri.uri(), "links_layer", "spatialite") + + # Get current max link_id + cols = ["link_id", "ogc_fid"] + datagen = ([f[col] for col in cols] for f in links_layer.getFeatures()) + links_ids = pd.DataFrame.from_records(data=datagen, columns=cols) + ogc_id = links_ids["ogc_fid"].max() + 1 + link_id = links_ids["link_id"].max() + 1 feedback.pushInfo(" ") feedback.setCurrentStep(1) - # Adding connectors - num_connectors = parameters["num_connectors"] - mode = parameters["mode"] - feedback.pushInfo(self.tr('Adding {} connectors when none exists for mode "{}"').format(num_connectors, mode)) + feedback.pushInfo(self.tr("Extracting required nodes to process")) + # Extract centroids to connect + alg_params = { + "EXPRESSION": '("is_centroid" = 1) AND ( not("modes" ILIKE \'%' + + parameters["mode"] + + '%\') OR "modes" IS NULL )', + "INPUT": nodes_layer, + "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, + } + ConnectFrom = processing.run( + "native:extractbyexpression", alg_params, context=context, feedback=feedback, is_child_algorithm=True + ) - for _, node in centroids.iterrows(): - cnt = nodes.get(node.node_id) - cnt.connect_mode(mode_id=mode, connectors=num_connectors) + # Extract nodes to connect + alg_params = { + "EXPRESSION": '("is_centroid" = 0) AND ("modes" ILIKE \'%' + parameters["mode"] + "%')", + "INPUT": nodes_layer, + "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, + } + ConnectTo = processing.run( + "native:extractbyexpression", alg_params, context=context, feedback=feedback, is_child_algorithm=True + ) feedback.pushInfo(" ") feedback.setCurrentStep(2) - project.close() + # Computing and adding connectors + feedback.pushInfo( + self.tr('Adding {} connectors when none exists for mode "{}"').format( + parameters["num_connectors"], parameters["mode"] + ) + ) + + alg_params = { + "SOURCE": ConnectFrom["OUTPUT"], + "DESTINATION": ConnectTo["OUTPUT"], + "METHOD": 0, + "DISTANCE": 10, + "NEIGHBORS": parameters["num_connectors"], + "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, + } + Connectors = processing.run( + "native:shortestline", alg_params, context=context, feedback=feedback, is_child_algorithm=True + ) + + connectors_layer = context.takeResultLayer(Connectors["OUTPUT"]) + feature_list = [] + for f in connectors_layer.getFeatures(): + geom = f.geometry() + nf = QgsFeature(links_layer.fields()) + nf.setGeometry(geom) + nf["ogc_fid"] = int(ogc_id) + nf["link_id"] = int(link_id) + nf["a_node"] = 0 + nf["b_node"] = 0 + nf["direction"] = 0 + nf["capacity_ab"] = 99999 + nf["capacity_ba"] = 99999 + nf["link_type"] = "centroid_connector" + nf["name"] = "centroid_connector zone " + str(f["node_id"]) + nf["modes"] = f["modes_2"] + feature_list.append(nf) + ogc_id = ogc_id + 1 + link_id = link_id + 1 + links_layer.startEditing() + links_layer.addFeatures(feature_list) + links_layer.commitChanges() + + feedback.pushInfo(self.tr("{} connectors have been added").format(len(feature_list))) + + feedback.pushInfo(" ") + feedback.setCurrentStep(3) + del feature_list, nodes_layer, links_layer, connectors_layer return {"Output": parameters["project_path"]} @@ -77,10 +151,10 @@ def displayName(self): return self.tr("Add centroid connectors") def group(self): - return self.tr("Model Building") + return "01-" + self.tr("Model Building") def groupId(self): - return self.tr("Model Building") + return "01-" + self.tr("Model Building") def shortHelpString(self): return self.tr("Go through all the centroids and add connectors only if none exists for the chosen mode") diff --git a/qaequilibrae/modules/processing_provider/create_pt_graph.py b/qaequilibrae/modules/processing_provider/create_pt_graph.py index 1167ad77..89efc4ff 100644 --- a/qaequilibrae/modules/processing_provider/create_pt_graph.py +++ b/qaequilibrae/modules/processing_provider/create_pt_graph.py @@ -10,7 +10,7 @@ from qaequilibrae.i18n.translate import trlt -class create_pt_graph(QgsProcessingAlgorithm): +class CreatePTGraph(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): self.addParameter( @@ -48,9 +48,7 @@ def initAlgorithm(self, config=None): param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) self.addParameter(param) - def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(3, model_feedback) - + def processAlgorithm(self, parameters, context, feedback): # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) @@ -65,8 +63,6 @@ def processAlgorithm(self, parameters, context, model_feedback): data = Transit(project) feedback.pushInfo(" ") - feedback.setCurrentStep(1) - feedback.pushInfo(self.tr("Creating graph")) # Creating graph if not parameters["has_zones"]: @@ -77,7 +73,6 @@ def processAlgorithm(self, parameters, context, model_feedback): connector_method="overlapping_regions", ) feedback.pushInfo(" ") - feedback.setCurrentStep(2) # Connector matching project.network.build_graphs() @@ -88,33 +83,28 @@ def processAlgorithm(self, parameters, context, model_feedback): data.save_graphs() feedback.pushInfo(" ") - feedback.setCurrentStep(3) project.close() return {"Output": "PT graph successfully created"} def name(self): - return self.tr("Create PT graph before PT assignment") + return "createptgraph" def displayName(self): - return self.tr("Create PT graph before PT assignment") + return self.tr("Create PT graph") def group(self): - return "04-" + self.tr("Public transport") + return "04-" + self.tr("Public Transport") def groupId(self): - return "04-" + self.tr("Public transport") + return "publictransport" def shortHelpString(self): - return textwrap.dedent("\n".join([self.string_order(1)])) + return "Creates a graph to be used with PT Assignment" def createInstance(self): - return create_pt_graph() - - def string_order(self, order): - if order == 1: - return self.tr("Create a PT graph.") + return CreatePTGraph() def tr(self, message): - return trlt("create_pt_graph", message) + return trlt("CreatePTGraph", message) diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 6a17c46b..1c0b8ecf 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -16,11 +16,14 @@ from qaequilibrae.modules.processing_provider.provider import Provider from qaequilibrae.modules.processing_provider.export_matrix import ExportMatrix + # from qaequilibrae.modules.processing_provider.matrix_from_layer import MatrixFromLayer from qaequilibrae.modules.processing_provider.project_from_layer import ProjectFromLayer -from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors +# from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors # from qaequilibrae.modules.processing_provider.assign_from_yaml import TrafficAssignYAML from qaequilibrae.modules.processing_provider.renumber_nodes_from_layer import RenumberNodesFromLayer +from qaequilibrae.modules.processing_provider.create_pt_graph import CreatePTGraph +from qaequilibrae.modules.processing_provider.assign_pt_from_yaml import ptAssignYAML def qgis_app(): @@ -98,78 +101,78 @@ def test_export_matrix(folder_path, source_file, format): # assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 -@pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) -def test_project_from_layer(folder_path, load_sfalls_from_layer): +# @pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) +# def test_project_from_layer(folder_path, load_sfalls_from_layer): - linkslayer = QgsProject.instance().mapLayersByName("Links layer")[0] +# linkslayer = QgsProject.instance().mapLayersByName("Links layer")[0] - linkslayer.startEditing() - field = QgsField("ltype", QVariant.String) - linkslayer.addAttribute(field) - linkslayer.updateFields() +# linkslayer.startEditing() +# field = QgsField("ltype", QVariant.String) +# linkslayer.addAttribute(field) +# linkslayer.updateFields() - for feature in linkslayer.getFeatures(): - feature["ltype"] = "road" - linkslayer.updateFeature(feature) +# for feature in linkslayer.getFeatures(): +# feature["ltype"] = "road" +# linkslayer.updateFeature(feature) - linkslayer.commitChanges() +# linkslayer.commitChanges() - action = ProjectFromLayer() +# action = ProjectFromLayer() - parameters = { - "links": linkslayer, - "link_id": "link_id", - "link_type": "ltype", - "direction": "direction", - "modes": "modes", - "dst": folder_path, - "project_name": "from_test", - } +# parameters = { +# "links": linkslayer, +# "link_id": "link_id", +# "link_type": "ltype", +# "direction": "direction", +# "modes": "modes", +# "folder": folder_path, +# "project_name": "from_test", +# } - context = QgsProcessingContext() - feedback = QgsProcessingFeedback() +# context = QgsProcessingContext() +# feedback = QgsProcessingFeedback() - result = action.run(parameters, context, feedback) +# result = action.run(parameters, context, feedback) - assert result[0]["Output"] == join(folder_path, parameters["project_name"]) + # assert result[0]["Output"] == join(folder_path, parameters["project_name"]) - QgsProject.instance().clear() + # QgsProject.instance().clear() - project = Project() - project.open(join(folder_path, parameters["project_name"])) + # project = Project() + # project.open(join(folder_path, parameters["project_name"])) - assert project.network.count_links() == 76 - assert project.network.count_nodes() == 24 + # assert project.network.count_links() == 76 + # assert project.network.count_nodes() == 24 -def test_add_centroid_connector(pt_no_feed): - project = pt_no_feed.project - project_folder = project.project_base_path +# def test_add_centroid_connector(pt_no_feed): +# project = pt_no_feed.project +# project_folder = project.project_base_path - nodes = project.network.nodes +# nodes = project.network.nodes - cnt = nodes.new_centroid(100_000) - cnt.geometry = Point(-71.34, -29.95) - cnt.save() +# cnt = nodes.new_centroid(100_000) +# cnt.geometry = Point(-71.34, -29.95) +# cnt.save() - action = AddConnectors() +# action = AddConnectors() - parameters = {"num_connectors": 3, "mode": "c", "project_path": project_folder} +# parameters = {"num_connectors": 3, "mode": "c", "project_path": project_folder} - context = QgsProcessingContext() - feedback = QgsProcessingFeedback() +# context = QgsProcessingContext() +# feedback = QgsProcessingFeedback() - result = action.processAlgorithm(parameters, context, feedback) +# result = action.processAlgorithm(parameters, context, feedback) - assert result["Output"] == project_folder +# assert result["Output"] == project_folder - node_qry = "select count(node_id) from nodes where is_centroid=1" - node_count = project.conn.execute(node_qry).fetchone()[0] - assert node_count == 1 +# node_qry = "select count(node_id) from nodes where is_centroid=1" +# node_count = project.conn.execute(node_qry).fetchone()[0] +# assert node_count == 1 - link_qry = "select count(name) from links where name like 'centroid connector%'" - link_count = project.conn.execute(link_qry).fetchone()[0] - assert link_count == 3 +# link_qry = "select count(name) from links where name like 'centroid connector%'" +# link_count = project.conn.execute(link_qry).fetchone()[0] +# assert link_count == 3 @pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) @@ -238,3 +241,35 @@ def test_renumber_from_centroids(ae_with_project, load_sfalls_from_layer): # row = conn.execute("SELECT * FROM test_from_yaml;").fetchone() # assert row + + +def test_create_pt_graph(coquimbo_project): + + project = coquimbo_project.project + project_folder = project.project_base_path + + action = CreatePTGraph() + + parameters = { + "project_path": project_folder, + "access_mode": "c", + "block_flows": False, + "walking_edges": False, + "outer_stops_transfers": False, + "has_zones": False, + } + + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() + + result = action.run(parameters, context, feedback) + print(result) + + assert result[0]["Output"] == "PT graph successfully created" + + periods = project.network.periods + assert periods.data.shape[0] == 1 + + +def test_pt_assign_yaml(): + pass From f59bbcad7f2d79c75515e2468e54327fab04f541 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Wed, 4 Dec 2024 16:36:18 -0300 Subject: [PATCH 05/34] Update provider.py --- qaequilibrae/modules/processing_provider/provider.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/provider.py b/qaequilibrae/modules/processing_provider/provider.py index f0673bc2..bdb23a1d 100644 --- a/qaequilibrae/modules/processing_provider/provider.py +++ b/qaequilibrae/modules/processing_provider/provider.py @@ -17,7 +17,7 @@ class Provider(QgsProcessingProvider): def loadAlgorithms(self): from .project_from_layer import ProjectFromLayer from .project_from_osm import ProjectFromOSM - from .add_connectors import AddConnectors + from .Add_connectors import AddConnectors from .assign_traffic_from_yaml import TrafficAssignYAML from .export_matrix import ExportMatrix from .create_matrix_from_layer import CreateMatrixFromLayer @@ -26,7 +26,7 @@ def loadAlgorithms(self): from .renumber_nodes_from_layer import RenumberNodesFromLayer from .matrix_calculator import MatrixCalculator from .import_gtfs import ImportGTFS - from .create_pt_graph import create_pt_graph + from .create_pt_graph import CreatePTGraph from .assign_pt_from_yaml import ptAssignYAML self.addAlgorithm(ProjectFromOSM()) @@ -40,7 +40,7 @@ def loadAlgorithms(self): self.addAlgorithm(AddConnectors()) self.addAlgorithm(TrafficAssignYAML()) self.addAlgorithm(ImportGTFS()) - self.addAlgorithm(create_pt_graph()) + self.addAlgorithm(CreatePTGraph()) self.addAlgorithm(ptAssignYAML()) def id(self): @@ -48,7 +48,7 @@ def id(self): This string should be a unique, short, character only string, eg "qgis" or "gdal". This string should not be localised. """ - return "AequilibraE" + return "aequilibrae" def name(self): """The human friendly name of the plugin in Processing. From cf8f6c5b7133632f78da781c4c9086e538833241 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Wed, 4 Dec 2024 17:54:01 -0300 Subject: [PATCH 06/34] update GTFS import --- .../processing_provider/import_gtfs.py | 44 +++++------ .../modules/processing_provider/provider.py | 5 +- test/test_processing_provider.py | 75 ++++++++++++------- 3 files changed, 66 insertions(+), 58 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/import_gtfs.py b/qaequilibrae/modules/processing_provider/import_gtfs.py index 0f5def34..243f568c 100644 --- a/qaequilibrae/modules/processing_provider/import_gtfs.py +++ b/qaequilibrae/modules/processing_provider/import_gtfs.py @@ -1,13 +1,11 @@ import importlib.util as iutil import sys -from datetime import datetime as dt - from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile from qgis.core import QgsProcessingParameterString, QgsProcessingParameterBoolean -from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt +from qaequilibrae.modules.common_tools import standard_path class ImportGTFS(QgsProcessingAlgorithm): @@ -22,35 +20,25 @@ def initAlgorithm(self, config=None): defaultValue=None, ) ) - self.addParameter(QgsProcessingParameterString("agency", self.tr("Agency to import"), multiLine=False)) + self.addParameter(QgsProcessingParameterString("gtfs_agency", self.tr("Transit agency"), multiLine=False)) self.addParameter( QgsProcessingParameterString( - "gtfs_date", self.tr("Date to import (YYYY-MM-DD)"), multiLine=False, defaultValue="2024-01-01" + "gtfs_date", self.tr("Date to import (YYYY-MM-DD)"), multiLine=False, defaultValue="1980-01-01" ) ) self.addParameter( - QgsProcessingParameterBoolean( - "map_match", self.tr("map matching of PT lines on the aequilibrae project network"), defaultValue=True - ) + QgsProcessingParameterBoolean("allow_map_match", self.tr("Map-match transit routes"), defaultValue=True) ) self.addParameter( QgsProcessingParameterFile( - "project", + "project_path", self.tr("Project path"), behavior=QgsProcessingParameterFile.Folder, defaultValue=standard_path(), ) ) - def processAlgorithm(self, parameters, context, model_feedback): - - if parameters["map_match"]: - i = 4 - else: - i = 3 - - feedback = QgsProcessingMultiStepFeedback(i, model_feedback) - + def processAlgorithm(self, parameters, context, feedback): # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) @@ -58,28 +46,30 @@ def processAlgorithm(self, parameters, context, model_feedback): from aequilibrae.project import Project from aequilibrae.transit import Transit + i = 4 if parameters["allow_map_match"] else 3 + feedback = QgsProcessingMultiStepFeedback(i, feedback) feedback.pushInfo(self.tr("Opening project")) # Opening project project = Project() - project.open(parameters["project"]) + project.open(parameters["project_path"]) feedback.setCurrentStep(1) feedback.pushInfo(" ") # Importing GTFS feedback.pushInfo(self.tr("Importing GTFS")) data = Transit(project) - transit = data.new_gtfs_builder(agency=parameters["agency"], file_path=parameters["gtfs_file"]) + transit = data.new_gtfs_builder(agency=parameters["gtfs_agency"], file_path=parameters["gtfs_file"]) transit.load_date(parameters["gtfs_date"]) feedback.setCurrentStep(2) feedback.pushInfo(" ") # Map matching if selected - if str(parameters["map_match"]) == "True": - feedback.pushInfo(self.tr("Map matching of PT lines on available network, it may take a while...")) + if parameters["allow_map_match"]: + feedback.pushInfo(self.tr("Map matching routes, it may take a while...")) transit.set_allow_map_match(True) transit.map_match() - feedback.setCurrentStep(i - 1) + feedback.setCurrentStep(3) feedback.pushInfo(" ") # Saving results @@ -93,19 +83,19 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": "Traffic assignment successfully completed"} def name(self): - return self.tr("Import GTFS") + return "importgtfs" def displayName(self): return self.tr("Import GTFS") def group(self): - return "04-" + self.tr("Public transport") + return "04-" + self.tr("Public Transport") def groupId(self): - return "04-" + self.tr("Public transport") + return "publictransport" def shortHelpString(self): - return self.tr("Add PT lines from a GTFS file to an existing aequilibrae project") + return self.tr("Add PT routes from a GTFS file to an existing AequilibraE project.") def createInstance(self): return ImportGTFS() diff --git a/qaequilibrae/modules/processing_provider/provider.py b/qaequilibrae/modules/processing_provider/provider.py index bdb23a1d..ad4ef06f 100644 --- a/qaequilibrae/modules/processing_provider/provider.py +++ b/qaequilibrae/modules/processing_provider/provider.py @@ -17,7 +17,8 @@ class Provider(QgsProcessingProvider): def loadAlgorithms(self): from .project_from_layer import ProjectFromLayer from .project_from_osm import ProjectFromOSM - from .Add_connectors import AddConnectors + + # from .Add_connectors import AddConnectors from .assign_traffic_from_yaml import TrafficAssignYAML from .export_matrix import ExportMatrix from .create_matrix_from_layer import CreateMatrixFromLayer @@ -37,7 +38,7 @@ def loadAlgorithms(self): self.addAlgorithm(ExportMatrix()) self.addAlgorithm(AddLinksFromLayer()) self.addAlgorithm(RenumberNodesFromLayer()) - self.addAlgorithm(AddConnectors()) + # self.addAlgorithm(AddConnectors()) self.addAlgorithm(TrafficAssignYAML()) self.addAlgorithm(ImportGTFS()) self.addAlgorithm(CreatePTGraph()) diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 1c0b8ecf..41626716 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -24,6 +24,7 @@ from qaequilibrae.modules.processing_provider.renumber_nodes_from_layer import RenumberNodesFromLayer from qaequilibrae.modules.processing_provider.create_pt_graph import CreatePTGraph from qaequilibrae.modules.processing_provider.assign_pt_from_yaml import ptAssignYAML +from qaequilibrae.modules.processing_provider.import_gtfs import ImportGTFS def qgis_app(): @@ -134,45 +135,45 @@ def test_export_matrix(folder_path, source_file, format): # result = action.run(parameters, context, feedback) - # assert result[0]["Output"] == join(folder_path, parameters["project_name"]) +# assert result[0]["Output"] == join(folder_path, parameters["project_name"]) - # QgsProject.instance().clear() +# QgsProject.instance().clear() - # project = Project() - # project.open(join(folder_path, parameters["project_name"])) +# project = Project() +# project.open(join(folder_path, parameters["project_name"])) - # assert project.network.count_links() == 76 - # assert project.network.count_nodes() == 24 +# assert project.network.count_links() == 76 +# assert project.network.count_nodes() == 24 -# def test_add_centroid_connector(pt_no_feed): -# project = pt_no_feed.project -# project_folder = project.project_base_path +def test_add_centroid_connector(pt_no_feed): + project = pt_no_feed.project + project_folder = project.project_base_path -# nodes = project.network.nodes + nodes = project.network.nodes -# cnt = nodes.new_centroid(100_000) -# cnt.geometry = Point(-71.34, -29.95) -# cnt.save() + cnt = nodes.new_centroid(100_000) + cnt.geometry = Point(-71.34, -29.95) + cnt.save() -# action = AddConnectors() + action = AddConnectors() -# parameters = {"num_connectors": 3, "mode": "c", "project_path": project_folder} + parameters = {"num_connectors": 3, "mode": "c", "project_path": project_folder} -# context = QgsProcessingContext() -# feedback = QgsProcessingFeedback() + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() -# result = action.processAlgorithm(parameters, context, feedback) + result = action.processAlgorithm(parameters, context, feedback) -# assert result["Output"] == project_folder + assert result["Output"] == project_folder -# node_qry = "select count(node_id) from nodes where is_centroid=1" -# node_count = project.conn.execute(node_qry).fetchone()[0] -# assert node_count == 1 + node_qry = "select count(node_id) from nodes where is_centroid=1" + node_count = project.conn.execute(node_qry).fetchone()[0] + assert node_count == 1 -# link_qry = "select count(name) from links where name like 'centroid connector%'" -# link_count = project.conn.execute(link_qry).fetchone()[0] -# assert link_count == 3 + link_qry = "select count(name) from links where name like 'centroid connector%'" + link_count = project.conn.execute(link_qry).fetchone()[0] + assert link_count == 3 @pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) @@ -263,13 +264,29 @@ def test_create_pt_graph(coquimbo_project): feedback = QgsProcessingFeedback() result = action.run(parameters, context, feedback) - print(result) - assert result[0]["Output"] == "PT graph successfully created" periods = project.network.periods assert periods.data.shape[0] == 1 -def test_pt_assign_yaml(): - pass +@pytest.mark.parametrize("allow_map_match", [True, False]) +def test_import_gtfs(pt_no_feed, allow_map_match): + project = pt_no_feed.project + project_folder = project.project_base_path + + action = ImportGTFS() + + parameters = { + "project_path": project_folder, + "gtfs_file": "test/data/coquimbo_project/gtfs_coquimbo.zip", + "gtfs_agency": "Lisanco", + "gtfs_date": "2016-04-16", + "allow_map_match": allow_map_match, + } + + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() + + result = action.run(parameters, context, feedback) + assert result[0]["Output"] == "Traffic assignment successfully completed" From f5269b12787b9e75a82265798521b710be8802be Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Thu, 5 Dec 2024 08:33:06 -0300 Subject: [PATCH 07/34] remove str localization --- .../processing_provider/Add_connectors.py | 4 ++-- .../add_links_from_layer.py | 6 ++--- .../add_matrix_from_layer.py | 4 ++-- .../assign_pt_from_yaml.py | 6 ++--- .../assign_traffic_from_yaml.py | 4 ++-- .../create_matrix_from_layer.py | 4 ++-- .../processing_provider/export_matrix.py | 4 ++-- .../processing_provider/group_string_match.py | 23 +++++++++++++++++++ .../processing_provider/matrix_calculator.py | 4 ++-- .../processing_provider/project_from_OSM.py | 4 ++-- .../processing_provider/project_from_layer.py | 4 ++-- .../renumber_nodes_from_layer.py | 9 ++++---- 12 files changed, 50 insertions(+), 26 deletions(-) create mode 100644 qaequilibrae/modules/processing_provider/group_string_match.py diff --git a/qaequilibrae/modules/processing_provider/Add_connectors.py b/qaequilibrae/modules/processing_provider/Add_connectors.py index e3563166..2939d2d7 100644 --- a/qaequilibrae/modules/processing_provider/Add_connectors.py +++ b/qaequilibrae/modules/processing_provider/Add_connectors.py @@ -145,7 +145,7 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": parameters["project_path"]} def name(self): - return self.tr("Add centroid connectors") + return "addcentroidconnector" def displayName(self): return self.tr("Add centroid connectors") @@ -154,7 +154,7 @@ def group(self): return "01-" + self.tr("Model Building") def groupId(self): - return "01-" + self.tr("Model Building") + return "modelbuilding" def shortHelpString(self): return self.tr("Go through all the centroids and add connectors only if none exists for the chosen mode") diff --git a/qaequilibrae/modules/processing_provider/add_links_from_layer.py b/qaequilibrae/modules/processing_provider/add_links_from_layer.py index 1a960aa3..148a1b6f 100644 --- a/qaequilibrae/modules/processing_provider/add_links_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_links_from_layer.py @@ -158,16 +158,16 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": project_path} def name(self): - return self.tr("Add links from layer to project") + return "addlinksfromlayer" def displayName(self): return self.tr("Add links from layer to project") def group(self): - return "01-" + self.tr("Model Building") + return def groupId(self): - return "01-" + self.tr("Model Building") + return "modelbuilding" def shortHelpString(self): return self.tr("Take links from a layer and add them to an existing AequilibraE project") diff --git a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py index 17c3d25e..3cc20cf8 100644 --- a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py @@ -153,7 +153,7 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": f"{mat.name}, {mat.description} ({matrix_file})"} def name(self): - return self.tr("Add matrix from layer to aem file") + return "exportmatrixasaem" def displayName(self): return self.tr("Add matrix from layer to aem file") @@ -162,7 +162,7 @@ def group(self): return "02-" + self.tr("Data") def groupId(self): - return "02-" + self.tr("Data") + return "data" def shortHelpString(self): return "\n".join( diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py index 4310a7aa..f8a7a0d1 100644 --- a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -118,16 +118,16 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": "PT assignment successfully completed"} def name(self): - return self.tr("PT assignment from file") + return "ptassignfromyaml" def displayName(self): return self.tr("PT assignment from file") def group(self): - return "04-" + self.tr("Public transport") + return "04-" + self.tr("Public Transport") def groupId(self): - return "04-" + self.tr("Public transport") + return "publictransport" def shortHelpString(self): return textwrap.dedent("\n".join([self.string_order(1), self.string_order(2), self.string_order(3)])) diff --git a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py index 5e896f8f..e7c49fc6 100644 --- a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py @@ -159,7 +159,7 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": "Traffic assignment successfully completed"} def name(self): - return self.tr("Traffic assignment from file") + return "assignmentfromyaml" def displayName(self): return self.tr("Traffic assignment from file") @@ -168,7 +168,7 @@ def group(self): return "03-" + self.tr("Paths and assignment") def groupId(self): - return "03-" + self.tr("Paths and assignment") + return "pathsandassignment" def shortHelpString(self): return textwrap.dedent("\n".join([self.string_order(1), self.string_order(2), self.string_order(3)])) diff --git a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py index b5adcff6..1a394957 100644 --- a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py @@ -152,7 +152,7 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": f"{mat.name}, {mat.description} ({file_name})"} def name(self): - return self.tr("Create aem matrix file from layer") + return "aemfromlayer" def displayName(self): return self.tr("Create aem matrix file from layer") @@ -161,7 +161,7 @@ def group(self): return "02-" + self.tr("Data") def groupId(self): - return "02-" + self.tr("Data") + return "data" def shortHelpString(self): return "\n".join([self.string_order(1), self.string_order(2), self.string_order(3), self.string_order(4)]) diff --git a/qaequilibrae/modules/processing_provider/export_matrix.py b/qaequilibrae/modules/processing_provider/export_matrix.py index 2211f054..ebf11091 100644 --- a/qaequilibrae/modules/processing_provider/export_matrix.py +++ b/qaequilibrae/modules/processing_provider/export_matrix.py @@ -66,7 +66,7 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": dst_path} def name(self): - return self.tr("Export matrices") + return "exportmatrices" def displayName(self): return self.tr("Export matrices") @@ -75,7 +75,7 @@ def group(self): return "02-" + self.tr("Data") def groupId(self): - return "02-" + self.tr("Data") + return "data" def shortHelpString(self): return self.tr("Export an existing *.omx or *.aem matrix file into *.csv, *.aem or *.omx") diff --git a/qaequilibrae/modules/processing_provider/group_string_match.py b/qaequilibrae/modules/processing_provider/group_string_match.py new file mode 100644 index 00000000..d2488e17 --- /dev/null +++ b/qaequilibrae/modules/processing_provider/group_string_match.py @@ -0,0 +1,23 @@ +from qaequilibrae.i18n.translate import trlt as tr + + +group_id_number = { + "modelbuilding": 1, + "data": 2, + "pathsandassignment": 3, + "publictransport": 4, +} + +group_name = { + 1: "Model Building", + 2: "Data", + 3: "Paths and assignment", + 4: "Public Transport", +} + + +def translate_group(context, group): + num = group_id_number[group] + name = tr(context, group_name[num]) + + return f"{num}. {name}" diff --git a/qaequilibrae/modules/processing_provider/matrix_calculator.py b/qaequilibrae/modules/processing_provider/matrix_calculator.py index 0cbfe053..f3ddb5f4 100644 --- a/qaequilibrae/modules/processing_provider/matrix_calculator.py +++ b/qaequilibrae/modules/processing_provider/matrix_calculator.py @@ -163,7 +163,7 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": self.tr("Calculation completed in: ") + str((dt.now() - start).total_seconds()) + "secs"} def name(self): - return self.tr("Matrix calculator") + return "matrixcald" def displayName(self): return self.tr("Matrix calculator") @@ -172,7 +172,7 @@ def group(self): return "02-" + self.tr("Data") def groupId(self): - return "02-" + self.tr("Data") + return "data" def shortHelpString(self): return textwrap.dedent( diff --git a/qaequilibrae/modules/processing_provider/project_from_OSM.py b/qaequilibrae/modules/processing_provider/project_from_OSM.py index e9db34bc..5f8d1834 100644 --- a/qaequilibrae/modules/processing_provider/project_from_OSM.py +++ b/qaequilibrae/modules/processing_provider/project_from_OSM.py @@ -56,7 +56,7 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": project_path} def name(self): - return self.tr("Create project from OSM") + return "projectfromosm" def displayName(self): return self.tr("Create project from OSM") @@ -65,7 +65,7 @@ def group(self): return "01-" + self.tr("Model Building") def groupId(self): - return "01-" + self.tr("Model Building") + return "modelbuilding" def shortHelpString(self): return self.tr("Create an AequilibraE project from OpenStreetMap") diff --git a/qaequilibrae/modules/processing_provider/project_from_layer.py b/qaequilibrae/modules/processing_provider/project_from_layer.py index fc3ee65f..bbce9bfd 100644 --- a/qaequilibrae/modules/processing_provider/project_from_layer.py +++ b/qaequilibrae/modules/processing_provider/project_from_layer.py @@ -172,7 +172,7 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": project_path} def name(self): - return self.tr("Create project from link layer") + return "projectfromlayer" def displayName(self): return self.tr("Create project from link layer") @@ -181,7 +181,7 @@ def group(self): return "01-" + self.tr("Model Building") def groupId(self): - return "01-" + self.tr("Model Building") + return "modelbuilding" def shortHelpString(self): return self.tr("Create an AequilibraE project from a given link layer") diff --git a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py index 2a8730fa..60ef147a 100644 --- a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py +++ b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py @@ -7,8 +7,9 @@ from qgis.core import QgsProcessing, QgsProcessingMultiStepFeedback, QgsProcessingAlgorithm from qgis.core import QgsProcessingParameterVectorLayer, QgsProcessingParameterField, QgsProcessingParameterFile -from qaequilibrae.modules.common_tools import standard_path +from .group_string_match import translate_group from qaequilibrae.i18n.translate import trlt +from qaequilibrae.modules.common_tools import standard_path class RenumberNodesFromLayer(QgsProcessingAlgorithm): @@ -122,16 +123,16 @@ def processAlgorithm(self, parameters, context, model_feedback): return {"Output": parameters["project_path"]} def name(self): - return self.tr("Add/Renumber nodes from layer") + return "renumbernodes" def displayName(self): return self.tr("Add/Renumber nodes from layer") def group(self): - return "01-" + self.tr("Model Building") + return translate_group("RenumberNodesFromLayer", self.groupId) def groupId(self): - return "01-" + self.tr("Model Building") + return "modelbuilding" def shortHelpString(self): return f"{self.string_order(1)}\n{self.string_order(2)} {self.string_order(3)}" From 1712eadede408a861f3e149c47a08b63216dd927 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Thu, 5 Dec 2024 08:39:07 -0300 Subject: [PATCH 08/34] localization --- .../processing_provider/Add_connectors.py | 2 +- .../add_links_from_layer.py | 2 +- .../add_matrix_from_layer.py | 2 +- .../assign_pt_from_yaml.py | 2 +- .../assign_traffic_from_yaml.py | 2 +- .../create_matrix_from_layer.py | 2 +- .../processing_provider/create_pt_graph.py | 2 +- .../processing_provider/export_matrix.py | 2 +- .../processing_provider/group_string_match.py | 23 ------------------- .../processing_provider/import_gtfs.py | 2 +- .../processing_provider/matrix_calculator.py | 2 +- .../processing_provider/project_from_OSM.py | 2 +- .../processing_provider/project_from_layer.py | 2 +- .../renumber_nodes_from_layer.py | 3 +-- 14 files changed, 13 insertions(+), 37 deletions(-) delete mode 100644 qaequilibrae/modules/processing_provider/group_string_match.py diff --git a/qaequilibrae/modules/processing_provider/Add_connectors.py b/qaequilibrae/modules/processing_provider/Add_connectors.py index 2939d2d7..1a7906b6 100644 --- a/qaequilibrae/modules/processing_provider/Add_connectors.py +++ b/qaequilibrae/modules/processing_provider/Add_connectors.py @@ -151,7 +151,7 @@ def displayName(self): return self.tr("Add centroid connectors") def group(self): - return "01-" + self.tr("Model Building") + return self.tr("1. Model Building") def groupId(self): return "modelbuilding" diff --git a/qaequilibrae/modules/processing_provider/add_links_from_layer.py b/qaequilibrae/modules/processing_provider/add_links_from_layer.py index 148a1b6f..4b128989 100644 --- a/qaequilibrae/modules/processing_provider/add_links_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_links_from_layer.py @@ -164,7 +164,7 @@ def displayName(self): return self.tr("Add links from layer to project") def group(self): - return + return self.tr("1. Model Building") def groupId(self): return "modelbuilding" diff --git a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py index 3cc20cf8..58953ff6 100644 --- a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py @@ -159,7 +159,7 @@ def displayName(self): return self.tr("Add matrix from layer to aem file") def group(self): - return "02-" + self.tr("Data") + return self.tr("2. Data") def groupId(self): return "data" diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py index f8a7a0d1..32dc4f24 100644 --- a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -124,7 +124,7 @@ def displayName(self): return self.tr("PT assignment from file") def group(self): - return "04-" + self.tr("Public Transport") + return self.tr("4. Public Transport") def groupId(self): return "publictransport" diff --git a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py index e7c49fc6..e502dc0f 100644 --- a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py @@ -165,7 +165,7 @@ def displayName(self): return self.tr("Traffic assignment from file") def group(self): - return "03-" + self.tr("Paths and assignment") + return self.tr("3. Paths and assignment") def groupId(self): return "pathsandassignment" diff --git a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py index 1a394957..273ab4a9 100644 --- a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py @@ -158,7 +158,7 @@ def displayName(self): return self.tr("Create aem matrix file from layer") def group(self): - return "02-" + self.tr("Data") + return self.tr("2. Data") def groupId(self): return "data" diff --git a/qaequilibrae/modules/processing_provider/create_pt_graph.py b/qaequilibrae/modules/processing_provider/create_pt_graph.py index 89efc4ff..b020e78f 100644 --- a/qaequilibrae/modules/processing_provider/create_pt_graph.py +++ b/qaequilibrae/modules/processing_provider/create_pt_graph.py @@ -95,7 +95,7 @@ def displayName(self): return self.tr("Create PT graph") def group(self): - return "04-" + self.tr("Public Transport") + return self.tr("4. Public Transport") def groupId(self): return "publictransport" diff --git a/qaequilibrae/modules/processing_provider/export_matrix.py b/qaequilibrae/modules/processing_provider/export_matrix.py index ebf11091..e0b535f4 100644 --- a/qaequilibrae/modules/processing_provider/export_matrix.py +++ b/qaequilibrae/modules/processing_provider/export_matrix.py @@ -72,7 +72,7 @@ def displayName(self): return self.tr("Export matrices") def group(self): - return "02-" + self.tr("Data") + return self.tr("2. Data") def groupId(self): return "data" diff --git a/qaequilibrae/modules/processing_provider/group_string_match.py b/qaequilibrae/modules/processing_provider/group_string_match.py deleted file mode 100644 index d2488e17..00000000 --- a/qaequilibrae/modules/processing_provider/group_string_match.py +++ /dev/null @@ -1,23 +0,0 @@ -from qaequilibrae.i18n.translate import trlt as tr - - -group_id_number = { - "modelbuilding": 1, - "data": 2, - "pathsandassignment": 3, - "publictransport": 4, -} - -group_name = { - 1: "Model Building", - 2: "Data", - 3: "Paths and assignment", - 4: "Public Transport", -} - - -def translate_group(context, group): - num = group_id_number[group] - name = tr(context, group_name[num]) - - return f"{num}. {name}" diff --git a/qaequilibrae/modules/processing_provider/import_gtfs.py b/qaequilibrae/modules/processing_provider/import_gtfs.py index 243f568c..68b1c57f 100644 --- a/qaequilibrae/modules/processing_provider/import_gtfs.py +++ b/qaequilibrae/modules/processing_provider/import_gtfs.py @@ -89,7 +89,7 @@ def displayName(self): return self.tr("Import GTFS") def group(self): - return "04-" + self.tr("Public Transport") + return self.tr("4. Public Transport") def groupId(self): return "publictransport" diff --git a/qaequilibrae/modules/processing_provider/matrix_calculator.py b/qaequilibrae/modules/processing_provider/matrix_calculator.py index f3ddb5f4..dcb61871 100644 --- a/qaequilibrae/modules/processing_provider/matrix_calculator.py +++ b/qaequilibrae/modules/processing_provider/matrix_calculator.py @@ -169,7 +169,7 @@ def displayName(self): return self.tr("Matrix calculator") def group(self): - return "02-" + self.tr("Data") + return self.tr("2. Data") def groupId(self): return "data" diff --git a/qaequilibrae/modules/processing_provider/project_from_OSM.py b/qaequilibrae/modules/processing_provider/project_from_OSM.py index 5f8d1834..89346fe9 100644 --- a/qaequilibrae/modules/processing_provider/project_from_OSM.py +++ b/qaequilibrae/modules/processing_provider/project_from_OSM.py @@ -62,7 +62,7 @@ def displayName(self): return self.tr("Create project from OSM") def group(self): - return "01-" + self.tr("Model Building") + return self.tr("1. Model Building") def groupId(self): return "modelbuilding" diff --git a/qaequilibrae/modules/processing_provider/project_from_layer.py b/qaequilibrae/modules/processing_provider/project_from_layer.py index bbce9bfd..5c3ac19e 100644 --- a/qaequilibrae/modules/processing_provider/project_from_layer.py +++ b/qaequilibrae/modules/processing_provider/project_from_layer.py @@ -178,7 +178,7 @@ def displayName(self): return self.tr("Create project from link layer") def group(self): - return "01-" + self.tr("Model Building") + return self.tr("1. Model Building") def groupId(self): return "modelbuilding" diff --git a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py index 60ef147a..77c5a859 100644 --- a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py +++ b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py @@ -7,7 +7,6 @@ from qgis.core import QgsProcessing, QgsProcessingMultiStepFeedback, QgsProcessingAlgorithm from qgis.core import QgsProcessingParameterVectorLayer, QgsProcessingParameterField, QgsProcessingParameterFile -from .group_string_match import translate_group from qaequilibrae.i18n.translate import trlt from qaequilibrae.modules.common_tools import standard_path @@ -129,7 +128,7 @@ def displayName(self): return self.tr("Add/Renumber nodes from layer") def group(self): - return translate_group("RenumberNodesFromLayer", self.groupId) + return self.tr("1. Model Building") def groupId(self): return "modelbuilding" From feeac67807a56d3ed6aac74555c0b13c1367c517 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Thu, 5 Dec 2024 10:47:37 -0300 Subject: [PATCH 09/34] Fix tests --- .../assign_traffic_from_yaml.py | 71 +++----- .../processing_provider/export_matrix.py | 36 ++-- test/data/SiouxFalls_project/config.yml | 5 +- test/test_processing_provider.py | 155 +++++++++--------- 4 files changed, 126 insertions(+), 141 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py index e502dc0f..f8a327f2 100644 --- a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py @@ -1,11 +1,9 @@ import importlib.util as iutil import sys import textwrap - -from datetime import datetime as dt +import yaml from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile -from qgis.core import QgsProcessingParameterDefinition, QgsProcessingParameterBoolean from qaequilibrae.i18n.translate import trlt @@ -23,36 +21,26 @@ def initAlgorithm(self, config=None): ) ) - advparams = [ - QgsProcessingParameterBoolean( - "datetime_to_resultname", self.tr("Include current datetime to result name"), defaultValue=True - ) - ] - - for param in advparams: - param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) - self.addParameter(param) - def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(5, model_feedback) - # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) - from aequilibrae.paths import TrafficAssignment, TrafficClass - from aequilibrae.project import Project + from aequilibrae import Project from aequilibrae.matrix import AequilibraeMatrix - import yaml + from aequilibrae.paths import TrafficAssignment, TrafficClass + feedback = QgsProcessingMultiStepFeedback(5, model_feedback) feedback.pushInfo(self.tr("Getting parameters from YAML")) + pathfile = parameters["conf_file"] with open(pathfile, "r") as f: params = yaml.safe_load(f) + feedback.pushInfo(" ") feedback.setCurrentStep(1) - feedback.pushInfo(self.tr("Opening project")) + # Opening project project = Project() project.open(params["project"]) @@ -63,17 +51,12 @@ def processAlgorithm(self, parameters, context, model_feedback): # Creating traffic classes traffic_classes = [] feedback.pushInfo(self.tr("{} traffic classes have been found").format(len(params["traffic_classes"]))) - select_links = "select_links" in params and params["select_links"] + select_links = True if "select_links" in params and params["select_links"] is not None else False if select_links: selection_dict = {} for selections in params["select_links"]: - for name in selections: - link_list = "" - for text in selections[name]: - link_list = link_list + "," + text - link_list = "[" + link_list[1:] + "]" - link_list = eval(link_list) - selection_dict[name] = link_list + for name, pairs in selections.items(): + selection_dict[name] = [tuple(p) for p in pairs] for classes in params["traffic_classes"]: for traffic in classes: @@ -86,12 +69,9 @@ def processAlgorithm(self, parameters, context, model_feedback): # Getting graph graph = project.network.graphs[classes[traffic]["network_mode"]] graph.set_graph(params["assignment"]["time_field"]) - if str(classes[traffic]["blocked_centroid_flows"]) == "True": - graph.set_blocked_centroid_flows(True) - else: - graph.set_blocked_centroid_flows(False) + graph.set_blocked_centroid_flows(classes[traffic]["blocked_centroid_flows"]) - if "skims" in classes[traffic] and classes[traffic]["skims"]: + if classes[traffic]["skims"] is not None: skims = [sk.strip() for sk in classes[traffic]["skims"].split(",")] graph.set_skimming(skims) @@ -99,21 +79,21 @@ def processAlgorithm(self, parameters, context, model_feedback): assigclass = TrafficClass(name=traffic, graph=graph, matrix=demand) assigclass.set_pce(classes[traffic]["pce"]) - if "fixed_cost" in classes[traffic] and classes[traffic]["fixed_cost"]: + if "fixed_cost" in classes[traffic] and classes[traffic]["fixed_cost"] is not None: if isinstance(classes[traffic]["vot"], (int, float)): assigclass.set_fixed_cost(classes[traffic]["fixed_cost"]) assigclass.set_vot(classes[traffic]["vot"]) else: - sys.exit("error: fixed_cost must come with a correct value of time") + sys.exit("Error: fixed_cost must come with a correct value of time") # Adding select links analysis if select_links: assigclass.set_select_links(selection_dict) # Adding class + traffic_classes.append(assigclass) feedback.pushInfo(f"\t- {traffic} ' ' {str(classes[traffic])}") - traffic_classes.append(assigclass) feedback.pushInfo(" ") feedback.setCurrentStep(2) @@ -137,20 +117,19 @@ def processAlgorithm(self, parameters, context, model_feedback): # Running assignment feedback.pushInfo(self.tr("Running assignment")) - assig.execute() feedback.pushInfo(" ") feedback.setCurrentStep(4) + assig.execute() # Saving outputs feedback.pushInfo(self.tr("Saving outputs")) - feedback.pushInfo(str(assig.report())) - if str(parameters["datetime_to_resultname"]) == "True": - params["result_name"] = params["result_name"] + dt.now().strftime("_%Y-%m-%d_%Hh%M") assig.save_results(params["result_name"]) - assig.save_skims(params["result_name"], which_ones="all", format="aem") + assig.save_skims(params["result_name"], which_ones="all", format="omx") + if select_links: - assig.procedure_id = assig.procedure_id + "_S" - assig.save_select_link_results(params["result_name"]) + assig.procedure_id += "SLA" + sl_name = f"{params["result_name"]}_select_link_analysis" + assig.save_select_link_results(sl_name) feedback.pushInfo(" ") feedback.setCurrentStep(5) @@ -185,7 +164,7 @@ def string_order(self, order): return textwrap.dedent( """\ project: D:/AequilibraE/Project/ - result_name: sce_from_yaml + result_name: your_result_name traffic_classes: - car: matrix_path: D:/AequilibraE/Project/matrices/demand.aem @@ -211,9 +190,9 @@ def string_order(self, order): time_field: travel_time max_iter: 250 rgap: 0.00001 - select_links: #optionnal, name with a list of tuples as [(link_id, link_direction)] - - survey_site_1: [(23,0)] - - est-west-transit: [(12, 1),(402, 1)] + select_links: # optional, name with a list of lists as [[link_id, link_direction]] + - from_node_1: [[1, 1], [2, 1]] + - random_nodes: [[3, 1], [5, 1]] """ ) diff --git a/qaequilibrae/modules/processing_provider/export_matrix.py b/qaequilibrae/modules/processing_provider/export_matrix.py index e0b535f4..61c4d133 100644 --- a/qaequilibrae/modules/processing_provider/export_matrix.py +++ b/qaequilibrae/modules/processing_provider/export_matrix.py @@ -1,7 +1,5 @@ import importlib.util as iutil -import tempfile import sys -from pathlib import Path from os.path import join from qgis.core import QgsProcessingAlgorithm, QgsProcessingParameterFile, QgsProcessingParameterEnum @@ -38,29 +36,31 @@ def initAlgorithm(self, config=None): ) ) - def processAlgorithm(self, parameters, context, model_feedback): - - src_path = parameters["src"] - file_format = [".csv", ".omx", ".aem"] - format = file_format[parameters["output_format"]] - dst_path = join(parameters["dst"], f"{Path(src_path).stem}.{format}") - + def processAlgorithm(self, parameters, context, feedback): # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) from aequilibrae.matrix import AequilibraeMatrix - if src_path[-3:] == "omx": - tmpmat = AequilibraeMatrix() - tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".aem").name - tmpmat.create_from_omx(tmp, src_path) - tmpmat.export(tmp) - src_path = tmp - tmpmat.close() + file_format = ["csv", "omx", "aem"] + format = file_format[parameters["output_format"]] + file_name, ext = parameters["src"].split("/")[-1].split(".") + dst_path = join(parameters["dst"], f"{file_name}.{format}") + + kwargs = {"file_path": dst_path, "memory_only": False} mat = AequilibraeMatrix() - mat.load(src_path) - mat.export(dst_path) + + if ext == "omx": + if format == "omx": + mat.create_from_omx(omx_path=parameters["src"], **kwargs) + elif format in ["csv", "aem"]: + mat.create_from_omx(parameters["src"]) + mat.export(dst_path) + elif ext == "aem": + mat.load(parameters["src"]) + mat.export(dst_path) + mat.close() return {"Output": dst_path} diff --git a/test/data/SiouxFalls_project/config.yml b/test/data/SiouxFalls_project/config.yml index 911922fd..bee1c7e7 100644 --- a/test/data/SiouxFalls_project/config.yml +++ b/test/data/SiouxFalls_project/config.yml @@ -16,4 +16,7 @@ assignment: capacity_field: capacity time_field: free_flow_time max_iter: 10 - rgap: 0.001 \ No newline at end of file + rgap: 0.001 +select_links: + - from_node_1: [[1, 1], [2, 1]] + - random_nodes: [[3, 1], [5, 1]] diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 41626716..c7a5e3ce 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -15,16 +15,19 @@ from qaequilibrae.modules.common_tools.data_layer_from_dataframe import layer_from_dataframe from qaequilibrae.modules.processing_provider.provider import Provider -from qaequilibrae.modules.processing_provider.export_matrix import ExportMatrix -# from qaequilibrae.modules.processing_provider.matrix_from_layer import MatrixFromLayer -from qaequilibrae.modules.processing_provider.project_from_layer import ProjectFromLayer # from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors -# from qaequilibrae.modules.processing_provider.assign_from_yaml import TrafficAssignYAML -from qaequilibrae.modules.processing_provider.renumber_nodes_from_layer import RenumberNodesFromLayer -from qaequilibrae.modules.processing_provider.create_pt_graph import CreatePTGraph +from qaequilibrae.modules.processing_provider.add_links_from_layer import AddLinksFromLayer +from qaequilibrae.modules.processing_provider.add_matrix_from_layer import AddMatrixFromLayer from qaequilibrae.modules.processing_provider.assign_pt_from_yaml import ptAssignYAML +from qaequilibrae.modules.processing_provider.assign_traffic_from_yaml import TrafficAssignYAML +from qaequilibrae.modules.processing_provider.create_matrix_from_layer import CreateMatrixFromLayer +from qaequilibrae.modules.processing_provider.create_pt_graph import CreatePTGraph +from qaequilibrae.modules.processing_provider.export_matrix import ExportMatrix from qaequilibrae.modules.processing_provider.import_gtfs import ImportGTFS +from qaequilibrae.modules.processing_provider.matrix_calculator import MatrixCalculator +from qaequilibrae.modules.processing_provider.project_from_layer import ProjectFromLayer +from qaequilibrae.modules.processing_provider.renumber_nodes_from_layer import RenumberNodesFromLayer def qgis_app(): @@ -63,43 +66,43 @@ def test_export_matrix(folder_path, source_file, format): assert isfile(result["Output"]) -# @pytest.mark.skip -# def test_matrix_from_layer(folder_path): -# makedirs(folder_path) +@pytest.mark.skip +def test_matrix_from_layer(folder_path): + makedirs(folder_path) -# df = pd.read_csv("test/data/SiouxFalls_project/SiouxFalls_od.csv") -# layer = layer_from_dataframe(df, "SiouxFalls_od") + df = pd.read_csv("test/data/SiouxFalls_project/SiouxFalls_od.csv") + layer = layer_from_dataframe(df, "SiouxFalls_od") -# action = MatrixFromLayer() + action = AddMatrixFromLayer() -# parameters = { -# "matrix_layer": layer, -# "origin": "O", -# "destination": "D", -# "value": "Ton", -# "file_name": "siouxfalls_od", -# "output_folder": folder_path, -# "matrix_name": "NAME_FOR_TEST", -# "matrix_description": "this is a description", -# "matrix_core": "MAT_CORE", -# } + parameters = { + "matrix_layer": layer, + "origin": "O", + "destination": "D", + "value": "Ton", + "file_name": "siouxfalls_od", + "output_folder": folder_path, + "matrix_name": "NAME_FOR_TEST", + "matrix_description": "this is a description", + "matrix_core": "MAT_CORE", + } -# context = QgsProcessingContext() -# feedback = QgsProcessingFeedback() + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() -# _ = action.run(parameters, context, feedback) + _ = action.run(parameters, context, feedback) -# assert isfile(join(folder_path, f"{parameters['file_name']}.aem")) + assert isfile(join(folder_path, f"{parameters['file_name']}.aem")) -# mat = AequilibraeMatrix() -# mat.load(join(folder_path, f"{parameters['file_name']}.aem")) + mat = AequilibraeMatrix() + mat.load(join(folder_path, f"{parameters['file_name']}.aem")) -# info = mat.__dict__ -# assert info["names"] == [parameters["matrix_core"]] -# assert parameters["matrix_name"].encode() in info["name"] -# assert parameters["matrix_description"].encode() in info["description"] -# assert info["zones"] == 24 -# assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 + info = mat.__dict__ + assert info["names"] == [parameters["matrix_core"]] + assert parameters["matrix_name"].encode() in info["name"] + assert parameters["matrix_description"].encode() in info["description"] + assert info["zones"] == 24 + assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 # @pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) @@ -146,34 +149,34 @@ def test_export_matrix(folder_path, source_file, format): # assert project.network.count_nodes() == 24 -def test_add_centroid_connector(pt_no_feed): - project = pt_no_feed.project - project_folder = project.project_base_path +# def test_add_centroid_connector(pt_no_feed): +# project = pt_no_feed.project +# project_folder = project.project_base_path - nodes = project.network.nodes +# nodes = project.network.nodes - cnt = nodes.new_centroid(100_000) - cnt.geometry = Point(-71.34, -29.95) - cnt.save() +# cnt = nodes.new_centroid(100_000) +# cnt.geometry = Point(-71.34, -29.95) +# cnt.save() - action = AddConnectors() +# action = AddConnectors() - parameters = {"num_connectors": 3, "mode": "c", "project_path": project_folder} +# parameters = {"num_connectors": 3, "mode": "c", "project_path": project_folder} - context = QgsProcessingContext() - feedback = QgsProcessingFeedback() +# context = QgsProcessingContext() +# feedback = QgsProcessingFeedback() - result = action.processAlgorithm(parameters, context, feedback) +# result = action.processAlgorithm(parameters, context, feedback) - assert result["Output"] == project_folder +# assert result["Output"] == project_folder - node_qry = "select count(node_id) from nodes where is_centroid=1" - node_count = project.conn.execute(node_qry).fetchone()[0] - assert node_count == 1 +# node_qry = "select count(node_id) from nodes where is_centroid=1" +# node_count = project.conn.execute(node_qry).fetchone()[0] +# assert node_count == 1 - link_qry = "select count(name) from links where name like 'centroid connector%'" - link_count = project.conn.execute(link_qry).fetchone()[0] - assert link_count == 3 +# link_qry = "select count(name) from links where name like 'centroid connector%'" +# link_count = project.conn.execute(link_qry).fetchone()[0] +# assert link_count == 3 @pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) @@ -207,41 +210,41 @@ def test_renumber_from_centroids(ae_with_project, load_sfalls_from_layer): assert node_count == list(range(1001, 1025)) -# def test_assign_from_yaml(ae_with_project): -# folder = ae_with_project.project.project_base_path -# file_path = join(folder, "config.yml") +def test_assign_from_yaml(ae_with_project): + folder = ae_with_project.project.project_base_path + file_path = join(folder, "config.yml") -# assert isfile(file_path) + assert isfile(file_path) -# string_to_replace = "path_to_project" + string_to_replace = "path_to_project" -# with open(file_path, "r", encoding="utf-8") as file: -# content = file.read() + with open(file_path, "r", encoding="utf-8") as file: + content = file.read() -# updated_content = re.sub(re.escape(string_to_replace), folder, content) + updated_content = re.sub(re.escape(string_to_replace), folder, content) -# with open(file_path, "w", encoding="utf-8") as file: -# file.write(updated_content) + with open(file_path, "w", encoding="utf-8") as file: + file.write(updated_content) -# action = TrafficAssignYAML() + action = TrafficAssignYAML() -# parameters = {"conf_file": file_path} + parameters = {"conf_file": file_path} -# context = QgsProcessingContext() -# feedback = QgsProcessingFeedback() + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() -# result = action.processAlgorithm(parameters, context, feedback) + result = action.processAlgorithm(parameters, context, feedback) -# assert result["Output"] == "Traffic assignment successfully completed" + assert result["Output"] == "Traffic assignment successfully completed" -# assert isfile(join(folder, "results_database.sqlite")) + assert isfile(join(folder, "results_database.sqlite")) -# conn = sqlite3.connect(join(folder, "results_database.sqlite")) -# tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchone()[0] -# assert tables == "test_from_yaml" + conn = sqlite3.connect(join(folder, "results_database.sqlite")) + tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchone()[0] + assert tables == "test_from_yaml" -# row = conn.execute("SELECT * FROM test_from_yaml;").fetchone() -# assert row + row = conn.execute("SELECT * FROM test_from_yaml;").fetchone() + assert row def test_create_pt_graph(coquimbo_project): From a1736d75e512f55dc24ff72232a396434482d4fd Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Thu, 5 Dec 2024 13:53:50 -0300 Subject: [PATCH 10/34] Update add matrix from layer --- .../add_matrix_from_layer.py | 90 ++++++------------- test/test_processing_provider.py | 12 +-- 2 files changed, 32 insertions(+), 70 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py index 58953ff6..a3e45258 100644 --- a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py @@ -2,7 +2,6 @@ import sys import numpy as np import pandas as pd -import os from scipy.sparse import coo_matrix from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessingParameterString @@ -49,7 +48,7 @@ def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterFile( "matrix_file", - self.tr("Existing .aem file"), + self.tr("Output name"), behavior=QgsProcessingParameterFile.File, fileFilter="", defaultValue=None, @@ -61,96 +60,65 @@ def initAlgorithm(self, config=None): ) def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(3, model_feedback) - # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) from aequilibrae.matrix import AequilibraeMatrix + feedback = QgsProcessingMultiStepFeedback(3, model_feedback) + origin = parameters["origin"] destination = parameters["destination"] value = parameters["value"] - - core_name = [parameters["matrix_core"]] - - matrix_file = parameters["matrix_file"] + list_cores = [parameters["matrix_core"]] + path_to_file = parameters["matrix_file"] # Import layer as a pandas df feedback.pushInfo(self.tr("Importing layer")) layer = self.parameterAsVectorLayer(parameters, "matrix_layer", context) - cols = [origin, destination, value] - datagen = ([f[col] for col in cols] for f in layer.getFeatures()) - matrix = pd.DataFrame.from_records(data=datagen, columns=cols) - feedback.pushInfo("") - feedback.setCurrentStep(1) - # Getting all zones - all_zones = np.array(sorted(list(set(list(matrix[origin].unique()) + list(matrix[destination].unique()))))) - num_zones = all_zones.shape[0] - idx = np.arange(num_zones) + columns = [origin, destination, value] + data = [feat.attributes() for feat in layer.getFeatures()] - # Creates the indexing dataframes - origs = pd.DataFrame({"from_index": all_zones, "from": idx}) - dests = pd.DataFrame({"to_index": all_zones, "to": idx}) + trip_df = pd.DataFrame(data=data, columns=columns) + feedback.pushInfo("") + feedback.setCurrentStep(1) - # adds the new index columns to the pandas dataframe - matrix = matrix.merge(origs, left_on=origin, right_on="from_index", how="left") - matrix = matrix.merge(dests, left_on=destination, right_on="to_index", how="left") + # Borrowed from AequilibraE's "create_from_trip_list" + zones_list = sorted(set(list(trip_df[origin].unique()) + list(trip_df[destination].unique()))) + zones_df = pd.DataFrame({"zone": zones_list, "idx": list(np.arange(len(zones_list)))}) - agg_matrix = matrix.groupby(["from", "to"]).sum() + trip_df = trip_df.merge( + zones_df.rename(columns={"zone": origin, "idx": origin + "_idx"}), on=origin, how="left" + ).merge(zones_df.rename(columns={"zone": destination, "idx": destination + "_idx"}), on=destination, how="left") - # returns the indices - agg_matrix.reset_index(inplace=True) + nb_of_zones = len(zones_list) + feedback.pushInfo(self.tr("{}x{} matrix imported ").format(nb_of_zones, nb_of_zones)) + feedback.pushInfo(" ") + feedback.setCurrentStep(2) - # Creating the aequilibrae matrix file mat = AequilibraeMatrix() - mat.load(matrix_file) - - cores = mat.names - cores.append(core_name[0]) - - output = AequilibraeMatrix() - output.create_empty( - file_name=matrix_file[-4] + "_temp.aem", - zones=mat.zones, - matrix_names=cores, - memory_only=False, + mat.create_empty( + file_name=path_to_file[:-4] + ".aem", zones=nb_of_zones, matrix_names=list_cores, memory_only=False ) m = ( - coo_matrix((agg_matrix[value], (agg_matrix["from"], agg_matrix["to"])), shape=(num_zones, num_zones)) + coo_matrix( + (trip_df[value], (trip_df[origin + "_idx"], trip_df[destination + "_idx"])), + shape=(nb_of_zones, nb_of_zones), + ) .toarray() .astype(np.float64) ) - output.index[:] = mat.index[:] - - for core in cores: - if core == core_name[0]: - output.matrix[core][:, :] = m[:, :] - else: - output.matrix[core][:, :] = mat.matrix[core][:, :] - output.setName(mat.name) - output.setDescription(mat.description.decode("utf-8")) - - feedback.pushInfo(self.tr("{}x{} matrix imported ").format(num_zones, num_zones)) - feedback.pushInfo(" ") - feedback.setCurrentStep(2) - - output.save() - output.close() - mat.close() - - os.remove(matrix_file) - os.rename(matrix_file[-4] + "_temp.aem", matrix_file) - del agg_matrix, matrix, m + mat.matrix[mat.names[0]][:, :] = m[:, :] + mat.save() feedback.pushInfo(" ") feedback.setCurrentStep(3) - return {"Output": f"{mat.name}, {mat.description} ({matrix_file})"} + return {"Output": f"{mat.name}, {mat.description} ({path_to_file})"} def name(self): return "exportmatrixasaem" diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index c7a5e3ce..e712ba70 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -66,7 +66,6 @@ def test_export_matrix(folder_path, source_file, format): assert isfile(result["Output"]) -@pytest.mark.skip def test_matrix_from_layer(folder_path): makedirs(folder_path) @@ -80,10 +79,7 @@ def test_matrix_from_layer(folder_path): "origin": "O", "destination": "D", "value": "Ton", - "file_name": "siouxfalls_od", - "output_folder": folder_path, - "matrix_name": "NAME_FOR_TEST", - "matrix_description": "this is a description", + "matrix_file": join(folder_path, "siouxfalls_od.aem"), "matrix_core": "MAT_CORE", } @@ -92,15 +88,13 @@ def test_matrix_from_layer(folder_path): _ = action.run(parameters, context, feedback) - assert isfile(join(folder_path, f"{parameters['file_name']}.aem")) + assert isfile(parameters["matrix_file"]) mat = AequilibraeMatrix() - mat.load(join(folder_path, f"{parameters['file_name']}.aem")) + mat.load(parameters["matrix_file"]) info = mat.__dict__ assert info["names"] == [parameters["matrix_core"]] - assert parameters["matrix_name"].encode() in info["name"] - assert parameters["matrix_description"].encode() in info["description"] assert info["zones"] == 24 assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 From c7726e7aa60b4d2fa7dcab7807d0d0a6460e8413 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Thu, 5 Dec 2024 14:44:56 -0300 Subject: [PATCH 11/34] Updates project from layer --- .../processing_provider/project_from_layer.py | 135 ++++++++---------- test/test_processing_provider.py | 61 ++++---- 2 files changed, 91 insertions(+), 105 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/project_from_layer.py b/qaequilibrae/modules/processing_provider/project_from_layer.py index 5c3ac19e..e0c847fe 100644 --- a/qaequilibrae/modules/processing_provider/project_from_layer.py +++ b/qaequilibrae/modules/processing_provider/project_from_layer.py @@ -1,16 +1,14 @@ import importlib.util as iutil -import pandas as pd import sys from os.path import join -from string import ascii_lowercase +from string import ascii_letters -from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProcessingAlgorithm +from qgis.core import QgsProcessingAlgorithm from qgis.core import QgsProcessing, QgsProcessingMultiStepFeedback, QgsProcessingParameterVectorLayer from qgis.core import QgsProcessingParameterField, QgsProcessingParameterFile, QgsProcessingParameterString -from qgis.core import QgsProject, QgsFeature, QgsVectorLayer, QgsDataSourceUri -from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt +from qaequilibrae.modules.common_tools import geodataframe_from_layer, standard_path class ProjectFromLayer(QgsProcessingAlgorithm): @@ -63,7 +61,7 @@ def initAlgorithm(self, config=None): ) self.addParameter( QgsProcessingParameterFile( - "dst", + "folder", self.tr("Output folder"), behavior=QgsProcessingParameterFile.Folder, defaultValue=standard_path(), @@ -76,98 +74,87 @@ def initAlgorithm(self, config=None): ) def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(5, model_feedback) - # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) from aequilibrae import Project + feedback = QgsProcessingMultiStepFeedback(5, model_feedback) feedback.pushInfo(self.tr("Creating project")) - project_path = join(parameters["dst"], parameters["project_name"]) + + project_path = join(parameters["folder"], parameters["project_name"]) project = Project() project.new(project_path) feedback.pushInfo(self.tr("Importing links layer")) - aeq_crs = QgsCoordinateReferenceSystem("EPSG:4326") - # Adding source_id field early to have all fields available in links table + # Load layer as GeoDataFrame + layer = self.parameterAsVectorLayer(parameters, "links", context) + gdf = geodataframe_from_layer(layer).infer_objects() + + columns = [ + parameters["link_id"], + parameters["link_type"], + parameters["direction"], + parameters["modes"], + "geometry", + ] + gdf = gdf[columns] + gdf.columns = ["link_id", "link_type", "direction", "modes", "geometry"] + + # We check if all modes exist in the project + all_modes = set("".join(gdf["modes"].unique())) + modes = project.network.modes + current_modes = list(modes.all_modes().keys()) + all_modes = [x for x in all_modes if x not in current_modes] + for md in all_modes: + new_mode = modes.new(md) + new_mode.mode_name = md + new_mode.description = "Mode automatically added during project creation from layers" + modes.add(new_mode) + new_mode.save() + + # We check if all link types exist in the project + all_link_types = gdf["link_type"].unique() + link_types = project.network.link_types + current_lt = [lt.link_type for lt in link_types.all_types().values()] + letters = [x for x in list(ascii_letters) if x not in link_types.all_types().keys()] + all_link_types = [lt for lt in all_link_types if lt not in current_lt] + for lt in all_link_types: + new_link_type = link_types.new(letters[0]) + letters = letters[1:] + new_link_type.link_type = lt + new_link_type.description = "Link type automatically added during project creation from layers" + new_link_type.save() + links = project.network.links - link_data = links.fields - link_data.add("source_id", "link_id from the data source") + + # Add `source_id` field + links.fields.add("source_id", "link_id from the data source") links.refresh_fields() - uri = QgsDataSourceUri() - uri.setDatabase(join(project_path, "project_database.sqlite")) - uri.setDataSource("", "links", "geometry") - links_layer = QgsVectorLayer(uri.uri(), "links_layer", "spatialite") - # Import QGIS layer as a panda dataframe and storing features for future copy - layer = self.parameterAsVectorLayer(parameters, "links", context) - columns = [parameters["modes"], parameters["link_type"]] - feature_list = [] - row_list = [] - for f in layer.getFeatures(): - geom = f.geometry() - geom.transform(QgsCoordinateTransform(layer.crs(), aeq_crs, QgsProject.instance())) - nf = QgsFeature(links_layer.fields()) - nf.setGeometry(geom) - nf["ogc_fid"] = f[parameters["link_id"]] - nf["link_id"] = f[parameters["link_id"]] - nf["a_node"] = 0 - nf["b_node"] = 0 - nf["source_id"] = f[parameters["link_id"]] - nf["direction"] = f[parameters["direction"]] - nf["link_type"] = f[parameters["link_type"]] - nf["modes"] = f[parameters["modes"]] - feature_list.append(nf) - row_list.append([f[parameters["modes"]], f[parameters["link_type"]]]) - df = pd.DataFrame(row_list, columns=columns) - feedback.pushInfo(" ") - feedback.setCurrentStep(1) - - feedback.pushInfo(self.tr("Getting parameters from layer")) - - # Updating link types - link_types = df[parameters["link_type"]].unique() - lt = project.network.link_types - lt_dict = lt.all_types() - - existing_types = [ltype.link_type for ltype in lt_dict.values()] - types_to_add = [ltype for ltype in link_types if ltype not in existing_types] - for i, ltype in enumerate(types_to_add): - new_type = lt.new(ascii_lowercase[i]) - new_type.link_type = ltype - new_type.save() - - # Updating modes - md = project.network.modes - md_dict = md.all_modes() - existing_modes = {k: v.mode_name for k, v in md_dict.items()} - - all_modes = set("".join(df[parameters["modes"]].unique())) - modes_to_add = [mode for mode in all_modes if mode not in existing_modes] - for i, mode_id in enumerate(modes_to_add): - new_mode = md.new(mode_id) - new_mode.mode_name = f"Mode_from_original_data_{mode_id}" - project.network.modes.add(new_mode) - new_mode.save() - project.close() feedback.pushInfo(" ") feedback.setCurrentStep(2) - feedback.pushInfo(self.tr("Adding links")) + # Now let's add all the fields we had + for _, record in gdf.iterrows(): + new_link = links.new() - # Adding links all at once - links_layer.startEditing() - links_layer.addFeatures(feature_list) - links_layer.commitChanges() + new_link.source_id = record.link_id + new_link.direction = record.direction + new_link.modes = record.modes + new_link.link_type = record.link_type + new_link.geometry = record.geometry + new_link.save() + feedback.pushInfo(self.tr("Adding links")) feedback.pushInfo(" ") feedback.setCurrentStep(3) + project.close() + feedback.pushInfo(self.tr("Closing project")) - del df, row_list, feature_list return {"Output": project_path} diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index e712ba70..7f22731e 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -99,48 +99,47 @@ def test_matrix_from_layer(folder_path): assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 -# @pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) -# def test_project_from_layer(folder_path, load_sfalls_from_layer): - -# linkslayer = QgsProject.instance().mapLayersByName("Links layer")[0] +@pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) +def test_project_from_layer(folder_path, load_sfalls_from_layer): -# linkslayer.startEditing() -# field = QgsField("ltype", QVariant.String) -# linkslayer.addAttribute(field) -# linkslayer.updateFields() + linkslayer = QgsProject.instance().mapLayersByName("Links layer")[0] -# for feature in linkslayer.getFeatures(): -# feature["ltype"] = "road" -# linkslayer.updateFeature(feature) + linkslayer.startEditing() + field = QgsField("ltype", QVariant.String) + linkslayer.addAttribute(field) + linkslayer.updateFields() -# linkslayer.commitChanges() + for feature in linkslayer.getFeatures(): + feature["ltype"] = "road" + linkslayer.updateFeature(feature) -# action = ProjectFromLayer() + linkslayer.commitChanges() -# parameters = { -# "links": linkslayer, -# "link_id": "link_id", -# "link_type": "ltype", -# "direction": "direction", -# "modes": "modes", -# "folder": folder_path, -# "project_name": "from_test", -# } + action = ProjectFromLayer() -# context = QgsProcessingContext() -# feedback = QgsProcessingFeedback() + parameters = { + "links": linkslayer, + "link_id": "link_id", + "link_type": "ltype", + "direction": "direction", + "modes": "modes", + "folder": folder_path, + "project_name": "from_test", + } -# result = action.run(parameters, context, feedback) + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() -# assert result[0]["Output"] == join(folder_path, parameters["project_name"]) + result = action.run(parameters, context, feedback) + assert result[0]["Output"] == join(folder_path, parameters["project_name"]) -# QgsProject.instance().clear() + QgsProject.instance().clear() -# project = Project() -# project.open(join(folder_path, parameters["project_name"])) + project = Project() + project.open(join(folder_path, parameters["project_name"])) -# assert project.network.count_links() == 76 -# assert project.network.count_nodes() == 24 + assert project.network.count_links() == 76 + assert project.network.count_nodes() == 24 # def test_add_centroid_connector(pt_no_feed): From 3a598ff58c5d1781ad529942ed747c3edbe932d9 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Thu, 5 Dec 2024 15:27:41 -0300 Subject: [PATCH 12/34] rename classes --- .../add_links_from_layer.py | 137 ++++++++---------- .../assign_pt_from_yaml.py | 31 ++-- .../modules/processing_provider/provider.py | 39 +++-- test/test_processing_provider.py | 33 ++++- 4 files changed, 117 insertions(+), 123 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/add_links_from_layer.py b/qaequilibrae/modules/processing_provider/add_links_from_layer.py index 4b128989..ce892976 100644 --- a/qaequilibrae/modules/processing_provider/add_links_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_links_from_layer.py @@ -1,16 +1,13 @@ import importlib.util as iutil -import pandas as pd import sys -from os.path import join -from string import ascii_lowercase +from string import ascii_letters -from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProcessingAlgorithm +from qgis.core import QgsProcessingAlgorithm from qgis.core import QgsProcessing, QgsProcessingMultiStepFeedback, QgsProcessingParameterVectorLayer -from qgis.core import QgsProcessingParameterField, QgsProcessingParameterFile, QgsProcessingParameterString -from qgis.core import QgsProject, QgsFeature, QgsVectorLayer, QgsDataSourceUri +from qgis.core import QgsProcessingParameterField, QgsProcessingParameterFile -from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt +from qaequilibrae.modules.common_tools import geodataframe_from_layer, standard_path class AddLinksFromLayer(QgsProcessingAlgorithm): @@ -61,99 +58,79 @@ def initAlgorithm(self, config=None): ) def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(5, model_feedback) - # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) from aequilibrae import Project - aeq_crs = QgsCoordinateReferenceSystem("EPSG:4326") - + feedback = QgsProcessingMultiStepFeedback(5, model_feedback) feedback.pushInfo(self.tr("Opening project")) - project_path = parameters["project_path"] - # Import links layer - uri = QgsDataSourceUri() - uri.setDatabase(join(project_path, "project_database.sqlite")) - uri.setDataSource("", "links", "geometry") - links_layer = QgsVectorLayer(uri.uri(), "links_layer", "spatialite") + project_path = parameters["project_path"] + project = Project() + project.open(project_path) - # Get current max link_id - cols = ["link_id", "ogc_fid"] - datagen = ([f[col] for col in cols] for f in links_layer.getFeatures()) - links_ids = pd.DataFrame.from_records(data=datagen, columns=cols) - ogc_id = links_ids["ogc_fid"].max() + 1 - link_id = links_ids["link_id"].max() + 1 + feedback.pushInfo(self.tr("Importing links layer")) - # Import QGIS layer as a panda dataframe and storing features for future copy + # Load layer as GeoDataFrame layer = self.parameterAsVectorLayer(parameters, "links", context) - columns = [parameters["modes"], parameters["link_type"]] - feature_list = [] - row_list = [] - for f in layer.getFeatures(): - geom = f.geometry() - geom.transform(QgsCoordinateTransform(layer.crs(), aeq_crs, QgsProject.instance())) - nf = QgsFeature(links_layer.fields()) - nf.setGeometry(geom) - nf["ogc_fid"] = int(ogc_id) - nf["link_id"] = int(link_id) - nf["a_node"] = 0 - nf["b_node"] = 0 - nf["direction"] = f[parameters["direction"]] - nf["link_type"] = f[parameters["link_type"]] - nf["modes"] = f[parameters["modes"]] - ogc_id = ogc_id + 1 - link_id = link_id + 1 - feature_list.append(nf) - row_list.append([f[parameters["modes"]], f[parameters["link_type"]]]) - df = pd.DataFrame(row_list, columns=columns) - feedback.pushInfo(" ") - feedback.setCurrentStep(1) - - feedback.pushInfo(self.tr("Getting parameters from layer")) - - # Updating link types - link_types = df[parameters["link_type"]].unique() - lt = project.network.link_types - lt_dict = lt.all_types() - - existing_types = [ltype.link_type for ltype in lt_dict.values()] - types_to_add = [ltype for ltype in link_types if ltype not in existing_types] - for i, ltype in enumerate(types_to_add): - new_type = lt.new(ascii_lowercase[i]) - new_type.link_type = ltype - new_type.save() - - # Updating modes - md = project.network.modes - md_dict = md.all_modes() - existing_modes = {k: v.mode_name for k, v in md_dict.items()} - - all_modes = set("".join(df[parameters["modes"]].unique())) - modes_to_add = [mode for mode in all_modes if mode not in existing_modes] - for i, mode_id in enumerate(modes_to_add): - new_mode = md.new(mode_id) - new_mode.mode_name = f"Mode_from_original_data_{mode_id}" - project.network.modes.add(new_mode) + gdf = geodataframe_from_layer(layer).infer_objects() + + columns = [parameters["link_type"], parameters["direction"], parameters["modes"], "geometry"] + + gdf = gdf[columns] + gdf.columns = ["link_type", "direction", "modes", "geometry"] + + # We check if all modes exist in the project + all_modes = set("".join(gdf["modes"].unique())) + modes = project.network.modes + current_modes = list(modes.all_modes().keys()) + all_modes = [x for x in all_modes if x not in current_modes] + for md in all_modes: + new_mode = modes.new(md) + new_mode.mode_name = md + new_mode.description = "Mode automatically added during project creation from layers" + modes.add(new_mode) new_mode.save() - project.close() + + # We check if all link types exist in the project + all_link_types = gdf["link_type"].unique() + link_types = project.network.link_types + current_lt = [lt.link_type for lt in link_types.all_types().values()] + letters = [x for x in list(ascii_letters) if x not in link_types.all_types().keys()] + all_link_types = [lt for lt in all_link_types if lt not in current_lt] + for lt in all_link_types: + new_link_type = link_types.new(letters[0]) + letters = letters[1:] + new_link_type.link_type = lt + new_link_type.description = "Link type automatically added during project creation from layers" + new_link_type.save() + feedback.pushInfo(" ") feedback.setCurrentStep(2) - feedback.pushInfo(self.tr("Adding links")) + links = project.network.links + + # Now let's add all the fields we had + for _, record in gdf.iterrows(): + new_link = links.new() - # Adding links all at once - links_layer.startEditing() - links_layer.addFeatures(feature_list) - links_layer.commitChanges() + new_link.direction = record.direction + new_link.modes = record.modes + new_link.link_type = record.link_type + new_link.geometry = record.geometry + new_link.save() feedback.pushInfo(" ") - feedback.setCurrentStep(3) + feedback.setCurrentStep(2) + feedback.pushInfo(self.tr("Adding links")) + + feedback.pushInfo(" ") + feedback.setCurrentStep(3) + project.close() feedback.pushInfo(self.tr("Closing project")) - del df, row_list, feature_list return {"Output": project_path} diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py index 32dc4f24..ae3bdd80 100644 --- a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -1,16 +1,14 @@ import importlib.util as iutil import sys import textwrap - -from datetime import datetime as dt +import yaml from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile -from qgis.core import QgsProcessingParameterDefinition, QgsProcessingParameterBoolean from qaequilibrae.i18n.translate import trlt -class ptAssignYAML(QgsProcessingAlgorithm): +class TransitAssignYAML(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): self.addParameter( @@ -23,30 +21,18 @@ def initAlgorithm(self, config=None): ) ) - advparameters = [ - QgsProcessingParameterBoolean( - "datetime_to_resultname", self.tr("Include current datetime to result name"), defaultValue=True - ) - ] - - for param in advparameters: - param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) - self.addParameter(param) - def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(5, model_feedback) - # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) - from aequilibrae.paths import TransitAssignment, TransitClass - from aequilibrae.project import Project + from aequilibrae import Project from aequilibrae.matrix import AequilibraeMatrix + from aequilibrae.paths import TransitAssignment, TransitClass from aequilibrae.project.database_connection import database_connection from aequilibrae.transit.transit_graph_builder import TransitGraphBuilder - import yaml + feedback = QgsProcessingMultiStepFeedback(5, model_feedback) feedback.pushInfo(self.tr("Getting parameters from YAML")) pathfile = parameters["conf_file"] @@ -100,14 +86,15 @@ def processAlgorithm(self, parameters, context, model_feedback): # Running assignment feedback.pushInfo(self.tr("Running assignment")) + assig.execute() + feedback.pushInfo(" ") feedback.setCurrentStep(4) # Saving outputs feedback.pushInfo(self.tr("Saving outputs")) - if str(parameters["datetime_to_resultname"]) == "True": - params["result_name"] = params["result_name"] + dt.now().strftime("_%Y-%m-%d_%Hh%M") + assig.save_results(params["result_name"]) feedback.pushInfo(" ") @@ -133,7 +120,7 @@ def shortHelpString(self): return textwrap.dedent("\n".join([self.string_order(1), self.string_order(2), self.string_order(3)])) def createInstance(self): - return ptAssignYAML() + return TransitAssignYAML() def string_order(self, order): if order == 1: diff --git a/qaequilibrae/modules/processing_provider/provider.py b/qaequilibrae/modules/processing_provider/provider.py index ad4ef06f..7ac272c8 100644 --- a/qaequilibrae/modules/processing_provider/provider.py +++ b/qaequilibrae/modules/processing_provider/provider.py @@ -15,34 +15,33 @@ class Provider(QgsProcessingProvider): def loadAlgorithms(self): - from .project_from_layer import ProjectFromLayer - from .project_from_osm import ProjectFromOSM - # from .Add_connectors import AddConnectors + from .add_links_from_layer import AddLinksFromLayer + from .add_matrix_from_layer import AddMatrixFromLayer + from .assign_pt_from_yaml import TransitAssignYAML from .assign_traffic_from_yaml import TrafficAssignYAML - from .export_matrix import ExportMatrix from .create_matrix_from_layer import CreateMatrixFromLayer - from .add_matrix_from_layer import AddMatrixFromLayer - from .add_links_from_layer import AddLinksFromLayer - from .renumber_nodes_from_layer import RenumberNodesFromLayer - from .matrix_calculator import MatrixCalculator - from .import_gtfs import ImportGTFS from .create_pt_graph import CreatePTGraph - from .assign_pt_from_yaml import ptAssignYAML + from .export_matrix import ExportMatrix + from .import_gtfs import ImportGTFS + from .matrix_calculator import MatrixCalculator + from .project_from_layer import ProjectFromLayer + from .project_from_OSM import ProjectFromOSM + from .renumber_nodes_from_layer import RenumberNodesFromLayer - self.addAlgorithm(ProjectFromOSM()) - self.addAlgorithm(ProjectFromLayer()) - self.addAlgorithm(CreateMatrixFromLayer()) - self.addAlgorithm(AddMatrixFromLayer()) - self.addAlgorithm(MatrixCalculator()) - self.addAlgorithm(ExportMatrix()) - self.addAlgorithm(AddLinksFromLayer()) - self.addAlgorithm(RenumberNodesFromLayer()) # self.addAlgorithm(AddConnectors()) + self.addAlgorithm(AddLinksFromLayer()) + self.addAlgorithm(AddMatrixFromLayer()) + self.addAlgorithm(TransitAssignYAML()) self.addAlgorithm(TrafficAssignYAML()) - self.addAlgorithm(ImportGTFS()) + self.addAlgorithm(CreateMatrixFromLayer()) self.addAlgorithm(CreatePTGraph()) - self.addAlgorithm(ptAssignYAML()) + self.addAlgorithm(ExportMatrix()) + self.addAlgorithm(ImportGTFS()) + self.addAlgorithm(MatrixCalculator()) + self.addAlgorithm(ProjectFromLayer()) + self.addAlgorithm(ProjectFromOSM()) + self.addAlgorithm(RenumberNodesFromLayer()) def id(self): """The ID used for identifying the provider. diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 7f22731e..ef331258 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -19,7 +19,7 @@ # from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors from qaequilibrae.modules.processing_provider.add_links_from_layer import AddLinksFromLayer from qaequilibrae.modules.processing_provider.add_matrix_from_layer import AddMatrixFromLayer -from qaequilibrae.modules.processing_provider.assign_pt_from_yaml import ptAssignYAML +from qaequilibrae.modules.processing_provider.assign_pt_from_yaml import TransitAssignYAML from qaequilibrae.modules.processing_provider.assign_traffic_from_yaml import TrafficAssignYAML from qaequilibrae.modules.processing_provider.create_matrix_from_layer import CreateMatrixFromLayer from qaequilibrae.modules.processing_provider.create_pt_graph import CreatePTGraph @@ -27,6 +27,7 @@ from qaequilibrae.modules.processing_provider.import_gtfs import ImportGTFS from qaequilibrae.modules.processing_provider.matrix_calculator import MatrixCalculator from qaequilibrae.modules.processing_provider.project_from_layer import ProjectFromLayer +from qaequilibrae.modules.processing_provider.project_from_OSM import ProjectFromOSM from qaequilibrae.modules.processing_provider.renumber_nodes_from_layer import RenumberNodesFromLayer @@ -286,3 +287,33 @@ def test_import_gtfs(pt_no_feed, allow_map_match): result = action.run(parameters, context, feedback) assert result[0]["Output"] == "Traffic assignment successfully completed" + + +def test_add_links_from_layer(): + + action = AddLinksFromLayer() + pass + + +def test_assign_transit_from_yaml(): + + action = TransitAssignYAML() + pass + + +def test_create_matrix_from_layer(): + + action = CreateMatrixFromLayer() + pass + + +def test_matrix_calc(): + + action = MatrixCalculator() + pass + + +def test_project_from_osm(): + + action = ProjectFromOSM() + pass From 500871cf2e5d4078a42cf29008500477728ec7a7 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Fri, 6 Dec 2024 11:24:17 -0300 Subject: [PATCH 13/34] Update tests --- .../processing_provider/Add_connectors.py | 2 +- .../processing_provider/project_from_OSM.py | 41 +++---- .../modules/processing_provider/provider.py | 4 +- test/test_processing_provider.py | 105 +++++++++++++----- 4 files changed, 96 insertions(+), 56 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/Add_connectors.py b/qaequilibrae/modules/processing_provider/Add_connectors.py index 1a7906b6..4ad77ace 100644 --- a/qaequilibrae/modules/processing_provider/Add_connectors.py +++ b/qaequilibrae/modules/processing_provider/Add_connectors.py @@ -7,7 +7,7 @@ from qgis.core import QgsProcessingParameterFile, QgsProcessingParameterNumber, QgsProcessingParameterString from qgis.core import QgsFeature, QgsVectorLayer, QgsDataSourceUri -import processing +from qgis import processing from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt diff --git a/qaequilibrae/modules/processing_provider/project_from_OSM.py b/qaequilibrae/modules/processing_provider/project_from_OSM.py index 89346fe9..c6fe4dcb 100644 --- a/qaequilibrae/modules/processing_provider/project_from_OSM.py +++ b/qaequilibrae/modules/processing_provider/project_from_OSM.py @@ -1,51 +1,38 @@ import importlib.util as iutil import sys -from os.path import join -from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile -from qgis.core import QgsProcessingParameterString +from qgis.core import ( + QgsProcessingAlgorithm, + QgsProcessingMultiStepFeedback, + QgsProcessingParameterString, + QgsProcessingParameterFolderDestination, +) -from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt class ProjectFromOSM(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): + self.addParameter(QgsProcessingParameterString("place_name", self.tr("Place name"), multiLine=False)) self.addParameter( - QgsProcessingParameterString( - "OSM_place", self.tr("Place name (OSM search)"), multiLine=False, defaultValue="" - ) - ) - self.addParameter( - QgsProcessingParameterFile( - "dst", - self.tr("Output folder"), - behavior=QgsProcessingParameterFile.Folder, - defaultValue=standard_path(), - ) - ) - self.addParameter( - QgsProcessingParameterString( - "project_name", self.tr("Project name"), multiLine=False, defaultValue="new_project" - ) + QgsProcessingParameterFolderDestination("project_folder", self.tr("Output folder"), createByDefault=True) ) def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(2, model_feedback) - # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) from aequilibrae import Project + feedback = QgsProcessingMultiStepFeedback(2, model_feedback) feedback.pushInfo(self.tr("Creating project")) - project_path = join(parameters["dst"], parameters["project_name"]) + project = Project() - project.new(project_path) + project.new(parameters["project_folder"]) - project.network.create_from_osm(place_name=parameters["OSM_place"]) + project.network.create_from_osm(place_name=parameters["place_name"]) feedback.pushInfo(" ") feedback.setCurrentStep(2) @@ -53,7 +40,7 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback.pushInfo(self.tr("Closing project")) project.close() - return {"Output": project_path} + return {"Output": parameters["project_folder"]} def name(self): return "projectfromosm" @@ -68,7 +55,7 @@ def groupId(self): return "modelbuilding" def shortHelpString(self): - return self.tr("Create an AequilibraE project from OpenStreetMap") + return self.tr("Create an AequilibraE project from OpenStreetMap network") def createInstance(self): return ProjectFromOSM() diff --git a/qaequilibrae/modules/processing_provider/provider.py b/qaequilibrae/modules/processing_provider/provider.py index 7ac272c8..6d241cab 100644 --- a/qaequilibrae/modules/processing_provider/provider.py +++ b/qaequilibrae/modules/processing_provider/provider.py @@ -15,7 +15,7 @@ class Provider(QgsProcessingProvider): def loadAlgorithms(self): - # from .Add_connectors import AddConnectors + from .Add_connectors import AddConnectors from .add_links_from_layer import AddLinksFromLayer from .add_matrix_from_layer import AddMatrixFromLayer from .assign_pt_from_yaml import TransitAssignYAML @@ -29,7 +29,7 @@ def loadAlgorithms(self): from .project_from_OSM import ProjectFromOSM from .renumber_nodes_from_layer import RenumberNodesFromLayer - # self.addAlgorithm(AddConnectors()) + self.addAlgorithm(AddConnectors()) self.addAlgorithm(AddLinksFromLayer()) self.addAlgorithm(AddMatrixFromLayer()) self.addAlgorithm(TransitAssignYAML()) diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index ef331258..51df633a 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -7,7 +7,7 @@ from os import makedirs from shapely.geometry import Point from aequilibrae.matrix import AequilibraeMatrix -from aequilibrae.project import Project +from aequilibrae import Project from qgis.core import QgsApplication, QgsProcessingContext, QgsProcessingFeedback from qgis.core import QgsProject, QgsField from PyQt5.QtCore import QVariant @@ -16,7 +16,7 @@ from qaequilibrae.modules.processing_provider.provider import Provider -# from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors +from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors from qaequilibrae.modules.processing_provider.add_links_from_layer import AddLinksFromLayer from qaequilibrae.modules.processing_provider.add_matrix_from_layer import AddMatrixFromLayer from qaequilibrae.modules.processing_provider.assign_pt_from_yaml import TransitAssignYAML @@ -143,34 +143,34 @@ def test_project_from_layer(folder_path, load_sfalls_from_layer): assert project.network.count_nodes() == 24 -# def test_add_centroid_connector(pt_no_feed): -# project = pt_no_feed.project -# project_folder = project.project_base_path +def test_add_centroid_connector(pt_no_feed): + project = pt_no_feed.project + project_folder = project.project_base_path -# nodes = project.network.nodes + nodes = project.network.nodes -# cnt = nodes.new_centroid(100_000) -# cnt.geometry = Point(-71.34, -29.95) -# cnt.save() + cnt = nodes.new_centroid(100_000) + cnt.geometry = Point(-71.34, -29.95) + cnt.save() -# action = AddConnectors() + action = AddConnectors() -# parameters = {"num_connectors": 3, "mode": "c", "project_path": project_folder} + parameters = {"num_connectors": 3, "mode": "c", "project_path": project_folder} -# context = QgsProcessingContext() -# feedback = QgsProcessingFeedback() + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() -# result = action.processAlgorithm(parameters, context, feedback) + result = action.processAlgorithm(parameters, context, feedback) -# assert result["Output"] == project_folder + assert result["Output"] == project_folder -# node_qry = "select count(node_id) from nodes where is_centroid=1" -# node_count = project.conn.execute(node_qry).fetchone()[0] -# assert node_count == 1 + node_qry = "select count(node_id) from nodes where is_centroid=1" + node_count = project.conn.execute(node_qry).fetchone()[0] + assert node_count == 1 -# link_qry = "select count(name) from links where name like 'centroid connector%'" -# link_count = project.conn.execute(link_qry).fetchone()[0] -# assert link_count == 3 + link_qry = "select count(name) from links where name like 'centroid connector%'" + link_count = project.conn.execute(link_qry).fetchone()[0] + assert link_count == 3 @pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) @@ -301,19 +301,72 @@ def test_assign_transit_from_yaml(): pass -def test_create_matrix_from_layer(): +def test_create_matrix_from_layer(folder_path): + makedirs(folder_path) + + df = pd.read_csv("test/data/SiouxFalls_project/SiouxFalls_od.csv") + layer = layer_from_dataframe(df, "SiouxFalls_od") action = CreateMatrixFromLayer() - pass + parameters = { + "matrix_layer": layer, + "origin": "O", + "destination": "D", + "value": "Ton", + "file_name": join(folder_path, "siouxfalls_od.aem"), + "matrix_core": "MAT_CORE", + } -def test_matrix_calc(): + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() + + _ = action.run(parameters, context, feedback) + assert isfile(parameters["matrix_file"]) + + mat = AequilibraeMatrix() + mat.load(parameters["matrix_file"]) + + info = mat.__dict__ + assert info["names"] == [parameters["matrix_core"]] + assert info["zones"] == 24 + assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 + + +def test_matrix_calc(ae): action = MatrixCalculator() + + # parameters = { + # "conf_file": "test/data/SiouxFalls_project/matrix_config.yml", + # "procedure": "sum (m1, m2)", + # "dest_path": "test/data/SiouxFalls_project/matrices/asdfg.aem", + # "matrix_core": "new_core", + # } + + # context = QgsProcessingContext() + # feedback = QgsProcessingFeedback() + + # result = action.run(parameters, context, feedback) + # print(result) pass -def test_project_from_osm(): +@pytest.mark.skip("Waaaaait a minute") +def test_project_from_osm(folder_path): + # makedirs(folder_path) action = ProjectFromOSM() - pass + + parameters = {"place_name": "Abrolhos", "project_folder": folder_path} + + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() + + _ = action.run(parameters, context, feedback) + + project = Project() + project.open(folder_path) + + assert project.network.count_links() == 11 + assert project.network.count_nodes() == 10 From 6485b453f73f7617dbf73ff02d25d12a491faedf Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Fri, 6 Dec 2024 11:24:40 -0300 Subject: [PATCH 14/34] Update create_matrix_from_layer.py --- .../create_matrix_from_layer.py | 109 ++++++++---------- 1 file changed, 45 insertions(+), 64 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py index 273ab4a9..21203515 100644 --- a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py @@ -2,14 +2,12 @@ import sys import numpy as np import pandas as pd -from os.path import join from scipy.sparse import coo_matrix from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessingParameterString, QgsProcessingParameterDefinition -from qgis.core import QgsProcessingParameterField, QgsProcessingParameterMapLayer, QgsProcessingParameterFile -from qgis.core import QgsProcessingAlgorithm +from qgis.core import QgsProcessingParameterField, QgsProcessingParameterMapLayer +from qgis.core import QgsProcessingAlgorithm, QgsProcessingParameterFileDestination -from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt @@ -24,7 +22,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="matrix_layer", allowMultiple=False, - defaultValue="origin", ) ) self.addParameter( @@ -34,7 +31,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="matrix_layer", allowMultiple=False, - defaultValue="destination", ) ) self.addParameter( @@ -44,118 +40,103 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="matrix_layer", allowMultiple=False, - defaultValue="value", ) ) self.addParameter( - QgsProcessingParameterString("file_name", self.tr("File name"), multiLine=False, defaultValue="") - ) - self.addParameter( - QgsProcessingParameterFile( - "output_folder", - self.tr("Output folder"), - behavior=QgsProcessingParameterFile.Folder, - fileFilter="All folders (*.*)", - defaultValue=standard_path(), - ) + QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "AequilibraE Matrix (*.aem)") ) + advparams = [ QgsProcessingParameterString( - "matrix_name", self.tr("Matrix name"), optional=True, multiLine=False, defaultValue="" + "matrix_name", + self.tr("Matrix name"), + optional=True, + multiLine=False, ), QgsProcessingParameterString( "matrix_description", self.tr("Matrix description"), optional=True, multiLine=False, - defaultValue="", ), - QgsProcessingParameterString("matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="Value"), + QgsProcessingParameterString( + "matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="matrix_core" + ), ] for param in advparams: param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) self.addParameter(param) def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(3, model_feedback) - # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) from aequilibrae.matrix import AequilibraeMatrix + feedback = QgsProcessingMultiStepFeedback(3, model_feedback) + origin = parameters["origin"] destination = parameters["destination"] value = parameters["value"] - - matrix_name = parameters["matrix_name"] - matrix_description = parameters["matrix_description"] - core_name = [parameters["matrix_core"]] - - output_folder = parameters["output_folder"] - output_name = parameters["file_name"] - file_name = join(output_folder, f"{output_name}.aem") + list_cores = [parameters["matrix_core"]] + path_to_file = parameters["file_name"] # Import layer as a pandas df feedback.pushInfo(self.tr("Importing layer")) layer = self.parameterAsVectorLayer(parameters, "matrix_layer", context) - cols = [origin, destination, value] - datagen = ([f[col] for col in cols] for f in layer.getFeatures()) - matrix = pd.DataFrame.from_records(data=datagen, columns=cols) - feedback.pushInfo("") - feedback.setCurrentStep(1) - # Getting all zones - all_zones = np.array(sorted(list(set(list(matrix[origin].unique()) + list(matrix[destination].unique()))))) - num_zones = all_zones.shape[0] - idx = np.arange(num_zones) + columns = [origin, destination, value] + data = [feat.attributes() for feat in layer.getFeatures()] - # Creates the indexing dataframes - origs = pd.DataFrame({"from_index": all_zones, "from": idx}) - dests = pd.DataFrame({"to_index": all_zones, "to": idx}) + trip_df = pd.DataFrame(data=data, columns=columns) + feedback.pushInfo("") + feedback.setCurrentStep(1) - # adds the new index columns to the pandas dataframe - matrix = matrix.merge(origs, left_on=origin, right_on="from_index", how="left") - matrix = matrix.merge(dests, left_on=destination, right_on="to_index", how="left") + # Borrowed from AequilibraE's "create_from_trip_list" + zones_list = sorted(set(list(trip_df[origin].unique()) + list(trip_df[destination].unique()))) + zones_df = pd.DataFrame({"zone": zones_list, "idx": list(np.arange(len(zones_list)))}) - agg_matrix = matrix.groupby(["from", "to"]).sum() + trip_df = trip_df.merge( + zones_df.rename(columns={"zone": origin, "idx": origin + "_idx"}), on=origin, how="left" + ).merge(zones_df.rename(columns={"zone": destination, "idx": destination + "_idx"}), on=destination, how="left") - # returns the indices - agg_matrix.reset_index(inplace=True) + nb_of_zones = len(zones_list) + feedback.pushInfo(self.tr("{}x{} matrix imported ").format(nb_of_zones, nb_of_zones)) + feedback.pushInfo(" ") + feedback.setCurrentStep(2) - # Creating the aequilibrae matrix file mat = AequilibraeMatrix() - mat.name = matrix_name - mat.description = matrix_description - - mat.create_empty(file_name=file_name, zones=num_zones, matrix_names=core_name, memory_only=False) - mat.index[:] = all_zones[:] + mat.create_empty(file_name=path_to_file, zones=nb_of_zones, matrix_names=list_cores, memory_only=False) m = ( - coo_matrix((agg_matrix[value], (agg_matrix["from"], agg_matrix["to"])), shape=(num_zones, num_zones)) + coo_matrix( + (trip_df[value], (trip_df[origin + "_idx"], trip_df[destination + "_idx"])), + shape=(nb_of_zones, nb_of_zones), + ) .toarray() .astype(np.float64) ) - mat.matrix[core_name[0]][:, :] = m[:, :] - feedback.pushInfo(self.tr("{}x{} matrix imported ").format(num_zones, num_zones)) - feedback.pushInfo(" ") - feedback.setCurrentStep(2) - mat.save() + mat.matrix[mat.names[0]][:, :] = m[:, :] + mat.index[:] = zones_df["zone"][:] + + if "matrix_name" in parameters: + mat.name = parameters["matrix_name"] + if "matrix_description" in parameters: + mat.description = parameters["matrix_description"] mat.close() - del agg_matrix, matrix, m feedback.pushInfo(" ") feedback.setCurrentStep(3) - return {"Output": f"{mat.name}, {mat.description} ({file_name})"} + return {"Output": f"{mat.name}, {mat.description} ({path_to_file})"} def name(self): return "aemfromlayer" def displayName(self): - return self.tr("Create aem matrix file from layer") + return self.tr("Create AequilibraE matrix from layer") def group(self): return self.tr("2. Data") @@ -171,7 +152,7 @@ def createInstance(self): def string_order(self, order): if order == 1: - return self.tr("Save a layer as a *.aem file. Notice that:") + return self.tr("Save layer as a *.aem file. Notice that:") elif order == 2: return self.tr("- the original matrix stored in the layer needs to be in list format") elif order == 3: From 28d5ff8b86fcb14bf50e836c16ee617b6528e272 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Fri, 6 Dec 2024 11:54:40 -0300 Subject: [PATCH 15/34] . --- .../common_tools/auxiliary_functions.py | 6 + .../network/adds_connectors_procedure.py | 13 +- .../processing_provider/Add_connectors.py | 127 +++++------------- .../processing_provider/project_from_OSM.py | 6 +- 4 files changed, 47 insertions(+), 105 deletions(-) diff --git a/qaequilibrae/modules/common_tools/auxiliary_functions.py b/qaequilibrae/modules/common_tools/auxiliary_functions.py index 4299a827..488a482b 100644 --- a/qaequilibrae/modules/common_tools/auxiliary_functions.py +++ b/qaequilibrae/modules/common_tools/auxiliary_functions.py @@ -1,6 +1,7 @@ import math import tempfile from os.path import isdir +from shapely.geometry import Point from time import localtime, strftime import qgis @@ -88,3 +89,8 @@ def only_str(str_input): if isinstance(str_input, bytes): return str_input.decode("utf-8") return str_input + + +def polygon_from_radius(self, point: Point): + # We approximate with the radius of the Earth at the equator + return point.buffer(self.radius / 110000) diff --git a/qaequilibrae/modules/network/adds_connectors_procedure.py b/qaequilibrae/modules/network/adds_connectors_procedure.py index 3ee3df47..ed3db42b 100644 --- a/qaequilibrae/modules/network/adds_connectors_procedure.py +++ b/qaequilibrae/modules/network/adds_connectors_procedure.py @@ -1,9 +1,8 @@ -import shapely.wkb -from shapely.geometry import Point - from aequilibrae.utils.interface.worker_thread import WorkerThread from PyQt5.QtCore import pyqtSignal +import shapely.wkb +from qaequilibrae.modules.common_tools import polygon_from_radius class AddsConnectorsProcedure(WorkerThread): signal = pyqtSignal(object) @@ -69,7 +68,7 @@ def do_from_network(self): self.signal.emit(["start", self.project.network.count_centroids(), "Adding connectors from nodes"]) for counter, zone_id in enumerate(centroids): node = nodes.get(zone_id) - geo = self.polygon_from_radius(node.geometry) + geo = polygon_from_radius(node.geometry) for mode_id in self.modes: node.connect_mode(area=geo, mode_id=mode_id, link_types=self.link_types, connectors=self.num_connectors) self.signal.emit(["update", counter + 1, f"Connector from node: {zone_id}"]) @@ -83,11 +82,7 @@ def do_from_layer(self): node = nodes.new_centroid(feat.id()) node.geometry = shapely.wkb.loads(feat.geometry().asWkb().data()) node.save() - geo = self.polygon_from_radius(node.geometry) + geo = polygon_from_radius(node.geometry) for mode_id in self.modes: node.connect_mode(area=geo, mode_id=mode_id, link_types=self.link_types, connectors=self.num_connectors) self.signal.emit(["update", counter + 1, f"Connector from layer feature: {feat.id()}"]) - - def polygon_from_radius(self, point: Point): - # We approximate with the radius of the Earth at the equator - return point.buffer(self.radius / 110000) diff --git a/qaequilibrae/modules/processing_provider/Add_connectors.py b/qaequilibrae/modules/processing_provider/Add_connectors.py index 4ad77ace..b6a3a897 100644 --- a/qaequilibrae/modules/processing_provider/Add_connectors.py +++ b/qaequilibrae/modules/processing_provider/Add_connectors.py @@ -5,12 +5,12 @@ from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessing, QgsProcessingAlgorithm from qgis.core import QgsProcessingParameterFile, QgsProcessingParameterNumber, QgsProcessingParameterString -from qgis.core import QgsFeature, QgsVectorLayer, QgsDataSourceUri +from qgis.core import QgsFeature, QgsVectorLayer, QgsDataSourceUri, QgsProcessingParameterBoolean from qgis import processing -from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt +from qaequilibrae.modules.common_tools import standard_path, polygon_from_radius class AddConnectors(QgsProcessingAlgorithm): @@ -22,13 +22,12 @@ def initAlgorithm(self, config=None): self.tr("Connectors per centroid"), type=QgsProcessingParameterNumber.Integer, minValue=1, - maxValue=10, defaultValue=1, ) ) self.addParameter( QgsProcessingParameterString( - "mode", self.tr("Modes to connect (only one at a time)"), multiLine=False, defaultValue="c" + "mode", self.tr("Modes to connect (defaults to all)"), multiLine=False, ) ) self.addParameter( @@ -39,108 +38,50 @@ def initAlgorithm(self, config=None): defaultValue=standard_path(), ) ) + self.addParameter( + QgsProcessingParameterString( + "link_type", self.tr("Link types to connect (defaults to all)"), multiLine=False, + ) + ) def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(2, model_feedback) + # Checks if we have access to aequilibrae library + if iutil.find_spec("aequilibrae") is None: + sys.exit(self.tr("AequilibraE module not found")) + from aequilibrae import Project + + feedback = QgsProcessingMultiStepFeedback(2, model_feedback) feedback.pushInfo(self.tr("Opening project")) - project_path = parameters["project_path"] - - # Import nodes layer - uri = QgsDataSourceUri() - uri.setDatabase(join(project_path, "project_database.sqlite")) - uri.setDataSource("", "nodes", "geometry") - nodes_layer = QgsVectorLayer(uri.uri(), "nodes_layer", "spatialite") - - # Import links layer - uri = QgsDataSourceUri() - uri.setDatabase(join(project_path, "project_database.sqlite")) - uri.setDataSource("", "links", "geometry") - links_layer = QgsVectorLayer(uri.uri(), "links_layer", "spatialite") - - # Get current max link_id - cols = ["link_id", "ogc_fid"] - datagen = ([f[col] for col in cols] for f in links_layer.getFeatures()) - links_ids = pd.DataFrame.from_records(data=datagen, columns=cols) - ogc_id = links_ids["ogc_fid"].max() + 1 - link_id = links_ids["link_id"].max() + 1 - feedback.pushInfo(" ") - feedback.setCurrentStep(1) + project = Project() + project.open(parameters["project_path"]) - feedback.pushInfo(self.tr("Extracting required nodes to process")) - # Extract centroids to connect - alg_params = { - "EXPRESSION": '("is_centroid" = 1) AND ( not("modes" ILIKE \'%' - + parameters["mode"] - + '%\') OR "modes" IS NULL )', - "INPUT": nodes_layer, - "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, - } - ConnectFrom = processing.run( - "native:extractbyexpression", alg_params, context=context, feedback=feedback, is_child_algorithm=True - ) + nodes = project.network.nodes + nodes.refresh() - # Extract nodes to connect - alg_params = { - "EXPRESSION": '("is_centroid" = 0) AND ("modes" ILIKE \'%' + parameters["mode"] + "%')", - "INPUT": nodes_layer, - "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, - } - ConnectTo = processing.run( - "native:extractbyexpression", alg_params, context=context, feedback=feedback, is_child_algorithm=True - ) + centroids = nodes.data[nodes.data["is_centroid"] == 1].node_id.tolist() feedback.pushInfo(" ") - feedback.setCurrentStep(2) - - # Computing and adding connectors - feedback.pushInfo( - self.tr('Adding {} connectors when none exists for mode "{}"').format( - parameters["num_connectors"], parameters["mode"] - ) - ) + feedback.setCurrentStep(1) - alg_params = { - "SOURCE": ConnectFrom["OUTPUT"], - "DESTINATION": ConnectTo["OUTPUT"], - "METHOD": 0, - "DISTANCE": 10, - "NEIGHBORS": parameters["num_connectors"], - "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, - } - Connectors = processing.run( - "native:shortestline", alg_params, context=context, feedback=feedback, is_child_algorithm=True - ) + # Adding connectors + num_connectors = parameters["num_connectors"] + mode = parameters["mode"] + feedback.pushInfo(self.tr('Adding {} connectors when none exists for mode "{}"').format(num_connectors, mode)) - connectors_layer = context.takeResultLayer(Connectors["OUTPUT"]) - feature_list = [] - for f in connectors_layer.getFeatures(): - geom = f.geometry() - nf = QgsFeature(links_layer.fields()) - nf.setGeometry(geom) - nf["ogc_fid"] = int(ogc_id) - nf["link_id"] = int(link_id) - nf["a_node"] = 0 - nf["b_node"] = 0 - nf["direction"] = 0 - nf["capacity_ab"] = 99999 - nf["capacity_ba"] = 99999 - nf["link_type"] = "centroid_connector" - nf["name"] = "centroid_connector zone " + str(f["node_id"]) - nf["modes"] = f["modes_2"] - feature_list.append(nf) - ogc_id = ogc_id + 1 - link_id = link_id + 1 - links_layer.startEditing() - links_layer.addFeatures(feature_list) - links_layer.commitChanges() - - feedback.pushInfo(self.tr("{} connectors have been added").format(len(feature_list))) + for counter, zone_id in enumerate(centroids): + node = nodes.get(zone_id) + geo = polygon_from_radius(node.geometry) + for mode_id in modes: + node.connect_mode(area=geo, mode_id=mode_id, link_types=link_types, connectors=num_connectors) feedback.pushInfo(" ") - feedback.setCurrentStep(3) - del feature_list, nodes_layer, links_layer, connectors_layer + feedback.setCurrentStep(2) + + project.network.nodes.refresh() + project.network.links.refresh() + project.close() return {"Output": parameters["project_path"]} diff --git a/qaequilibrae/modules/processing_provider/project_from_OSM.py b/qaequilibrae/modules/processing_provider/project_from_OSM.py index c6fe4dcb..c2c5f194 100644 --- a/qaequilibrae/modules/processing_provider/project_from_OSM.py +++ b/qaequilibrae/modules/processing_provider/project_from_OSM.py @@ -16,7 +16,7 @@ class ProjectFromOSM(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): self.addParameter(QgsProcessingParameterString("place_name", self.tr("Place name"), multiLine=False)) self.addParameter( - QgsProcessingParameterFolderDestination("project_folder", self.tr("Output folder"), createByDefault=True) + QgsProcessingParameterFolderDestination("project_path", self.tr("Output folder"), createByDefault=True) ) def processAlgorithm(self, parameters, context, model_feedback): @@ -30,7 +30,7 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback.pushInfo(self.tr("Creating project")) project = Project() - project.new(parameters["project_folder"]) + project.new(parameters["project_path"]) project.network.create_from_osm(place_name=parameters["place_name"]) @@ -40,7 +40,7 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback.pushInfo(self.tr("Closing project")) project.close() - return {"Output": parameters["project_folder"]} + return {"Output": parameters["project_path"]} def name(self): return "projectfromosm" From a6c508a7f33e9b31bfbcfb317eb10752da2c9bf5 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Fri, 6 Dec 2024 13:59:08 -0300 Subject: [PATCH 16/34] update add centroids --- .../common_tools/auxiliary_functions.py | 4 +- .../network/adds_connectors_procedure.py | 5 +- .../processing_provider/Add_connectors.py | 50 +++++++++++-------- test/test_processing_provider.py | 2 - 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/qaequilibrae/modules/common_tools/auxiliary_functions.py b/qaequilibrae/modules/common_tools/auxiliary_functions.py index 488a482b..3c9434c5 100644 --- a/qaequilibrae/modules/common_tools/auxiliary_functions.py +++ b/qaequilibrae/modules/common_tools/auxiliary_functions.py @@ -91,6 +91,6 @@ def only_str(str_input): return str_input -def polygon_from_radius(self, point: Point): +def polygon_from_radius(point: Point, radius): # We approximate with the radius of the Earth at the equator - return point.buffer(self.radius / 110000) + return point.buffer(radius / 110000) diff --git a/qaequilibrae/modules/network/adds_connectors_procedure.py b/qaequilibrae/modules/network/adds_connectors_procedure.py index ed3db42b..d77ed293 100644 --- a/qaequilibrae/modules/network/adds_connectors_procedure.py +++ b/qaequilibrae/modules/network/adds_connectors_procedure.py @@ -4,6 +4,7 @@ from qaequilibrae.modules.common_tools import polygon_from_radius + class AddsConnectorsProcedure(WorkerThread): signal = pyqtSignal(object) @@ -68,7 +69,7 @@ def do_from_network(self): self.signal.emit(["start", self.project.network.count_centroids(), "Adding connectors from nodes"]) for counter, zone_id in enumerate(centroids): node = nodes.get(zone_id) - geo = polygon_from_radius(node.geometry) + geo = polygon_from_radius(node.geometry, self.radius) for mode_id in self.modes: node.connect_mode(area=geo, mode_id=mode_id, link_types=self.link_types, connectors=self.num_connectors) self.signal.emit(["update", counter + 1, f"Connector from node: {zone_id}"]) @@ -82,7 +83,7 @@ def do_from_layer(self): node = nodes.new_centroid(feat.id()) node.geometry = shapely.wkb.loads(feat.geometry().asWkb().data()) node.save() - geo = polygon_from_radius(node.geometry) + geo = polygon_from_radius(node.geometry, self.radius) for mode_id in self.modes: node.connect_mode(area=geo, mode_id=mode_id, link_types=self.link_types, connectors=self.num_connectors) self.signal.emit(["update", counter + 1, f"Connector from layer feature: {feat.id()}"]) diff --git a/qaequilibrae/modules/processing_provider/Add_connectors.py b/qaequilibrae/modules/processing_provider/Add_connectors.py index b6a3a897..541ea9b4 100644 --- a/qaequilibrae/modules/processing_provider/Add_connectors.py +++ b/qaequilibrae/modules/processing_provider/Add_connectors.py @@ -1,13 +1,13 @@ import importlib.util as iutil import sys -from os.path import join -import pandas as pd -from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessing, QgsProcessingAlgorithm -from qgis.core import QgsProcessingParameterFile, QgsProcessingParameterNumber, QgsProcessingParameterString -from qgis.core import QgsFeature, QgsVectorLayer, QgsDataSourceUri, QgsProcessingParameterBoolean - -from qgis import processing +from qgis.core import ( + QgsProcessingMultiStepFeedback, + QgsProcessingAlgorithm, + QgsProcessingParameterFile, + QgsProcessingParameterNumber, + QgsProcessingParameterString, +) from qaequilibrae.i18n.translate import trlt from qaequilibrae.modules.common_tools import standard_path, polygon_from_radius @@ -16,6 +16,14 @@ class AddConnectors(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterFile( + "project_path", + self.tr("Project path"), + behavior=QgsProcessingParameterFile.Folder, + defaultValue=standard_path(), + ) + ) self.addParameter( QgsProcessingParameterNumber( "num_connectors", @@ -27,20 +35,12 @@ def initAlgorithm(self, config=None): ) self.addParameter( QgsProcessingParameterString( - "mode", self.tr("Modes to connect (defaults to all)"), multiLine=False, - ) - ) - self.addParameter( - QgsProcessingParameterFile( - "project_path", - self.tr("Project path"), - behavior=QgsProcessingParameterFile.Folder, - defaultValue=standard_path(), + "mode", self.tr("Modes to connect (defaults to all)"), multiLine=False, optional=True ) ) self.addParameter( QgsProcessingParameterString( - "link_type", self.tr("Link types to connect (defaults to all)"), multiLine=False, + "link_type", self.tr("Link types to connect (defaults to all)"), multiLine=False, optional=True ) ) @@ -66,15 +66,21 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback.setCurrentStep(1) # Adding connectors - num_connectors = parameters["num_connectors"] - mode = parameters["mode"] - feedback.pushInfo(self.tr('Adding {} connectors when none exists for mode "{}"').format(num_connectors, mode)) + feedback.pushInfo(self.tr("Adding centroid connectors")) + + lt = project.network.link_types.all_types() + link_types = parameters["link_type"] if "link_type" in parameters else "".join(lt.keys()) + + modes = project.network.modes.all_modes() + modes = list(set(parameters["mode"])) if "mode" in parameters else [k for k in modes.keys()] for counter, zone_id in enumerate(centroids): node = nodes.get(zone_id) - geo = polygon_from_radius(node.geometry) + geo = polygon_from_radius(node.geometry, 3000) for mode_id in modes: - node.connect_mode(area=geo, mode_id=mode_id, link_types=link_types, connectors=num_connectors) + node.connect_mode( + area=geo, mode_id=mode_id, link_types=link_types, connectors=parameters["num_connectors"] + ) feedback.pushInfo(" ") feedback.setCurrentStep(2) diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 51df633a..0df6a0e3 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -13,9 +13,7 @@ from PyQt5.QtCore import QVariant from qaequilibrae.modules.common_tools.data_layer_from_dataframe import layer_from_dataframe - from qaequilibrae.modules.processing_provider.provider import Provider - from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors from qaequilibrae.modules.processing_provider.add_links_from_layer import AddLinksFromLayer from qaequilibrae.modules.processing_provider.add_matrix_from_layer import AddMatrixFromLayer From 6aa6eb36e8051ea487b6c3543727bb0e23615b6a Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Fri, 6 Dec 2024 14:31:59 -0300 Subject: [PATCH 17/34] . --- .../add_links_from_layer.py | 4 ++- .../data/coquimbo_project/matrices/demand.aem | Bin 0 -> 142828 bytes .../data/coquimbo_project/transit_config.yaml | 14 ++++++++ test/test_processing_provider.py | 30 +++++++++++++++--- 4 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 test/data/coquimbo_project/matrices/demand.aem create mode 100644 test/data/coquimbo_project/transit_config.yaml diff --git a/qaequilibrae/modules/processing_provider/add_links_from_layer.py b/qaequilibrae/modules/processing_provider/add_links_from_layer.py index ce892976..fe7c9d90 100644 --- a/qaequilibrae/modules/processing_provider/add_links_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_links_from_layer.py @@ -122,6 +122,8 @@ def processAlgorithm(self, parameters, context, model_feedback): new_link.geometry = record.geometry new_link.save() + links.refresh() + feedback.pushInfo(" ") feedback.setCurrentStep(2) @@ -132,7 +134,7 @@ def processAlgorithm(self, parameters, context, model_feedback): project.close() feedback.pushInfo(self.tr("Closing project")) - return {"Output": project_path} + return {"Output": project.network.count_links()} def name(self): return "addlinksfromlayer" diff --git a/test/data/coquimbo_project/matrices/demand.aem b/test/data/coquimbo_project/matrices/demand.aem new file mode 100644 index 0000000000000000000000000000000000000000..b7d8463f4cc2f19b95da9f5ba587708c0be0df60 GIT binary patch literal 142828 zcmeIyTbGw(9Dw2Zx7U6{8A+)mBqf`WsL)o~Z=%N3Of}M^5koc!ecwI;ntPVxPOJ{D z_u#qT-@&`qyPowt*I;P)?V-ER?SIz6V6bRry1&=yt5cW9r@p&~pS&_UF*!0ZIX3>| ze;*Bcom1!5d3AnWP#4zOEqb7Naa~fE)@5~hT~SxoRdsb;Qy;7k)wOk9eYg(SN9y|e zXx&gBs~hX4`gq-3x74lmiMp*mS-01x>eKa^x}!c@ch=|XuDZKEU-#4(>WlTI`f}Y{ zU#YLw*Xq9ddfi{&sBhK-^O}Vp?8`O*CX|4Jyws`6ZPGCvYx8%)%WWM^~3s6 z{kVQoKdqnD&+F;>Mg6j#sb}j*{i=@EbM<^3tK;=Ty;v{RiTZWDT)(MT>SVoIzpdBm zRGq!g*PFkuKh)_udxd{$zEOX!ztmsrZ}n#Vz22&S)IaNA^>&@fosN&%kAHW-IdBe~ z1NVRf9N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4 zIKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G z-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$ zfCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h0 z0S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K0 z2ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`2 z9N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8 zaDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0W zzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h z00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70 z103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh1 z4sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4 zIKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G z-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$ cfCC)h00%h00S<70103K02ROii|JQ-P0TWjEJ^%m! literal 0 HcmV?d00001 diff --git a/test/data/coquimbo_project/transit_config.yaml b/test/data/coquimbo_project/transit_config.yaml new file mode 100644 index 00000000..a4be151d --- /dev/null +++ b/test/data/coquimbo_project/transit_config.yaml @@ -0,0 +1,14 @@ +project_path: path_to_project +result_name: transit_from_yaml +matrix_path: path_to_project/matrices/demand.aem +matrix_core: workers +assignment: + time_field: trav_time + frequency: freq + algorithm: os +graph: + period_id: 1 + with_outer_stop_transfers: False + with_walking_edges: False + blocking_centroid_flows: False + connector_method: overlapping_regions \ No newline at end of file diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 0df6a0e3..2008e479 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -9,7 +9,7 @@ from aequilibrae.matrix import AequilibraeMatrix from aequilibrae import Project from qgis.core import QgsApplication, QgsProcessingContext, QgsProcessingFeedback -from qgis.core import QgsProject, QgsField +from qgis.core import QgsProject, QgsField, QgsVectorLayer from PyQt5.QtCore import QVariant from qaequilibrae.modules.common_tools.data_layer_from_dataframe import layer_from_dataframe @@ -287,10 +287,31 @@ def test_import_gtfs(pt_no_feed, allow_map_match): assert result[0]["Output"] == "Traffic assignment successfully completed" -def test_add_links_from_layer(): +def test_add_links_from_layer(ae_with_project): + + csv_path = "test/data/NetworkPreparation/link.csv" + uri = "file://{}?delimiter=,&crs=epsg:4326&wktField={}".format(csv_path, "geometry") + layer = QgsVectorLayer(uri, "link", "delimitedtext") + + if not layer.isValid(): + print("Layer failed to load!") + else: + QgsProject.instance().addMapLayer(layer) action = AddLinksFromLayer() - pass + + parameters = { + "links": layer, + "link_type": "link_type", + "direction": "direction", + "modes": "modes", + "project_path": ae_with_project.project.project_base_path + } + + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() + + result = action.run(parameters, context, feedback) def test_assign_transit_from_yaml(): @@ -350,9 +371,8 @@ def test_matrix_calc(ae): pass -@pytest.mark.skip("Waaaaait a minute") +@pytest.mark.skip("Configure to run only in GH Actions") def test_project_from_osm(folder_path): - # makedirs(folder_path) action = ProjectFromOSM() From b81cf098e0e9118cdf94168e542e9e2357736e5c Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Fri, 6 Dec 2024 14:52:12 -0300 Subject: [PATCH 18/34] add test --- .../assign_pt_from_yaml.py | 31 +++++------ test/test_processing_provider.py | 52 +++++++++++++++++-- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py index ae3bdd80..5caefe5e 100644 --- a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -102,7 +102,7 @@ def processAlgorithm(self, parameters, context, model_feedback): project.close() - return {"Output": "PT assignment successfully completed"} + return {"Output": "Transit assignment successfully completed"} def name(self): return "ptassignfromyaml" @@ -129,24 +129,21 @@ def string_order(self, order): return self.tr("Example of valid configuration file:") elif order == 3: return textwrap.dedent( - """\ - project: D:/AequilibraE/Project/ - - result_name: sce_from_yaml - - transit_classes: - - student: - matrix_path: D:/AequilibraE/Project/matrices/demand.aem - matrix_core: student_pt - blocked_centroid_flows: True - skims: travel_time, distance - - worker: - matrix_path: D:/AequilibraE/Project/matrices/demand.aem - matrix_core: worker_pt - blocked_centroid_flows: True - + """ + project_path: path_to_project + result_name: transit_from_yaml + matrix_path: path_to_project/matrices/demand.aem + matrix_core: workers assignment: + time_field: trav_time + frequency: freq + algorithm: os + graph: period_id: 1 + with_outer_stop_transfers: False + with_walking_edges: False + blocking_centroid_flows: False + connector_method: overlapping_regions """ ) diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 2008e479..82c9669c 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -8,6 +8,7 @@ from shapely.geometry import Point from aequilibrae.matrix import AequilibraeMatrix from aequilibrae import Project +from aequilibrae.transit import Transit from qgis.core import QgsApplication, QgsProcessingContext, QgsProcessingFeedback from qgis.core import QgsProject, QgsField, QgsVectorLayer from PyQt5.QtCore import QVariant @@ -311,13 +312,58 @@ def test_add_links_from_layer(ae_with_project): context = QgsProcessingContext() feedback = QgsProcessingFeedback() - result = action.run(parameters, context, feedback) + _ = action.run(parameters, context, feedback) + + +def test_assign_transit_from_yaml(coquimbo_project): + + folder = coquimbo_project.project.project_base_path + file_path = join(folder, "transit_config.yml") + + assert isfile(file_path) + + string_to_replace = "path_to_project" + + with open(file_path, "r", encoding="utf-8") as file: + content = file.read() + updated_content = re.sub(re.escape(string_to_replace), folder, content) + + with open(file_path, "w", encoding="utf-8") as file: + file.write(updated_content) -def test_assign_transit_from_yaml(): + data = Transit(coquimbo_project.project) + graph = data.create_graph( + with_outer_stop_transfers=False, + with_walking_edges=False, + blocking_centroid_flows=False, + connector_method="overlapping_regions", + ) + + coquimbo_project.project.network.build_graphs() + graph.create_line_geometry(method="connector project match", graph="c") + + data.save_graphs() action = TransitAssignYAML() - pass + + parameters = {"conf_file": file_path} + + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() + + result = action.processAlgorithm(parameters, context, feedback) + + assert result["Output"] == "Transit assignment successfully completed" + + assert isfile(join(folder, "results_database.sqlite")) + + conn = sqlite3.connect(join(folder, "results_database.sqlite")) + tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchone()[0] + assert tables == "transit_from_yaml" + + row = conn.execute("SELECT * FROM transit_from_yaml;").fetchone() + assert row def test_create_matrix_from_layer(folder_path): From 3aaa35791ee58371f37b444517685ac20d6c9ebc Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 08:21:53 -0300 Subject: [PATCH 19/34] file path --- .../{transit_config.yaml => transit_config.yml} | 0 test/test_processing_provider.py | 9 ++++----- 2 files changed, 4 insertions(+), 5 deletions(-) rename test/data/coquimbo_project/{transit_config.yaml => transit_config.yml} (100%) diff --git a/test/data/coquimbo_project/transit_config.yaml b/test/data/coquimbo_project/transit_config.yml similarity index 100% rename from test/data/coquimbo_project/transit_config.yaml rename to test/data/coquimbo_project/transit_config.yml diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 82c9669c..3c1e62e5 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -4,7 +4,7 @@ import numpy as np import sqlite3 from os.path import isfile, join -from os import makedirs +from os import environ, makedirs from shapely.geometry import Point from aequilibrae.matrix import AequilibraeMatrix from aequilibrae import Project @@ -316,7 +316,6 @@ def test_add_links_from_layer(ae_with_project): def test_assign_transit_from_yaml(coquimbo_project): - folder = coquimbo_project.project.project_base_path file_path = join(folder, "transit_config.yml") @@ -387,10 +386,10 @@ def test_create_matrix_from_layer(folder_path): feedback = QgsProcessingFeedback() _ = action.run(parameters, context, feedback) - assert isfile(parameters["matrix_file"]) + assert isfile(parameters["file_name"]) mat = AequilibraeMatrix() - mat.load(parameters["matrix_file"]) + mat.load(parameters["file_name"]) info = mat.__dict__ assert info["names"] == [parameters["matrix_core"]] @@ -417,7 +416,7 @@ def test_matrix_calc(ae): pass -@pytest.mark.skip("Configure to run only in GH Actions") +@pytest.mark.skipif(not bool(environ.get('CI')), reason="Runs only in GitHub Action") def test_project_from_osm(folder_path): action = ProjectFromOSM() From 1a1d6faa7c549accc0b51ff6981c15e1dee2d6b8 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 08:42:30 -0300 Subject: [PATCH 20/34] Update test_processing_provider.py --- test/test_processing_provider.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 3c1e62e5..465f5cb8 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -2,6 +2,7 @@ import re import pandas as pd import numpy as np +import shutil import sqlite3 from os.path import isfile, join from os import environ, makedirs @@ -306,7 +307,7 @@ def test_add_links_from_layer(ae_with_project): "link_type": "link_type", "direction": "direction", "modes": "modes", - "project_path": ae_with_project.project.project_base_path + "project_path": ae_with_project.project.project_base_path, } context = QgsProcessingContext() @@ -317,8 +318,10 @@ def test_add_links_from_layer(ae_with_project): def test_assign_transit_from_yaml(coquimbo_project): folder = coquimbo_project.project.project_base_path - file_path = join(folder, "transit_config.yml") + shutil.copyfile("test/data/coquimbo_project/transit_config.yml", f"{folder}/transit_config.yml") + shutil.copyfile("test/data/coquimbo_project/matrices/demand.aem", f"{folder}/matrices/demand.aem") + file_path = join(folder, "transit_config.yml") assert isfile(file_path) string_to_replace = "path_to_project" @@ -333,19 +336,19 @@ def test_assign_transit_from_yaml(coquimbo_project): data = Transit(coquimbo_project.project) graph = data.create_graph( - with_outer_stop_transfers=False, - with_walking_edges=False, - blocking_centroid_flows=False, - connector_method="overlapping_regions", - ) - + with_outer_stop_transfers=False, + with_walking_edges=False, + blocking_centroid_flows=False, + connector_method="overlapping_regions", + ) + coquimbo_project.project.network.build_graphs() graph.create_line_geometry(method="connector project match", graph="c") - + data.save_graphs() action = TransitAssignYAML() - + parameters = {"conf_file": file_path} context = QgsProcessingContext() @@ -416,7 +419,7 @@ def test_matrix_calc(ae): pass -@pytest.mark.skipif(not bool(environ.get('CI')), reason="Runs only in GitHub Action") +@pytest.mark.skipif(not bool(environ.get("CI")), reason="Runs only in GitHub Action") def test_project_from_osm(folder_path): action = ProjectFromOSM() From bea9f8446a89cf193f458e43cb45b97fbb6a46a9 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 08:52:27 -0300 Subject: [PATCH 21/34] Fix test add links from layer --- test/test_processing_provider.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 465f5cb8..9b94671b 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -290,8 +290,10 @@ def test_import_gtfs(pt_no_feed, allow_map_match): def test_add_links_from_layer(ae_with_project): + folder_path = ae_with_project.project.project_base_path + csv_path = f"{folder_path}/link.csv" + shutil.copyfile("test/data/NetworkPreparation/link.csv", csv_path) - csv_path = "test/data/NetworkPreparation/link.csv" uri = "file://{}?delimiter=,&crs=epsg:4326&wktField={}".format(csv_path, "geometry") layer = QgsVectorLayer(uri, "link", "delimitedtext") @@ -315,6 +317,12 @@ def test_add_links_from_layer(ae_with_project): _ = action.run(parameters, context, feedback) + project = Project() + project.open(folder_path) + + assert project.network.count_links() == 80 + assert project.network.count_nodes() == 28 + def test_assign_transit_from_yaml(coquimbo_project): folder = coquimbo_project.project.project_base_path From c0b9f02e2d5084a03cfbfdcd2ed22860c7122c0f Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 09:09:21 -0300 Subject: [PATCH 22/34] Update create_matrix_from_layer.py --- .../modules/processing_provider/create_matrix_from_layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py index 21203515..2dc118c8 100644 --- a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py @@ -152,7 +152,7 @@ def createInstance(self): def string_order(self, order): if order == 1: - return self.tr("Save layer as a *.aem file. Notice that:") + return self.tr("Save layer as a new *.aem file. Notice that:") elif order == 2: return self.tr("- the original matrix stored in the layer needs to be in list format") elif order == 3: From 3066babe8e4d2e9ea5470808215ee5b888515aa0 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 09:40:04 -0300 Subject: [PATCH 23/34] Test add matrix from layer --- .../add_matrix_from_layer.py | 33 +++++++------------ test/test_processing_provider.py | 16 ++++----- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py index a3e45258..413bd1a3 100644 --- a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py @@ -5,8 +5,8 @@ from scipy.sparse import coo_matrix from qgis.core import QgsProcessingMultiStepFeedback, QgsProcessingParameterString -from qgis.core import QgsProcessingParameterField, QgsProcessingParameterMapLayer, QgsProcessingParameterFile -from qgis.core import QgsProcessingAlgorithm +from qgis.core import QgsProcessingParameterField, QgsProcessingParameterMapLayer +from qgis.core import QgsProcessingAlgorithm, QgsProcessingParameterFileDestination from qaequilibrae.i18n.translate import trlt @@ -46,13 +46,7 @@ def initAlgorithm(self, config=None): ) ) self.addParameter( - QgsProcessingParameterFile( - "matrix_file", - self.tr("Output name"), - behavior=QgsProcessingParameterFile.File, - fileFilter="", - defaultValue=None, - ) + QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "Open Matrix (*.omx)") ) self.addParameter( @@ -65,14 +59,13 @@ def processAlgorithm(self, parameters, context, model_feedback): sys.exit(self.tr("AequilibraE module not found")) from aequilibrae.matrix import AequilibraeMatrix + import openmatrix as omx feedback = QgsProcessingMultiStepFeedback(3, model_feedback) origin = parameters["origin"] destination = parameters["destination"] value = parameters["value"] - list_cores = [parameters["matrix_core"]] - path_to_file = parameters["matrix_file"] # Import layer as a pandas df feedback.pushInfo(self.tr("Importing layer")) @@ -98,11 +91,6 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback.pushInfo(" ") feedback.setCurrentStep(2) - mat = AequilibraeMatrix() - mat.create_empty( - file_name=path_to_file[:-4] + ".aem", zones=nb_of_zones, matrix_names=list_cores, memory_only=False - ) - m = ( coo_matrix( (trip_df[value], (trip_df[origin + "_idx"], trip_df[destination + "_idx"])), @@ -112,19 +100,20 @@ def processAlgorithm(self, parameters, context, model_feedback): .astype(np.float64) ) - mat.matrix[mat.names[0]][:, :] = m[:, :] - mat.save() + mat = omx.open_file(parameters["file_name"], "a") + mat[parameters["matrix_core"]] = m + mat.close() feedback.pushInfo(" ") feedback.setCurrentStep(3) - return {"Output": f"{mat.name}, {mat.description} ({path_to_file})"} + return {"Output": f"New core addedd to {parameters["file_name"]}"} def name(self): - return "exportmatrixasaem" + return "exportmatrixasomx" def displayName(self): - return self.tr("Add matrix from layer to aem file") + return self.tr("Save matrix from layer in existing file") def group(self): return self.tr("2. Data") @@ -148,7 +137,7 @@ def createInstance(self): def string_order(self, order): if order == 1: - return self.tr("Save a layer to an existing *.aem file. Notice that:") + return self.tr("Save a layer to an existing *.omx file. Notice that:") elif order == 2: return self.tr("- the original matrix stored in the layer needs to be in list format") elif order == 3: diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 9b94671b..94fac357 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -2,6 +2,7 @@ import re import pandas as pd import numpy as np +import openmatrix as omx import shutil import sqlite3 from os.path import isfile, join @@ -80,7 +81,7 @@ def test_matrix_from_layer(folder_path): "origin": "O", "destination": "D", "value": "Ton", - "matrix_file": join(folder_path, "siouxfalls_od.aem"), + "file_name": join(folder_path, "demand.omx"), "matrix_core": "MAT_CORE", } @@ -89,15 +90,14 @@ def test_matrix_from_layer(folder_path): _ = action.run(parameters, context, feedback) - assert isfile(parameters["matrix_file"]) + assert isfile(parameters["file_name"]) - mat = AequilibraeMatrix() - mat.load(parameters["matrix_file"]) + mat = omx.open_file(parameters["file_name"]) + assert "MAT_CORE" in mat.list_matrices() - info = mat.__dict__ - assert info["names"] == [parameters["matrix_core"]] - assert info["zones"] == 24 - assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 + m = np.array(mat["MAT_CORE"]) + assert m.shape == (24, 24) + assert m.sum() == 360600 @pytest.mark.parametrize("load_sfalls_from_layer", ["tmp"], indirect=True) From 95f8c4cf59deb84f68d03578c5333c79e5d2af46 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 09:49:34 -0300 Subject: [PATCH 24/34] Fix parameter --- test/test_processing_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 94fac357..426f847a 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -432,7 +432,7 @@ def test_project_from_osm(folder_path): action = ProjectFromOSM() - parameters = {"place_name": "Abrolhos", "project_folder": folder_path} + parameters = {"place_name": "Abrolhos", "project_path": folder_path} context = QgsProcessingContext() feedback = QgsProcessingFeedback() From d1c06ef13738b6138ba79b149be672b41aedac1e Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 11:42:12 -0300 Subject: [PATCH 25/34] Update matrix calculator --- .../processing_provider/matrix_calculator.py | 197 ++++++------------ .../data/SiouxFalls_project/matrix_config.yml | 6 + test/test_processing_provider.py | 32 +-- 3 files changed, 86 insertions(+), 149 deletions(-) create mode 100644 test/data/SiouxFalls_project/matrix_config.yml diff --git a/qaequilibrae/modules/processing_provider/matrix_calculator.py b/qaequilibrae/modules/processing_provider/matrix_calculator.py index dcb61871..3e1d6023 100644 --- a/qaequilibrae/modules/processing_provider/matrix_calculator.py +++ b/qaequilibrae/modules/processing_provider/matrix_calculator.py @@ -1,11 +1,14 @@ import importlib.util as iutil import sys import textwrap - -from datetime import datetime as dt +import yaml from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile -from qgis.core import QgsProcessingParameterDefinition, QgsProcessingParameterBoolean, QgsProcessingParameterString +from qgis.core import ( + QgsProcessingParameterDefinition, + QgsProcessingParameterFileDestination, + QgsProcessingParameterString, +) from qaequilibrae.i18n.translate import trlt @@ -13,6 +16,16 @@ class MatrixCalculator(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): + self.operation_map = { + "min(": "np.min(", + "max(": "np.max(", + "abs(": "np.absolute(", + "ln(": "np.log(", + "exp(": "np.exp(", + "power(": "np.power(", + "null_diag(": "np.null_diag(", + } + self.addParameter( QgsProcessingParameterFile( "conf_file", @@ -23,21 +36,13 @@ def initAlgorithm(self, config=None): ) ) self.addParameter( - QgsProcessingParameterString("request", self.tr("Request"), multiLine=False, defaultValue=None) + QgsProcessingParameterString("procedure", self.tr("Matrix core"), multiLine=True, defaultValue="") ) self.addParameter( - QgsProcessingParameterFile( - "dest_path", - self.tr("Existing .aem file") + self.tr("(used to store computed matrix)"), - behavior=QgsProcessingParameterFile.File, - fileFilter="", - defaultValue=None, - ) + QgsProcessingParameterString("matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="matrix") ) self.addParameter( - QgsProcessingParameterString( - "matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="MatrixCalculator_Result" - ) + QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "AequilibraE Matrix (*.aem)") ) advparams = [ @@ -51,119 +56,58 @@ def initAlgorithm(self, config=None): self.addParameter(param) def processAlgorithm(self, parameters, context, model_feedback): - feedback = QgsProcessingMultiStepFeedback(4, model_feedback) - # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: sys.exit(self.tr("AequilibraE module not found")) - exec("from aequilibrae.matrix import AequilibraeMatrix", globals()) - exec("import numpy as np", globals()) - import yaml + from aequilibrae.matrix import AequilibraeMatrix - start = dt.now() - - # Import or create all needed matrices as numpy arrays + feedback = QgsProcessingMultiStepFeedback(4, model_feedback) feedback.pushInfo(self.tr("Getting matrices from configuration file")) - conf_file = parameters["conf_file"] - dest_path = parameters["dest_path"] - dest_core = [parameters["matrix_core"]] - request = parameters["request"] - - destination = AequilibraeMatrix() - destination.load(dest_path) - global d - d = len(destination.get_matrix(dest_core[0])) - - feedback.pushInfo( - self.tr("Matrix total before calculation: ") - + "{:,.2f}".format(destination.get_matrix(dest_core[0]).sum()).replace(",", " ") - ) - feedback.pushInfo(self.tr("Expected dimensions of matrix based on destination file: ") + str(d) + "x" + str(d)) - feedback.pushInfo("") - with open(conf_file, "r") as f: + with open(parameters["conf_file"], "r") as f: params = yaml.safe_load(f) - m_list = [] - - for matrices in params["Matrices"]: - for matrix in matrices: - exec( - f""" -{matrix} = AequilibraeMatrix() -{matrix}.load("{matrices[matrix]["matrix_path"]}") -{matrix}={matrix}.get_matrix("{matrices[matrix]["matrix_core"]}") -""", - globals(), - ) - - m_list.append(matrix) - exec(f"dim=len({matrix})", globals()) - feedback.pushInfo(str(matrix)) - feedback.pushInfo(self.tr(f"Importation of {matrix}, matrix dimensions {dim}x{dim} and total is:")) - exec('feedback.pushInfo("{:,.2f}".format(' + matrix + '.sum()).replace(",", " "))') - assert d == dim, self.tr("Matrices must have the same dimensions as the desired result !") - feedback.pushInfo("") - - if "null_diag" in request: # If needed, prepare a matrix to set diagonal to 0 - exec( - """ -null_diag=np.ones((d, d), dtype=np.float64) -np.fill_diagonal(null_diag, 0)""", - globals(), - ) - if "zeros" in request: # If needed, prepare a matrix full of zero - exec("zeros=np.zeros((d, d), dtype=np.float64)", globals()) - feedback.pushInfo(" ") - feedback.setCurrentStep(1) - - # Setting up request, Used grammar is close to R language, need to be translated for numpy - request = request.replace("max(", "np.maximum(") - request = request.replace("min(", "np.minimum(") - request = request.replace("ln(", "np.log(") - request = request.replace("exp(", "np.exp(") - request = request.replace("power(", "np.power(") - request = request.replace("abs(", "np.absolute(") - request = request.replace("null_diag(", "null_diag*(") - request = request.replace("t(", "np.transpose(") - - feedback.pushInfo(" ") - feedback.setCurrentStep(2) - - # Compute request: if a filtering matrix is used, update only a part of the destination matrix - filtering_matrix = parameters["filtering_matrix"] - if len(filtering_matrix) > 0: - global result - exec("filtering_matrix=np.nan_to_num(" + filtering_matrix + ")", globals()) - assert np.any((filtering_matrix == 0.0) | (filtering_matrix == 1.0)) - keep = np.absolute(filtering_matrix - np.ones(d)) * destination.get_matrix(dest_core[0]) - exec("new=filtering_matrix*(" + request + ")", globals()) - result = keep + new - del filtering_matrix - else: - exec("result=" + request, globals()) - feedback.pushInfo(self.tr("Result (total: ") + f"{'{:,.2f}'.format(result.sum()).replace(',', ' ')}): ") - feedback.pushInfo(str(result)) - - feedback.pushInfo(" ") - feedback.setCurrentStep(3) - - # Updating destination matrix file - destination.matrix[dest_core[0]][:, :] = result[:, :] - destination.save() - destination.close() - - for m in m_list: - exec("del " + m, globals()) - - feedback.pushInfo(" ") - feedback.setCurrentStep(4) - - return {"Output": self.tr("Calculation completed in: ") + str((dt.now() - start).total_seconds()) + "secs"} + # Load matrices + matrices = {} + index = [] + for matrix in params: + for name, values in matrix.items(): + mat = AequilibraeMatrix() + mat.load(values["matrix_path"]) + matrices[name] = mat.get_matrix(values["matrix_core"]) + index[:] = mat.index[:] + mat.close() + + expression = parameters["procedure"] + + # Replace the expression for matrices variables + for key in matrices.keys(): + if key in expression: + expression = expression.replace(key, f"matrices['{key}']") + + # Replace the expression for numpy operations + for key in self.operation_map.keys(): + if key in expression: + expression = expression.replace(key, self.operation_map[key]) + + out = eval(expression) + + mat = AequilibraeMatrix() + mat.create_empty( + file_name=parameters["file_name"], + zones=len(index), + matrix_names=[parameters["matrix_core"]], + memory_only=False, + ) + mat.matrix[parameters["matrix_core"]][:, :] = out[:, :] + mat.index[:] = index[:] + mat.close() + + return {"Output": "Finished"} def name(self): - return "matrixcald" + return "matrixcalc" def displayName(self): return self.tr("Matrix calculator") @@ -185,8 +129,6 @@ def shortHelpString(self): self.string_order(5), self.string_order(6), self.string_order(7), - self.string_order(8), - self.string_order(9), ] ) ) @@ -230,25 +172,6 @@ def string_order(self, order): matrix_core: gen_time """ ) - elif order == 8: - return self.tr("List of available functions :") - elif order == 9: - return textwrap.dedent( - """\ - + - - - / - * - min(matA, matB) - max(matA, matB) - abs(matA) - ln(matA) - exp(matA) - power(matA, n) - null_diag(matA) - t(matA) #transpose - """ - ) def tr(self, message): return trlt("MatrixCalculator", message) diff --git a/test/data/SiouxFalls_project/matrix_config.yml b/test/data/SiouxFalls_project/matrix_config.yml new file mode 100644 index 00000000..03f4fbc2 --- /dev/null +++ b/test/data/SiouxFalls_project/matrix_config.yml @@ -0,0 +1,6 @@ +- cars: + matrix_path: test/data/SiouxFalls_project/matrices/demand_mc.aem + matrix_core: car +- heavy_vehicles: + matrix_path: test/data/SiouxFalls_project/matrices/demand_mc.aem + matrix_core: trucks diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 426f847a..f9bc7582 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -408,23 +408,31 @@ def test_create_matrix_from_layer(folder_path): assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) == 360600 -def test_matrix_calc(ae): +def test_matrix_calc(folder_path): + makedirs(folder_path) action = MatrixCalculator() - # parameters = { - # "conf_file": "test/data/SiouxFalls_project/matrix_config.yml", - # "procedure": "sum (m1, m2)", - # "dest_path": "test/data/SiouxFalls_project/matrices/asdfg.aem", - # "matrix_core": "new_core", - # } + parameters = { + "conf_file": "test/data/SiouxFalls_project/matrix_config.yml", + "procedure": "(cars + heavy_vehicles).T", + "file_name": f"{folder_path}/hello.aem", + "matrix_core": "new_core", + } + + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() + + _ = action.run(parameters, context, feedback) - # context = QgsProcessingContext() - # feedback = QgsProcessingFeedback() + assert isfile(parameters["file_name"]) + mat = AequilibraeMatrix() + mat.load(parameters["file_name"]) - # result = action.run(parameters, context, feedback) - # print(result) - pass + info = mat.__dict__ + assert info["names"] == [parameters["matrix_core"]] + assert info["zones"] == 24 + assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) > 360600 @pytest.mark.skipif(not bool(environ.get("CI")), reason="Runs only in GitHub Action") From fde1619e513bb45325f37739c9e3edbf7088dd4b Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 14:59:26 -0300 Subject: [PATCH 26/34] rename parameters --- .../processing_provider/Add_connectors.py | 25 ++--- .../add_links_from_layer.py | 22 ++--- .../add_matrix_from_layer.py | 14 +-- .../assign_pt_from_yaml.py | 1 - .../create_matrix_from_layer.py | 8 +- .../processing_provider/create_pt_graph.py | 24 ++--- .../processing_provider/import_gtfs.py | 11 ++- .../processing_provider/matrix_calculator.py | 96 +++++-------------- .../processing_provider/project_from_layer.py | 23 +---- .../renumber_nodes_from_layer.py | 21 ++-- test/test_processing_provider.py | 8 +- 11 files changed, 91 insertions(+), 162 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/Add_connectors.py b/qaequilibrae/modules/processing_provider/Add_connectors.py index 541ea9b4..91ef3614 100644 --- a/qaequilibrae/modules/processing_provider/Add_connectors.py +++ b/qaequilibrae/modules/processing_provider/Add_connectors.py @@ -4,13 +4,14 @@ from qgis.core import ( QgsProcessingMultiStepFeedback, QgsProcessingAlgorithm, + QgsProcessingParameterDefinition, QgsProcessingParameterFile, QgsProcessingParameterNumber, QgsProcessingParameterString, ) from qaequilibrae.i18n.translate import trlt -from qaequilibrae.modules.common_tools import standard_path, polygon_from_radius +from qaequilibrae.modules.common_tools import polygon_from_radius class AddConnectors(QgsProcessingAlgorithm): @@ -18,31 +19,31 @@ class AddConnectors(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterFile( - "project_path", - self.tr("Project path"), - behavior=QgsProcessingParameterFile.Folder, - defaultValue=standard_path(), + "project_path", self.tr("Project path"), behavior=QgsProcessingParameterFile.Folder ) ) self.addParameter( QgsProcessingParameterNumber( "num_connectors", - self.tr("Connectors per centroid"), + self.tr("Number of connectors per centroid"), type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=1, ) ) - self.addParameter( + + advparams = [ QgsProcessingParameterString( "mode", self.tr("Modes to connect (defaults to all)"), multiLine=False, optional=True - ) - ) - self.addParameter( + ), QgsProcessingParameterString( "link_type", self.tr("Link types to connect (defaults to all)"), multiLine=False, optional=True - ) - ) + ), + ] + + for param in advparams: + param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) + self.addParameter(param) def processAlgorithm(self, parameters, context, model_feedback): # Checks if we have access to aequilibrae library diff --git a/qaequilibrae/modules/processing_provider/add_links_from_layer.py b/qaequilibrae/modules/processing_provider/add_links_from_layer.py index fe7c9d90..45054b74 100644 --- a/qaequilibrae/modules/processing_provider/add_links_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_links_from_layer.py @@ -7,12 +7,19 @@ from qgis.core import QgsProcessingParameterField, QgsProcessingParameterFile from qaequilibrae.i18n.translate import trlt -from qaequilibrae.modules.common_tools import geodataframe_from_layer, standard_path +from qaequilibrae.modules.common_tools import geodataframe_from_layer class AddLinksFromLayer(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterFile( + "project_path", + self.tr("Project path"), + behavior=QgsProcessingParameterFile.Folder, + ) + ) self.addParameter( QgsProcessingParameterVectorLayer( "links", self.tr("Links"), types=[QgsProcessing.TypeVectorLine], defaultValue=None @@ -25,7 +32,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.String, parentLayerParameterName="links", allowMultiple=False, - defaultValue="link_type", ) ) self.addParameter( @@ -35,7 +41,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="links", allowMultiple=False, - defaultValue="direction", ) ) self.addParameter( @@ -45,15 +50,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.String, parentLayerParameterName="links", allowMultiple=False, - defaultValue="modes", - ) - ) - self.addParameter( - QgsProcessingParameterFile( - "project_path", - self.tr("Project path"), - behavior=QgsProcessingParameterFile.Folder, - defaultValue=standard_path(), ) ) @@ -149,7 +145,7 @@ def groupId(self): return "modelbuilding" def shortHelpString(self): - return self.tr("Take links from a layer and add them to an existing AequilibraE project") + return self.tr("Adds links from a layer to an existing AequilibraE project") def createInstance(self): return AddLinksFromLayer() diff --git a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py index 413bd1a3..487ef6c9 100644 --- a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py @@ -14,6 +14,9 @@ class AddMatrixFromLayer(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "Open Matrix (*.omx)") + ) self.addParameter(QgsProcessingParameterMapLayer("matrix_layer", self.tr("Matrix Layer"))) self.addParameter( QgsProcessingParameterField( @@ -22,7 +25,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="matrix_layer", allowMultiple=False, - defaultValue="origin", ) ) self.addParameter( @@ -32,7 +34,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="matrix_layer", allowMultiple=False, - defaultValue="destination", ) ) self.addParameter( @@ -42,16 +43,9 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="matrix_layer", allowMultiple=False, - defaultValue="value", ) ) - self.addParameter( - QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "Open Matrix (*.omx)") - ) - - self.addParameter( - QgsProcessingParameterString("matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="Value") - ) + self.addParameter(QgsProcessingParameterString("matrix_core", self.tr("Matrix core"), "matrix_core", False)) def processAlgorithm(self, parameters, context, model_feedback): # Checks if we have access to aequilibrae library diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py index 5caefe5e..7e7b4d94 100644 --- a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -17,7 +17,6 @@ def initAlgorithm(self, config=None): self.tr("Configuration file (.yaml)"), behavior=QgsProcessingParameterFile.File, fileFilter="", - defaultValue=None, ) ) diff --git a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py index 2dc118c8..018eb3d8 100644 --- a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py @@ -42,6 +42,11 @@ def initAlgorithm(self, config=None): allowMultiple=False, ) ) + self.addParameter( + QgsProcessingParameterString( + "matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="matrix_core" + ) + ) self.addParameter( QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "AequilibraE Matrix (*.aem)") ) @@ -59,9 +64,6 @@ def initAlgorithm(self, config=None): optional=True, multiLine=False, ), - QgsProcessingParameterString( - "matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="matrix_core" - ), ] for param in advparams: param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) diff --git a/qaequilibrae/modules/processing_provider/create_pt_graph.py b/qaequilibrae/modules/processing_provider/create_pt_graph.py index b020e78f..e89643ae 100644 --- a/qaequilibrae/modules/processing_provider/create_pt_graph.py +++ b/qaequilibrae/modules/processing_provider/create_pt_graph.py @@ -1,8 +1,7 @@ import importlib.util as iutil import sys -import textwrap -from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile +from qgis.core import QgsProcessingAlgorithm, QgsProcessingParameterFile from qgis.core import QgsProcessingParameterBoolean, QgsProcessingParameterString, QgsProcessingParameterNumber from qgis.core import QgsProcessingParameterDefinition @@ -21,9 +20,8 @@ def initAlgorithm(self, config=None): defaultValue=standard_path(), ) ) - # This should load all mode_ids available. Could be a dict, e.g.: "w": walk, "c": car, etc self.addParameter( - QgsProcessingParameterString("access_mode", self.tr("access mode"), multiLine=False, defaultValue="w") + QgsProcessingParameterString("access_mode", self.tr("Mode"), multiLine=False, defaultValue="w") ) self.addParameter( QgsProcessingParameterBoolean("block_flows", self.tr("Block flows through centroids"), defaultValue=True) @@ -40,7 +38,7 @@ def initAlgorithm(self, config=None): advparams = [ QgsProcessingParameterBoolean("has_zones", self.tr("Project has zoning information"), defaultValue=True), QgsProcessingParameterNumber( - "period_id", self.tr("Period id"), type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=1 + "period_id", self.tr("Period ID"), type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=1 ), ] @@ -65,13 +63,15 @@ def processAlgorithm(self, parameters, context, feedback): feedback.pushInfo(" ") feedback.pushInfo(self.tr("Creating graph")) # Creating graph - if not parameters["has_zones"]: - graph = data.create_graph( - with_outer_stop_transfers=parameters["outer_stops_transfers"], - with_walking_edges=parameters["walking_edges"], - blocking_centroid_flows=parameters["block_flows"], - connector_method="overlapping_regions", - ) + if "has_zones" in parameters and parameters["has_zones"] == True: + graph.add_zones(project.zoning) + + graph = data.create_graph( + with_outer_stop_transfers=parameters["outer_stops_transfers"], + with_walking_edges=parameters["walking_edges"], + blocking_centroid_flows=parameters["block_flows"], + connector_method="overlapping_regions", + ) feedback.pushInfo(" ") # Connector matching diff --git a/qaequilibrae/modules/processing_provider/import_gtfs.py b/qaequilibrae/modules/processing_provider/import_gtfs.py index 68b1c57f..c62f3a1e 100644 --- a/qaequilibrae/modules/processing_provider/import_gtfs.py +++ b/qaequilibrae/modules/processing_provider/import_gtfs.py @@ -14,16 +14,18 @@ def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterFile( "gtfs_file", - self.tr("GTFS file (.zip)"), + self.tr("GTFS file"), behavior=QgsProcessingParameterFile.File, - fileFilter="", - defaultValue=None, + fileFilter="ZIP (*.zip)", ) ) self.addParameter(QgsProcessingParameterString("gtfs_agency", self.tr("Transit agency"), multiLine=False)) self.addParameter( QgsProcessingParameterString( - "gtfs_date", self.tr("Date to import (YYYY-MM-DD)"), multiLine=False, defaultValue="1980-01-01" + "gtfs_date", + self.tr("Date to import (YYYY-MM-DD)"), + defaultValue="1980-01-01", + multiLine=False, ) ) self.addParameter( @@ -34,7 +36,6 @@ def initAlgorithm(self, config=None): "project_path", self.tr("Project path"), behavior=QgsProcessingParameterFile.Folder, - defaultValue=standard_path(), ) ) diff --git a/qaequilibrae/modules/processing_provider/matrix_calculator.py b/qaequilibrae/modules/processing_provider/matrix_calculator.py index 3e1d6023..4c3ffbe0 100644 --- a/qaequilibrae/modules/processing_provider/matrix_calculator.py +++ b/qaequilibrae/modules/processing_provider/matrix_calculator.py @@ -1,11 +1,13 @@ import importlib.util as iutil import sys -import textwrap import yaml -from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile +from qgis.core import QgsProcessingException from qgis.core import ( + QgsProcessingAlgorithm, + QgsProcessingMultiStepFeedback, QgsProcessingParameterDefinition, + QgsProcessingParameterFile, QgsProcessingParameterFileDestination, QgsProcessingParameterString, ) @@ -29,14 +31,12 @@ def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterFile( "conf_file", - self.tr("Matrix configuration file (.yaml)"), + self.tr("Configuration file (*.yaml)"), behavior=QgsProcessingParameterFile.File, - fileFilter="", - defaultValue=None, ) ) self.addParameter( - QgsProcessingParameterString("procedure", self.tr("Matrix core"), multiLine=True, defaultValue="") + QgsProcessingParameterString("procedure", self.tr("Expression"), multiLine=True, defaultValue="") ) self.addParameter( QgsProcessingParameterString("matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="matrix") @@ -45,16 +45,6 @@ def initAlgorithm(self, config=None): QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "AequilibraE Matrix (*.aem)") ) - advparams = [ - QgsProcessingParameterString( - "filtering_matrix", self.tr("Filtering matrix"), multiLine=False, optional=True, defaultValue=None - ) - ] - - for param in advparams: - param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) - self.addParameter(param) - def processAlgorithm(self, parameters, context, model_feedback): # Checks if we have access to aequilibrae library if iutil.find_spec("aequilibrae") is None: @@ -62,6 +52,9 @@ def processAlgorithm(self, parameters, context, model_feedback): from aequilibrae.matrix import AequilibraeMatrix + if parameters["file_name"] is None: + raise QgsProcessingException(self.tr("Plase use a valid file name.")) + feedback = QgsProcessingMultiStepFeedback(4, model_feedback) feedback.pushInfo(self.tr("Getting matrices from configuration file")) @@ -81,16 +74,16 @@ def processAlgorithm(self, parameters, context, model_feedback): expression = parameters["procedure"] - # Replace the expression for matrices variables - for key in matrices.keys(): - if key in expression: - expression = expression.replace(key, f"matrices['{key}']") - # Replace the expression for numpy operations for key in self.operation_map.keys(): if key in expression: expression = expression.replace(key, self.operation_map[key]) + # Replace the expression for matrices variables + for key in matrices.keys(): + if key in expression: + expression = expression.replace(key, f"matrices['{key}']") + out = eval(expression) mat = AequilibraeMatrix() @@ -119,59 +112,20 @@ def groupId(self): return "data" def shortHelpString(self): - return textwrap.dedent( - "\n".join( - [ - self.string_order(1), - self.string_order(2), - self.string_order(3), - self.string_order(4), - self.string_order(5), - self.string_order(6), - self.string_order(7), - ] - ) - ) + help_messages = [ + self.tr("Run a matrix calculation based on a matrix configuration file (*.yaml) and an expression."), + self.tr("Results are stored in an AequilibraE Matrix."), + self.tr("Please notice that:"), + self.tr( + "- each key in the configuration file corresponds to the name of the matrix in the input expression;" + ), + self.tr("- expression must be written according to NumPy syntax."), + self.tr("Examples of valid expressions and configuration are provided in the plugin documentation."), + ] + return "\n".join(help_messages) def createInstance(self): return MatrixCalculator() - def string_order(self, order): - if order == 1: - return self.tr("Run a matrix calculation based on a request and a matrix config file (.yaml) :") - elif order == 2: - return self.tr("- Matrix configuration file (.yaml file)") - elif order == 3: - return ( - self.tr("- Request as a formula, example : ") - + "null_diag( abs( max( t(matA)-(matB*3), zeros ) + power(matC,2) ) )" - ) - elif order == 4: - return self.tr("- .aem file and matrix core to store calculated matrix") - elif order == 5: - return self.tr( - "- filtering matrix, a matrix of 0 and 1 defined in matrix config file that will be used to update only a part of the destination matrix " - ) - elif order == 6: - return self.tr("Example of valid matrix configuration file:") - elif order == 7: - return textwrap.dedent( - """\ - Matrices: - - generation: - matrix_path: D:/AequilibraE/Project/matrices/socioeconomic_2024.aem - matrix_core: generation - - pop2024: - matrix_path: D:/AequilibraE/Project/matrices/socioeconomic_2024.aem - matrix_core: pop_dest - - emp2024: - matrix_path: D:/AequilibraE/Project/matrices/socioeconomic_2024.aem - matrix_core: emp_dest - - gen_time: - matrix_path: D:/AequilibraE/Project/matrices/aon_skims.aem - matrix_core: gen_time - """ - ) - def tr(self, message): return trlt("MatrixCalculator", message) diff --git a/qaequilibrae/modules/processing_provider/project_from_layer.py b/qaequilibrae/modules/processing_provider/project_from_layer.py index e0c847fe..f781c129 100644 --- a/qaequilibrae/modules/processing_provider/project_from_layer.py +++ b/qaequilibrae/modules/processing_provider/project_from_layer.py @@ -5,7 +5,7 @@ from qgis.core import QgsProcessingAlgorithm from qgis.core import QgsProcessing, QgsProcessingMultiStepFeedback, QgsProcessingParameterVectorLayer -from qgis.core import QgsProcessingParameterField, QgsProcessingParameterFile, QgsProcessingParameterString +from qgis.core import QgsProcessingParameterField, QgsProcessingParameterFolderDestination from qaequilibrae.i18n.translate import trlt from qaequilibrae.modules.common_tools import geodataframe_from_layer, standard_path @@ -26,7 +26,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="links", allowMultiple=False, - defaultValue="link_id", ) ) self.addParameter( @@ -36,7 +35,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.String, parentLayerParameterName="links", allowMultiple=False, - defaultValue="link_type", ) ) self.addParameter( @@ -46,7 +44,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="links", allowMultiple=False, - defaultValue="direction", ) ) self.addParameter( @@ -56,21 +53,10 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.String, parentLayerParameterName="links", allowMultiple=False, - defaultValue="modes", ) ) self.addParameter( - QgsProcessingParameterFile( - "folder", - self.tr("Output folder"), - behavior=QgsProcessingParameterFile.Folder, - defaultValue=standard_path(), - ) - ) - self.addParameter( - QgsProcessingParameterString( - "project_name", self.tr("Project name"), multiLine=False, defaultValue="new_project" - ) + QgsProcessingParameterFolderDestination("project_path", self.tr("Output folder"), createByDefault=True) ) def processAlgorithm(self, parameters, context, model_feedback): @@ -83,9 +69,8 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback = QgsProcessingMultiStepFeedback(5, model_feedback) feedback.pushInfo(self.tr("Creating project")) - project_path = join(parameters["folder"], parameters["project_name"]) project = Project() - project.new(project_path) + project.new(parameters["project_path"]) feedback.pushInfo(self.tr("Importing links layer")) @@ -156,7 +141,7 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback.pushInfo(self.tr("Closing project")) - return {"Output": project_path} + return {"Output": parameters["project_path"]} def name(self): return "projectfromlayer" diff --git a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py index 77c5a859..8c3eaefb 100644 --- a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py +++ b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py @@ -8,15 +8,23 @@ from qgis.core import QgsProcessingParameterVectorLayer, QgsProcessingParameterField, QgsProcessingParameterFile from qaequilibrae.i18n.translate import trlt -from qaequilibrae.modules.common_tools import standard_path class RenumberNodesFromLayer(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterFile( + "project_path", + self.tr("Project path"), + behavior=QgsProcessingParameterFile.Folder, + ) + ) self.addParameter( QgsProcessingParameterVectorLayer( - "nodes", self.tr("Centroids"), types=[QgsProcessing.TypeVectorPoint], defaultValue=None + "nodes", + self.tr("Centroids"), + types=[QgsProcessing.TypeVectorPoint], ) ) self.addParameter( @@ -26,15 +34,6 @@ def initAlgorithm(self, config=None): type=QgsProcessingParameterField.Numeric, parentLayerParameterName="nodes", allowMultiple=False, - defaultValue=None, - ) - ) - self.addParameter( - QgsProcessingParameterFile( - "project_path", - self.tr("Output folder"), - behavior=QgsProcessingParameterFile.Folder, - defaultValue=standard_path(), ) ) diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index f9bc7582..e0a6543d 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -124,20 +124,19 @@ def test_project_from_layer(folder_path, load_sfalls_from_layer): "link_type": "ltype", "direction": "direction", "modes": "modes", - "folder": folder_path, - "project_name": "from_test", + "project_path": f"{folder_path}/new_project", } context = QgsProcessingContext() feedback = QgsProcessingFeedback() result = action.run(parameters, context, feedback) - assert result[0]["Output"] == join(folder_path, parameters["project_name"]) + assert result[0]["Output"] == parameters["project_path"] QgsProject.instance().clear() project = Project() - project.open(join(folder_path, parameters["project_name"])) + project.open(parameters["project_path"]) assert project.network.count_links() == 76 assert project.network.count_nodes() == 24 @@ -254,7 +253,6 @@ def test_create_pt_graph(coquimbo_project): "block_flows": False, "walking_edges": False, "outer_stops_transfers": False, - "has_zones": False, } context = QgsProcessingContext() From b6274c4222b69d6c51df20cfc90e938512db9b8b Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 15:19:17 -0300 Subject: [PATCH 27/34] update helper messages --- docs/source/processing_provider.rst | 59 +++++++++++++++++++ .../processing_provider/Add_connectors.py | 2 +- .../add_matrix_from_layer.py | 29 +++------ .../assign_pt_from_yaml.py | 32 ++-------- .../assign_traffic_from_yaml.py | 48 ++------------- .../create_matrix_from_layer.py | 18 +++--- .../processing_provider/create_pt_graph.py | 2 +- .../processing_provider/export_matrix.py | 2 +- .../processing_provider/import_gtfs.py | 3 +- .../processing_provider/matrix_calculator.py | 3 +- .../processing_provider/project_from_OSM.py | 2 +- .../processing_provider/project_from_layer.py | 5 +- .../renumber_nodes_from_layer.py | 15 ++--- 13 files changed, 98 insertions(+), 122 deletions(-) diff --git a/docs/source/processing_provider.rst b/docs/source/processing_provider.rst index 142dc3f5..f5b16339 100644 --- a/docs/source/processing_provider.rst +++ b/docs/source/processing_provider.rst @@ -128,3 +128,62 @@ an example of a valid YAML configuration. time_field: free_flow_time max_iter: 10 rgap: 0.001 + + +Public Transport +---------------- + + +.. code-block:: yaml + :caption: Transit assignment configuration + + project: path_to_aequilibrae_project + result_name: your_result_name + traffic_classes: + - car: + matrix_path: path_to_aequilibrae_project/matrices/demand.aem + matrix_core: car + network_mode: c + pce: 1 + blocked_centroid_flows: True + skims: travel_time, distance + - truck: + matrix_path: path_to_aequilibrae_project/matrices/demand.aem + matrix_core: truck + network_mode: c + pce: 2 + fixed_cost: toll + vot: 12 + blocked_centroid_flows: True + assignment: + algorithm: bfw + vdf: BPR2 + alpha: 0.15 + beta: power + capacity_field: capacity + time_field: travel_time + max_iter: 250 + rgap: 0.00001 + select_links: # optional, name with a list of lists as [[link_id, link_direction]] + - from_node_1: [[1, 1], [2, 1]] + - random_nodes: [[3, 1], [5, 1]] + + +.. code-block:: yaml + :caption: Transit graph Configuration + + project_path: path_to_aequilibrae_project + result_name: transit_from_yaml + matrix_path: path_to_aequilibrae_project/matrices/demand.aem + matrix_core: workers + assignment: + time_field: trav_time + frequency: freq + algorithm: os + graph: + period_id: 1 + with_outer_stop_transfers: False + with_walking_edges: False + blocking_centroid_flows: False + connector_method: overlapping_regions + diff --git a/qaequilibrae/modules/processing_provider/Add_connectors.py b/qaequilibrae/modules/processing_provider/Add_connectors.py index 91ef3614..899bf97e 100644 --- a/qaequilibrae/modules/processing_provider/Add_connectors.py +++ b/qaequilibrae/modules/processing_provider/Add_connectors.py @@ -105,7 +105,7 @@ def groupId(self): return "modelbuilding" def shortHelpString(self): - return self.tr("Go through all the centroids and add connectors only if none exists for the chosen mode") + return self.tr("Adds centroid connectors for one or all modes.") def createInstance(self): return AddConnectors() diff --git a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py index 487ef6c9..5402b5ec 100644 --- a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py @@ -116,30 +116,17 @@ def groupId(self): return "data" def shortHelpString(self): - return "\n".join( - [ - self.string_order(1), - self.string_order(2), - self.string_order(3), - self.string_order(4), - self.string_order(5), - ] - ) + help_messages = [ + self.tr("Saves a layer to an existing *.omx file. Notice that:"), + self.tr("- the original matrix stored in the layer needs to be in list format"), + self.tr("- origin and destination fields need to be integers"), + self.tr("- value field can be either integer or real"), + self.tr("- if matrix_core already exists, it will be updated and previous data will be lost"), + ] + return "\n".join(help_messages) def createInstance(self): return AddMatrixFromLayer() - def string_order(self, order): - if order == 1: - return self.tr("Save a layer to an existing *.omx file. Notice that:") - elif order == 2: - return self.tr("- the original matrix stored in the layer needs to be in list format") - elif order == 3: - return self.tr("- origin and destination fields need to be integers") - elif order == 4: - return self.tr("- value field can be either integer or real") - elif order == 5: - return self.tr("- if matrix_core already exists, it will be updated and previous data will be lost") - def tr(self, message): return trlt("AddMatrixFromLayer", message) diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py index 7e7b4d94..c7793198 100644 --- a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -1,6 +1,5 @@ import importlib.util as iutil import sys -import textwrap import yaml from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile @@ -116,35 +115,14 @@ def groupId(self): return "publictransport" def shortHelpString(self): - return textwrap.dedent("\n".join([self.string_order(1), self.string_order(2), self.string_order(3)])) + help_messages = [ + self.tr("Runs transit assignment using a YAML configuration file."), + self.tr("Example of valid configuration is provided in the plugin documentation."), + ] + return "\n".join(help_messages) def createInstance(self): return TransitAssignYAML() - def string_order(self, order): - if order == 1: - return self.tr("Run a pt assignment using a YAML configuration file.") - elif order == 2: - return self.tr("Example of valid configuration file:") - elif order == 3: - return textwrap.dedent( - """ - project_path: path_to_project - result_name: transit_from_yaml - matrix_path: path_to_project/matrices/demand.aem - matrix_core: workers - assignment: - time_field: trav_time - frequency: freq - algorithm: os - graph: - period_id: 1 - with_outer_stop_transfers: False - with_walking_edges: False - blocking_centroid_flows: False - connector_method: overlapping_regions - """ - ) - def tr(self, message): return trlt("ptAssignYAML", message) diff --git a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py index f8a327f2..b220e7e9 100644 --- a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py @@ -1,6 +1,5 @@ import importlib.util as iutil import sys -import textwrap import yaml from qgis.core import QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, QgsProcessingParameterFile @@ -150,51 +149,14 @@ def groupId(self): return "pathsandassignment" def shortHelpString(self): - return textwrap.dedent("\n".join([self.string_order(1), self.string_order(2), self.string_order(3)])) + help_messages = [ + self.tr("Runs traffic assignment using a YAML configuration file."), + self.tr("Example of valid configuration is provided in the plugin documentation."), + ] + return "\n".join(help_messages) def createInstance(self): return TrafficAssignYAML() - def string_order(self, order): - if order == 1: - return self.tr("Run a traffic assignment using a YAML configuration file.") - elif order == 2: - return self.tr("Example of valid configuration file:") - elif order == 3: - return textwrap.dedent( - """\ - project: D:/AequilibraE/Project/ - result_name: your_result_name - traffic_classes: - - car: - matrix_path: D:/AequilibraE/Project/matrices/demand.aem - matrix_core: car - network_mode: c - pce: 1 - blocked_centroid_flows: True - skims: travel_time, distance - - truck: - matrix_path: D:/AequilibraE/Project/matrices/demand.aem - matrix_core: truck - network_mode: c - pce: 2 - fixed_cost: toll - vot: 12 - blocked_centroid_flows: True - assignment: - algorithm: bfw - vdf: BPR2 - alpha: 0.15 - beta: power - capacity_field: capacity - time_field: travel_time - max_iter: 250 - rgap: 0.00001 - select_links: # optional, name with a list of lists as [[link_id, link_direction]] - - from_node_1: [[1, 1], [2, 1]] - - random_nodes: [[3, 1], [5, 1]] - """ - ) - def tr(self, message): return trlt("TrafficAssignYAML", message) diff --git a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py index 018eb3d8..ddf99b34 100644 --- a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py @@ -147,20 +147,16 @@ def groupId(self): return "data" def shortHelpString(self): - return "\n".join([self.string_order(1), self.string_order(2), self.string_order(3), self.string_order(4)]) + help_messages = [ + self.tr("Saves layer as a new *.aem file. Notice that:"), + self.tr("- the original matrix stored in the layer needs to be in list format"), + self.tr("- origin and destination fields need to be integers"), + self.tr("- value field can be either integer or real"), + ] + return "\n".join(help_messages) def createInstance(self): return CreateMatrixFromLayer() - def string_order(self, order): - if order == 1: - return self.tr("Save layer as a new *.aem file. Notice that:") - elif order == 2: - return self.tr("- the original matrix stored in the layer needs to be in list format") - elif order == 3: - return self.tr("- origin and destination fields need to be integers") - elif order == 4: - return self.tr("- value field can be either integer or real") - def tr(self, message): return trlt("CreateMatrixFromLayer", message) diff --git a/qaequilibrae/modules/processing_provider/create_pt_graph.py b/qaequilibrae/modules/processing_provider/create_pt_graph.py index e89643ae..34478ec4 100644 --- a/qaequilibrae/modules/processing_provider/create_pt_graph.py +++ b/qaequilibrae/modules/processing_provider/create_pt_graph.py @@ -101,7 +101,7 @@ def groupId(self): return "publictransport" def shortHelpString(self): - return "Creates a graph to be used with PT Assignment" + return "Creates a transit graph" def createInstance(self): return CreatePTGraph() diff --git a/qaequilibrae/modules/processing_provider/export_matrix.py b/qaequilibrae/modules/processing_provider/export_matrix.py index 61c4d133..a13d7d5c 100644 --- a/qaequilibrae/modules/processing_provider/export_matrix.py +++ b/qaequilibrae/modules/processing_provider/export_matrix.py @@ -78,7 +78,7 @@ def groupId(self): return "data" def shortHelpString(self): - return self.tr("Export an existing *.omx or *.aem matrix file into *.csv, *.aem or *.omx") + return self.tr("Exports an existing *.omx or *.aem matrix file into *.csv, *.aem or *.omx") def createInstance(self): return ExportMatrix() diff --git a/qaequilibrae/modules/processing_provider/import_gtfs.py b/qaequilibrae/modules/processing_provider/import_gtfs.py index c62f3a1e..60dad075 100644 --- a/qaequilibrae/modules/processing_provider/import_gtfs.py +++ b/qaequilibrae/modules/processing_provider/import_gtfs.py @@ -5,7 +5,6 @@ from qgis.core import QgsProcessingParameterString, QgsProcessingParameterBoolean from qaequilibrae.i18n.translate import trlt -from qaequilibrae.modules.common_tools import standard_path class ImportGTFS(QgsProcessingAlgorithm): @@ -96,7 +95,7 @@ def groupId(self): return "publictransport" def shortHelpString(self): - return self.tr("Add PT routes from a GTFS file to an existing AequilibraE project.") + return self.tr("Adds transit routes from a GTFS to an existing AequilibraE project.") def createInstance(self): return ImportGTFS() diff --git a/qaequilibrae/modules/processing_provider/matrix_calculator.py b/qaequilibrae/modules/processing_provider/matrix_calculator.py index 4c3ffbe0..6496e695 100644 --- a/qaequilibrae/modules/processing_provider/matrix_calculator.py +++ b/qaequilibrae/modules/processing_provider/matrix_calculator.py @@ -6,7 +6,6 @@ from qgis.core import ( QgsProcessingAlgorithm, QgsProcessingMultiStepFeedback, - QgsProcessingParameterDefinition, QgsProcessingParameterFile, QgsProcessingParameterFileDestination, QgsProcessingParameterString, @@ -113,7 +112,7 @@ def groupId(self): def shortHelpString(self): help_messages = [ - self.tr("Run a matrix calculation based on a matrix configuration file (*.yaml) and an expression."), + self.tr("Runs a matrix calculation based on a matrix configuration file (*.yaml) and an expression."), self.tr("Results are stored in an AequilibraE Matrix."), self.tr("Please notice that:"), self.tr( diff --git a/qaequilibrae/modules/processing_provider/project_from_OSM.py b/qaequilibrae/modules/processing_provider/project_from_OSM.py index c2c5f194..e6dfaf9a 100644 --- a/qaequilibrae/modules/processing_provider/project_from_OSM.py +++ b/qaequilibrae/modules/processing_provider/project_from_OSM.py @@ -55,7 +55,7 @@ def groupId(self): return "modelbuilding" def shortHelpString(self): - return self.tr("Create an AequilibraE project from OpenStreetMap network") + return self.tr("Creates an AequilibraE project from OpenStreetMap") def createInstance(self): return ProjectFromOSM() diff --git a/qaequilibrae/modules/processing_provider/project_from_layer.py b/qaequilibrae/modules/processing_provider/project_from_layer.py index f781c129..46d4b00a 100644 --- a/qaequilibrae/modules/processing_provider/project_from_layer.py +++ b/qaequilibrae/modules/processing_provider/project_from_layer.py @@ -1,6 +1,5 @@ import importlib.util as iutil import sys -from os.path import join from string import ascii_letters from qgis.core import QgsProcessingAlgorithm @@ -8,7 +7,7 @@ from qgis.core import QgsProcessingParameterField, QgsProcessingParameterFolderDestination from qaequilibrae.i18n.translate import trlt -from qaequilibrae.modules.common_tools import geodataframe_from_layer, standard_path +from qaequilibrae.modules.common_tools import geodataframe_from_layer class ProjectFromLayer(QgsProcessingAlgorithm): @@ -156,7 +155,7 @@ def groupId(self): return "modelbuilding" def shortHelpString(self): - return self.tr("Create an AequilibraE project from a given link layer") + return self.tr("Creates an AequilibraE project from a given link layer") def createInstance(self): return ProjectFromLayer() diff --git a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py index 8c3eaefb..c532355e 100644 --- a/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py +++ b/qaequilibrae/modules/processing_provider/renumber_nodes_from_layer.py @@ -133,18 +133,15 @@ def groupId(self): return "modelbuilding" def shortHelpString(self): - return f"{self.string_order(1)}\n{self.string_order(2)} {self.string_order(3)}" + help_messages = [ + self.tr("Adds or renumbers nodes in an AequilibraE project to match a layer of centroids."), + self.tr("WARNING: you may have to change existing node_id (ex. using QGIS field calculator)"), + self.tr("to ensure that changed node IDs (coming from Zone ID) are not already used."), + ] + return "\n".join(help_messages) def createInstance(self): return RenumberNodesFromLayer() - def string_order(self, order): - if order == 1: - return self.tr("Add or renumber nodes in an AequilibraE project to match a layer of centroids.") - elif order == 2: - return self.tr("WARNING: you may have to change existing node_id (ex. using QGIS field calculator)") - elif order == 3: - return self.tr("to ensure that changed node IDs (coming from Zone ID) are not already used.") - def tr(self, message): return trlt("RenumberNodesFromLayer", message) From 9ab88512f210cc752d5689f056d090d9e5e7a35d Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Mon, 9 Dec 2024 16:05:33 -0300 Subject: [PATCH 28/34] update docs --- .../images/processing_provider_centroids.png | Bin 15130 -> 18459 bytes ...ocessing_provider_create_transit_graph.png | Bin 0 -> 18441 bytes .../processing_provider_export_matrices.png | Bin 13390 -> 15418 bytes .../processing_provider_import_gtfs.png | Bin 0 -> 16718 bytes .../processing_provider_import_matrices.png | Bin 21160 -> 25410 bytes .../processing_provider_matrix_calc.png | Bin 0 -> 22846 bytes ...ocessing_provider_new_links_to_project.png | Bin 0 -> 20112 bytes ...ocessing_provider_nodes_from_centroids.png | Bin 17982 -> 20314 bytes ...processing_provider_project_from_links.png | Bin 16390 -> 21227 bytes .../processing_provider_project_from_osm.png | Bin 0 -> 15633 bytes ..._provider_save_matrix_in_existing_file.png | Bin 0 -> 25082 bytes .../images/processing_provider_toolbox-2.png | Bin 5701 -> 10081 bytes ...processing_provider_traffic_assignment.png | Bin 20266 -> 16565 bytes ...processing_provider_transit_assignment.png | Bin 0 -> 16258 bytes docs/source/processing_provider.rst | 161 +++++++++++------- .../assign_pt_from_yaml.py | 2 +- .../processing_provider/create_pt_graph.py | 2 +- 17 files changed, 106 insertions(+), 59 deletions(-) create mode 100644 docs/source/images/processing_provider_create_transit_graph.png create mode 100644 docs/source/images/processing_provider_import_gtfs.png create mode 100644 docs/source/images/processing_provider_matrix_calc.png create mode 100644 docs/source/images/processing_provider_new_links_to_project.png create mode 100644 docs/source/images/processing_provider_project_from_osm.png create mode 100644 docs/source/images/processing_provider_save_matrix_in_existing_file.png create mode 100644 docs/source/images/processing_provider_transit_assignment.png diff --git a/docs/source/images/processing_provider_centroids.png b/docs/source/images/processing_provider_centroids.png index 8fc82bb1c3f84b436e43b14a1e511f886ee3f81b..9f06c92f270fbadd8ba49e656402d0ae1f277111 100644 GIT binary patch literal 18459 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 literal 15130 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 MCO1m2IsE#607>fF8vp;SKvcRy2xy@oy%-v$ z?-QC31PO)oAZ-E>mePeTKnM^>?uyoZd%yk8e&?Kh?j3KuagSpli`D%9Kj)h5H|M{i zZW-wd>=oM!0D!>tYgg_70BlTTCMD#{^xD`s z!A+(6YjVCW;pyJ0(UCI}&m$gRxV5Y2C*j@W`~SG8_S2)zD9xwib<5o@Qet8Imye}B z7ryv8qTZ`e-Mv4r(yYIzI)80U*_{&t#>88Abtn&79=^A2TpB8F9574V%ANXX*R@{1 z$oatA6}V8IvC=q2{BlwusE4RUEtcG7TqbTUy99t1s?U*k*Jj zvNw0q&9ycVwhu$L7=KI-c5StHZ8a)vHNwW|u~@Rt*FRrSLq-uc#8*P-^(H>*(xy0~ z?tEI6B!V-OyS+;8!$0aT=CE3$8pEepOk#*>;0HJLs-_SQ6U}*O{Q733`Iw>VsP{^T zDm9Q+$fS66B@(y375CS(8O3N&oI2#PgK4L|qHnuZj9&dir*3Y@Fk^jdN{90k02EXy zI(JggoNYg9FjGcnqm{UsPu#0`-s?W74N{zmUzCfti=iPA)&c;qGhnqxA5lABWrZLx z=7!6Ud+CB^)GzgG<{WnoK>%>vi$N_C`V*_fsm!jBrDo2iesCy1aB)T|c(unkWH~-g zbNNrw6K5?Zw2HHayuiiQg&JB>?P5I&9PU!*43!#ZsRO{T!`n+D_a`IpL}d0CSav;>?dWi@|;UQ+4$2_$G)st7z&* zb)5G4HxzO8PaB!V5GqV4gA<`^EJ&2EUlYwhFRgh)igI?Y*Fb@g%eLd8?T#P66?ncG zqdKORk0b_7MkA^x`OvI9v{;A@XP6VXHV4jJoNqUmu3sf_6s5L7tj;T^Ts7pxNAlQO z)#}@+rSYb5m(?diLB~4Qp!cn{7&utl8~wuRg6+?BF)P92x9YBd%WVqAEjRX$C3#c( zsIA#9ocZ5lC1DA%p5{a49A*)AMb(8w{WP4%Q3#6^$`t`FCS7ie@SlFL@Z|yZ2!@qJ z#BZqHZx+tE_!t((c78xu|F4J-3tD#Ci>B{dKd!SPHT<8s~0h7oSp6#_?Y zA6!6L-d0v8tEj14;gj}%oN1PF)mheT)KXPXJH(v+zt{E@YO&YyjFRRW!)*i;6 zErNA+9c!HoAdf6M-xU>!ge@)#s|dlAgbruCBb=?f`=KNOcE56g}_Pv^_j#|lfwq+567~5SssO4|YIvkX- zCUUYYCFFRK`Xlm5q@jMF^KrF_n|3jOs0p@h(m=H%cdSKQ#+k=_Zz}HoaEPx@33n(2 zAwM{9b~o!In?I!mit`+6dRJ|YBI~J*)QQtAJ0cvAUKtoC z99~V^|7c5#hjBy_UI@7L?wjgDWUSp5hrnVr7W+wV3@b7Ei-Q=1;-I+*Y4*oL4!t`U zy?jDOaBOW*-)?10dNbUQQx01YUq>e#aXaxl_*@d%ErR{U?b$Ce;IZF9BdPFDd!kcX zo%T=BPBtZPxlJhSb?(RAisH}nD?c3TKv}5%weBXiXC(qVe>OVaq1!IWHYO}-c7&i{ zmLk630$13QGWPhmQF5$4Mm(Z*{m9O7K``@OaMNuRatcnKib$Ntm5R1FN8t`AEnbJ{ zo08;jY+FC2+I6%!dKWTyiqsgiPS6^b;su(co`{DacFi>0v{G6aWoB${_;FS;2&)<4 zR0QJSTE26AAQN3XN8)UokFBIq*T;rmv1Y_cf4uEx+XvHXt7Ys7FFfX!#(nDnn&WV;Ir{L!5QPH8?`T;E&0_b z;*zuDb6by-1s;eY7x?>twW@P{0qtvLa@6d#iM7!P;S^-h+col#6rV#RJ}1C<7ee`F z6*cuuHK9aJ0u%3GD4|+gi8%W^3@1ar54<^>R+OgWg>#{NNmFG{Tt%;Mj}PX{qt~3- z%T3N*=>qZ4e;W=lkztI*cOx2_FLK6*7yhn^y&UBlqmQBU2w%Roe z(O`9HSTfxG)cs+l&=PII9M^+Yk`D}3DvR$B;&d_MN=%6(EiF+p5!94RgooBn4*Q*- zPCoM5JEelSJtP+k!-*iUJrV*UZc^pdkq}7_;pJ~a2D}+L+D(f{9G5J8`Y2on!3uT> z!_Ko@i+VM$cBdX)i>VE-b?e-#*zv#%H-8?u_58!zG(|5QoDxY~Za~;>qqlPXwlA(T zJ{hF1<(qGlb<~z+iD)n%L0p{llM3jN9b;5vu)wLUL|vW0VVRKoODIZ}@0*W7uKOac z-F$Z}%s^As%v?>Yvt^&>or1mxNJGWGBl)uXG%gLK_MY7ho+_EZ6TObM!1g6i?aggT zItD)+hLrfpA>Y4Z7;P~AjQ(=6cb@F7vTs6H87BrW4ro8OTM?oJ4s(H*9Z>O*KQz!{ z@^rE%nW*59GfWh1;cs>vcdSK{ncYX6CQg6&qNt)Ou?vZNctcU${|AMVTO6JPTC39{ zRCcL3al)o+C}^rL*-nSGuwukvxt;Mmw`f$E=a~NKU#OWyojyW-S9=-YJOq(=ns}zTxtJK-(blzIc zo(f(|$GS4Ku}J1~(oSG=(vu>3d2(!}S*Mo9CKI=Ynq1v7dhn=g;0_?zz{MH>?w%GC z0UrBckvza%)&G~ncrj)^0F=lp$pZjQ4|==={+~I#AjbUK8s7r>%Zh zf|9ro+6nCQui;}PfhXb_V5Z^Ddrm=B3YZSThXJR6cuYryG#Qahq zwxBw@&NL|fIL>b%dhH6GL{QN2wuU$#aLkKdEso*W`NPTYCZ19)LXEdQn?%}ae>JS# z5G#eL?FynN+ijMPDA=qtD^(&o`tZ`6^_IjzyrFl<*G7yafA<4~I5UA7IH`!HC9K|4 zhvu`$QCXlMc-3^mC=IMHbTU1xb=zPAV)b6MlIIej=CE;&m+Ib-|5)zkvFKK z*TMr>EMqa~lkcUPu?x};6;laa__%_LV60PP2}^4s20MDm^xdd-VP}*V0oyUdSbqgZ zE0tT_y$sefWmtKGIysA&!PN_`RKElp4kkx9dx-d=ad$Z}++St>oY!W9Z z*gHZOy8N*(-#iW5VF8-HqEpPu#QoNt59`T7!UeN`LXs>#n$fRnsa$bNlD4SU72(Ot zR8lif36be|aeKk%RI(g4>esn+7-RVaNOm!6C$y|nN>9gir_IV8Rl83d8YS7B@KT1K znR*jTrr+E=O{qcYLnF5hxKfa2hH~jomc(upy>K(l6%cogWXD>04k;fB)%CKXv<_^m zdWUEZ*l74~RE>>!Exg#+J^Fs^=@Z2@eoU>Ql`1@8e=T+)?Gm`-c{UkuNM8j#rm5=D zPR_mlZQgo*&|uZ0&{*XQUY}l}64M?@gTZfS=N5W1t&-1`FeOki3R+Vqyv`N`R zJ6nz9wA7crBzXp7VEW^3*1!cHaonpb+nafILd|4+-Koo`&k7W$2BRdm`b8V%9o%-CR zQt|U=XWz-X9IJckI`vy_%>AMh^W899az>>?SGS-pv${D=iM)?VeQEV9x^_x%^iIpm z?WYwjKgV?|Z(Y+BW<`=lbCybuYY;1H8xJeX11sWg6iZxo@(!`R#aV-PgxI|yGs*6o zu$$?_?Z%@e#ki)W;Lf^uITnJny)SFxWu#k5T^iUYk4w{E&!*=MXfYPOzL1z)o{l?6 z`+s?&Fjw^ODu%ydD@R2hR{W{WtX>|g!bFx%S~-EX!HoXX0P~4)(1h@DFCKf=U2fU7kQNAAN1gXTfpBgCj?XQxk6HE50|_H zc>q~M@Nz<$CxurW(^1W?P9?%{Ht#y3AY1*&#rn^(CJgz?*US#gw_Vwg0oLikKX=55 z;hs@CbbZXEC=$Vi;BgM{qCu`(5pwc#kKeth=uILXlN zkE;5so_ER=V=F~vXqz6_?Eqt?=_86*7f;0DIF+^$8mpG4;f%!%Fv7?^a=tLpL-tXk zEh?Yr@CIp6Za@W3^_5+Sfni|aN0;cN8e}m)IW{L5yM4)dACT`Xih;d!Wl+XvYe#GR zn%dS6FNV8*^Z&WyX3^`?kmWmsV6j5QqME#5#Zi++ns>#)m7s}7jHgdf&n(Hx(ayHC zKMeG|T(2(97L*a(DFa=?VKel1mglsUF4+FDdg_!)oE=!@l=lruNgcAKO7S+#T3iOr zBnREgH5T;BakjntXjv&PJ(FM7Zy|zd2Th2-z|&qTiJRs637Jitp2s@mpsUxkX9UH^ z!+Lrl+iXQ%x5Ua#yq{;#XBp35RYqdOy%fdz-OBBQ-fHzhc+eI(w8RQdVpV0w&fipj14b1k*kvAis$5%DS^A0t<3 zL$I~YkSsHuLADUK9TNjA4=?i4wGbFhf_pQxg59WqW@Cj>&_9_|JPZmvIu1uQ?oCR}-DZRkwIlZTNtJ-_}bE zq)~FmABG}4&8H_H29D(CAdk0os=!}gALMzgto%A13M~0EqM~=hvIuStdSK%gWG&7< zIH%S0Rp)F@c_AtMEM#$xTzH-CaKU?)iby1d?}Vti`=@3Ue$ks<=R`FabH1+DccF0parnL* z=hs0KQ8H4Cn+=nsNxld^;eVVBN(T)Umj7{K(&#OE%Ri2NLO(X_H-S*ajYf-cN{KGP zJ{ik7t$71}{RMLj{`Cw+1OBC3cbqIe?B(tjO^Ps&9J+>%gQQKLRM)!QT+_V}%Pd z8gQXzgma%?MSs`Xk5z>lRbm)tJt{ch+%Jq31%`-_7a9&H74oW_n!7SHaPOciwW0_zvdh_a=5cz@xAq8mUz1`r`uom*gT|;Op*; z%$dH5zf(Hkk@vH|q%9-2e{?qgN;qDX9R)AJYph8N?}w`s=maCe8wX*&r`_mXub$=^exiiKy4rXw5w2L zJ;v_KCZxnp(5S!LxKV0c?@#Ase%$$36q@c{qL}K-`S2+fotIYI4No(E1Ad%_y!qw} zN{{iEstBOr7_`3EI3x#*vw3c7s9KKXdAtvrI1^Id!;pe~ti#kUb)5l#?*lrEGyi;X zVnzeF7`r5ztZnH2<0YgQWE=1RE9#KhS_cd>a+JApRD}#(GIm{$clnFAzB^Q*0L8II zTm-nA`tQFRh^T+-)j^hW>`|MX{?z`2Y+>N>@gEC_2r-jQ3QA4VBS>2vMw~)F6$eH6MQYGP8QG zX1Gnz6aJY!nA=`znxKwQXfv9t*2?#i0a&l0(NTSPbK3w%mkx8ntSQ|Qht&P8S**}A z0{wQXy}+XF^7ueY!d;IJGXqL_>8jQgrG)4qlP>u9=8q*ra|#-9#O-;t-|Z$sTKs}q zbcM7IIqwp~MdhiD`DQ3LX4WJmTKr#+;|SwMnvy^gS358y0XbH0V*RQiBG9Dn!IS~T z-VBr)Dd??8+7r4y58pTNXRD*vqUTabvYfs%Z;91kbjuS~d!Ofv*m&ROKvWMf@rL%wMAen!)gy|RltuR)zFU4l za74z;*);d_bt^vW*L#HN%$l{yk#eo!3|CSbIlZc0N4Vt@$I&Melex{uw~h2#Xh@z} zoK>peXTnH_Dm9oG^2l$)}s&GG7+NC%-~=YoCvy2{+oQ z3N?2dHVvrgh7Wr54i^&9C`$FbnjqQFY14f|?e+GBqnbFK>9`bBN|oNsj=2L|Wq6Ma z^{8{+t3s=V#cnBc%PDgbOD1$mMaFPW#T(JzL*M>w#X$`W2JEM} zHVTCixAyM2I+f~W#1)e_$oqokr^-EoTn_mZHiPJ?0wY}1e)q+5p838mv61~|Js%?~ z{m-(ktY_|0h}Abf*P1CJ?G?R!2#xlvZ4zw+Gcl^pM2E+VZ9Q0G&?#SzPQd! zo3Iz?0xK1U6IbpO|1O)t=pU6-^B?sut3}hc1`G#Dk$QZa(as%N<(p)n#Em--gH*UI z8$;VGuIy+UZg@3TzyGw)e)Hm#B>Eq}bl|ef8((z1u?%uiv{fqd5K1QRhGa(3G2Z{& zGlL0u$0CwQZ|h`_D`1oGIZ^|?hh=AOq3K`Rzgmnld)hPoL7;$}W|~zZ`1If zIE zkI4PD16Hv&wdX4OSkB>AM!bL-6m6c(XKTTG5tU97;8~+i?enu;pS@Bd?_qNsDqYLJ z4>r@zKGne_&|eNLM(W{okne0$oGzoGP(p3GZr`Lj0d4lyo5w5}8fvEs+~&TasFBh= zTKAv+*LzdmrE22?j@caF7wR@-U7?!=ao1i6(GihW|kH^AAr$5f7?O4kwYOdpE%d03!Yhf;N>gPRU-Pz?>CV zb^XB{T01w|=Z1<(@Yp^+Aqh2q4Z@pm-IIEriY(67j&mYhc_~Bc-XPt}Yd1Gs8Jtov zTjL{F?S)-w8_7Mm*UuHjbM6{sc1=Agr;-xVjma*xlP{ZVA0GDoJ)zQgf7S9%`3Av0 zC{|b?X`$nOKo5-e53@v}VynDodGA6*Inm4hpVn`cH%}Awi_L^2r0j|`j#|mZ^jMdnoJRe}r%$E0ui|D2&)i8}Y8Pm!^!&+Z5Jq8=CM;GsL)SHRjuG-+%)3xA zwLV{H>szF%9sFn|Duu_M8`rc$5cBr5KC=Lse@5(;$-aW20&vJp@84IhzS{iB0=53( zJam4)Yscqn%EQ(rQa9(iYwvj()9pE{dgaEIP8ILu#_U-xudg%JtDVbDHF6=H%4Hh= zWDn;`hZ~qv%+j-4$H?ZX#tt9)J9T>mshj`bsat4gW@mN^67?K@L9C|#Mt`30o)PMq z*jm`fWAkZaM=3Jzs>JrJ%wt_OR}yAd^fqz78RsMd54e$7Ke5GdL@^ENk)x*0`uI-A zq{~z4S!PN^e@@3I_8Ub(jYy4v!5CJk9@?qEG%^$xM!$GVMImD1(X2LB1X=G@A&Lkv zxQ&Kf=)t%90IpxFwJht&*z*&6e$F-eG~v zDL3Vq)rt=^j%HQ&jAu&rTB9N#o{M4SswM}I=v#ub{sdj-^cT5oWkqQ>QU_3S7!s-* z9+XW-hK)Uq*5LGE{T6LXqL)@tv$u4C$T$@L@X=6>i$*qku)No`5Zk(bd8Q~iYL@yF z&Ev3bCA=VTlv;8y(L6a+7Z&5DOxQQlWjV8`wREdcxK|6ecm{()`3_`-GRD_3lT>-X z$BU2)fb0G#GpcmpB~ZYf9*St8WI<}v$H2it!vWSi_+r8c+);4;$0eS}+5a4W`^OaR zAK#i;& zK!>{VAY9^8m8l2ibrs6j8MU4Ol$db+G=`+*J2%AaICLZ{n|JmetfV^N&8EQ$!DS9l zn#}Cu%ioDDi!N?lR!YlSF^Q787MW~APN{+^i^xVS^Pg1A*dS0@geivRysI&PWaHC{irlDD zr&}GQpWPW`wZ7TbsOIbL@SNcloIZ?sv ztGsujO&R@SRVRv+7Y*pZEt(N* z8BEj6Hk(&P+BLcN&NU?a?*Ys(kd)Vc#(#*^*&2t6$?TqhsWcH@W<@c*K+&Ts`vJ zU>XH`o;%HEIX%l|;stPb57*M#g1ZnXGMU|~vmrB;foAjDtv8qBtyTFenuUgA;-fP$w{|OL3}u6s+&=hTms_mrr`~t{c+zm>9jt*Px{Ra_Ip+ytGeKc z8})@c&a~FQgbHb`b~gbHH^;#XK`tQ+UKzF9YvewCS1xWNiJ&Y+_AJHG%z?+%;c=Zy zJjvQOz9+Z-;F!-K6cGYtVSj&G57gdTYMPO@0PF?Fu_k}z`Vts^{$428e*`7pP%XLP zQxCob%C7-geX#K<7Yz8fZg@jLa0{&8rX?E7p#H4_7&OQTizKj}oX~lQo8;P$LV0-i z4JCL@VmcW?+-^@&L>54WFCAzW7aws|55{LGnXRp-)z)uxAR-b`6ugYB-kR^4iv#hGL(+gIYF0+I;A>cPxNsb`A3 z7;;vBuW%97^J=0sej^+GMAnnX_Ydy09Ib^;cEM$rVJLmgMg;byOnCbI$b=48i&&d> z)fH_nex;@7H_GSPkvL`A--G1yn~Tf&{k)Ojx7iNa^G91~di;@{`z-mvYA~v&&{w6{ z*=ThNmQq=Kf$@@#HKn!W`pHXD8~Ekl38^A3*G;cydAHI(KC#46|$I~M-+$4bIR*mkipE5-ihz{#idE9EtJ}5^x{rQ!^*f_-?;|%ZeMaYJeor@#|Gwld)KG&ypH?9u-Y|Z9IEH4NSart zdYS?1d zU@15>qAT(es(jMr9Qd;Hfkwcm?8sdNnZl2)!%+FdTK)VkdqD{Is(6Hf8RC$*<5z|? zUYYr)4nYZ!%adcufC4H z;xy%P$8wIpbrKi|l<;xw!cH;VOi#Z2(A`hW;%z~=(@5m(*sE%w05V7Xmf28dii3C3 zafOUhjhl9Um;5cz2gsk@ta~5K`kzWu9nj7Xez$TEFbjpqD7*!lVJtEF+2Xm4H+}4t zUgaqjTvzP>;HH!=`s<)m4(gqc9B@~Z%ex(zl=?u);0?>G?pCx~vcFOcOfeL~MBJQe zA|dm~g*=~{O`|9e^fFbz&h{#C91)rXN>z3i+JaT+*<)hUgC8!{WWG(HP|I!;MyaJ{}{jfu&_s6|~yNL0X1*l(VW(A?~myv#gg8GM{TI{pK z+I&Q<$N=qiF7p?mB2ARaC_nJ>Y>;4xyEfD{ZL)bN^)j@uwR&We#f&ZR<^kR7p_GH; zU#B7NoYh~y!iu~uG|(Fj#e*xA1c~Y80xL9)EQDEOCZYJBw?XzAM!%t#5K&p9k*UCMXlkyb|>W{9dfy%91H!8 zQ4eeH$8!;%AIsg8xIF1*J>&|Be8P#Kx50(J5IdM_VXgj34;FgGnIv(&(SSuC~XM@gZhB8eG?(N+G4`K@C!n2UfUVoYMz|35TjNH0Q%_?x&Ns z|J2v!mdlu5RsJV2vNAYiZV#TDb^~TcaB$ON=QOvD@aV_zEpVj;2s(brez6mn+^?-s zF6JkOX{)aUF{r6DKd49J&x6_;O?)n!zkV-TK&M&rI5ZUXpq4)HHR%)y@dAqBacxVP z0Z@1}>Pz4s~F@RA=JHk+mf4;{}=K5e+`@XPu6uHmi=3` zga6a#hN_N?LAzo|&J-Z{^1pfdub^cA&9(mu*SMG(dnpoX&6+z2!6uMh{0}rQ{X6K$ z|Bo&wU|w!M|n-+cYt# zQJ=y8EjrNl2h?0Jq&_3;2j_ONCt+AS0ecy4A7*%5z!0uiXICGTd;`F(y->8+Py?Z` zKmn9Q{eN?q5<}7oSpHgizeSJ-C=t0Fl?Ju{zq07kg0?|IkQSv5+7S@Za#KjNuMUHn zuN)ln?lXj%QS2AP+M(wj%$6tI3i*Irdjer*e(CLLIAk$?;u&WT&|u4-l(JdyZH^{OCG>ya@cUkU^*#Up`IQ+(|oz{zMHi@RU>Fz&wG5_RgqcGpwMqWzIW4|(v7BC zKeM8)B$H5Z!+8E@m=xQyzi8%=cCNkeE-$rhk%T4hMQbq&nN_ENy^4iMUC#D=;{s>B zxj3NXFfPX&jiMa}>6aVpMbKO9)qBUs&nwH9=u|E%Us-t2n?v%PO&85j)Xv7yeZyKl;~UtY+0Uv(&FyAX zbn?4xd2S`RV#GHWY5bd8En~~cvPRh=x<)p)C5sa<1K~-ypt+S%MX<(F?ckA*RIvTt zcY@Jk9+ZUDlW;YqBHPDzz7uO_)lH==CEzGasxwy&UK`tes-IMLxP-Eh@H6r#F18LS zE4SwvKR@M4Q6+A4h>6@)EG&{-PYUb#?9zX0CvQQKqz9!qt**{(X!Ym!Pkoez6-L-M zy8}d5ovYkCNrc(Fd?oo3c(O-f$i+tG&P&p-*XP$@ta9MUgLtcTTBz;2Z>)*{cV!}*GQ|JV8G&8!Ll>9>&_>~a!f?J+nTMe<&}tt43@sWMz(9xg zqyKnls0S`Ya^_2hIq?$g!9L&4IX@|&YBi}VXc7w*{2U>QzGSdxGIID9UbuOpm-vd) z^N~%pM}pj?Atd06fA8v$9BWE)NVab*02sQnn*u44dhpwVN^bkexI^E4++4=3B*mk) z=ziLi8|799=RS3}P>NKoqaA@4<+zl__gGF+J4h`!VUG9v?bj+}1JGvU&@LTL2_h`g zFmAN0czIO~C%n+P=6~I2h4+NJYIdJK2 z{0GesOMG4s#2N(7>Sz{JyCNv;0KT!N?VE2b9A zEEBUi?|klo5`3tFz0#yKUahLq7@wOcN0+>=;M;pa{*aW{5=NZJ%Lt8~TM9L_b_Wj+ zX3rG43TcA^Nkaj%q*~Vzm=IvKcUWX|QQUy(OzdNKbJBDS`cS`WPF9dc&-5?bFrTeX zU-~^<)TT6ga$iIYNg!na9rAjji@I9iOqe*_6*!Q>)-;SUjog)!h*;p4)CyePmK%4} zxW%Ene4l+jKa5V2Ey93l-PHpXxhcLbohC)W&7=y)T9>~~Pc!gqS=6Li5WVyj$NV>x zk#&BJ_l=-d-aB$8zlQIxGW=@IdS-47!^-;hq<(nbgLmlL>=J5f%(7M#- zbvDC>XTP--UvFt_gf<-9$uM7BhA9}EVEY}A7Xmt`@1*hfdzFtuyWe$~UOG(S%5%FF z`krjY>4zdH>yqyfkGx;49utm7T64xw30XdEGZplktOFzDD*0DtIoW9@R)|4Z4pkR5 zh4;}iQCP6fQAb1*52Qtn(dBNUrg-cPjJsTJh)wF;x#s&W1zxbewwT z(_U%6JgFP#Ay>(pieS&R)c5SL&z2@>{TsR_wDtI`&K310v6ctX6!*0?&^wDO!3&rudk6ppvkPM1I5<5P-@Wz zYJW0Jc8{xalPs3XTq%=kSNWU7ee4}IYo>W3gBWcp6L>A|USSL-(Z;4rsm)i9D~mA2 z{tG_ZYuNQDY8;mog@Y6R*Z(FhM=!8>4cAW?Y0YvD$Ve4%Tvk3L#>Ix~p8leex3cM6 z>HKtU^HZD7kj}~2sih6e!1EA`euxh0Xq~r2SAFTisqw-+f#@Z1N)~G2Yo=51IsZVV z`|)i2iZr)G+5Sg9 z+Dxq4u=a0^i^V*70U`U19A5a;q^gg2W9wa4b+87h| z4H5?V`t^wbsIX*-)*mwuzLZg)A=GQW3L<9no3IM=P3w*dsNwaC?)8>^$)b{lu`#N} zRi4Cs5egNaq5|;$W5(=~gEfrFl6~v7z5~}Q)`Q|fH^ystT?d;${ zl!UkKE@4HG8BhUE7hhjQT$wtct@L;N)MBrLadM;Y&)hX`rn6L`Itf);20SL%^mMIk zjY~o50KU(}6P72$9?*wA+<_YIpE*Gg*)tk5bG7jfWaPMwntEV_j>f*OGu>MF8z+`NBQkAmQdh>d@>q!EF;MEe}pFeO~0mWKHO^^0AJnd1LSu{sYJ%LnGe_H4E>nJM*-z#+v z*EpYNb)Fq<9h6pE+KivM%5b}n4YUzD!v~coEW2%00zUOB3z5&u_E+U^-?j_Br~1Ad z6E+qZqIxjFwbR~z5k-X|z=(%MXu$^^-_7z`7p%lQhp+;aWIqpv%Cz_T>_HK2{M z+;(`wrZ?={&npj0ozrykAKJ{6nTz+cFAh`n{XRntdy}Ti(b|MIeHK(MJsv;b^p~?* zQCWx*mVwuAOqTcz`C-EO_Qi=xsc8AOX>&bO4A<=*(!LTarM0=#Bow*7fVg0-JKh6% z`#OHEzr32~1NH2FfSL%K$bl|g_f9XGkAx;}58)a;E>c@eWN)@XBsY9$z+_okaW~*z zJOG8R04>LjB9aP0UBF%G6*fnm7kGTCXur(uCvxN;^$b++1w%kDF~0pR5f)G;m18fuA^)~Tm!8HbE;*0QA4 zn8RJ1Z+079^&LBbH&=u-ml~k2bgX|63RyCS3h>6MYPXdaxMPho(ezd6ke+DHD2y7= z+JexWMZ59-O;*L}vk?9?`B zTPvL~jz0908#0?KU$@jaNLcV$bo^#xQP!<>wbm_?FfM>t2h&yS>5xtK9hTnik+!LM zUDA3v1e8f%6DGbO>5gqL_(j$Va1IbQXY+NIU&L*-W^7%*M&_2g*Xdv}dYi^UJG}i( VXBQt-n}YsbziM=)=(7FO{{fRi7dZd` literal 0 HcmV?d00001 diff --git a/docs/source/images/processing_provider_export_matrices.png b/docs/source/images/processing_provider_export_matrices.png index 88bf9c344ac62fc7f946138777f19425c01d115c..71bf98bf33e9e2110c9dfea1605d264d492dd14e 100644 GIT binary patch literal 15418 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 literal 13390 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 I&)eVoUw3awg#Z8m diff --git a/docs/source/images/processing_provider_import_gtfs.png b/docs/source/images/processing_provider_import_gtfs.png new file mode 100644 index 0000000000000000000000000000000000000000..c699629f8c6435d7b7f476916c1b9e8e9ec30858 GIT binary patch literal 16718 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 In%1}f8=n>J7ytkO literal 21160 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 diff --git a/docs/source/images/processing_provider_matrix_calc.png b/docs/source/images/processing_provider_matrix_calc.png new file mode 100644 index 0000000000000000000000000000000000000000..40658310b309e87af02d3aa3efa0c38908bc1efa GIT binary patch literal 22846 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 E0E*wrDgXcg literal 0 HcmV?d00001 diff --git a/docs/source/images/processing_provider_nodes_from_centroids.png b/docs/source/images/processing_provider_nodes_from_centroids.png index 0e43e504803fa855415661b0124d38a6664abe10..01847d2292576c4d9937e68f2157ec5f7c926b43 100644 GIT binary patch literal 20314 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 diff --git a/docs/source/images/processing_provider_project_from_links.png b/docs/source/images/processing_provider_project_from_links.png index b8b2474b1bfe114b93a378e0a728572d79c15e4e..54c62ee503147db923af5d8daccee4bcc5aa3ccd 100644 GIT binary patch literal 21227 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 z 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 Ab^rhX literal 16390 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 diff --git a/docs/source/images/processing_provider_project_from_osm.png b/docs/source/images/processing_provider_project_from_osm.png new file mode 100644 index 0000000000000000000000000000000000000000..520073b35fe5ec67305f28fb7ea359c36b89ec69 GIT binary patch literal 15633 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 SSR#NQ(3#VAr^-%v-}xWSz|b)O literal 0 HcmV?d00001 diff --git a/docs/source/images/processing_provider_save_matrix_in_existing_file.png b/docs/source/images/processing_provider_save_matrix_in_existing_file.png new file mode 100644 index 0000000000000000000000000000000000000000..3fb0d1f813bc86ae69b510e07dd65add392bde82 GIT binary patch literal 25082 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

^Cf;=Pv+}n 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 literal 20266 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%0Dxu>1jEGV2tLM{F+)*{i6z)C;*CG>zgyI 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 diff --git a/docs/source/images/processing_provider_transit_assignment.png b/docs/source/images/processing_provider_transit_assignment.png new file mode 100644 index 0000000000000000000000000000000000000000..ec9ee7a6832fdb8e9426c0d901a4e6fe11491d06 GIT binary patch literal 16258 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 ZcaQKP_}0;G;6Om9PCA?@w(`3DzW@S` for more details). -Its usage is straightforward: select the matrix you want to export, specify the path -on your machine to store the file, and select its output format. Only \*.aem and \*.omx files can -be used as input, and the output format can be either one of \*.aem, \*.omx, or \*.csv. - -.. image:: images/processing_provider_export_matrices.png - :align: center - :alt: Processing provider export matrices - -Import matrices -~~~~~~~~~~~~~~~ -With *Import matrices*, the user can save an open data layer directly as a \*.aem file. -This tool is analogous to the widget menu :ref:`importing_matrices`, but it does not -require an open AequilibraE project to work. To use the tool, the user must have an open layer -loaded in QGIS, and the menus are the ones presented in the figure below. - -.. image:: images/processing_provider_import_matrices.png - :align: center - :alt: Processing provider import matrices - -The upper fields are mandatory and are responsible for selecting the layer, indicating -which columns correspond to the origin, destination, and flow, creating a file name, and -specifying the destination folder. In the *Advanced Parameters*, the user will find fields to add -extra information to the AequilibraE matrix they are about to create. Model Building -------------- @@ -71,6 +42,23 @@ The default connection mode is **c** (car). :align: center :alt: Processing provider add centroid connectors +Add links from layer to project +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. image:: images/processing_provider_new_links_to_project.png + :align: center + :alt: Processing provider add new links from layer to project + +Add/Renumber nodes from layer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +One can also add or renumber nodes in an AequilibraE project to match a layer of centroids. +Just select or import the centroids layer, specify the node ID you want to match, and the output +folder. + +.. image:: images/processing_provider_nodes_from_centroids.png + :align: center + :alt: Processing provider update nodes from centroids + Create project from link layer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Create project from link layer* is similar to the widget menu @@ -83,15 +71,56 @@ name and specify the location where you want to save it on your machine. :align: center :alt: Processing provider create project from link layer -Add/Renumber nodes from layer -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -One can also add or renumber nodes in an AequilibraE project to match a layer of centroids. -Just select or import the centroids layer, specify the node ID you want to match, and the output -folder. +Create project from OSM +~~~~~~~~~~~~~~~~~~~~~~~ -.. image:: images/processing_provider_nodes_from_centroids.png +.. image:: images/processing_provider_project_from_osm.png :align: center - :alt: Processing provider update nodes from centroids + :alt: Processing provider create project from osm + +Data +---- +Create AequilibraE Matrix from layer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +With *Import matrices*, the user can save an open data layer directly as a \*.aem file. +This tool is analogous to the widget menu :ref:`importing_matrices`, but it does not +require an open AequilibraE project to work. To use the tool, the user must have an open layer +loaded in QGIS, and the menus are the ones presented in the figure below. + +.. image:: images/processing_provider_import_matrices.png + :align: center + :alt: Processing provider import matrices + +The upper fields are mandatory and are responsible for selecting the layer, indicating +which columns correspond to the origin, destination, and flow, creating a file name, and +specifying the destination folder. In the *Advanced Parameters*, the user will find fields to add +extra information to the AequilibraE matrix they are about to create. + +Export matrices +~~~~~~~~~~~~~~~ +The *Export matrices* tool is analogous to the *Export* button in the matrix viewer +(see: :ref:`this figure ` for more details). +Its usage is straightforward: select the matrix you want to export, specify the path +on your machine to store the file, and select its output format. Only \*.aem and \*.omx files can +be used as input, and the output format can be either one of \*.aem, \*.omx, or \*.csv. + +.. image:: images/processing_provider_export_matrices.png + :align: center + :alt: Processing provider export matrices + +Matrix calculator +~~~~~~~~~~~~~~~~~ + +.. image:: images/processing_provider_matrix_calc.png + :align: center + :alt: Processing provider matrix calculator + +Save matrix from layer in existing file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. image:: images/processing_provider_save_matrix_in_existing_file.png + :align: center + :alt: Processing provider save matrix in existing file Paths and assignment -------------------- @@ -132,8 +161,46 @@ an example of a valid YAML configuration. Public Transport ---------------- +Create transit graph +~~~~~~~~~~~~~~~~~~~~ + +.. image:: images/processing_provider_create_transit_graph.png + :align: center + :alt: Processing provider create transit graph + +.. code-block:: yaml + :caption: Transit graph Configuration + + project_path: path_to_aequilibrae_project + result_name: transit_from_yaml + matrix_path: path_to_aequilibrae_project/matrices/demand.aem + matrix_core: workers + assignment: + time_field: trav_time + frequency: freq + algorithm: os + graph: + period_id: 1 + with_outer_stop_transfers: False + with_walking_edges: False + blocking_centroid_flows: False + connector_method: overlapping_regions + +Create GTFS +~~~~~~~~~~~ + +.. image:: images/processing_provider_import_gtfs.png + :align: center + :alt: Processing provider import GTFS +Transit assignment from file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. image:: images/processing_provider_transit_assignment.png + :align: center + :alt: Processing provider transit assignment from file + .. code-block:: yaml :caption: Transit assignment configuration @@ -166,24 +233,4 @@ Public Transport rgap: 0.00001 select_links: # optional, name with a list of lists as [[link_id, link_direction]] - from_node_1: [[1, 1], [2, 1]] - - random_nodes: [[3, 1], [5, 1]] - - -.. code-block:: yaml - :caption: Transit graph Configuration - - project_path: path_to_aequilibrae_project - result_name: transit_from_yaml - matrix_path: path_to_aequilibrae_project/matrices/demand.aem - matrix_core: workers - assignment: - time_field: trav_time - frequency: freq - algorithm: os - graph: - period_id: 1 - with_outer_stop_transfers: False - with_walking_edges: False - blocking_centroid_flows: False - connector_method: overlapping_regions - + - random_nodes: [[3, 1], [5, 1]] \ No newline at end of file diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py index c7793198..292e4fd4 100644 --- a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -106,7 +106,7 @@ def name(self): return "ptassignfromyaml" def displayName(self): - return self.tr("PT assignment from file") + return self.tr("Transit assignment from file") def group(self): return self.tr("4. Public Transport") diff --git a/qaequilibrae/modules/processing_provider/create_pt_graph.py b/qaequilibrae/modules/processing_provider/create_pt_graph.py index 34478ec4..8c674a81 100644 --- a/qaequilibrae/modules/processing_provider/create_pt_graph.py +++ b/qaequilibrae/modules/processing_provider/create_pt_graph.py @@ -92,7 +92,7 @@ def name(self): return "createptgraph" def displayName(self): - return self.tr("Create PT graph") + return self.tr("Create transit graph") def group(self): return self.tr("4. Public Transport") From af9d8507bbf777faa5f69cc0fa46eba517cfa0e4 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Tue, 10 Dec 2024 10:03:11 -0300 Subject: [PATCH 29/34] docs --- docs/source/processing_provider.rst | 96 +++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 24 deletions(-) diff --git a/docs/source/processing_provider.rst b/docs/source/processing_provider.rst index cdb4467c..0e7e06be 100644 --- a/docs/source/processing_provider.rst +++ b/docs/source/processing_provider.rst @@ -1,11 +1,11 @@ Processing Tools ================ -Some of AequilibraE's plugin functionalities are now available in a Processing plugin. -The processing plugin is automatically installed with AequilibraE and allows the user to -create projects from links, export matrices, and much more. The processing plugin usage -does not require open AequilibraE projects, although it is mandatory to have AequilibraE -installed. +Some of AequilibraE's plugin functionalities are now available in a processing plugin. +The processing plugin is automatically installed with AequilibraE and allows you to perform +several tasks, such as creating project from links, exporting matrices, and much more, +as a batch process or not. To use the processing plugin, you don't have to directly open +the AequilibraE project, although it is mandatory to have AequilibraE installed. To find AequilibraE's processing plugin, click on the **Processing** panel and select **Toolbox**. You can also use the available QGIS shortcut to open the Toolbox window. @@ -15,7 +15,7 @@ You can also use the available QGIS shortcut to open the Toolbox window. :alt: Processing provider menu At the bottom of the window, you'll find the AequilibraE logo and the available functions. -The functions are divided into three groups, following the same logic as the AequilibraE Widget +The functions are divided into groups, following the same logic as the AequilibraE widget menu. Notice that not all AequilibraE functionalities are available for processing. .. subfigure:: AB @@ -29,14 +29,14 @@ menu. Notice that not all AequilibraE functionalities are available for processi In the following subsections, we'll go over all functionalities. - Model Building -------------- Add centroid connectors ~~~~~~~~~~~~~~~~~~~~~~~ -AequilibraE's processing tool can also add centroid connectors to a project's network. The user -needs to specify the number of centroids, the modes to be connected, and the project folder. -The default connection mode is **c** (car). +AequilibraE's processing tool can add centroid connectors to a project's network. All you +need to do is specify the number of centroids and the project folder. You can also choose +the modes and the link types you want to connect, otherwise the default configuration uses +all modes and link types. .. image:: images/processing_provider_centroids.png :align: center @@ -44,14 +44,20 @@ The default connection mode is **c** (car). Add links from layer to project ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +This tool allows you to add links from a vector layer to your existing project network. +The fields usage is straightforward: in *Project path*, you add the project's path in your +machine, then select a vector layer that corresponds to the new links you want to add to +your project, and indicate the layer fields that correspond to the link type, direction, and +modes. Notice that this tool doesn't require a node layer, nor does it require fields such +as ``a_node`` or ``b_node``, as it will use the existing numbering in the project. + .. image:: images/processing_provider_new_links_to_project.png :align: center :alt: Processing provider add new links from layer to project Add/Renumber nodes from layer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -One can also add or renumber nodes in an AequilibraE project to match a layer of centroids. +You can also add or renumber nodes in an AequilibraE project to match a layer of centroids. Just select or import the centroids layer, specify the node ID you want to match, and the output folder. @@ -62,10 +68,10 @@ folder. Create project from link layer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Create project from link layer* is similar to the widget menu -:ref:`Create project from layers `, and allows the user to create an AequilibraE -project directly from a link layer, without requiring a node layer. With a geometric layer loaded into -QGIS, select it in the *Links* button, and add the required data in the subsequent menus. Choose the project's -name and specify the location where you want to save it on your machine. +:ref:`Create project from layers `, and allows you to create an AequilibraE +project directly from a link layer, without requiring a node layer. With a geometric layer loaded +into QGIS, select it in the *Links* button, and add the required data in the subsequent menus. +Choose the project's name and specify the location where you want to save it on your machine. .. image:: images/processing_provider_project_from_links.png :align: center @@ -73,6 +79,9 @@ name and specify the location where you want to save it on your machine. Create project from OSM ~~~~~~~~~~~~~~~~~~~~~~~ +This tool is similar to the homonymous widget menu +:ref:`Create project from OSM `, and allows you to create an AequilibraE +project only specifying the place name and the folder path and name you want to save the project. .. image:: images/processing_provider_project_from_osm.png :align: center @@ -82,19 +91,20 @@ Data ---- Create AequilibraE Matrix from layer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -With *Import matrices*, the user can save an open data layer directly as a \*.aem file. +With *Import matrices*, you can save an open data layer directly as a \*.aem file. This tool is analogous to the widget menu :ref:`importing_matrices`, but it does not -require an open AequilibraE project to work. To use the tool, the user must have an open layer +require an open AequilibraE project to work. To use the tool, you must have an open layer loaded in QGIS, and the menus are the ones presented in the figure below. .. image:: images/processing_provider_import_matrices.png :align: center :alt: Processing provider import matrices -The upper fields are mandatory and are responsible for selecting the layer, indicating -which columns correspond to the origin, destination, and flow, creating a file name, and -specifying the destination folder. In the *Advanced Parameters*, the user will find fields to add -extra information to the AequilibraE matrix they are about to create. +The upper fields are mandatory and are res.. note::ponsible for selecting the layer, indicating +which columns correspond to the origin, destination, and flow, creating a core name for your +matrix, and specifying the output file name and path. In the *Advanced Parameters*, you can add +extra information about your AequilibraE matrix using the fields ``Matrix name`` and +``Matrix description``. Export matrices ~~~~~~~~~~~~~~~ @@ -110,13 +120,51 @@ be used as input, and the output format can be either one of \*.aem, \*.omx, or Matrix calculator ~~~~~~~~~~~~~~~~~ +Under the hood, this tool performs several matrix calculations using NumPy. Its output is +an AequilibraE matrix stored in the file path you provide. Notice that not all matrices +operations available in NumPy are also available here. We currently handle the following +operations. + +* ``+``, ``-``, ``*``, ``/`` +* ``min``, ``max``, ``abs`` +* ``ln``, ``exp``, ``power`` +* ``null_diag``, ``T`` + +To be more effective in your calculation, please use the brackets to separate the operations +in the desired order of execution. + +The following code blocks present, respectively, the matrix input configuration in the YAML file +and an expression that can be used for calculation. .. image:: images/processing_provider_matrix_calc.png :align: center :alt: Processing provider matrix calculator - + +.. code-block:: yaml + :caption: Matrix configuration + + # For each matrix used for calculation + - matrix_name1: + matrix_path: path to file + matrix_core: specifiy the core name + # For all the constants used for calculation + - constants: + constant_name1: 3 + constant_name2: 0.8 + +.. code-block:: yaml + :caption: Expression + + (matrix_name1 - matrix_name2).T + Save matrix from layer in existing file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This tools allows you to export the data from a + +.. important:: + + Currently, we cannot add new cores to an existing AequilibraE matrix. For this reason + the only output file format available is \*.omx. .. image:: images/processing_provider_save_matrix_in_existing_file.png :align: center @@ -136,7 +184,7 @@ an example of a valid YAML configuration. :alt: Processing provider traffic assignment from file .. code-block:: yaml - :caption: YAML configuration example + :caption: Traffic assignment configuration project: path_to_aequilibrae_project result_name: name_of_result_file_to_save From e04d3bc0857f815d14144c864e9c921c6bdaacd5 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Tue, 10 Dec 2024 11:19:20 -0300 Subject: [PATCH 30/34] update docs and UI --- docs/source/processing_provider.rst | 117 +++++++++--------- .../assign_pt_from_yaml.py | 2 +- .../assign_traffic_from_yaml.py | 2 +- .../processing_provider/create_pt_graph.py | 5 +- .../processing_provider/export_matrix.py | 6 +- .../processing_provider/matrix_calculator.py | 4 +- .../processing_provider/project_from_layer.py | 12 +- 7 files changed, 75 insertions(+), 73 deletions(-) diff --git a/docs/source/processing_provider.rst b/docs/source/processing_provider.rst index 0e7e06be..e6c41a4d 100644 --- a/docs/source/processing_provider.rst +++ b/docs/source/processing_provider.rst @@ -2,10 +2,11 @@ Processing Tools ================ Some of AequilibraE's plugin functionalities are now available in a processing plugin. -The processing plugin is automatically installed with AequilibraE and allows you to perform +The processing plugin is automatically installed with QAequilibraE and allows you to perform several tasks, such as creating project from links, exporting matrices, and much more, as a batch process or not. To use the processing plugin, you don't have to directly open -the AequilibraE project, although it is mandatory to have AequilibraE installed. +the AequilibraE project, nor have the widget open, although it is mandatory to have +AequilibraE installed. To find AequilibraE's processing plugin, click on the **Processing** panel and select **Toolbox**. You can also use the available QGIS shortcut to open the Toolbox window. @@ -133,13 +134,13 @@ operations. To be more effective in your calculation, please use the brackets to separate the operations in the desired order of execution. -The following code blocks present, respectively, the matrix input configuration in the YAML file -and an expression that can be used for calculation. - .. image:: images/processing_provider_matrix_calc.png :align: center :alt: Processing provider matrix calculator +The following code blocks present, respectively, examples of a matrix input configuration for +the YAML file and an expression that can be used for calculation. + .. code-block:: yaml :caption: Matrix configuration @@ -159,7 +160,7 @@ and an expression that can be used for calculation. Save matrix from layer in existing file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This tools allows you to export the data from a +This tools allows you to export the data from an open layer to an existing \*.omx file. .. important:: @@ -176,21 +177,22 @@ Traffic assignment from file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AequilibraE traffic assignment can now be performed using a YAML file that contains the model input information. The process is straightforward: create a valid YAML file with your project path, -required matrices, and valid parameters, and load it into AequilibraE. The code block below contains -an example of a valid YAML configuration. +required matrices, and valid parameters, and load it into AequilibraE. .. image:: images/processing_provider_traffic_assignment.png :align: center :alt: Processing provider traffic assignment from file +The code block below contains an example of a valid YAML configuration. + .. code-block:: yaml :caption: Traffic assignment configuration - project: path_to_aequilibrae_project - result_name: name_of_result_file_to_save + project: path_to_project + result_name: test_from_yaml traffic_classes: - car: - matrix_path: path_to_aequilibrae_project/matrices/demand.aem + matrix_path: path_to_project/matrices/demand.aem matrix_core: matrix network_mode: c pce: 1 @@ -205,80 +207,81 @@ an example of a valid YAML configuration. time_field: free_flow_time max_iter: 10 rgap: 0.001 - + select_links: # optional, name with a list of lists as [[link_id, link_direction]] + - from_node_1: [[1, 1], [2, 1]] + - random_nodes: [[3, 1], [5, 1]] Public Transport ---------------- Create transit graph ~~~~~~~~~~~~~~~~~~~~ +Benefiting from new AequilibraE features, this processing tool allows you to create and +save a transit graph to use in the transit assignment. Figure below presents an screenshot +of the create transit graph processing interface. .. image:: images/processing_provider_create_transit_graph.png :align: center :alt: Processing provider create transit graph -.. code-block:: yaml - :caption: Transit graph Configuration +Notice that you will have to input data such as the project path, the desired mode, and the +period ID for which you want to create your graph. Other graph configuration, such +as ``Block flows through centroids`` and ``Project with walking edges`` are boolean, +and can be selected as necessary. You can read more about these configuration +`here `_. - project_path: path_to_aequilibrae_project - result_name: transit_from_yaml - matrix_path: path_to_aequilibrae_project/matrices/demand.aem - matrix_core: workers - assignment: - time_field: trav_time - frequency: freq - algorithm: os - graph: - period_id: 1 - with_outer_stop_transfers: False - with_walking_edges: False - blocking_centroid_flows: False - connector_method: overlapping_regions +.. note:: + + Currently only a single transit graph can be saved and reloaded. Create GTFS ~~~~~~~~~~~ +This tool allows you to import a GTFS feed to your project. Just point to the +GTFS zip and project paths in your machine, select the date for which you want to +import the transit routes, and if you want to map-match the routes or not. Remember +that depending on the GTFS size, the map-matching procedure can be really time-consuming. +Unlike the GTFS importer in the widget menu, to use this processing tool you must +know which calendar date you are going to use. .. image:: images/processing_provider_import_gtfs.png :align: center :alt: Processing provider import GTFS +.. tip:: + + Mobility Data is a non-profit organization that provides a + `GTFS validator tool `_. + If you want to use QAequilibraE processing processing provider tool to import a GTFS + feed, you can load your GTFS file at their validator and it will provide you useful + information, including calendar date ranges. Transit assignment from file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Transit assignment from file is quite similar to the traffic assignment presented above, +with the remarkable differences related to the transit graph and assignment, as shown in +AequilibraE. The YAML file setup includes the project location in your machine, as well as +information on matrix and assignment. To use this tool, you must have a transit graph, +either created by the processing tool above or using AequilibraE code. .. image:: images/processing_provider_transit_assignment.png :align: center :alt: Processing provider transit assignment from file +The code block below contains an example of a valid YAML configuration. + .. code-block:: yaml :caption: Transit assignment configuration - project: path_to_aequilibrae_project - result_name: your_result_name - traffic_classes: - - car: - matrix_path: path_to_aequilibrae_project/matrices/demand.aem - matrix_core: car - network_mode: c - pce: 1 - blocked_centroid_flows: True - skims: travel_time, distance - - truck: - matrix_path: path_to_aequilibrae_project/matrices/demand.aem - matrix_core: truck - network_mode: c - pce: 2 - fixed_cost: toll - vot: 12 - blocked_centroid_flows: True + project_path: path_to_project + result_name: transit_from_yaml + matrix_path: path_to_project/matrices/demand.aem + matrix_core: workers assignment: - algorithm: bfw - vdf: BPR2 - alpha: 0.15 - beta: power - capacity_field: capacity - time_field: travel_time - max_iter: 250 - rgap: 0.00001 - select_links: # optional, name with a list of lists as [[link_id, link_direction]] - - from_node_1: [[1, 1], [2, 1]] - - random_nodes: [[3, 1], [5, 1]] \ No newline at end of file + time_field: trav_time + frequency: freq + algorithm: os + graph: + period_id: 1 + with_outer_stop_transfers: False + with_walking_edges: False + blocking_centroid_flows: False + connector_method: overlapping_regions diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py index 292e4fd4..d9ad294f 100644 --- a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -13,7 +13,7 @@ def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterFile( "conf_file", - self.tr("Configuration file (.yaml)"), + self.tr("Configuration file (*.yaml)"), behavior=QgsProcessingParameterFile.File, fileFilter="", ) diff --git a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py index b220e7e9..25bb6c53 100644 --- a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py @@ -13,7 +13,7 @@ def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterFile( "conf_file", - self.tr("Configuration file (.yaml)"), + self.tr("Configuration file (*.yaml)"), behavior=QgsProcessingParameterFile.File, fileFilter="", defaultValue=None, diff --git a/qaequilibrae/modules/processing_provider/create_pt_graph.py b/qaequilibrae/modules/processing_provider/create_pt_graph.py index 8c674a81..488f8ffb 100644 --- a/qaequilibrae/modules/processing_provider/create_pt_graph.py +++ b/qaequilibrae/modules/processing_provider/create_pt_graph.py @@ -16,12 +16,11 @@ def initAlgorithm(self, config=None): QgsProcessingParameterFile( "project_path", self.tr("Project path"), - behavior=QgsProcessingParameterFile.Folder, - defaultValue=standard_path(), + behavior=QgsProcessingParameterFile.Folder ) ) self.addParameter( - QgsProcessingParameterString("access_mode", self.tr("Mode"), multiLine=False, defaultValue="w") + QgsProcessingParameterString("access_mode", self.tr("Modes"), multiLine=False) ) self.addParameter( QgsProcessingParameterBoolean("block_flows", self.tr("Block flows through centroids"), defaultValue=True) diff --git a/qaequilibrae/modules/processing_provider/export_matrix.py b/qaequilibrae/modules/processing_provider/export_matrix.py index a13d7d5c..6ee17e27 100644 --- a/qaequilibrae/modules/processing_provider/export_matrix.py +++ b/qaequilibrae/modules/processing_provider/export_matrix.py @@ -21,8 +21,8 @@ def initAlgorithm(self, config=None): ) self.addParameter( QgsProcessingParameterFile( - "dst", - self.tr("Output folder"), + "file_path", + self.tr("File path"), behavior=QgsProcessingParameterFile.Folder, defaultValue=None, ) @@ -46,7 +46,7 @@ def processAlgorithm(self, parameters, context, feedback): file_format = ["csv", "omx", "aem"] format = file_format[parameters["output_format"]] file_name, ext = parameters["src"].split("/")[-1].split(".") - dst_path = join(parameters["dst"], f"{file_name}.{format}") + dst_path = join(parameters["file_path"], f"{file_name}.{format}") kwargs = {"file_path": dst_path, "memory_only": False} mat = AequilibraeMatrix() diff --git a/qaequilibrae/modules/processing_provider/matrix_calculator.py b/qaequilibrae/modules/processing_provider/matrix_calculator.py index 6496e695..7e15c73c 100644 --- a/qaequilibrae/modules/processing_provider/matrix_calculator.py +++ b/qaequilibrae/modules/processing_provider/matrix_calculator.py @@ -35,10 +35,10 @@ def initAlgorithm(self, config=None): ) ) self.addParameter( - QgsProcessingParameterString("procedure", self.tr("Expression"), multiLine=True, defaultValue="") + QgsProcessingParameterString("procedure", self.tr("Expression"), multiLine=True) ) self.addParameter( - QgsProcessingParameterString("matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="matrix") + QgsProcessingParameterString("matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="matrix_core") ) self.addParameter( QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "AequilibraE Matrix (*.aem)") diff --git a/qaequilibrae/modules/processing_provider/project_from_layer.py b/qaequilibrae/modules/processing_provider/project_from_layer.py index 46d4b00a..434a1927 100644 --- a/qaequilibrae/modules/processing_provider/project_from_layer.py +++ b/qaequilibrae/modules/processing_provider/project_from_layer.py @@ -29,18 +29,18 @@ def initAlgorithm(self, config=None): ) self.addParameter( QgsProcessingParameterField( - "link_type", - self.tr("Link type"), - type=QgsProcessingParameterField.String, + "direction", + self.tr("Direction"), + type=QgsProcessingParameterField.Numeric, parentLayerParameterName="links", allowMultiple=False, ) ) self.addParameter( QgsProcessingParameterField( - "direction", - self.tr("Direction"), - type=QgsProcessingParameterField.Numeric, + "link_type", + self.tr("Link type"), + type=QgsProcessingParameterField.String, parentLayerParameterName="links", allowMultiple=False, ) From 25cf665ce9dd957a5abd7a695aa7686385b82a04 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Tue, 10 Dec 2024 11:39:10 -0300 Subject: [PATCH 31/34] update UI --- .../add_links_from_layer.py | 16 ++++++------ .../add_matrix_from_layer.py | 6 ++--- .../assign_pt_from_yaml.py | 1 - .../assign_traffic_from_yaml.py | 2 -- .../create_matrix_from_layer.py | 6 ++--- .../processing_provider/create_pt_graph.py | 25 ++++++------------- .../processing_provider/export_matrix.py | 15 +++++------ .../processing_provider/import_gtfs.py | 14 +++++------ .../processing_provider/matrix_calculator.py | 14 +++++------ 9 files changed, 43 insertions(+), 56 deletions(-) diff --git a/qaequilibrae/modules/processing_provider/add_links_from_layer.py b/qaequilibrae/modules/processing_provider/add_links_from_layer.py index 45054b74..b92b1d83 100644 --- a/qaequilibrae/modules/processing_provider/add_links_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_links_from_layer.py @@ -22,23 +22,25 @@ def initAlgorithm(self, config=None): ) self.addParameter( QgsProcessingParameterVectorLayer( - "links", self.tr("Links"), types=[QgsProcessing.TypeVectorLine], defaultValue=None + "links", + self.tr("Links"), + types=[QgsProcessing.TypeVectorLine], ) ) self.addParameter( QgsProcessingParameterField( - "link_type", - self.tr("Link type"), - type=QgsProcessingParameterField.String, + "direction", + self.tr("Direction"), + type=QgsProcessingParameterField.Numeric, parentLayerParameterName="links", allowMultiple=False, ) ) self.addParameter( QgsProcessingParameterField( - "direction", - self.tr("Direction"), - type=QgsProcessingParameterField.Numeric, + "link_type", + self.tr("Link type"), + type=QgsProcessingParameterField.String, parentLayerParameterName="links", allowMultiple=False, ) diff --git a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py index 5402b5ec..3fbda34e 100644 --- a/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/add_matrix_from_layer.py @@ -15,7 +15,7 @@ class AddMatrixFromLayer(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): self.addParameter( - QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "Open Matrix (*.omx)") + QgsProcessingParameterFileDestination("file_path", self.tr("File path"), "Open Matrix (*.omx)") ) self.addParameter(QgsProcessingParameterMapLayer("matrix_layer", self.tr("Matrix Layer"))) self.addParameter( @@ -94,14 +94,14 @@ def processAlgorithm(self, parameters, context, model_feedback): .astype(np.float64) ) - mat = omx.open_file(parameters["file_name"], "a") + mat = omx.open_file(parameters["file_path"], "a") mat[parameters["matrix_core"]] = m mat.close() feedback.pushInfo(" ") feedback.setCurrentStep(3) - return {"Output": f"New core addedd to {parameters["file_name"]}"} + return {"Output": f"New core addedd to {parameters["file_path"]}"} def name(self): return "exportmatrixasomx" diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py index d9ad294f..55597030 100644 --- a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py @@ -15,7 +15,6 @@ def initAlgorithm(self, config=None): "conf_file", self.tr("Configuration file (*.yaml)"), behavior=QgsProcessingParameterFile.File, - fileFilter="", ) ) diff --git a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py index 25bb6c53..991d2730 100644 --- a/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py +++ b/qaequilibrae/modules/processing_provider/assign_traffic_from_yaml.py @@ -15,8 +15,6 @@ def initAlgorithm(self, config=None): "conf_file", self.tr("Configuration file (*.yaml)"), behavior=QgsProcessingParameterFile.File, - fileFilter="", - defaultValue=None, ) ) diff --git a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py index ddf99b34..d081dadf 100644 --- a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py @@ -48,7 +48,7 @@ def initAlgorithm(self, config=None): ) ) self.addParameter( - QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "AequilibraE Matrix (*.aem)") + QgsProcessingParameterFileDestination("file_path", self.tr("File path"), "AequilibraE Matrix (*.aem)") ) advparams = [ @@ -82,7 +82,7 @@ def processAlgorithm(self, parameters, context, model_feedback): destination = parameters["destination"] value = parameters["value"] list_cores = [parameters["matrix_core"]] - path_to_file = parameters["file_name"] + path_to_file = parameters["file_path"] # Import layer as a pandas df feedback.pushInfo(self.tr("Importing layer")) @@ -109,7 +109,7 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback.setCurrentStep(2) mat = AequilibraeMatrix() - mat.create_empty(file_name=path_to_file, zones=nb_of_zones, matrix_names=list_cores, memory_only=False) + mat.create_empty(file_path=path_to_file, zones=nb_of_zones, matrix_names=list_cores, memory_only=False) m = ( coo_matrix( diff --git a/qaequilibrae/modules/processing_provider/create_pt_graph.py b/qaequilibrae/modules/processing_provider/create_pt_graph.py index 488f8ffb..c1826323 100644 --- a/qaequilibrae/modules/processing_provider/create_pt_graph.py +++ b/qaequilibrae/modules/processing_provider/create_pt_graph.py @@ -3,9 +3,7 @@ from qgis.core import QgsProcessingAlgorithm, QgsProcessingParameterFile from qgis.core import QgsProcessingParameterBoolean, QgsProcessingParameterString, QgsProcessingParameterNumber -from qgis.core import QgsProcessingParameterDefinition -from qaequilibrae.modules.common_tools import standard_path from qaequilibrae.i18n.translate import trlt @@ -14,14 +12,15 @@ class CreatePTGraph(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterFile( - "project_path", - self.tr("Project path"), - behavior=QgsProcessingParameterFile.Folder + "project_path", self.tr("Project path"), behavior=QgsProcessingParameterFile.Folder ) ) self.addParameter( - QgsProcessingParameterString("access_mode", self.tr("Modes"), multiLine=False) + QgsProcessingParameterNumber( + "period_id", self.tr("Period ID"), type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=1 + ) ) + self.addParameter(QgsProcessingParameterString("access_mode", self.tr("Modes"), multiLine=False)) self.addParameter( QgsProcessingParameterBoolean("block_flows", self.tr("Block flows through centroids"), defaultValue=True) ) @@ -33,17 +32,9 @@ def initAlgorithm(self, config=None): "outer_stops_transfers", self.tr("Project with outer stops transfers"), defaultValue=False ) ) - - advparams = [ - QgsProcessingParameterBoolean("has_zones", self.tr("Project has zoning information"), defaultValue=True), - QgsProcessingParameterNumber( - "period_id", self.tr("Period ID"), type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=1 - ), - ] - - for param in advparams: - param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) - self.addParameter(param) + self.addParameter( + QgsProcessingParameterBoolean("has_zones", self.tr("Project has zoning information"), defaultValue=True) + ) def processAlgorithm(self, parameters, context, feedback): # Checks if we have access to aequilibrae library diff --git a/qaequilibrae/modules/processing_provider/export_matrix.py b/qaequilibrae/modules/processing_provider/export_matrix.py index 6ee17e27..631815f7 100644 --- a/qaequilibrae/modules/processing_provider/export_matrix.py +++ b/qaequilibrae/modules/processing_provider/export_matrix.py @@ -12,11 +12,9 @@ class ExportMatrix(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterFile( - "src", - self.tr("Matrix"), + "matrix_path", + self.tr("Matrix path"), behavior=QgsProcessingParameterFile.File, - fileFilter="*.omx, *.aem", - defaultValue=None, ) ) self.addParameter( @@ -24,7 +22,6 @@ def initAlgorithm(self, config=None): "file_path", self.tr("File path"), behavior=QgsProcessingParameterFile.Folder, - defaultValue=None, ) ) self.addParameter( @@ -45,7 +42,7 @@ def processAlgorithm(self, parameters, context, feedback): file_format = ["csv", "omx", "aem"] format = file_format[parameters["output_format"]] - file_name, ext = parameters["src"].split("/")[-1].split(".") + file_name, ext = parameters["matrix_path"].split("/")[-1].split(".") dst_path = join(parameters["file_path"], f"{file_name}.{format}") kwargs = {"file_path": dst_path, "memory_only": False} @@ -53,12 +50,12 @@ def processAlgorithm(self, parameters, context, feedback): if ext == "omx": if format == "omx": - mat.create_from_omx(omx_path=parameters["src"], **kwargs) + mat.create_from_omx(omx_path=parameters["matrix_path"], **kwargs) elif format in ["csv", "aem"]: - mat.create_from_omx(parameters["src"]) + mat.create_from_omx(parameters["matrix_path"]) mat.export(dst_path) elif ext == "aem": - mat.load(parameters["src"]) + mat.load(parameters["matrix_path"]) mat.export(dst_path) mat.close() diff --git a/qaequilibrae/modules/processing_provider/import_gtfs.py b/qaequilibrae/modules/processing_provider/import_gtfs.py index 60dad075..72ec1731 100644 --- a/qaequilibrae/modules/processing_provider/import_gtfs.py +++ b/qaequilibrae/modules/processing_provider/import_gtfs.py @@ -10,6 +10,13 @@ class ImportGTFS(QgsProcessingAlgorithm): def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterFile( + "project_path", + self.tr("Project path"), + behavior=QgsProcessingParameterFile.Folder, + ) + ) self.addParameter( QgsProcessingParameterFile( "gtfs_file", @@ -30,13 +37,6 @@ def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterBoolean("allow_map_match", self.tr("Map-match transit routes"), defaultValue=True) ) - self.addParameter( - QgsProcessingParameterFile( - "project_path", - self.tr("Project path"), - behavior=QgsProcessingParameterFile.Folder, - ) - ) def processAlgorithm(self, parameters, context, feedback): # Checks if we have access to aequilibrae library diff --git a/qaequilibrae/modules/processing_provider/matrix_calculator.py b/qaequilibrae/modules/processing_provider/matrix_calculator.py index 7e15c73c..bf55b493 100644 --- a/qaequilibrae/modules/processing_provider/matrix_calculator.py +++ b/qaequilibrae/modules/processing_provider/matrix_calculator.py @@ -34,14 +34,14 @@ def initAlgorithm(self, config=None): behavior=QgsProcessingParameterFile.File, ) ) + self.addParameter(QgsProcessingParameterString("procedure", self.tr("Expression"), multiLine=True)) self.addParameter( - QgsProcessingParameterString("procedure", self.tr("Expression"), multiLine=True) - ) - self.addParameter( - QgsProcessingParameterString("matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="matrix_core") + QgsProcessingParameterString( + "matrix_core", self.tr("Matrix core"), multiLine=False, defaultValue="matrix_core" + ) ) self.addParameter( - QgsProcessingParameterFileDestination("file_name", self.tr("File name"), "AequilibraE Matrix (*.aem)") + QgsProcessingParameterFileDestination("file_path", self.tr("File path"), "AequilibraE Matrix (*.aem)") ) def processAlgorithm(self, parameters, context, model_feedback): @@ -51,7 +51,7 @@ def processAlgorithm(self, parameters, context, model_feedback): from aequilibrae.matrix import AequilibraeMatrix - if parameters["file_name"] is None: + if parameters["file_path"] is None: raise QgsProcessingException(self.tr("Plase use a valid file name.")) feedback = QgsProcessingMultiStepFeedback(4, model_feedback) @@ -87,7 +87,7 @@ def processAlgorithm(self, parameters, context, model_feedback): mat = AequilibraeMatrix() mat.create_empty( - file_name=parameters["file_name"], + file_path=parameters["file_path"], zones=len(index), matrix_names=[parameters["matrix_core"]], memory_only=False, From 35ef2022b19faf8d03d4644d212d6337917ef52e Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Tue, 10 Dec 2024 11:53:42 -0300 Subject: [PATCH 32/34] rename files --- ...om_yaml.py => assign_transit_from_yaml.py} | 0 ...te_pt_graph.py => create_transit_graph.py} | 2 +- .../modules/processing_provider/provider.py | 4 +- test/test_processing_provider.py | 41 ++++++++----------- 4 files changed, 19 insertions(+), 28 deletions(-) rename qaequilibrae/modules/processing_provider/{assign_pt_from_yaml.py => assign_transit_from_yaml.py} (100%) rename qaequilibrae/modules/processing_provider/{create_pt_graph.py => create_transit_graph.py} (98%) diff --git a/qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py b/qaequilibrae/modules/processing_provider/assign_transit_from_yaml.py similarity index 100% rename from qaequilibrae/modules/processing_provider/assign_pt_from_yaml.py rename to qaequilibrae/modules/processing_provider/assign_transit_from_yaml.py diff --git a/qaequilibrae/modules/processing_provider/create_pt_graph.py b/qaequilibrae/modules/processing_provider/create_transit_graph.py similarity index 98% rename from qaequilibrae/modules/processing_provider/create_pt_graph.py rename to qaequilibrae/modules/processing_provider/create_transit_graph.py index c1826323..8693c8a1 100644 --- a/qaequilibrae/modules/processing_provider/create_pt_graph.py +++ b/qaequilibrae/modules/processing_provider/create_transit_graph.py @@ -33,7 +33,7 @@ def initAlgorithm(self, config=None): ) ) self.addParameter( - QgsProcessingParameterBoolean("has_zones", self.tr("Project has zoning information"), defaultValue=True) + QgsProcessingParameterBoolean("has_zones", self.tr("Project has zoning information"), defaultValue=False) ) def processAlgorithm(self, parameters, context, feedback): diff --git a/qaequilibrae/modules/processing_provider/provider.py b/qaequilibrae/modules/processing_provider/provider.py index 6d241cab..8fbb0890 100644 --- a/qaequilibrae/modules/processing_provider/provider.py +++ b/qaequilibrae/modules/processing_provider/provider.py @@ -18,10 +18,10 @@ def loadAlgorithms(self): from .Add_connectors import AddConnectors from .add_links_from_layer import AddLinksFromLayer from .add_matrix_from_layer import AddMatrixFromLayer - from .assign_pt_from_yaml import TransitAssignYAML + from .assign_transit_from_yaml import TransitAssignYAML from .assign_traffic_from_yaml import TrafficAssignYAML from .create_matrix_from_layer import CreateMatrixFromLayer - from .create_pt_graph import CreatePTGraph + from .create_transit_graph import CreatePTGraph from .export_matrix import ExportMatrix from .import_gtfs import ImportGTFS from .matrix_calculator import MatrixCalculator diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index 0a5ac0f6..f34b6177 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -11,37 +11,28 @@ import pytest from shapely.geometry import Point -from aequilibrae.matrix import AequilibraeMatrix from aequilibrae import Project +from aequilibrae.matrix import AequilibraeMatrix from aequilibrae.transit import Transit from qgis.core import QgsApplication, QgsProcessingContext, QgsProcessingFeedback from qgis.core import QgsProject, QgsField, QgsVectorLayer from PyQt5.QtCore import QVariant +from .utilities import load_sfalls_from_layer from qaequilibrae.modules.common_tools.data_layer_from_dataframe import layer_from_dataframe from qaequilibrae.modules.processing_provider.provider import Provider from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors from qaequilibrae.modules.processing_provider.add_links_from_layer import AddLinksFromLayer from qaequilibrae.modules.processing_provider.add_matrix_from_layer import AddMatrixFromLayer -from qaequilibrae.modules.processing_provider.assign_pt_from_yaml import TransitAssignYAML +from qaequilibrae.modules.processing_provider.assign_transit_from_yaml import TransitAssignYAML from qaequilibrae.modules.processing_provider.assign_traffic_from_yaml import TrafficAssignYAML from qaequilibrae.modules.processing_provider.create_matrix_from_layer import CreateMatrixFromLayer -from qaequilibrae.modules.processing_provider.create_pt_graph import CreatePTGraph +from qaequilibrae.modules.processing_provider.create_transit_graph import CreatePTGraph from qaequilibrae.modules.processing_provider.export_matrix import ExportMatrix from qaequilibrae.modules.processing_provider.import_gtfs import ImportGTFS from qaequilibrae.modules.processing_provider.matrix_calculator import MatrixCalculator from qaequilibrae.modules.processing_provider.project_from_layer import ProjectFromLayer from qaequilibrae.modules.processing_provider.project_from_OSM import ProjectFromOSM -from aequilibrae.project import Project - -from .utilities import load_sfalls_from_layer -from qaequilibrae.modules.common_tools.data_layer_from_dataframe import layer_from_dataframe -from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors -from qaequilibrae.modules.processing_provider.assign_from_yaml import TrafficAssignYAML -from qaequilibrae.modules.processing_provider.export_matrix import ExportMatrix -from qaequilibrae.modules.processing_provider.matrix_from_layer import MatrixFromLayer -from qaequilibrae.modules.processing_provider.project_from_layer import ProjectFromLayer -from qaequilibrae.modules.processing_provider.provider import Provider from qaequilibrae.modules.processing_provider.renumber_nodes_from_layer import RenumberNodesFromLayer @@ -68,8 +59,8 @@ def test_export_matrix(folder_path, source_file, format): action = ExportMatrix() parameters = { - "src": f"test/data/SiouxFalls_project/matrices/{source_file}", - "dst": folder_path, + "matrix_path": f"test/data/SiouxFalls_project/matrices/{source_file}", + "file_path": folder_path, "output_format": format, } @@ -94,7 +85,7 @@ def test_matrix_from_layer(folder_path): "origin": "O", "destination": "D", "value": "Ton", - "file_name": join(folder_path, "demand.omx"), + "file_path": join(folder_path, "demand.omx"), "matrix_core": "MAT_CORE", } @@ -103,9 +94,9 @@ def test_matrix_from_layer(folder_path): _ = action.run(parameters, context, feedback) - assert isfile(parameters["file_name"]) + assert isfile(parameters["file_path"]) - mat = omx.open_file(parameters["file_name"]) + mat = omx.open_file(parameters["file_path"]) assert "MAT_CORE" in mat.list_matrices() m = np.array(mat["MAT_CORE"]) @@ -330,7 +321,7 @@ def test_add_links_from_layer(ae_with_project): project = Project() project.open(folder_path) - assert project.network.count_links() == 80 + assert project.network.count_links() == 81 assert project.network.count_nodes() == 28 @@ -399,7 +390,7 @@ def test_create_matrix_from_layer(folder_path): "origin": "O", "destination": "D", "value": "Ton", - "file_name": join(folder_path, "siouxfalls_od.aem"), + "file_path": join(folder_path, "siouxfalls_od.aem"), "matrix_core": "MAT_CORE", } @@ -407,10 +398,10 @@ def test_create_matrix_from_layer(folder_path): feedback = QgsProcessingFeedback() _ = action.run(parameters, context, feedback) - assert isfile(parameters["file_name"]) + assert isfile(parameters["file_path"]) mat = AequilibraeMatrix() - mat.load(parameters["file_name"]) + mat.load(parameters["file_path"]) info = mat.__dict__ assert info["names"] == [parameters["matrix_core"]] @@ -426,7 +417,7 @@ def test_matrix_calc(folder_path): parameters = { "conf_file": "test/data/SiouxFalls_project/matrix_config.yml", "procedure": "(cars + heavy_vehicles).T", - "file_name": f"{folder_path}/hello.aem", + "file_path": f"{folder_path}/hello.aem", "matrix_core": "new_core", } @@ -435,9 +426,9 @@ def test_matrix_calc(folder_path): _ = action.run(parameters, context, feedback) - assert isfile(parameters["file_name"]) + assert isfile(parameters["file_path"]) mat = AequilibraeMatrix() - mat.load(parameters["file_name"]) + mat.load(parameters["file_path"]) info = mat.__dict__ assert info["names"] == [parameters["matrix_core"]] From 3d9a256a31e51cd475ec7834b5e3f63ce14584e2 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Tue, 10 Dec 2024 13:57:48 -0300 Subject: [PATCH 33/34] . --- docs/source/processing_provider.rst | 4 - .../create_matrix_from_layer.py | 2 +- .../processing_provider/matrix_calculator.py | 4 +- test/test_processing_provider.py | 75 +++++++------------ 4 files changed, 30 insertions(+), 55 deletions(-) diff --git a/docs/source/processing_provider.rst b/docs/source/processing_provider.rst index e6c41a4d..59209112 100644 --- a/docs/source/processing_provider.rst +++ b/docs/source/processing_provider.rst @@ -148,10 +148,6 @@ the YAML file and an expression that can be used for calculation. - matrix_name1: matrix_path: path to file matrix_core: specifiy the core name - # For all the constants used for calculation - - constants: - constant_name1: 3 - constant_name2: 0.8 .. code-block:: yaml :caption: Expression diff --git a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py index d081dadf..cbb4724f 100644 --- a/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py +++ b/qaequilibrae/modules/processing_provider/create_matrix_from_layer.py @@ -109,7 +109,7 @@ def processAlgorithm(self, parameters, context, model_feedback): feedback.setCurrentStep(2) mat = AequilibraeMatrix() - mat.create_empty(file_path=path_to_file, zones=nb_of_zones, matrix_names=list_cores, memory_only=False) + mat.create_empty(file_name=path_to_file, zones=nb_of_zones, matrix_names=list_cores, memory_only=False) m = ( coo_matrix( diff --git a/qaequilibrae/modules/processing_provider/matrix_calculator.py b/qaequilibrae/modules/processing_provider/matrix_calculator.py index bf55b493..44f6da57 100644 --- a/qaequilibrae/modules/processing_provider/matrix_calculator.py +++ b/qaequilibrae/modules/processing_provider/matrix_calculator.py @@ -87,7 +87,7 @@ def processAlgorithm(self, parameters, context, model_feedback): mat = AequilibraeMatrix() mat.create_empty( - file_path=parameters["file_path"], + file_name=parameters["file_path"], zones=len(index), matrix_names=[parameters["matrix_core"]], memory_only=False, @@ -121,7 +121,7 @@ def shortHelpString(self): self.tr("- expression must be written according to NumPy syntax."), self.tr("Examples of valid expressions and configuration are provided in the plugin documentation."), ] - return "\n".join(help_messages) + return "".join(help_messages) def createInstance(self): return MatrixCalculator() diff --git a/test/test_processing_provider.py b/test/test_processing_provider.py index f34b6177..4a9c0bdd 100644 --- a/test/test_processing_provider.py +++ b/test/test_processing_provider.py @@ -1,24 +1,22 @@ -import os -import re -import pandas as pd import numpy as np import openmatrix as omx +import pandas as pd +import pytest +import re import shutil import sqlite3 -from os.path import isfile, join -from os import environ, makedirs - -import pytest -from shapely.geometry import Point from aequilibrae import Project from aequilibrae.matrix import AequilibraeMatrix from aequilibrae.transit import Transit +from os import environ, makedirs +from os.path import isfile, join +from PyQt5.QtCore import QVariant from qgis.core import QgsApplication, QgsProcessingContext, QgsProcessingFeedback from qgis.core import QgsProject, QgsField, QgsVectorLayer -from PyQt5.QtCore import QVariant +from shapely.geometry import Point -from .utilities import load_sfalls_from_layer +from .utilities import load_test_layer, load_sfalls_from_layer from qaequilibrae.modules.common_tools.data_layer_from_dataframe import layer_from_dataframe from qaequilibrae.modules.processing_provider.provider import Provider from qaequilibrae.modules.processing_provider.Add_connectors import AddConnectors @@ -55,8 +53,7 @@ def test_provider_exists(qgis_app): @pytest.mark.parametrize("format", [0, 1, 2]) @pytest.mark.parametrize("source_file", ["sfalls_skims.omx", "demand.aem"]) def test_export_matrix(folder_path, source_file, format): - os.makedirs(folder_path) - action = ExportMatrix() + makedirs(folder_path) parameters = { "matrix_path": f"test/data/SiouxFalls_project/matrices/{source_file}", @@ -64,6 +61,7 @@ def test_export_matrix(folder_path, source_file, format): "output_format": format, } + action = ExportMatrix() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -73,13 +71,11 @@ def test_export_matrix(folder_path, source_file, format): def test_matrix_from_layer(folder_path): - os.makedirs(folder_path) + makedirs(folder_path) df = pd.read_csv("test/data/SiouxFalls_project/SiouxFalls_od.csv") layer = layer_from_dataframe(df, "SiouxFalls_od") - action = AddMatrixFromLayer() - parameters = { "matrix_layer": layer, "origin": "O", @@ -89,6 +85,7 @@ def test_matrix_from_layer(folder_path): "matrix_core": "MAT_CORE", } + action = AddMatrixFromLayer() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -120,8 +117,6 @@ def test_project_from_layer(folder_path): linkslayer.commitChanges() - action = ProjectFromLayer() - parameters = { "links": linkslayer, "link_id": "link_id", @@ -131,6 +126,7 @@ def test_project_from_layer(folder_path): "project_path": f"{folder_path}/new_project", } + action = ProjectFromLayer() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -154,10 +150,9 @@ def test_add_centroid_connector(pt_no_feed): cnt.geometry = Point(-71.34, -29.95) cnt.save() - action = AddConnectors() - parameters = {"num_connectors": 3, "mode": "c", "project_path": project_folder} + action = AddConnectors() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -189,10 +184,9 @@ def test_renumber_from_centroids(ae_with_project, tmp_path): nodeslayer.commitChanges() - action = RenumberNodesFromLayer() - parameters = {"nodes": nodeslayer, "node_id": "id", "project_path": project_folder} + action = RenumberNodesFromLayer() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -222,10 +216,9 @@ def test_assign_from_yaml(ae_with_project): with open(file_path, "w", encoding="utf-8") as file: file.write(updated_content) - action = TrafficAssignYAML() - parameters = {"conf_file": file_path} + action = TrafficAssignYAML() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -248,8 +241,6 @@ def test_create_pt_graph(coquimbo_project): project = coquimbo_project.project project_folder = project.project_base_path - action = CreatePTGraph() - parameters = { "project_path": project_folder, "access_mode": "c", @@ -258,6 +249,7 @@ def test_create_pt_graph(coquimbo_project): "outer_stops_transfers": False, } + action = CreatePTGraph() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -273,8 +265,6 @@ def test_import_gtfs(pt_no_feed, allow_map_match): project = pt_no_feed.project project_folder = project.project_base_path - action = ImportGTFS() - parameters = { "project_path": project_folder, "gtfs_file": "test/data/coquimbo_project/gtfs_coquimbo.zip", @@ -283,6 +273,7 @@ def test_import_gtfs(pt_no_feed, allow_map_match): "allow_map_match": allow_map_match, } + action = ImportGTFS() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -292,18 +283,9 @@ def test_import_gtfs(pt_no_feed, allow_map_match): def test_add_links_from_layer(ae_with_project): folder_path = ae_with_project.project.project_base_path - csv_path = f"{folder_path}/link.csv" - shutil.copyfile("test/data/NetworkPreparation/link.csv", csv_path) - - uri = "file://{}?delimiter=,&crs=epsg:4326&wktField={}".format(csv_path, "geometry") - layer = QgsVectorLayer(uri, "link", "delimitedtext") - - if not layer.isValid(): - print("Layer failed to load!") - else: - QgsProject.instance().addMapLayer(layer) - action = AddLinksFromLayer() + load_test_layer(ae_with_project.project.project_base_path, "link") + layer = QgsProject.instance().mapLayersByName("link")[0] parameters = { "links": layer, @@ -313,6 +295,7 @@ def test_add_links_from_layer(ae_with_project): "project_path": ae_with_project.project.project_base_path, } + action = AddLinksFromLayer() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -356,10 +339,9 @@ def test_assign_transit_from_yaml(coquimbo_project): data.save_graphs() - action = TransitAssignYAML() - parameters = {"conf_file": file_path} + action = TransitAssignYAML() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -383,8 +365,6 @@ def test_create_matrix_from_layer(folder_path): df = pd.read_csv("test/data/SiouxFalls_project/SiouxFalls_od.csv") layer = layer_from_dataframe(df, "SiouxFalls_od") - action = CreateMatrixFromLayer() - parameters = { "matrix_layer": layer, "origin": "O", @@ -394,6 +374,7 @@ def test_create_matrix_from_layer(folder_path): "matrix_core": "MAT_CORE", } + action = CreateMatrixFromLayer() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -412,15 +393,14 @@ def test_create_matrix_from_layer(folder_path): def test_matrix_calc(folder_path): makedirs(folder_path) - action = MatrixCalculator() - parameters = { "conf_file": "test/data/SiouxFalls_project/matrix_config.yml", - "procedure": "(cars + heavy_vehicles).T", + "procedure": "(cars - (heavy_vehicles * 0.25)).T", "file_path": f"{folder_path}/hello.aem", "matrix_core": "new_core", } + action = MatrixCalculator() context = QgsProcessingContext() feedback = QgsProcessingFeedback() @@ -433,16 +413,15 @@ def test_matrix_calc(folder_path): info = mat.__dict__ assert info["names"] == [parameters["matrix_core"]] assert info["zones"] == 24 - assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) > 360600 + assert np.sum(info["matrix"][parameters["matrix_core"]][:, :]) > 0 @pytest.mark.skipif(not bool(environ.get("CI")), reason="Runs only in GitHub Action") def test_project_from_osm(folder_path): - action = ProjectFromOSM() - parameters = {"place_name": "Abrolhos", "project_path": folder_path} + action = ProjectFromOSM() context = QgsProcessingContext() feedback = QgsProcessingFeedback() From 4638b5061bfd1ea7c4f66a1c6b97f5b292eb2016 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Tue, 10 Dec 2024 14:05:19 -0300 Subject: [PATCH 34/34] Update docs images --- .../images/processing_provider_centroids.png | Bin 18459 -> 16378 bytes ...ocessing_provider_create_transit_graph.png | Bin 18441 -> 15770 bytes .../processing_provider_export_matrices.png | Bin 15418 -> 13713 bytes .../processing_provider_import_gtfs.png | Bin 16718 -> 15236 bytes .../processing_provider_import_matrices.png | Bin 25410 -> 21606 bytes .../processing_provider_matrix_calc.png | Bin 22846 -> 20588 bytes ...ocessing_provider_new_links_to_project.png | Bin 20112 -> 15443 bytes ...ocessing_provider_nodes_from_centroids.png | Bin 20314 -> 18221 bytes ...processing_provider_project_from_links.png | Bin 21227 -> 16250 bytes .../processing_provider_project_from_osm.png | Bin 15633 -> 14024 bytes ..._provider_save_matrix_in_existing_file.png | Bin 25082 -> 20895 bytes ...processing_provider_traffic_assignment.png | Bin 16565 -> 15055 bytes ...processing_provider_transit_assignment.png | Bin 16258 -> 14823 bytes 13 files changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/source/images/processing_provider_centroids.png b/docs/source/images/processing_provider_centroids.png index 9f06c92f270fbadd8ba49e656402d0ae1f277111..8e2639120dcf79573fbcba2da8dddeada4ef1c9f 100644 GIT binary patch literal 16378 zcmeHucT|+ymgk2kAkmCMAt*VcL_v~BD53%dA{04DF0z1R1Qn4aIjJPcQHmTTC&?5! z=b+@wobulL-gNhy?l;}NX04euf1qD|;heqC+55NSdHY0BnuL&o5P~2QxXfc^2s&2; z{tUq(c4?5<+A`c#xU6yE2$?_>&5 z*_v9lcXS9ks_r+eRJDp8bKg0OI_t*0+6W`FaX$Xlc2_mx$x`j_ z3%G25J@3yy{!#*s2SH&o(+vUmq_82h^+aZF70ZFHY=&aIAbpG21oo-v+386rerJNP z(9YpX?gpmNzl#`xqEJ^ZI<5^nEcd0SFI-KffFSw2g#=eCQ&Uqj8=GH%j#N_Yy+~~r z)2;+z6(!LV`+5)lsnwN<2Zwd@xJ{?-r{#O@3k~t)oR#`kfL z#e@TYYvG-89p}{(Cy~S6=ZZ+ups z&Tcn|bn58nhz{_M7jlxtwF?Q|Rd$~Ke$ftTesZ|8wY4>WSLuxWZinQf#*ZPqOE1jY zn#cU9-Jg-an;B_!T`z5l{i0*|?AEB(wU0TnH?$5jQu5trV{k@T-L50#LR~89^fDmG z?d~11T|-Xlk7_q|2=KdJnVc-}Rh@BG?{Mp2PAMZfBac%W)Hz@6ZBdHulTRE+cZqIq zfgeexevMAqR$GFvCSZC}=FOj~ z7JB;0M$*;GR&undC%3477S`~KzXp9-ko59v5!)ufpBUb1^4Og`noEpM;arKCiwxr6 z6nW*m)Xi$G)5E*>@ZiW}w+1{lsoGLNs?afty9ordkK7)5q)4>%CE@c7>Pf|)b3dx~ zjoHew$7u*Fnc`M6J&S6fCs_%;Jx~F0vGHBvQNo)hb2mqTT`-wH)Z{6#?`jn-k60hDe7AkagoAKTe{cOXk>6tm zceAT^V*HbN#NOE6eD>M$n*Zt8X5CI3r^j4tIRA#na*%!OnEysU;49q#@b!U>WHlj& z-+YIzC6%qbP#8*9CNpB)!THoy9Kg|*>w-ci!EwJ$Fs{D0;?|5Pcj0i2f=5m#@8+~K z88I(1TZnVQsTCcag)t`iZI@Dr@-`kTnNXS^3cpNF$&M7?b`5SAku6s}vVXK*rb82M$sVIZ|48Jx`_D#n!hU}m*-4Xv zt7w&h``DC9A^PDytH<_EqL9m>X>Y2S<9Li4AEv**I42_Ecpp>wkzLz*G-iCFQkGdR zP=s4+{Y8XoYjc^FOVLn)@a^sWl(4c3m6Nln%q#uN6jOXZlBGENT}9WminYq1J)6hB zWLOnhk^>XedufO8ZQ86-s9IzDII^ZfNAIz3AThb#Y)XR!NXI6$(JgN0YZ6Z6WzqAB zdWn)@9GjUVlGR_P1#xuWFB;NR4||tB&6E}pa5w(dt8><%G`?rIxpLWcxB6s$r0Hz) zG}_~ckxc98we)E{|DL=1)NGi?&f-SJf#cknLzuAjxj$pcG9xK|Y@;Q=r6mQ4y%k29$nWml#GL_fl5g0fd z?>YsK=?rNK<~K9Q>f?-wSYz@56ucl|dUZTBIdGl6E63cIqr7mWpj=Tw>Jk`TamtN- zo2G%|ewO>eJO$L~PfifC;B$LQ?3Lv_x5vJRhxX~g%+A?-^oEtDwsu78+#El(`@F|l zkgLZO_e$`8f8O?TE$-Q+0ky_)~UdW0{3(KPOx!<)lo8a%0JtT}~YAQ-n)2a&V~NJx$?? ztip}S-RsH*Bh7Xfkr7p8Y!^PWvX>&XM4|U3Jxo8isI#6Uj>xYxyp}T&MIVTs)CyPA zoQ=NR$PgXd*Yv19QmPWP+Y0GDswzH;pj_A3Nw?NIT8MQ&I!!zKGR25*rD5k}hLyk*xS&vuB;~JD&896i%oPOM|YPcZ`tC=05? z+qM;V^A<>^5dPZIm7Oxw@Nn460!~L=JYyIOB)6_PEhGr^B45Q*MK&OA^)G9tE?Ir<@{% z$~j0^m6s4--`V+Kgp+FD<1BBti~nR$Df=u?DfetoXJ`{&C}N=6;UK%*Y3%S)xTQI&9BNf-Ka0lP*zL83ASn&% zIvfakb8!l|cC({W0^q+K%MmMD81N8?f8YG+1RM)7(%;vYu$P_1N7jg`NlWm?cgvA= zM(nHa5AwZBfnRww2n9y4CBTOu8vlQIY0{s8@CBAVcq$D0uU)LK4`br19kld<)roRzI>COj zd`^vlQ{j@gx^~PLB3s2T49r#S;_Yi(Q`5eLbs(A5F{?ZR6-T00v+mGNh45 zU}p_LK$0tr77qQYfyEgdAPrzh&>4GrWae>J4&}Xf=qwb?x7S%S(jcf4u113F|(#WFH6RFayGS`_v z_*mdbheE%ip~4RAz^YHoN47z#cJW+J~@*`@eXueU}_p`<6TcH49~ z5(0!Nuc_i+abgQ0nZDhuNZVVplG^gMbc>@@CT-KTq|ISrGxKp`V!o|e8nWe41_fOO zb45A5`Ig`dg>l3jCkdmptGPadW?r5NnW>+sR@ zKJS0_+T{NA9Xs-HbgpaTbYE2?NyhW2T(gGZDt8aKLzold(2uB=Mo*24nD!EB4+ZmK zBCKz8hiLi59+_jm^x*aN;dS^yqs0}?5ee$LS|92z_m5&=ekD_Z<_q5Xg3XG4b(myU z7rvj@Mu?)-b5^tMcaLRW+pL)pUGKbOxDwYoO>rFaE;?YX_g$R6>y)s84U>w>&0&vr zZIacKp20<>$RFl*QiRUx#bLdf`kz+KCS!bk5Xj?rTse<=jy@fpkL3q^;ZAZysg}Fk zL}N&#vy)|RR(NRt&J`GGt4CIFF%1k#N~41rQdW+mPZY+gH`M5*CA#nuLU+?w)k4g) zZla$&wWZ6>gZ07aTtqoxkHe*(B5*+<=$h#(=tPJlx?V|E@OX)0 zGrTl2bT>sJ*~}_pyjA^1%>H#@ilNLaiUKl13)ghiOpjg}VKh0v`#fHX!+j+1?DO~( z&6{Lj9;C zRA!8A6Y@>jIWjFi;fZqJu9ogONFuhfe9|f;dIV6*`jTCE!l_Kvv7@Y`%ADEmMXjhO zch~L_`}$lD^$+ho9Mx@k?~ALeyE#QOQnQ8mw11LR-tV#7?X!d^?%%U`Vz|H+$GeXv z1U?hH>YG<4x4z9T-XBGpm;i`Li9cf@wIJitkCKQwK@hZ^5tGAL+ay84$%A^G!lI6t&R z>%ERK+#ZBDy5BF6dd>q2#c*y4dhr1T>E8W!Z{(a!)o4LA&0vSc!B^AL0+2VbI+<$O zcVW;?17BPkfSE|(|rbhay0_u5G<7l8+9^&Kc#Crw!K|O zZ-+x;3_g=VPwBd}KJQ)ZGTOp*ZICWslM#Rz@W41dHUfER8>zf1C&F(p;zNKDNF47v zsjA?!LgoiSgV}IVnP9n-eDA7{40Q>kErHv^<7%N^@(*IgNvez$tR9<0O_%Ub#BoTO z?zZ50=JUKkq1+c1M9^Cmr83vd{az&BxVrqKlAnHE*pNjk#J%3lxr_E^1F*4b$JVSv zs85}S%#6}@F2tGjB0_bRa0hs(Z&@*~#?|^hA=R)V7D^!_{~{{HQBla~juh^tkki+= zm}2X)bo&_&t3{;6FOnu$yMD}KeZ>_Lzk+SCL-^5Vg8xo~tv!si9X;2%x3){X+j^TY0Ad1vDMM^3+QeS8uiI>&2@u)tTceqg4!vjtsGIVyo>+SG6ls~5gDEkjY>aB)>If4X4HaJ| zoIJcgN}T9A@|Ly$O5`wdIV+jM5Us3nHR(wRrIrV3vhVABnT1f<+Sq;1#cgI-b7!1I zi-zD6Y4zg4%+^PN!<`BZpIv(m#B8jXdhS)W3K|O+_SW4fP@#|QBQ}e<9%&NomtJtW z0u#WyjJ7A{uHw%UvR=EUSbeN%_V7_^vBq3$wqK#Zwyq1znx~(?R4pm>!j7xnjkHE$ zqecg_p42)Ixf8zcs83y{?85VwKC5cKa<9Y;u!tw~Uq{OcezKzN(?Q6`#(Zeek>QD7 ztAOdLv7J7Uy(;6{Vl`)3BoDZ}{BOY;tSre$V>_wkGF?y|!+08biHRDLp5_B~U z)X0w5NWoC#mQR#Sv%gKHOZzYhG78O;&t*tcA+xvcg)ld`0mq5oawHlY7-rOSHubzW!UVqA4N zo`fd^_%1~J2E;UWntNlNU6x~0)$Eb>p!A}kPN1Rr9I zi{rjA%WL$G>8V?cXIssKkR;^-x2L<3kxo`tptj)@dpe%!UX|Hz4~*%o`Z^^4-u;y= zBp(dC*td)cTsUH-=dd`v~iO7h7oP2?QJFm6W`^2(`)xL?tHjA4w*R#>B?TDL=lsL_hN3 z7CkV(-u9HFvqHGsWYEVDWZfz`DI9OQiIv_DKLbworQ{J*UNDymj#vV0sz5U8PtxE4xg*8ipWcU!5{U4Nx9fSA&CPH8he_`MF%VvU=`VOK)?Be_jV`=DHU)xi* zwB#T+|Am?_J6bmD;`rSkViVQcVrRfG(~SA~ETyNfRuBk3JbX1I!*jC-!>gTUT;G2q zHgM2DzYhBjmA}stulefR%Puds_wquz{dPiXU&hC(&{B%Fp<1F2 zAD1k4)z<69ZN;L);2dk8?^*ox0s%?Q`~#*FUliwR?F~hc4TuSn`Wt5M864@ zS2u9uyov9^q73R!5EHv*72bo&oisa{tm*ldS^Cns%3EgdDk~_MBL|`yUKq(0@M=3% z=L^0loEh32k@^uE9JXrg=N--%+msC%_AJyEThNduep>W?Mt8iW?Zw|;2m%3 z;=p{ap=S?#OIX=BRMnDGvpC+?KrMTet+~%+&8r(AmNzjQY{-ZGf#j8W9iu$|VD-E; z-<(0TJc5FEm0f*+O_)SZQ!pvrQJWJTz(H1jCX4TY=q)BnW8%2A7g2tuPsnBVhwS4V)(F?(WC8sHUfxY-U))c; zf4~rp`+r9Gdz=NH{myrUX+m63!4w+@M+^zmpC}139f>`1&=0bLmSa0yP^OTRD?PKl ziIrkYfnWmbc^uCH!>|JzZYANJj~KuI89aZ)j2p)M{34d03bdNx20)9UVD>p_=Y^~D zbs!Hg3;^LKWkJgE51aMTQc+o%T2*?$pB&It1Bv2~)XAXibhM=8aX534xjCiumk+g! z2>8U3m>#xTu@obu6muWqq1SBPyDE6=xJqIH*G+vBq&QwA!3BbKf1pvQ%}(>w^HY$R z043@C{QPZ}U|F|F6ja2si25WW21X)a1RqlbzXAd1U$j&Vdd`Aa=Lc|ne-k@~M@J2G znh)Scqn`!y2Hg#Ea%wg(&>vIz0OYr5jjiDWofDC|4TCpU6d?&Z?gC*DO-?xbDu*(cqXHWedLR-g`uXCuk9~S0HqbB#CSdo(g6=IJR4`SE(ZU#$A8!0bzv6;BRabN$ zV`=gsz_+urqt2oyk?+0I@|3^QxTEN>!<{jQOw7C^HN_!A+=XtL)zm73q;~=~)jJ=ou9LUo>kQZe3Y>004> zYFAGgud%F?6vENi<{h(1@NIK0Nw=Tn2G@q^oZ`Q5TPvHV=CN)MAch;|^^MQoRrOeU z-u#m#eX#WznK@nB$ z$tO>gtr$0Oq_)a#glE;N8db86>^E49zl!vw;6&$a@}(Ao>cqJ>zikN*?BVJD%zVak z1%XQ=#g<2J6ZhYedFk9GV zCDQLmr?DLs(H#})gJx;>lR*z8A$rU)w)APOP~B>Zrq08QVPtIzjBfm;D8UDA1z&nq zd9@Ah`#GtqDQ3^%-HQ`ULkm6e;hWo9R(8L*ezMwX9+oJav{L!Y^A|RxCFX%u>T?HOfK7pS#=Em$t!A{$g#B(h@IDU~kkUXw72QtTQPHya@o ze&n8zoMX1^d%IS{_KO9HOH`Io5TDi7XpEfN;sAa2JIm3jiX&6{OIHD88h)A*s{kq2 z>Vw$ogYF>r?Yh@Qsf5sPcam5T_NF&YDe<9mj}|1hhn1T)JWU9=>}EW2yb> zR|Bo|hbUnt0F2)Dw@K+5+NcNRATFkYh2~C!-A@3=2mnsMJUv(dK{y_K7lv_ezx@&G zQ{i1E<;X&(C_V;llW&FU!wbG-{usy*b9xpS>3ptW+tq!fa+xh=x+7wYa|MNtM|vaFbIf z7c8)>E}%EnnBYs&jRW`>Aw>g|&(*d>TYPg3(5Bocz#YB$ar@xciJp72IT^qF9LU3LmJ6JFho__Fe4_l;*^wN(p^pUT-;IaY z$MdYj4wRcosa2;4uPKa-Uz2r>rf}$0%wD=MBp!EV8pK1-DMC=etA{R;gOnxZftk28 zfuzM!Xn2*dJbc6AX5!j<;0&Lm^;>;8;60`AwwNg&Xg|+y%(mNDE;u%m>J8;}?P$-Q zEuZVTY_H&$IaYopgTW~6XW3AJv3Z5@sitg~bFP~kCpupvVvlch;0>q=yf9U*^TMn+ z+(Ca%LswAbDkx&|O(X*Sfc9S#0!|pg-Q& z$go#N2fUA`F0nF1rz!|M*)a{zzIWZq{QG;Xxx7DBbDy$AuxPvGi=!(-mW&t~W^K@( zi?qaJh2btS9SXDuSvX&R9kKrPcYxeVU7Y-=C4rMQ-EYodcqz`?a^rns|4`$hTAR}x zm}vFd!QpX<6++Jt{ml($K4I$L56Z7;h!%zpV*~D}k8R}h#bT@2$?M7R z^ZIHRsM8GOJ}gd)YuO2sO;0kw==03s4^@hzY#>`Kk0P zumaC1+y#QIFSI|0KH*?^+IOFNVfW}5MN|1NZvpt>G6oC{V!bC|s}_OdQWFL62MM&} zCO2?f%>fYx0IBQ)fg{xpG&lz!)B9V158%*x-UE?D8Ia^Z28r?W0gW>;nP%V{TtLO& zpZv$eTkcQk8XGreU4STp73wXhum8Esz?~%`A~JpeJ&|*K?}JYkvzCO-!Rn3}5{mUuRQcE}- z<@%AbMrcrFQK!GIbzUwZ7xV6jQKN^}cs^(1+#&F#u*)7SQ9Q+xUZa`gCc@5HfY=|<$$9@%Aw&oz!tO;1^E zC>Bzg%$NFQN{bjY6j&zYSO-cR){)2vosJjJ3ygE4OT%BGwFJF$TCBdgsz2&aUcIJG zt~p>4IN0tX*D|QiQL(#IIofEfF+PIQG_dgX18r^5P7`i}S^@<4QO{`yYx+EUD=@u42~L1(Y3Q=S(lsY+-X1NW>6CN^s z3%7F3ZLCZwdZ`XNWsp6b$i{JpSUAQNeYnC(u6=ZhJYU=zUd1Ufv!1Ip zchJXInJi~M7`SBkusa=MAv&fc`zoecgVVbBk>uwTp$riHzRTS7XHS39E-@#Yp?47F zD43=@A~a*dTby6jzlnSh-^VT_StTNxqlvhQv9#3jEHx1t*zGY&lls=uUy^-~?@_(@ zbr4Yw5cuNmSbmLgS6{Gdb`Kn0sT_NbFbY>RVP=?N*v1LTRV8t-ZlF{%q&2DRv0*b2 zbLcW>j&#&Q{*lbgsZZ}#nWt6>D=WI|_5q0OO5=8{$(p5|ipqMs1 zvz%l2&Na;AjI@a+4L?y^N9F=|WBP9%ckWSgF-LN?TYBYRp&;GQKR0>HU0{(LGf$-H z@qP9(QPa|pZMCCX2f5899i6(`XM`m9$Iozne!oFF`>Lh0_3h9Q;^CV+)L*T~+p3=b ziR3G>o$>-VML$n{A_UcX)-n($%2)hA)dXFK$gt4n9|E1xyxkGo_va1J7A zPSq<8BK$n%NzDo+q)zEJeW04pz`{JVE&Q8|UOJe?cm)V&bydL~&|C1k3iiK%`2QHl z{|P(sZw8@s7l?|EzGsf(iD%f$H6nchi+exoYmbkQLGoCG6zU75ngLuJAN^(AE^SI9 ztF8yHLr*05-X*k%VUZn_k%cxY3P=7j0sjKw|M#sfsLxxT(aL}h-k1YgB4{j37<8x< zbvp|PIIe=^N)1g*0_s45?CK|h2smWEv+@lC7ZzjLZvfN%+HY=xDPf0X+CU&b^*zW%A)>3?~E zWK)5mD!1~|46MzM0VX<_VQO;9pPB)93%^U7Kmq69KW&eMGe;f0H;*BoIH~gXQ zFMvn%A12rT+g4E~3`OISidA%M9`dh3_kY{)Ab<6LNX|?tNQKI=!iCP665^YkWbX2=ats+bf#^TmRq^Q({AlZL2f{vIo&fdxK2+ zUqAkF@8o~-E+Y+$jg1YQbg=|2rNk|li%Uvgd?@n1%BTnvcCpv#o5h*C*MU1|1~kJ0 zvk4B!Ai;YUaFJkZ`;OZAU|N;qm*?UhIv2o2UQm$oSq%N;grN5iTJYy}?O+dVXA>Df zQ>62%nL>T-nA3#iI4d~xVcwgn03NT7pf{wiO57fJ=m?@qNEcW_EU&YDzCP575O!&* zGEg-53uICQncPmJ_qH-hUr62#18tG1@%##={A*bm51bcxF-XWw z7ejW%3ck*e?P$q`pp3B3OewmX-g0P&B*e}2eaJ8c-4tK1FT`Cg-~ z)8{@h2g#p(l`FG-#UH-R2f+UASr z=|x3kGJDjFe&N)#I@}~3*Lapo>S3q%HB2O%P0C9@@F$04zHtfxe$AVLg~~$>Z>P-> zR}e2zBBsPhJ6W?Uzg8{iRO{yCux05~(;(2Izw~X>*JUy3PZ1ee>xN^=i9+vCh!Q|Y^LW;5Whr{n{D}xj6M>A_o7xTI8h{F>l@C1tFT%7S;Bu; zQsH(U{QjlinkRqm-_g~J1o&Y;bMFtF1#ld<#f_zVY(Zta?cnqoC{EubunRw&1YyUz=Pr>x4vXhwgVCk4+9Eiu zY{zTzc#ad?^xJox z+cQu1ggGY{j9?-^=^_?xaywH%v(@?qqYSF z%#hjE9`eXa9H$%1N@IDFk>!&eh#h+bn!*udTd#^J#QC45-5u-ZM7r%nei+{D+X-6U z{Ml@v_S)yRi53k;pZ@YtuU;DozePGG82{^(BIPAg!yj}n!^1q8@_%-(#G@9CrP2|R zgQ8~Za0!HC4BbiS(<=MQbXiR~1KJ73_|{ma^h~Gu_Gl%yWtHm0U~jD$N_Y-fQLrL6 zqC53()2XMowdB4wxfe$tYo!r*M6jOMshXN%y6oVfJvf2Lt))nr8xfz&P2K?66B7s)51T}=bokr8ii-P6dL`^id~7NMYl?l~y9h6k;Pvr*G_dAR z@SiMU^x`dk@boB>oesLIBDQWWN>A^PMaOV{rI z2xB6#?09%D?Q`QOCNx2qmD$P(%~l~7lG!qDC#Zi|{&fG*%b>h(({D2nmCg_npiEV! zd*;TCet7lQHnQyKnCDx;Ieiz9AMvcX(W5xOci62l+jsb0ys+(-!=NRftDc_I&fZzw z`mj1!$vhNIbf)j=wPq~>hd1fwJD%^pdu4g?M5GPOWx0bhTM4o`sMhEkAv2E&Sjz9Fwv7D$vk}4iF z9`1Z?!EH5Y{kv&7I5==S+HLu9-|G7xUv?M>G0cLgIDfg9}n+I?)<-)ugZ!HjF z-9OzcARz*YeINu!cdU5T!HsD+*W~ZxKu;54t3&xS*qSgnO(f6t_PmhOI`)LJu*34l zbZ}tk>gsE9ZE#K~)@4501e~$9SO(6;`7oKEtA$;PR6>pxN4skaU5WhtVAQ+to53

97gO%Z#?@a&uPd0>vMbp&=qWrHc7Pq30kFShGbS~)_he(n5&IS z=Z1UXZ^KHcKe8Kz%?9mo{ziRK0BmD04*vka;J@lXQ_Lp(+sNAy?VZ)*kn@&NiRa3> zIapzjtB*DE(RF=(bfHGd(Z(^LnCJIHg{?Axr*l}Jl6KD<2OQwY)<6s%a7kz9F6rFA z8LAl>2~;%=nI?}+KL(2UfDeKE#(hKad9s2 zq>}QTCN#W83-EVtz;{Hnfi0*pBPHDuHNI!3(IHGe`x~uHZZ78^3{hZxJ@ZLUE74;q z2l(p8(e`3L`uvk4cgcvald;~)`v!CPRn*GpxsVbvK@03mjbgp}=x`zJ`ctL&i+REq*=#Qgrv`XRec`F_%A>GLF<_dw$p@)8AfFQ& zF8jpo(;CL$Ht9a^y@%cFc|yS;=BoVCFOcZn#q$rNoPiZJidY;T9Rpuf0f7``o;^iB HHunE-Q(enV literal 20314 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 literal 21227 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 z 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 Ab^rhX diff --git a/docs/source/images/processing_provider_project_from_osm.png b/docs/source/images/processing_provider_project_from_osm.png index 520073b35fe5ec67305f28fb7ea359c36b89ec69..81221f23e946b087373f7ce5d21dc886b0987059 100644 GIT binary patch literal 14024 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 SSR#NQ(3#VAr^-%v-}xWSz|b)O diff --git a/docs/source/images/processing_provider_save_matrix_in_existing_file.png b/docs/source/images/processing_provider_save_matrix_in_existing_file.png index 3fb0d1f813bc86ae69b510e07dd65add392bde82..29ebd9735d38165f48fa6c2a9a5d2934eba706af 100644 GIT binary patch literal 20895 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 KMNUMnLSTZvD4$dS literal 25082 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 L3gU&LZ{Ghe#EQoG literal 16565 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 diff --git a/docs/source/images/processing_provider_transit_assignment.png b/docs/source/images/processing_provider_transit_assignment.png index ec9ee7a6832fdb8e9426c0d901a4e6fe11491d06..f4065e35b7e7c62731f2f53cbcf8e37143323166 100644 GIT binary patch literal 14823 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 literal 16258 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 ZcaQKP_}0;G;6Om9PCA?@w(`3DzW@S

je()$ZA^oP(&pZ=mgvl+}mf+k640lm|J_O*xCUKm7HA&ke$9CVz3h3d|?c3ct% zg^(w;6*R;V7!fHS43o6agGXh0q}7e>Q^Ox%zhe2V$IBd6!jwcxK@(<@bdW4@Fc(e8 dB$(*%Y_O^A`?r_X`XF?G;F5}ua~|n>{||Q>p6~zw literal 18459 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 diff --git a/docs/source/images/processing_provider_create_transit_graph.png b/docs/source/images/processing_provider_create_transit_graph.png index 689497bd29e97068b6fa2a7bca5f8965ac21d308..c326f6cd55caf2f4c791de20b9b03beeda71f4c0 100644 GIT binary patch literal 15770 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 XmpTHj{lzgrt&r?Pr3Xd#jh_EMqgM7` literal 18441 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 VXBQt-n}YsbziM=)=(7FO{{fRi7dZd` diff --git a/docs/source/images/processing_provider_export_matrices.png b/docs/source/images/processing_provider_export_matrices.png index 71bf98bf33e9e2110c9dfea1605d264d492dd14e..20f3a88ce7b616c5a686448f48eca2044d80253a 100644 GIT binary patch literal 13713 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 literal 15418 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 diff --git a/docs/source/images/processing_provider_import_gtfs.png b/docs/source/images/processing_provider_import_gtfs.png index c699629f8c6435d7b7f476916c1b9e8e9ec30858..42c4ca32266bcad83d3e53d2ce13188c51e5a64a 100644 GIT binary patch literal 15236 zcmd^mcT|(xw(o~QLJcS)D4{3_2ntA7x~TNtRHP_PdZhP&6bn+M3P@3U5fG3Lp{R6F zLJ!4AF9D^5p1d!*_dffc`_8!Uyz#~xZ@l{lnyjok*POrkn{%!8Oh-$Zj`}P$004BV zDmU~1;8-R2r%rhcEJ=P9s|fx_=BB579VqF8FM(gkZ51`a!uQcMhxdDEPciaHr zq&w-4Y|4hi8!SBOe)G1wzKe~!*L_!OK-tyW+S%=)i@TX2CD`QJf$9xK18+0jq(hnM zT)_0tBMFy{T$k7p)w2`#;#GO5&w22QrfH3zvHhGZ=7j#-OGbN{EjsSA_c6N()w0wX z^`2f0IDKVnBGC5oiz(-l3c32RN6vLDV=C7<8Eyx~C@2TLXM0V^==L41NdGV_w=(8e z+PLF`-w{n|t4PPxb=)ORk12oa^ILD+S*u@f+U%1yF1c5Wz_xbA@g^lE!r)RrJ~C>r zX0VtaEgO6J%zlBbPNVuODn6IqJ1`9V>2N)8jQAD8_&M=Or3`-5vZA8m35@NU>ud*& zP{R*d+~MA4X(Rq_`-Kou+ddVZ7zAQ%qE`?(+~>-K$p0p&OCWj5h~{od^fZX`GM`=8Ws^T4fzwebxaS3WwlTYr@~ac%65G%ElUyYj^;EkaIp%QT|$yeM|>@2J<_Ki`AhBG)4qPHP2jI@A+-7i?kjhJ0S_6UNr z%&Kyptkcia#z3OoyJBSX-v=Dvow46qbBvv*4_Pz(b~Cz5+4>LH=jOUS73#O}D=T<{ zvgm$f0C5OE{3;^@wNg^Qs@Pd#T5mNtTJtCicloNv@?hi6lmop;3HtSQm?korHd$Y4 zWu&y)az@kH$snl?NenzFTdV7qvGt3&lD09#KJAfo=_hj{vKs)L;uttfr#U$cJQLqB zz|!~o_A%^D%cZEjP4lsz(n&(bhdG~&&4_EZ9E32G@8W{|L5EP|;dn(=_47fA0!Do1 z$3x|GO_LIgK~nh|HuGvN%f)KE#f?J~GhGZe(-}!+ABf7pWaEeu1;h_N?|Y_o##<}N z042s7!Qq_>#SE|}pKtoey>Esa4(kJxxwd;bGu;uaLPAbW8~B@OxAk=S{cdPUthsi; z!a1})kKqmK`)vr$xD`1WPIzUuD{+k%#}4aRuaO0S7f)%(d*gz4ch^gnPQ%tF{U+bB z%5kISwVkiXCK0jgQ~MMBsDK3*(<$HX@;>Oa3}WRnse-4_q~&~k^7ly@_^T@U=}Jvl zjPBJ_xl*-=Z+YZrMBMI0_lH6BiJ{3n=Dqw&Um0=jEV*dYH>oxfFT+!39z@b6v)?b# zSHawC&_HuNH`iaOxrUP`bL+KX^fF5}@>$PS-WBa;o)I)uK_OWvZ_V8!M5;)S(gDIJ zc~0k7yH{9oIya(Lc%eJJgy>Y%Pode7xalbi-$eR%_3kV3eg`j+jSYy&4R!Nc*SUcs z?Zbj(QNJxYQC`lQ9Zb3;nW(+0(h%sEbkcY2(Lg7bUSAvAdKEs%jn1DD?2JdC@wHUt z(Um#pQd1p%2o1#q8b9iFwkh}Dmey>0cX=Hhc4T>->_ck}t}Z zXw_@kQKFadJDr-z-KRzP^ANTt<`5PjzUAD%MX8^0FVBJ8qew$7?V_KeZoJ|C$y1_=vYMrXswVr^gVW|P zCxLqNGaio=UuoIJ+m464*vfZHBIIV*YZ0k-rE8>J>FyitsfS_;Wzdyr8x_38qtV6hgQ?P)fwkr(;$Qw zH(m9+9x>+mv)932P0k-W1q>{iXT$4KV*{)6emn`i_evgZ$_rRX@ne$}7#1nTaf6C$E+P1Tz<%D8EKDpU@R6lQVRI z=Ajy*G-0SWmGz;J`y;1}L7m9TAW{x=Wx$_~O!?2HPfD62*Gn}6oFWglpOq5v1IZ91 zYG+uUFkU)Qxz>jK*|FZA0bA(`joG&~vE=021AveAr(hp9Ha4pJ!uy;nRi;`b?`Ku|m_Cs-jUo&g2`3N1-gPylGI4mkMrfm2xubSlRW(?DOTqwwo< zDCuL_5y8Yz${X}o3I`kb15z7KTV%0CG}!hd7pc2rtz-be_p9gs^zn9u4ILKjcXoFc z{P&c9t&i00+qXwiNTSBTECn+&GmZ|TGU9CUcubyRTdv7Q)3!fd7N4Ka4Jk+=ijmD~ zg*7?>&tiA7jzsA-Uh!ZpFjXFrt-=24PF`t%E9m79Rtj&{T zTH32KO#uh1GZbH-NwlFj{&R4P2Pa^@+>!_LsV?JhWiPqjY9$k92!&+QfK4c&&Gzll zOhMN|L)cHig2;a`pA1%Oql4zH)#T1h)S&TIx3s)^+45Ffg211}ROHIuooprJ8UE51 zTr@20vRY|W`|fLaNL$9ywmEV2zMn8lD8%AbD?-?7ha-MM))v|xT;EJ#yxldgjp>Xs zHN5iuU~Ar(KO;0TqoyI^?$e>Ss!}x`rZb2iie9`f#NO$KqiosHM@kFfY<2yC@n61L z`u5=@JMK>|(n&5hv3iawifhm6_g;P8-jY9_w|vRQ4iXCC^eG4raUL?~_a!MvV4=_b>aJYk!PPvs|VH%IW@-}Kze(5u2!J3gbCRXi;;#4t-$ z>UPEaeoGj{gsO4j}(8MOQIPB*y&&2aNsj_GxMZ zZk=}xdFNFP&cT7UK`HodKuMZretyExX4}A0xX#Dr@T_ z8VOl zClKP7?2ybS2;fEXE~4yYeQsc2mEGhEN14(-FN{$IB4*u0ceuOI*$5;QkJVk=*{K6Ajw(YM~wn33R2!bEcc>Mf{L@dv=j&NfCp~E z6K6Nrox|2T7i<|@)0bWP>xUe(yxCE0uEyC3LW7jX);&HBw;Y71E%QNnp+8SwMf6Cn zUO&32bmnqj0oyyr(b~QKOFgb0r(V<7e4`XI4mBBY?rdGDvX@GW1~EIMD7#FEQaEYt zx?v%O`s5C+j4VTqa@Fd>IUDgGCh4@|-P{r^I9^-^t-uHd)#bim75s(lA z!w=P?#^PBe)yN`8g=t za^L5=riW+aSUL5cR_i-K)0etvQ#aqXs68%c-y#1O7r?P74m%Y^e`{CFNX_dK&z!So zPxpVT(a8)bp&04Smk!pwYiJtbpe;mk8dhjv4*Prpo2l$tq4y3YdGD9)is7DwXd}l3 z(28V&LkMI;)ivhQ_v+#$DwNpcTc=_1-wpZZ8m|mfLSg09p_#H+H!l@vk;)@X@H^lEf8lwuzp1eVneNBIApKFmU!w|^Q$v? zpcJKB$%3AN5S#+S>#rJD|78KIzf>6%5SE~XDx3lwcTPW1skX<;H+AemXAr>uC>+ zQ+*!>@@^uoifd;wf70utr^Pnt1bqqBO!uU8#P5vPiP>7;W;$pHtxvrBHZJsRt-+@bSzU@R?a79QDCR(``xPWsA2B|ofYc^4 zbqpm_o_EH0Oh}hI`|V;MWc2Y*mH*&}ZhUz#ls32>JzFSq`3dB}sdguzzNkeJ6K{tu z=&ouHoYmo*64b-SXb%7=%PHJy#@a-YrYYwvnIrSf@u>x!M>CugR;@R>W9aTShe3kc+C+EE+WYp!l zovwLj(Lkq^i34fXgQ5O>aoX?I*ur{yp-{8v6z6g0H}cai5S6~5*5E+H?rtd|z2%$? zRJoyTfpTM)lk%>nLsf>)By+o%{@|gm+p>i=k^_yPmR=aKk^He>?D#;dG+C=&!_HI4 z&{nKpE7FS2ukPgf;dAMm$@1Ak%~@4CwiUgx{!UBw0?9=Kw(s>@O@5SMoSeOSqI%_> z@*ZU5$xmxh_Qjf8$<-d`qJ`#avEE7cV%&JMVSb^q!tiki1rt)W>P<4&pt)gB?s(X~ z5cl|}wFW>>>=hyg6;WaT4V5;Dky-revbkJ0%X3f^3SYjPD>hc)%%S^U!l8SkOBeM< z=p0vGL_<<0F5|sx(;FL`!#Dmm5^a(DsqvET{6f>c^b%C_1?ev|Xm}26w`}=6InYkL z;}>#hTuqY0rB??m$3uplrJmX}%~V5Q^8EnpX}RGYMYkI}MVCLof3B4jsykmV>td2c zbG)dl!k|4)-}+GZVF1sZl5W9>tmK?GJM^5(*>?*~No0d6EjLWPm%lqw!kH>|Xv#Od znv1%aqogb^A+7gnMpk>o1$2pMe1_uvI5O4@1VbPLLnH#o{LI-J-0-Z?_5SqNy`sBx z#`syJQ^}T~m&rbt83xA?Md4>7-#koX&!6%3dCZwA#>TzEGtRO7)pgSmCR0Z*S}I!) zTi@LMPJdjM&{|h@PIgU#Us-)8b?3|!zc{xOk^}WFK0Wn(+5oTlwn0Vqq0G>lubspj z_e94h4S7tK_)apQ(gMJ8`k$~}e`rV7gA@w`vk1rnC!oue!53!x(QdcadhbLL-L~2?dpz# zy6Li-C&oiZFR)ZY_VrnI;}@Jq4$D_Rc_YtVkx_5zFp+o&!lJTV>@2bRSkSX8Pqkq| zSGX>o>k)=1NdYl(tz@y-0K}KOVj#l3A_r*>H5O3VC*dH-IY9>7TqqHR&D>Z|A)9%# z#0!mU7h!hr?0zz_ zw%53bl$@?w(TcLFWQAq7r$d24gJH+LHFGnbqZqbTvy?5`^YBFx0qZN;(19+3hlq4O ze?Cq`cI<5#?`{h2Vd^r6vqSXNH|)J*IVsf%C974rwkFAfLwb`XIY#b{%x!qC05F=! zGPqNbv#ESURmG+u)uEm>s5_}Qgyv1CGhV-N;3-bzNnLd?=Au@f-LpBZ-?(>Pj$^9gj z6yJhA@K!;&je6eTF2|PIFa-v79$s^|aI7CT%VC!HT~jota`cT+E#X^HDi^wu9rf;3 z#HJDkNLhPr~>u#SjCQ^Uj}r zx~;Y<(%<{amdmb{G6!!49W_f%SIXryy&2TBz#Udcb*cQ9NCsf{Z_C;7z2Feyq|68l zGK>Hnc|5;EmAhIbvf8*@Vl?r$v;VV?>7|5Xx~dDHoBmsSfnRI*t>?{rhQp3a@yAdT z0@yoe_ zt^JT7Q2U3wV4gxCVBN5jgkO4yHvn|FFWfUbfe+9Xla%DGRh;5~Z)F%mOHQIP&Qc5; zd6m`jSYUw1CA`i`7y&LxZ3T=tZ$T2@Qa8 z@Y~`(gs|w)*W6k9gWs$OObhdaksseXFiA6+8x!#XZPLi)fa{fHJ}~&Sla!!_x&fKA zeLw~xh1zfS6wLqAXU;4oy=y%1W@-M~ojpmXw9~Hk`lY1(0@aCAtsdK4^z){`lMv1m zQe)buJ_;eNA}_gj8$J}a*P^!2BT+eAc*ywrQV7B#qVCOu;7A~WsznSO3oxgXZQVMj$_N?OltBE z5SyB9M0*}U;lytN#>6&mRgr}Q%^jrK{<9Q8W%&=x^IvU4{BT>##KgqvYB4QY zkoFWU4Gj%m^Q*}3xpQ_}JbLu=JYet=AuKQNGR=Hbq!LU+r=9=a!S90`H5K_SN`)rT zvIVjr{*A=4b(&~y$WO&mZbXM`ebTMp>h?bcHE>7g|1^q)=zT`e(*B|1S{HxFuQFkQ zMMiK_f1AizVu)GixP=LcR{zcFQ2)v5z?dU6B@{wM0gB{ZK4?rA#R=cVCj95w1e>q@hdDR6&UMXw z`CQO9_<8wO@IL{;!p26q>{DJ4NvM9u55En6Z)2|d7ry+h6g=FUA=79w{oof0_DUvOg{6#}Dwuo)j#lJZR!eNllHL z;B-m2UCysU@%RrN+tVM%WFP>$I7uZ_5f&-Z)^8&KfQw{||Ep^BFRd9wn`<{6@{(2+ zToQ9fQZC&%s6p2GxEBY6uy&UO;Nhb@;!vkk{`}W)g49 z;L=|;3X^LrJ-KGIS{~4%*LWXst2Vk=$#?Kr>9qX0Aj4nHeWf}a%9OiGw)V4f8T@j5 zY}AbHjc4lP?J83Dm8(Yksv$nn<0$W20Vl?|doOPoL2jFpkm7{DYYel8Y3gPD!nWkX z=7mSCnw0n}MiadmncjA788g0@SgAWGnwLqi`2wUCm;g0%!Ja_OP4baDEJNA6qnf8{ zujb~t4n22syu`^06tRHXBr<@A`H*vGr;%VFXN}t$c6@wS=hD#BUGe;JvukBp{8pzD zeTvGf?y}_qLrJ`JKoN}8s16Ymz{xqRrCC6Dp6vX*q<4y3^jmHOLK3C^ihZnweI@<5 z=;?W@i!B*Yi*3+L>5kJwXB70V%gZyy%vnJ!#7PjU2ZK&Qp+`4D0<(?>y(E?J%)~)} zI1-}&8G`;Z5U8OMKSnL1$Fh7udztx#J11e>Ea1i$KOmX+3f98e+1b<6C>*e$oDHie zE3+_HIP)Lzf%au+$ljjM!P$X7@b`wdA3MNu-e+%gB5p)uqpaY}_9UwUfXMy1G+)oj}7Pz~dieQ}10Zxtz)cYe)cT^ZaV1R-g@qe?6 zhm!D~zP|BIpqZhwyS*t~?Dt~IGRO4Ensq=%*q!>1QqEcJf*amvjs=~IVb=P?^Z7~v zzoq-9%lh}NBqaT^W+~1+_pQ0)%mbT3^d0F&tLUK0-+l*DkgioN!tYU~nr1KZ4r|mq zk*##4S~(>-?!B9UbQtod!Y}zJwkf_L-}iW@ zax2xKARJ9mw4d!`nvhs4G%{qOt(Er3zAMd;jhYR{f3W>>&iq|vuW0FN53F1whJ^ao zx3LOV7u1q?+h`ZqmTSCc3sQ}Wod<;4mWu{;MIG~OtOxKI_KJ_|U!*mzouE53)5zIJb{nA`t8CCWRlA%A4>Oh(F)kHPi z@^R}5D-ynJes^@JN4L?pFy)o_Vc`88KBpW4*2zwy5^D4%51;r2YkJc~HgVGQvq#yL zBwSPC0Z!!d>Q5dF`x|L>P0stEHg)l}1`qNdOnT#wYKqJVF?yHo5yYx1?t&asX)ak2 zb$+D6)3<1ZE34e_epGb`@2Wumv-Ou;Zv74}O=DZ#+f*JdHZ~IStEG2SzxK9%agKV&i4>ONS2+-@WxXgD*> zK(#M_ptv!e5IR*>3OaGm9yzNoSt$)L(f6MS%N8JpjijpkH2sgOz3-WeN_gN zh(?U0fxwI-NCCm1fc9mB|Ehxu$#;MhgC<3m384LSc-YY3^N-T&gm|^kq;mkvF&`{> zr@|lH9AE)crT?|A{2en({iH_gz1G1iF%I-Hp%9Hrq%^7rJv5e<5*k!Gi9qcBzy{ED zh}8qY-7m86LDCt|2QWzffiW_s%Og{8se1wmEC$Fy{lm*#Xpds6cVCLNV}t>fg?>`s z+Nl*R#IOpv0gFl;`vn>M1v}G7b6EQ|_$AF!QxI?Ifnv4EHbpklInTq^7A1Pw!6kRO z?E>xOHetAmY$CScP7(%qx2)bJvK6u1uW#r-E9T;E|5;Gntu>$l z7Eml#D4g5$R!cUGjaeJ}u5NGMF(u{XnoxU=CUxE*V`6LfmyHj;rg9gg-Sq_|FR~}! z`2^z(_;aPgtu4~)4V!5BBeeWpoc!KrR+o5r35Eo$g=*e0Lv)UlpNy{#bDg6Cle@mB zsIvi`b!1n-jX>%Tm!?(Nte?!yIVZ^X+Tw*=zNcB)@YiczMbPDyRa~last=Y&Jz(_m zyOU>{o4>hC5!0}S4dM_0fu>JPis3j)tMjZ$Z6jiToRgldf!@m+b(x-jGs?q zs5kG``aI32a_5Y$tKmo%+Gm1At7|zcmAJ$ChQ0y0w-20#6Xz1L0+r0K-_kOc5fVQ0 zrx;Jcm>&(94{aAPf>K;=4St6#QD(DA__A%qCJ3LMc=#ozv_&p~u1%gc{Kg!= zomZ_E3a9pA<V|$ONB)x)N&FGnr*=a9w|rFXAGF!sc-5$ zI*31umGiAzGEknXnit|uq1uyUukSjdR4S_JLoiBSkhYXKhoa?@Dgd)|Yk{Wi&v)KN zM=TuYQQAQ?gJ+!0I&F$+!f-L>Q(8d&z#nEKP6w6tTB}sv?jrFyEo$O(s}xfPFdohf z{$rcKWE(nHQ#Kp|us|o<$mERxkg5SoE9|gk2AJ^szuWEKk2L<|lR4l4CwQ@qgeat= z5AbV@1$d6~3nBmQ=u|BZ(TpUgYF;Lh$A6z){ZmHazflMAxmXJj2l4srVBqXc3KUa9 zLn2uvPyRvY|4gm^%Xsa-k*xk7lmW%V|1*DR-3(^JKPUci-{7p3l=m6n^DFQx&$_b31JaeN6wuWI!skFe1W3tT0HFSr zb^#Q?^f~zDZ{`0NKAvxFX>DyK939vK!0oW?(942?@+DHE9!xsBKo z5TGubRLT7O$jD3v-2TAL(IHt^Rpygz^_-rkc?q4DIvWDoU0XOEksN5|=iO^QEz$qp zvYqhgK}YX6res76KH=6ci?2Nfl-c)!cf(reuevXSfm!%OaU+hDfodi{2M2u+z_)l3 z7AQqVT6rkQ=uY)zU>3!)AeSH8&ZrTDAb&6xcf`N}Mk@7wsY68VnhaU?}hOCb$ZPih*6 zR6$qfq*(B) z@e+Eh-34{@vjX4Db%eJJGI4%M1s*%YPVa9fY}2%a%Kb6$@yE|OIIK*^iVJsvOs~t~ zAzr74i@v+iUou>(=yN^AxAXLyPQ0HlnBM#xU$nDqOQksHWeH~6*gUWb)C&nsjrmOr z<|vEkl1s(rC{ELAdBR&cgRB9(uR)T1(M$j2;!Up;gxKHn{K?IP+EAt-@KTMz2{z}2 zbxd1ZHaHu8yxI{B-rgJ#70NNI4>;P#xFA=LC!aH)bVTD53vLnwTVe^M{iYlWgY1>; zZ;;1exWS8!Iy%g-*?N1w7_nMS(iO+!;EbAz0v(QZIKf2Vj-zEQa>f8)^zP_j2LtMm z?^gaPExUWa)pVk`X~`Khu4GcKlH)P}6n!~7JpBIs?PbUGg>=8QkIxwO8N6I3O;J*Xcoiyu8wjbruSU&_PLCF#uggJa2v|7;-#v-U~S zAF6T5uX%;}J+#>sFx+S0*W5b@x*FpxA<#J+oRc5V0^RfvO^g^^Wn#De**QrE7mTQ` zwuJ#dse9b`hi<~T*Wg`De3k5AjRG1xI1}B>`sZqsNaB(FYnDH10ocszb0Mku;Fy{O zUK)#U8dAG0T7^R<^i5 z`c^1p%m7;I%}c;97ZLHHvJcUmTHMul_P*`=9?KG`Km#JEW*KtCcTrOdZV?T zGxrPqHh^&+(q#M~J2;_zmu{gzjAwMrgpH}x?SjvrFuskA9_L)f1cheL+3)5?QbNlM zU}oa!M+4x+FyzsYF>>h+=B2(8(`3lV?u`RH&hI1F6HkSOt}bYjJQ?xQz}h|3r%DXN z>!P)_yAtL*e3>Qv2H}%mx3ABkf^YEUuk>+7E#H79*Su$<%PQ!KC zbXyhG@JJgX&QFd^f-hL)_Byo*FL~&$Rzj{B8_CriQY}XG^gVFN{$e-2@33TcX+0KK z-q4OZjx<>}@XSp+duf|}WO~Rv1XVG1cW1G)#craGDUj=N)W9zFayqCYs*UljdwtDp z2dyrLpP8e^LX_uZH}enC>taqv+cayMIXoY3lGfo~`sn4>ftdHt+NQ&~htnlkj0hfg zCJUP?aUR~0d(GRhYvWBkeJZ2jx%U^pvR2Ca2w3_WRBp}Z8!C=(8I3#T@UC=e4Swtv zLS1^Vpwi}P=bD;8FNi!wxU+imw6vy4Q}~YFr-_)9)p;99zAc{QfzxaEXKi;RPMVgS zGk3&r8j)mWjFV@N<<$f`DxT2 zcTM%cW|~AsFf|C%p_k|jnC+J4?)>y*%MN!LZwU?gW;PfJ-EqMT4A8g23$4evMe`cE z)=#v&0WZ1Z%!Xt^4XCM5X(Qrj1+ykB$FE=RiK0=;d3-i%`Mjx_i8Bk~e$u%t=km&4 zpL(Hc-)KrYBFUt)%>;#nFd<}jQ_Si;eLKaj>EolTSKM)~(RS4e&TcGNg~olgQkBi| zODI!KOygyT>5`DIf7s?xfkyJaN=M*%?$syP_iUByr4C-HjE|W4Imvz7F1l)_Em3%D zqj#u^@FrhQw|`bbfa4y4{4l~jX~s0SkrtUUeR}Fms=w0|R&zVLCo*wlJn^dEl-}W7 zpb7btw_oDq7aZGHGmMrb&)0-GiF+B8u605lrVgru*#9or#2_K?Yb8hWvU@K3m9*UZ zDIzTy^VKGtq#a&%xFuEURO;!SV+)`zbX2QVI)XPfM1T7#`hsOR-L{WuLy z=(jIZFg=6pktbjBavI-@cZ@$b1e)lI7NH2iF6 zn~Iy0FkE#Lc-JdE^s;((+;6$`jk_unW4Y7ndJ@X*lgkYR&75>Bdxc@`8?nQTOF_Y+ z+ZzMTmk)c#KOieC=m&N4vZ6ec?i{oui+Og@&($gVCLO_@Ur8WF8I)eziK3e>$*H#9 z{k`>15uDGIh#fqSNOt1vn%tHV9c^Kg~#Wl+^POtC*AZj=00 z&OgM}OZ7`GJPn_ZpKlH3h8=OGe(ZDtL8H^>SeD+-ELo-Ia*n@ozaWow?Rqvyi(o8AX<*|~0YZ7h%EC}>yU73G9AlEZ_s%kWL>O=pPJwscupfW8sD7y$qpzn?Pb{0`tK!2%g7 z3V&Dd7uV&ukThwpCc^$o6-b^ngrAYud*YVCw}R{73&bk$y`x6iLIyIBNH|K%OZQy{ zUpxLP1nX(bAGt4pu3y@7RSHRHz)^tD5>;D+ZXBbcNCTfu%53(CLh0EnxxmMS=T%vx z{CCU9L;Aq?m5BYVCGd408~EbUZ~7pe4J4$DGvJHMlMp=kIBj|GBG{hU-2dm^LWaE0 z#w=P}z7ed>r5vSV^ljQ4e6Zo8w{`)dvXlgHUQuWbf~yHHzLxbH_V?yA1rs#~!_`e6 z{C3trQtddnihNlsAAQ5OMsvDYL{|35BN{#)oG3e(3w?i9Cg?1l?0(Jailxjb^PG3t zg>1H}U2&TT2W0j~m+?wFFw_NKO@$KhK`vnRWmKYTTeszpU|DE#Mq)_xS_(%`{ ORBvkCD7kL&_)mU;^|#)2 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 WuOGJ0U`88+P|DlW&x7g~mi~YEVa#R# literal 25410 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 In%1}f8=n>J7ytkO diff --git a/docs/source/images/processing_provider_matrix_calc.png b/docs/source/images/processing_provider_matrix_calc.png index 40658310b309e87af02d3aa3efa0c38908bc1efa..ea0c2e3dc8e7da77a4961cf4a40949310c68f581 100644 GIT binary patch literal 20588 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 II;Vst0N^tT`2YX_ literal 22846 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 IYWd**15n?^V*mgE literal 20112 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 E0E*wrDgXcg diff --git a/docs/source/images/processing_provider_nodes_from_centroids.png b/docs/source/images/processing_provider_nodes_from_centroids.png index 01847d2292576c4d9937e68f2157ec5f7c926b43..15a4e80f37771ba1dc5620f8f8f4c0cf3fc1c9f3 100644 GIT binary patch literal 18221 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