def _initWidget(self):
        # create two 3-column tables for variables selection
        self.firstTable = VariableTable()
        self.secondTable = VariableTable()

        # create the options
        self.intersect = QCheckBox()
        self.intersect.setChecked(True)
        self.timeSelection = SimpleTimeDateSelection()
        self.referenceLine = QComboBox()

        # create the submit button
        self.btnSubmit = QPushButton('Submit\nto .csv',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Write</b> output to .csv')
        self.btnSubmit.setFixedSize(105, 50)
        self.btnSubmit.setEnabled(False)

        # create the output file name box
        self.csvNameBox = QLineEdit()
        self.csvNameBox.setReadOnly(True)
        self.csvNameBox.setFixedHeight(30)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)
Beispiel #2
0
    def _initWidgets(self):
        # create a slider for time selection
        self.timeSlider = TimeRangeSlider()
        self.timeSlider.setFixedHeight(30)
        self.timeSlider.setMinimumWidth(600)
        self.timeSlider.setEnabled(False)

        # create a button for add condition
        self.btnAdd = QPushButton('Add new condition')
        self.btnAdd.setFixedSize(135, 50)

        # create a table for created condition
        self.conditionTable = QTableWidget()
        self.conditionTable.setColumnCount(3)
        self.conditionTable.setHorizontalHeaderLabels(
            ['Condition', 'Arrival', 'Duration'])
        vh = self.conditionTable.verticalHeader()
        vh.setSectionResizeMode(QHeaderView.Fixed)
        vh.setDefaultSectionSize(20)
        hh = self.conditionTable.horizontalHeader()
        hh.setDefaultSectionSize(150)
        self.conditionTable.setMaximumHeight(500)

        # create text boxes for displaying the time selection
        self.timeSelection = TimeSelection(self)
        self.timeSelection.startIndex.setEnabled(False)
        self.timeSelection.endIndex.setEnabled(False)
        self.timeSelection.startValue.setEnabled(False)
        self.timeSelection.endValue.setEnabled(False)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

        # create a combo box for time unit
        self.unitBox = QComboBox()
        for unit in ['second', 'minute', 'hour', 'day', 'percentage']:
            self.unitBox.addItem(unit)
        self.unitBox.setFixedHeight(30)
        self.unitBox.setMaximumWidth(200)

        # create a check box for output file format (simple or double precision)
        self.singlePrecisionBox = QCheckBox(
            'Convert to SERAFIN \n(single precision)', self)
        self.singlePrecisionBox.setEnabled(False)

        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b> to write a Serafin output')
        self.btnSubmit.setFixedSize(105, 50)
        self.btnSubmit.setEnabled(False)
Beispiel #3
0
    def _initWidgets(self):
        # create a checkbox for operation selection
        self.opBox = QGroupBox('Compute')
        hlayout = QHBoxLayout()
        self.maxButton = QRadioButton('Max')
        self.minButton = QRadioButton('Min')
        meanButton = QRadioButton('Mean')

        hlayout.addWidget(self.maxButton)
        hlayout.addWidget(self.minButton)
        hlayout.addWidget(meanButton)

        self.opBox.setLayout(hlayout)
        self.opBox.setMaximumHeight(80)
        self.opBox.setMaximumWidth(200)
        self.maxButton.setChecked(True)

        # create a slider for time selection
        self.timeSlider = TimeRangeSlider()
        self.timeSlider.setFixedHeight(30)
        self.timeSlider.setMinimumWidth(600)
        self.timeSlider.setEnabled(False)

        # create text boxes for displaying the time selection
        self.timeSelection = TimeSelection(self)
        self.timeSelection.startIndex.setEnabled(False)
        self.timeSelection.endIndex.setEnabled(False)
        self.timeSelection.startValue.setEnabled(False)
        self.timeSelection.endValue.setEnabled(False)

        # create two 3-column tables for variables selection
        self.firstTable = VariableTable()
        self.secondTable = VariableTable()
        self.secondTable.setMinimumHeight(300)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

        # create a check box for output file format (simple or double precision)
        self.singlePrecisionBox = QCheckBox(
            'Convert to SERAFIN \n(single precision)', self)
        self.singlePrecisionBox.setEnabled(False)

        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b> to write a Serafin output')
        self.btnSubmit.setFixedSize(105, 50)
        self.btnSubmit.setEnabled(False)
Beispiel #4
0
    def __init__(self, inputTab, timeSelection, parent):
        super().__init__()
        self.inputTab = inputTab
        self.data = None
        self.timeSelection = timeSelection
        self.parent = parent

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

        # create a check box for output file format (simple or double precision)
        self.singlePrecisionBox = QCheckBox(
            'Convert to SERAFIN \n(single precision)', self)
        self.singlePrecisionBox.setEnabled(False)

        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b> to write a Serafin output')
        self.btnSubmit.setFixedSize(105, 50)
        self.btnSubmit.setEnabled(False)

        # bind events
        self.btnSubmit.clicked.connect(self.btnSubmitEvent)

        # set layout
        mainLayout = QVBoxLayout()
        mainLayout.addItem(QSpacerItem(50, 20))
        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.btnSubmit)
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.singlePrecisionBox)
        hlayout.addItem(QSpacerItem(50, 10))
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(30, 15))
        mainLayout.addWidget(QLabel('   Message logs'))
        mainLayout.addWidget(self.logTextBox.widget)
        self.setLayout(mainLayout)
    def _initWidgets(self):
        """!
        @brief (Used in __init__) Create widgets
        """
        # create the group box for coordinate transformation
        self.confBox = QGroupBox('Apply coordinate transformation (optional)')
        self.confBox.setStyleSheet(
            'QGroupBox {font-size: 12px;font-weight: bold;}')
        self.btnConfig = QPushButton('Load\nTransformation', self)
        self.btnConfig.setToolTip('<b>Open</b> a transformation config file')
        self.btnConfig.setFixedSize(105, 50)
        self.confNameBox = QLineEdit()
        self.confNameBox.setReadOnly(True)
        self.confNameBox.setFixedHeight(30)
        self.fromBox = QComboBox()
        self.fromBox.setFixedWidth(150)
        self.toBox = QComboBox()
        self.toBox.setFixedWidth(150)

        # create the open button
        self.btnOpen = QPushButton('Open',
                                   self,
                                   icon=self.style().standardIcon(
                                       QStyle.SP_DialogOpenButton))
        self.btnOpen.setToolTip(
            '<b>Open</b> a geometry file (.shp .xyz .i2s .i3s)')
        self.btnOpen.setFixedSize(105, 50)

        # create some text fields displaying the IO files info
        self.inNameBox = QLineEdit()
        self.inNameBox.setReadOnly(True)
        self.inNameBox.setFixedHeight(30)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)
    def _initWidgets(self):
        # create a text field for mesh intersection info display
        self.infoBox = QPlainTextEdit()
        self.infoBox.setFixedHeight(60)
        self.infoBox.setReadOnly(True)

        # create two 3-column tables for variables selection
        self.firstTable = VariableTable()
        self.secondTable = VariableTable()

        # create combo box widgets for choosing the operation
        self.operationBox = QComboBox()
        self.operationBox.setFixedSize(400, 30)
        for op in [
                'Project B on A', 'B - A', 'A - B', 'max(A, B)', 'min(A, B)'
        ]:
            self.operationBox.addItem(op)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

        # create a check box for output file format (simple or double precision)
        self.singlePrecisionBox = QCheckBox(
            'Convert to SERAFIN \n(single precision)', self)
        self.singlePrecisionBox.setEnabled(False)

        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b> to write a Serafin output')
        self.btnSubmit.setFixedSize(105, 50)
