From 7a6343b8892383d6da8899ca8bab6e0fd743566c Mon Sep 17 00:00:00 2001 From: pveigadecamargo Date: Thu, 14 Sep 2023 22:31:42 +1000 Subject: [PATCH 1/5] converts interface to use only matrices from project --- .../apply_gravity_procedure.py | 6 +- .../calibrate_gravity_procedure.py | 14 ++- .../distribution_models_dialog.py | 88 +++++++++---------- .../forms/ui_distribution.ui | 84 +++--------------- .../menu_actions/action_distribution.py | 5 +- 5 files changed, 65 insertions(+), 132 deletions(-) diff --git a/qaequilibrae/modules/distribution_procedures/apply_gravity_procedure.py b/qaequilibrae/modules/distribution_procedures/apply_gravity_procedure.py index 1312a0f6..92f1c798 100644 --- a/qaequilibrae/modules/distribution_procedures/apply_gravity_procedure.py +++ b/qaequilibrae/modules/distribution_procedures/apply_gravity_procedure.py @@ -1,6 +1,6 @@ -from qgis.PyQt.QtCore import * -from aequilibrae.utils.worker_thread import WorkerThread from aequilibrae.distribution import GravityApplication +from aequilibrae.utils.worker_thread import WorkerThread +from qgis.PyQt.QtCore import * class ApplyGravityProcedure(WorkerThread): @@ -18,4 +18,4 @@ def doWork(self): self.report = self.gravity.report except ValueError as e: self.error = e - self.finished_threaded_procedure.emit("apply_gravity") + self.jobFinished.emit("apply_gravity") diff --git a/qaequilibrae/modules/distribution_procedures/calibrate_gravity_procedure.py b/qaequilibrae/modules/distribution_procedures/calibrate_gravity_procedure.py index 3eb405dd..7a2b3601 100644 --- a/qaequilibrae/modules/distribution_procedures/calibrate_gravity_procedure.py +++ b/qaequilibrae/modules/distribution_procedures/calibrate_gravity_procedure.py @@ -1,6 +1,7 @@ +from aequilibrae.distribution import GravityCalibration +from aequilibrae.utils.worker_thread import WorkerThread from qgis.PyQt.QtCore import * -from aequilibrae.utils.worker_thread import WorkerThread class CalibrateGravityProcedure(WorkerThread): def __init__(self, parentThread, **kwargs): @@ -11,10 +12,7 @@ def __init__(self, parentThread, **kwargs): self.model = None def doWork(self): - try: - self.gravity.calibrate() - self.report = self.gravity.report - self.model = self.gravity.model - except ValueError as e: - self.error = e - self.finished_threaded_procedure.emit("calibrate") + self.gravity.calibrate() + self.report = self.gravity.report + self.model = self.gravity.model + self.jobFinished.emit("calibrate") diff --git a/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py b/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py index 1678017e..d2202370 100644 --- a/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py +++ b/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py @@ -2,12 +2,17 @@ import os from collections import OrderedDict from functools import partial +from os.path import join import numpy as np from aequilibrae.distribution import SyntheticGravityModel from aequilibrae.distribution.synthetic_gravity_model import valid_functions from aequilibrae.matrix import AequilibraeData, AequilibraeMatrix +from qgis.PyQt.QtWidgets import QAbstractItemView +from qaequilibrae.modules.matrix_procedures.matrix_lister import list_matrices +from qaequilibrae.modules.matrix_procedures.results_lister import list_results +from qaequilibrae.modules.common_tools import PandasModel import qgis from aequilibrae.context import get_logger from qgis.PyQt import QtWidgets, uic @@ -31,12 +36,15 @@ class DistributionModelsDialog(QtWidgets.QDialog, FORM_CLASS): - def __init__(self, iface, mode=None): + def __init__(self, qgs_proj, mode=None): QtWidgets.QDialog.__init__(self) - self.iface = iface + self.iface = qgs_proj.iface self.setupUi(self) self.path = standard_path() + self.qgs_proj = qgs_proj + self.project = qgs_proj.project + self.error = None self.report = [] self.job_queue = OrderedDict() @@ -55,7 +63,6 @@ def __init__(self, iface, mode=None): self.rdo_calibrate_gravity.clicked.connect(self.configure_inputs) self.but_load_data.clicked.connect(self.load_datasets) - self.but_load_mat.clicked.connect(self.load_matrices) self.but_load_model.clicked.connect(self.load_model) self.cob_prod_data.currentIndexChanged.connect( @@ -75,8 +82,7 @@ def __init__(self, iface, mode=None): self.but_run.clicked.connect(self.run) self.but_queue.clicked.connect(self.add_job_to_queue) self.but_cancel.clicked.connect(self.exit_procedure) - self.table_datasets.doubleClicked.connect(self.matrix_and_data_double_clicked) - self.table_matrices.doubleClicked.connect(self.matrix_and_data_double_clicked) + self.table_datasets.doubleClicked.connect(self.data_double_clicked) self.table_jobs.setColumnWidth(0, 50) self.table_jobs.setColumnWidth(1, 295) @@ -95,18 +101,24 @@ def __init__(self, iface, mode=None): self.rdo_calibrate_gravity.setChecked(True) self.configure_inputs() + self.load_matrices() self.user_chosen_model = None self.update_model_parameters() - def matrix_and_data_double_clicked(self, mi): + def load_matrices(self): + self.matrices = list_matrices(self.project.matrices.fldr) + + self.matrices_model = PandasModel(self.matrices) + self.list_matrices.setModel(self.matrices_model) + self.cob_imped_mat.addItems(self.matrices["name"].tolist()) + self.cob_seed_mat.addItems(self.matrices["name"].tolist()) + + + def data_double_clicked(self, mi): row = mi.row() if row > -1: - if self.sender().objectName() == "table_matrices": - obj_to_view = self.table_matrices.item(row, 0).text() - dlg2 = DisplayAequilibraEFormatsDialog(self.iface, self.matrices[obj_to_view]) - else: - obj_to_view = self.table_datasets.item(row, 0).text() - dlg2 = DisplayAequilibraEFormatsDialog(self.iface, self.datasets[obj_to_view]) + obj_to_view = self.table_datasets.item(row, 0).text() + dlg2 = DisplayAequilibraEFormatsDialog(self.iface, self.datasets[obj_to_view]) dlg2.show() dlg2.exec_() @@ -118,7 +130,6 @@ def configure_inputs(self): self.resize(511, 334) self.model_tabs.setEnabled(True) self.model_tabs.setVisible(True) - self.progressbar.setVisible(False) to_remove = [] if self.rdo_ipf.isChecked(): self.job = "ipf" @@ -206,20 +217,6 @@ def load_datasets(self): self.load_comboboxes(self.datasets.keys(), self.cob_prod_data) self.load_comboboxes(self.datasets.keys(), self.cob_atra_data) - def load_matrices(self): - dlg2 = LoadMatrixDialog(self.iface) - dlg2.show() - dlg2.exec_() - if isinstance(dlg2.matrix, AequilibraeMatrix): - matrix_name = dlg2.matrix.file_path - if matrix_name is not None: - matrix_name = os.path.splitext(os.path.basename(matrix_name))[0] - matrix_name = self.find_non_conflicting_name(matrix_name, self.matrices) - self.matrices[matrix_name] = dlg2.matrix - self.add_to_table(self.matrices, self.table_matrices) - self.load_comboboxes(self.matrices.keys(), self.cob_imped_mat) - self.load_comboboxes(self.matrices.keys(), self.cob_seed_mat) - def load_model(self): file_name = self.browse_outfile("mod") try: @@ -239,8 +236,10 @@ def change_vector_field(self, cob_orig, cob_dest, dt): ): cob_dest.addItem(f) else: - for f in self.matrices[d].names: - cob_dest.addItem(f) + file_name = self.matrices.at[cob_orig.currentIndex(), "file_name"] + mat = AequilibraeMatrix() + mat.load(join(self.project.matrices.fldr, file_name)) + cob_dest.addItems(mat.names) def load_comboboxes(self, list_to_load, data_cob): data_cob.clear() @@ -286,15 +285,25 @@ def browse_outfile(self, file_type): file_chosen, _ = GetOutputFileName(self, ft[0], ft[1], ft[2], self.path) return file_chosen + def get_matrix(self, matrix_name): + + + + return + def add_job_to_queue(self): worker_thread = None if self.check_data(): if self.job != "ipf": - imped_matrix = self.matrices[self.cob_imped_mat.currentText()] + imped_name = self.matrices.at[self.cob_imped_mat.currentIndex(), "file_name"] + imped_matrix = AequilibraeMatrix() + imped_matrix.load(join(self.project.matrices.fldr, imped_name)) imped_matrix.computational_view([self.cob_imped_field.currentText()]) if self.job != "apply": - seed_matrix = self.matrices[self.cob_seed_mat.currentText()] + seed_name = self.matrices.at[self.cob_seed_mat.currentIndex(), "file_name"] + seed_matrix = AequilibraeMatrix() + seed_matrix.load(join(self.project.matrices.fldr, seed_name)) seed_matrix.computational_view([self.cob_seed_field.currentText()]) if self.job != "calibrate": @@ -377,7 +386,6 @@ def add_job_to_list(self, job, out_name): self.table_jobs.setItem(i, 2, QTableWidgetItem(self.tr("Queued"))) def run(self): - self.progressbar.setVisible(True) self.chb_empty_as_zero.setVisible(False) try: for out_name in self.job_queue.keys(): @@ -412,22 +420,10 @@ def check_data(self): return True def run_thread(self): - self.worker_thread.ProgressValue.connect(self.progress_value_from_thread) - self.worker_thread.ProgressText.connect(self.progress_text_from_thread) - self.worker_thread.ProgressMaxValue.connect(self.progress_range_from_thread) - self.worker_thread.finished_threaded_procedure.connect(self.job_finished_from_thread) - self.worker_thread.start() + self.worker_thread.jobFinished.connect(self.job_finished_from_thread) + self.worker_thread.doWork() self.show() - def progress_range_from_thread(self, val): - self.progressbar.setRange(0, val[1]) - - def progress_value_from_thread(self, value): - self.progressbar.setValue(value[1]) - - def progress_text_from_thread(self, value): - self.progress_label.setText(value[1]) - def job_finished_from_thread(self, success): error = self.worker_thread.error if error is not None: diff --git a/qaequilibrae/modules/distribution_procedures/forms/ui_distribution.ui b/qaequilibrae/modules/distribution_procedures/forms/ui_distribution.ui index 5cec33e0..6d7f24b8 100644 --- a/qaequilibrae/modules/distribution_procedures/forms/ui_distribution.ui +++ b/qaequilibrae/modules/distribution_procedures/forms/ui_distribution.ui @@ -7,7 +7,7 @@ 0 0 511 - 330 + 334 @@ -103,62 +103,8 @@ Load matrices - - - - - Matrix name - - - - - # of cores - - - - - - - - Matrices - - - Qt::AlignCenter - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Load - - + + @@ -466,10 +412,13 @@ jobs - - - - 0 + + + + Treat empties as zeros + + + false @@ -492,20 +441,7 @@ - - - - Treat empties as zeros - - - false - - - - progressbar - table_jobs - chb_empty_as_zero diff --git a/qaequilibrae/modules/menu_actions/action_distribution.py b/qaequilibrae/modules/menu_actions/action_distribution.py index 8985caca..7e5ee148 100644 --- a/qaequilibrae/modules/menu_actions/action_distribution.py +++ b/qaequilibrae/modules/menu_actions/action_distribution.py @@ -1,5 +1,8 @@ def run_distribution_models(qgis_project): from qaequilibrae.modules.distribution_procedures import DistributionModelsDialog - dlg2 = DistributionModelsDialog(qgis_project.iface) + if qgis_project.project is None: + qgis_project.iface.messageBar().pushMessage("Error", "You need to load a project first", level=3, duration=10) + return + dlg2 = DistributionModelsDialog(qgis_project) dlg2.show() dlg2.exec_() From 08084e39b734dda835fa4a849f41831b336d0c10 Mon Sep 17 00:00:00 2001 From: Renata Imai Date: Sun, 17 Sep 2023 19:38:26 -0300 Subject: [PATCH 2/5] changes distribution procedures --- qaequilibrae/modules/common_tools/database_model.py | 2 +- .../distribution_models_dialog.py | 13 +++---------- .../distribution_procedures/ipf_procedure.py | 4 ++-- test/test_qaequilibrae_menu_without_project.py | 8 ++------ 4 files changed, 8 insertions(+), 19 deletions(-) diff --git a/qaequilibrae/modules/common_tools/database_model.py b/qaequilibrae/modules/common_tools/database_model.py index d6c770d7..6d380916 100644 --- a/qaequilibrae/modules/common_tools/database_model.py +++ b/qaequilibrae/modules/common_tools/database_model.py @@ -54,7 +54,7 @@ def __init__(self, aeq_dataset, separator, decimals, parent=None): if np.issubdtype(t, np.integer): self.types.append(0) self.empties.append(np.iinfo(t).min) - elif np.issubdtype(t, np.float): + elif np.issubdtype(t, np.float64): self.types.append(1) self.empties.append(np.nan) else: diff --git a/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py b/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py index d2202370..5256cd1e 100644 --- a/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py +++ b/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py @@ -11,7 +11,6 @@ from qgis.PyQt.QtWidgets import QAbstractItemView from qaequilibrae.modules.matrix_procedures.matrix_lister import list_matrices -from qaequilibrae.modules.matrix_procedures.results_lister import list_results from qaequilibrae.modules.common_tools import PandasModel import qgis from aequilibrae.context import get_logger @@ -23,7 +22,7 @@ from qaequilibrae.modules.common_tools import GetOutputFileName from qaequilibrae.modules.common_tools import ReportDialog from qaequilibrae.modules.common_tools.auxiliary_functions import standard_path -from qaequilibrae.modules.matrix_procedures import LoadMatrixDialog, LoadDatasetDialog, DisplayAequilibraEFormatsDialog +from qaequilibrae.modules.matrix_procedures import LoadDatasetDialog, DisplayAequilibraEFormatsDialog FORM_CLASS, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), "forms/ui_distribution.ui")) spec = iutil.find_spec("openmatrix") @@ -81,7 +80,7 @@ def __init__(self, qgs_proj, mode=None): self.but_run.clicked.connect(self.run) self.but_queue.clicked.connect(self.add_job_to_queue) - self.but_cancel.clicked.connect(self.exit_procedure) + self.but_cancel.clicked.connect(self.close) self.table_datasets.doubleClicked.connect(self.data_double_clicked) self.table_jobs.setColumnWidth(0, 50) @@ -232,7 +231,7 @@ def change_vector_field(self, cob_orig, cob_dest, dt): if dt == "data": for f in self.datasets[d].fields: if np.issubdtype(self.datasets[d].data[f].dtype, np.integer) or np.issubdtype( - self.datasets[d].data[f].dtype, np.float + self.datasets[d].data[f].dtype, np.float64 ): cob_dest.addItem(f) else: @@ -285,12 +284,6 @@ def browse_outfile(self, file_type): file_chosen, _ = GetOutputFileName(self, ft[0], ft[1], ft[2], self.path) return file_chosen - def get_matrix(self, matrix_name): - - - - return - def add_job_to_queue(self): worker_thread = None if self.check_data(): diff --git a/qaequilibrae/modules/distribution_procedures/ipf_procedure.py b/qaequilibrae/modules/distribution_procedures/ipf_procedure.py index 4b372f70..267c6673 100644 --- a/qaequilibrae/modules/distribution_procedures/ipf_procedure.py +++ b/qaequilibrae/modules/distribution_procedures/ipf_procedure.py @@ -5,7 +5,7 @@ class IpfProcedure(WorkerThread): - finished_threaded_procedure = pyqtSignal(object) + # finished_threaded_procedure = pyqtSignal(object) def __init__(self, parentThread, **kwargs): WorkerThread.__init__(self, parentThread) @@ -21,4 +21,4 @@ def doWork(self): self.output = self.ipf.output except ValueError as e: self.error = e - self.finished_threaded_procedure.emit("finishedIPF") + self.jobFinished.emit("finishedIPF") diff --git a/test/test_qaequilibrae_menu_without_project.py b/test/test_qaequilibrae_menu_without_project.py index 5033f125..854eec8c 100644 --- a/test/test_qaequilibrae_menu_without_project.py +++ b/test/test_qaequilibrae_menu_without_project.py @@ -125,15 +125,11 @@ def handle_trigger(): def test_trip_distribution_menu(ae, qtbot): - from qaequilibrae.modules.distribution_procedures import DistributionModelsDialog - - def handle_trigger(): - check_if_new_active_window_matches_class(qtbot, DistributionModelsDialog) - action = ae.menuActions["Trip Distribution"][0] assert action.text() == "Trip Distribution", "Wrong text content" - QTimer.singleShot(10, handle_trigger) action.trigger() + messagebar = ae.iface.messageBar() + assert messagebar.messages[3][0] == "Error:You need to load a project first", "Level 3 error message is missing" def test_shortest_path_menu(ae, qtbot): From 8cc33de5859a7f1026eff0c355ed0fcfe0a3b550 Mon Sep 17 00:00:00 2001 From: pveigadecamargo Date: Mon, 18 Sep 2023 21:05:34 +1000 Subject: [PATCH 3/5] small change --- .../distribution_procedures/distribution_models_dialog.py | 1 - 1 file changed, 1 deletion(-) diff --git a/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py b/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py index 5256cd1e..b561b2cd 100644 --- a/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py +++ b/qaequilibrae/modules/distribution_procedures/distribution_models_dialog.py @@ -431,7 +431,6 @@ def job_finished_from_thread(self, success): self.exit_procedure() def exit_procedure(self): - self.close() if self.report is not None: dlg2 = ReportDialog(self.iface, self.report) dlg2.show() From b9357ed1966b0d854a0f3d2fc2cb89bcc2c3a6c9 Mon Sep 17 00:00:00 2001 From: Pedro Camargo Date: Mon, 9 Oct 2023 17:14:36 +1000 Subject: [PATCH 4/5] Update qaequilibrae/modules/distribution_procedures/ipf_procedure.py Co-authored-by: Jamie Cook --- qaequilibrae/modules/distribution_procedures/ipf_procedure.py | 1 - 1 file changed, 1 deletion(-) diff --git a/qaequilibrae/modules/distribution_procedures/ipf_procedure.py b/qaequilibrae/modules/distribution_procedures/ipf_procedure.py index 267c6673..40ecab47 100644 --- a/qaequilibrae/modules/distribution_procedures/ipf_procedure.py +++ b/qaequilibrae/modules/distribution_procedures/ipf_procedure.py @@ -5,7 +5,6 @@ class IpfProcedure(WorkerThread): - # finished_threaded_procedure = pyqtSignal(object) def __init__(self, parentThread, **kwargs): WorkerThread.__init__(self, parentThread) From a6686d02264b16cda5a3f29f3c777695dc8b9a83 Mon Sep 17 00:00:00 2001 From: pveigadecamargo Date: Mon, 9 Oct 2023 17:31:17 +1000 Subject: [PATCH 5/5] fixes type checking --- qaequilibrae/modules/common_tools/database_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qaequilibrae/modules/common_tools/database_model.py b/qaequilibrae/modules/common_tools/database_model.py index 6d380916..28394798 100644 --- a/qaequilibrae/modules/common_tools/database_model.py +++ b/qaequilibrae/modules/common_tools/database_model.py @@ -54,7 +54,7 @@ def __init__(self, aeq_dataset, separator, decimals, parent=None): if np.issubdtype(t, np.integer): self.types.append(0) self.empties.append(np.iinfo(t).min) - elif np.issubdtype(t, np.float64): + elif np.issubdtype(t, np.floating): self.types.append(1) self.empties.append(np.nan) else: