Exemplo n.º 1
0
    def __init__(self, path_prj, name_prj):

        super().__init__()
        self.tab_name = "estimhab"
        self.tab_position = 7
        self.model_type = "Estimhab"
        self.eq50 = QLineEdit()
        self.esub = QLineEdit()
        self.path_prj = path_prj
        self.name_prj = name_prj
        self.path_bio_estimhab = os.path.join(self.path_bio, 'estimhab')
        self.total_lineedit_number = 1
        self.init_iu()
        self.process_manager = MyProcessManager(
            "estimhab_plot")  # SC (Suitability Curve)
        self.read_estimhab_dict()
        self.fill_input_data()
        self.fill_fish_name()
        self.check_if_ready_to_compute()
        self.eq1.textChanged.connect(self.check_if_ready_to_compute)
        self.eq2.textChanged.connect(self.check_if_ready_to_compute)
        self.ew1.textChanged.connect(self.check_if_ready_to_compute)
        self.ew2.textChanged.connect(self.check_if_ready_to_compute)
        self.eh1.textChanged.connect(self.check_if_ready_to_compute)
        self.eh2.textChanged.connect(self.check_if_ready_to_compute)
        self.eq50.textChanged.connect(self.check_if_ready_to_compute)
        self.eqmin.textChanged.connect(self.check_if_ready_to_compute)
        self.eqmax.textChanged.connect(self.check_if_ready_to_compute)
        self.esub.textChanged.connect(self.check_if_ready_to_compute)
        self.selected_aquatic_animal_qtablewidget.model().rowsInserted.connect(
            self.check_if_ready_to_compute)
        self.selected_aquatic_animal_qtablewidget.model().rowsRemoved.connect(
            self.check_if_ready_to_compute)
Exemplo n.º 2
0
 def __init__(self, path_prj, name_prj, send_log, title):
     super().__init__()
     self.path_prj = path_prj
     self.name_prj = name_prj
     self.send_log = send_log
     self.path_last_file_loaded = self.path_prj
     self.project_properties = load_project_properties(self.path_prj)
     self.setTitle(title)
     self.init_ui()
     # process_manager
     self.process_manager = MyProcessManager("hrr")
Exemplo n.º 3
0
 def __init__(self, path_prj, name_prj, send_log, title):
     super().__init__()
     self.path_prj = path_prj
     self.name_prj = name_prj
     self.send_log = send_log
     self.path_last_file_loaded = self.path_prj
     self.project_properties = load_project_properties(self.path_prj)
     self.setTitle(title)
     self.init_ui()
     self.msg2 = QMessageBox()
     self.mesh_manager_file = self.read_attribute_xml("mesh_manager_file")
     self.read_mesh_manager_file(self.mesh_manager_file)
     # process_manager
     self.process_manager = MyProcessManager("mesh_manager")
Exemplo n.º 4
0
 def __init__(self, path_prj, name_prj, send_log, title):
     super().__init__()
     self.path_prj = path_prj
     self.name_prj = name_prj
     self.send_log = send_log
     self.path_last_file_loaded = self.path_prj
     self.classhv = None
     self.project_properties = load_project_properties(self.path_prj)
     self.setTitle(title)
     self.init_ui()
     self.input_class_file_info = self.read_attribute_xml("HS_input_class")
     self.read_input_class(os.path.join(self.input_class_file_info["path"], self.input_class_file_info["file"]))
     # process_manager
     self.process_manager = MyProcessManager("hs")
Exemplo n.º 5
0
 def __init__(self, path_prj, name_prj, send_log):
     super().__init__()
     self.tab_name = "interpolation"
     self.tab_title = "Interpolation"
     self.tooltip_str = self.tr("Interpolation of habitat values")
     self.path_prj = path_prj
     self.name_prj = name_prj
     self.send_log = send_log
     self.mytablemodel = None
     self.path_last_file_loaded = self.path_prj
     self.process_manager = MyProcessManager("interpolation")
     self.init_ui()
     self.process_prog_show = ProcessProgShow(send_log=self.send_log,
                                              # progress_bar=self.nativeParentWidget().progress_bar,
                                              # progress_label=self.progress_label,
                                              run_function=self.plot_chronicle,
                                              computation_pushbutton=self.plot_chronicle_qpushbutton)
Exemplo n.º 6
0
 def __init__(self, path_prj, name_prj, send_log, title):
     super().__init__()
     self.path_prj = path_prj
     self.name_prj = name_prj
     self.send_log = send_log
     self.path_last_file_loaded = self.path_prj
     self.process_manager = MyProcessManager("hs_plot")
     self.axe_mod_choosen = 1
     self.setTitle(title)
     self.init_ui()
     self.process_prog_show_input = ProcessProgShow(send_log=self.send_log,
                                              run_function=self.plot_hs_class,
                                              computation_pushbutton=self.input_class_plot_button)
     self.process_prog_show_area = ProcessProgShow(send_log=self.send_log,
                                              run_function=self.plot_hs_area,
                                              computation_pushbutton=self.result_plot_button_area)
     self.process_prog_show_volume = ProcessProgShow(send_log=self.send_log,
                                              run_function=self.plot_hs_volume,
                                              computation_pushbutton=self.result_plot_button_volume)
Exemplo n.º 7
0
    def __init__(self,
                 run_function,
                 send_log,
                 process_type,
                 send_refresh_filenames=None):
        super().__init__()
        widget_height = QComboBox().minimumSizeHint().height()
        # send_log
        self.send_log = send_log
        # progress_bar
        self.progress_bar = QProgressBar()
        self.progress_bar.setMaximumHeight(widget_height)
        self.progress_bar.setValue(0.0)
        self.progress_bar.setRange(0.0, 100.0)
        self.progress_bar.setTextVisible(False)

        # progress_label
        self.progress_label = QLabel()
        self.progress_label.setText("{0:.0f}/{1:.0f}".format(0, 0))

        # run_stop_button
        self.run_stop_button = QPushButton(self.tr("run"))
        self.run_stop_button.setMaximumHeight(widget_height)
        change_button_color(self.run_stop_button, "#47B5E6")  #47B5E6
        self.run_stop_button.clicked.connect(
            run_function)  # self.collect_data_from_gui_and_plot
        self.run_stop_button.setEnabled(False)

        # layout
        self.addWidget(self.progress_bar)
        self.addWidget(self.progress_label)
        self.addWidget(self.run_stop_button)

        # process_manager
        # app = QCoreApplication([])
        self.process_manager = MyProcessManager(process_type)
        # self.process_manager.finished.connect(app.exit)

        # process_prog_show
        self.process_prog_show = ProcessProgShow(
            send_log=self.send_log,
            send_refresh_filenames=send_refresh_filenames,
            progressbar=self.progress_bar,
            progress_label=self.progress_label,
            computation_pushbutton=self.run_stop_button,
            run_function=run_function)
Exemplo n.º 8
0
class ComputingGroup(QGroupBoxCollapsible):
    """
    This class is a subclass of class QGroupBox.
    """
    send_refresh_filenames = pyqtSignal(name='send_refresh_filenames')

    def __init__(self, path_prj, name_prj, send_log, title):
        super().__init__()
        self.path_prj = path_prj
        self.name_prj = name_prj
        self.send_log = send_log
        self.path_last_file_loaded = self.path_prj
        self.project_properties = load_project_properties(self.path_prj)
        self.setTitle(title)
        self.init_ui()
        self.msg2 = QMessageBox()
        self.mesh_manager_file = self.read_attribute_xml("mesh_manager_file")
        self.read_mesh_manager_file(self.mesh_manager_file)
        # process_manager
        self.process_manager = MyProcessManager("mesh_manager")

    def init_ui(self):
        # file_selection
        file_selection_label = QLabel(self.tr("Select a 2D mesh file :"))
        self.file_selection_listwidget = QListWidget()
        self.file_selection_listwidget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.file_selection_listwidget.itemSelectionChanged.connect(
            self.names_hdf5_change)
        self.file_selection_listwidget.setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff)
        self.file_selection_listwidget.verticalScrollBar().setEnabled(True)
        self.file_selection_listwidget.verticalScrollBar(
        ).valueChanged.connect(self.change_scroll_position)
        self.scrollbar = self.file_selection_listwidget.verticalScrollBar()

        mesh_manager_file = QLabel(self.tr("Mesh manager file (.txt)"))
        self.mesh_manager_filename_label = QLabel("")
        self.mesh_manager_file_select_pushbutton = QPushButton("...")
        self.mesh_manager_file_select_pushbutton.clicked.connect(
            self.select_mesh_manager_file_dialog)

        # progress_layout
        self.progress_layout = ProcessProgLayout(
            self.compute,
            send_log=self.send_log,
            process_type="mesh_manager",
            send_refresh_filenames=self.send_refresh_filenames)

        file_selection_layout = QGridLayout()
        file_selection_layout.addWidget(file_selection_label, 0, 0)
        file_selection_layout.addWidget(self.file_selection_listwidget, 1, 0)
        file_selection_layout.addWidget(self.scrollbar, 1, 1)
        file_selection_layout.setColumnStretch(0, 30)
        file_selection_layout.setColumnStretch(1, 1)

        grid_layout = QGridLayout()
        grid_layout.addWidget(mesh_manager_file, 0, 0, Qt.AlignLeft)
        grid_layout.addWidget(self.mesh_manager_filename_label, 0, 1,
                              Qt.AlignLeft)
        grid_layout.addWidget(self.mesh_manager_file_select_pushbutton, 0, 2,
                              Qt.AlignLeft)
        grid_layout.addLayout(self.progress_layout, 1, 0, 1, 3)

        general_layout = QVBoxLayout()
        general_layout.addLayout(file_selection_layout)
        general_layout.addLayout(grid_layout)

        self.setLayout(general_layout)

    def update_gui(self):
        selected_file_names = [
            selection_el.text()
            for selection_el in self.file_selection_listwidget.selectedItems()
        ]
        # computing_group
        hyd_names = get_filename_by_type_physic(
            "hydraulic", os.path.join(self.path_prj, "hdf5"))
        hab_names = get_filename_by_type_physic(
            "habitat", os.path.join(self.path_prj, "hdf5"))
        names = hyd_names + hab_names
        self.file_selection_listwidget.blockSignals(True)
        self.file_selection_listwidget.clear()
        if names:
            for name in names:
                # check
                try:
                    hdf5 = Hdf5Management(self.path_prj,
                                          name,
                                          new=False,
                                          edit=False)
                    hdf5.get_hdf5_attributes(close_file=True)
                    item_name = QListWidgetItem()
                    item_name.setText(name)
                    self.file_selection_listwidget.addItem(item_name)
                    if name in selected_file_names:
                        item_name.setSelected(True)
                    if True:  #TODO : sort files (hdf5 attributes available for HRR) .hyd, one whole profile for all units, ...
                        pass
                    else:
                        pass
                except:
                    self.send_log.emit(
                        self.
                        tr("Error: " + name +
                           " file seems to be corrupted. Delete it with HABBY or manually."
                           ))

        self.file_selection_listwidget.blockSignals(False)
        # preselection if one
        if self.file_selection_listwidget.count() == 1:
            self.file_selection_listwidget.selectAll()

    def change_scroll_position(self, index):
        self.file_selection_listwidget.verticalScrollBar().setValue(index)

    def names_hdf5_change(self):
        selection = self.file_selection_listwidget.selectedItems()
        self.progress_layout.progress_bar.setValue(0.0)
        self.progress_layout.progress_label.setText("{0:.0f}/{1:.0f}".format(
            0.0, len(selection)))
        if selection:
            self.progress_layout.run_stop_button.setEnabled(True)
        else:
            self.progress_layout.run_stop_button.setEnabled(False)

    def read_mesh_manager_file(self, mesh_manager_file):
        if os.path.exists(mesh_manager_file):
            self.mesh_manager_description, warnings_list = mesh_manager_from_file(
                mesh_manager_file)
            if warnings_list:
                for warning in warnings_list:
                    self.send_log.emit(warning)
            if self.mesh_manager_description["mesh_manager_data"] is None:
                self.send_log.emit(
                    self.tr("Error: Mesh manager file : ") +
                    os.path.basename(mesh_manager_file) +
                    self.tr(" is not valid."))
                self.progress_layout.run_stop_button.setEnabled(False)
            else:
                self.mesh_manager_filename_label.setText(
                    os.path.basename(mesh_manager_file))
                if self.file_selection_listwidget.selectedItems():
                    self.progress_layout.run_stop_button.setEnabled(True)
        else:
            self.progress_layout.run_stop_button.setEnabled(False)

        self.progress_layout.progress_bar.setValue(0.0)
        self.progress_layout.progress_label.setText("{0:.0f}/{1:.0f}".format(
            0.0, len(self.file_selection_listwidget.selectedItems())))

    def select_mesh_manager_file_dialog(self):
        self.mesh_manager_file = self.read_attribute_xml("mesh_manager_file")
        # get last path
        if self.mesh_manager_file != self.path_prj and self.mesh_manager_file != "":
            model_path = self.mesh_manager_file  # path spe
        elif self.read_attribute_xml(
                "path_last_file_loaded"
        ) != self.path_prj and self.read_attribute_xml(
                "path_last_file_loaded") != "":
            model_path = self.read_attribute_xml(
                "path_last_file_loaded")  # path last
        else:
            model_path = self.path_prj  # path proj

        filename, _ = QFileDialog.getOpenFileName(
            self, self.tr("Select a mesh manager file"), model_path,
            self.tr("Text files") + " (*.txt)")
        if filename:
            self.pathfile = filename  # source file path
            self.save_xml("mesh_manager_file")
            self.read_mesh_manager_file(filename)
            self.mesh_manager_file = self.read_attribute_xml(
                "mesh_manager_file")

    def read_attribute_xml(self, att_here):
        """
        A function to read the text of an attribute in the xml project file.

        :param att_here: the attribute name (string).
        """
        data = ''

        filename_path_pro = os.path.join(self.path_prj,
                                         self.name_prj + '.habby')
        if os.path.isfile(filename_path_pro):
            if att_here in {"path_last_file_loaded"}:
                data = load_project_properties(self.path_prj)[att_here]
            else:
                try:
                    data = load_project_properties(self.path_prj)[att_here]
                except KeyError:
                    self.save_xml("mesh_manager_file")
                    data = load_project_properties(self.path_prj)[att_here]
        else:
            pass

        return data

    def save_xml(self, attr):
        """
        A function to save the loaded data in the xml file.

        This function adds the name and the path of the newly chosen hydrological data to the xml project file. First,
        it open the xml project file (and send an error if the project is not saved, or if it cannot find the project
        file). Then, it opens the xml file and add the path and name of the file to this xml file. If the model data was
        already loaded, it adds the new name without erasing the old name IF the switch append_name is True. Otherwise,
        it erase the old name and replace it by a new name. The variable “i” has the same role than in select_file_and_show_informations_dialog.

        :param i: a int for the case where there is more than one file to load
        :param append_name: A boolean. If True, the name found will be append to the existing name in the xml file,
                instead of remplacing the old name by the new name.

        """
        filename_path_pro = os.path.join(self.path_prj,
                                         self.name_prj + '.habby')

        # save the name and the path in the xml .prj file
        if not os.path.isfile(filename_path_pro):
            self.end_log.emit(
                'Error: The project is not saved. '
                'Save the project in the General tab before saving hydrological data. \n'
            )
        else:
            # change path_last_file_loaded, model_type (path)
            self.project_properties = load_project_properties(
                self.path_prj)  # load_project_properties
            self.project_properties[
                "path_last_file_loaded"] = self.pathfile  # change value
            self.project_properties[attr] = self.pathfile  # change value
            save_project_properties(
                self.path_prj,
                self.project_properties)  # save_project_properties

    def compute(self):
        if len(self.file_selection_listwidget.selectedItems()) > 0:
            mesh_manager_description = self.mesh_manager_description
            mesh_manager_description["hdf5_name_list"] = [
                selection_el.text() for selection_el in
                self.file_selection_listwidget.selectedItems()
            ]

            # for hdf5_file in mesh_manager_description["hdf5_name_list"]:
            #     hdf5_1 = Hdf5Management(self.path_prj, hdf5_file, new=False, edit=False)
            #     hdf5_1.load_hdf5(whole_profil=False)
            #     if hdf5_1.data_2d.hvum.hdf5_and_computable_list.habs():
            #         self.msg2.setIcon(QMessageBox.Warning)
            #         self.msg2.setWindowTitle(self.tr("HSI data in ") + hdf5_1.filename[:-4] + "_MM" + hdf5_1.extension + ".")
            #         self.msg2.setText(self.tr("If computing, existing HSI data will be removed in ") + hdf5_1.filename[:-4] + "_MM" + hdf5_1.extension + ".\n"+
            #                           self.tr("Do you really want to continue computing ?"))
            #         self.msg2.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            #         res = self.msg2.exec_()
            #
            #         # cancel
            #         if res == QMessageBox.No:
            #             return
            #         if res == QMessageBox.Yes:
            #             break

            self.progress_layout.process_manager.set_mesh_manager(
                self.path_prj, mesh_manager_description,
                self.project_properties)

            # start thread
            self.progress_layout.start_process()

    def stop_compute(self):
        # stop_by_user
        self.process_manager.stop_by_user()