class SubmitTab(QWidget):
    def __init__(self, inputTab, parent):
        super().__init__()
        self.input = inputTab
        self.parent = parent

        self._initWidgets()
        self._bindEvents()
        self._setLayout()

    def _initWidgets(self):
        # create a text field for mesh intersection info display
        self.infoBox = QPlainTextEdit()
        self.infoBox.setFixedHeight(60)
        self.infoBox.setReadOnly(True)

        # create two 3-column tables for variables selection
        self.firstTable = VariableTable()
        self.secondTable = VariableTable()

        # create combo box widgets for choosing the operation
        self.operationBox = QComboBox()
        self.operationBox.setFixedSize(400, 30)
        for op in [
                'Project B on A', 'B - A', 'A - B', 'max(A, B)', 'min(A, B)'
        ]:
            self.operationBox.addItem(op)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

        # create a check box for output file format (simple or double precision)
        self.singlePrecisionBox = QCheckBox(
            'Convert to SERAFIN \n(single precision)', self)
        self.singlePrecisionBox.setEnabled(False)

        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b> to write a Serafin output')
        self.btnSubmit.setFixedSize(105, 50)

    def _bindEvents(self):
        self.btnSubmit.clicked.connect(self.btnSubmitEvent)

    def _setLayout(self):
        mainLayout = QVBoxLayout()
        mainLayout.addItem(QSpacerItem(1, 10))
        mainLayout.addWidget(self.infoBox)
        mainLayout.addItem(QSpacerItem(1, 15))
        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(30, 1))

        vlayout = QVBoxLayout()
        lb = QLabel('Available variables')
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addWidget(self.firstTable)
        hlayout.addLayout(vlayout)
        hlayout.addItem(QSpacerItem(15, 1))

        vlayout = QVBoxLayout()
        lb = QLabel('Output variables')
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addWidget(self.secondTable)

        hlayout.addLayout(vlayout)
        hlayout.addItem(QSpacerItem(30, 1))

        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(50, 20))
        glayout = QGridLayout()
        glayout.addWidget(QLabel('     Select an operation'), 1, 1)
        glayout.addWidget(self.operationBox, 1, 2)
        glayout.setSpacing(10)
        mainLayout.addLayout(glayout)
        mainLayout.setAlignment(glayout, Qt.AlignTop | Qt.AlignLeft)
        mainLayout.addItem(QSpacerItem(50, 20))

        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.btnSubmit)
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.singlePrecisionBox)
        hlayout.addItem(QSpacerItem(50, 10))
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(30, 15))
        mainLayout.addWidget(QLabel('   Message logs'))
        mainLayout.addWidget(self.logTextBox.widget)
        self.setLayout(mainLayout)

    def _initVarTables(self, common_vars):
        for i, (var_ID, var_name, var_unit) in enumerate(common_vars):
            self.firstTable.insertRow(self.firstTable.rowCount())
            id_item = QTableWidgetItem(var_ID.strip())
            name_item = QTableWidgetItem(var_name.decode('utf-8').strip())
            unit_item = QTableWidgetItem(var_unit.decode('utf-8').strip())
            self.firstTable.setItem(i, 0, id_item)
            self.firstTable.setItem(i, 1, name_item)
            self.firstTable.setItem(i, 2, unit_item)

    def _getSelectedVariables(self):
        return self.secondTable.get_selected_all()

    def _getOutputHeader(self):
        selected_vars = self._getSelectedVariables()
        output_header = self.input.first_data.header.copy()
        output_header.nb_var = len(selected_vars)
        output_header.var_IDs, output_header.var_names, output_header.var_units = [], [], []
        for var_ID, var_name, var_unit in selected_vars:
            output_header.var_IDs.append(var_ID)
            output_header.var_names.append(var_name)
            output_header.var_units.append(var_unit)
        if self.singlePrecisionBox.isChecked():
            output_header.to_single_precision()
        return output_header

    def _updateInfo(self):
        self.infoBox.clear()
        self.infoBox.appendPlainText(
            'The two files has {} common variables and {} common frames.\n'
            'The mesh A has {} / {} nodes inside the mesh B.'.format(
                self.firstTable.rowCount() + self.secondTable.rowCount(),
                len(self.input.common_frames), sum(self.input.is_inside),
                self.input.first_data.header.nb_nodes))

    def reset(self):
        self.firstTable.setRowCount(0)
        self.secondTable.setRowCount(0)
        self.singlePrecisionBox.setChecked(False)
        self.singlePrecisionBox.setEnabled(False)

    def resetFirst(self):
        common_vars = [
            (var_ID, var_name, var_unit) for var_ID, var_name, var_unit in zip(
                self.input.first_data.header.var_IDs, self.input.first_data.
                header.var_names, self.input.first_data.header.var_units)
            if var_ID in self.input.second_data.header.var_IDs
        ]
        if not common_vars:
            self.firstTable.setRowCount(0)
            self.secondTable.setRowCount(0)
            return False
        else:
            # recover, if possible, old variable selection
            old_selected = self._getSelectedVariables()
            self.firstTable.setRowCount(0)
            self.secondTable.setRowCount(0)

            self._initVarTables([(var_ID, var_name, var_unit)
                                 for var_ID, var_name, var_unit in common_vars
                                 if var_ID not in old_selected])
            for var_ID, var_name, var_unit in common_vars:
                if var_ID in old_selected:
                    row = self.secondTable.rowCount()
                    self.secondTable.insertRow(row)
                    id_item = QTableWidgetItem(var_ID.strip())
                    name_item = QTableWidgetItem(
                        var_name.decode('utf-8').strip())
                    unit_item = QTableWidgetItem(
                        var_unit.decode('utf-8').strip())
                    self.secondTable.setItem(row, 0, id_item)
                    self.secondTable.setItem(row, 1, name_item)
                    self.secondTable.setItem(row, 2, unit_item)
            return True

    def getSecond(self, old_second, common_vars):
        if not old_second:
            self.firstTable.setRowCount(0)
            self.secondTable.setRowCount(0)
            self._initVarTables(common_vars)
            if self.input.first_data.header.is_double_precision():
                self.singlePrecisionBox.setEnabled(True)
        self._updateInfo()

    def btnSubmitEvent(self):
        if self.secondTable.rowCount() == 0:
            QMessageBox.critical(
                self, 'Error',
                'Choose at least one output variable before submit!',
                QMessageBox.Ok)
            return

        canceled, filename = save_dialog('Serafin',
                                         input_names=[
                                             self.input.first_data.filename,
                                             self.input.second_data.filename
                                         ])
        if canceled:
            return

        # deduce header from selected variable IDs
        output_header = self._getOutputHeader()
        time_indices = self.input.common_frames
        operation_type = {
            0: operations.PROJECT,
            1: operations.DIFF,
            2: operations.REV_DIFF,
            3: operations.MAX_BETWEEN,
            4: operations.MIN_BETWEEN
        }[self.operationBox.currentIndex()]
        self.parent.inDialog()
        progressBar = OutputProgressDialog()

        # do some calculations
        with Serafin.Read(self.input.first_data.filename,
                          self.input.first_data.language) as first_in:
            first_in.header = self.input.first_data.header
            first_in.time = self.input.first_data.time

            with Serafin.Read(self.input.second_data.filename,
                              self.input.second_data.language) as second_in:
                second_in.header = self.input.second_data.header
                second_in.time = self.input.second_data.time

                progressBar.setValue(5)
                QApplication.processEvents()

                with Serafin.Write(
                        filename,
                        self.input.first_data.language) as out_stream:

                    out_stream.write_header(output_header)
                    process = ProjectMeshThread(first_in, second_in,
                                                out_stream, output_header,
                                                self.input.is_inside,
                                                self.input.point_interpolators,
                                                time_indices, operation_type)
                    progressBar.connectToThread(process)
                    process.run()

                    if not process.canceled:
                        progressBar.outputFinished()

        progressBar.exec_()
        self.parent.outDialog()
    def _initWidgets(self):
        # create a text for input information
        self.inputBox = QPlainTextEdit()
        self.inputBox.setFixedHeight(60)
        self.inputBox.setReadOnly(True)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.input.parent.logging_level)

        # create a combo box for output file type
        self.outTypeBox = QComboBox()
        self.outTypeBox.setFixedHeight(30)

        # create a text box for output file name
        self.outNameBox = QLineEdit()
        self.outNameBox.setReadOnly(True)
        self.outNameBox.setFixedHeight(30)

        # create the option panel
        self.stack = QStackedLayout()

        self.empty = QWidget()

        self.bkshp = QWidget()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Attribute name'))
        self.bkshpname = QLineEdit('Value')
        self.bkshpname.setFixedHeight(30)
        hlayout.addWidget(self.bkshpname)
        self.bkshp.setLayout(hlayout)

        self.zfield = QWidget()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill Z with'))
        self.zfieldchoice = QComboBox()
        self.zfieldchoice.setFixedHeight(30)
        hlayout.addWidget(self.zfieldchoice, Qt.AlignLeft)
        self.zfield.setLayout(hlayout)

        self.mfield = QWidget()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill M with'))
        self.mfieldchoice = QComboBox()
        self.mfieldchoice.setFixedHeight(30)
        hlayout.addWidget(self.mfieldchoice, Qt.AlignLeft)
        self.mfield.setLayout(hlayout)

        self.shpbk = QWidget()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill attribute with'))
        self.shpbkmethod = QComboBox()
        self.shpbkmethod.setFixedHeight(30)
        hlayout.addWidget(self.shpbkmethod, Qt.AlignLeft)
        self.shpbk.setLayout(hlayout)

        self.shpbkz = QWidget()
        vlayout = QVBoxLayout()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill Z with'))
        self.zfieldchoicebis = QComboBox()
        self.zfieldchoicebis.setFixedHeight(30)
        hlayout.addWidget(self.zfieldchoicebis, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill attribute with'))
        self.shpbkmethodbis = QComboBox()
        self.shpbkmethodbis.setFixedHeight(30)
        hlayout.addWidget(self.shpbkmethodbis, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        self.shpbkz.setLayout(vlayout)

        self.shpzm = QWidget()
        vlayout = QVBoxLayout()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill Z with'))
        self.zfieldchoiceter = QComboBox()
        self.zfieldchoiceter.setFixedHeight(30)
        hlayout.addWidget(self.zfieldchoiceter, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill M with'))
        self.mfieldchoicebis = QComboBox()
        self.mfieldchoicebis.setFixedHeight(30)
        hlayout.addWidget(self.mfieldchoicebis, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        self.shpzm.setLayout(vlayout)

        for panel in [
                self.empty, self.bkshp, self.zfield, self.mfield, self.shpbk,
                self.shpbkz, self.shpzm
        ]:
            self.stack.addWidget(panel)

        self.stackbis = QStackedLayout()
        self.emptybis = QWidget()

        self.resample = QGroupBox('Re-sample lines by Maximum Length')
        self.resample.setCheckable(True)
        vlayout = QVBoxLayout()
        self.valueButton = QRadioButton('Use constant')
        self.valueBox = QLineEdit('1')
        self.choiceButton = QRadioButton('Use attribute')
        self.choiceBox = QComboBox()
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.valueButton)
        hlayout.addWidget(self.valueBox)
        vlayout.addLayout(hlayout)
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.choiceButton)
        hlayout.addWidget(self.choiceBox, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        self.resample.setLayout(vlayout)
        self.choiceBox.setVisible(False)
        self.valueBox.setVisible(False)
        self.resample.setChecked(False)
        self.valueButton.toggled.connect(
            lambda checked: self.valueBox.setVisible(checked))
        self.choiceButton.toggled.connect(
            lambda checked: self.choiceBox.setVisible(checked))
        self.valueButton.setChecked(True)

        self.stackbis.addWidget(self.emptybis)
        self.stackbis.addWidget(self.resample)
        self.stackbis.setCurrentIndex(1)
        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b>')
        self.btnSubmit.setFixedSize(105, 50)
class FileConverterOutputTab(QWidget):
    def __init__(self, inputTab):
        super().__init__()
        self.input = inputTab

        self.EMPTY = 0
        self.BK_SHP = 1
        self.Z_FROM_SHP = 2
        self.M_FROM_SHP = 3
        self.SHP_BK = 4
        self.Z_AND_BK = 5
        self.Z_AND_M = 6

        self.convert_type = {
            'xyz': {
                'xyz': self.EMPTY,
                'shp PointZ': self.BK_SHP,
                'csv': self.EMPTY
            },
            'i2s': {
                'i2s': self.EMPTY,
                'shp Polyline': self.BK_SHP,
                'shp Polygon': self.BK_SHP,
                'csv': self.EMPTY
            },
            'i3s': {
                'i3s': self.EMPTY,
                'i2s': self.EMPTY,
                'shp PolylineZ': self.BK_SHP,
                'shp PolygonZ': self.BK_SHP,
                'csv': self.EMPTY
            },
            'shp Point': {
                'shp Point': self.EMPTY,
                'shp PointZ': self.Z_AND_M,
                'xyz': self.Z_FROM_SHP,
                'csv': self.EMPTY
            },
            'shp PointZ': {
                'shp Point': self.EMPTY,
                'shp PointZ': self.Z_AND_M,
                'shp PointM': self.M_FROM_SHP,
                'xyz': self.Z_FROM_SHP,
                'csv': self.EMPTY
            },
            'shp PointM': {
                'shp Point': self.EMPTY,
                'shp PointM': self.M_FROM_SHP,
                'shp PointZ': self.Z_AND_M,
                'xyz': self.Z_FROM_SHP,
                'csv': self.EMPTY
            },
            'shp Polyline': {
                'shp Polyline': self.EMPTY,
                'shp PolylineZ': self.Z_AND_M,
                'i2s': self.SHP_BK,
                'i3s': self.Z_AND_BK,
                'csv': self.EMPTY
            },
            'shp Polygon': {
                'shp Polygon': self.EMPTY,
                'shp PolygonZ': self.Z_AND_M,
                'i2s': self.SHP_BK,
                'i3s': self.Z_AND_BK,
                'csv': self.EMPTY
            },
            'shp PolylineZ': {
                'shp PolylineZ': self.Z_AND_M,
                'shp Polyline': self.EMPTY,
                'i2s': self.SHP_BK,
                'i3s': self.Z_AND_BK,
                'csv': self.EMPTY
            },
            'shp PolygonZ': {
                'shp PolygonZ': self.Z_AND_M,
                'shp Polygon': self.EMPTY,
                'i2s': self.SHP_BK,
                'i3s': self.Z_AND_BK,
                'csv': self.EMPTY
            },
            'shp PolylineM': {
                'shp Polyline': self.EMPTY,
                'shp PolylineM': self.M_FROM_SHP,
                'shp PolylineZ': self.Z_AND_M,
                'i2s': self.SHP_BK,
                'i3s': self.Z_AND_BK,
                'csv': self.EMPTY
            },
            'shp PolygonM': {
                'shp Polygon': self.EMPTY,
                'shp PolygonM': self.M_FROM_SHP,
                'shp PolygonZ': self.Z_AND_M,
                'i2s': self.SHP_BK,
                'i3s': self.Z_AND_BK,
                'csv': self.EMPTY
            },
            'shp Multipoint': {
                'shp MultiPoint': self.EMPTY,
                'shp Point': self.EMPTY,
                'csv': self.EMPTY
            },
            'shp MultiPoint': {
                'shp MultiPoint': self.EMPTY,
                'shp Point': self.EMPTY,
                'csv': self.EMPTY
            },
            'shp MultiPointZ': {
                'shp MultiPointZ': self.EMPTY,
                'shp PointZ': self.EMPTY,
                'csv': self.EMPTY
            },
            'shp MultiPointM': {
                'shp MultiPointM': self.EMPTY,
                'shp PointM': self.EMPTY,
                'csv': self.EMPTY
            }
        }
        self._initWidgets()
        self._setLayout()
        self._bindEvents()

    def _initWidgets(self):
        # create a text for input information
        self.inputBox = QPlainTextEdit()
        self.inputBox.setFixedHeight(60)
        self.inputBox.setReadOnly(True)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.input.parent.logging_level)

        # create a combo box for output file type
        self.outTypeBox = QComboBox()
        self.outTypeBox.setFixedHeight(30)

        # create a text box for output file name
        self.outNameBox = QLineEdit()
        self.outNameBox.setReadOnly(True)
        self.outNameBox.setFixedHeight(30)

        # create the option panel
        self.stack = QStackedLayout()

        self.empty = QWidget()

        self.bkshp = QWidget()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Attribute name'))
        self.bkshpname = QLineEdit('Value')
        self.bkshpname.setFixedHeight(30)
        hlayout.addWidget(self.bkshpname)
        self.bkshp.setLayout(hlayout)

        self.zfield = QWidget()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill Z with'))
        self.zfieldchoice = QComboBox()
        self.zfieldchoice.setFixedHeight(30)
        hlayout.addWidget(self.zfieldchoice, Qt.AlignLeft)
        self.zfield.setLayout(hlayout)

        self.mfield = QWidget()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill M with'))
        self.mfieldchoice = QComboBox()
        self.mfieldchoice.setFixedHeight(30)
        hlayout.addWidget(self.mfieldchoice, Qt.AlignLeft)
        self.mfield.setLayout(hlayout)

        self.shpbk = QWidget()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill attribute with'))
        self.shpbkmethod = QComboBox()
        self.shpbkmethod.setFixedHeight(30)
        hlayout.addWidget(self.shpbkmethod, Qt.AlignLeft)
        self.shpbk.setLayout(hlayout)

        self.shpbkz = QWidget()
        vlayout = QVBoxLayout()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill Z with'))
        self.zfieldchoicebis = QComboBox()
        self.zfieldchoicebis.setFixedHeight(30)
        hlayout.addWidget(self.zfieldchoicebis, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill attribute with'))
        self.shpbkmethodbis = QComboBox()
        self.shpbkmethodbis.setFixedHeight(30)
        hlayout.addWidget(self.shpbkmethodbis, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        self.shpbkz.setLayout(vlayout)

        self.shpzm = QWidget()
        vlayout = QVBoxLayout()
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill Z with'))
        self.zfieldchoiceter = QComboBox()
        self.zfieldchoiceter.setFixedHeight(30)
        hlayout.addWidget(self.zfieldchoiceter, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Fill M with'))
        self.mfieldchoicebis = QComboBox()
        self.mfieldchoicebis.setFixedHeight(30)
        hlayout.addWidget(self.mfieldchoicebis, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        self.shpzm.setLayout(vlayout)

        for panel in [
                self.empty, self.bkshp, self.zfield, self.mfield, self.shpbk,
                self.shpbkz, self.shpzm
        ]:
            self.stack.addWidget(panel)

        self.stackbis = QStackedLayout()
        self.emptybis = QWidget()

        self.resample = QGroupBox('Re-sample lines by Maximum Length')
        self.resample.setCheckable(True)
        vlayout = QVBoxLayout()
        self.valueButton = QRadioButton('Use constant')
        self.valueBox = QLineEdit('1')
        self.choiceButton = QRadioButton('Use attribute')
        self.choiceBox = QComboBox()
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.valueButton)
        hlayout.addWidget(self.valueBox)
        vlayout.addLayout(hlayout)
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.choiceButton)
        hlayout.addWidget(self.choiceBox, Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        self.resample.setLayout(vlayout)
        self.choiceBox.setVisible(False)
        self.valueBox.setVisible(False)
        self.resample.setChecked(False)
        self.valueButton.toggled.connect(
            lambda checked: self.valueBox.setVisible(checked))
        self.choiceButton.toggled.connect(
            lambda checked: self.choiceBox.setVisible(checked))
        self.valueButton.setChecked(True)

        self.stackbis.addWidget(self.emptybis)
        self.stackbis.addWidget(self.resample)
        self.stackbis.setCurrentIndex(1)
        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b>')
        self.btnSubmit.setFixedSize(105, 50)

    def _bindEvents(self):
        self.btnSubmit.clicked.connect(self.btnSubmitEvent)
        self.outTypeBox.currentIndexChanged.connect(self.changeOutType)

    def _setLayout(self):
        mainLayout = QVBoxLayout()
        mainLayout.addItem(QSpacerItem(50, 20))
        mainLayout.addWidget(self.inputBox)
        mainLayout.addItem(QSpacerItem(50, 20))
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('Output file type'))
        hlayout.addWidget(self.outTypeBox, Qt.AlignLeft)
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(50, 10))
        mainLayout.addLayout(self.stack)
        mainLayout.addItem(QSpacerItem(50, 10))
        mainLayout.addLayout(self.stackbis)
        mainLayout.addItem(QSpacerItem(50, 10))
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.btnSubmit)
        hlayout.addWidget(self.outNameBox)
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(30, 15))
        mainLayout.addWidget(QLabel('   Message logs'))
        mainLayout.addWidget(self.logTextBox.widget)
        self.setLayout(mainLayout)

    def reset(self):
        self.inputBox.clear()
        self.outTypeBox.clear()
        self.outNameBox.clear()
        self.bkshpname.setText('Value')
        self.zfieldchoice.clear()
        self.zfieldchoicebis.clear()
        self.zfieldchoiceter.clear()
        self.mfieldchoice.clear()
        self.mfieldchoicebis.clear()
        self.shpbkmethod.clear()
        self.shpbkmethod.addItem('0')
        self.shpbkmethod.addItem('Iteration')
        self.shpbkmethodbis.clear()
        self.shpbkmethodbis.addItem('0')
        self.shpbkmethodbis.addItem('Iteration')
        self.choiceBox.clear()

    def changeOutType(self, index):
        if self.outTypeBox.currentText():
            self.stack.setCurrentIndex(self.convert_type[self.input.from_type][
                self.outTypeBox.currentText()])

    def _check_options(self):
        current_type = self.stack.currentIndex()
        if current_type == self.BK_SHP:
            attribute_name = self.bkshpname.text()
            if not attribute_name:
                QMessageBox.critical(None, 'Error',
                                     'The attribute name cannot be empty!',
                                     QMessageBox.Ok)
                return False, []
            options = [attribute_name]
        elif current_type == self.Z_FROM_SHP:
            options = [self.zfieldchoice.currentText()]
        elif current_type == self.M_FROM_SHP:
            options = [self.mfieldchoice.currentText()]
        elif current_type == self.SHP_BK:
            options = [self.shpbkmethod.currentText()]
        elif current_type == self.Z_AND_BK:
            options = [
                self.zfieldchoicebis.currentText(),
                self.shpbkmethodbis.currentText()
            ]
        elif current_type == self.Z_AND_M:
            options = [
                self.zfieldchoiceter.currentText(),
                self.mfieldchoicebis.currentText()
            ]
        else:
            options = []
        if self.stackbis.currentIndex() == 1:
            if self.resample.isChecked():
                if self.valueButton.isChecked():
                    value = self.valueBox.text()
                    try:
                        value = float(value)
                    except ValueError:
                        QMessageBox.critical(
                            None, 'Error',
                            'Re-sampling Maximum Length must be a number!',
                            QMessageBox.Ok)
                        return False, []
                    if value <= 0:
                        QMessageBox.critical(
                            None, 'Error',
                            'Re-sampling Maximum Length must be a positive!',
                            QMessageBox.Ok)
                        return False, []
                    options.append('v|' + str(value))
                else:
                    attribute = self.choiceBox.currentText()
                    if not attribute:
                        QMessageBox.critical(
                            None, 'Error',
                            'No numeric attribute available for re-sampling.',
                            QMessageBox.Ok)
                        return False, []
                    options.append('a|' + attribute)
            else:
                options.append('')
        return True, options

    def getInput(self):
        self.reset()

        from_type = self.input.from_type
        message = 'The input format is of type {}.\n'.format(from_type)
        is_line = False
        possible_types = self.convert_type[from_type].keys()

        if from_type == 'i2s' or from_type == 'i3s':
            is_line = True
            self.choiceBox.addItem('Attribute')
            nb_closed, nb_open = self.input.converter.nb_closed, self.input.converter.nb_open
            if nb_closed > 0 and nb_open > 0:
                possible_types = self.convert_type[from_type].keys()
            elif nb_closed == 0:
                if from_type == 'i2s':
                    possible_types = ['i2s', 'shp Polyline', 'csv']
                else:
                    possible_types = ['i3s', 'i2s', 'shp PolylineZ', 'csv']
            else:
                if from_type == 'i2s':
                    possible_types = ['i2s', 'shp Polygon', 'csv']
                else:
                    possible_types = ['i3s', 'i2s', 'shp PolygonZ', 'csv']
            message += 'It has {} polygon{} and {} open polyline{}.\n'.format(
                nb_closed, 's' if nb_closed > 1 else '', nb_open,
                's' if nb_open > 1 else '')
        elif from_type == 'shp Point':
            numeric_fields = self.input.converter.numeric_fields
            if numeric_fields:
                self.mfieldchoicebis.addItem('0')
                for index, name in numeric_fields:
                    item = '%d - %s' % (index, name)
                    self.zfieldchoice.addItem(item)
                    self.zfieldchoiceter.addItem(item)
                    self.mfieldchoicebis.addItem(item)
            else:
                possible_types = ['shp Point', 'csv']

        elif from_type == 'shp PointM':
            numeric_fields = self.input.converter.numeric_fields
            self.mfieldchoice.addItem('M')
            self.mfieldchoicebis.addItem('M')
            if numeric_fields:
                for index, name in numeric_fields:
                    item = '%d - %s' % (index, name)
                    self.zfieldchoice.addItem(item)
                    self.zfieldchoiceter.addItem(item)
                    self.mfieldchoice.addItem(item)
                    self.mfieldchoicebis.addItem(item)
            else:
                possible_types = ['shp PointM', 'shp Point', 'csv']

        elif from_type == 'shp PointZ':
            self.zfieldchoice.addItem('Z')
            self.zfieldchoiceter.addItem('Z')
            self.mfieldchoice.addItem('M')
            self.mfieldchoicebis.addItem('M')
            numeric_fields = self.input.converter.numeric_fields
            if numeric_fields:
                for index, name in numeric_fields:
                    item = '%d - %s' % (index, name)
                    self.zfieldchoice.addItem(item)
                    self.zfieldchoiceter.addItem(item)
                    self.mfieldchoice.addItem(item)
                    self.mfieldchoicebis.addItem(item)

        elif from_type == 'shp Polyline' or from_type == 'shp Polygon':
            is_line = True
            numeric_fields = self.input.converter.numeric_fields
            if numeric_fields:
                self.mfieldchoicebis.addItem('0')
                for index, name in numeric_fields:
                    item = '%d - %s' % (index, name)
                    self.zfieldchoiceter.addItem(item)
                    self.mfieldchoicebis.addItem(item)
                    self.zfieldchoicebis.addItem(item)
                    self.shpbkmethod.addItem(item)
                    self.shpbkmethodbis.addItem(item)
                    self.choiceBox.addItem(item)
            else:
                possible_types = [from_type, 'i2s', 'csv']

        elif from_type == 'shp PolylineZ' or from_type == 'shp PolygonZ':
            is_line = True
            self.zfieldchoiceter.addItem('Z')
            self.zfieldchoicebis.addItem('Z')
            self.mfieldchoicebis.addItem('M')
            numeric_fields = self.input.converter.numeric_fields
            if numeric_fields:
                for index, name in numeric_fields:
                    item = '%d - %s' % (index, name)
                    self.zfieldchoiceter.addItem(item)
                    self.zfieldchoicebis.addItem(item)
                    self.mfieldchoicebis.addItem(item)
                    self.shpbkmethod.addItem(item)
                    self.shpbkmethodbis.addItem(item)
                    self.choiceBox.addItem(item)

        elif from_type == 'shp PolylineM' or from_type == 'shp PolygonM':
            is_line = True
            numeric_fields = self.input.converter.numeric_fields
            self.mfieldchoice.addItem('M')
            self.mfieldchoicebis.addItem('M')
            if numeric_fields:
                for index, name in numeric_fields:
                    item = '%d - %s' % (index, name)
                    self.mfieldchoice.addItem(item)
                    self.zfieldchoiceter.addItem(item)
                    self.zfieldchoicebis.addItem(item)
                    self.mfieldchoicebis.addItem(item)
                    self.shpbkmethod.addItem(item)
                    self.shpbkmethodbis.addItem(item)
                    self.choiceBox.addItem(item)
            else:
                possible_types = [from_type, from_type[:-1], 'i2s', 'csv']

        for to_type in possible_types:
            self.outTypeBox.addItem(to_type)

        if is_line:
            self.stackbis.setCurrentIndex(1)
        else:
            self.stackbis.setCurrentIndex(0)

        message += 'It can be converted to the following types: {}.'.format(
            ', '.join(list(possible_types)))
        self.inputBox.appendPlainText(message)

    def btnSubmitEvent(self):
        # check the transformations options
        valid, options = self._check_options()
        if not valid:
            return

        # getting the converter options right
        if self.input.transformation is not None:
            from_index, to_index = self.input.fromBox.currentIndex(
            ), self.input.toBox.currentIndex()
            trans = self.input.transformation.get_transformation(
                from_index, to_index)
            self.input.converter.set_transformations(trans)

        out_type = self.outTypeBox.currentText()
        if out_type[:3] == 'shp':
            out_type = 'shp'
        filename, _ = QFileDialog.getSaveFileName(
            self,
            'Choose the output file name',
            '',
            '%s Files (*.%s)' % (out_type, out_type),
            options=QFileDialog.Options() | QFileDialog.DontUseNativeDialog)
        if not filename:
            return
        if len(filename) < 5 or filename[-3:] != out_type:
            filename += '.' + out_type
        if filename == self.input.converter.from_file:
            QMessageBox.critical(self, 'Error',
                                 'Cannot overwrite to the input file.',
                                 QMessageBox.Ok)
            return
        try:
            with open(filename, 'w') as f:
                pass
        except PermissionError:
            QMessageBox.critical(
                self, 'Error',
                'Permission denied (Is the file opened by another application?).',
                QMessageBox.Ok)
            return None

        self.outNameBox.setText(filename)
        logging.info('Start conversion from %s\nto %s' %
                     (self.input.converter.from_file, filename))
        QApplication.processEvents()
        try:
            self.input.converter.write(self.outTypeBox.currentText(), filename,
                                       options)
        except RuntimeError:
            QMessageBox.critical(
                self, 'Error',
                'The attribute used for re-sampling contains non-positive number.',
                QMessageBox.Ok)
            logging.info('Failed.')
            return None
        logging.info('Done.')
        QMessageBox.information(self, 'Success',
                                'File conversion finished successfully!',
                                QMessageBox.Ok)
class FileConverterInputTab(QWidget):
    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        self.transformation = None
        self.converter = None
        self.from_type = None

        self.frenchButton = QCheckBox()
        self.englishButton = QCheckBox()
        for button in (self.frenchButton, self.englishButton):
            button.setVisible(False)

        self._initWidgets()
        self._setLayout()
        self._bindEvents()

    def _initWidgets(self):
        """!
        @brief (Used in __init__) Create widgets
        """
        # create the group box for coordinate transformation
        self.confBox = QGroupBox('Apply coordinate transformation (optional)')
        self.confBox.setStyleSheet(
            'QGroupBox {font-size: 12px;font-weight: bold;}')
        self.btnConfig = QPushButton('Load\nTransformation', self)
        self.btnConfig.setToolTip('<b>Open</b> a transformation config file')
        self.btnConfig.setFixedSize(105, 50)
        self.confNameBox = QLineEdit()
        self.confNameBox.setReadOnly(True)
        self.confNameBox.setFixedHeight(30)
        self.fromBox = QComboBox()
        self.fromBox.setFixedWidth(150)
        self.toBox = QComboBox()
        self.toBox.setFixedWidth(150)

        # create the open button
        self.btnOpen = QPushButton('Open',
                                   self,
                                   icon=self.style().standardIcon(
                                       QStyle.SP_DialogOpenButton))
        self.btnOpen.setToolTip(
            '<b>Open</b> a geometry file (.shp .xyz .i2s .i3s)')
        self.btnOpen.setFixedSize(105, 50)

        # create some text fields displaying the IO files info
        self.inNameBox = QLineEdit()
        self.inNameBox.setReadOnly(True)
        self.inNameBox.setFixedHeight(30)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

    def _setLayout(self):
        mainLayout = QVBoxLayout()
        mainLayout.addItem(QSpacerItem(10, 10))
        mainLayout.setSpacing(15)

        vlayout = QVBoxLayout()
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.btnConfig)
        hlayout.addWidget(self.confNameBox)
        vlayout.addLayout(hlayout)

        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('    Transform from'))
        hlayout.addWidget(self.fromBox)
        hlayout.addWidget(QLabel('to'))
        hlayout.addWidget(self.toBox)
        hlayout.setAlignment(Qt.AlignLeft)
        vlayout.addLayout(hlayout)
        vlayout.setSpacing(15)
        self.confBox.setLayout(vlayout)
        mainLayout.addWidget(self.confBox)

        mainLayout.addItem(QSpacerItem(10, 15))
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.btnOpen)
        hlayout.addWidget(self.inNameBox)
        mainLayout.addLayout(hlayout)

        mainLayout.addItem(QSpacerItem(10, 10))

        mainLayout.addItem(QSpacerItem(10, 15))
        mainLayout.addWidget(QLabel('   Message logs'))
        mainLayout.addWidget(self.logTextBox.widget)
        self.setLayout(mainLayout)

    def _bindEvents(self):
        self.btnOpen.clicked.connect(self.btnOpenEvent)
        self.btnConfig.clicked.connect(self.btnConfigEvent)

    def _handleOpenShapefile(self, filename):
        try:
            with open(filename, 'r') as f:
                pass
        except PermissionError:
            QMessageBox.critical(None, 'Error', 'Permission denied.',
                                 QMessageBox.Ok)
            self.parent.reset()
            return False
        try:
            shape_type = shp.get_shape_type(filename)
        except shapefile.ShapefileException:
            QMessageBox.critical(
                None, 'Error',
                'Failed to open shp file (is the .dbf file present?).',
                QMessageBox.Ok)
            self.parent.reset()
            return False

        if shape_type == 1:
            self.from_type = 'shp Point'
        elif shape_type == 11:
            self.from_type = 'shp PointZ'
        elif shape_type == 21:
            self.from_type = 'shp PointM'
        elif shape_type == 3:
            self.from_type = 'shp Polyline'
        elif shape_type == 13:
            self.from_type = 'shp PolylineZ'
        elif shape_type == 23:
            self.from_type = 'shp PolylineM'
        elif shape_type == 5:
            self.from_type = 'shp Polygon'
        elif shape_type == 15:
            self.from_type = 'shp PolygonZ'
        elif shape_type == 25:
            self.from_type = 'shp PolygonM'
        elif shape_type == 8:
            self.from_type = 'shp MultiPoint'
        elif shape_type == 18:
            self.from_type = 'shp MultiPointZ'
        elif shape_type == 28:
            self.from_type = 'shp MultiPointM'
        elif shape_type == 0:
            QMessageBox.critical(
                None, 'Error',
                'The shape type Null is currently not supported!',
                QMessageBox.Ok)
            self.parent.reset()
            return False
        else:
            QMessageBox.critical(
                None, 'Error',
                'The shape type MultiPatch is currently not supported!',
                QMessageBox.Ok)
            self.parent.reset()
            return False
        if shape_type in (1, 11, 21):
            self.converter = convert.ShpPointConverter(filename, shape_type)
        elif shape_type in (3, 5, 13, 15, 23, 25):
            self.converter = convert.ShpLineConverter(filename, shape_type)
        else:
            self.converter = convert.ShpMultiPointConverter(
                filename, shape_type)
        return True

    def btnConfigEvent(self):
        filename, _ = QFileDialog.getOpenFileName(
            self,
            'Choose the file name',
            '',
            'All files (*)',
            options=QFileDialog.Options() | QFileDialog.DontUseNativeDialog)
        if not filename:
            return
        self.fromBox.clear()
        self.toBox.clear()
        self.confNameBox.clear()
        self.transformation = None

        success, self.transformation = load_transformation_map(filename)
        if not success:
            QMessageBox.critical(self, 'Error',
                                 'The configuration is not valid.',
                                 QMessageBox.Ok)
            return
        self.confNameBox.setText(filename)
        for label in self.transformation.labels:
            self.fromBox.addItem(label)
            self.toBox.addItem(label)

    def btnOpenEvent(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        filename, _ = QFileDialog.getOpenFileName(
            self,
            'Open a geometry file',
            '',
            'Geometry Files (*.shp *.xyz *.i2s *.i3s)',
            options=options)
        if not filename:
            return

        self.inNameBox.setText(filename)
        suffix = filename[-4:]
        if suffix == '.xyz':
            self.converter = convert.XYZConverter(filename)
            self.from_type = 'xyz'
        elif suffix == '.shp':
            if not self._handleOpenShapefile(filename):
                return
        elif suffix == '.i2s' or suffix == '.i3s':
            self.converter = convert.BKLineConverter(filename)
            self.from_type = suffix[1:]

        self.converter.set_csv_separator(self.parent.csv_separator)
        logging.info('Reading the input file...')
        QApplication.processEvents()
        try:
            self.converter.read()
        except PermissionError:
            QMessageBox.critical(
                None, 'Error',
                'Permission denied (Is the file opened by another application?).',
                QMessageBox.Ok)
            self.parent.reset()
            return
        except ValueError:
            QMessageBox.critical(None, 'Error', 'The file is empty!',
                                 QMessageBox.Ok)
            self.parent.reset()
            return
        except RuntimeError:
            QMessageBox.critical(
                None, 'Error',
                'Failed to read the shp file: Inconsistent bytes.',
                QMessageBox.Ok)
            self.parent.reset()
            return
        logging.info('Finished reading the input file: %s' % filename)
        self.parent.getInput()
        QMessageBox.information(
            self, 'Success',
            'Finished reading the input file. The file converter is ready!',
            QMessageBox.Ok)
Beispiel #11
0
class SynchMaxTab(QWidget):
    def __init__(self, parent):
        super().__init__()
        self.data = None
        self.parent = parent

        self._initWidgets()
        self._setLayout()
        self._bindEvents()

    def _initWidgets(self):
        # create a combox box for variable selection
        self.varBox = QComboBox()
        self.varBox.setFixedSize(200, 30)

        # create a slider for time selection
        self.timeSlider = TimeRangeSlider()
        self.timeSlider.setFixedHeight(30)
        self.timeSlider.setMinimumWidth(600)
        self.timeSlider.setEnabled(False)

        # create text boxes for displaying the time selection
        self.timeSelection = TimeSelection(self)
        self.timeSelection.startIndex.setEnabled(False)
        self.timeSelection.endIndex.setEnabled(False)
        self.timeSelection.startValue.setEnabled(False)
        self.timeSelection.endValue.setEnabled(False)

        # create two 3-column tables for variables selection
        self.firstTable = VariableTable()
        self.secondTable = VariableTable()
        self.secondTable.setMinimumHeight(300)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

        # create a check box for output file format (simple or double precision)
        self.singlePrecisionBox = QCheckBox(
            'Convert to SERAFIN \n(single precision)', self)
        self.singlePrecisionBox.setEnabled(False)

        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b> to write a Serafin output')
        self.btnSubmit.setFixedSize(105, 50)
        self.btnSubmit.setEnabled(False)

    def _setLayout(self):
        mainLayout = QVBoxLayout()
        mainLayout.addItem(QSpacerItem(1, 10))
        mainLayout.addWidget(self.timeSlider)
        mainLayout.addWidget(self.timeSelection)
        mainLayout.addItem(QSpacerItem(1, 10))

        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('  Select the reference variable '))
        hlayout.addWidget(self.varBox, Qt.AlignLeft)
        hlayout.addStretch()
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(1, 10))

        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(30, 1))
        vlayout = QVBoxLayout()
        vlayout.setAlignment(Qt.AlignHCenter)
        lb = QLabel('Available variables')
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addWidget(self.firstTable)
        hlayout.addLayout(vlayout)
        hlayout.addItem(QSpacerItem(15, 1))
        vlayout = QVBoxLayout()
        lb = QLabel('Output variables')
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addWidget(self.secondTable)
        hlayout.addLayout(vlayout)
        hlayout.addItem(QSpacerItem(30, 1))

        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(50, 20))
        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.btnSubmit)
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.singlePrecisionBox)
        hlayout.addItem(QSpacerItem(50, 10))
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(30, 15))
        mainLayout.addWidget(QLabel('   Message logs'))
        mainLayout.addWidget(self.logTextBox.widget)
        self.setLayout(mainLayout)

    def _bindEvents(self):
        self.btnSubmit.clicked.connect(self.btnSubmitEvent)
        self.timeSelection.startIndex.editingFinished.connect(
            self.timeSlider.enterIndexEvent)
        self.timeSelection.endIndex.editingFinished.connect(
            self.timeSlider.enterIndexEvent)
        self.timeSelection.startValue.editingFinished.connect(
            self.timeSlider.enterValueEvent)
        self.timeSelection.endValue.editingFinished.connect(
            self.timeSlider.enterValueEvent)

    def _initVarTables(self):
        self.firstTable.fill(self.data.header)
        self.secondTable.insertRow(0)
        self.secondTable.setItem(0, 0, QTableWidgetItem('MAX TIME'))
        self.secondTable.setItem(0, 1, QTableWidgetItem('MAX TIME'))
        self.secondTable.setItem(0, 2, QTableWidgetItem('S'))
        for j in range(3):
            self.secondTable.item(0, j).setFlags(Qt.NoItemFlags)

    def _getSelectedVariables(self):
        return self.secondTable.get_selected_all()

    def reset(self):
        self.varBox.clear()
        self.firstTable.setRowCount(0)
        self.secondTable.setRowCount(0)
        self.timeSelection.disable()
        self.btnSubmit.setEnabled(False)
        self.singlePrecisionBox.setChecked(False)
        self.singlePrecisionBox.setEnabled(False)

    def getOutputHeader(self, selected_vars):
        output_header = self.data.header.copy()
        output_header.nb_var = len(selected_vars)
        output_header.var_IDs, output_header.var_names, output_header.var_units = [], [], []
        for var_ID, var_name, var_unit in selected_vars:
            output_header.var_IDs.append(var_ID)
            output_header.var_names.append(var_name)
            output_header.var_units.append(var_unit)
        if self.singlePrecisionBox.isChecked():
            output_header.to_single_precision()
        return output_header

    def getInput(self, data):
        self.data = data
        self._initVarTables()
        for var, var_name in zip(self.data.header.var_IDs,
                                 self.data.header.var_names):
            item = '%s (%s)' % (var, var_name.decode('utf-8').strip())
            self.varBox.addItem(item)

        self.btnSubmit.setEnabled(True)

        # unlock convert to single precision
        if self.data.header.is_double_precision():
            self.singlePrecisionBox.setEnabled(True)

        if self.data.header.date is not None:
            year, month, day, hour, minute, second = self.data.header.date
            start_time = datetime.datetime(year, month, day, hour, minute,
                                           second)
        else:
            start_time = datetime.datetime(1900, 1, 1, 0, 0, 0)

        time_frames = list(
            map(lambda x: datetime.timedelta(seconds=x), self.data.time))
        self.timeSlider.reinit(start_time, time_frames, self.timeSelection)
        self.timeSlider.setEnabled(True)
        self.timeSelection.enable()

    def btnSubmitEvent(self):
        # fetch the list of selected variables
        selected_vars = self._getSelectedVariables()
        if not selected_vars:
            QMessageBox.critical(self, 'Error',
                                 'Select at least one variable.',
                                 QMessageBox.Ok)
            return

        canceled, filename = save_dialog('Serafin', self.data.filename)
        if canceled:
            return

        # deduce header from selected variable IDs and write header
        output_header = self.getOutputHeader(selected_vars)

        start_index = int(self.timeSelection.startIndex.text()) - 1
        end_index = int(self.timeSelection.endIndex.text())
        time_indices = list(range(start_index, end_index))
        var = self.varBox.currentText().split(' (')[0]

        output_message = 'Computing SynchMax of variables %s between frame %d and %d.' \
                          % (str(list(map(lambda x: x[0], selected_vars[1:]))), start_index+1, end_index)
        self.parent.inDialog()
        logging.info(output_message)
        progressBar = OutputProgressDialog()

        # do some calculations
        with Serafin.Read(self.data.filename,
                          self.data.language) as input_stream:
            input_stream.header = self.data.header
            input_stream.time = self.data.time

            progressBar.setValue(5)
            QApplication.processEvents()

            with Serafin.Write(filename, self.data.language) as output_stream:
                process = SynchMaxThread(input_stream, selected_vars[1:],
                                         time_indices, var)
                progressBar.connectToThread(process)
                values = process.run()

                if not process.canceled:
                    output_stream.write_header(output_header)
                    output_stream.write_entire_frame(output_header,
                                                     self.data.time[0], values)
                    progressBar.outputFinished()

        progressBar.exec_()
        self.parent.outDialog()
