Beispiel #1
0
    def change_n_components(self, n_components: int):
        for widget in self.control_widgets:
            self.control_layout.removeWidget(widget)
            widget.hide()
        self.control_widgets.clear()
        self.input_widgets.clear()

        widgets = []
        slider_range = (0, 1000)
        input_widgets = []
        mean_range = (-5, 15)
        std_range = (0.0, 10)
        weight_range = (0, 10)
        names = [self.tr("Mean"), self.tr("STD"), self.tr("Weight")]
        ranges = [mean_range, std_range, weight_range]
        slider_values = [500, 100, 100]
        input_values = [0.0, 1.0, 1.0]

        for i in range(n_components):
            group = QGroupBox(f"C{i+1}")
            group.setMinimumWidth(200)
            group_layout = QGridLayout(group)
            inputs = []
            for j, (name, range_, slider_value, input_value) in enumerate(
                    zip(names, ranges, slider_values, input_values)):
                label = QLabel(name)
                slider = QSlider()
                slider.setRange(*slider_range)
                slider.setValue(slider_value)
                slider.setOrientation(Qt.Horizontal)
                input_ = QDoubleSpinBox()
                input_.setRange(*range_)
                input_.setDecimals(3)
                input_.setSingleStep(0.01)
                input_.setValue(input_value)
                slider.valueChanged.connect(self.on_value_changed)
                input_.valueChanged.connect(self.on_value_changed)
                slider.valueChanged.connect(
                    lambda x, input_=input_, range_=range_: input_.setValue(
                        x / 1000 * (range_[-1] - range_[0]) + range_[0]))
                input_.valueChanged.connect(
                    lambda x, slider=slider, range_=range_: slider.setValue(
                        (x - range_[0]) / (range_[-1] - range_[0]) * 1000))

                group_layout.addWidget(label, j, 0)
                group_layout.addWidget(slider, j, 1)
                group_layout.addWidget(input_, j, 2)
                inputs.append(input_)

            self.control_layout.addWidget(group, i + 5, 0, 1, 4)
            widgets.append(group)
            input_widgets.append(inputs)

        self.control_widgets = widgets
        self.input_widgets = input_widgets