Exemplo n.º 9
0
class EstimhabW(StatModUseful):
    """
    The Estimhab class provides the graphical interface for the version of the Estimhab model written in HABBY.
    The Estimhab model is described elsewhere. EstimhabW() just loads the data for Estimhab given by the user.
    """

    save_signal_estimhab = pyqtSignal()
    """
    PyQtsignal to save the Estimhab data.
    """
    def __init__(self, path_prj, name_prj):

        super().__init__()
        self.tab_name = "estimhab"
        self.tab_position = 7
        self.model_type = "Estimhab"
        self.eq50 = QLineEdit()
        self.esub = QLineEdit()
        self.path_prj = path_prj
        self.name_prj = name_prj
        self.path_bio_estimhab = os.path.join(self.path_bio, 'estimhab')
        self.total_lineedit_number = 1
        self.init_iu()
        self.process_manager = MyProcessManager(
            "estimhab_plot")  # SC (Suitability Curve)
        self.read_estimhab_dict()
        self.fill_input_data()
        self.fill_fish_name()
        self.check_if_ready_to_compute()
        self.eq1.textChanged.connect(self.check_if_ready_to_compute)
        self.eq2.textChanged.connect(self.check_if_ready_to_compute)
        self.ew1.textChanged.connect(self.check_if_ready_to_compute)
        self.ew2.textChanged.connect(self.check_if_ready_to_compute)
        self.eh1.textChanged.connect(self.check_if_ready_to_compute)
        self.eh2.textChanged.connect(self.check_if_ready_to_compute)
        self.eq50.textChanged.connect(self.check_if_ready_to_compute)
        self.eqmin.textChanged.connect(self.check_if_ready_to_compute)
        self.eqmax.textChanged.connect(self.check_if_ready_to_compute)
        self.esub.textChanged.connect(self.check_if_ready_to_compute)
        self.selected_aquatic_animal_qtablewidget.model().rowsInserted.connect(
            self.check_if_ready_to_compute)
        self.selected_aquatic_animal_qtablewidget.model().rowsRemoved.connect(
            self.check_if_ready_to_compute)

    def init_iu(self):
        """
        This function is used to initialized an instance of the EstimhabW() class. It is called by __init__().

         **Technical comments and walk-through**

         First we looked if some data for Estimhab was saved before by an user. If yes, we will fill the GUI with
         the information saved before. Estimhab information is saved in hdf5 file format and the path/name of the
         hdf5 file is saved in the xml project file. So we open the xml project file and look if the name of an hdf5
         file was saved for Estimhab. If yes, the hdf5 file is read.

         The format of hdf5 file is relatively simple. Each input data for Estimhab has its own dataset (qmes, hmes,
         wmes, q50, qrange, and substrate).  Then, we have a list of string which are a code for the fish species which
         were analyzed.  All the data contained in hdf5 file is loaded into variable.

         The different label are written on the graphical interface. Then, two QListWidget are modified. The first
         list contains all the fish species on which HABBY has info (see XML Estimhab format for more info).
         The second list is the fish selected by the user on which Estimhab will be run. Here, we link these lists
         with two functions so that the user can select/deselect fish using the mouse. The function name are add_fish()
         and remove_fish().

         Then, we fill the first list. HABBY look up all file of xml type in the “Path_bio” folder (the one indicated in
         the xml project file under the attribute “Path_bio”).  The name are them modified so that the only the name of
         species appears (and not the full path). We set the layout with all the different QLineEdit where the user
         can write the needed data.

         Estimhab model is saved using a function situated in MainWindows_1.py  (frankly, I am not so sure why I did put
         the save function there, but anyway). So the save button just send a signal to MainWindows
         here, which save the data.
        """

        available_model_label = QLabel(self.tr('Available'))
        selected_model_label = QLabel(self.tr('Selected'))

        self.lineedit_width = 50
        self.spacer_width = 50

        # input
        q1_layout = QHBoxLayout()
        q1_layout.addWidget(QLabel('Q1 [m<sup>3</sup>/s]'))
        q1_layout.addWidget(self.eq1)
        q1_layout.addItem(QSpacerItem(self.spacer_width, 1))
        self.eq1.setFixedWidth(self.lineedit_width)

        q2_layout = QHBoxLayout()
        q2_layout.addWidget(QLabel('Q2 [m<sup>3</sup>/s]'))
        q2_layout.addWidget(self.eq2)
        q2_layout.addItem(QSpacerItem(self.spacer_width, 1))
        self.eq2.setFixedWidth(self.lineedit_width)

        w1_layout = QHBoxLayout()
        w1_layout.addWidget(QLabel(self.tr("Width1 [m]")))
        w1_layout.addWidget(self.ew1)
        w1_layout.addItem(QSpacerItem(self.spacer_width, 1))
        self.ew1.setFixedWidth(self.lineedit_width)

        w2_layout = QHBoxLayout()
        w2_layout.addWidget(QLabel(self.tr("Width2 [m]")))
        w2_layout.addWidget(self.ew2)
        w2_layout.addItem(QSpacerItem(self.spacer_width, 1))
        self.ew2.setFixedWidth(self.lineedit_width)

        h1_layout = QHBoxLayout()
        h1_layout.addWidget(QLabel(self.tr("Height1 [m]")))
        h1_layout.addWidget(self.eh1)
        self.eh1.setFixedWidth(self.lineedit_width)

        h2_layout = QHBoxLayout()
        h2_layout.addWidget(QLabel(self.tr("Height2 [m]")))
        h2_layout.addWidget(self.eh2)
        self.eh2.setFixedWidth(self.lineedit_width)

        q50_layout = QHBoxLayout()
        q50_layout.addWidget(QLabel('Qmedian/Q50 [m<sup>3</sup>/s]'))
        q50_layout.addWidget(self.eq50)
        q50_layout.addItem(QSpacerItem(self.spacer_width, 1))
        self.eq50.setFixedWidth(self.lineedit_width)

        sub_layout = QHBoxLayout()
        sub_layout.addWidget(QLabel(self.tr('Mean substrate size [m]')))
        sub_layout.addWidget(self.esub)
        sub_layout.addItem(QSpacerItem(self.spacer_width, 1))
        self.esub.setFixedWidth(self.lineedit_width)

        # output
        q1out_layout = QHBoxLayout()
        q1out_layout.addWidget(QLabel(self.tr("Qmin [m<sup>3</sup>/s]")))
        q1out_layout.addWidget(self.eqmin)
        q1out_layout.addItem(QSpacerItem(self.spacer_width, 1))
        self.eqmin.setFixedWidth(self.lineedit_width)

        q2out_layout = QHBoxLayout()
        q2out_layout.addWidget(QLabel(self.tr("Qmax [m<sup>3</sup>/s]")))
        q2out_layout.addWidget(self.eqmax)
        q2out_layout.addItem(QSpacerItem(self.spacer_width, 1))
        self.eqmax.setFixedWidth(self.lineedit_width)

        self.q2target_layout = QHBoxLayout()
        self.q2target_layout.addWidget(
            QLabel(self.tr("Qtarget [m<sup>3</sup>/s]")))
        self.q2target_layout.addWidget(self.add_qtarget_button)
        self.q2target_layout.addWidget(self.remove_qtarget_button)
        self.add_qtarget_button.clicked.connect(self.add_new_qtarget)
        self.remove_qtarget_button.clicked.connect(self.remove_one_qtarget)

        # create lists with the possible fishes
        self.list_f.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.list_f.setDragDropMode(QAbstractItemView.DragDrop)
        self.list_f.setDefaultDropAction(Qt.MoveAction)
        self.list_f.setAcceptDrops(True)
        self.list_f.setSortingEnabled(True)

        self.selected_aquatic_animal_qtablewidget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.selected_aquatic_animal_qtablewidget.setDragDropMode(
            QAbstractItemView.DragDrop)
        self.selected_aquatic_animal_qtablewidget.setDefaultDropAction(
            Qt.MoveAction)
        self.selected_aquatic_animal_qtablewidget.setAcceptDrops(True)
        self.selected_aquatic_animal_qtablewidget.setSortingEnabled(True)

        # insist on white background color (for linux, mac)
        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.white)
        self.setPalette(p)

        # send model
        self.run_stop_button = QPushButton(self.tr('Run Estimhab'), self)
        self.run_stop_button.clicked.connect(self.run_estmihab)
        change_button_color(self.run_stop_button, "#47B5E6")
        self.run_stop_button.setEnabled(False)

        # empty frame scrolable
        content_widget = QFrame()

        # hydraulic_data_group
        hydraulic_data_group = QGroupBox(self.tr('Hydraulic data input'))
        hydraulic_data_group.setToolTip(
            self.tr("Double click to reset the input data group."))
        hydraulic_data_layout = QGridLayout(hydraulic_data_group)
        hydraulic_data_layout.addLayout(q1_layout, 0, 0)
        hydraulic_data_layout.addLayout(w1_layout, 0, 1)
        hydraulic_data_layout.addLayout(h1_layout, 0, 2)
        hydraulic_data_layout.addLayout(q2_layout, 1, 0)
        hydraulic_data_layout.addLayout(w2_layout, 1, 1)
        hydraulic_data_layout.addLayout(h2_layout, 1, 2)
        hydraulic_data_layout.addLayout(q50_layout, 2, 0)
        hydraulic_data_layout.addLayout(sub_layout, 2, 1)
        hydraulic_data_group.setSizePolicy(QSizePolicy.Maximum,
                                           QSizePolicy.Maximum)
        self.doubleclick_input_group = DoubleClicOutputGroup()
        hydraulic_data_group.installEventFilter(self.doubleclick_input_group)
        self.doubleclick_input_group.double_clic_signal.connect(
            self.reset_hydraulic_data_input_group)

        # hydraulic_data_output_group
        hydraulic_data_output_group = QGroupBox(
            self.tr('Desired hydraulic output data'))
        hydraulic_data_output_group.setToolTip(
            self.tr("Double click to reset the outpout data group."))
        hydraulic_data_layout = QGridLayout(hydraulic_data_output_group)
        hydraulic_data_layout.addLayout(q1out_layout, 0, 0)
        hydraulic_data_layout.addLayout(q2out_layout, 0, 1)
        hydraulic_data_layout.addLayout(self.q2target_layout, 0, 2)
        hydraulic_data_output_group.setSizePolicy(QSizePolicy.Maximum,
                                                  QSizePolicy.Maximum)
        self.doubleclick_output_group = DoubleClicOutputGroup()
        hydraulic_data_output_group.installEventFilter(
            self.doubleclick_output_group)
        self.doubleclick_output_group.double_clic_signal.connect(
            self.reset_hydraulic_data_output_group)

        # models_group
        models_group = QGroupBox(self.tr('Biological models'))
        models_layout = QGridLayout(models_group)
        models_layout.addWidget(available_model_label, 0, 0)
        models_layout.addWidget(selected_model_label, 0, 1)
        models_layout.addWidget(self.list_f, 1, 0)
        models_layout.addWidget(self.selected_aquatic_animal_qtablewidget, 1,
                                1)
        models_layout.addWidget(self.run_stop_button, 2, 1)
        self.doubleclick_models_group = DoubleClicOutputGroup()
        models_group.installEventFilter(self.doubleclick_models_group)
        self.doubleclick_models_group.double_clic_signal.connect(
            self.reset_models_group)

        # gereral_layout
        self.layout3 = QVBoxLayout(content_widget)
        self.layout3.addWidget(hydraulic_data_group, Qt.AlignLeft)
        self.layout3.addWidget(hydraulic_data_output_group)
        self.layout3.addWidget(models_group)

        # self.setLayout(self.layout3)
        self.setWidgetResizable(True)
        self.setFrameShape(QFrame.NoFrame)
        self.setWidget(content_widget)

    def add_new_qtarget(self):
        # count existing number of lineedit
        total_widget_number = self.q2target_layout.count()
        self.total_lineedit_number = total_widget_number - 2  # - first : qlabel and plus and moins button + New lineedit
        lineedit_name = 'new_qtarget' + str(self.total_lineedit_number)
        setattr(self, lineedit_name, QLineEdit())
        getattr(self, lineedit_name).setFixedWidth(self.lineedit_width)
        self.target_lineedit_list.append(getattr(self, lineedit_name))
        self.q2target_layout.insertWidget(total_widget_number - 2,
                                          getattr(self, lineedit_name))

    def remove_one_qtarget(self):
        # count existing number of lineedit
        total_widget_number = self.q2target_layout.count()
        self.total_lineedit_number = total_widget_number - 3  # - first : qlabel and plus and moins button - New lineedit
        if self.total_lineedit_number > 0:
            self.target_lineedit_list.pop(-1)
            self.q2target_layout.itemAt(total_widget_number -
                                        3).widget().setParent(None)
            self.total_lineedit_number = self.total_lineedit_number - 1

    def reset_hydraulic_data_input_group(self):
        # remove txt in lineedit
        self.eq1.setText("")
        self.eq2.setText("")
        self.ew1.setText("")
        self.ew2.setText("")
        self.eh1.setText("")
        self.eh2.setText("")
        self.eq50.setText("")
        self.esub.setText("")

    def reset_hydraulic_data_output_group(self):
        # remove txt in lineedit
        self.eqmin.setText("")
        self.eqmax.setText("")
        # remove lineedits qtarget
        for i in reversed(range(1, self.q2target_layout.count() - 1)):
            self.q2target_layout.itemAt(i).widget().setParent(None)
            self.total_lineedit_number = self.total_lineedit_number - 1
        self.target_lineedit_list = []

    def reset_models_group(self):
        if self.selected_aquatic_animal_qtablewidget.count() > 0:
            self.selected_aquatic_animal_qtablewidget.clear()
            self.fill_fish_name()

    def read_estimhab_dict(self):
        """
        This function opens the json data created by estimhab
        """
        # load_project_properties
        self.estimhab_dict = load_specific_properties(self.path_prj,
                                                      [self.model_type])[0]

    def fill_fish_name(self):
        """
        This function reads all latin fish name from the xml files which are contained in the biological directory
        related to estimhab and fill GUI fish names
        """
        all_xmlfile = glob.glob(os.path.join(self.path_bio_estimhab, r'*.xml'))

        if self.estimhab_dict:
            selected_fish = self.estimhab_dict["fish_list"]
        else:
            selected_fish = []

        for f in all_xmlfile:
            # open xml
            try:
                try:
                    docxml = ET.parse(f)
                    root = docxml.getroot()
                except IOError:
                    self.send_log.emit(
                        self.tr("Warning: ") +
                        self.tr("The .habby project file ") + f +
                        self.tr(" could not be open.\n"))
                    return
            except ET.ParseError:
                self.send_log.emit(
                    self.tr("Warning: ") +
                    self.tr("The .habby project file ") + f +
                    self.tr(" is not well-formed.\n"))
                return

            # find fish name
            fish_name = root.find(".//LatinName")
            # None is null for python 3
            if fish_name is not None:
                fish_name = fish_name.text.strip()

            # find fish stage
            stage = root.find(".//estimhab/stage")
            # None is null for python 3
            if stage is not None:
                stage = stage.text.strip()
            if stage != 'all_stage':
                fish_name += ' ' + stage

            # check if not selected
            if fish_name not in selected_fish:
                # add to the list
                item = QListWidgetItem(fish_name)
                item.setData(1, f)
                self.list_f.addItem(item)
            else:
                # add to the list
                item2 = QListWidgetItem(fish_name)
                item2.setData(1, f)
                self.selected_aquatic_animal_qtablewidget.addItem(item2)

    def fill_input_data(self):
        if self.estimhab_dict:
            # input data
            self.eq1.setText(str(self.estimhab_dict["q"][0]))
            self.eq2.setText(str(self.estimhab_dict["q"][1]))
            self.eh1.setText(str(self.estimhab_dict["h"][0]))
            self.eh2.setText(str(self.estimhab_dict["h"][1]))
            self.ew1.setText(str(self.estimhab_dict["w"][0]))
            self.ew2.setText(str(self.estimhab_dict["w"][1]))
            self.eq50.setText(str(self.estimhab_dict["q50"]))
            self.eqmin.setText(str(self.estimhab_dict["qrange"][0]))
            self.eqmax.setText(str(self.estimhab_dict["qrange"][1]))
            self.esub.setText(str(self.estimhab_dict["substrate"]))
            # qtarg
            if len(self.estimhab_dict["qtarg"]) > 0:
                while self.total_lineedit_number != len(
                        self.estimhab_dict["qtarg"]):
                    self.add_new_qtarget()
                for qtarg_num, qtarg_value in enumerate(
                        self.estimhab_dict["qtarg"][1:]):
                    getattr(self, 'new_qtarget' + str(qtarg_num + 2)).setText(
                        str(qtarg_value))

    def check_if_ready_to_compute(self):
        all_string_selection = (self.eq1.text(), self.eq2.text(),
                                self.ew1.text(), self.ew2.text(),
                                self.eh1.text(), self.eh2.text(),
                                self.eq50.text(), self.eqmin.text(),
                                self.eqmax.text(), self.esub.text())
        # minimum one fish and string in input lineedits to enable run_stop_button
        if self.selected_aquatic_animal_qtablewidget.count(
        ) > 0 and "" not in all_string_selection:
            self.run_stop_button.setEnabled(True)
        else:
            self.run_stop_button.setEnabled(False)

    def change_folder(self):
        """
        A small method to change the folder which indicates where is the biological data
        """
        # user find new path
        self.path_bio_estimhab = QFileDialog.getExistingDirectory(
            self, self.tr("Open Directory"), os.getenv('HOME'))
        # update list
        self.list_f.clear()
        all_file = glob.glob(os.path.join(self.path_bio_estimhab, r'*.xml'))
        # make it look nicer
        for i in range(0, len(all_file)):
            all_file[i] = all_file[i].replace(self.path_bio_estimhab, "")
            all_file[i] = all_file[i].replace("\\", "")
            all_file[i] = all_file[i].replace(".xml", "")
            item = QListWidgetItem(all_file[i])
            # add them to the menu
            self.list_f.addItem(item)

    def run_estmihab(self):
        """
        A function to execute Estimhab by calling the estimhab function.

        **Technical comment**

        This is the function making the link between the GUI and the source code proper. The source code for Estimhab
        is in src/Estimhab.py.

        This function loads in memory the data given in the graphical interface and call sthe Estimhab model.
        The data could be written by the user now or it could be data which was saved in the hdf5 file before and
        loaded when HABBY was open (and the init function called).  We check that all necessary data is present and
        that the data given makes sense (e.g.,the minimum discharge should not be bigger than the maximal discharge,
        the data should be a float, etc.). We then remove the duplicate fish species (in case the user select one
        specie twice) and the Estimhab model is called. The log is then written (see the paragraph on the log for more
        information). Next, the figures created by Estimmhab are shown. As there is only a short number of outputs
        for Estimhab, we create a figure in all cases (it could be changed by adding a checkbox on the GUI like
        in the Telemac or other hydrological class).

        """
        # prepare data
        try:
            q = [
                float(self.eq1.text().replace(",", ".")),
                float(self.eq2.text().replace(",", "."))
            ]
            w = [
                float(self.ew1.text().replace(",", ".")),
                float(self.ew2.text().replace(",", "."))
            ]
            h = [
                float(self.eh1.text().replace(",", ".")),
                float(self.eh2.text().replace(",", "."))
            ]
            q50 = float(self.eq50.text().replace(",", "."))
            qrange = [
                float(self.eqmin.text().replace(",", ".")),
                float(self.eqmax.text().replace(",", "."))
            ]
            qtarget_values_list = []
            for qtarg_lineedit in self.target_lineedit_list:
                if qtarg_lineedit.text():
                    qtarget_values_list.append(
                        float(qtarg_lineedit.text().replace(",", ".")))
            substrate = float(self.esub.text().replace(",", "."))
        except ValueError:
            self.send_log.emit('Error: ' + self.tr(
                'Some data are empty or not float. Cannot run Estimhab'))
            return

        # get the list of xml file
        fish_list = []
        fish_name2 = []
        for i in range(0, self.selected_aquatic_animal_qtablewidget.count()):
            fish_item = self.selected_aquatic_animal_qtablewidget.item(i)
            fish_item_str = fish_item.text()
            fish_list.append(os.path.basename(fish_item.data(1)))
            fish_name2.append(fish_item_str)
        # check internal logic
        if not fish_list:
            self.send_log.emit(
                'Error: ' + self.tr('No fish selected. Cannot run Estimhab.'))
            return
        if qrange[0] >= qrange[1]:
            self.send_log.emit('Error: ' + self.tr(
                'Minimum discharge bigger or equal to max discharge. Cannot run Estimhab.'
            ))
            return
        if qtarget_values_list:
            for qtarg in qtarget_values_list:
                if qtarg < qrange[0] or qtarg > qrange[1]:
                    self.send_log.emit('Error: ' + self.tr(
                        'Target discharge is not between Qmin and Qmax. Cannot run Estimhab.'
                    ))
                    return
        if q[0] == q[1]:
            self.send_log.emit(
                'Error: ' +
                self.tr('Estimhab needs two differents measured discharges.'))
            return
        if h[0] == h[1]:
            self.send_log.emit(
                'Error: ' +
                self.tr('Estimhab needs two different measured height.'))
            return
        if w[0] == w[1]:
            self.send_log.emit(
                'Error: ' +
                self.tr('Estimhab needs two different measured width.'))
            return
        if (q[0] > q[1] and h[0] < h[1]) or (q[0] > q[1] and w[0] < w[1]) or (q[1] > q[0] and h[1] < h[0]) \
                or (q[1] > q[0] and w[1] < w[0]):
            self.send_log.emit(
                'Error: ' +
                self.tr('Discharge, width, and height data are not coherent.'))
            return
        if q[0] <= 0 or q[1] <= 0 or w[0] <= 0 or w[1] <= 0 or h[0] <= 0 or h[1] <= 0 or qrange[0] <= 0 or qrange[1] <= 0 \
                or substrate <= 0 or q50 <= 0:
            self.send_log.emit('Error: ' + self.tr(
                'Negative or zero data found. Could not run Estimhab.'))
            return
        if substrate > 3:
            self.send_log.emit(
                'Error: ' +
                self.tr('Substrate is too large. Could not run Estimhab.'))
            return

        self.send_log.emit(self.tr('# Computing: Estimhab...'))

        # check if the discharge range is realistic with the result
        self.qall = [q[0], q[1], qrange[0], qrange[1], q50]
        self.check_all_q()

        # run and save
        project_properties = load_project_properties(self.path_prj)
        sys.stdout = mystdout = StringIO()

        self.estimhab_dict = dict(q=q,
                                  w=w,
                                  h=h,
                                  q50=q50,
                                  qrange=qrange,
                                  qtarg=qtarget_values_list,
                                  substrate=substrate,
                                  path_bio=self.path_bio_estimhab,
                                  xml_list=fish_list,
                                  fish_list=fish_name2)

        # change_specific_properties
        change_specific_properties(self.path_prj, ["Estimhab"],
                                   [self.estimhab_dict])

        # process
        state = Value("d", 0)
        self.p = Process(target=estimhab_mod.estimhab_process,
                         args=(self.estimhab_dict, project_properties,
                               self.path_prj, state),
                         name="Estimhab")
        self.p.start()
        self.p.join()

        # plot
        plot_attr = lambda: None
        plot_attr.name_hdf5 = self.name_prj + '_ESTIMHAB' + '.hab'
        plot_attr.nb_plot = 1

        self.process_manager.set_estimhab_plot_mode(
            self.path_prj, plot_attr, load_project_properties(self.path_prj))
        self.process_manager.start()

        # log info
        str_found = mystdout.getvalue()
        str_found = str_found.split('\n')
        for i in range(0, len(str_found)):
            if len(str_found[i]) > 1:
                self.send_log.emit(str_found[i])

        self.send_log.emit(
            self.
            tr("Estimhab computation done. Figure and text files created in output project folder."
               ))
        self.send_log.emit("py    data = [" + str(q) + ',' + str(w) + ',' +
                           str(h) + ',' + str(q50) + ',' + str(substrate) +
                           ']')
        self.send_log.emit("py    qrange =[" + str(qrange[0]) + ',' +
                           str(qrange[1]) + ']')
        self.send_log.emit(
            "py    path1= os.path.join(os.path.dirname(path_bio),'" +
            self.path_bio_estimhab + "')")
        fish_list_str = "py    fish_list = ["
        for i in range(0, len(fish_list)):
            fish_list_str += "'" + fish_list[i] + "',"
        fish_list_str = fish_list_str[:-1] + ']'
        self.send_log.emit(fish_list_str)
        self.send_log.emit(
            "py    [OSI, WUA] = estimhab.estimhab(data[0], data[1], data[2], data[3] ,"
            " qrange, data[4], path1, fish_list, '.', True, {}, '.')\n")