Beispiel #12
0
class ArrivalDurationTab(QWidget):
    def __init__(self, parent):
        super().__init__()
        self.data = None
        self.parent = parent

        self.conditions = []

        self._initWidgets()
        self._setLayout()
        self._bindEvents()

    def _initWidgets(self):
        # create a slider for time selection
        self.timeSlider = TimeRangeSlider()
        self.timeSlider.setFixedHeight(30)
        self.timeSlider.setMinimumWidth(600)
        self.timeSlider.setEnabled(False)

        # create a button for add condition
        self.btnAdd = QPushButton('Add new condition')
        self.btnAdd.setFixedSize(135, 50)

        # create a table for created condition
        self.conditionTable = QTableWidget()
        self.conditionTable.setColumnCount(3)
        self.conditionTable.setHorizontalHeaderLabels(
            ['Condition', 'Arrival', 'Duration'])
        vh = self.conditionTable.verticalHeader()
        vh.setSectionResizeMode(QHeaderView.Fixed)
        vh.setDefaultSectionSize(20)
        hh = self.conditionTable.horizontalHeader()
        hh.setDefaultSectionSize(150)
        self.conditionTable.setMaximumHeight(500)

        # create text boxes for displaying the time selection
        self.timeSelection = TimeSelection(self)
        self.timeSelection.startIndex.setEnabled(False)
        self.timeSelection.endIndex.setEnabled(False)
        self.timeSelection.startValue.setEnabled(False)
        self.timeSelection.endValue.setEnabled(False)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

        # create a combo box for time unit
        self.unitBox = QComboBox()
        for unit in ['second', 'minute', 'hour', 'day', 'percentage']:
            self.unitBox.addItem(unit)
        self.unitBox.setFixedHeight(30)
        self.unitBox.setMaximumWidth(200)

        # create a check box for output file format (simple or double precision)
        self.singlePrecisionBox = QCheckBox(
            'Convert to SERAFIN \n(single precision)', self)
        self.singlePrecisionBox.setEnabled(False)

        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b> to write a Serafin output')
        self.btnSubmit.setFixedSize(105, 50)
        self.btnSubmit.setEnabled(False)

    def _setLayout(self):
        mainLayout = QVBoxLayout()
        mainLayout.addItem(QSpacerItem(1, 10))
        mainLayout.addWidget(self.timeSlider)
        mainLayout.addWidget(self.timeSelection)
        mainLayout.addItem(QSpacerItem(1, 10))

        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.btnAdd)
        lb = QLabel(
            'Double click on the cells to edit Arrival / Duration variable names'
        )
        hlayout.addWidget(lb)
        hlayout.setAlignment(lb, Qt.AlignBottom | Qt.AlignRight)
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(1, 5))
        mainLayout.addWidget(self.conditionTable)

        mainLayout.addItem(QSpacerItem(1, 10))
        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.btnSubmit)
        hlayout.addItem(QSpacerItem(10, 10))
        vlayout = QVBoxLayout()
        vlayout.addWidget(QLabel('Time unit'))
        vlayout.addWidget(self.unitBox)
        hlayout.addLayout(vlayout)
        hlayout.addItem(QSpacerItem(10, 10))
        hlayout.addWidget(self.singlePrecisionBox)
        hlayout.addItem(QSpacerItem(50, 10))
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(30, 15))
        mainLayout.addWidget(QLabel('   Message logs'))
        mainLayout.addWidget(self.logTextBox.widget)
        self.setLayout(mainLayout)

    def _bindEvents(self):
        self.btnAdd.clicked.connect(self.btnAddEvent)
        self.btnSubmit.clicked.connect(self.btnSubmitEvent)
        self.conditionTable.cellChanged.connect(self._checkName)
        self.timeSelection.startIndex.editingFinished.connect(
            self.timeSlider.enterIndexEvent)
        self.timeSelection.endIndex.editingFinished.connect(
            self.timeSlider.enterIndexEvent)
        self.timeSelection.startValue.editingFinished.connect(
            self.timeSlider.enterValueEvent)
        self.timeSelection.endValue.editingFinished.connect(
            self.timeSlider.enterValueEvent)

    def _current_names(self, ignore_row, ignore_column):
        names = []
        for row in range(self.conditionTable.rowCount()):
            for column in range(1, 3):
                if row == ignore_row and column == ignore_column:
                    continue
                item = self.conditionTable.item(row, column)
                if item is not None:
                    names.append(item.text())
        return names

    def _current_conditions(self):
        conditions = []
        for row in range(self.conditionTable.rowCount()):
            conditions.append(self.conditionTable.item(row, 0).text())
        return conditions

    def _checkName(self, row, column):
        if column == 1 or column == 2:
            name = self.conditionTable.item(row, column).text()
            if len(name) < 2 or len(name) > 16:
                QMessageBox.critical(
                    self, 'Error',
                    'The variable names should be between 2 and 16 characters!',
                    QMessageBox.Ok)
            elif name in self._current_names(row, column):
                QMessageBox.critical(self, 'Error', 'Duplicated name.',
                                     QMessageBox.Ok)
            else:
                return
            # back to default
            condition = self.conditionTable.item(row, 0).text()
            condition_tight = operations.tighten_expression(condition)
            if column == 1:
                self.conditionTable.setItem(
                    row, column, QTableWidgetItem(
                        ('A ' + condition_tight)[:16]))
            else:
                self.conditionTable.setItem(
                    row, column, QTableWidgetItem(
                        ('D ' + condition_tight)[:16]))

    def _convertTimeUnit(self, time_indices, values):
        time_unit = self.unitBox.currentText()
        if time_unit == 'minute':
            values /= 60
        elif time_unit == 'hour':
            values /= 3600
        elif time_unit == 'day':
            values /= 86400
        elif time_unit == 'percentage':
            values *= 100 / (self.input.time[time_indices[-1]] -
                             self.input.time[time_indices[0]])
        return values

    def reset(self):
        self.conditions = []
        self.conditionTable.setRowCount(0)
        self.timeSelection.disable()
        self.btnSubmit.setEnabled(False)
        self.singlePrecisionBox.setChecked(False)
        self.singlePrecisionBox.setEnabled(False)

    def getInput(self, data):
        self.btnSubmit.setEnabled(True)
        self.data = data

        # unlock convert to single precision
        if self.data.header.is_double_precision():
            self.singlePrecisionBox.setEnabled(True)

        if self.data.header.date is not None:
            year, month, day, hour, minute, second = self.data.header.date
            start_time = datetime.datetime(year, month, day, hour, minute,
                                           second)
        else:
            start_time = datetime.datetime(1900, 1, 1, 0, 0, 0)

        time_frames = list(
            map(lambda x: datetime.timedelta(seconds=x), self.data.time))
        self.timeSlider.reinit(start_time, time_frames, self.timeSelection)

        self.timeSlider.setEnabled(True)
        self.timeSelection.enable()

    def getOutputHeader(self):
        output_header = self.data.header.copy()
        output_header.nb_var = 2 * len(self.conditions)
        output_header.var_IDs, output_header.var_names, output_header.var_units = [], [], []
        for row in range(self.conditionTable.rowCount()):
            a_name = self.conditionTable.item(row, 1).text()
            d_name = self.conditionTable.item(row, 2).text()
            for name in [a_name, d_name]:
                output_header.var_IDs.append('')
                output_header.var_names.append(bytes(name, 'utf-8').ljust(16))
                output_header.var_units.append(
                    bytes(self.unitBox.currentText().upper(),
                          'utf-8').ljust(16))
        if self.singlePrecisionBox.isChecked():
            output_header.to_single_precision()
        return output_header

    def btnAddEvent(self):
        dlg = ConditionDialog(self.data.header.var_IDs,
                              self.data.header.var_names)
        value = dlg.exec_()
        if value == QDialog.Rejected:
            return
        condition = str(dlg.condition)
        if condition in self._current_conditions():
            QMessageBox.critical(self, 'Error',
                                 'This condition is already added!',
                                 QMessageBox.Ok)
            return
        condition_tight = operations.tighten_expression(
            condition)  # used to define variable names
        self.conditions.append(dlg.condition)

        row = self.conditionTable.rowCount()
        self.conditionTable.insertRow(row)
        condition_item = QTableWidgetItem(condition)
        condition_item.setFlags(Qt.ItemIsEditable)
        self.conditionTable.setItem(row, 0, condition_item)
        self.conditionTable.setItem(
            row, 1, QTableWidgetItem(('A ' + condition_tight)[:16]))
        self.conditionTable.setItem(
            row, 2, QTableWidgetItem(('D ' + condition_tight)[:16]))

    def btnSubmitEvent(self):
        if not self.conditions:
            QMessageBox.critical(self, 'Error', 'Add at least one condition.',
                                 QMessageBox.Ok)
            return

        start_index = int(self.timeSelection.startIndex.text()) - 1
        end_index = int(self.timeSelection.endIndex.text())
        time_indices = list(range(start_index, end_index))

        if len(time_indices) == 1:
            QMessageBox.critical(self, 'Error',
                                 'Start and end frame cannot be the same.',
                                 QMessageBox.Ok)
            return

        canceled, filename = save_dialog('Serafin', self.data.filename)
        if canceled:
            return

        # deduce header from selected variable IDs and write header
        output_header = self.getOutputHeader()
        output_message = 'Computing Arrival / Duration between frame %d and %d.' \
                          % (start_index+1, end_index)
        self.parent.inDialog()
        logging.info(output_message)
        progressBar = OutputProgressDialog()

        # do some calculations
        with Serafin.Read(self.data.filename,
                          self.data.language) as input_stream:
            input_stream.header = self.data.header
            input_stream.time = self.data.time

            progressBar.setValue(5)
            QApplication.processEvents()

            with Serafin.Write(filename, self.data.language) as output_stream:
                process = ArrivalDurationThread(input_stream, self.conditions,
                                                time_indices)
                progressBar.connectToThread(process)
                values = process.run()

                if not process.canceled:
                    values = self._convertTimeUnit(time_indices, values)
                    output_stream.write_header(output_header)
                    output_stream.write_entire_frame(output_header,
                                                     self.data.time[0], values)
                    progressBar.outputFinished()

        progressBar.exec_()
        self.parent.outDialog()