Beispiel #2
0
class Widget(QWidget):

    def __init__(self):
        QWidget.__init__(self)

        # Data for plotting and marker data storage
        self.data = {}
        self.slice_index = {
            'ind1': 0, 
            'ind2': 0
            }
        self.marker_id = 0
        self.marker_ind = []
        self.marker_setpoint = {
            'Marker1': 0, 
            'Marker2': 0, 
            }

        # Error message dialog widget
        self.error_popup = QErrorMessage()
        self.error_popup.setWindowTitle('Snap file error')

        # Left (List of Checkboxes)
        self.list_widget = QListWidget()
        #Resize width and height
        self.list_widget.setSizePolicy(QSizePolicy.Preferred, 
                                       QSizePolicy.Preferred)
        self.list_widget.setMinimumWidth(200)
        self.list_widget.setMaximumWidth(400)
        # self.list_widget.setMinimumHeight(300)
        self.list_widget.setMaximumHeight(500)

        # Signal groupbox
        self.signal_groupbox = QGroupBox('Available Signals')
        self.signal_groupbox.setMinimumWidth(200)
        self.signal_groupbox.setMaximumWidth(350)
        self.signal_groupbox.setMinimumHeight(100)
        self.sig_group_layout = QVBoxLayout()
        self.signal_groupbox.setLayout(self.sig_group_layout)
        # Statistics groupbox
        self.stats_groupbox = QGroupBox('Statistics')
        self.stats_groupbox.setMinimumWidth(200)
        self.stats_groupbox.setMaximumWidth(350)
        self.stats_groupbox.setMinimumHeight(240)
        self.stats_group_layout = QFormLayout()

        # Label initiation
        # Marker Time 1
        self.mark_one_time_label = QLabel('Marker1_time: ')
        self.mark_one_time_value = QLabel()
        # Marker Time 2
        self.mark_two_time_label = QLabel('Marker2_time: ')
        self.mark_two_time_value = QLabel()
        # On/Off labels for 0/1 signals counter
        self.on_off_label = QLabel('On/Off: ')
        self.on_off_value = QLabel()
        # Mean value
        self.mean_label = QLabel('Mean: ')
        self.mean_value = QLabel()
        # Standard deviation
        self.std_label = QLabel('Sigma(STD): ')
        self.std_value = QLabel()
        # Minimal value
        self.min_label = QLabel('Min: ')
        self.min_value = QLabel()
        # Maximual value
        self.max_label = QLabel('Max: ')
        self.max_value = QLabel()
        # Max - Min value
        self.val_diff_label = QLabel('Max-Min: ')
        self.val_diff_value = QLabel()
        # Time difference (X-axis)
        self.time_diff_label = QLabel('Time_diff: ')
        self.time_diff_value = QLabel('')

        # Row addition of labels
        self.stats_group_layout.addRow(self.mark_one_time_label, 
                                       self.mark_one_time_value)
        self.stats_group_layout.addRow(self.mark_two_time_label,
                                       self.mark_two_time_value)
        self.stats_group_layout.addRow(self.time_diff_label, 
                                       self.time_diff_value)
        self.stats_group_layout.addRow(self.on_off_label, self.on_off_value)
        self.stats_group_layout.addRow(self.mean_label, self.mean_value)
        self.stats_group_layout.addRow(self.std_label, self.std_value)
        self.stats_group_layout.addRow(self.min_label, self.min_value)
        self.stats_group_layout.addRow(self.max_label, self.max_value)
        self.stats_group_layout.addRow(self.val_diff_label, 
                                       self.val_diff_value)
        self.stats_groupbox.setLayout(self.stats_group_layout)

        # Set markers section of the application (bottom left)
        self.marker_grid = QGridLayout()
        self.marker_one_notice = QLabel()
        self.marker_two_notice = QLabel()
        self.set_marker_one_label = QLabel('Set Marker1:')
        self.set_marker_two_label = QLabel('Set Marker2:')
        self.set_marker_one_value = QLineEdit()
        self.set_marker_one_value.setMaximumWidth(100)
        self.set_marker_two_value = QLineEdit()
        self.set_marker_two_value.setMaximumWidth(100)

        self.marker_grid.addWidget(self.set_marker_one_label)
        self.marker_grid.addWidget(self.set_marker_one_value)
        self.marker_grid.addWidget(self.marker_one_notice)
        self.marker_grid.addWidget(self.set_marker_two_label)
        self.marker_grid.addWidget(self.set_marker_two_value)
        self.marker_grid.addWidget(self.marker_two_notice)
                                        
        # Leftside app layout
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.list_widget)
        self.v_layout.addWidget(self.signal_groupbox)
        self.v_layout.addWidget(self.stats_groupbox)
        self.v_layout.addLayout(self.marker_grid)

        # Matplotlib figure
        self.fig = Figure(figsize=(5, 3))
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setSizePolicy(QSizePolicy.Expanding, 
                                  QSizePolicy.Expanding)
        self.ax = self.canvas.figure.subplots()
        self.ax.grid()
        self.ax.set_xlabel('Time[s]')
        self.fig.suptitle('Parameter Plot')
      
        # QWidget Layout
        self.h_layout = QHBoxLayout()
        self.h_layout.addLayout(self.v_layout)
        self.h_layout.addWidget(self.canvas)

        # Set the layout to the QWidget
        self.setLayout(self.h_layout)

        # ListWidget and plot connections
        self.list_widget.itemChanged.connect(self.item_changed)
        self.click_event = self.fig.canvas.mpl_connect('button_press_event',
                                                       self.on_click)
        self.set_marker_one_value.returnPressed.connect(
                                                lambda: self.add_marker('one'))
        self.set_marker_two_value.returnPressed.connect(
                                                lambda: self.add_marker('two'))
        
    # Add radio button when signal is checked for plotting
    def add_radio_button(self, name):
        self.rad_btn = QRadioButton(name)
        self.rad_btn.toggled.connect(self.calculate_signal_stats)
        self.sig_group_layout.addWidget(self.rad_btn)

    # Remove radio button when signal is unchecked for plotting
    def remove_radio_button(self, name):
        for item in self.signal_groupbox.children():
            try:
                if item.text() == name:
                    item.setParent(None)
            except AttributeError:
                pass
    
    # Remove all radiobuttons on new data load
    def clear_signals(self):
        count = 0
        for item in self.signal_groupbox.children():
            if count == 0:
                count = 1
                continue 
            else:
                item.setParent(None)  
    # Check state of all radiobuttons, if none is checked remove stats values
    def check_signals(self):
        count = 0
        num_of_check = 0
        for item in self.signal_groupbox.children():
            if count == 0:
                count = 1
                continue 
            else:
                if item.isChecked():
                    num_of_check += 1
        # If no radiobuttons are checked, remove stats
        if num_of_check == 0:
            self.mean_value.setText('') 
            self.std_value.setText('') 
            self.max_value.setText('') 
            self.min_value.setText('') 
            self.val_diff_value.setText('') 
            self.on_off_value.setText('')               

    # Item additon of listWidget
    def fill_list(self, list_items):
        self.list_widget.clear()

        for column in list_items:
            item = QListWidgetItem(column)
            item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Unchecked)
            self.list_widget.addItem(item)

        self.show()
    
    # If new data is loaded, replace the old one
    def replace_data(self, temp):
        if not temp == self.data:
            self.data = temp
            self.clear_signals()

    @Slot()
    # Item state changed in listWidget event handler
    def item_changed(self, item):
        if item.checkState() == Qt.Unchecked:
           self.remove_plot(item.text())
           self.remove_radio_button(item.text())
           self.check_signals()
        else:
            self.add_plot(self.data['Time'], 
                          self.data[item.text()], item.text())
            self.add_radio_button(item.text())
                
    # Method for plotting data
    def add_plot(self, x_data, y_data, name):
        self.ax.plot(x_data, y_data, label=name, picker=3)
        self.ax.grid(True)
        self.ax.relim()
        self.ax.set_xlabel('Time[s]')
        self.ax.autoscale_view()
        self.ax.legend(loc='upper right')
        self.canvas.draw()

    # Method for marker addition via QLineEdit
    def add_marker(self, label):
        # Check if any signal is plotted
        sig_count = 0
        for i in range(self.list_widget.count()):
            if self.list_widget.item(i).checkState() == Qt.Checked:
                sig_count += 1

        if sig_count == 0:
            self.marker_one_notice.setText('No active signal!')
            self.marker_two_notice.setText('No active signal!')
            return
        try:
            max_time = self.data['Time'][-1]
            min_time = self.data['Time'][0]
        except KeyError:
            self.marker_one_notice.setText('Signal data not loaded!')
            self.marker_two_notice.setText('Signal data not loaded!')
        if label == 'one':
            try:
                mark1_value = float(self.set_marker_one_value.text())
                if mark1_value < max_time and mark1_value > min_time:
                    if self.marker_id == 0:
                        self.marker_id += 1
                        label_id = self.marker_id
                    elif self.marker_id == 1:
                        self.marker_id += 1
                        label_id = self.marker_id
                        self.remove_marker('first')
                    else:
                        self.remove_marker('first')
                        label_id = 1

                    self.marker_one_notice.setText('')
                    self.marker_setpoint['Marker1'] = mark1_value
                    self.mark_one_time_value.setText(
                                            self.set_marker_one_value.text())
                    self.calculate_marker_stats()
                    self.calculate_signal_stats()
                    
                    # Draw the marker
                    L =  self.ax.axvline(
                                    x=float(self.set_marker_one_value.text()), 
                                    linestyle='dashed', 
                                    color='red', 
                                    label='_Marker' + str(label_id))
                    self.fig.canvas.draw()
                else:
                    self.marker_one_notice.setText('Marker1 out of bounds')
            except ValueError:
                self.marker_one_notice.setText('Non-Valid value entered!')
        else:
            try:
                mark2_value = float(self.set_marker_two_value.text()) 
                if mark2_value < max_time and mark2_value > min_time:
                    if self.marker_id == 1:
                        self.marker_id += 1
                        label_id = self.marker_id
                    elif self.marker_id == 2:
                        label_id = 2
                        self.remove_marker('second')
                    else:
                        self.marker_two_notice.setText('Marker1 not placed')
                    self.marker_two_notice.setText('')
                    self.marker_setpoint['Marker2'] = mark2_value
                    self.mark_two_time_value.setText(
                                            self.set_marker_two_value.text())
                    self.calculate_marker_stats()
                    self.calculate_signal_stats()
                    # Draw the marker
                    L =  self.ax.axvline(
                                    x=float(self.set_marker_two_value.text()), 
                                    linestyle='dashed', 
                                    color='red', 
                                    label='_Marker' + str(label_id))
                    self.fig.canvas.draw()
                else:
                    self.marker_two_notice.setText('Marker2 out of bounds')
            except:
                self.marker_two_notice.setText('Non-Valid value entered!')
    
    # Marker removal method
    def remove_marker(self, label):
        for item in self.ax.lines:
            if 'Marker' in item.get_label():
                self.marker_ind.append(item)

        # If there are two markers remove them from plot and adjust marker
        # time labels
        if label == 'both':
            self.marker_ind[0].remove()
            self.marker_ind[1].remove()
            self.marker_ind = []
            self.marker_setpoint['Marker1'] = 0
            self.marker_setpoint['Marker2'] = 0
            self.mark_one_time_value.setText('')
            self.mark_two_time_value.setText('')
            self.time_diff_value.setText('')
            self.marker_id = 0
        # Remove only marker1
        elif label == 'first':
            self.marker_ind[0].remove()
            self.marker_ind = []
            self.marker_setpoint['Marker1'] = 0
            self.mark_one_time_value.setText('')
            self.marker_id -= 1
        elif label == 'second':
            self.marker_ind[1].remove()
            self.marker_ind = []
            self.marker_setpoint['Marker2'] = 0
            self.mark_two_time_value.setText('')
            self.marker_id -= 1

        self.ax.set_xlabel('Time[s]')
        self.canvas.draw()
    
    # Method for plot removal
    def remove_plot(self, name):
        cnt = 0
        for item in self.ax.lines:
            if item.get_label() == name:
                self.ax.lines[cnt].remove()
            cnt += 1
        self.ax.relim()
        self.ax.autoscale_view()
        self.ax.legend(loc='upper right')
        self.ax.set_xlabel('Time[s]')
        self.canvas.draw()

        # Check if all elements are unticked
        counter = 0
        for i in range(self.list_widget.count()):
            if self.list_widget.item(i).checkState() == Qt.Checked:
                counter +=1
        if counter == 0:
            self.remove_marker('both')
            
    # On click event for plot, only two markers can be active at the time
    def on_click(self, event):
        try:
            # Catch left click event
            if event.button == 1:
                x = event.xdata
                if self.marker_id < 2:
                    if self.marker_id == 0:
                        self.marker_setpoint['Marker1'] = round(x)
                        self.mark_one_time_value.setText(
                                            str(self.marker_setpoint['Marker1']))
                        self.calculate_marker_stats()
                        self.calculate_signal_stats()
                    else:
                        self.marker_setpoint['Marker2'] = round(x)
                        self.mark_two_time_value.setText(
                                            str(self.marker_setpoint['Marker2']))
                        self.calculate_marker_stats()
                        self.calculate_signal_stats()
                    self.marker_id += 1
                    L =  self.ax.axvline(x=x, 
                                        linestyle='dashed', 
                                        color='red', 
                                        label='_Marker' + str(self.marker_id))
                    self.fig.canvas.draw()
            # Catch right click event
            elif event.button == 3:
                self.remove_marker('both')
        except TypeError:
            pass
    # Marker analysis method
    def calculate_marker_stats(self):
        if self.marker_setpoint['Marker2'] == 0:
            diff = self.data['Time'][-1] - self.marker_setpoint['Marker1']
            self.time_diff_value.setText(str(diff))
        else:
            diff = self.marker_setpoint['Marker2'] -  \
                   self.marker_setpoint['Marker1']
            
            self.time_diff_value.setText(convert_seconds(diff))
    # Signal analysis method
    def calculate_signal_stats(self):
        self.check_signals()
        selected_signal = ''
        signal_data = []
        num_off, num_on = 0, 0
        for item in self.signal_groupbox.children():
            try:
                if item.isChecked():
                    # Signal extraction block
                    selected_signal = item.text()
                    # If only one marker, Marker1 is placed on graph
                    if self.marker_setpoint['Marker2'] == 0 and self.marker_setpoint['Marker1'] != 0:
                        for i in range(len(self.data['Time'])):
                            if self.data['Time'][i] > self.marker_setpoint['Marker1']:
                                self.slice_index['ind1'] = i
                                break
                        signal_data = np.asarray(
                        self.data[selected_signal][self.slice_index['ind1']:], 
                                    dtype=np.float32)
                    # Both markers, Marker1 and Marker2 are present on graph
                    elif self.marker_setpoint['Marker1'] != 0 and self.marker_setpoint['Marker2'] != 0:
                        for i in range(len(self.data['Time'])):
                            if self.data['Time'][i] > self.marker_setpoint['Marker1']:
                                self.slice_index['ind1'] = i
                                break
                        for i in range(len(self.data['Time'])):
                            if self.data['Time'][len(self.data['Time']) - i - 1] < self.marker_setpoint['Marker2']:
                                self.slice_index['ind2'] = len(self.data['Time']) - i
                                break
                        signal_data = np.asarray(
                        self.data[selected_signal][self.slice_index['ind1']:self.slice_index['ind2'] - 1], 
                                                    dtype=np.float32)
                        
                    # No markers present, whole signal stats are showed
                    else:
                        signal_data = np.asarray(self.data[selected_signal], 
                                                    dtype=np.float32)
                    try:
                        # Signal mean calculation
                        self.mean_value.setText(str(np.mean(signal_data)))
                        # Standard deviation
                        self.std_value.setText(str(np.std(signal_data)))
                        # Maximum value
                        self.max_value.setText(str(np.max(signal_data)))
                        # Minimum value
                        self.min_value.setText(str(np.min(signal_data)))
                        # Max - Min
                        self.val_diff_value.setText(str(np.max(signal_data) - 
                                                    (np.min(signal_data))))
                        if np.max(signal_data) == 1.0:
                            for i in range(len(signal_data)):
                                if i != len(signal_data) - 1:
                                    temp = signal_data[i] - signal_data[i+1]
                                    if temp == 1:
                                        num_off += 1
                                    elif temp == -1:
                                        num_on += 1
                            self.on_off_value.setText(str(num_on) + 
                                                    '\\' + str(num_off))
                    except ValueError:
                        err_line1 = 'Missing data, result is empty array!'
                        err_line2 = '\n Please check snap file.' 
                        self.error_popup.showMessage(err_line1 + err_line2)
            except AttributeError:
                pass