Exemplo n.º 10
0
class VisualGroup(QGroupBoxCollapsible):
    """
    This class is a subclass of class QGroupBox.
    """

    def __init__(self, path_prj, name_prj, send_log, title):
        super().__init__()
        self.path_prj = path_prj
        self.name_prj = name_prj
        self.send_log = send_log
        self.path_last_file_loaded = self.path_prj
        self.process_manager = MyProcessManager("hs_plot")
        self.axe_mod_choosen = 1
        self.setTitle(title)
        self.init_ui()
        self.process_prog_show_input = ProcessProgShow(send_log=self.send_log,
                                                 run_function=self.plot_hs_class,
                                                 computation_pushbutton=self.input_class_plot_button)
        self.process_prog_show_area = ProcessProgShow(send_log=self.send_log,
                                                 run_function=self.plot_hs_area,
                                                 computation_pushbutton=self.result_plot_button_area)
        self.process_prog_show_volume = ProcessProgShow(send_log=self.send_log,
                                                 run_function=self.plot_hs_volume,
                                                 computation_pushbutton=self.result_plot_button_volume)

    def init_ui(self):
        # file_selection
        file_selection_label = QLabel(self.tr("HS files :"))
        self.file_selection_listwidget = QListWidget()
        self.file_selection_listwidget.itemSelectionChanged.connect(self.names_hdf5_change)
        file_selection_layout = QVBoxLayout()
        file_selection_layout.addWidget(file_selection_label)
        file_selection_layout.addWidget(self.file_selection_listwidget)

        # reach
        reach_label = QLabel(self.tr('reach(s)'))
        self.reach_QListWidget = QListWidget()
        self.reach_QListWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.reach_QListWidget.itemSelectionChanged.connect(self.reach_hdf5_change)
        reach_layout = QVBoxLayout()
        reach_layout.addWidget(reach_label)
        reach_layout.addWidget(self.reach_QListWidget)

        # units
        units_label = QLabel(self.tr('unit(s)'))
        self.units_QListWidget = QListWidget()
        self.units_QListWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.units_QListWidget.itemSelectionChanged.connect(self.unit_hdf5_change)
        units_layout = QVBoxLayout()
        units_layout.addWidget(units_label)
        units_layout.addWidget(self.units_QListWidget)

        # axe
        self.axe_mod_choosen = load_specific_properties(self.path_prj, ["hs_axe_mod"])[0]

        axe_label = QLabel(self.tr("Axe orientation :"))
        self.axe_mod_1_radio = QRadioButton()
        if self.axe_mod_choosen == 1:
            self.axe_mod_1_radio.setChecked(True)
        self.axe_mod_1_radio.setIcon(QIcon(r"file_dep/axe_mod_1.png"))
        self.axe_mod_1_radio.setIconSize(QSize(75, 75))
        self.axe_mod_1_radio.clicked.connect(self.change_axe_mod)

        self.axe_mod_2_radio = QRadioButton()
        if self.axe_mod_choosen == 2:
            self.axe_mod_2_radio.setChecked(True)
        self.axe_mod_2_radio.setIcon(QIcon(r"file_dep/axe_mod_2.png"))
        self.axe_mod_2_radio.setIconSize(QSize(75, 75))
        self.axe_mod_2_radio.clicked.connect(self.change_axe_mod)

        self.axe_mod_3_radio = QRadioButton()
        if self.axe_mod_choosen == 3:
            self.axe_mod_3_radio.setChecked(True)
        self.axe_mod_3_radio.setIcon(QIcon(r"file_dep/axe_mod_3.png"))
        self.axe_mod_3_radio.setIconSize(QSize(75, 75))
        self.axe_mod_3_radio.clicked.connect(self.change_axe_mod)

        axe_mod_layout = QHBoxLayout()
        axe_mod_layout.addWidget(self.axe_mod_1_radio)
        axe_mod_layout.addWidget(self.axe_mod_2_radio)
        axe_mod_layout.addWidget(self.axe_mod_3_radio)
        axe_layout = QVBoxLayout()
        axe_layout.addWidget(axe_label)
        axe_layout.addLayout(axe_mod_layout)
        axe_layout.addStretch()
        selection_layout = QHBoxLayout()
        selection_layout.addLayout(file_selection_layout)
        selection_layout.addLayout(reach_layout)
        selection_layout.addLayout(units_layout)
        selection_layout.addLayout(axe_layout)

        # input_class
        input_class_label = QLabel(self.tr("Input class :"))
        input_class_h_label = QLabel(self.tr("h (m)"))
        self.input_class_h_lineedit = QLineEdit("")
        input_class_v_label = QLabel(self.tr("v (m)"))
        self.input_class_v_lineedit = QLineEdit("")
        self.input_class_plot_button = QPushButton(self.tr("Show input"))
        self.input_class_plot_button.clicked.connect(self.plot_hs_class)
        change_button_color(self.input_class_plot_button, "#47B5E6")
        self.input_class_plot_button.setEnabled(False)
        input_class_layout = QGridLayout()
        input_class_layout.addWidget(input_class_label, 0, 0, 1, 2)
        input_class_layout.addWidget(input_class_h_label, 1, 0)
        input_class_layout.addWidget(input_class_v_label, 2, 0)
        input_class_layout.addWidget(self.input_class_h_lineedit, 1, 1)
        input_class_layout.addWidget(self.input_class_v_lineedit, 2, 1)
        input_class_layout.addWidget(self.input_class_plot_button, 1, 2, 2, 1)  # from row, from column, nb row, nb column

        # result
        result_label = QLabel(self.tr("Result :"))
        self.result_tableview = QTableView()
        self.result_tableview.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.result_tableview.verticalHeader().setVisible(False)
        self.result_tableview.horizontalHeader().setVisible(False)
        self.result_plot_button_area = QPushButton(self.tr("Show area"))
        self.result_plot_button_area.clicked.connect(self.plot_hs_area)
        self.result_plot_button_area.setEnabled(False)
        change_button_color(self.result_plot_button_area, "#47B5E6")
        self.result_plot_button_volume = QPushButton(self.tr("Show volume"))
        self.result_plot_button_volume.clicked.connect(self.plot_hs_volume)
        self.result_plot_button_volume.setEnabled(False)
        change_button_color(self.result_plot_button_volume, "#47B5E6")
        pushbutton_layout = QVBoxLayout()
        pushbutton_layout.addWidget(self.result_plot_button_area)
        pushbutton_layout.addWidget(self.result_plot_button_volume)
        result_layout = QGridLayout()
        result_layout.addWidget(result_label, 0, 0)
        result_layout.addWidget(self.result_tableview, 1, 0, 2, 1)
        result_layout.addLayout(pushbutton_layout, 1, 1)
        self.input_result_group = QGroupBox()
        input_result_layout = QVBoxLayout()
        input_result_layout.addLayout(input_class_layout)
        input_result_layout.addLayout(result_layout)
        self.input_result_group.setLayout(input_result_layout)
        self.input_result_group.hide()

        general_layout = QVBoxLayout()
        general_layout.addLayout(selection_layout)
        general_layout.addWidget(self.input_result_group)

        self.setLayout(general_layout)

    def update_gui(self):
        hs_names = get_filename_hs(os.path.join(self.path_prj, "hdf5"))
        self.file_selection_listwidget.blockSignals(True)
        self.file_selection_listwidget.clear()
        if hs_names:
            self.file_selection_listwidget.addItems(hs_names)
        self.file_selection_listwidget.blockSignals(False)

    def change_axe_mod(self):
        if self.axe_mod_1_radio.isChecked():
            self.axe_mod_choosen = 1
        elif self.axe_mod_2_radio.isChecked():
            self.axe_mod_choosen = 2
        elif self.axe_mod_3_radio.isChecked():
            self.axe_mod_choosen = 3
        change_specific_properties(self.path_prj, ["hs_axe_mod"], [self.axe_mod_choosen])

    def names_hdf5_change(self):
        self.reach_QListWidget.clear()
        self.units_QListWidget.clear()
        selection = self.file_selection_listwidget.selectedItems()
        if selection:
            # read
            hdf5name = selection[0].text()
            hdf5 = Hdf5Management(self.path_prj, hdf5name, new=False, edit=False)
            hdf5.get_hdf5_attributes(close_file=True)
            # check reach
            self.reach_QListWidget.addItems(hdf5.data_2d.reach_list)

            self.input_class_h_lineedit.setText(", ".join(list(map(str, hdf5.hs_input_class[0]))))
            self.input_class_v_lineedit.setText(", ".join(list(map(str, hdf5.hs_input_class[1]))))

            self.input_class_plot_button.setEnabled(True)

            self.toggle_group(False)
            self.input_result_group.show()
            self.toggle_group(True)

        else:
            self.input_result_group.hide()

    def reach_hdf5_change(self):
        selection_file = self.file_selection_listwidget.selectedItems()
        selection_reach = self.reach_QListWidget.selectedItems()
        self.units_QListWidget.clear()
        # one file selected
        if len(selection_reach) == 1:
            hdf5name = selection_file[0].text()

            # create hdf5 class
            hdf5 = Hdf5Management(self.path_prj, hdf5name, new=False, edit=False)
            hdf5.get_hdf5_attributes(close_file=True)

            # add units
            for item_text in hdf5.data_2d.unit_list[self.reach_QListWidget.currentRow()]:
                item = QListWidgetItem(item_text)
                item.setTextAlignment(Qt.AlignRight)
                self.units_QListWidget.addItem(item)

        if len(selection_reach) > 1:
            # add units
            item = QListWidgetItem("all units")
            item.setTextAlignment(Qt.AlignRight)
            self.units_QListWidget.addItem(item)
            self.units_QListWidget.selectAll()

    def unit_hdf5_change(self):
        selection_unit = self.units_QListWidget.selectedItems()
        # one file selected
        if len(selection_unit) > 0:
            hdf5name = self.file_selection_listwidget.selectedItems()[0].text()

            # create hdf5 class
            hdf5 = Hdf5Management(self.path_prj, hdf5name, new=False, edit=False)
            hdf5.load_hydrosignature()
            hdf5.close_file()

            if len(selection_unit) == 1 and selection_unit[0].text() == "all units":
                # get hs data
                hdf5.data_2d.get_hs_summary_data([element.row() for element in self.reach_QListWidget.selectedIndexes()],
                                                 list(range(hdf5.nb_unit)))
            else:
                # get hs data
                hdf5.data_2d.get_hs_summary_data([element.row() for element in self.reach_QListWidget.selectedIndexes()],
                                                 [element.row() for element in self.units_QListWidget.selectedIndexes()])

            # table
            mytablemodel = MyTableModel(hdf5.data_2d.hs_summary_data)
            self.result_tableview.setModel(mytablemodel)  # set model
            self.result_plot_button_area.setEnabled(True)
            self.result_plot_button_volume.setEnabled(True)
        else:
            mytablemodel = MyTableModel(["", ""])
            self.result_tableview.setModel(mytablemodel)  # set model
            self.result_plot_button_area.setEnabled(False)
            self.result_plot_button_volume.setEnabled(False)

    def plot_hs_class(self):
        plot_attr = lambda: None

        plot_attr.nb_plot = 1
        plot_attr.axe_mod_choosen = self.axe_mod_choosen
        plot_attr.hs_plot_type = "input_class"

        # process_manager
        self.process_manager.set_plot_hdf5_mode(self.path_prj,
                                                [self.file_selection_listwidget.selectedItems()[0].text()],
                                                plot_attr,
                                                load_project_properties(self.path_prj))

        # process_prog_show
        self.process_prog_show_input.start_show_prog(self.process_manager)

    def plot_hs_area(self):
        plot_attr = lambda: None

        plot_attr.axe_mod_choosen = self.axe_mod_choosen
        plot_attr.hs_plot_type = "area"
        plot_attr.reach = [element.row() for element in self.reach_QListWidget.selectedIndexes()]
        plot_attr.units = [element.row() for element in self.units_QListWidget.selectedIndexes()]
        plot_attr.nb_plot = len(plot_attr.units)

        # process_manager
        self.process_manager.set_plot_hdf5_mode(self.path_prj,
                                                [self.file_selection_listwidget.selectedItems()[0].text()],
                                                plot_attr,
                                                load_project_properties(self.path_prj))

        # process_prog_show
        self.process_prog_show_area.start_show_prog(self.process_manager)

    def plot_hs_volume(self):
        plot_attr = lambda: None

        plot_attr.axe_mod_choosen = self.axe_mod_choosen
        plot_attr.hs_plot_type = "volume"
        plot_attr.reach = [element.row() for element in self.reach_QListWidget.selectedIndexes()]
        plot_attr.units = [element.row() for element in self.units_QListWidget.selectedIndexes()]
        plot_attr.nb_plot = len(plot_attr.units)

        # process_manager
        self.process_manager.set_plot_hdf5_mode(self.path_prj,
                                                [self.file_selection_listwidget.selectedItems()[0].text()],
                                                plot_attr,
                                                load_project_properties(self.path_prj))

        # process_prog_show
        self.process_prog_show_volume.start_show_prog(self.process_manager)