class CSVTab(QWidget):
    def __init__(self, inputTab, parent):
        super().__init__()
        self.input = inputTab
        self.parent = parent

        self._initWidget()
        self._setLayout()
        self.btnSubmit.clicked.connect(self.btnSubmitEvent)

    def _initWidget(self):
        # create two 3-column tables for variables selection
        self.firstTable = VariableTable()
        self.secondTable = VariableTable()

        # create the options
        self.intersect = QCheckBox()
        self.intersect.setChecked(True)
        self.timeSelection = SimpleTimeDateSelection()
        self.referenceLine = QComboBox()

        # create the submit button
        self.btnSubmit = QPushButton('Submit\nto .csv',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Write</b> output to .csv')
        self.btnSubmit.setFixedSize(105, 50)
        self.btnSubmit.setEnabled(False)

        # create the output file name box
        self.csvNameBox = QLineEdit()
        self.csvNameBox.setReadOnly(True)
        self.csvNameBox.setFixedHeight(30)

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

    def _setLayout(self):
        mainLayout = QVBoxLayout()
        mainLayout.setSpacing(15)
        mainLayout.addItem(QSpacerItem(10, 10))
        mainLayout.addWidget(self.timeSelection)
        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel('   Reference line'))
        hlayout.addWidget(self.referenceLine)
        hlayout.setAlignment(self.referenceLine, Qt.AlignLeft)
        hlayout.addStretch()
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(10, 10))

        glayout = QGridLayout()
        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(30, 1))
        vlayout = QVBoxLayout()
        lb = QLabel('Available variables')
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addWidget(self.firstTable)
        hlayout2 = QHBoxLayout()
        hlayout2.addItem(QSpacerItem(30, 1))
        hlayout2.addWidget(self.intersect)
        hlayout2.addWidget(QLabel('Add intersection points'))
        hlayout2.setAlignment(self.intersect, Qt.AlignLeft)
        hlayout2.addStretch()
        vlayout.addLayout(hlayout2)
        hlayout.addLayout(vlayout)
        hlayout.addItem(QSpacerItem(15, 1))

        vlayout = QVBoxLayout()
        lb = QLabel('Output variables')
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addWidget(self.secondTable)
        hlayout.addLayout(vlayout)
        hlayout.addItem(QSpacerItem(30, 1))
        glayout.addLayout(hlayout, 1, 1)
        glayout.setAlignment(Qt.AlignLeft)
        glayout.setSpacing(10)
        mainLayout.addLayout(glayout)
        mainLayout.addItem(QSpacerItem(30, 10))

        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(30, 1))
        hlayout.addWidget(self.btnSubmit)
        hlayout.addWidget(self.csvNameBox)
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(30, 15))

        mainLayout.addWidget(QLabel('   Message logs'))
        mainLayout.addWidget(self.logTextBox.widget)
        self.setLayout(mainLayout)

    def getSelectedVariables(self):
        return self.secondTable.get_selected()

    def _initVarTables(self):
        self.firstTable.fill(self.input.data.header)

    def getInput(self):
        self._initVarTables()
        self.btnSubmit.setEnabled(True)
        self.csvNameBox.clear()
        if self.input.data.header.date is not None:
            year, month, day, hour, minute, second = self.input.data.header.date
            start_time = datetime.datetime(year, month, day, hour, minute,
                                           second)
        else:
            start_time = datetime.datetime(1900, 1, 1, 0, 0, 0)
        frames = list(
            map(lambda x: start_time + datetime.timedelta(seconds=x),
                self.input.data.time))
        self.timeSelection.initTime(self.input.data.time, frames)
        for i in range(len(self.input.lines)):
            id_line = str(i + 1)
            if self.input.line_interpolators[i][0]:
                self.referenceLine.addItem('Line %s' % id_line)

    def reset(self):
        self.firstTable.setRowCount(0)
        self.secondTable.setRowCount(0)
        self.intersect.setChecked(False)
        self.btnSubmit.setEnabled(False)
        self.timeSelection.clearText()
        self.csvNameBox.clear()
        self.referenceLine.clear()
        self.intersect.setChecked(True)

    def btnSubmitEvent(self):
        selected_var_IDs = self.getSelectedVariables()
        if not selected_var_IDs:
            QMessageBox.critical(
                self, 'Error',
                'Choose at least one output variable before submit!',
                QMessageBox.Ok)
            return

        canceled, filename = save_dialog('CSV')
        if canceled:
            return

        self.csvNameBox.setText(filename)
        logging.info('Writing the output to %s' % filename)
        self.parent.inDialog()

        indices_nonempty = [
            i for i in range(len(self.input.lines))
            if self.input.line_interpolators[i][0]
        ]
        reference = self.input.lines[
            int(self.referenceLine.currentText().split()[1]) - 1]
        time_index = int(self.timeSelection.index.text()) - 1

        # initialize the progress bar
        process = WriteCSVProcess(self.parent.csv_separator,
                                  self.parent.digits, self.input.mesh)
        progressBar = OutputProgressDialog()

        with Serafin.Read(self.input.data.filename,
                          self.input.data.language) as input_stream:
            input_stream.header = self.input.data.header
            input_stream.time = self.input.data.time

            progressBar.setValue(1)
            QApplication.processEvents()

            with open(filename, 'w') as output_stream:
                progressBar.connectToThread(process)

                if self.intersect.isChecked():
                    process.write_csv(input_stream, selected_var_IDs,
                                      output_stream,
                                      self.input.line_interpolators,
                                      indices_nonempty, reference, time_index)
                else:
                    process.write_csv(input_stream, selected_var_IDs,
                                      output_stream,
                                      self.input.line_interpolators_internal,
                                      indices_nonempty, reference, time_index)
        if not process.canceled:
            progressBar.outputFinished()
        progressBar.exec_()
        self.parent.outDialog()
        if process.canceled:
            self.csvNameBox.clear()
            return