Beispiel #3
0
class AppearanceTab(QWidget):
    def __init__(self, parent):
        """Initialize the appearance tab
        """

        super(AppearanceTab, self).__init__(parent)

        self.prefs = parent.prefs

        # Default column width code
        col_width_label = QLabel("Default Column Width:")
        self.col_width_edit = QLineEdit(str(self.prefs['default_column_width']))
        self.col_width_edit.setMinimumWidth(40)
        self.col_width_edit.setMaximumWidth(100)
        validator = QIntValidator(10, 200, self)
        self.col_width_edit.setValidator(validator)

        # Visual style code
        style_label = QLabel("Visual Style of Application:")
        self.style_edit = QComboBox(self)
        self.style_edit.addItems(list(QStyleFactory.keys()))
        self.style_edit.setMaximumWidth(200)
        self.style_edit.setCurrentIndex(self.style_edit.findText(self.prefs['style']))

        # Units display code
        units_header_label = QLabel("Units Display:")
        self.header_units_check = QCheckBox('Show Units in Table Headers', self)
        checked_header = Qt.Checked if self.prefs['show_units_in_headers'] == 1 else Qt.Unchecked
        self.header_units_check.setCheckState(checked_header)
        self.cells_units_check = QCheckBox('Show Units in Table Cells', self)
        checked_cells = Qt.Checked if self.prefs['show_units_in_cells'] == 1 else Qt.Unchecked
        self.cells_units_check.setCheckState(checked_cells)

        # Handling of file options code
        default_handling_text = QLabel("Select how options saved directly within an IDF "
                                             "file are treated. See \"Save Options\" tab "
                                             "for the options in question.")
        default_handling_text.setWordWrap(True)
        default_handling_text.setMaximumWidth(450)
        self.button_force = QRadioButton("Force Session Options:", self)
        force_text = QLabel("Options from the current session will be used for all "
                                  "files, ignoring any options saved in the IDF file.")
        force_text.setWordWrap(True)
        force_text.setMaximumWidth(450)
        force_text.setMinimumHeight(30)
        force_text.setIndent(25)
        self.button_obey = QRadioButton("Obey IDF Options if Present:", self)
        obey_text = QLabel("Obey options saved in the IDF file. If none are "
                                 "present, use the current session's options.")
        obey_text.setWordWrap(True)
        obey_text.setMaximumWidth(450)
        obey_text.setMinimumHeight(30)
        obey_text.setIndent(25)

        # Handling of file options group box
        self.behaviour_group_box = QGroupBox("Handling of File-based Options")
        self.behaviour_group_box.setMinimumHeight(220)
        self.behaviour_group_box.setMinimumWidth(450)
        behaviour_box = QVBoxLayout()
        behaviour_box.addWidget(default_handling_text)
        behaviour_box.addWidget(self.button_force)
        behaviour_box.addWidget(force_text)
        behaviour_box.addSpacing(5)
        behaviour_box.addWidget(self.button_obey)
        behaviour_box.addWidget(obey_text)
        behaviour_box.addStretch(1)
        self.behaviour_group_box.setLayout(behaviour_box)

        self.behaviour_button_group = QButtonGroup(self)
        self.behaviour_button_group.addButton(self.button_force)
        self.behaviour_button_group.addButton(self.button_obey)
        self.behaviour_button_group.setId(self.button_force, 0)
        self.behaviour_button_group.setId(self.button_obey, 1)
        self.behaviour_button_group.button(self.prefs['obey_idf_options']).setChecked(True)

        # Main layout code
        mainLayout = QVBoxLayout()
        mainLayout.addWidget(col_width_label)
        mainLayout.addWidget(self.col_width_edit)
        mainLayout.addSpacing(10)
        mainLayout.addWidget(style_label)
        mainLayout.addWidget(self.style_edit)
        mainLayout.addSpacing(10)
        mainLayout.addWidget(self.behaviour_group_box)
        mainLayout.addSpacing(10)
        mainLayout.addWidget(units_header_label)
        mainLayout.addWidget(self.header_units_check)
        mainLayout.addWidget(self.cells_units_check)
        mainLayout.addStretch(1)
        self.setLayout(mainLayout)

        # Update settings
        self.behaviour_button_group.buttonClicked.connect(self.update)
        self.col_width_edit.textChanged.connect(self.update)
        self.style_edit.currentIndexChanged.connect(self.update)
        self.header_units_check.stateChanged.connect(self.update)
        self.cells_units_check.stateChanged.connect(self.update)

    def update(self):
        self.prefs['default_column_width'] = self.col_width_edit.text()
        self.prefs['style'] = self.style_edit.currentText()
        self.prefs['obey_idf_options'] = self.behaviour_button_group.checkedId()
        self.prefs['show_units_in_headers'] = 1 if self.header_units_check.checkState() else 0
        self.prefs['show_units_in_cells'] = 1 if self.cells_units_check.checkState() else 0