Exemplo n.º 11
0
class ComputingGroup(QGroupBoxCollapsible):
    """
    This class is a subclass of class QGroupBox.
    """
    send_refresh_filenames = pyqtSignal(name='send_refresh_filenames')

    def __init__(self, path_prj, name_prj, send_log, title):
        super().__init__()
        self.path_prj = path_prj
        self.name_prj = name_prj
        self.send_log = send_log
        self.path_last_file_loaded = self.path_prj
        self.classhv = None
        self.project_properties = load_project_properties(self.path_prj)
        self.setTitle(title)
        self.init_ui()
        self.input_class_file_info = self.read_attribute_xml("HS_input_class")
        self.read_input_class(os.path.join(self.input_class_file_info["path"], self.input_class_file_info["file"]))
        # process_manager
        self.process_manager = MyProcessManager("hs")

    def init_ui(self):
        # file_selection
        file_selection_label = QLabel(self.tr("Select a 2D mesh file :"))
        self.file_selection_listwidget = QListWidget()
        self.file_selection_listwidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.file_selection_listwidget.itemSelectionChanged.connect(self.names_hdf5_change)
        self.file_selection_listwidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.file_selection_listwidget.verticalScrollBar().setEnabled(True)
        self.file_selection_listwidget.verticalScrollBar().valueChanged.connect(self.change_scroll_position)
        self.scrollbar = self.file_selection_listwidget.verticalScrollBar()
        file_computed_label = QLabel(self.tr("Computed ?"))
        self.hs_computed_listwidget = QListWidget()
        self.hs_computed_listwidget.setEnabled(False)
        self.hs_computed_listwidget.setFlow(QListView.TopToBottom)
        self.hs_computed_listwidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.hs_computed_listwidget.verticalScrollBar().setEnabled(True)
        self.hs_computed_listwidget.verticalScrollBar().valueChanged.connect(self.change_scroll_position)

        file_selection_layout = QGridLayout()
        file_selection_layout.addWidget(file_selection_label, 0, 0)
        file_selection_layout.addWidget(self.file_selection_listwidget, 1, 0)
        file_selection_layout.addWidget(file_computed_label, 0, 1)
        file_selection_layout.addWidget(self.hs_computed_listwidget, 1, 1)
        file_selection_layout.addWidget(self.scrollbar, 1, 2)
        file_selection_layout.setColumnStretch(0, 30)
        file_selection_layout.setColumnStretch(1, 1)

        input_class_label = QLabel(self.tr("Input class (.txt)"))
        self.input_class_filename = QLabel("")
        self.input_class_pushbutton = QPushButton("...")
        self.input_class_pushbutton.clicked.connect(self.select_input_class_dialog)
        hs_export_txt_label = QLabel(self.tr("Export results (.txt)"))
        self.hs_export_txt_checkbox = QCheckBox()
        self.hs_export_txt_checkbox.setChecked(True)
        hs_export_mesh_label = QLabel(self.tr("Export mesh results (.hyd or .hab)"))
        self.hs_export_mesh_checkbox = QCheckBox()

        """ progress layout """
        # progress_layout
        self.progress_layout = ProcessProgLayout(self.compute,
                                                 send_log=self.send_log,
                                                 process_type="hs",
                                                 send_refresh_filenames=self.send_refresh_filenames)

        grid_layout = QGridLayout()
        grid_layout.addWidget(input_class_label, 2, 0, Qt.AlignLeft)
        grid_layout.addWidget(self.input_class_filename, 2, 1, Qt.AlignLeft)
        grid_layout.addWidget(self.input_class_pushbutton, 2, 2, Qt.AlignLeft)
        grid_layout.addWidget(hs_export_txt_label, 3, 0, Qt.AlignLeft)
        grid_layout.addWidget(self.hs_export_txt_checkbox, 3, 1, Qt.AlignLeft)
        grid_layout.addWidget(hs_export_mesh_label, 4, 0, Qt.AlignLeft)
        grid_layout.addWidget(self.hs_export_mesh_checkbox, 4, 1, Qt.AlignLeft)
        grid_layout.addLayout(self.progress_layout, 5, 0, 1, 3)

        grid_layout.setColumnStretch(0, 2)
        grid_layout.setColumnStretch(1, 1)
        grid_layout.setColumnStretch(2, 1)
        grid_layout.setAlignment(Qt.AlignRight)

        general_layout = QVBoxLayout()
        general_layout.addLayout(file_selection_layout)
        general_layout.addLayout(grid_layout)

        self.setLayout(general_layout)

    def update_gui(self):
        selected_file_names = [selection_el.text() for selection_el in self.file_selection_listwidget.selectedItems()]
        # computing_group
        hyd_names = get_filename_by_type_physic("hydraulic", os.path.join(self.path_prj, "hdf5"))
        hab_names = get_filename_by_type_physic("habitat", os.path.join(self.path_prj, "hdf5"))
        names = hyd_names + hab_names
        self.file_selection_listwidget.blockSignals(True)
        self.file_selection_listwidget.clear()
        self.hs_computed_listwidget.blockSignals(True)
        self.hs_computed_listwidget.clear()
        if names:
            for name in names:
                # filename
                item_name = QListWidgetItem()
                item_name.setText(name)
                self.file_selection_listwidget.addItem(item_name)
                if name in selected_file_names:
                    item_name.setSelected(True)
                # check
                item = QListWidgetItem()
                item.setText("")
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
                try:
                    hdf5 = Hdf5Management(self.path_prj, name, new=False, edit=False)
                    hdf5.get_hdf5_attributes(close_file=True)
                    if hdf5.hs_calculated:
                        item.setCheckState(Qt.Checked)
                    else:
                        item.setCheckState(Qt.Unchecked)
                except:
                    self.send_log.emit(self.tr("Error: " + name + " file seems to be corrupted. Delete it with HABBY or manually."))
                self.hs_computed_listwidget.addItem(item)

                item.setTextAlignment(Qt.AlignCenter)

        self.file_selection_listwidget.blockSignals(False)
        self.hs_computed_listwidget.blockSignals(False)
        # preselection if one
        if self.file_selection_listwidget.count() == 1:
            self.file_selection_listwidget.selectAll()

    def change_scroll_position(self, index):
        self.file_selection_listwidget.verticalScrollBar().setValue(index)
        self.hs_computed_listwidget.verticalScrollBar().setValue(index)

    def read_input_class(self, input_class_file):
        if os.path.exists(input_class_file):
            self.classhv, warnings_list = hydrosignature_mod.hydraulic_class_from_file(input_class_file)
            if warnings_list:
                for warning in warnings_list:
                    self.send_log.emit(warning)
            if self.classhv is None:
                self.send_log.emit(self.tr("Error: Input class file : ") + os.path.basename(input_class_file) + self.tr(" is not valid."))
                self.progress_layout.run_stop_button.setEnabled(False)
            else:
                self.input_class_filename.setText(os.path.basename(input_class_file))
                if self.file_selection_listwidget.selectedItems():
                    self.progress_layout.run_stop_button.setEnabled(True)
        else:
            self.progress_layout.run_stop_button.setEnabled(False)

        self.progress_layout.progress_bar.setValue(0.0)
        self.progress_layout.progress_label.setText(
            "{0:.0f}/{1:.0f}".format(0.0, len(self.file_selection_listwidget.selectedItems())))

    def names_hdf5_change(self):
        selection = self.file_selection_listwidget.selectedItems()
        self.progress_layout.progress_bar.setValue(0.0)
        self.progress_layout.progress_label.setText(
            "{0:.0f}/{1:.0f}".format(0.0, len(selection)))
        if selection:
            # enable run button
            if self.input_class_filename.text():
                self.progress_layout.run_stop_button.setEnabled(True)
            else:
                self.progress_layout.run_stop_button.setEnabled(False)
        else:
            self.progress_layout.run_stop_button.setEnabled(False)

    def select_input_class_dialog(self):
        self.input_class_file_info = self.read_attribute_xml("HS_input_class")
        # get last path
        if self.input_class_file_info["path"] != self.path_prj and self.input_class_file_info["path"] != "":
            model_path = self.input_class_file_info["path"]  # path spe
        elif self.read_attribute_xml("path_last_file_loaded") != self.path_prj and self.read_attribute_xml("path_last_file_loaded") != "":
            model_path = self.read_attribute_xml("path_last_file_loaded")  # path last
        else:
            model_path = self.path_prj  # path proj

        filename, _ = QFileDialog.getOpenFileName(self, self.tr("Select hydraulic class file"),
                                                  model_path, self.tr("Text files") + " (*.txt)")
        if filename:
            self.pathfile = os.path.dirname(filename)  # source file path
            self.namefile = os.path.basename(filename)  # source file name
            self.save_xml("HS_input_class")
            self.read_input_class(filename)
            self.input_class_file_info = self.read_attribute_xml("HS_input_class")

    def read_attribute_xml(self, att_here):
        """
        A function to read the text of an attribute in the xml project file.

        :param att_here: the attribute name (string).
        """
        data = ''

        filename_path_pro = os.path.join(self.path_prj, self.name_prj + '.habby')
        if os.path.isfile(filename_path_pro):
            if att_here in {"path_last_file_loaded", "HS_input_class"}:
                data = load_project_properties(self.path_prj)[att_here]
            else:
                data = load_project_properties(self.path_prj)[att_here]["path"]
        else:
            pass

        return data

    def save_xml(self, attr):
        """
        A function to save the loaded data in the xml file.

        This function adds the name and the path of the newly chosen hydrological data to the xml project file. First,
        it open the xml project file (and send an error if the project is not saved, or if it cannot find the project
        file). Then, it opens the xml file and add the path and name of the file to this xml file. If the model data was
        already loaded, it adds the new name without erasing the old name IF the switch append_name is True. Otherwise,
        it erase the old name and replace it by a new name. The variable “i” has the same role than in select_file_and_show_informations_dialog.

        :param i: a int for the case where there is more than one file to load
        :param append_name: A boolean. If True, the name found will be append to the existing name in the xml file,
                instead of remplacing the old name by the new name.

        """
        filename_path_pro = os.path.join(self.path_prj, self.name_prj + '.habby')

        # save the name and the path in the xml .prj file
        if not os.path.isfile(filename_path_pro):
            self.end_log.emit('Error: The project is not saved. '
                              'Save the project in the General tab before saving hydrological data. \n')
        else:
            # change path_last_file_loaded, model_type (path)
            self.project_properties = load_project_properties(self.path_prj)  # load_project_properties
            self.project_properties["path_last_file_loaded"] = self.pathfile  # change value
            self.project_properties[attr]["file"] = self.namefile  # change value
            self.project_properties[attr]["path"] = self.pathfile  # change value
            save_project_properties(self.path_prj, self.project_properties)  # save_project_properties

    def compute(self):
        if len(self.file_selection_listwidget.selectedItems()) > 0:
            hydrosignature_description = dict(hs_export_mesh=self.hs_export_mesh_checkbox.isChecked(),
                                              hdf5_name_list=[selection_el.text() for selection_el in
                                                              self.file_selection_listwidget.selectedItems()],
                                              hs_export_txt=self.hs_export_txt_checkbox.isChecked(),
                                              classhv_input_class_file_info=self.input_class_file_info,
                                              classhv=self.classhv)

            self.progress_layout.process_manager.set_hs_hdf5_mode(self.path_prj,
                                                                  hydrosignature_description,
                                                                  self.project_properties)

            # start thread
            self.progress_layout.start_process()

    def stop_compute(self):
        # stop_by_user
        self.process_manager.stop_by_user()