Beispiel #14
0
class SubmitTab(QWidget):
    def __init__(self, inputTab, timeSelection, parent):
        super().__init__()
        self.inputTab = inputTab
        self.data = None
        self.timeSelection = timeSelection
        self.parent = parent

        # create the widget displaying message logs
        self.logTextBox = QPlainTextEditLogger(self)
        self.logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - [%(levelname)s] - \n%(message)s'))
        logging.getLogger().addHandler(self.logTextBox)
        logging.getLogger().setLevel(self.parent.logging_level)

        # create a check box for output file format (simple or double precision)
        self.singlePrecisionBox = QCheckBox(
            'Convert to SERAFIN \n(single precision)', self)
        self.singlePrecisionBox.setEnabled(False)

        # create the submit button
        self.btnSubmit = QPushButton('Submit',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Submit</b> to write a Serafin output')
        self.btnSubmit.setFixedSize(105, 50)
        self.btnSubmit.setEnabled(False)

        # bind events
        self.btnSubmit.clicked.connect(self.btnSubmitEvent)

        # set layout
        mainLayout = QVBoxLayout()
        mainLayout.addItem(QSpacerItem(50, 20))
        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.btnSubmit)
        hlayout.addItem(QSpacerItem(50, 10))
        hlayout.addWidget(self.singlePrecisionBox)
        hlayout.addItem(QSpacerItem(50, 10))
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(30, 15))
        mainLayout.addWidget(QLabel('   Message logs'))
        mainLayout.addWidget(self.logTextBox.widget)
        self.setLayout(mainLayout)

    def reset(self):
        self.btnSubmit.setEnabled(False)
        self.singlePrecisionBox.setChecked(False)
        self.singlePrecisionBox.setEnabled(False)

    def getOutputHeader(self, selected_vars):
        output_header = self.data.header.copy()
        output_header.nb_var = len(selected_vars)
        output_header.var_IDs, output_header.var_names, output_header.var_units = [], [], []
        for var_ID, var_name, var_unit in selected_vars:
            output_header.var_IDs.append(var_ID)
            output_header.var_names.append(var_name)
            output_header.var_units.append(var_unit)
        if self.singlePrecisionBox.isChecked():
            output_header.to_single_precision()
        return output_header

    def getInput(self, data):
        self.data = data
        # unlock convert to single precision
        if self.data.header.is_double_precision():
            self.singlePrecisionBox.setEnabled(True)

        # unlock the submit button
        self.btnSubmit.setEnabled(True)

    def btnSubmitEvent(self):
        canceled, filename = save_dialog('Serafin', self.data.filename)
        if canceled:
            return

        # fetch the list of selected variables
        selected_vars = self.inputTab.getSelectedVariables()

        # deduce header from selected variable IDs and write header
        output_header = self.getOutputHeader(selected_vars)

        # fetch the list of selected frames
        if self.timeSelection.manualSelection.hasData:
            output_time_indices = self.timeSelection.getManualTime()
            output_message = 'Writing the output with variables %s for %d frame%s between frame %d and %d.' \
                             % (str(output_header.var_IDs), len(output_time_indices),
                             ['', 's'][len(output_time_indices) > 1], output_time_indices[0]+1, output_time_indices[-1]+1)
        else:
            start_index, end_index, sampling_frequency, output_time_indices = self.timeSelection.getTime(
            )
            output_message = 'Writing the output with variables %s between frame %d and %d with sampling frequency %d.' \
                             % (str(output_header.var_IDs), start_index, end_index, sampling_frequency)

        self.parent.inDialog()
        progressBar = OutputProgressDialog()

        # do some calculations
        with Serafin.Read(self.data.filename,
                          self.data.language) as input_stream:
            # instead of re-reading the header and the time, just do a copy
            input_stream.header = self.data.header
            input_stream.time = self.data.time
            progressBar.setValue(5)
            QApplication.processEvents()

            with Serafin.Write(filename, self.data.language) as output_stream:
                logging.info(output_message)

                output_stream.write_header(output_header)

                # do some additional computations
                necessary_equations = get_necessary_equations(
                    self.data.header.var_IDs,
                    output_header.var_IDs,
                    is_2d=output_header.is_2d,
                    us_equation=self.data.us_equation)
                process = ExtractVariablesThread(necessary_equations,
                                                 self.data.us_equation,
                                                 input_stream, output_stream,
                                                 output_header,
                                                 output_time_indices)
                progressBar.connectToThread(process)
                process.run()

                if not process.canceled:
                    progressBar.outputFinished()
                progressBar.exec_()
                self.parent.outDialog()