Exemplo n.º 12
0
class InterpolationTab(QScrollArea):
    def __init__(self, path_prj, name_prj, send_log):
        super().__init__()
        self.tab_name = "interpolation"
        self.tab_title = "Interpolation"
        self.tooltip_str = self.tr("Interpolation of habitat values")
        self.path_prj = path_prj
        self.name_prj = name_prj
        self.send_log = send_log
        self.mytablemodel = None
        self.path_last_file_loaded = self.path_prj
        self.process_manager = MyProcessManager("interpolation")
        self.init_ui()
        self.process_prog_show = ProcessProgShow(send_log=self.send_log,
                                                 # progress_bar=self.nativeParentWidget().progress_bar,
                                                 # progress_label=self.progress_label,
                                                 run_function=self.plot_chronicle,
                                                 computation_pushbutton=self.plot_chronicle_qpushbutton)

    def init_ui(self):
        # insist on white background color (for linux, mac)
        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.white)
        self.setPalette(p)
        self.setWidgetResizable(True)
        self.setFrameShape(QFrame.NoFrame)
        # tools frame
        tools_frame = QFrame()
        tools_frame.setFrameShape(QFrame.NoFrame)
        tools_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        """ Available data """
        habitat_filenames_qlabel = QLabel(self.tr('Select an habitat file'))
        self.hab_filenames_qcombobox = QComboBox()
        self.hab_filenames_qcombobox.currentIndexChanged.connect(self.names_hab_change)
        habitat_reach_qlabel = QLabel(self.tr("Select a reach"))
        self.hab_reach_qcombobox = QComboBox()
        self.hab_reach_qcombobox.currentIndexChanged.connect(self.reach_hab_change)
        unit_min_title_qlabel = QLabel(self.tr("unit min :"))
        unit_max_title_qlabel = QLabel(self.tr("unit max :"))
        unit_type_title_qlabel = QLabel(self.tr("unit type :"))
        self.unit_min_qlabel = QLabel("")
        self.unit_max_qlabel = QLabel("")
        self.unit_type_qlabel = QLabel("")
        fish_available_qlabel = QLabel(self.tr('aquatic animal(s) :'))
        self.fish_available_qlistwidget = QListWidget()
        self.fish_available_qlistwidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.export_empty_text_pushbutton = QPushButton(self.tr("export empty required text file"))
        change_button_color(self.export_empty_text_pushbutton, "")
        self.export_empty_text_pushbutton.clicked.connect(self.export_empty_text_file)
        self.export_empty_text_pushbutton.setEnabled(False)

        available_firstlayout = QVBoxLayout()
        available_firstlayout.setAlignment(Qt.AlignTop)
        available_firstlayout.addWidget(habitat_filenames_qlabel)
        available_firstlayout.addWidget(self.hab_filenames_qcombobox)
        available_firstlayout.addWidget(habitat_reach_qlabel)
        available_firstlayout.addWidget(self.hab_reach_qcombobox)
        units_info_gridlayout = QGridLayout()
        available_firstlayout.addLayout(units_info_gridlayout)  # stretch factor
        available_firstlayout.addWidget(fish_available_qlabel)
        available_firstlayout.addWidget(self.fish_available_qlistwidget)
        available_firstlayout.addWidget(self.export_empty_text_pushbutton)
        units_info_gridlayout.addWidget(unit_min_title_qlabel, 0, 0)
        units_info_gridlayout.addWidget(unit_max_title_qlabel, 1, 0)
        units_info_gridlayout.addWidget(unit_type_title_qlabel, 2, 0)
        units_info_gridlayout.addWidget(self.unit_min_qlabel, 0, 1)
        units_info_gridlayout.addWidget(self.unit_max_qlabel, 1, 1)
        units_info_gridlayout.addWidget(self.unit_type_qlabel, 2, 1)

        """ Required data """
        # sequence layout
        fromsequence_group = QGroupBox(self.tr("from a sequence"))
        from_qlabel = QLabel(self.tr('min'))
        self.from_qlineedit = QLineEdit()
        self.from_qlineedit.returnPressed.connect(self.display_required_units_from_sequence)
        to_qlabel = QLabel(self.tr('max'))
        self.to_qlineedit = QLineEdit()
        self.to_qlineedit.returnPressed.connect(self.display_required_units_from_sequence)
        by_qlabel = QLabel(self.tr('by'))
        self.by_qlineedit = QLineEdit()
        self.by_qlineedit.returnPressed.connect(self.display_required_units_from_sequence)
        self.by_qlineedit.textEdited.connect(self.enable_seq_pushbutton)
        self.unit_qlabel = QLabel(self.tr('[]'))
        self.display_required_units_from_sequence_pushbutton = QPushButton(self.tr("run"))
        self.display_required_units_from_sequence_pushbutton.clicked.connect(self.display_required_units_from_sequence)
        change_button_color(self.display_required_units_from_sequence_pushbutton, "#47B5E6")
        self.display_required_units_from_sequence_pushbutton.setEnabled(False)
        require_secondlayout = QGridLayout()
        require_secondlayout.addWidget(from_qlabel, 1, 0)
        require_secondlayout.addWidget(self.from_qlineedit, 1, 1)
        require_secondlayout.addWidget(to_qlabel, 1, 2)
        require_secondlayout.addWidget(self.to_qlineedit, 1, 3)
        require_secondlayout.addWidget(by_qlabel, 1, 4)
        require_secondlayout.addWidget(self.by_qlineedit, 1, 5)
        require_secondlayout.addWidget(self.unit_qlabel, 1, 6)
        require_secondlayout.addWidget(self.display_required_units_from_sequence_pushbutton, 1, 7)
        fromsequence_group.setLayout(require_secondlayout)

        # txt layout
        fromtext_group = QGroupBox(self.tr("from .txt file"))
        self.fromtext_qpushbutton = QPushButton(self.tr('load and run'))
        change_button_color(self.fromtext_qpushbutton, "#47B5E6")
        self.fromtext_qpushbutton.clicked.connect(self.display_required_units_from_txtfile)
        fromtext_layout = QHBoxLayout()
        fromtext_layout.addWidget(self.fromtext_qpushbutton)
        fromtext_group.setLayout(fromtext_layout)

        """ Interpolated results """
        require_units_qlabel = QLabel(self.tr('desired units and interpolated habitat values :'))
        self.require_unit_qtableview = QTableView()
        self.require_unit_qtableview.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.require_unit_qtableview.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.require_unit_qtableview.verticalHeader().setVisible(True)
        self.require_unit_qtableview.horizontalHeader().setVisible(True)
        self.require_unit_qtableview.setMinimumHeight(350)
        mytablemodel = MyTableModelHab("", "", "", "")
        self.require_unit_qtableview.setModel(mytablemodel)

        plot_chronicle_label = QLabel(self.tr("View interpolate chronicle :"))
        export_txt_chronicle_label = QLabel(self.tr("Export interpolate chronicle :"))
        self.plot_chronicle_qpushbutton = QPushButton(self.tr('run'))
        change_button_color(self.plot_chronicle_qpushbutton, "#47B5E6")
        self.plot_chronicle_qpushbutton.clicked.connect(self.plot_chronicle)
        self.plot_chronicle_qpushbutton.setEnabled(False)
        self.export_txt_chronicle_qpushbutton = QPushButton(self.tr('run'))
        change_button_color(self.export_txt_chronicle_qpushbutton, "#47B5E6")
        self.export_txt_chronicle_qpushbutton.clicked.connect(self.export_chronicle)
        self.export_txt_chronicle_qpushbutton.setEnabled(False)

        """ Available data """
        available_data_layout = QHBoxLayout()
        available_data_layout.addLayout(available_firstlayout)
        self.available_data_group = QGroupBoxCollapsible(self.tr("Available data"))
        self.available_data_group.setChecked(True)
        self.available_data_group.setLayout(available_data_layout)

        """ Required data """
        self.require_data_layout = QVBoxLayout()
        self.require_data_group = QGroupBoxCollapsible(self.tr("Desired data"))
        self.require_data_group.hide()
        self.require_data_group.setChecked(False)
        self.require_data_group.setLayout(self.require_data_layout)

        require_first_layout = QHBoxLayout()
        require_first_layout.addWidget(fromsequence_group)
        require_first_layout.addWidget(fromtext_group)
        self.require_data_layout.addLayout(require_first_layout)

        """ Interpolated results """
        self.interpolated_results_group = QGroupBoxCollapsible(self.tr("Interpolated results"))
        self.interpolated_results_group.hide()
        self.interpolated_results_group.setChecked(False)
        require_unit_layout = QVBoxLayout()
        require_unit_layout.addWidget(require_units_qlabel)
        require_unit_layout.addWidget(self.require_unit_qtableview)
        plot_export_layout = QGridLayout()
        plot_export_layout.addWidget(plot_chronicle_label, 0, 0)
        plot_export_layout.addWidget(export_txt_chronicle_label, 0, 1)
        plot_export_layout.addWidget(self.plot_chronicle_qpushbutton, 1, 0)
        plot_export_layout.addWidget(self.export_txt_chronicle_qpushbutton, 1, 1)
        require_unit_layout.addLayout(plot_export_layout)

        unit_hv_layout = QHBoxLayout()
        unit_hv_layout.addLayout(require_unit_layout)
        self.interpolated_results_group.setLayout(unit_hv_layout)

        # vertical layout
        global_layout = QVBoxLayout()
        global_layout.setAlignment(Qt.AlignTop)
        tools_frame.setLayout(global_layout)
        global_layout.addWidget(self.available_data_group)
        global_layout.addWidget(self.require_data_group)
        global_layout.addWidget(self.interpolated_results_group)
        # global_layout.addStretch()
        self.setWidget(tools_frame)
        self.refresh_gui()

    def refresh_gui(self):
        # get list of file name by type
        names = get_filename_by_type_physic("habitat", os.path.join(self.path_prj, "hdf5"))
        current_index = self.hab_filenames_qcombobox.currentIndex()
        # self.hab_filenames_qcombobox.blockSignals(True)
        self.hab_filenames_qcombobox.clear()
        if names:
            if current_index == -1:
                current_index = 1
            # append_empty_element_to_list
            names = [""] + names
            # change list widget
            self.hab_filenames_qcombobox.addItems(names)
            self.hab_filenames_qcombobox.setCurrentIndex(current_index)
        # self.hab_filenames_qcombobox.blockSignals(False)

    def disable_and_clean_group_widgets(self, disable):
        """
        Disable and clean widgets.
        :param checker:
        :return:
        """
        self.require_data_group.show()
        self.require_data_group.setChecked(True)
        # available
        self.unit_min_qlabel.setText("")
        self.unit_max_qlabel.setText("")
        self.unit_type_qlabel.setText("")
        self.fish_available_qlistwidget.clear()
        self.export_empty_text_pushbutton.setDisabled(disable)
        # desired
        self.from_qlineedit.setText("")
        self.from_qlineedit.setDisabled(disable)
        self.to_qlineedit.setText("")
        self.to_qlineedit.setDisabled(disable)
        self.by_qlineedit.setText("")
        self.by_qlineedit.setDisabled(disable)
        self.fromtext_qpushbutton.setDisabled(disable)
        self.require_unit_qtableview.model().clear()
        if disable:
            self.interpolated_results_group.hide()
            # disable pushbutton
            self.plot_chronicle_qpushbutton.setDisabled(disable)
            self.export_txt_chronicle_qpushbutton.setDisabled(disable)

    def names_hab_change(self):
        """
        Ajust item list according to hdf5 filename selected by user
        """
        hdf5name = self.hab_filenames_qcombobox.currentText()
        # no file
        if not hdf5name:
            # clean
            self.hab_reach_qcombobox.clear()
            self.require_data_group.hide()
        # file
        if hdf5name:
            # clean
            self.hab_reach_qcombobox.clear()
            # create hdf5 class to get hdf5 inforamtions
            hdf5 = Hdf5Management(self.path_prj, hdf5name, new=False, edit=False)
            if hdf5.file_object:
                hdf5.get_hdf5_attributes(close_file=True)
                if len(hdf5.data_2d.reach_list) == 1:
                    reach_names = hdf5.data_2d.reach_list
                else:
                    reach_names = [""] + hdf5.data_2d.reach_list

                unit_type = hdf5.data_2d.unit_type
                if "Date" not in unit_type:
                    self.hab_reach_qcombobox.addItems(reach_names)
                else:
                    if self.sender().hasFocus():
                        self.send_log.emit(self.tr("Warning: This file contain date unit. "
                                                   "To be interpolated, file must contain discharge or timestep unit."))

    def reach_hab_change(self):
        hdf5name = self.hab_filenames_qcombobox.currentText()
        reach_name = self.hab_reach_qcombobox.currentText()
        self.unit_qlabel.setText("[]")
        # no file
        if not reach_name:
            # clean
            self.disable_and_clean_group_widgets(True)
        # file
        if reach_name:
            # clean
            self.disable_and_clean_group_widgets(False)
            # clean
            hdf5 = Hdf5Management(self.path_prj, hdf5name, new=False, edit=False)
            hdf5.get_hdf5_attributes(close_file=True)
            unit_type = hdf5.data_2d.unit_type
            unit_type = unit_type.replace("m3/s", "m<sup>3</sup>/s")
            unit_type_value = unit_type[unit_type.index("["):unit_type.index("]")+1]
            reach_index = hdf5.data_2d.reach_list.index(reach_name)
            units_name = hdf5.data_2d.unit_list[reach_index]

            # hab
            if hdf5.data_2d.hvum.hdf5_and_computable_list.habs().meshs().names_gui():
                for mesh in hdf5.data_2d.hvum.hdf5_and_computable_list.habs().meshs():
                    mesh_item = QListWidgetItem(mesh.name_gui, self.fish_available_qlistwidget)
                    mesh_item.setData(Qt.UserRole, mesh)
                    self.fish_available_qlistwidget.addItem(mesh_item)
                self.fish_available_qlistwidget.selectAll()
                # set min and max unit for from to by
            unit_number_list = list(map(float, units_name))
            min_unit = min(unit_number_list)
            max_unit = max(unit_number_list)
            self.unit_min_qlabel.setText(str(min_unit))
            self.unit_max_qlabel.setText(str(max_unit))
            self.unit_type_qlabel.setText(unit_type)
            # sequence
            if len(unit_number_list) > 1:
                self.from_qlineedit.setText(str(min_unit))
                self.to_qlineedit.setText(str(max_unit))
                self.unit_qlabel.setText(unit_type_value)
            elif len(unit_number_list) == 1:
                pass
                # self.send_log.emit("Warning: " + self.tr("Interpolation need at least two time/discharge unit. "
                #                                          "Their is only one is this file."))

    def enable_seq_pushbutton(self):
        if self.by_qlineedit.text():
            self.display_required_units_from_sequence_pushbutton.setEnabled(True)
        else:
            self.display_required_units_from_sequence_pushbutton.setEnabled(False)

    def display_required_units_from_sequence(self):
        from_sequ = self.from_qlineedit.text().replace(",", ".")
        to_sequ = self.to_qlineedit.text().replace(",", ".")
        by_sequ = self.by_qlineedit.text().replace(",", ".")

        # is string
        if from_sequ == "" or to_sequ == "" or by_sequ == "":
            self.send_log.emit('Error: ' + self.tr('The sequence values must be specified (from, to and by).'))
            return

        # is float string
        if not isstranumber(from_sequ) or not isstranumber(to_sequ) or not isstranumber(by_sequ):
            self.send_log.emit('Error: ' + self.tr('The sequence values must be of numerical type.'))
            return

        # is float min < max
        if not float(from_sequ) < float(to_sequ):
            self.send_log.emit('Error: ' + self.tr('Max sequence value must be strictly greater than min sequence value.'))
            return

        # is by > 0
        if not float(by_sequ) > 0:
            self.send_log.emit('Error: ' + self.tr('By sequence value must be strictly greater than 0.'))
            return

        # is fish selected
        selection = self.fish_available_qlistwidget.selectedItems()
        if not selection:
            self.send_log.emit('Error: ' + self.tr('No fish selected.'))
            return

        # ok
        else:
            from_sequ = float(from_sequ)  # from
            to_sequ = float(to_sequ)  # to
            by_sequ = float(by_sequ)  # by

            # dict range
            chonicle_from_seq = dict(units=list(frange(from_sequ, to_sequ, by_sequ)))

            # types
            text_unit = self.unit_type_qlabel.text()
            types_from_seq = dict(units=text_unit)  # #[text_unit.find('[') + 1:text_unit.find(']')]

            # display
            self.create_model_array_and_display(chonicle_from_seq, types_from_seq, source="seq")

    def display_required_units_from_txtfile(self):
        # is fish ?
        selection = self.fish_available_qlistwidget.selectedItems()
        if not selection:
            self.send_log.emit('Error: ' + self.tr('No fish selected.'))
            return

        # find the filename based on user choice
        filename_path = QFileDialog.getOpenFileName(self,
                                                    self.tr("Select file"),
                                                    self.path_last_file_loaded,
                                                    "File (*.txt)")[0]

        self.path_last_file_loaded = os.path.dirname(filename_path)

        # exeption: you should be able to clik on "cancel"
        if filename_path:
            chronicle_from_file, types_from_file = read_chronicle_from_text_file(filename_path)

            if not chronicle_from_file:
                self.send_log.emit(types_from_file)
            if chronicle_from_file:
                # display
                self.create_model_array_and_display(chronicle_from_file, types_from_file, source=filename_path)

    def create_model_array_and_display(self, chronicle, types, source):
        hvum = HydraulicVariableUnitManagement()
        # get fish selected
        for selection in self.fish_available_qlistwidget.selectedItems():
            hvum.user_target_list.append(selection.data(Qt.UserRole))

        # get filename
        hdf5name = self.hab_filenames_qcombobox.currentText()

        # load hdf5 data
        hdf5 = Hdf5Management(self.path_prj, hdf5name, new=False, edit=False)
        hdf5.get_hdf5_attributes(close_file=True)

        # get reach_name
        reach_index = hdf5.data_2d.reach_list.index(self.hab_reach_qcombobox.currentText())

        # check matching units for interpolation
        valid, text = check_matching_units(hdf5.data_2d.unit_type, types)

        if not valid:
            self.send_log.emit("Warning: " + self.tr("Interpolation not done.") + text)
            # disable pushbutton
            self.plot_chronicle_qpushbutton.setEnabled(False)
            self.export_txt_chronicle_qpushbutton.setEnabled(False)
        if valid:
            data_to_table, horiz_headers, vertical_headers = compute_interpolation(hdf5.data_2d,
                                                                                         hvum.user_target_list,
                                                                                         reach_index,
                                                                                         chronicle,
                                                                                         types,
                                                                                         rounddata=True)
            for horiz_header_num, horiz_header in enumerate(horiz_headers):
                horiz_headers[horiz_header_num] = horiz_header.replace("m<sup>3</sup>/s", "m3/s")

            self.mytablemodel = MyTableModelHab(data_to_table, horiz_headers, vertical_headers, source=source)
            self.require_unit_qtableview.model().clear()
            self.require_unit_qtableview.setModel(self.mytablemodel)  # set model
            # ajust width
            header = self.require_unit_qtableview.horizontalHeader()
            for i in range(len(horiz_headers)):
                header.setSectionResizeMode(i, QHeaderView.ResizeToContents)
            self.require_unit_qtableview.verticalHeader().setDefaultSectionSize(
                self.require_unit_qtableview.verticalHeader().minimumSectionSize())
            self.plot_chronicle_qpushbutton.setEnabled(True)
            self.export_txt_chronicle_qpushbutton.setEnabled(True)
            self.send_log.emit(self.tr("Interpolation done. Interpolated values can now be view in graphic and export in text file."))
            # disable pushbutton
            self.plot_chronicle_qpushbutton.setEnabled(True)
            self.export_txt_chronicle_qpushbutton.setEnabled(True)
            self.interpolated_results_group.show()
            self.interpolated_results_group.setChecked(True)

    def export_empty_text_file(self):
        hdf5name = self.hab_filenames_qcombobox.currentText()
        if hdf5name:
            # create hdf5 class
            hdf5 = Hdf5Management(self.path_prj, hdf5name, new=False, edit=False)
            # get hdf5 inforamtions
            hdf5.get_hdf5_attributes(close_file=True)
            unit_type = hdf5.data_2d.unit_type
            units_name = hdf5.data_2d.unit_list[self.hab_reach_qcombobox.currentIndex()]
            unit_number = list(map(float, units_name))
            min_unit = min(unit_number)
            max_unit = max(unit_number)

            # export
            exported = export_empty_text_from_hdf5(unit_type, min_unit, max_unit, hdf5name, self.path_prj)
            if exported:
                self.send_log.emit(self.tr("Empty text has been exported in 'output/text' project folder. Open and fill it "
                                   "with the desired values and then import it in HABBY."))
            if not exported:
                self.send_log.emit('Error: ' + self.tr('The file has not been exported as it may be opened by another program.'))

    def plot_chronicle(self):
        hvum = HydraulicVariableUnitManagement()
        # get fish selected
        for selection in self.fish_available_qlistwidget.selectedItems():
            hvum.user_target_list.append(selection.data(Qt.UserRole))

        # get filename
        hdf5name = self.hab_filenames_qcombobox.currentText()

        if not hdf5name:
            self.send_log.emit('Error: ' + self.tr('No .hab selected.'))
            return

        if self.mytablemodel:
            # max
            if len(hvum.user_target_list) > 32:
                self.send_log.emit('Warning: ' + self.tr(
                    'You cannot display more than 32 habitat values per graph. Current selected : ') + str(
                    len(hvum.user_target_list)) + ". " + self.tr("Only the first 32 will be displayed.") + " " + self.tr(
                    'You have to re-compute interpolation with 32 selected habitat values at maximum. There is no limit for txt exports.'))
                hvum.user_target_list = hvum.user_target_list[:32]

            # seq or txt
            source = self.mytablemodel.source

            # reread from seq (tablemodel)
            if source == "seq":
                units = dict(units=list(map(float, self.mytablemodel.rownames)))
                unit_type = dict(units=self.unit_type_qlabel.text())
            # reread from text file (re-read file)
            else:
                units, unit_type = read_chronicle_from_text_file(source)

            # load figure option
            project_properties = load_project_properties(self.path_prj)

            interp_attr = lambda: None
            interp_attr.reach = self.hab_reach_qcombobox.currentText()
            interp_attr.units = units
            interp_attr.unit_type = unit_type
            interp_attr.hvum = hvum
            interp_attr.mode = "plot"
            # process_manager
            self.process_manager.set_interpolation_hdf5_mode(self.path_prj,
                                                    self.hab_filenames_qcombobox.currentText(),
                                                    interp_attr,
                                                    project_properties)

            # process_prog_show
            self.process_prog_show.start_show_prog(self.process_manager)

    def export_chronicle(self):
        hvum = HydraulicVariableUnitManagement()
        # get fish selected
        for selection in self.fish_available_qlistwidget.selectedItems():
            hvum.user_target_list.append(selection.data(Qt.UserRole))

        # get filename
        hdf5name = self.hab_filenames_qcombobox.currentText()
        if not hdf5name:
            self.send_log.emit('Error: ' + self.tr('No .hab selected.'))
            return

        if self.mytablemodel:
            # fish names and units names from tableview
            fish_names_osi_wua = self.mytablemodel.colnames
            fish_names = []
            for fish in fish_names_osi_wua:
                if "osi_" in fish:
                    fish_names.append(fish.replace("osi_", ""))
                if "wua_" in fish:
                    fish_names.append(fish.replace("wua_", ""))

            # seq or txt
            source = self.mytablemodel.source

            # reread from seq (tablemodel)
            if source == "seq":
                units = dict(units=list(map(float, self.mytablemodel.rownames)))
                # types
                text_unit = self.unit_type_qlabel.text()
                unit_type = dict(units=text_unit[text_unit.find('[') + 1:text_unit.find(']')])
            # reread from text file (re-read file)
            else:
                units, unit_type = read_chronicle_from_text_file(source)

            # load figure option
            project_properties = load_project_properties(self.path_prj)

            interp_attr = lambda: None
            interp_attr.reach = self.hab_reach_qcombobox.currentText()
            interp_attr.units = units
            interp_attr.unit_type = unit_type
            interp_attr.hvum = hvum
            interp_attr.mode = "export"

            # process_manager
            self.process_manager.set_interpolation_hdf5_mode(self.path_prj,
                                                             hdf5name,
                                                             interp_attr,
                                                             project_properties)

            # process_prog_show
            self.process_prog_show.start_show_prog(self.process_manager)
Exemplo n.º 13
0
class ComputingGroup(QGroupBoxCollapsible):
    """
    This class is a subclass of class QGroupBox.
    """
    send_refresh_filenames = pyqtSignal(name='send_refresh_filenames')

    def __init__(self, path_prj, name_prj, send_log, title):
        super().__init__()
        self.path_prj = path_prj
        self.name_prj = name_prj
        self.send_log = send_log
        self.path_last_file_loaded = self.path_prj
        self.project_properties = load_project_properties(self.path_prj)
        self.setTitle(title)
        self.init_ui()
        # process_manager
        self.process_manager = MyProcessManager("hrr")

    def init_ui(self):
        # file_selection
        file_selection_label = QLabel(self.tr("Select a 2D mesh file :"))
        self.file_selection_listwidget = QListWidget()
        self.file_selection_listwidget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.file_selection_listwidget.itemSelectionChanged.connect(
            self.names_hdf5_change)
        self.file_selection_listwidget.setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff)
        self.file_selection_listwidget.verticalScrollBar().setEnabled(True)
        self.file_selection_listwidget.verticalScrollBar(
        ).valueChanged.connect(self.change_scroll_position)
        self.scrollbar = self.file_selection_listwidget.verticalScrollBar()

        file_selection_layout = QGridLayout()
        file_selection_layout.addWidget(file_selection_label, 0, 0)
        file_selection_layout.addWidget(self.file_selection_listwidget, 1, 0)
        file_selection_layout.addWidget(self.scrollbar, 1, 2)
        file_selection_layout.setColumnStretch(0, 30)
        file_selection_layout.setColumnStretch(1, 1)
        """ progress layout """
        # progress_layout
        self.progress_layout = ProcessProgLayout(
            self.compute,
            send_log=self.send_log,
            process_type="hrr",
            send_refresh_filenames=self.send_refresh_filenames)

        grid_layout = QGridLayout()
        grid_layout.addLayout(self.progress_layout, 5, 0, 1, 3)

        general_layout = QVBoxLayout()
        general_layout.addLayout(file_selection_layout)
        general_layout.addLayout(grid_layout)

        self.setLayout(general_layout)

    def update_gui(self):
        selected_file_names = [
            selection_el.text()
            for selection_el in self.file_selection_listwidget.selectedItems()
        ]
        # computing_group
        hyd_names = get_filename_by_type_physic(
            "hydraulic", os.path.join(self.path_prj, "hdf5"))
        names = hyd_names
        self.file_selection_listwidget.blockSignals(True)
        self.file_selection_listwidget.clear()
        if names:
            for name in names:
                # check
                try:
                    hdf5 = Hdf5Management(self.path_prj,
                                          name,
                                          new=False,
                                          edit=False)
                    hdf5.get_hdf5_attributes(close_file=True)
                    item_name = QListWidgetItem()
                    item_name.setText(name)
                    self.file_selection_listwidget.addItem(item_name)
                    if True:  #TODO : sort files (hdf5 attributes available for HRR) .hyd, one whole profile for all units, ...
                        pass
                    else:
                        pass
                except:
                    self.send_log.emit(
                        self.
                        tr("Error: " + name +
                           " file seems to be corrupted. Delete it with HABBY or manually."
                           ))

        self.file_selection_listwidget.blockSignals(False)
        # preselection if one
        if self.file_selection_listwidget.count() == 1:
            self.file_selection_listwidget.selectAll()

    def change_scroll_position(self, index):
        self.file_selection_listwidget.verticalScrollBar().setValue(index)

    def names_hdf5_change(self):
        selection = self.file_selection_listwidget.selectedItems()
        self.progress_layout.progress_bar.setValue(0.0)
        self.progress_layout.progress_label.setText("{0:.0f}/{1:.0f}".format(
            0.0, len(selection)))
        if selection:
            self.progress_layout.run_stop_button.setEnabled(True)
        else:
            self.progress_layout.run_stop_button.setEnabled(False)

    def compute(self):
        if len(self.file_selection_listwidget.selectedItems()) > 0:
            hrr_description = dict(
                deltatlist=[],
                hdf5_name_list=[
                    selection_el.text() for selection_el in
                    self.file_selection_listwidget.selectedItems()
                ])

            self.progress_layout.process_manager.set_hrr_hdf5_mode(
                self.path_prj, hrr_description, self.project_properties)

            # start thread
            self.progress_layout.start_process()

    def stop_compute(self):
        # stop_by_user
        self.process_manager.stop_by_user()